コード例 #1
0
        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);
        }
コード例 #2
0
        /// <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));
            }
        }
コード例 #3
0
 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;
 }
コード例 #4
0
 /// <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;
 }
コード例 #5
0
 /// <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;
 }
コード例 #6
0
        /// <summary>
        /// Parses the symtbl segment of the file, and reconstructs a reverse lookup symbol table.
        /// </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 symbol reverse lookup table.</returns>
        private static ReverseSymbolTable ParseSymbolTableSection(BinaryReader reader, int sectionSize)
        {
            // for every symbol, read the first byte. this dictates how long the symbol name is.
            var symTable  = new ReverseSymbolTable();
            int readBytes = 0;

            while (readBytes < sectionSize)
            {
                byte symStrSize = reader.ReadByte();
                ++readBytes;

                byte[] symbolName = reader.ReadBytes(symStrSize);
                readBytes += symStrSize;

                string symNameStr    = Encoding.ASCII.GetString(symbolName);
                int    symbolAddress = reader.ReadInt32();
                readBytes += sizeof(int);

                symTable.AddSymbol(symbolAddress, new Symbol(symNameStr, SegmentType.Data, symbolAddress));
            }

            return(symTable);
        }
コード例 #7
0
        /// <summary>
        /// Formats and stringifies an instruction as well as its parameters.
        /// </summary>
        /// <param name="currPgrmCtr">The value that the program counter would theoretically be at
        /// upon encountering this instruction.</param>
        /// <param name="inst">The disassembled instruction to stringify.</param>
        /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param>
        /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns>
        public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable)
        {
            string retStr = string.Empty;

            // first, see if the program counter has a symbol mapped to it.
            if (symTable.ContainsSymbol(currPgrmCtr))
            {
                Symbol sym = symTable.GetSymbol(currPgrmCtr);
                retStr += sym.LabelName + ":\t\t";
            }
            else
            {
                retStr += "\t\t\t";
            }

            retStr += m_Name;
            return(retStr);
        }
コード例 #8
0
        /// <summary>
        /// Formats and stringifies an instruction as well as its parameters.
        /// </summary>
        /// <param name="currPgrmCtr">The value that the program counter would theoretically be at
        /// upon encountering this instruction.</param>
        /// <param name="inst">The disassembled instruction to stringify.</param>
        /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param>
        /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns>
        public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable)
        {
            string retStr = string.Empty;

            // first, see if the program counter has a symbol mapped to it.
            if (symTable.ContainsSymbol(currPgrmCtr))
            {
                Symbol sym = symTable.GetSymbol(currPgrmCtr);
                retStr += sym.LabelName + ":\t\t";
            }
            else
            {
                retStr += "\t\t\t";
            }

            retStr += "flw ";
            if (inst.Parameters.Count() != 3)
            {
                throw new ArgumentException("Floating point I instruction expected 3 arguments, received " + inst.Parameters.Count());
            }

            string rd  = ReverseRegisterMap.GetStringifiedFloatingPtRegisterValue(inst.Parameters.ElementAt(0));
            string rs1 = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(1));

            int offset = inst.Parameters.ElementAt(2);

            retStr += rd + ", " + offset + "(" + rs1 + ")";

            return(retStr);
        }
