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 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 ImageSegmentRenderer CreateRenderer(ElfSection shdr, ElfMachine machine) { switch (shdr.Type) { case SectionHeaderType.SHT_DYNAMIC: return(new DynamicSectionRenderer32(this, shdr, machine)); case SectionHeaderType.SHT_REL: return(new RelSegmentRenderer(this, shdr)); case SectionHeaderType.SHT_RELA: return(new RelaSegmentRenderer(this, shdr)); case SectionHeaderType.SHT_SYMTAB: case SectionHeaderType.SHT_DYNSYM: return(new SymtabSegmentRenderer32(this, shdr)); default: return(null); } }
private void DumpRel(ElfSection sh) { var entries = sh.Size / sh.EntrySize; var symtab = sh.LinkedSection; var rdr = CreateReader(sh.FileOffset); for (ulong i = 0; i < entries; ++i) { if (!rdr.TryReadUInt64(out ulong offset)) { return; } if (!rdr.TryReadUInt64(out ulong info)) { return; } ulong sym = info >> 8; string symStr = GetStrPtr(symtab !, sym); ElfImageLoader.trace.Verbose(" RELA {0:X16} {1,3} {2:X16} {3}", offset, info & 0xFF, sym, symStr); } }
public override Dictionary <int, ElfSymbol> LoadSymbolsSection(ElfSection symSection) { ElfImageLoader.trace.Inform("== Symbols from {0} ==", symSection.Name); var symbols = new Dictionary <int, ElfSymbol>(); var stringtableSection = symSection.LinkedSection !; var rdr = CreateReader(symSection.FileOffset); for (ulong i = 0; i < symSection.Size / symSection.EntrySize; ++i) { if (!Elf64_Sym.TryLoad(rdr, out var sym)) { ElfImageLoader.trace.Warn("Unable to load symbol entry {0} from {1}", i, symSection.Name); continue; } var name = RemoveModuleSuffix(ReadAsciiString(stringtableSection.FileOffset + sym.st_name)); ElfImageLoader.trace.Verbose(" {0,3} {1,-25} {2,-12} {3,6} {4} {5,-15} {6:X16} {7,9}", i, string.IsNullOrWhiteSpace(name) ? "<empty>" : name, (ElfSymbolType)(sym.st_info & 0xF), sym.st_shndx, GetBindingName((ElfSymbolBinding)(sym.st_info >> 4)), GetSectionName(sym.st_shndx), sym.st_value, sym.st_size); var esym = new ElfSymbol(name) { Type = (ElfSymbolType)(sym.st_info & 0xF), Bind = (ElfSymbolBinding)(sym.st_info >> 4), SectionIndex = sym.st_shndx, Value = sym.st_value, Size = sym.st_size, }; symbols.Add((int)i, esym); } return(symbols); }
/// <summary> /// Allocate the space required by SHN_COMMON symbols into a /// synthesized section called ".reko.common", and which will /// be placed into its own segment later. /// </summary> private void CollectCommonSymbolsIntoSection() { var rekoCommon = new ElfSection { Name = ".reko.common", Number = (uint)loader.Sections.Count, Type = SectionHeaderType.SHT_NOBITS, Flags = ElfLoader.SHF_WRITE | ElfLoader.SHF_ALLOC | ElfLoader.SHF_REKOCOMMON, FileOffset = 0, Size = 0, }; foreach (var sym in loader.GetAllSymbols().Where(s => s.SectionIndex == 0xFFF2)) { rekoCommon.Size = Align(rekoCommon.Size, sym.Value); sym.Value = (uint)rekoCommon.Size; sym.SectionIndex = (uint)loader.Sections.Count; rekoCommon.Size += sym.Size; } if (rekoCommon.Size > 0) { loader.Sections.Add(rekoCommon); } }
/// <summary> /// Allocate the space required by SHN_COMMON symbols into a /// synthesized section called ".reko.common", and which will /// be placed into its own segment later. /// </summary> private void CollectCommonSymbolsIntoSection() { var rekoCommon = new ElfSection { Name = ".reko.common", Number = (uint) loader.Sections.Count, Type = SectionHeaderType.SHT_NOBITS, Flags = ElfLoader.SHF_WRITE | ElfLoader.SHF_ALLOC | ElfLoader.SHF_REKOCOMMON, FileOffset = 0, Size = 0, }; foreach (var sym in loader.GetAllSymbols().Where(s => s.SectionIndex == 0xFFF2)) { rekoCommon.Size = Align(rekoCommon.Size, sym.Value); sym.Value = (uint) rekoCommon.Size; sym.SectionIndex = (uint) loader.Sections.Count; rekoCommon.Size += sym.Size; } if (rekoCommon.Size > 0) { loader.Sections.Add(rekoCommon); } }
public override void LoadSectionHeaders() { // Create the sections. var inames = new List<uint>(); var links = new List<uint>(); var infos = new List<uint>(); var rdr = imgLoader.CreateReader(Header64.e_shoff); for (uint i = 0; i < Header64.e_shnum; ++i) { var shdr = Elf64_SHdr.Load(rdr); var section = new ElfSection { Number = i, Type = shdr.sh_type, Flags = shdr.sh_flags, Address = shdr.sh_addr != 0 ? platform.MakeAddressFromLinear(shdr.sh_addr) : null, FileOffset = shdr.sh_offset, Size = shdr.sh_size, Alignment = shdr.sh_addralign, EntrySize = shdr.sh_entsize, }; Sections.Add(section); inames.Add(shdr.sh_name); links.Add(shdr.sh_link); infos.Add(shdr.sh_info); } // Get section names and crosslink sections. for (int i = 0; i < Sections.Count; ++i) { var section = Sections[i]; section.Name = ReadSectionName(inames[i]); ElfSection linkSection = null; ElfSection relSection = null; switch (section.Type) { case SectionHeaderType.SHT_REL: case SectionHeaderType.SHT_RELA: linkSection = GetSectionByIndex(links[i]); relSection = GetSectionByIndex(infos[i]); break; case SectionHeaderType.SHT_DYNAMIC: case SectionHeaderType.SHT_HASH: case SectionHeaderType.SHT_SYMTAB: case SectionHeaderType.SHT_DYNSYM: linkSection = GetSectionByIndex(links[i]); break; } section.LinkedSection = linkSection; section.RelocatedSection = relSection; } }
public string GetSymbolName(ElfSection symSection, uint symbolNo) { var strSection = symSection.LinkedSection; uint offset = (uint)(symSection.FileOffset + symbolNo * symSection.EntrySize); var rdr = imgLoader.CreateReader(offset); rdr.TryReadUInt32(out offset); return GetStrPtr(strSection, offset); }
public abstract Dictionary <int, ElfSymbol> LoadSymbolsSection(ElfSection symSection);
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { throw new NotImplementedException(); }
public override void Render(ImageSegment segment, Program program, Formatter formatter) { // Get the entry that has the segment# for the string table. var dynStrtab = loader.GetDynEntries64(shdr.FileOffset).Where(d => d.d_tag == DT_STRTAB).FirstOrDefault(); if (dynStrtab == null) return; this.strtabSection = loader.GetSectionInfoByAddr64(dynStrtab.d_ptr); foreach (var entry in loader.GetDynEntries64(shdr.FileOffset)) { DtFormat fmt; string entryName; Entry dser; if (!entries.TryGetValue(entry.d_tag, out dser)) { entryName = string.Format("{0:X8} ", entry.d_tag); fmt = DtFormat.Hexadecimal; } else { entryName = dser.Name; fmt = dser.Format; } RenderEntry(entryName, fmt, entry, formatter); formatter.WriteLine(); } }
public DynamicSectionRenderer32(ElfLoader32 loader, ElfSection shdr, ElfMachine machine) { this.loader = loader; this.shdr = shdr; if (!machineSpecificEntries.TryGetValue(machine, out machineSpecific)) { machineSpecific = new Dictionary<long, Entry>(); } }
public virtual void RelocateEntry(ElfSymbol symbol, ElfSection referringSection, Elf64_Rela rela) { throw new NotImplementedException(); }
public override void RelocateEntry(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); 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; default: throw new NotImplementedException(string.Format( "SPARC ELF relocation type {0} not implemented yet.", rt)); } var w = relR.ReadBeUInt32(); w += ((uint)(S + A + P) >> sh) & mask; relW.WriteBeUInt32(w); }
private ImageSegmentRenderer CreateRenderer64(ElfSection shdr) { switch (shdr.Type) { case SectionHeaderType.SHT_DYNAMIC: return new DynamicSectionRenderer64(this, shdr); case SectionHeaderType.SHT_RELA: return new RelaSegmentRenderer64(this, shdr); case SectionHeaderType.SHT_SYMTAB: case SectionHeaderType.SHT_DYNSYM: return new SymtabSegmentRenderer64(this, shdr); default: return null; } }
public RelaSegmentRenderer64(ElfLoader64 loader, ElfSection shdr) { this.loader = loader; this.shdr = shdr; }
public abstract void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela);
public override List<ElfSymbol> LoadSymbolsSection(ElfSection symSection) { //Debug.Print("Symbols"); var stringtableSection = symSection.LinkedSection; var rdr = CreateReader(symSection.FileOffset); var symbols = new List<ElfSymbol>(); for (ulong i = 0; i < symSection.Size / symSection.EntrySize; ++i) { var sym = Elf64_Sym.Load(rdr); //Debug.Print(" {0,3} {1,-25} {2,-12} {3,6} {4,-15} {5:X8} {6,9}", // i, // ReadAsciiString(stringtableSection.FileOffset + sym.st_name), // (ElfSymbolType)(sym.st_info & 0xF), // sym.st_shndx, // GetSectionName(sym.st_shndx), // sym.st_value, // sym.st_size); symbols.Add(new ElfSymbol { Name = ReadAsciiString(stringtableSection.FileOffset + sym.st_name), Type = (ElfSymbolType)(sym.st_info & 0xF), SectionIndex = sym.st_shndx, Value = sym.st_value, Size = sym.st_size, }); } return symbols; }
/// <summary> /// Allocate an arbitrary 16 bytes for each unresolved /// external symbol. /// </summary> private void CollectUndefinedSymbolsIntoSection() { var rekoExtfn = new ElfSection { Name = ".reko.externs", Number = (uint) loader.Sections.Count, Type = SectionHeaderType.SHT_NOBITS, Flags = ElfLoader.SHF_ALLOC | ElfLoader.SHF_EXECINSTR, FileOffset = 0, Size = 0, Alignment = 0x10, }; foreach (var sym in loader.GetAllSymbols().Where(s => s.Type == ElfSymbolType.STT_NOTYPE && !string.IsNullOrEmpty(s.Name))) { rekoExtfn.Size = Align(rekoExtfn.Size, 0x10); sym.Value = (uint) rekoExtfn.Size; sym.SectionIndex = (uint)loader.Sections.Count; rekoExtfn.Size += 0x10; } if (rekoExtfn.Size > 0) { loader.Sections.Add(rekoExtfn); } }
public string GetStrPtr(ElfSection section, ulong offset) { if (section == null) { // Most commonly, this will be an index of -1, because a call to GetSectionIndexByName() failed throw new ArgumentNullException("section"); } // Get a pointer to the start of the string table and add the offset return imgLoader.ReadAsciiString(section.FileOffset + offset); }
public RelSegmentRenderer(ElfLoader32 loader, ElfSection shdr) { this.loader = loader; this.shdr = shdr; }
public DynamicSectionRenderer64(ElfLoader64 loader, ElfSection shdr) { this.loader = loader; this.shdr = shdr; }
public abstract void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela);
public RelaSegmentRenderer(ElfLoader32 imgLoader, ElfSection shdr) { this.loader = imgLoader; this.shdr = shdr; }
private void DumpRela(ElfSection sh) { var entries = sh.Size / sh.EntrySize; var symtab = sh.LinkedSection; var rdr = imgLoader.CreateReader(sh.FileOffset); for (ulong i = 0; i < entries; ++i) { uint offset; if (!rdr.TryReadUInt32(out offset)) return; uint info; if (!rdr.TryReadUInt32(out info)) return; int addend; if (!rdr.TryReadInt32(out addend)) return; uint sym = info >> 8; string symStr = GetStrPtr(symtab, sym); Debug.Print(" RELA {0:X8} {1,3} {2:X8} {3:X8} {4}", offset, info & 0xFF, sym, addend, symStr); } }
public abstract List<ElfSymbol> LoadSymbolsSection(ElfSection symSection);
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 DynamicSectionRenderer64(ElfLoader64 loader, ElfSection shdr) { this.loader = loader; this.shdr = shdr; }
public override List <ElfSection> LoadSectionHeaders() { // Create the sections. var inames = new List <uint>(); var links = new List <uint>(); var infos = new List <uint>(); var sections = new List <ElfSection>(); var rdr = CreateReader(Header.e_shoff); for (uint i = 0; i < Header.e_shnum; ++i) { var shdr = Elf32_SHdr.Load(rdr); if (shdr == null) { break; } var section = new ElfSection { Number = i, Type = shdr.sh_type, Flags = shdr.sh_flags, Address = Address.Ptr32(shdr.sh_addr), FileOffset = shdr.sh_offset, Size = shdr.sh_size, Alignment = shdr.sh_addralign, EntrySize = shdr.sh_entsize, }; sections.Add(section); inames.Add(shdr.sh_name); links.Add(shdr.sh_link); infos.Add(shdr.sh_info); } // Get section names and crosslink sections. for (int i = 0; i < sections.Count; ++i) { var section = sections[i]; section.Name = ReadSectionName(sections, inames[i]); ElfSection linkSection = null; ElfSection relSection = null; switch (section.Type) { case SectionHeaderType.SHT_REL: case SectionHeaderType.SHT_RELA: linkSection = GetSectionByIndex(sections, links[i]); relSection = GetSectionByIndex(sections, infos[i]); break; case SectionHeaderType.SHT_DYNAMIC: case SectionHeaderType.SHT_HASH: case SectionHeaderType.SHT_SYMTAB: case SectionHeaderType.SHT_DYNSYM: linkSection = GetSectionByIndex(sections, links[i]); break; } section.LinkedSection = linkSection; section.RelocatedSection = relSection; } return(sections); }
public override void RelocateEntry(ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { throw new NotImplementedException(); }
public string GetSymbol64(ElfSection symSection, ulong symbolNo) { var strSection = symSection.LinkedSection; ulong offset = symSection.FileOffset + symbolNo * symSection.EntrySize; var rdr = imgLoader.CreateReader(offset); rdr.TryReadUInt64(out offset); return GetStrPtr(symSection.LinkedSection, (uint)offset); }
public SymtabSegmentRenderer64(ElfLoader64 loader, ElfSection shdr) { this.loader = loader; this.shdr = shdr; }
public override void RelocateEntry(Program program, ElfSymbol symbol, ElfSection referringSection, Elf32_Rela rela) { switch ((PpcRt)(rela.r_info & 0xFF)) { case PpcRt.R_PPC_GLOB_DAT: case PpcRt.R_PPC_COPY: case PpcRt.R_PPC_JMP_SLOT: break; default: throw new NotImplementedException(); } }