public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { //$TODO: implement me! return(null, null); }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rel) { 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; switch ((MIPSrt)(rel.Info & 0xFF)) { case MIPSrt.R_MIPS_NONE: return(symbol); 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); return(symbol); }
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); }
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); }
public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol symbol, ElfSection?referringSection, ElfRelocation rel) { if (symbol == null || loader.Sections.Count <= symbol.SectionIndex) { return(null, null); } 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(addr, 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) { var rt = (x86_64Rt)(rela.Info & 0xFF); if (loader.Sections.Count <= sym.SectionIndex) { return(null, null); } if (rt == x86_64Rt.R_X86_64_GLOB_DAT || rt == x86_64Rt.R_X86_64_JUMP_SLOT) { var addrPfn = Address.Ptr64(rela.Offset); var st = ElfLoader.GetSymbolType(sym); if (!st.HasValue) { return(null, null); } importReferences.Add(addrPfn, new NamedImportReference(addrPfn, null, sym.Name, st.Value)); var gotSym = loader.CreateGotSymbol(addrPfn, sym.Name); imageSymbols.Add(addrPfn, gotSym); return(addrPfn, null); } ulong S = 0; if (sym.SectionIndex != 0) { var symSection = loader.Sections[(int)sym.SectionIndex]; 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 arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, 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); } return(addr, null); }
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); 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(sym); } } 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(sym); 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(sym); default: ElfImageLoader.trace.Error( "SPARC ELF relocation type {0} not implemented yet.", rt); return(sym); } }
/// <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 ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { //$TODO: implement me! return(symbol); }
public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol symbol, ElfSection?referringSection, ElfRelocation rela) { //throw new NotImplementedException(); return(null, null); }
private ElfRelocation ReadElf32Relocation(IList<byte> data, int p, bool is_rela) { ElfRelocation r = new ElfRelocation(); r.r_offset = ListReader.ReadUInt32(data, ref p); uint r_info = ListReader.ReadUInt32(data, ref p); r.r_sym = (int)(r_info >> 8); r.r_type = (int)(r_info & 0xff); if (is_rela) r.r_addend = ListReader.ReadInt32(data, ref p); return r; }
private ElfRelocation ReadElf64Relocation(IList<byte> data, int p, bool is_rela) { ElfRelocation r = new ElfRelocation(); r.r_offset = ListReader.ReadUInt64(data, ref p); r.r_type = ListReader.ReadInt32(data, ref p); r.r_sym = ListReader.ReadInt32(data, ref p); if (is_rela) r.r_addend = ListReader.ReadInt64(data, ref p); return r; }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection?referringSection, ElfRelocation rela) { throw new NotImplementedException(); }
public override void RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= sym.SectionIndex) { return; } if (sym.SectionIndex == 0) { return; } if (referringSection == null) { 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.Offset; uint P = (uint)addr.ToLinear(); uint PP = P; var relR = program.CreateImageReader(addr); var relW = program.CreateImageWriter(addr); var rt = (i386Rt)(rela.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 = (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.ReadBeUInt32(); w += ((uint)(S + A + P) >> sh) & mask; relW.WriteBeUInt32(w); }
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 */ var rt = (Arm32Rt)(rela.Info & 0xFF); switch (rt) { case Arm32Rt.R_ARM_COPY: break; case Arm32Rt.R_ARM_GLOB_DAT: case Arm32Rt.R_ARM_JUMP_SLOT: break; default: throw new NotImplementedException($"AArch32 relocation type {rt} is not implemented yet."); } return(symbol); }
public override (Address, 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(addrPfn, null); } return(null, null); }
public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol symbol, ElfSection?referringSection, ElfRelocation rela) { return(null, null); }
public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol symbol, ElfSection?referringSection, ElfRelocation rel) { if (symbol == null || loader.Sections.Count <= symbol.SectionIndex) { return(null, null); } Address addr; ulong P; if (referringSection?.Address != null) { addr = referringSection.Address + rel.Offset; P = addr.ToLinear(); } else { addr = Address.Ptr64(rel.Offset); P = 0; } if (addr.ToLinear() == 0) { return(addr, symbol); } var S = symbol.Value; ulong PP = P; var relR = program.CreateImageReader(program.Architecture, addr); var relW = program.CreateImageWriter(program.Architecture, addr); int sh = 0; uint mask = 0; if (!relR.TryPeekBeUInt32(0, out uint w)) { return(null, null); } uint A = (rel.Addend.HasValue) ? (uint)rel.Addend.Value : w; uint ww = w; switch ((Mips64Rt)rel.Info) { case Mips64Rt.R_MIPS_NONE: return(null, null); case Mips64Rt.R_MIPS_64: ulong A64; if (rel.Addend.HasValue) { A64 = (ulong)rel.Addend.Value; } else if (!relR.TryPeekUInt64(0, out A64)) { return(null, null); } Debug.Print(" Reloc at {0} is now {1:16}", addr, S + A64); relW.WriteUInt64(S + A64); return(addr, symbol); case Mips64Rt.R_MIPS_26: uint n; if (symbol.Bind == ElfSymbolBinding.STB_LOCAL) { n = (uint)(((A << 2) | (addr.ToLinear() & 0xF0000000u)) + S) >> 2; } else { long sA = targ26.ReadSigned(A) << 2; n = (uint)((S + (ulong)sA) >> 2); } ww = (w & 0xFC000000u) | n; relW.WriteUInt32(w); break; default: ElfImageLoader.trace.Warn("Unimplemented MIPS64 relocation type: {0}", RelocationTypeToString((uint)rel.Info)); return(addr, symbol); } relW.WriteUInt32(ww); Debug.Print(" Reloc at {0} was {1:X8}, is now {2:X8}", addr, w, ww); return(addr, symbol); }
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); program.ImportReferences[addrPfn] = new NamedImportReference(addrPfn, null, symbol.Name); return(symbol); } return(symbol); }
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 !.Value; 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) { //$TODO: implement me :) throw new NotImplementedException(); }
public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol symbol, ElfSection?referringSection, ElfRelocation rel) { if (symbol == null || loader.Sections.Count <= symbol.SectionIndex) { return(null, null); } Address addr; ulong P; if (referringSection?.Address != null) { addr = referringSection.Address + rel.Offset; P = addr.ToLinear(); } else { addr = Address.Ptr64(rel.Offset); P = 0; } if (addr.ToLinear() == 0) { return(addr, symbol); } var uAddrSection = (symbol.SectionIndex != 0) ? loader.Sections[(int)symbol.SectionIndex].Address?.ToLinear() ?? 0 : 0; uint S = (uint)(symbol.Value + uAddrSection); ulong PP = P; var relR = program.CreateImageReader(program.Architecture, addr); var relW = program.CreateImageWriter(program.Architecture, addr); int sh = 0; uint mask = 0; if (!relR.TryPeekBeUInt32(0, out uint w)) { return(null, null); } uint A = (rel.Addend.HasValue) ? (uint)rel.Addend.Value : w; uint ww = w; switch ((Mips64Rt)rel.Info) { case Mips64Rt.R_MIPS_NONE: return(null, null); case Mips64Rt.R_MIPS_64: ulong A64; if (rel.Addend.HasValue) { A64 = (ulong)rel.Addend.Value; } else if (!relR.TryPeekUInt64(0, out A64)) { return(null, null); } relW.WriteUInt64(S + A64); return(addr, symbol); case Mips64Rt.R_MIPS_26: long sA = targ26.ReadSigned(A) << 2; uint n = (uint)((S + (ulong)sA) >> 2); ww = (w & 0xFC000000u) | n; break; default: ElfImageLoader.trace.Warn("Unimplemented MIPS64 relocation type: {0}", RelocationTypeToString((uint)rel.Info)); return(addr, symbol); } relW.WriteUInt32(ww); return(addr, symbol); }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { return(symbol); }
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 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); importReferences[addrPfn] = new NamedImportReference(addrPfn, null, sym.Name); 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, ElfRelocation rela) { //throw new NotImplementedException(); }
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 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 ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { ulong S = (ulong)symbol.Value; ulong A = 0; ulong B = 0; var rt = (zSeriesRt)(rela.Info & 0xFF); 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 zSeriesRt.R_390_RELATIVE: // B + A A = (ulong)rela.Addend; B = program.SegmentMap.BaseAddress.ToLinear(); S = 0; break; case zSeriesRt.R_390_GLOB_DAT: // S + A A = (ulong)rela.Addend; break; case zSeriesRt.R_390_JMP_SLOT: if (symbol.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.PeekBeUInt64(0); return(CreatePltStubSymbolFromRelocation(symbol, gotEntry, 0xE)); } break; default: Debug.Print("Unhandled relocation {0}: {1}", rt, rela); break; } var w = relR.ReadBeUInt64(); w += ((uint)(B + S + A)); relW.WriteBeUInt64(w); return(symbol); }
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); 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(addrPfn, null); } } 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(addr, null); 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)re
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 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); }