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); } }
private void WriteElf32Symbol(ElfSymbol sym, System.IO.BinaryWriter w) { w.Write((uint)sym.st_name); w.Write((uint)sym.st_value); w.Write((uint)sym.st_size); uint st_info = (sym.st_bind << 4) + (sym.st_type & 0xf); w.Write((byte)st_info); w.Write((byte)0); w.Write((ushort)sym.st_shndx); }
public virtual void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rel rel) { }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= sym.SectionIndex) { return(sym); } 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); return(CreatePltStubSymbolFromRelocation(sym, gotEntry, 6)); } 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(sym); }
public override (Address?, ElfSymbol?) RelocateEntry(Program program, ElfSymbol symbol, ElfSection?referringSection, ElfRelocation rela) { throw new NotImplementedException(); }
private void AddSymbol(ISymbol sym, StringSection strtab, List<ElfSymbol> osyms, Dictionary<ISymbol, int> sym_map, Dictionary<ISection, int> sect_map) { ElfSymbol esym = new ElfSymbol(); esym.Name = sym.Name; esym.st_name = AllocateString(sym.Name, strtab); esym.st_value = sym.Offset; if (IsExecutable && sym.DefinedIn != null) esym.st_value += sym.DefinedIn.LoadAddress; esym.st_size = sym.Size; esym.st_bind = 0; switch(sym.Type) { case SymbolType.Global: esym.st_bind = 1; break; case SymbolType.Weak: esym.st_bind = 2; break; } esym.st_type = 0; switch (sym.ObjectType) { case SymbolObjectType.Object: esym.st_type = 1; break; case SymbolObjectType.Function: esym.st_type = 2; break; } esym.st_shndx = sect_map[sym.DefinedIn]; sym_map[sym] = osyms.Count; osyms.Add(esym); }
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; switch ((MIPSrt)(rel.Info & 0xFF)) { case MIPSrt.R_MIPS_NONE: return(symbol); case MIPSrt.R_MIPS_REL32: break; default: mask = 0; 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 ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { //throw new NotImplementedException(); return(symbol); }
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; 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(null, null); } 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(addr, null); }
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 (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 DwarfCompilationUnitItem(ElfSymbol symbol) { Name = symbol.Name; Pc = symbol.Header.ValueAddr; Size = symbol.Header.Size; }
public override ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { //$TODO: implement me! return(symbol); }
private ElfSymbol ReadElf32Symbol(IList<byte> data, int p) { ElfSymbol s = new ElfSymbol(); s.st_name = ListReader.ReadInt32(data, ref p); s.st_value = ListReader.ReadUInt32(data, ref p); s.st_size = ListReader.ReadInt32(data, ref p); s.st_info = ListReader.ReadByte(data, ref p); s.st_other = ListReader.ReadByte(data, ref p); s.st_shndx = ListReader.ReadInt16(data, ref p); s.st_bind = s.st_info >> 4; s.st_type = s.st_info & 0xf; return s; }
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 ElfSymbol RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { 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 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 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.HasValue ? rela.Addend.Value : 0, (int)(rela.Info >> 8), "section?"); switch (rt) { case 0: return(null, null); case SparcRt.R_SPARC_HI22: A = (int)rela.Addend !.Value; 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 !.Value; 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 !.Value; 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 !.Value; 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 !.Value; 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 !.Value; 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); } }
private void WriteElf64Symbol(ElfSymbol sym, System.IO.BinaryWriter w) { throw new NotImplementedException(); }
public override (Address, ElfSymbol) RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela) { return(null, null); }
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
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) { //$TODO: implement me :) throw new NotImplementedException(); }
public abstract void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, ElfRelocation rela);
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); }
private void LoadMod0Symbols(MemoryManager memory, ulong textOffset) { ulong mod0Offset = textOffset + memory.Read <uint>(textOffset + 4); if (mod0Offset < textOffset || !memory.IsMapped(mod0Offset) || (mod0Offset & 3) != 0) { return; } Dictionary <ElfDynamicTag, ulong> dynamic = new Dictionary <ElfDynamicTag, ulong>(); int mod0Magic = memory.Read <int>(mod0Offset + 0x0); if (mod0Magic != Mod0) { return; } ulong dynamicOffset = memory.Read <uint>(mod0Offset + 0x4) + mod0Offset; ulong bssStartOffset = memory.Read <uint>(mod0Offset + 0x8) + mod0Offset; ulong bssEndOffset = memory.Read <uint>(mod0Offset + 0xc) + mod0Offset; ulong ehHdrStartOffset = memory.Read <uint>(mod0Offset + 0x10) + mod0Offset; ulong ehHdrEndOffset = memory.Read <uint>(mod0Offset + 0x14) + mod0Offset; ulong modObjOffset = memory.Read <uint>(mod0Offset + 0x18) + mod0Offset; bool isAArch32 = memory.Read <ulong>(dynamicOffset) > 0xFFFFFFFF || memory.Read <ulong>(dynamicOffset + 0x10) > 0xFFFFFFFF; while (true) { ulong tagVal; ulong value; if (isAArch32) { tagVal = memory.Read <uint>(dynamicOffset + 0); value = memory.Read <uint>(dynamicOffset + 4); dynamicOffset += 0x8; } else { tagVal = memory.Read <ulong>(dynamicOffset + 0); value = memory.Read <ulong>(dynamicOffset + 8); dynamicOffset += 0x10; } ElfDynamicTag tag = (ElfDynamicTag)tagVal; if (tag == ElfDynamicTag.DT_NULL) { break; } dynamic[tag] = value; } if (!dynamic.TryGetValue(ElfDynamicTag.DT_STRTAB, out ulong strTab) || !dynamic.TryGetValue(ElfDynamicTag.DT_SYMTAB, out ulong symTab) || !dynamic.TryGetValue(ElfDynamicTag.DT_SYMENT, out ulong symEntSize)) { return; } ulong strTblAddr = textOffset + strTab; ulong symTblAddr = textOffset + symTab; List <ElfSymbol> symbols = new List <ElfSymbol>(); while (symTblAddr < strTblAddr) { ElfSymbol sym = isAArch32 ? GetSymbol32(memory, symTblAddr, strTblAddr) : GetSymbol64(memory, symTblAddr, strTblAddr); symbols.Add(sym); symTblAddr += symEntSize; } lock (_images) { _images.Add(new Image(textOffset, symbols.OrderBy(x => x.Value).ToArray())); } }
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); } } }
private void LoadMod0Symbols(MemoryManager memory, long textOffset) { long mod0Offset = textOffset + memory.ReadUInt32(textOffset + 4); if (mod0Offset < textOffset || !memory.IsMapped(mod0Offset) || (mod0Offset & 3) != 0) { return; } Dictionary <ElfDynamicTag, long> dynamic = new Dictionary <ElfDynamicTag, long>(); int mod0Magic = memory.ReadInt32(mod0Offset + 0x0); if (mod0Magic != Mod0) { return; } long dynamicOffset = memory.ReadInt32(mod0Offset + 0x4) + mod0Offset; long bssStartOffset = memory.ReadInt32(mod0Offset + 0x8) + mod0Offset; long bssEndOffset = memory.ReadInt32(mod0Offset + 0xc) + mod0Offset; long ehHdrStartOffset = memory.ReadInt32(mod0Offset + 0x10) + mod0Offset; long ehHdrEndOffset = memory.ReadInt32(mod0Offset + 0x14) + mod0Offset; long modObjOffset = memory.ReadInt32(mod0Offset + 0x18) + mod0Offset; while (true) { long tagVal = memory.ReadInt64(dynamicOffset + 0); long value = memory.ReadInt64(dynamicOffset + 8); dynamicOffset += 0x10; ElfDynamicTag tag = (ElfDynamicTag)tagVal; if (tag == ElfDynamicTag.DT_NULL) { break; } dynamic[tag] = value; } if (!dynamic.TryGetValue(ElfDynamicTag.DT_STRTAB, out long strTab) || !dynamic.TryGetValue(ElfDynamicTag.DT_SYMTAB, out long symTab) || !dynamic.TryGetValue(ElfDynamicTag.DT_SYMENT, out long symEntSize)) { return; } long strTblAddr = textOffset + strTab; long symTblAddr = textOffset + symTab; List <ElfSymbol> symbols = new List <ElfSymbol>(); while ((ulong)symTblAddr < (ulong)strTblAddr) { ElfSymbol sym = GetSymbol(memory, symTblAddr, strTblAddr); symbols.Add(sym); symTblAddr += symEntSize; } lock (_images) { _images.Add(new Image(textOffset, symbols.OrderBy(x => x.Value).ToArray())); } }
/// <summary> /// Creates a symbol that refers to the location of a PLT stub functon, based on the value /// found in the GOT for that PLT stub. /// </summary> /// <remarks> /// Some versions of GCC emit a R_386_JUMP_SLOT relocation where the symbol being referred to /// has a value of 0, where it normally would have been the virtual address of a PLT stub. Those /// versions of GCC put, in the GOT entry for the relocation, a pointer to the PLT stub + 6 bytes. /// We subtract those 6 bytes to obtain a pointer to the PLT stub. /// </remarks> protected ElfSymbol CreatePltStubSymbolFromRelocation(ElfSymbol sym, ulong gotEntry, int offset) { sym.Value = (ulong)((long)gotEntry - offset); // skip past the Jmp [ebx+xxxxxxxx] return(sym); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf64_Rela rela) { //throw new NotImplementedException(); }
/// <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) { var rt = (RiscVRt)(rela.Info & 0xFF); return(null, symbol); }
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 abstract void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela);
public override (Address?, 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.HasValue ? rela.Addend.Value : 0; 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(addr, null); 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(addr, null); } 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(addr, null); } offset >>= 2; offset &= 0x00ffffff; uInstr &= 0xFF000000; uInstr |= offset; var relWriter = program.CreateImageWriter(program.Architecture, addr); relWriter.WriteUInt32(uInstr); return(addr, null); } 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(addr, null); } 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(addr, null); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { throw new NotImplementedException(); }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { return; }