コード例 #9
0
        /// <summary>
        /// Writes out the .data segment of the file.
        /// </summary>
        /// <param name="writer">The StreamWriter to use while writing the file.</param>
        /// <param name="symTable">The reverse lookup symbol table to use for symbol mapping.</param>
        /// <param name="dataSegment">The accessor to the file's data segment.</param>
        private void GenerateDataSegment(StreamWriter writer, ReverseSymbolTable symTable, DataSegmentAccessor dataSegment)
        {
            int currAlignment = CommonConstants.DEFAULT_ALIGNMENT;

            writer.WriteLine(".data");
            int processedByteCount = 0;
            int currAddress        = dataSegment.BaseRuntimeDataAddress;

            foreach (MetadataElement elem in m_File.Metadata)
            {
                // don't do any processing if we're looking at padding bytes.
                if (processedByteCount % currAlignment == 0)
                {
                    // first, see if there's a label associated with the data element.
                    if (symTable.ContainsSymbol(currAddress))
                    {
                        // if so, write it out.
                        Symbol sym = symTable.GetSymbol(currAddress);
                        writer.Write(sym.LabelName);
                        writer.Write(":\t\t");
                    }
                    else
                    {
                        writer.Write("\t\t\t");
                    }

                    // determine what to write out.
                    switch (elem.TypeCode)
                    {
                    case ObjectTypeCode.Byte:
                    {
                        writer.Write(".byte ");
                        byte value = dataSegment.ReadUnsignedByte(currAddress);
                        writer.WriteLine(value);
                        processedByteCount += sizeof(byte);
                        break;
                    }

                    case ObjectTypeCode.Half:
                    {
                        writer.Write(".half ");
                        short value = dataSegment.ReadShort(currAddress);
                        writer.WriteLine(value);
                        processedByteCount += sizeof(short);
                        break;
                    }

                    case ObjectTypeCode.Word:
                    {
                        writer.Write(".word ");
                        int value = dataSegment.ReadWord(currAddress);
                        writer.WriteLine(value);
                        processedByteCount += sizeof(int);
                        break;
                    }

                    case ObjectTypeCode.Dword:
                    {
                        writer.Write(".dword ");
                        long value = dataSegment.ReadLong(currAddress);
                        writer.WriteLine(value);
                        processedByteCount += sizeof(long);
                        break;
                    }

                    case ObjectTypeCode.String:
                    {
                        writer.Write(".asciiz ");
                        string value          = dataSegment.ReadString(currAddress);
                        string processedValue = ProcessString(value);
                        writer.WriteLine(processedValue);
                        processedByteCount += value.Length;

                        // account for a null terminating byte here.
                        ++processedByteCount;
                        break;
                    }

                    case ObjectTypeCode.AlignmentChange:
                    {
                        currAlignment = elem.Alignment;
                        break;
                    }
                    }
                }
                else
                {
                    // otherwise, assume we're at a padding byte and don't print it.
                    ++processedByteCount;
                }

                currAddress += elem.Size;
            }
        }
