Beispiel #1
0
 private V1Disassembler(SmxFile file, SmxCodeV1Section code, int proc_offset)
 {
     data_         = file.Header.Data;
     code_start_   = code.CodeStart;
     proc_offset_  = proc_offset;
     cursor_       = proc_offset;
     cursor_limit_ = code.Header.CodeSize;
 }
Beispiel #2
0
 public static V1Instruction[] TryDisassemble(SmxFile file, SmxCodeV1Section code, int proc_offset)
 {
     try
     {
         return(Disassemble(file, code, proc_offset));
     }
     catch
     {
         return(null);
     }
 }
Beispiel #3
0
        public SmxFile(BinaryReader br)
        {
            Header = FileHeader.From(br);

            // Parse precursor sections.
            foreach (var section in Header.Sections)
            {
                if (section.Name == ".names")
                {
                    Names = new SmxNameTable(Header, section);
                }
                else if (section.Name == ".dbg.strings")
                {
                    DebugNames = new SmxNameTable(Header, section);
                }
                else if (section.Name == ".dbg.info")
                {
                    DebugInfo = new SmxDebugInfoSection(Header, section);
                }
            }

            CalledFunctions = new SmxCalledFunctionsTable();

            // .dbg.names was removed when RTTI was added.
            if (DebugNames == null)
            {
                DebugNames = Names;
            }

            // Parse out other sections.
            var unknown = new List <SectionEntry>();

            foreach (var section in Header.Sections)
            {
                try
                {
                    switch (section.Name)
                    {
                    case ".names":
                    case ".dbg.strings":
                    case ".dbg.info":
                        break;

                    case ".natives":
                        Natives = new SmxNativeTable(Header, section, Names);
                        break;

                    case ".publics":
                        Publics = new SmxPublicTable(Header, section, Names);
                        break;

                    case ".pubvars":
                        Pubvars = new SmxPubvarTable(Header, section, Names);
                        break;

                    case ".tags":
                        Tags = new SmxTagTable(Header, section, Names);
                        break;

                    case ".data":
                        Data = new SmxDataSection(Header, section);
                        break;

                    case ".code":
                        CodeV1 = new SmxCodeV1Section(Header, section);
                        break;

                    case ".dbg.files":
                        DebugFiles = new SmxDebugFilesTable(Header, section, DebugNames);
                        break;

                    case ".dbg.lines":
                        DebugLines = new SmxDebugLinesTable(Header, section);
                        break;

                    case ".dbg.natives":
                        DebugNatives = new SmxDebugNativesTable(Header, section, DebugNames);
                        break;

                    case ".dbg.symbols":
                        DebugSymbols = new SmxDebugSymbolsTable(Header, section, DebugInfo, DebugNames);
                        break;

                    case ".dbg.methods":
                        DebugMethods = new SmxDebugMethods(Header, section, Names);
                        break;

                    case ".dbg.globals":
                        DebugGlobals = new SmxDebugGlobals(Header, section, Names);
                        break;

                    case ".dbg.locals":
                        DebugLocals = new SmxDebugLocals(this, Header, section, Names);
                        break;

                    case "rtti.data":
                        RttiData = new SmxRttiData(this, Header, section);
                        break;

                    case "rtti.classdefs":
                        RttiClassDefs = new SmxRttiClassDefTable(Header, section, Names);
                        break;

                    case "rtti.fields":
                        RttiFields = new SmxRttiFieldTable(Header, section, Names);
                        break;

                    case "rtti.methods":
                        RttiMethods = new SmxRttiMethodTable(Header, section, Names);
                        break;

                    case "rtti.natives":
                        RttiNatives = new SmxRttiNativeTable(Header, section, Names);
                        break;

                    case "rtti.enums":
                        RttiEnums = new SmxRttiEnumTable(Header, section, Names);
                        break;

                    case "rtti.typedefs":
                        RttiTypedefs = new SmxRttiTypedefTable(Header, section, Names);
                        break;

                    case "rtti.typesets":
                        RttiTypesets = new SmxRttiTypesetTable(Header, section, Names);
                        break;

                    default:
                        unknown.Add(section);
                        break;
                    }
                }
                catch
                {
                    // Set a breakpoint here to see why the section failed to be parsed.
                    unknown.Add(section);
                }
            }
            UnknownSections = unknown.ToArray();

            // Disassemble all functions right away to find all called functions.
            if (DebugSymbols != null)
            {
                foreach (var entry in DebugSymbols.Entries)
                {
                    if (entry.Ident != SymKind.Function)
                    {
                        continue;
                    }
                    V1Disassembler.TryDisassemble(this, CodeV1, entry.Address);
                }
            }
            if (Publics != null)
            {
                foreach (var pubfun in Publics.Entries)
                {
                    V1Disassembler.TryDisassemble(this, CodeV1, (int)pubfun.Address);
                }
            }
            if (CalledFunctions != null)
            {
                foreach (var fun in CalledFunctions.Entries)
                {
                    V1Disassembler.TryDisassemble(this, CodeV1, (int)fun.Address);
                }
            }
        }
