示例#1
0
        public bool DoIt(string[] args)
        {
            if (args.Length >= 2)
            {
                var mapFile = args[1];

                var linkFile = (args.Length >= 3) ? args[2] : null;

                var      map  = new MapFile(mapFile);
                LinkFile link = null;
                if (linkFile != null)
                {
                    link = new LinkFile(linkFile);
                }

                var debug_symbol_table = new HSDStruct((map.Entries.Count + 1) * 0xC);
                int symbol_index       = 0;
                foreach (var e in map.Entries)
                {
                    debug_symbol_table.SetInt32(symbol_index * 0xC, (int)e.Start);
                    debug_symbol_table.SetInt32(symbol_index * 0xC + 4, (int)e.End);

                    if (link != null && link.TryGetAddressSymbol(e.Start, out string sym))
                    {
                        debug_symbol_table.SetString(symbol_index * 0xC + 8, sym, true);
                    }
                    else
                    if (!e.Symbol.StartsWith("zz_"))
                    {
                        debug_symbol_table.SetString(symbol_index * 0xC + 8, e.Symbol, true);
                    }
                    symbol_index++;
                }

                var function = new HSDAccessor()
                {
                    _s = new HSDStruct(0x10)
                };
                function._s.SetInt32(0, map.Entries.Count);
                function._s.SetReferenceStruct(0x04, debug_symbol_table);

                HSDRawFile f = new HSDRawFile();
                f.Roots.Add(new HSDRootNode()
                {
                    Data = function,
                    Name = "mexDebug"
                });

                f.Save("MxDb.dat");


                return(true);
            }

            return(false);
        }
