private void PatchRELEntries(byte[] File_Buffer) { List <Relocation_Entry> Relocation_Entries_List = new List <Relocation_Entry>(); List <string> Relocated_Output = new List <string>(); for (int i = 0; i < Import_Entries.Length; i++) { Import_Entry Current_Import_Entry = Import_Entries[i]; uint Current_Section = 0; uint Current_Offset = 0; uint Value = 0; uint Where = 0; uint Orig = 0; int Index = 0; if (Current_Import_Entry.Module_Id == Header.Id) // These relocations are inside our own file { while (true) { int Rel_Offset = (int)(Current_Import_Entry.Offset + Index * 8); Relocation_Entry Entry = new Relocation_Entry(BitConverter.ToUInt16(File_Buffer, Rel_Offset).Reverse(), File_Buffer[Rel_Offset + 2], File_Buffer[Rel_Offset + 3], BitConverter.ToUInt32(File_Buffer, Rel_Offset + 4).Reverse()); Relocation_Entries_List.Add(Entry); //Debug.WriteLine(Entry.Offset.ToString("X4") + " | " + Entry.Type_Value.ToString()); if (Entry.IsEnd()) { break; } Current_Offset += Entry.Offset; uint OverwriteAddress = 0; uint OverwriteValue = 0; switch (Entry.Type) { case RelocationType.R_DOLPHIN_SECTION: Current_Section = Entry.Section; Current_Offset = 0; //Debug.WriteLine("DOLPHIN_SECTION Set Section to " + Current_Section); //Relocated_Output.Add("DOLPHIN_SECTION Set Section to " + Current_Section); break; case RelocationType.R_DOLPHIN_NOP: break; case RelocationType.R_PPC_ADDR32: OverwriteAddress = GetSectionAddress(Current_Section, Current_Offset); OverwriteValue = GetSectionAddress(Entry.Section, Entry.Addend); //Debug.WriteLine(string.Format("ADDR32 Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X"))); //Relocated_Output.Add(string.Format("ADDR32 Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X"))); break; case RelocationType.R_PPC_ADDR16_LO: OverwriteAddress = GetSectionAddress(Current_Section, Current_Offset); OverwriteValue = GetSectionAddress(Entry.Section, Entry.Addend) & 0xFFFF; //Debug.WriteLine(string.Format("ADDR16_LO Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X"))); //Relocated_Output.Add(string.Format("ADDR16_LO Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X"))); break; case RelocationType.R_PPC_ADDR16_HA: OverwriteAddress = GetSectionAddress(Current_Section, Current_Offset); OverwriteValue = GetSectionAddress(Entry.Section, Entry.Addend); if ((OverwriteValue & 0x8000) == 0x8000) { OverwriteValue += 0x00010000; } //OverwriteValue += 0x80000000; OverwriteValue = (OverwriteValue >> 16) & 0xFFFF; //Debug.WriteLine(string.Format("ADDR16_HA Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X"))); //Relocated_Output.Add(string.Format("ADDR16_HA Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X"))); break; case RelocationType.R_PPC_REL24: Where = GetSectionAddress(Current_Section, Current_Offset); Value = GetSectionAddress(Entry.Section, Entry.Addend); Value -= Where; Orig = BitConverter.ToUInt32(File_Buffer, (int)Where).Reverse(); Orig &= 0xFC000003; Orig |= Value & 0x03FFFFFC; //Debug.WriteLine("REL24 Offset 0x{0} is now 0x{1}", Where.ToString("X"), Orig.ToString("X")); //Relocated_Output.Add(string.Format("REL24 Offset 0x{0} is now 0x{1}", Where.ToString("X"), Orig.ToString("X"))); break; default: Debug.WriteLine(string.Format("Unsupported Relocation Type: {0}", Entry.Type)); break; } Index++; } } else // Move on to external relocations { /*while (true) * { * int Rel_Offset = (int)(Current_Import_Entry.Offset + Index * 8); * Relocation_Entry Entry = new Relocation_Entry(BitConverter.ToUInt16(File_Buffer.Skip(Rel_Offset).Take(2).Reverse().ToArray(), 0), * File_Buffer[Rel_Offset + 2], File_Buffer[Rel_Offset + 3], BitConverter.ToUInt32(File_Buffer.Skip(Rel_Offset + 4).Take(4).Reverse().ToArray(), 0)); * Relocation_Entries_List.Add(Entry); * * if (Entry.IsEnd()) * break; * * //if (Entry.Type == RelocationType.R_DOLPHIN_SECTION || Entry.Type == RelocationType.R_DOLPHIN_NOP) * //Debug.WriteLine("Extenral Entry called an unneeded opcode: " + Entry.Type.ToString()); * * Index++; * }*/ } } using (TextWriter Writer = File.CreateText(Path.GetDirectoryName(Location) + "\\Relocation_Output.txt")) { foreach (string s in Relocated_Output) { Writer.WriteLine(s); } Writer.Flush(); } }
public REL(byte[] Rel_Buffer, string Rel_Location, bool Load_Externals = true) { Debug.WriteLine(string.Format("============= Loading REL {0} =============", Path.GetFileNameWithoutExtension(Rel_Location))); Header = new REL_Header(Rel_Buffer); Location = Rel_Location; // Load Section Entries Section_Entries = new Section_Entry[Header.Section_Count]; for (int i = 0; i < Header.Section_Count; i++) { int Section_Offset = (int)(Header.Section_Table_Offset + i * 8); if (Section_Offset >= Rel_Buffer.Length) { Debug.WriteLine(string.Format("Section {0} could not be loaded as the file ended while parsing it!", i)); continue; } Section_Entry Entry = new Section_Entry(BitConverter.ToUInt32(Rel_Buffer, Section_Offset).Reverse(), BitConverter.ToUInt32(Rel_Buffer, Section_Offset + 4).Reverse()); // Sanity Checks if (Entry.Offset == 0 && Entry.Size != 0) // .bss Section { // Set .bss offset if (i > 0) { Entry.Offset = Section_Entries[i - 1].Offset + Section_Entries[i - 1].Size; } if (Entry.Size != Header.BSS_Size) { Debug.WriteLine(string.Format("Section {0} seems to be the .bss section, but its size does not match the header's size. This size: 0x{1} | Header size: 0x{2}", i, Entry.Size.ToString("X"), Header.BSS_Size.ToString("X"))); } else if (Entry.Offset == Header.Import_Offset || Entry.Offset == Header.Relocation_Offset) { Debug.WriteLine(string.Format("Section {0} seemst o be the .bss section, but it overlaps with the import or relocation section. It's likely not in the file.", i)); } else { Debug.WriteLine(string.Format("Successfully loaded the .bss Section: {0} | Offset: {1} | Size: {2}", i, Entry.Offset.ToString("X"), Entry.Size.ToString("X"))); } } else if (Entry.Offset != 0 && Entry.Size != 0) { if (Entry.Offset < Header.GetHeaderSize()) { Debug.WriteLine("Section {0} seems to be inside the REL header! Offset: 0x{1} | Expected Minimum Offset: 0x{2}", i, Entry.Offset.ToString("X"), Header.GetHeaderSize().ToString("X")); } else if (Entry.Offset + Entry.Size >= Rel_Buffer.Length) { Debug.WriteLine("Section {0} seems to go past the end of the file! End Offset: 0x{1} | Maximum End Offset: 0x{2}", i, (Entry.Offset + Entry.Size).ToString("X"), Rel_Buffer.Length.ToString("X")); } else { Debug.WriteLine(string.Format("Successfully loaded Section {0}! Offset: 0x{1} | Size: 0x{2} | End Offset: 0x{3}", i, Entry.Offset.ToString("X"), Entry.Size.ToString("X"), (Entry.Offset + Entry.Size).ToString("X"))); } } else { Debug.WriteLine(string.Format("Section {0} has a zeroed Offset and Size! It's probably an unused section.", i)); } //Debug.WriteLine(string.Format("Added section #{0} with a start address of 0x{1}", i, Entry.Offset.ToString("X8"))); Section_Entries[i] = Entry; } // Load Import Table Entries LoadModuleNames(Rel_Location, Load_Externals); int Import_Table_Count = (int)(Header.Import_Size / 8); //(int)(Header.Relocation_Offset - Header.Import_Offset) / 8; Import_Entries = new Import_Entry[Import_Table_Count]; for (int i = 0; i < Import_Table_Count; i++) { int Current_Offset = (int)(Header.Import_Offset + i * 8); uint Id = BitConverter.ToUInt32(Rel_Buffer, Current_Offset).Reverse(); Import_Entries[i] = new Import_Entry(Id, BitConverter.ToUInt32(Rel_Buffer, Current_Offset + 4).Reverse(), Module_Names.ContainsKey(Id) ? Module_Names[Id] : null); } // Load and Patch Relocation Table Entries //PatchRELEntries(Rel_Buffer); }