Beispiel #4
0
        public static V1Instruction[] Disassemble(SmxFile file, SmxCodeV1Section code, int proc_offset)
        {
            var disassembler = new V1Disassembler(file, code, proc_offset);

            return(disassembler.disassemble());
        }
Beispiel #5
0
 public static V1Instruction[] Disassemble(SmxFile file, SmxCodeV1Section code, int proc_offset)
 {
     var disassembler = new V1Disassembler(file, code, proc_offset);
     return disassembler.disassemble();
 }
Beispiel #6
0
 private V1Disassembler(SmxFile file, SmxCodeV1Section code, int proc_offset)
 {
     data_ = file.Header.Data;
     code_start_ = code.CodeStart;
     proc_offset_ = proc_offset;
     cursor_ = proc_offset;
     cursor_limit_ = code.Header.CodeSize;
 }
Beispiel #7
0
        private void renderCodeSection(TreeNode root, SmxCodeV1Section code)
        {
            root.Tag = new NodeData(delegate()
            {
                renderSectionHeaderDetail(code.SectionHeader);
                addDetailLine("codesize = {0} bytes", code.Header.CodeSize);
                addDetailLine("cellsize = {0} bytes", code.Header.CellSize);
                addDetailLine("codeversion = 0x{0:x}", code.Header.CodeVersion);
                addDetailLine("flags = 0x{0:x} ; {0}", code.Header.Flags, code.Header.Flags.ToString());
                addDetailLine("main = 0x{0:x}", code.Header.main);
                addDetailLine("codeoffs = 0x{0:x}", code.Header.codeoffs);
                endDetailUpdate();
            }, code);

            root.Nodes.Add("cell view").Tag = new NodeData(delegate()
            {
                renderHexView(code.Reader(), (int)code.Header.CodeSize);
            }, null);

            var functionMap = new Dictionary<string, uint>();

            if (file_.Publics != null)
            {
                foreach (var pubfun in file_.Publics.Entries)
                {
                    functionMap[pubfun.Name] = pubfun.Address;
                }
            }
            if (file_.DebugSymbols != null)
            {
                foreach (var sym in file_.DebugSymbols.Entries)
                {
                    if (sym.Ident != SymKind.Function)
                        continue;
                    functionMap[sym.Name] = sym.CodeStart;
                }
            }

            foreach (var pair in functionMap)
            {
                var name = pair.Key;
                var address = functionMap[pair.Key];
                root.Nodes.Add(pair.Key).Tag = new NodeData(delegate()
                {
                    renderCodeView(code, name, (int)address);
                }, null);
            }
        }
Beispiel #8
0
        private void renderCodeView(SmxCodeV1Section code, string name, int address)
        {
            startDetailUpdate();

            V1Instruction[] insns;
            try
            {
                insns = V1Disassembler.Disassemble(file_, code, address);
            }
            catch (Exception e)
            {
               addDetailLine("Could not disassemble method {0}: {1}", name, e.Message);
               endDetailUpdate();
               return;
            }

            addDetailLine("; {0}", name);
            addDetailLine("; {0} instruction(s)", insns.Length);
            addDetailLine("; starts at code address 0x{0:x}", address);
            addDetailLine("---");

            if (insns.Length == 0)
            {
                endDetailUpdate();
                return;
            }


            // Find the largest address so we can get consistent column length.
            int last_address = insns[insns.Length - 1].Address;
            var ndigits = string.Format("{0:x}", last_address).Length;
            var addrfmt = "0x{0:x" + ndigits + "}: ";

            var buffer = new StringBuilder();
            var comment = new StringBuilder();
            foreach (var insn in insns)
            {
                buffer.Clear();
                comment.Clear();
                buffer.Append(insn.Info.Name);

                for (var i = 0; i < insn.Params.Length; i++)
                {
                    if (i >= insn.Info.Params.Length)
                        break;
                    var kind = insn.Info.Params[i];
                    var value = insn.Params[i];

                    switch (kind)
                    {
                        case V1Param.Constant:
                        case V1Param.CaseTable:
                            buffer.Append(string.Format(" 0x{0:x}", value));
                            comment.Append(string.Format(" {0}", value));
                            break;
                        case V1Param.Native:
                            buffer.Append(string.Format(" {0}", value));
                            if (file_.Natives != null && value < file_.Natives.Length)
                                comment.Append(string.Format(" {0}", file_.Natives[value].Name));
                            break;
                        case V1Param.Jump:
                            int delta = value - insn.Address;
                            buffer.Append(string.Format(" 0x{0:x}", value));
                            if (delta >= 0)
                                comment.Append(string.Format(" +0x{0:x}", delta));
                            else
                                comment.Append(string.Format(" -0x{0:x}", -delta));
                            break;
                        case V1Param.Address:
                        {
                            DebugSymbolEntry sym = null;
                            if (file_.DebugSymbols != null)
                                sym = file_.DebugSymbols.FindDataRef(value);
                            buffer.Append(string.Format(" 0x{0:x}", value));
                            if (sym != null)
                                comment.Append(string.Format(" {0}", sym.Name));
                            else
                                comment.Append(string.Format(" {0}", value));
                            break;
                        }
                        case V1Param.Stack:
                        {
                            DebugSymbolEntry sym = null;
                            if (file_.DebugSymbols != null)
                                sym = file_.DebugSymbols.FindStackRef(insn.Address, value);
                            buffer.Append(string.Format(" 0x{0:x}", value));
                            if (sym != null)
                                comment.Append(string.Format(" {0}", sym.Name));
                            else
                                comment.Append(string.Format(" {0}", value));
                            break;
                        }
                        case V1Param.Function:
                            string fun = file_.FindFunctionName(value);
                            buffer.Append(string.Format(" 0x{0:x}", value));
                            comment.Append(string.Format(" {0}", fun));
                            break;
                    }
                }

                detail_buffer_.Append(string.Format(addrfmt, insn.Address));
                detail_buffer_.Append(string.Format("{0,-32}", buffer));
                if (comment.Length > 0)
                {
                    detail_buffer_.Append(string.Format(" ;{1}", buffer, comment));
                }
                detail_buffer_.Append("\r\n");
            }

            endDetailUpdate();
        }