コード例 #10
0
        /// <summary>
        /// Writes out the .data segment of the file.
        /// </summary>
        /// <param name="writer">The StreamWriter to use while writing the file.</param>
        /// <param name="symTable">The reverse lookup symbol table to use for symbol mapping.</param>
        /// <param name="dataSegment">The accessor to the file's data segment.</param>
        private void GenerateDataSegment(StreamWriter writer, ReverseSymbolTable symTable, DataSegmentAccessor dataSegment)
        {
            int currAddress = dataSegment.BaseRuntimeDataAddress;

            writer.WriteLine(".data");

            int endAddress = currAddress + dataSegment.SegmentSize;

            // get the address of each symbol in the .data segment, and sort
            // them in ascending order.
            var symbolAddresses = symTable.AllSymbols
                                  .SelectIf(sym => sym.Address,
                                            sym => dataSegment.BaseRuntimeDataAddress <= sym.Address && sym.Address < endAddress)
                                  .OrderBy(num => num);

            while (currAddress < endAddress)
            {
                // are there any addresses in our symbol table that fall between our current
                // address and the next address we'll examine?
                if (symbolAddresses.Any(address => currAddress <= address && address < (currAddress + sizeof(int))))
                {
                    // okay, slightly narrow our screen
                    if (symbolAddresses.Any(address => currAddress <= address && address < (currAddress + sizeof(short))))
                    {
                        if (symTable.ContainsSymbol(currAddress))
                        {
                            Symbol sym = symTable.GetSymbol(currAddress);
                            writer.Write(sym.LabelName);
                            writer.Write(":\t\t");
                            switch (sym.Size)
                            {
                            case sizeof(byte):
                            {
                                writer.Write(".byte ");
                                sbyte value = dataSegment.ReadSignedByte(currAddress);
                                writer.WriteLine(value.ToString(StringifyAsHexadecimal(value, 2)));
                                currAddress += sizeof(byte);
                                break;
                            }

                            case sizeof(short):
                            {
                                writer.Write(".half ");
                                short value = dataSegment.ReadShort(currAddress);
                                writer.WriteLine(StringifyAsHexadecimal(value, 4));
                                currAddress += sizeof(short);
                                break;
                            }

                            case sizeof(int):
                            {
                                writer.Write(".word ");
                                int value = dataSegment.ReadWord(currAddress);
                                writer.WriteLine(StringifyAsHexadecimal(value, 8));
                                currAddress += sizeof(int);
                                break;
                            }

                            case sizeof(long):
                            {
                                writer.Write(".dword ");
                                long value = dataSegment.ReadLong(currAddress);
                                writer.WriteLine(StringifyAsHexadecimal(value, 16));
                                currAddress += sizeof(int);
                                break;
                            }

                            default:
                            {
                                // just be cheap for now and write out numeric values
                                // (even though this could be an ascii string, in theory).
                                // maybe at some point the assembler will be nice enough
                                // to force strings into .strtable section for smarter
                                // heuristics, but we don't want to force that upon the user
                                // unless the user specifically directs us so.
                                // (or maybe we do?). if someone thinks of a better
                                // algorithm that can be done in the disassembler, I'm
                                // al ears.
                                int numWordsInSize = sym.Size / sizeof(int);
                                int numLeftover    = sym.Size % sizeof(int);

                                int numHalfWordsInRemainingBytes = numLeftover / sizeof(int);
                                int numRemainingBytes            = numLeftover % sizeof(int);


                                for (int i = 0; i < numWordsInSize; ++i)
                                {
                                    writer.Write(".word ");
                                    int value = dataSegment.ReadWord(currAddress);
                                    writer.WriteLine(StringifyAsHexadecimal(value, 8));
                                    currAddress += sizeof(int);
                                }

                                for (int i = 0; i < numHalfWordsInRemainingBytes; ++i)
                                {
                                    writer.Write(".half ");
                                    short value = dataSegment.ReadShort(currAddress);
                                    writer.WriteLine(StringifyAsHexadecimal(value, 4));
                                    currAddress += sizeof(short);
                                }

                                for (int i = 0; i < numRemainingBytes; ++i)
                                {
                                    writer.Write(".byte ");
                                    sbyte value = dataSegment.ReadSignedByte(currAddress);
                                    writer.WriteLine(StringifyAsHexadecimal(value, 2));
                                    currAddress += sizeof(byte);
                                }

                                break;
                            }

                                // todo: determine if we need to perform alignment
                                // detection (as in theory at this point we could judge
                                // if the new byte offset is on a word boundary).
                            }
                        }
                        else
                        {
                            writer.Write(".byte ");
                            sbyte value = dataSegment.ReadSignedByte(currAddress);
                            writer.WriteLine(value.ToString(StringifyAsHexadecimal(value, 2)));
                            currAddress += sizeof(byte);
                            break;
                        }
                    }
                    else
                    {
                        writer.Write(".half ");
                        short value = dataSegment.ReadShort(currAddress);
                        writer.WriteLine(StringifyAsHexadecimal(value, 4));
                        currAddress += sizeof(short);
                    }
                }
                else
                {
                    writer.Write(".word ");
                    int value = dataSegment.ReadWord(currAddress);
                    writer.WriteLine(StringifyAsHexadecimal(value, 8));
                    currAddress += sizeof(int);
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Formats and stringifies an instruction as well as its parameters.
        /// </summary>
        /// <param name="currPgrmCtr">The value that the program counter would theoretically be at
        /// upon encountering this instruction.</param>
        /// <param name="inst">The disassembled instruction to stringify.</param>
        /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param>
        /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns>
        public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable)
        {
            string retStr = string.Empty;

            // first, see if the program counter has a symbol mapped to it.
            if (symTable.ContainsSymbol(currPgrmCtr))
            {
                Symbol sym = symTable.GetSymbol(currPgrmCtr);
                retStr += sym.LabelName + ":\t\t";
            }
            else
            {
                retStr += "\t\t\t";
            }

            retStr += m_Name + ' ';

            if (inst.Parameters.Count() != 2)
            {
                throw new ArgumentException("U-type instruction expected 2 arguments, received " + inst.Parameters.Count());
            }

            string rd        = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(0));
            int    immediate = inst.Parameters.ElementAt(1);

            retStr += rd + ", 0x" + immediate.ToString("X2");

            return(retStr);
        }
コード例 #12
0
        /// <summary>
        /// Formats and stringifies an instruction as well as its parameters.
        /// </summary>
        /// <param name="currPgrmCtr">The value that the program counter would theoretically be at
        /// upon encountering this instruction.</param>
        /// <param name="inst">The disassembled instruction to stringify.</param>
        /// <param name="symTable">A reverse symbol table used to map addresses back to label names.</param>
        /// <returns>A string representing the instruction and its parameters that can be written to a text file.</returns>
        public string GetFormattedInstruction(int currPgrmCtr, DisassembledInstruction inst, ReverseSymbolTable symTable)
        {
            string retStr = string.Empty;

            // first, see if the program counter has a symbol mapped to it.
            if (symTable.ContainsSymbol(currPgrmCtr))
            {
                Symbol sym = symTable.GetSymbol(currPgrmCtr);
                retStr += sym.LabelName + ":\t\t";
            }
            else
            {
                retStr += "\t\t\t";
            }

            retStr += m_Name + ' ';
            if (inst.Parameters.Count() != 3)
            {
                throw new ArgumentException("sb instruction expected 3 arguments, received " + inst.Parameters.Count());
            }

            string rs1 = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(0));
            string rs2 = ReverseRegisterMap.GetStringifiedRegisterValue(inst.Parameters.ElementAt(1));

            retStr += rs1 + ", " + rs2 + ", ";

            int offset = inst.Parameters.ElementAt(2);

            int address = currPgrmCtr + offset;

            // see if there's a symbol mapped to it.
            if (symTable.ContainsSymbol(address))
            {
                Symbol sym = symTable.GetSymbol(address);
                retStr += sym.LabelName;
            }
            else
            {
                retStr += "0x" + address.ToString("X2");
            }

            return(retStr);
        }
