private void ReadSymbols(Dictionary <string, long> exceptions) { var symbolTableOffset = Reader.ReadInt32(); var numberOfSymbols = Reader.ReadInt32(); symbols = new Symbol[numberOfSymbols]; var stringTableOffset = Reader.ReadInt32(); Reader.ReadInt32(); // string table size var symbolStream = ProvideStream(); var headerPosition = symbolStream.Position; // location before seeking to symbol table symbolStream.Seek(symbolTableOffset, SeekOrigin.Begin); using (var symbolReader = new BinaryReader(symbolStream, Encoding.UTF8, true)) { var stringTableStream = ProvideStream(); for (var i = 0; i < numberOfSymbols; i++) { try { var nameOffset = symbolReader.ReadInt32(); var symbolTablePosition = stringTableStream.Position; // location before reading from string table var name = ReadStringFromOffset(stringTableStream, stringTableOffset + nameOffset); stringTableStream.Position = symbolTablePosition; symbolReader.ReadBytes(4); // ignoring for now long value = is64 ? symbolReader.ReadInt64() : symbolReader.ReadInt32(); symbols[i] = new Symbol(name, value); } catch (Exception e) { if (exceptions != null) { MachOReader.AddException(exceptions, e.Message); } else { throw; } } } } symbolStream.Position = headerPosition; }
public static IEnumerable <MachO> Enumerate(Stream stream, bool shouldOwnStream) { // Fat header is always big endian. var reader = new SimpleEndianessAwareReader(stream, Endianess.BigEndian, !shouldOwnStream); // We assume that fat magic has been already read. var machOCount = reader.ReadInt32(); var alreadyRead = 0; var fatEntriesBegin = stream.Position; while (alreadyRead < machOCount) { // We're only interested in offset and size. stream.Seek(fatEntriesBegin + 20 * alreadyRead + 8, SeekOrigin.Begin); var offset = reader.ReadInt32(); var size = reader.ReadInt32(); var substream = new SubStream(stream, offset, size); yield return(MachOReader.Load(substream, false)); alreadyRead++; } }
private void ReadCommands(int noOfCommands, BinaryReader reader) { for (var i = 0; i < noOfCommands; i++) { try { var loadCommandType = reader.ReadUInt32(); var commandSize = reader.ReadUInt32(); switch ((CommandType)loadCommandType) { case CommandType.SymbolTable: commands[i] = new SymbolTable(reader, OpenStream, is64, throwExceptions ? null : Exceptions); break; case CommandType.Main: commands[i] = new EntryPoint(reader, OpenStream); break; case CommandType.Segment: case CommandType.Segment64: commands[i] = new Segment(reader, OpenStream, is64, throwExceptions ? null : Exceptions); break; default: reader.ReadBytes((int)commandSize - 8); // 8 bytes is the size of the common command header break; } } catch (Exception e) { if (!throwExceptions) { MachOReader.AddException(Exceptions, e.Message); } throw; } } }
public Segment(BinaryReader reader, Func <Stream> streamProvider, bool is64, Dictionary <String, long> exceptionsToQueue = null) : base(reader, streamProvider) { this.is64 = is64; Name = ReadSectionOrSegmentName(); Address = ReadInt32OrInt64(); Size = ReadInt32OrInt64(); var fileOffset = ReadInt32OrInt64(); var fileSize = ReadInt32OrInt64(); MaximalProtection = ReadProtection(); InitialProtection = ReadProtection(); var numberOfSections = Reader.ReadInt32(); Reader.ReadInt32(); // we ignore flags for now if (fileSize > 0) { data = new byte[Size]; var stream = streamProvider(); var previousPosition = stream.Position; stream.Seek(fileOffset, SeekOrigin.Begin); var buffer = stream.ReadBytesOrThrow(checked ((int)fileSize), exceptionsToQueue); Array.Copy(buffer, data, buffer.Length); stream.Position = previousPosition; } var sections = new List <Section>(); try { for (var i = 0; i < numberOfSections; i++) { var sectionName = ReadSectionOrSegmentName(); var segmentName = ReadSectionOrSegmentName(); // set name to segment name in edge case where name is empty string if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(segmentName)) { Name = segmentName; } if (segmentName != Name) { if (exceptionsToQueue == null) { throw new InvalidOperationException(UNEXPECTED_SEGMENT_NAME); } else { MachOReader.AddException(exceptionsToQueue, UNEXPECTED_SEGMENT_NAME); } } var sectionAddress = ReadInt32OrInt64(); var sectionSize = ReadInt32OrInt64(); var offsetInSegment = ReadInt32OrInt64() - fileOffset; if (offsetInSegment < 0) { if (exceptionsToQueue == null) { throw new InvalidOperationException(UNEXPECTED_SECTION_OFFSET); } else { MachOReader.AddException(exceptionsToQueue, UNEXPECTED_SECTION_OFFSET); } } var alignExponent = Reader.ReadInt32(); Reader.ReadBytes(20); var section = new Section(sectionName, sectionAddress, sectionSize, offsetInSegment, alignExponent, this); sections.Add(section); } } finally { Sections = new ReadOnlyCollection <Section>(sections); } }