Beispiel #9
0
        public SmxFile(BinaryReader br)
        {
            Header = FileHeader.From(br);

            // Parse precursor sections.
            foreach (var section in Header.Sections)
            {
                if (section.Name == ".names")
                {
                    Names = new SmxNameTable(Header, section);
                }
                else if (section.Name == ".dbg.strings")
                {
                    DebugNames = new SmxNameTable(Header, section);
                }
                else if (section.Name == ".dbg.info")
                {
                    DebugInfo = new SmxDebugInfoSection(Header, section);
                }
            }

            // Parse out other sections.
            var unknown = new List <SectionEntry>();

            foreach (var section in Header.Sections)
            {
                switch (section.Name)
                {
                case ".names":
                case ".dbg.strings":
                case ".dbg.info":
                    break;

                case ".natives":
                    Natives = new SmxNativeTable(Header, section, Names);
                    break;

                case ".publics":
                    Publics = new SmxPublicTable(Header, section, Names);
                    break;

                case ".pubvars":
                    Pubvars = new SmxPubvarTable(Header, section, Names);
                    break;

                case ".tags":
                    Tags = new SmxTagTable(Header, section, Names);
                    break;

                case ".data":
                    Data = new SmxDataSection(Header, section);
                    break;

                case ".code":
                    CodeV1 = new SmxCodeV1Section(Header, section);
                    break;

                case ".dbg.files":
                    DebugFiles = new SmxDebugFilesTable(Header, section, DebugNames);
                    break;

                case ".dbg.lines":
                    DebugLines = new SmxDebugLinesTable(Header, section);
                    break;

                case ".dbg.natives":
                    DebugNatives = new SmxDebugNativesTable(Header, section, DebugNames);
                    break;

                case ".dbg.symbols":
                    DebugSymbols = new SmxDebugSymbolsTable(Header, section, DebugInfo, DebugNames);
                    break;

                default:
                    unknown.Add(section);
                    break;
                }
            }
            UnknownSections = unknown.ToArray();
        }
Beispiel #10
0
        public SmxFile(BinaryReader br)
        {
            Header = FileHeader.From(br);

            // Parse precursor sections.
            foreach (var section in Header.Sections)
            {
                if (section.Name == ".names")
                    Names = new SmxNameTable(Header, section);
                else if (section.Name == ".dbg.strings")
                    DebugNames = new SmxNameTable(Header, section);
                else if (section.Name == ".dbg.info")
                    DebugInfo = new SmxDebugInfoSection(Header, section);
            }
            
            // Parse out other sections.
            var unknown = new List<SectionEntry>();
            foreach (var section in Header.Sections)
            {
                switch (section.Name)
                {
                case ".names":
                case ".dbg.strings":
                case ".dbg.info":
                    break;
                case ".natives":
                    Natives = new SmxNativeTable(Header, section, Names);
                    break;
                case ".publics":
                    Publics = new SmxPublicTable(Header, section, Names);
                    break;
                case ".pubvars":
                    Pubvars = new SmxPubvarTable(Header, section, Names);
                    break;
                case ".tags":
                    Tags = new SmxTagTable(Header, section, Names);
                    break;
                case ".data":
                    Data = new SmxDataSection(Header, section);
                    break;
                case ".code":
                    CodeV1 = new SmxCodeV1Section(Header, section);
                    break;
                case ".dbg.files":
                    DebugFiles = new SmxDebugFilesTable(Header, section, DebugNames);
                    break;
                case ".dbg.lines":
                    DebugLines = new SmxDebugLinesTable(Header, section);
                    break;
                case ".dbg.natives":
                    DebugNatives = new SmxDebugNativesTable(Header, section, DebugNames);
                    break;
                case ".dbg.symbols":
                    DebugSymbols = new SmxDebugSymbolsTable(Header, section, DebugInfo, DebugNames);
                    break;
                default:
                    unknown.Add(section);
                    break;
                }
            }
            UnknownSections = unknown.ToArray();
        }