/// <summary> /// Parses a .JEF file for all relevent assembly data. /// </summary> /// <param name="fileName">The path of the file to parse.</param> /// <returns>A structure representing all the relevant data in the file.</returns> public static JefFile ParseFile(string fileName) { using (var fileReader = new EndianReader(File.OpenRead(fileName), Endianness.LittleEndian)) { FileHeader hdr = ReadHeader(fileReader); System.Diagnostics.Debug.Assert(fileReader.BaseStream.Position == 0x30); int dataMdataSize = hdr.DataOffset - hdr.DataMetadataOffset; IEnumerable <MetadataElement> dataMetaData = ReadMetadataSection(fileReader, dataMdataSize); int dataSize = hdr.TextOffset - hdr.DataOffset; IEnumerable <byte> dataElems = ParseDataSegment(fileReader, dataMetaData); int textSize = hdr.ExternOffset - hdr.TextOffset; IEnumerable <int> textElems = ParseTextSection(fileReader, textSize); // extern segment should just be all zeroes, so read the number of bytes as specified in the size. int externSize = hdr.SymTblOffset - hdr.ExternOffset; IEnumerable <byte> externElems = fileReader.ReadBytes(externSize); int symTblSize = hdr.SrcMapOffset - hdr.SymTblOffset; ReverseSymbolTable symTbl = ParseSymbolTableSection(fileReader, symTblSize); // src map table runs from the starting offset to the end of the file, so just calculate the delta. int srcMapSize = (int)(fileReader.BaseStream.Length - hdr.SrcMapOffset); SourceDebugData dbgData = ParseSourceMapInformation(fileReader, srcMapSize); return(new JefFile(hdr.BaseDataAddress, hdr.BaseTextAddress, hdr.BaseExternAddress, dataMetaData, dataElems, textElems, externElems, symTbl, dbgData)); } }
public static IEnumerable <InstructionData> GenerateInstructionData(ReverseSymbolTable symTable, TextSegmentAccessor textSegment, SourceDebugData dbgData) { IEnumerable <InstructionData> ret = null; if (File.Exists(dbgData.SourceFilePath)) { try { ret = GenerateInstructionDataWithSource(symTable, textSegment, dbgData); } catch (Exception) { // if anything goes wrong, try just parsing the file with no source. ret = GenerateInstructionDataWithNoSource(symTable, textSegment); } } else { ret = GenerateInstructionDataWithNoSource(symTable, textSegment); } return(ret); }
/// <summary> /// Creates an instance of the basic object file. /// </summary> /// <param name="srcFileName">The name of the assembly source file.</param> /// <param name="symTable">The symbol table that will be stored away.</param> public BasicObjectFile(string srcFileName, SymbolTable symTable) { m_DbgData = new SourceDebugData(srcFileName); m_SymTable = symTable; m_DataElements = new List <IObjectFileComponent>(); m_TextElements = new List <IObjectFileComponent>(); m_ExternElements = new List <IObjectFileComponent>(); }
public DisassembledJefFile(DataSegmentAccessor dataSegment, TextSegmentAccessor instructions, IEnumerable <byte> externSegment, ReverseSymbolTable symTable, IEnumerable <MetadataElement> metadata, SourceDebugData dbgData) : base(dataSegment, instructions, externSegment, symTable, dbgData) { m_FileWriter = new JefAssemblyFileWriter(this); m_Metadata = metadata; }
/// <summary> /// Creates an instance of the disassembled file. /// </summary> /// <param name="dataSegment">The disassembled .data segment of the file.</param> /// <param name="instructions">The disassembled .text segment of the file.</param> /// <param name="externSegment">The constituent bytes of the .extern segment.</param> /// <param name="symTable">The symbol table associated with the file.</param> /// <param name="dbgData">The source file information associated with the file.</param> protected DisassembledFileBase(DataSegmentAccessor dataSegment, TextSegmentAccessor instructions, IEnumerable <byte> externSegment, ReverseSymbolTable symTable, SourceDebugData dbgData) { m_DataSegment = dataSegment; m_TextSegment = instructions; m_ExternSize = externSegment.Count(); m_SymTbl = symTable; m_DbgInfo = dbgData; }
/// <summary> /// Creates a representation of a .JEF file in memory. /// </summary> /// <param name="baseDataAddress">The base .data segment address.</param> /// <param name="baseTextAddress">The base .text segment address.</param> /// <param name="baseExternAddress">The base .extern segment address.</param> /// <param name="metadataElems">An IEnumerable of all the data metadata elements.</param> /// <param name="dataElements">An IEnumerable of all the data elements, represented as bytes.</param> /// <param name="textElements">An IEnumerable of all 32-bit instructions in the .JEF file.</param> /// <param name="externElements">An IEnumerable of all the .extern elements in the .JEF file.</param> /// <param name="symTable">A reconstructed SymbolTable instance from the .JEF file.</param> private JefFile(int baseDataAddress, int baseTextAddress, int baseExternAddress, IEnumerable <MetadataElement> metadataElems, IEnumerable <byte> dataElements, IEnumerable <int> textElements, IEnumerable <byte> externElements, ReverseSymbolTable symTable, SourceDebugData dbgData) { m_BaseDataAddress = baseDataAddress; m_BaseTextAddress = baseTextAddress; m_BaseExternAddress = baseExternAddress; m_DataMetadata = metadataElems; m_DataElems = dataElements; m_TextElems = textElements; m_ExternElems = externElements; m_SymTbl = symTable; m_DbgData = dbgData; }
private int WriteSourceMappingInfoToFile(Stream stream, SourceDebugData dbgData) { byte[] srcFileNameBytes = Encoding.ASCII.GetBytes(dbgData.SourceFilePath); byte[] nullTerminatedByteArr = new byte[srcFileNameBytes.Length + 1]; Array.Copy(srcFileNameBytes, nullTerminatedByteArr, srcFileNameBytes.Length); long startPos = stream.Position; stream.Write(nullTerminatedByteArr, 0, nullTerminatedByteArr.Length); foreach (SourceLineInformation srcLine in dbgData.SourceInfo) { short lineNum = (short)srcLine.SourceFileLineNumber; int pgmCtrAddr = srcLine.TextSegmentAddress; byte[] lineNumBytes = ToByteArray(lineNum); byte[] pgmCtrBytes = ToByteArray(pgmCtrAddr); stream.Write(lineNumBytes, 0, lineNumBytes.Length); stream.Write(pgmCtrBytes, 0, pgmCtrBytes.Length); } long newPos = stream.Position; return((int)(newPos - startPos)); }
/// <summary> /// Parses the source map table segment, and constructs an instruction word to source /// line mapping. /// </summary> /// <param name="reader">The reader to parse the file with.</param> /// <param name="sectionSize">The size of the symbol table area, in bytes.</param> /// <returns>A populated SourceDebugData structure.</returns> private static SourceDebugData ParseSourceMapInformation(BinaryReader reader, int sectionSize) { SourceDebugData srcInfo = null; try { int totalNumReadBytes = 0; var fileNameBuilder = new StringBuilder(); byte readByte = reader.ReadByte(); ++totalNumReadBytes; while (readByte != 0 && totalNumReadBytes < sectionSize) { char asciiVal = Convert.ToChar(readByte); fileNameBuilder.Append(asciiVal); readByte = reader.ReadByte(); ++totalNumReadBytes; } string sourceFilePath = fileNameBuilder.ToString(); srcInfo = new SourceDebugData(sourceFilePath); while (totalNumReadBytes < sectionSize) { short lineNum = reader.ReadInt16(); totalNumReadBytes += sizeof(short); int instructionAddr = reader.ReadInt32(); totalNumReadBytes += sizeof(int); srcInfo.AddSourceLineInformation(new SourceLineInformation(sourceFilePath, lineNum, instructionAddr)); } } catch (Exception ex) { srcInfo = new SourceDebugData(string.Empty); } return(srcInfo); }
private static IEnumerable <InstructionData> GenerateInstructionDataWithSource(ReverseSymbolTable symTable, TextSegmentAccessor textSegment, SourceDebugData dbgData) { var instructions = new List <InstructionData>(); using (var reader = File.OpenText(dbgData.SourceFilePath)) { int currPgrmCtr = textSegment.StartingSegmentAddress; foreach (DisassembledInstruction inst in textSegment.RawInstructions) { IParameterStringifier stringifier = InstructionTextMap.GetParameterStringifier(inst.InstructionType); string formattedInstruction = stringifier.GetFormattedInstruction(currPgrmCtr, inst, symTable); string originalSourceLine = string.Empty; int lineNum = -1; if (dbgData.IsSourceTextAssociatedWithAddress(currPgrmCtr)) { lineNum = dbgData.GetLineNumberAssociatedWithAddress(currPgrmCtr); originalSourceLine = reader.ReadLineAt(lineNum); originalSourceLine = originalSourceLine.Trim(); } var srcLineInfo = new SourceLineInformation(dbgData.SourceFilePath, lineNum, currPgrmCtr, originalSourceLine); var instructionElem = new InstructionData(inst.InstructionWord, currPgrmCtr, formattedInstruction, srcLineInfo); instructions.Add(instructionElem); currPgrmCtr += sizeof(int); } return(instructions); } }