示例#2
0
文件: RelocELF.cs 项目: akaneia/MexTK
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public static HSDAccessor GenerateFunctionDAT(LinkedELF lelf, LinkFile link, string[] functions, bool debug, bool quiet = false)
        {
            // Generate Function DAT
            var function = new HSDAccessor()
            {
                _s = new HSDStruct(0x20)
            };

            // Generate code section
            HSDStruct debug_symbol_table = null;
            int       debug_symbol_count = 0;
            Dictionary <SymbolData, long> dataToOffset = new Dictionary <SymbolData, long>();

            byte[] codedata;
            using (MemoryStream code = new MemoryStream())
            {
                // create debug symbol table
                if (debug)
                {
                    debug_symbol_table = new HSDStruct((lelf.AllSymbols.Count + 1) * 0xC);
                }

                // process all code
                foreach (var v in lelf.AllSymbols)
                {
                    // align
                    if (code.Length % 4 != 0)
                    {
                        code.Write(new byte[4 - (code.Length % 4)], 0, 4 - ((int)code.Length % 4));
                    }

                    int code_start = (int)code.Position;
                    // write code
                    if (v.Data.Length == 0 && link.TryGetSymbolAddress(CppSanatize(v.Symbol), out uint addr))
                    {
                        dataToOffset.Add(v, addr);
                    }
                    else
                    {
                        dataToOffset.Add(v, code.Length);
                        code.Write(v.Data, 0, v.Data.Length);
                    }
                    int code_end = (int)code.Position;

                    //Console.WriteLine($"{v.SectionName} {v.Symbol} Start: {code_start.ToString("X")} End: {code_end.ToString("X")} ");

                    if (debug && code_start != code_end)
                    {
                        debug_symbol_table.SetInt32(debug_symbol_count * 0xC, code_start);
                        debug_symbol_table.SetInt32(debug_symbol_count * 0xC + 4, code_end);
                        debug_symbol_table.SetString(debug_symbol_count * 0xC + 8, string.IsNullOrEmpty(v.Symbol) ? v.SectionName : v.Symbol, true);
                        debug_symbol_count++;
                    }
                }
                codedata = code.ToArray();

                // resize debug table
                if (debug)
                {
                    debug_symbol_table.Resize(debug_symbol_count * 0xC);
                }
            }

            // generate function table
            HSDStruct functionTable = new HSDStruct(8);
            var       funcCount     = 0;
            var       fl            = functions.ToList();

            foreach (var v in lelf.SymbolToData)
            {
                functionTable.Resize(8 * (funcCount + 1));
                functionTable.SetInt32(funcCount * 8, fl.IndexOf(v.Key));
                functionTable.SetInt32(funcCount * 8 + 4, (int)dataToOffset[v.Value]);
                funcCount++;
            }


            // set function table
            function._s.SetReferenceStruct(0x0C, functionTable);
            function._s.SetInt32(0x10, funcCount);


            // Generate Relocation Table
            HSDStruct relocationTable = new HSDStruct(0);
            var       relocCount      = 0;

            foreach (var v in lelf.AllSymbols)
            {
                // check data length
                if (v.Data.Length == 0)
                {
                    if (link.ContainsSymbol(CppSanatize(v.Symbol)))
                    {
                        continue;
                    }
                    else
                    {
                        throw new Exception($"Error: {v.Symbol} length is {v.Data.Length.ToString("X")}");
                    }
                }

                // print debug info
                if (!quiet)
                {
                    Console.WriteLine($"{v.Symbol,-30} {v.SectionName, -50} Offset: {dataToOffset[v].ToString("X8"), -16} Length: {v.Data.Length.ToString("X8")}");

                    if (v.Relocations.Count > 0)
                    {
                        Console.WriteLine($"\t {"Section:",-50} {"RelocType:",-20} {"FuncOffset:", -16} {"SectionOffset:"}");
                    }
                }

                // process and create relocation table
                foreach (var reloc in v.Relocations)
                {
                    if (!quiet)
                    {
                        Console.WriteLine($"\t {reloc.Symbol.SectionName, -50} {reloc.Type, -20} {reloc.Offset.ToString("X8"), -16} {reloc.AddEnd.ToString("X8")}");
                    }

                    // gather code positions
                    var codeOffset       = (int)(dataToOffset[v] + reloc.Offset);
                    var toFunctionOffset = (int)(dataToOffset[reloc.Symbol] + reloc.AddEnd);

                    // currently supported types check
                    switch (reloc.Type)
                    {
                    case RelocType.R_PPC_REL32:
                    case RelocType.R_PPC_REL24:
                    case RelocType.R_PPC_ADDR32:
                    case RelocType.R_PPC_ADDR16_LO:
                    case RelocType.R_PPC_ADDR16_HA:
                        break;

                    case (RelocType)0x6D:
                        break;

                    default:
                        // no exception, but not guarenteed to work
                        Console.WriteLine($"Warning: unsupported reloc type {toFunctionOffset.ToString("X")} " + reloc.Type.ToString("X") + $" in {v.Symbol} to {reloc.Symbol.Symbol} send this to Ploaj or UnclePunch");
                        break;
                    }

                    bool addEntry = true;

                    // only apply optimization if not external
                    if (!reloc.Symbol.External)
                    {
                        // calculate relative offset
                        var rel = toFunctionOffset - codeOffset;

                        // apply relocation automatically if possible
                        switch (reloc.Type)
                        {
                        case (RelocType)0x6D:
                        case RelocType.R_PPC_REL32:
                            codedata[codeOffset]     = (byte)((rel >> 24) & 0xFF);
                            codedata[codeOffset + 1] = (byte)((rel >> 16) & 0xFF);
                            codedata[codeOffset + 2] = (byte)((rel >> 8) & 0xFF);
                            codedata[codeOffset + 3] = (byte)((rel) & 0xFF);

                            addEntry = false;
                            break;

                        case RelocType.R_PPC_REL24:
                            var cur = ((codedata[codeOffset] & 0xFF) << 24) | ((codedata[codeOffset + 1] & 0xFF) << 16) | ((codedata[codeOffset + 2] & 0xFF) << 8) | ((codedata[codeOffset + 3] & 0xFF));
                            rel = cur | (rel & 0x03FFFFFC);

                            codedata[codeOffset]     = (byte)((rel >> 24) & 0xFF);
                            codedata[codeOffset + 1] = (byte)((rel >> 16) & 0xFF);
                            codedata[codeOffset + 2] = (byte)((rel >> 8) & 0xFF);
                            codedata[codeOffset + 3] = (byte)((rel) & 0xFF);

                            addEntry = false;
                            break;
                        }
                    }

                    // add relocation to table
                    if (addEntry)
                    {
                        relocationTable.Resize((relocCount + 1) * 0x08);
                        relocationTable.SetInt32(0x00 + relocCount * 8, codeOffset);
                        relocationTable.SetByte(0x00 + relocCount * 8, (byte)reloc.Type);
                        relocationTable.SetInt32(0x04 + relocCount * 8, toFunctionOffset);

                        relocCount++;
                    }
                }
            }

            function._s.SetReferenceStruct(0x00, new HSDStruct(codedata));
            function._s.SetReferenceStruct(0x04, relocationTable);
            function._s.SetInt32(0x08, relocCount);

            if (debug_symbol_table != null)
            {
                function._s.SetInt32(0x14, codedata.Length);
                function._s.SetInt32(0x18, debug_symbol_count);
                function._s.SetReferenceStruct(0x1C, debug_symbol_table);
            }

            return(function);
        }