コード例 #13
0
 public DisassembledElfFile(DataSegmentAccessor dataSegment, TextSegmentAccessor instructions,
                            IEnumerable <byte> externSegment, ReverseSymbolTable symTable) :
     base(dataSegment, instructions, externSegment, symTable, new SourceDebugData(string.Empty))
 {
     m_FileWriter = new ElfAssemblyFileWriter(this);
 }
コード例 #14
0
        private static IEnumerable <InstructionData> GenerateInstructionDataWithNoSource(ReverseSymbolTable symTable,
                                                                                         TextSegmentAccessor textSegment)
        {
            var instructions = new List <InstructionData>();
            int currPgrmCtr  = textSegment.StartingSegmentAddress;

            foreach (DisassembledInstruction inst in textSegment.RawInstructions)
            {
                IParameterStringifier stringifier = InstructionTextMap.GetParameterStringifier(inst.InstructionType);
                string formattedInstruction       = stringifier.GetFormattedInstruction(currPgrmCtr, inst, symTable);
                var    srcLineInfo     = new SourceLineInformation(string.Empty, -1, currPgrmCtr);
                var    instructionElem = new InstructionData(inst.InstructionWord, currPgrmCtr, formattedInstruction, srcLineInfo);
                instructions.Add(instructionElem);
                currPgrmCtr += sizeof(int);
            }

            return(instructions);
        }
コード例 #15
0
        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);
            }
        }