public override void RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, Elf32_Rela rela) { if (loader.Sections.Count <= sym.SectionIndex) return; if (sym.SectionIndex == 0) return; var symSection = loader.Sections[(int)sym.SectionIndex]; uint S = (uint)sym.Value + symSection.Address.ToUInt32(); int A = 0; int sh = 0; uint mask = ~0u; var addr = referringSection.Address + rela.r_offset; uint P = (uint)addr.ToLinear(); uint PP = P; Debug.Print(" off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2} {5}", rela.r_offset, (SparcRt)(rela.r_info & 0xFF), sym.Name, rela.r_addend, (int)(rela.r_info >> 8), symSection.Name); var rt = (SparcRt)(rela.r_info & 0xFF); switch (rt) { case 0: return; case SparcRt.R_SPARC_HI22: A = rela.r_addend; sh = 10; P = 0; break; case SparcRt.R_SPARC_LO10: A = rela.r_addend; mask = 0x3FF; P = 0; break; case SparcRt.R_SPARC_WDISP30: A = rela.r_addend; P = ~P + 1; sh = 2; break; case SparcRt.R_SPARC_COPY: Debug.Print("Relocation type {0} not handled yet.", rt); return; default: throw new NotImplementedException(string.Format( "SPARC ELF relocation type {0} not implemented yet.", rt)); } var relR = program.CreateImageReader(addr); var relW = program.CreateImageWriter(addr); var w = relR.ReadBeUInt32(); w += ((uint)(S + A + P) >> sh) & mask; relW.WriteBeUInt32(w); }
public override void RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, Elf32_Rela rela) { if (loader.Sections.Count <= sym.SectionIndex) return; if (sym.SectionIndex == 0) return; var symSection = loader.Sections[(int)sym.SectionIndex]; uint S = (uint)sym.Value + symSection.Address.ToUInt32(); int A = 0; int sh = 0; uint mask = ~0u; var addr = referringSection.Address + rela.r_offset; uint P = (uint)addr.ToLinear(); uint PP = P; var relR = program.CreateImageReader(addr); var relW = program.CreateImageWriter(addr); var rt = (i386Rt)(rela.r_info & 0xFF); switch (rt) { case i386Rt.R_386_NONE: // just ignore (common) break; case i386Rt.R_386_32: // S + A // Read the symTabIndex'th symbol. A = rela.r_addend; P = 0; break; case i386Rt.R_386_PC32: // S + A - P if (sym.Value == 0) { // This means that the symbol doesn't exist in this module, and is not accessed // through the PLT, i.e. it will be statically linked, e.g. strcmp. We have the // name of the symbol right here in the symbol table entry, but the only way // to communicate with the loader is through the target address of the call. // So we use some very improbable addresses (e.g. -1, -2, etc) and give them entries // in the symbol table //S = nextFakeLibAddr--; // Allocate a new fake address //loader.AddSymbol(S, sym.Name); //} } A = rela.r_addend; P = ~P + 1; break; case i386Rt.R_386_GLOB_DAT: // This relocation type is used to set a global offset table entry to the address of the // specified symbol. The special relocation type allows one to determine the // correspondence between symbols and global offset table entries. P = 0; break; default: throw new NotImplementedException(string.Format( "i386 ELF relocation type {0} not implemented yet.", rt)); } var w = relR.ReadBeUInt32(); w += ((uint)(S + A + P) >> sh) & mask; relW.WriteBeUInt32(w); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf64_Rela rela) { var rt = (RiscV64Rt)(rela.r_info & 0xFF); switch (rt) { case RiscV64Rt.R_RISCV_COPY: break; } }
public override void RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, Elf64_Rela rela) { if (loader.Sections.Count <= sym.SectionIndex) return; if (sym.SectionIndex == 0) return; var symSection = loader.Sections[(int)sym.SectionIndex]; ulong S = (ulong)sym.Value + symSection.Address.ToLinear(); long A = 0; int sh = 0; uint mask = ~0u; Address addr; ulong P; ImageReader relR; ImageWriter relW; if (referringSection.Address != null) { addr = referringSection.Address + rela.r_offset; P = addr.ToLinear(); relR = program.CreateImageReader(addr); relW = program.CreateImageWriter(addr); } else { addr = null; P = 0; relR = null; relW = null; } ulong PP = P; var rt = (x86_64Rt)(rela.r_info & 0xFF); switch (rt) { case x86_64Rt.R_X86_64_NONE: // just ignore (common) break; case x86_64Rt.R_X86_64_COPY: break; default: Debug.Print("x86_64 ELF relocation type {0} not implemented yet.", rt); break; //throw new NotImplementedException(string.Format( // "x86_64 ELF relocation type {0} not implemented yet.", // rt)); } if (relR != null) { var w = relR.ReadUInt64(); w += ((ulong)(S + (ulong)A + P) >> sh) & mask; relW.WriteUInt64(w); } }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { var rt = (SuperHrt)(byte)rela.Info; if (rt == SuperHrt.R_SH_GLOB_DAT || rt == SuperHrt.R_SH_JMP_SLOT) { var addrPfn = Address.Ptr32((uint)rela.Offset); Debug.Print("Import reference {0} - {1}", addrPfn, symbol.Name); var st = ElfLoader.GetSymbolType(symbol); if (st.HasValue) { program.ImportReferences[addrPfn] = new NamedImportReference(addrPfn, null, symbol.Name, st.Value); } return(symbol); } return(symbol); }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rel) { if (symbol == null) { return(symbol); } if (loader.Sections.Count <= symbol.SectionIndex) { return(symbol); } if (symbol.SectionIndex == 0) { return(symbol); } var symSection = loader.Sections[(int)symbol.SectionIndex]; Address addr; uint P; if (referringSection?.Address != null) { addr = referringSection.Address + rel.Offset; P = (uint)addr.ToLinear(); } else { addr = Address.Ptr64(rel.Offset); P = 0; } //var S = symbol.Value; //uint PP = P; //var relR = program.CreateImageReader(program.Architecture, addr); //var relW = program.CreateImageWriter(program.Architecture, addr); //int sh = 0; //uint mask = 0; //uint A = 0; //var rt = (MIPSrt) (rel.Info & 0xFF); //switch (rt) //{ //} return(symbol); }
static void PrintSectionFiles(ElfSection section) { var items = section.Items; var fileGroups = items.GroupBy(v => Path.GetFileName(v.FileStr)); foreach (var f in fileGroups) { Console.WriteLine("\tFile: {0}", f.Key); ulong totalSize = 0; foreach (var dwarfCompilationUnitItem in f) { totalSize += dwarfCompilationUnitItem.Size; Console.WriteLine("\t\tItem: {0}\ts:{1}", dwarfCompilationUnitItem.Name, dwarfCompilationUnitItem.Size); } Console.WriteLine("\tFile size: {0}", totalSize); } }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { var addr = Address.Ptr64(rela.Offset); var rt = (RtAarch64)(rela.Info & 0xFFFF); ulong A = (ulong)rela.Addend; ulong S = symbol.Value; switch (rt) { case RtAarch64.R_AARCH64_RELATIVE: A = S = 0; break; case RtAarch64.R_AARCH64_JUMP_SLOT: // A + S case RtAarch64.R_AARCH64_GLOB_DAT: // A + S break; default: var listener = this.loader.Services.RequireService <DecompilerEventListener>(); var loc = listener.CreateAddressNavigator(program, addr); listener.Warn(loc, $"Unimplemented PowerPC64 relocation type {rt}."); return(addr, null); } var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var w = relR.ReadUInt64(); w += (S + A); relW.WriteUInt64(w); return(addr, null); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { throw new NotImplementedException(); }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { /* * S (when used on its own) is the address of the symbol * A is the addend for the relocation. * P is the address of the place being relocated (derived from r_offset). * Pa is the adjusted address of the place being reloc * ated, defined as (P & 0xFFFFFFFC). * T is 1 if the target symbol S has type STT_FUNC and the symbol addresses a Thumb instruction; it is 0 * otherwise. * B(S) is the addressing origin of the output segment defining the symbol S. The origin is not required to be * the base address of the segment. This value must always be word-aligned. * * GOT_ORG is the addressing origin of the Global Offset Table (the indirection table for imported data * addresses). This value must always be word-aligned. See §4.6.1.8, Proxy generating relocations. * GOT(S) is the address of the GOT entry for the symbol S. * Table * 0 R_ARM_NONE Static Miscellaneous * 1 R_ARM_PC24 Deprecated ARM ((S + A) | T) - P * 2 R_ARM_ABS32 Static Data ((S + A) | T) * 3 R_ARM_REL32 Static Data ((S + A) | T) – P * 4 R_ARM_LDR_PC_G0 Static ARM S + A – P * 5 R_ARM_ABS16 Static Data S + A * 6 R_ARM_ABS12 Static ARM S + A * 7 R_ARM_THM_ABS5 Static Thumb16 S + A * 8 R_ARM_ABS8 Static Data S + A * 9 R_ARM_SBREL32 Static Data ((S + A) | T) – B(S) * 20 R_ARM_COPY S * 21 R_ARM_GLOB_DAT Dynamic Data (S + A) | T * 22 R_ARM_JUMP_SLOT Dynamic Data (S + A) | T * 23 R_ARM_RELATIVE Dynamic Data B(S) + A [Note: see Table 4-18] */ var A = rela.Addend; uint S = (uint)symbol.Value; uint mask = ~0u; int sh = 0; var addr = referringSection != null ? referringSection.Address + rela.Offset : loader.CreateAddress(rela.Offset); var rt = (Arm32Rt)(rela.Info & 0xFF); switch (rt) { case Arm32Rt.R_ARM_NONE: return(symbol); case Arm32Rt.R_ARM_COPY: A = S = 0; break; case Arm32Rt.R_ARM_ABS32: case Arm32Rt.R_ARM_GLOB_DAT: case Arm32Rt.R_ARM_JUMP_SLOT: // Add sym + rel.a break; case Arm32Rt.R_ARM_RELATIVE: // From the docs: // // (S ≠ 0) B(S) resolves to the difference between the address // at which the segment defining the symbol S was loaded and // the address at which it was linked. // (S = 0) B(S) resolves to the difference between the address // at which the segment being relocated was loaded and the // address at which it was linked. // // Reko always loads objects at their specified physical address, // so this relocation is a no-op; A = S = 0; break; case Arm32Rt.R_ARM_TLS_TPOFF32: // Allocates a 32 bit TLS slot //$REVIEW: the documentation is unreadable, but this is a // guess. uint tlsSlotOffset = AllocateTlsSlot(); A += tlsSlotOffset; break; case Arm32Rt.R_ARM_TLS_DTPMOD32: //$REVIEW: this seems to refer to the modules // used when creating the binary. My guess is // that it wont be necessary for a fruitful // decompilation -jkl A = S = 0; break; case Arm32Rt.R_ARM_TLS_DTPOFF32: //$NYI break; case Arm32Rt.R_ARM_CALL: case Arm32Rt.R_ARM_PC24: case Arm32Rt.R_ARM_JUMP24: { if ((symbol.Value & 0b11) != 0) { var eventListener = loader.Services.RequireService <DecompilerEventListener>(); var loc = eventListener.CreateAddressNavigator(program, addr); eventListener.Warn(loc, "Section {0}: unsupported interworking call (ARM -> Thumb)", referringSection?.Name ?? "<null>"); return(symbol); } var relInstr = program.CreateImageReader(program.Architecture, addr); var uInstr = relInstr.ReadUInt32(); var offset = uInstr; offset = (offset & 0x00ffffff) << 2; if ((offset & 0x02000000) != 0) { offset -= 0x04000000; } offset += (uint)symbol.Value - addr.ToUInt32() + program.SegmentMap.BaseAddress.ToUInt32(); #if NOT_YET /* * Route through a PLT entry if 'offset' exceeds the * supported range. Note that 'offset + loc + 8' * contains the absolute jump target, i.e., * @sym + addend, corrected for the +8 PC bias. */ if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS) && (offset <= (s32)0xfe000000 || offset >= (s32)0x02000000)) { offset = get_module_plt(module, loc, offset + loc + 8) - loc - 8; } #endif if ((int)offset <= -0x02000000 || (int)offset >= 0x02000000) { var eventListener = loader.Services.RequireService <DecompilerEventListener>(); var loc = eventListener.CreateAddressNavigator(program, addr); eventListener.Warn(loc, "section {0} relocation at {1} out of range", referringSection?.Name ?? "<null>", addr); return(symbol); } offset >>= 2; offset &= 0x00ffffff; uInstr &= 0xFF000000; uInstr |= offset; var relWriter = program.CreateImageWriter(program.Architecture, addr); relWriter.WriteUInt32(uInstr); return(symbol); } case Arm32Rt.R_ARM_MOVW_ABS_NC: case Arm32Rt.R_ARM_MOVT_ABS: { //var instr = program.CreateDisassembler(program.Architecture, addr).First(); var relInstr = program.CreateImageReader(program.Architecture, addr); var uInstr = relInstr.ReadUInt32(); var offset = uInstr; offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff); offset = (offset ^ 0x8000) - 0x8000; offset += (uint)symbol.Value; if (rt == Arm32Rt.R_ARM_MOVT_ABS) { offset >>= 16; } var tmp = uInstr & 0xfff0f000; tmp |= ((offset & 0xf000) << 4) | (offset & 0x0fff); var relWriter = program.CreateImageWriter(program.Architecture, addr); relWriter.WriteUInt32(tmp); return(symbol); } default: throw new NotImplementedException($"AArch32 relocation type {rt} is not implemented yet."); } var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var w = relR.ReadLeUInt32(); w += ((uint)(S + A) >> sh) & mask; relW.WriteLeUInt32(w); return(symbol); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { //$TODO: need a ELF PIC MIPS image to do this. return; }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { //$TODO: implement me :) throw new NotImplementedException(); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { throw new NotImplementedException(); }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { var rt = (RiscVRt)(rela.Info & 0xFF); ulong S = symbol.Value; ulong A = 0; ulong B = 0; var addr = referringSection != null ? referringSection.Address + rela.Offset : loader.CreateAddress(rela.Offset); var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); switch (rt) { case RiscVRt.R_RISCV_COPY: return(addr, null); case RiscVRt.R_RISCV_RELATIVE: // B + A A = (ulong)rela.Addend; B = program.SegmentMap.BaseAddress.ToLinear(); S = 0; break; case RiscVRt.R_RISCV_64: // S + A A = (ulong)rela.Addend; B = 0; break; case RiscVRt.R_RISCV_JUMP_SLOT: // S S = symbol.Value; if (S == 0) { var gotEntry = relR.PeekLeUInt64(0); var newSym = CreatePltStubSymbolFromRelocation(symbol, gotEntry, 0x0); return(addr, newSym); } break; default: Debug.Print("ELF RiscV: unhandled 32-bit relocation {0}: {1}", rt, rela); break; } var w = relR.ReadLeUInt64(); w += ((uint)(B + S + A)); relW.WriteLeUInt64(w); return(addr, null); }
protected ElfSymbol FindSymbol( ElfSection section, uint symbolIndex ) { return _symbols[ ( int )symbolIndex ]; //return _symbolLookup[ section ][ ( int )symbolIndex ]; }
protected void ApplyRelocations( BinaryReader reader, IMemory memory, ElfSection section, uint baseAddress ) { List<HiReloc> hiRelocs = new List<HiReloc>(); ElfSection linked = section.Reference; if( ( linked.Flags & ElfSectionFlags.Alloc ) != ElfSectionFlags.Alloc ) return; Debug.WriteLine( string.Format( "Relocating section {0} using {1}, {2} relocations total", linked.Name, section.Name, section.Length / 8 ) ); ElfSection textSection = _sectionLookup[ ".text" ]; ElfSection dataSection = _sectionLookup[ ".data" ]; Debug.Assert( textSection != null ); Debug.Assert( dataSection != null ); for( int n = 0; n < section.Length / 8; n++ ) { reader.BaseStream.Seek( section.ElfOffset + ( 8 * n ), SeekOrigin.Begin ); NativeElfRel rel = new NativeElfRel( reader ); ElfRelocation relocation = new ElfRelocation(); //relocation.Section = section; relocation.Offset = rel.Offset; relocation.BaseAddress = ( rel.Info >> 16 ) & 0xFF; relocation.Symbol = ( rel.Info >> 8 ) & 0xFF; relocation.RelocationType = ( ElfRelocationType )( byte )( rel.Info & 0xFF ); uint pointer = relocation.Offset; //ElfSection offsetBase = null; //ElfSection addressBase = null; if( ( relocation.Symbol & ( uint )RelocationOffset.Data ) == ( uint )RelocationOffset.Data ) { //offsetBase = dataSection; pointer += dataSection.Address; } //else if( relocation.BaseAddress == 0x1 ) //{ // offsetBase = textSection; // pointer += textSection.Address; //} else { //offsetBase = textSection; pointer += baseAddress; } //ElfSection offsetBase = _sections[ ( int )relocation.Symbol ]; //ElfSection addressBase = _sections[ ( int )relocation.BaseAddress ]; // Happens sometime if( _symbols.Count == 0 ) { Debug.WriteLine( "Unable to relocate symbol; symbol table is empty - possibly no .symtab section?" ); return; } ElfSymbol symbol = _symbols[ ( int )relocation.Symbol ]; uint symbolValue = symbol.Value; // !!! This could be bogus if( ( ( rel.Info >> 8 ) & RelocationRelativeData ) == RelocationRelativeData ) symbolValue += dataSection.Address; else symbolValue += baseAddress; //if( addressBase.Address == 0 ) // symbolValue += baseAddress; //else // symbolValue += addressBase.Address; uint value = ( uint )memory.ReadWord( ( int )pointer ); //Debug.WriteLine( string.Format( " Relocation pointer 0x{0:X8} (elf {1:X8}), value {2:X8}, type {3}, existing memory value {4:X8}", // pointer, relocation.Offset, symbolValue, relocation.RelocationType, value ) ); bool writeMemory = false; switch( relocation.RelocationType ) { case ElfRelocationType.None: break; case ElfRelocationType.Mips32: value += symbolValue; writeMemory = true; break; case ElfRelocationType.Mips26: Debug.Assert( symbolValue % 4 == 0 ); value = ( uint )( ( value & ~0x03FFFFFF ) | ( ( value + ( symbolValue >> 2 ) ) & 0x03FFFFFF ) ); writeMemory = true; break; case ElfRelocationType.Hi16: { HiReloc hiReloc = new HiReloc(); hiReloc.Address = pointer; hiReloc.Value = symbolValue; hiRelocs.Add( hiReloc ); } break; case ElfRelocationType.Lo16: { uint vallo = ( ( value & 0x0000FFFF ) ^ 0x00008000 ) - 0x00008000; while( hiRelocs.Count > 0 ) { HiReloc hiReloc = hiRelocs[ hiRelocs.Count - 1 ]; hiRelocs.RemoveAt( hiRelocs.Count - 1 ); Debug.Assert( hiReloc.Value == symbolValue ); uint value2 = ( uint )memory.ReadWord( ( int )hiReloc.Address ); uint temp = ( ( value2 & 0x0000FFFF ) << 16 ) + vallo; temp += symbolValue; temp = ( ( temp >> 16 ) + ( ( ( temp & 0x00008000 ) != 0 ) ? ( uint )1 : ( uint )0 ) ) & 0x0000FFFF; value2 = ( uint )( ( value2 & ~0x0000FFFF ) | temp ); //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8} (from previous HI16)", hiReloc.Address, value2 ) ); memory.WriteWord( ( int )hiReloc.Address, 4, ( int )value2 ); } value = ( uint )( ( value & ~0x0000FFFF ) | ( ( symbolValue + vallo ) & 0x0000FFFF ) ); } writeMemory = true; break; default: // Unsupported type Debugger.Break(); break; } if( writeMemory == true ) { //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8}", pointer, value ) ); memory.WriteWord( ( int )pointer, 4, ( int )value ); } } }
public abstract void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela);
protected ElfSymbol FindSymbol(ElfSection section, uint symbolIndex) { return(_symbols[( int )symbolIndex]); //return _symbolLookup[ section ][ ( int )symbolIndex ]; }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { /* * S (when used on its own) is the address of the symbol * A is the addend for the relocation. * P is the address of the place being relocated (derived from r_offset). * Pa is the adjusted address of the place being reloc * ated, defined as (P & 0xFFFFFFFC). * T is 1 if the target symbol S has type STT_FUNC and the symbol addresses a Thumb instruction; it is 0 * otherwise. * B(S) is the addressing origin of the output segment defining the symbol S. The origin is not required to be * the base address of the segment. This value must always be word-aligned. * * GOT_ORG is the addressing origin of the Global Offset Table (the indirection table for imported data * addresses). This value must always be word-aligned. See §4.6.1.8, Proxy generating relocations. * GOT(S) is the address of the GOT entry for the symbol S. * Table * 0 R_ARM_NONE Static Miscellaneous * 1 R_ARM_PC24 Deprecated ARM ((S + A) | T) - P * 2 R_ARM_ABS32 Static Data ((S + A) | T) * 3 R_ARM_REL32 Static Data ((S + A) | T) – P * 4 R_ARM_LDR_PC_G0 Static ARM S + A – P * 5 R_ARM_ABS16 Static Data S + A * 6 R_ARM_ABS12 Static ARM S + A * 7 R_ARM_THM_ABS5 Static Thumb16 S + A * 8 R_ARM_ABS8 Static Data S + A * 9 R_ARM_SBREL32 Static Data ((S + A) | T) – B(S) * 20 R_ARM_COPY S * 21 R_ARM_GLOB_DAT Dynamic Data (S + A) | T * 22 R_ARM_JUMP_SLOT Dynamic Data (S + A) | T * 23 R_ARM_RELATIVE Dynamic Data B(S) + A [Note: see Table 4-18] */ var A = rela.Addend; uint S = (uint)symbol.Value; uint mask = ~0u; int sh = 0; var rt = (Arm32Rt)(rela.Info & 0xFF); switch (rt) { case Arm32Rt.R_ARM_NONE: return(symbol); case Arm32Rt.R_ARM_COPY: A = S = 0; break; case Arm32Rt.R_ARM_ABS32: break; case Arm32Rt.R_ARM_GLOB_DAT: case Arm32Rt.R_ARM_JUMP_SLOT: A = S = 0; break; case Arm32Rt.R_ARM_RELATIVE: // From the docs: // // (S ≠ 0) B(S) resolves to the difference between the address // at which the segment defining the symbol S was loaded and // the address at which it was linked. // (S = 0) B(S) resolves to the difference between the address // at which the segment being relocated was loaded and the // address at which it was linked. // // Reko always loads objects at their specified physical address, // so this relocation is a no-op; A = S = 0; break; default: throw new NotImplementedException($"AArch32 relocation type {rt} is not implemented yet."); } var addr = referringSection != null ? referringSection.Address + rela.Offset : loader.CreateAddress(rela.Offset); var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var w = relR.ReadLeUInt32(); w += ((uint)(S + A) >> sh) & mask; relW.WriteLeUInt32(w); return(symbol); }
public abstract void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela);
protected void ApplyRelocations(BinaryReader reader, IMemory memory, ElfSection section, uint baseAddress) { List <HiReloc> hiRelocs = new List <HiReloc>(); ElfSection linked = section.Reference; if ((linked.Flags & ElfSectionFlags.Alloc) != ElfSectionFlags.Alloc) { return; } Debug.WriteLine(string.Format("Relocating section {0} using {1}, {2} relocations total", linked.Name, section.Name, section.Length / 8)); ElfSection textSection = _sectionLookup[".text"]; ElfSection dataSection = _sectionLookup[".data"]; Debug.Assert(textSection != null); Debug.Assert(dataSection != null); for (int n = 0; n < section.Length / 8; n++) { reader.BaseStream.Seek(section.ElfOffset + (8 * n), SeekOrigin.Begin); NativeElfRel rel = new NativeElfRel(reader); ElfRelocation relocation = new ElfRelocation(); //relocation.Section = section; relocation.Offset = rel.Offset; relocation.BaseAddress = (rel.Info >> 16) & 0xFF; relocation.Symbol = (rel.Info >> 8) & 0xFF; relocation.RelocationType = ( ElfRelocationType )( byte )(rel.Info & 0xFF); uint pointer = relocation.Offset; //ElfSection offsetBase = null; //ElfSection addressBase = null; if ((relocation.Symbol & ( uint )RelocationOffset.Data) == ( uint )RelocationOffset.Data) { //offsetBase = dataSection; pointer += dataSection.Address; } //else if( relocation.BaseAddress == 0x1 ) //{ // offsetBase = textSection; // pointer += textSection.Address; //} else { //offsetBase = textSection; pointer += baseAddress; } //ElfSection offsetBase = _sections[ ( int )relocation.Symbol ]; //ElfSection addressBase = _sections[ ( int )relocation.BaseAddress ]; // Happens sometime if (_symbols.Count == 0) { Debug.WriteLine("Unable to relocate symbol; symbol table is empty - possibly no .symtab section?"); return; } ElfSymbol symbol = _symbols[( int )relocation.Symbol]; uint symbolValue = symbol.Value; // !!! This could be bogus if (((rel.Info >> 8) & RelocationRelativeData) == RelocationRelativeData) { symbolValue += dataSection.Address; } else { symbolValue += baseAddress; } //if( addressBase.Address == 0 ) // symbolValue += baseAddress; //else // symbolValue += addressBase.Address; uint value = ( uint )memory.ReadWord(( int )pointer); //Debug.WriteLine( string.Format( " Relocation pointer 0x{0:X8} (elf {1:X8}), value {2:X8}, type {3}, existing memory value {4:X8}", // pointer, relocation.Offset, symbolValue, relocation.RelocationType, value ) ); bool writeMemory = false; switch (relocation.RelocationType) { case ElfRelocationType.None: break; case ElfRelocationType.Mips32: value += symbolValue; writeMemory = true; break; case ElfRelocationType.Mips26: Debug.Assert(symbolValue % 4 == 0); value = ( uint )((value & ~0x03FFFFFF) | ((value + (symbolValue >> 2)) & 0x03FFFFFF)); writeMemory = true; break; case ElfRelocationType.Hi16: { HiReloc hiReloc = new HiReloc(); hiReloc.Address = pointer; hiReloc.Value = symbolValue; hiRelocs.Add(hiReloc); } break; case ElfRelocationType.Lo16: { uint vallo = ((value & 0x0000FFFF) ^ 0x00008000) - 0x00008000; while (hiRelocs.Count > 0) { HiReloc hiReloc = hiRelocs[hiRelocs.Count - 1]; hiRelocs.RemoveAt(hiRelocs.Count - 1); Debug.Assert(hiReloc.Value == symbolValue); uint value2 = ( uint )memory.ReadWord(( int )hiReloc.Address); uint temp = ((value2 & 0x0000FFFF) << 16) + vallo; temp += symbolValue; temp = ((temp >> 16) + (((temp & 0x00008000) != 0) ? ( uint )1 : ( uint )0)) & 0x0000FFFF; value2 = ( uint )((value2 & ~0x0000FFFF) | temp); //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8} (from previous HI16)", hiReloc.Address, value2 ) ); memory.WriteWord(( int )hiReloc.Address, 4, ( int )value2); } value = ( uint )((value & ~0x0000FFFF) | ((symbolValue + vallo) & 0x0000FFFF)); } writeMemory = true; break; default: // Unsupported type Debugger.Break(); break; } if (writeMemory == true) { //Debug.WriteLine( string.Format( " Updating memory at 0x{0:X8} to {1:X8}", pointer, value ) ); memory.WriteWord(( int )pointer, 4, ( int )value); } } }
public bool Load(Stream stream, IEmulationInstance emulator, uint baseAddress) { // Relocate only if we need to if (_needsRelocation == false) { baseAddress = 0; } _entryAddress += baseAddress; _initAddress += baseAddress; IMemory memory = emulator.Cpu.Memory; foreach (ElfSection section in _allocSections) { // Sanity check for broken ELFs if ((baseAddress != 0) && (baseAddress == section.Address)) { // Fuckers lied - no relocation needed! _needsRelocation = false; baseAddress = 0; } uint address = baseAddress + section.Address; section.Address = address; if (section.SectionType == ElfSectionType.NoBits) { // Write zeros? } else if (section.SectionType == ElfSectionType.ProgramBits) { stream.Seek(section.ElfOffset, SeekOrigin.Begin); byte[] bytes = new byte[section.Length]; stream.Read(bytes, 0, ( int )section.Length); memory.WriteBytes(( int )address, bytes); _upperAddress = Math.Max(_upperAddress, address + ( uint )bytes.Length); } } BinaryReader reader = new BinaryReader(stream); ElfSection sceModuleInfo = _sectionLookup[".rodata.sceModuleInfo"]; reader.BaseStream.Seek(sceModuleInfo.ElfOffset, SeekOrigin.Begin); ModuleInfo moduleInfo = new ModuleInfo(reader); _globalPointer = baseAddress + moduleInfo.Gp; // Not sure if this is needed - the header seems to give an ok address //if( _programType == ElfType.Prx ) //{ // ElfSection sceResident = _sectionLookup[ ".rodata.sceResident" ]; // reader.BaseStream.Seek( sceResident.ElfOffset, SeekOrigin.Begin ); // // 2 magic words // reader.BaseStream.Seek( 8, SeekOrigin.Current ); // _entryAddress = reader.ReadUInt32(); //} if (_needsRelocation == true) { //foreach( ElfRelocation relocation in _relocations ) //{ // this.FixRelocation( reader, memory, relocation, baseAddress ); //} foreach (ElfSection section in _relocSections) { this.ApplyRelocations(reader, memory, section, baseAddress); } } //result.Stubs = this.FixupStubs( reader, emulator.Cpu, memory, emulator.Bios, baseAddress ); return(true); }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= sym.SectionIndex) { return(null, null); } uint S = (uint)sym.Value; int A = 0; int sh = 0; uint mask = ~0u; var addr = referringSection != null ? referringSection.Address + rela.Offset : loader.CreateAddress(rela.Offset); uint P = (uint)addr.ToLinear(); uint PP = P; uint B = 0; var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var rt = (i386Rt)(rela.Info & 0xFF); switch (rt) { case i386Rt.R_386_NONE: // just ignore (common) break; case i386Rt.R_386_COPY: break; case i386Rt.R_386_RELATIVE: // B + A A = (int)rela.Addend; B = program.SegmentMap.BaseAddress.ToUInt32(); break; case i386Rt.R_386_JMP_SLOT: if (sym.Value == 0) { // Broken GCC compilers generate relocations referring to symbols // whose value is 0 instead of the expected address of the PLT stub. var gotEntry = relR.PeekLeUInt32(0); var symNew = CreatePltStubSymbolFromRelocation(sym, gotEntry, 6); return(addr, symNew); } break; case i386Rt.R_386_32: // S + A // Read the symTabIndex'th symbol. A = (int)rela.Addend; P = 0; break; case i386Rt.R_386_PC32: // S + A - P if (sym.Value == 0) { // This means that the symbol doesn't exist in this module, and is not accessed // through the PLT, i.e. it will be statically linked, e.g. strcmp. We have the // name of the symbol right here in the symbol table entry, but the only way // to communicate with the loader is through the target address of the call. // So we use some very improbable addresses (e.g. -1, -2, etc) and give them entries // in the symbol table //S = nextFakeLibAddr--; // Allocate a new fake address //loader.AddSymbol(S, sym.Name); //} } A = (int)rela.Addend; P = ~P + 1; break; case i386Rt.R_386_GLOB_DAT: // This relocation type is used to set a global offset table entry to the address of the // specified symbol. The special relocation type allows one to determine the // correspondence between symbols and global offset table entries. P = 0; break; default: throw new NotImplementedException(string.Format( "i386 ELF relocation type {0} not implemented yet.", rt)); } var w = relR.ReadLeUInt32(); w += ((uint)(B + S + A + P) >> sh) & mask; relW.WriteLeUInt32(w); return(addr, sym); }
protected bool LoadElf( BinaryReader reader ) { NativeElfEhdr ehdr = new NativeElfEhdr( reader ); if( ehdr.Magic != NativeElfEhdr.ElfMagic ) { Debug.WriteLine( "ElfFile: elf magic number invalid" ); return false; } if( ehdr.Machine != ElfMachineMips ) { Debug.WriteLine( "ElfFile: machine version invalid" ); return false; } _programType = ( ElfType )ehdr.Type; _entryAddress = ehdr.Entry; // Easy test for relocation: if( _entryAddress < 0x08000000 ) _needsRelocation = true; reader.BaseStream.Seek( ehdr.Phoff, SeekOrigin.Begin ); List<NativeElfPhdr> phdrs = new List<NativeElfPhdr>(); for( int n = 0; n < ehdr.Phnum; n++ ) { NativeElfPhdr phdr = new NativeElfPhdr( reader ); phdrs.Add( phdr ); } for( int n = 0; n < ehdr.Shnum; n++ ) { reader.BaseStream.Seek( ehdr.Shoff + ( n * ehdr.Shentsize ), SeekOrigin.Begin ); NativeElfShdr shdr = new NativeElfShdr( reader ); ElfSection section = new ElfSection(); section.NameIndex = shdr.Name; section.ElfOffset = shdr.Offset; section.Flags = ( ElfSectionFlags )shdr.Flags; section.LinkInfo = shdr.Info; section.SectionType = ( ElfSectionType )shdr.Type; section.Address = shdr.Address; section.AddressAlignment = shdr.AddressAlignment; section.Length = shdr.Size; _sections.Add( section ); if( ( section.Flags & ElfSectionFlags.Alloc ) == ElfSectionFlags.Alloc ) _allocSections.Add( section ); if( ( ( _programType == ElfType.Executable ) && ( section.SectionType == ElfSectionType.Relocation ) ) || ( ( _programType == ElfType.Prx ) && ( section.SectionType == ElfSectionType.PrxReloc ) ) ) _relocSections.Add( section ); } uint nameBase = _sections[ ehdr.Shstrndx ].ElfOffset; foreach( ElfSection section in _sections ) { reader.BaseStream.Seek( nameBase + section.NameIndex, SeekOrigin.Begin ); section.Name = ReadString( reader ); if( ( ( section.SectionType == ElfSectionType.Relocation ) || ( section.SectionType == ElfSectionType.PrxReloc ) ) && ( ( _sections[ ( int )section.LinkInfo ].Flags & ElfSectionFlags.Alloc ) != 0 ) ) { section.Reference = _sections[ ( int )section.LinkInfo ]; //_needsRelocation = true; } if( ( section.Name != null ) && ( section.Name.Length > 0 ) ) _sectionLookup.Add( section.Name, section ); } // Not sure if this is important if( _sectionLookup.ContainsKey( ".init" ) == true ) _initAddress = _sectionLookup[ ".init" ].Address; else _initAddress = 0x0; if( _sectionLookup.ContainsKey( ".symtab" ) == true ) { ElfSection symtab = _sectionLookup[ ".symtab" ]; ElfSection strtab = _sectionLookup[ ".strtab" ]; for( int n = 0; n < symtab.Length / 16; n++ ) { reader.BaseStream.Seek( symtab.ElfOffset + ( 16 * n ), SeekOrigin.Begin ); NativeElfSym sym = new NativeElfSym( reader ); ElfSymbol symbol = new ElfSymbol(); symbol.Index = sym.SectionIndex; // May be ElfAbsoluteSymbol symbol.Size = sym.Size; symbol.Value = sym.Value; symbol.Binding = ( ElfSymbolBinding )( sym.Info >> 4 ); symbol.SymbolType = ( ElfSymbolType )( sym.Info & 0xF ); reader.BaseStream.Seek( strtab.ElfOffset + sym.Name, SeekOrigin.Begin ); symbol.Name = ReadString( reader ); _symbols.Add( symbol ); if( symbol.Index != ElfAbsoluteSymbol ) { ElfSection symbolParent = _sections[ ( int )symbol.Index ]; List<ElfSymbol> syms; if( _symbolLookup.ContainsKey( symbolParent ) == true ) syms = _symbolLookup[ symbolParent ]; else { syms = new List<ElfSymbol>(); _symbolLookup.Add( symbolParent, syms ); } syms.Add( symbol ); } } } //foreach( ElfSection section in _sections ) //{ // Debugger.Break(); // if( ( _programType == ElfType.Executable ) && // ( section.SectionType != ElfSectionType.Relocation ) ) // continue; // if( ( _programType == ElfType.Prx ) && // ( section.SectionType != ElfSectionType.PrxReloc ) ) // continue; // for( int n = 0; n < section.Length / 8; n++ ) // { // reader.BaseStream.Seek( section.ElfOffset + ( 8 * n ), SeekOrigin.Begin ); // NativeElfRel rel = new NativeElfRel( reader ); // ElfRelocation relocation = new ElfRelocation(); // relocation.Section = section; // relocation.Offset = rel.Offset; // relocation.BaseAddress = ( rel.Info >> 16 ) & 0xFF; // relocation.Symbol = rel.Info >> 8; // relocation.RelocationType = ( ElfRelocationType )( byte )( rel.Info & 0xFF ); // _relocations.Add( relocation ); // } //} return true; }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { var rt = (XtensaRt)(rela.Info & 0xFF); ElfImageLoader.trace.Inform("XTensa relocation {0}: {1}", rt, rela); switch (rt) { case XtensaRt.R_XTENSA_32: //aspace.make_data(raddr, wordsz); //if (value != null) { // data = aspace.get_data(raddr, wordsz); // if (is_exe) { // if (data != value) { // log.Warn("Computed reloc value and value present in fully linked file differ: 0x%x vs 0x%x", value, data) // } // } // else { // data += value; // aspace.set_data(raddr, data, wordsz); // aspace.make_arg_offset(raddr, 0, data); // } //} else { // // Undefined symbol // // TODO: This is more or less hacky way to do this. It would be // // better to explicitly assign a symbolic alias to a value at // // particular address, but so far we assume call below to do // // that. // aspace.make_arg_offset(raddr, 0, symname); //} break; case XtensaRt.R_XTENSA_SLOT0_OP: //if (is_exe) // break; //var opcode = aspace.get_byte(raddr); //if ((opcode & 0xf) == 0x5) { // // call // if (value != null) { // p = raddr // value -= ((p & ~0x3) + 4); // Debug.Assert((value & 0x3) == 0); // value = value >> 2; // aspace.set_byte(p, (opcode & ~0xc0) | ((value << 6) & 0xc0)); // aspace.set_byte(p + 1, value >> 2); // aspace.set_byte(p + 2, value >> 10); // } //} //if (opcode & 0xf == 0x1) { // // l32r //} break; default: break; } return(null, null); }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { switch ((Mips64Rt)rela.Info) { case Mips64Rt.R_MIPS_NONE: return(null, null); default: ElfImageLoader.trace.Warn("Unimplemented MIPS64 relocation type: {0}", RelocationTypeToString((uint)rela.Info)); break; } return(null, null); }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= sym.SectionIndex) { return(sym); } if (sym.SectionIndex == 0) { return(sym); } var symSection = loader.Sections[(int)sym.SectionIndex]; uint S = (uint)sym.Value; uint A = (uint)rela.Addend; uint P = (uint)rela.Offset; var addr = Address.Ptr32(P); uint PP = P; var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var rt = (PpcRt)(rela.Info & 0xFF); switch (rt) { case PpcRt.R_PPC_GLOB_DAT: case PpcRt.R_PPC_COPY: case PpcRt.R_PPC_JMP_SLOT: break; case PpcRt.R_PPC_ADDR32: relW.WriteUInt32(S + A); break; case PpcRt.R_PPC_REL24: uint wInstr = relR.ReadUInt32(); // 24 bit relocation where bits 3-29 are used for relocations uint value = (S + A - P); wInstr = (wInstr & 0xFC000003) | (value & 0x03FFFFFC); relW.WriteUInt32(wInstr); break; case PpcRt.R_PPC_ADDR16_HI: case PpcRt.R_PPC_ADDR16_HA: // Wait for the following R_PPC_ADDR16_LO relocation. prevPpcHi16 = rela; prevRelR = relR; prevRelW = relW; break; case PpcRt.R_PPC_ADDR16_LO: if (prevPpcHi16 == null) { return(sym); } uint valueHi = prevRelR.ReadUInt16(); uint valueLo = relR.ReadUInt16(); if ((PpcRt)(prevPpcHi16.Info & 0xFF) == PpcRt.R_PPC_ADDR16_HA) { valueHi += (valueHi & 0x8000u) != 0 ? 1u : 0u; } value = (valueHi << 16) | valueLo; value += S; valueHi = (value >> 16) & 0xFFFF; valueLo = value & 0xFFFF; prevRelW.WriteBeUInt16((ushort)valueHi); relW.WriteBeUInt16((ushort)valueLo); break; default: if (!missedRelocations.TryGetValue(rt, out var count)) { count = 0; } missedRelocations[rt] = count + 1; break; } return(sym); }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= sym.SectionIndex) { return(null, null); } var rt = (SparcRt)(rela.Info & 0xFF); var addr = referringSection != null ? referringSection.Address + rela.Offset : loader.CreateAddress(rela.Offset); if (sym.SectionIndex == 0) { if (rt == SparcRt.R_SPARC_GLOB_DAT || rt == SparcRt.R_SPARC_JMP_SLOT) { var addrPfn = Address.Ptr32((uint)rela.Offset); ElfImageLoader.trace.Verbose("Import reference {0} - {1}", addrPfn, sym.Name); var st = ElfLoader.GetSymbolType(sym); if (st.HasValue) { importReferences[addrPfn] = new NamedImportReference(addrPfn, null, sym.Name, st.Value); } return(addrPfn, null); } } var symSection = loader.Sections[(int)sym.SectionIndex]; ulong S = 0; int A = 0; int sh = 0; uint mask = ~0u; if (referringSection != null) { addr = referringSection.Address + rela.Offset; } else { addr = Address.Ptr64(rela.Offset); } ulong P = addr.ToLinear(); ulong PP = P; ulong B = 0; ElfImageLoader.trace.Verbose(" off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2} {5}", rela.Offset, (SparcRt)(rela.Info & 0xFF), sym.Name, rela.Addend, (int)(rela.Info >> 8), "section?"); switch (rt) { case 0: return(null, null); case SparcRt.R_SPARC_HI22: A = (int)rela.Addend; sh = 10; P = 0; mask = 0x3FFFFF; return(Relocate32(program, sym, addr, S, A, sh, mask, P, B)); case SparcRt.R_SPARC_LM22: A = (int)rela.Addend; S = sym.Value; sh = 10; P = 0; mask = 0x3FFFFF; return(Relocate32(program, sym, addr, S, A, sh, mask, P, B)); case SparcRt.R_SPARC_LO10: A = (int)rela.Addend; S = sym.Value; mask = 0x3FF; P = 0; return(Relocate32(program, sym, addr, S, A, sh, mask, P, B)); case SparcRt.R_SPARC_32: A = (int)rela.Addend; S = sym.Value; mask = 0xFFFFFFFF; P = 0; return(Relocate32(program, sym, addr, S, A, sh, mask, P, B)); case SparcRt.R_SPARC_WDISP30: A = (int)rela.Addend; P = ~P + 1; sh = 2; return(Relocate32(program, sym, addr, S, A, sh, mask, P, B)); case SparcRt.R_SPARC_RELATIVE: A = (int)rela.Addend; B = program.SegmentMap.BaseAddress.ToLinear(); P = 0; return(Relocate64(program, sym, addr, S, A, sh, mask, P, B)); case SparcRt.R_SPARC_COPY: ElfImageLoader.trace.Warn("Relocation type {0} not handled yet.", rt); return(addr, null); default: ElfImageLoader.trace.Error( "SPARC ELF relocation type {0} not implemented yet.", rt); return(addr, null); } }
public override void RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, Elf32_Rela rela) { if (loader.Sections.Count <= sym.SectionIndex) { return; } if (sym.SectionIndex == 0) { return; } var symSection = loader.Sections[(int)sym.SectionIndex]; uint S = (uint)sym.Value + symSection.Address.ToUInt32(); int A = 0; int sh = 0; uint mask = ~0u; var addr = referringSection.Address + rela.r_offset; uint P = (uint)addr.ToLinear(); uint PP = P; Debug.Print(" off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2} {5}", rela.r_offset, (SparcRt)(rela.r_info & 0xFF), sym.Name, rela.r_addend, (int)(rela.r_info >> 8), symSection.Name); var rt = (SparcRt)(rela.r_info & 0xFF); switch (rt) { case 0: return; case SparcRt.R_SPARC_HI22: A = rela.r_addend; sh = 10; P = 0; break; case SparcRt.R_SPARC_LO10: A = rela.r_addend; mask = 0x3FF; P = 0; break; case SparcRt.R_SPARC_WDISP30: A = rela.r_addend; P = ~P + 1; sh = 2; break; case SparcRt.R_SPARC_COPY: Debug.Print("Relocation type {0} not handled yet.", rt); return; default: throw new NotImplementedException(string.Format( "SPARC ELF relocation type {0} not implemented yet.", rt)); } var relR = program.CreateImageReader(addr); var relW = program.CreateImageWriter(addr); var w = relR.ReadBeUInt32(); w += ((uint)(S + A + P) >> sh) & mask; relW.WriteBeUInt32(w); }
public override void RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { var rt = (x86_64Rt)(rela.Info & 0xFF); if (loader.Sections.Count <= sym.SectionIndex) { return; } if (rt == x86_64Rt.R_X86_64_GLOB_DAT || rt == x86_64Rt.R_X86_64_JUMP_SLOT) { var addrPfn = Address.Ptr64(rela.Offset); importReferences.Add(addrPfn, new NamedImportReference(addrPfn, null, sym.Name)); var gotSym = loader.CreateGotSymbol(addrPfn, sym.Name); imageSymbols.Add(addrPfn, gotSym); return; } if (sym.SectionIndex == 0) { return; } var symSection = loader.Sections[(int)sym.SectionIndex]; ulong S = (ulong)sym.Value + symSection.Address.ToLinear(); long A = 0; int sh = 0; uint mask = ~0u; Address addr; ulong P; if (referringSection?.Address != null) { addr = referringSection.Address + rela.Offset; P = addr.ToLinear(); } else { addr = Address.Ptr64(rela.Offset); P = 0; } var relR = program.CreateImageReader(addr); var relW = program.CreateImageWriter(addr); ulong PP = P; switch (rt) { case x86_64Rt.R_X86_64_NONE: // just ignore (common) break; case x86_64Rt.R_X86_64_COPY: break; default: Debug.Print("x86_64 ELF relocation type {0} not implemented yet.", rt); break; //throw new NotImplementedException(string.Format( // "x86_64 ELF relocation type {0} not implemented yet.", // rt)); } if (relR != null) { var w = relR.ReadUInt64(); w += ((ulong)(S + (ulong)A + P) >> sh) & mask; relW.WriteUInt64(w); } }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rel rel) { if (loader.Sections.Count <= symbol.SectionIndex) { return; } if (symbol.SectionIndex == 0) { return; } var symSection = loader.Sections[(int)symbol.SectionIndex]; var addr = referringSection.Address + rel.r_offset; var S = symbol.Value; uint P = (uint)addr.ToLinear(); uint PP = P; var relR = program.CreateImageReader(addr); var relW = program.CreateImageWriter(addr); int sh = 0; uint mask = 0; uint A = 0; switch ((MIPSrt)(rel.r_info & 0xFF)) { case MIPSrt.R_MIPS_NONE: return; case MIPSrt.R_MIPS_REL32: break; /* * R_MIPS_NONE 0 none local none * R_MIPS_16 1 V–half16 external S + sign–extend(A) * 1 V–half16 local S + sign–extend(A) * R_MIPS_32 2 T–word32 external S + A * 2 T–word32 local S + A * R_MIPS_REL32 3 T–word32 external A – EA + S * R_MIPS_REL32 3 T–word32 local A – EA + S * R_MIPS_26 4 T–targ26 local (((A << 2) | \ * (P & 0xf0000000) + S) >> 2 * 4 T–targ26 external (sign–extend(A < 2) + S) >> 2 * R_MIPS_HI16 5 T–hi16 external ((AHL + S) – \ * (short)(AHL + S)) >> 16 * 5 T–hi16 local ((AHL + S) – \ * (short)(AHL + S)) >> 16 * 5 V–hi16 _gp_disp (AHL + GP – P) – (short) \ * (AHL + GP – P)) >> 16 * R_MIPS_LO16 6 T–lo16 external AHL + S * 6 T–lo16 local AHL + S * 6 V–lo16 _gp_disp AHL + GP – P + 4 * R_MIPS_GPREL16 7 V–rel16 external sign–extend(A) + S + GP * 7 V–rel16 local sign–extend(A) + S + GP0 – GP * R_MIPS_LITERAL 8 V–lit16 local sign–extend(A) + L * R_MIPS_GOT16 9 V–rel16 external G * 9 V–rel16 local see below * R_MIPS_PC16 10 V–pc16 external sign–extend(A) + S – P * R_MIPS_CALL16 11 V–rel16 external G * R_MIPS_GPREL32 12 T–word32 local A + S + GP0 – GP * R_MIPS_GOTHI16 21 T-hi16 external (G - (short)G) >> 16 + A * R_MIPS_GOTLO16 22 T-lo16 external G & 0xffff * R_MIPS_CALLHI16 30 T-hi16 external (G - (short)G) >> 16 + A * R_MIPS_CALLLO16 31 T-lo16 external G & 0xffff */ } var w = relR.ReadUInt32(); w += ((uint)(S + A + P) >> sh) & mask; relW.WriteUInt32(w); }
public static ElfSection Read(BinaryReader reader) { var s = new ElfSection(); s.sh_name = reader.ReadBigUInt32(); s.sh_type = (Type)reader.ReadBigUInt32(); s.sh_flags = (Flags)reader.ReadBigUInt32(); s.sh_addr = reader.ReadBigUInt32(); uint sh_offset = reader.ReadBigUInt32(); s.sh_size = reader.ReadBigUInt32(); s.sh_link = reader.ReadBigUInt32(); s.sh_info = reader.ReadBigUInt32(); s.sh_addralign = reader.ReadBigUInt32(); s.sh_entsize = reader.ReadBigUInt32(); if (s.sh_type != Type.SHT_NULL && s.sh_type != Type.SHT_NOBITS) { long savePos = reader.BaseStream.Position; reader.BaseStream.Position = sh_offset; s.data = reader.ReadBytes((int) s.sh_size); reader.BaseStream.Position = savePos; } return s; }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= sym.SectionIndex) { return(sym); } var rt = (SparcRt)(rela.Info & 0xFF); if (sym.SectionIndex == 0) { if (rt == SparcRt.R_SPARC_GLOB_DAT || rt == SparcRt.R_SPARC_JMP_SLOT) { var addrPfn = Address.Ptr32((uint)rela.Offset); Debug.Print("Import reference {0} - {1}", addrPfn, sym.Name); var st = ElfLoader.GetSymbolType(sym); if (st.HasValue) { importReferences[addrPfn] = new NamedImportReference(addrPfn, null, sym.Name, st.Value); } return(sym); } } var symSection = loader.Sections[(int)sym.SectionIndex]; uint S = (uint)sym.Value + symSection.Address.ToUInt32(); int A = 0; int sh = 0; uint mask = ~0u; Address addr; if (referringSection != null) { addr = referringSection.Address + rela.Offset; } else { addr = Address.Ptr32((uint)rela.Offset); } uint P = (uint)addr.ToLinear(); uint PP = P; uint B = 0; Debug.Print(" off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2} {5}", rela.Offset, (SparcRt)(rela.Info & 0xFF), sym.Name, rela.Addend, (int)(rela.Info >> 8), "section?"); switch (rt) { case 0: return(sym); case SparcRt.R_SPARC_HI22: A = (int)rela.Addend; sh = 10; P = 0; break; case SparcRt.R_SPARC_LO10: A = (int)rela.Addend; mask = 0x3FF; P = 0; break; case SparcRt.R_SPARC_32: A = (int)rela.Addend; mask = 0xFFFFFFFF; P = 0; break; case SparcRt.R_SPARC_WDISP30: A = (int)rela.Addend; P = ~P + 1; sh = 2; break; case SparcRt.R_SPARC_RELATIVE: A = (int)rela.Addend; B = program.SegmentMap.BaseAddress.ToUInt32(); break; case SparcRt.R_SPARC_COPY: Debug.Print("Relocation type {0} not handled yet.", rt); return(sym); default: throw new NotImplementedException(string.Format( "SPARC ELF relocation type {0} not implemented yet.", rt)); } var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var w = relR.ReadBeUInt32(); w += ((uint)(B + S + A + P) >> sh) & mask; relW.WriteBeUInt32(w); return(sym); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { return; }
/// <summary> /// Perform the relocation specified by <paramref name="rela"/>, using the <paramref name="symbol"/> as a /// reference. /// </summary> /// <param name="program">The program image being loaded</param> /// <param name="symbol">The <see cref="ElfSymbol"/> associated with this relocation.</param> /// <param name="referringSection">The section in which the relocation is.</param> /// <param name="rela">The relocation information.</param> /// <returns>The address of the entry in the GOT where the relocation was performed, and optionally /// a symbol for the PLT entry that refers to that GOT entry.</returns> public abstract (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela);
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= symbol.SectionIndex) { return(null, null); } ulong S = (ulong)symbol.Value; ulong A = (ulong)rela.Addend; ulong P = (ulong)rela.Offset; ulong B = program.SegmentMap.BaseAddress.ToLinear(); var addr = Address.Ptr64(P); ulong PP = P; var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var rt = (Ppc64Rt)(rela.Info & 0xFF); switch (rt) { case Ppc64Rt.R_PPC64_RELATIVE: // B + A S = 0; P = 0; break; case Ppc64Rt.R_PPC64_ADDR64: // S + A B = 0; P = 0; break; case Ppc64Rt.R_PPC64_JMP_SLOT: return(addr, null); default: var listener = this.loader.Services.RequireService <DecompilerEventListener>(); var loc = listener.CreateAddressNavigator(program, addr); listener.Warn(loc, $"Unimplemented PowerPC64 relocation type {rt}."); return(addr, null); } var w = relR.ReadUInt64(); w += (B + A + S + P); relW.WriteUInt64(w); return(addr, null); }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { return(symbol); }
public override void RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, Elf32_Rela rela) { if (loader.Sections.Count <= sym.SectionIndex) { return; } if (sym.SectionIndex == 0) { return; } var symSection = loader.Sections[(int)sym.SectionIndex]; uint S = (uint)sym.Value + symSection.Address.ToUInt32(); int A = 0; int sh = 0; uint mask = ~0u; var addr = referringSection.Address + rela.r_offset; uint P = (uint)addr.ToLinear(); uint PP = P; var relR = program.CreateImageReader(addr); var relW = program.CreateImageWriter(addr); var rt = (i386Rt)(rela.r_info & 0xFF); switch (rt) { case i386Rt.R_386_NONE: // just ignore (common) break; case i386Rt.R_386_32: // S + A // Read the symTabIndex'th symbol. A = rela.r_addend; P = 0; break; case i386Rt.R_386_PC32: // S + A - P if (sym.Value == 0) { // This means that the symbol doesn't exist in this module, and is not accessed // through the PLT, i.e. it will be statically linked, e.g. strcmp. We have the // name of the symbol right here in the symbol table entry, but the only way // to communicate with the loader is through the target address of the call. // So we use some very improbable addresses (e.g. -1, -2, etc) and give them entries // in the symbol table //S = nextFakeLibAddr--; // Allocate a new fake address //loader.AddSymbol(S, sym.Name); //} } A = rela.r_addend; P = ~P + 1; break; case i386Rt.R_386_GLOB_DAT: // This relocation type is used to set a global offset table entry to the address of the // specified symbol. The special relocation type allows one to determine the // correspondence between symbols and global offset table entries. P = 0; break; default: throw new NotImplementedException(string.Format( "i386 ELF relocation type {0} not implemented yet.", rt)); } var w = relR.ReadBeUInt32(); w += ((uint)(S + A + P) >> sh) & mask; relW.WriteBeUInt32(w); }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { //$TODO: relocate! return(null, null); }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { //throw new NotImplementedException(); return(null, null); }