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); }
/// <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); }