private void When_CreateLoader32(bool big_endian) { this.eil = new ElfImageLoader(sc, "foo", this.bytes); this.el32 = new ElfLoader32(eil, eih, this.bytes, big_endian ? ElfLoader.ELFDATA2MSB : ElfLoader.ELFDATA2LSB); el32.ProgramHeaders.AddRange(programHeaders); el32.Sections.AddRange(sections); }
private void ReadMod0(byte[] dcmpTextData, SegmentMap map) { var f = new LeImageReader(dcmpTextData); var mod0 = f.ReadStruct <Mod0>(); if (!map.TryFindSegment(mod0.DynamicOffset, out var dynseg)) { return; } var offset = mod0.DynamicOffset - dynseg.MemoryArea.BaseAddress.ToLinear(); offset += mod0.MagicOffset; var rdr = dynseg.MemoryArea.CreateLeReader((int)offset); var elfHdr = new Elf32_EHdr { e_machine = (ushort)ElfMachine.EM_ARM }; var elfLoader = new ElfLoader32(Services, elfHdr, 0, EndianServices.Little, RawImage); var(deps, entries) = elfLoader.LoadDynamicSegment(rdr); var dynEntries = entries.ToDictionary(e => e.Tag, e => e.UValue); var syms = LoadSymbols(map, dynEntries); LoadRelocations(map, dynEntries, syms); }
private void When_CreateLoader32() { this.eil = new ElfImageLoader(sc, "foo", this.bytes); this.el32 = new ElfLoader32(eil, eih, this.bytes); el32.ProgramHeaders.AddRange(programHeaders); el32.Sections.AddRange(sections); }
protected void DumpRela32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA)) { ElfImageLoader.trace.Inform( "RELA: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); var symbols = loader.Symbols[section.LinkedSection.FileOffset]; var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rela = Elf32_Rela.Read(rdr); ElfImageLoader.trace.Verbose( " off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2}", rela.r_offset, RelocationTypeToString(rela.r_info & 0xFF), symbols[(int)(rela.r_info >> 8)].Name, rela.r_addend, (int)(rela.r_info >> 8)); } } }
private void When_CreateLoader32(bool big_endian) { this.eil = new ElfImageLoader(sc, "foo", this.bytes); this.el32 = new ElfLoader32(sc, eih, 0, big_endian ? EndianServices.Big: EndianServices.Little, this.bytes); this.el32.LoadArchitectureFromHeader(); el32.Segments.AddRange(programHeaders); el32.Sections.AddRange(sections); }
public void El32_SegmentSequence() { var mems = ElfLoader32.AllocateMemoryAreas(new[] { ElfSeg(1000, 10) }); Assert.AreEqual(1, mems.Count); }
public void El32_SegmentSequence_Disjoint() { var mems = ElfLoader32.AllocateMemoryAreas(new[] { ElfSeg(1000, 10), ElfSeg(1020, 10), }); Assert.AreEqual(2, mems.Count); }
public void El32_SegmentSequence_Adjacent() { var mems = ElfLoader32.AllocateMemoryAreas(new[] { ElfSeg(1000, 10), ElfSeg(1010, 20), }); Assert.AreEqual(1, mems.Count); Assert.AreEqual(30, mems.Values[0].Length); }
public void Setup() { this.program = new Program(); this.program.SegmentMap = new SegmentMap(Address.Ptr32(0x1000)); this.program.Architecture = new Reko.Arch.X86.X86ArchitectureFlat32("x86-flat-32"); this.symbols = new Dictionary <int, ElfSymbol>(); var services = new ServiceContainer(); var elfImgLoader = new ElfImageLoader(services, "foo.elf", new byte[0]); this.loader = new ElfLoader32(); loader.Sections.Add(new ElfSection { Name = "" }); // section 0 }
private void Given_Linker(bool big_endian) { BuildObjectFile32(); var eil = new ElfImageLoader(sc, "foo.o", rawBytes); eil.LoadElfIdentification(); var eh = Elf32_EHdr.Load(new BeImageReader(rawBytes, ElfImageLoader.HEADER_OFFSET)); var el = new ElfLoader32(eil, eh, rawBytes, big_endian ? ElfLoader.ELFDATA2MSB : ElfLoader.ELFDATA2LSB); el.LoadSectionHeaders(); el.LoadSymbolsFromSections(); this.linker = new ElfObjectLinker32(el, arch.Object, rawBytes); }
private void Given_Linker() { BuildObjectFile32(); mr.ReplayAll(); var eil = new ElfImageLoader(sc, "foo.o", rawBytes); eil.LoadElfIdentification(); var eh = Elf32_EHdr.Load(new BeImageReader(rawBytes, ElfImageLoader.HEADER_OFFSET)); var el = new ElfLoader32(eil, eh, rawBytes); el.LoadSectionHeaders(); el.LoadSymbols(); this.linker = new ElfObjectLinker32(el, arch, rawBytes); }
public void Eol32_CommonSymbol() { Given_SegName(".text"); Given_SegName(".data"); Given_Section(".text", SectionHeaderType.SHT_PROGBITS, ElfLoader.SHF_ALLOC | ElfLoader.SHF_EXECINSTR, new byte[] { 0xc3 }); Given_Section(".data", SectionHeaderType.SHT_PROGBITS, ElfLoader.SHF_ALLOC | ElfLoader.SHF_WRITE, new byte[] { 0x01, 0x02, 0x03, 0x04 }); Given_Symbol( "shared_global", 8, 0x4000, ElfLoader32.ELF32_ST_INFO(0, ElfSymbolType.STT_OBJECT), 0xFFF2); Given_Linker(false); linker.ComputeSegmentSizes(); Assert.AreEqual(0x4000, linker.Segments[3].p_pmemsz); }
private void Given_Linker(bool big_endian) { BuildObjectFile32(big_endian); var eil = new ElfImageLoader(sc, ImageLocation.FromUri("file:foo.o"), rawBytes); eil.LoadElfIdentification(); var rdr = big_endian ? new BeImageReader(rawBytes, ElfImageLoader.HEADER_OFFSET) : (EndianImageReader) new LeImageReader(rawBytes, ElfImageLoader.HEADER_OFFSET); var eh = Elf32_EHdr.Load(rdr); var el = new ElfLoader32(sc, eh, 0, big_endian ? EndianServices.Big: EndianServices.Little, rawBytes); el.Sections.AddRange(el.LoadSectionHeaders()); el.LoadSymbolsFromSections(); this.linker = new ElfObjectLinker32(el, arch.Object, rawBytes); }
public void Eol32_UnresolvedExternals_OwnSegment() { Given_SegName(".text"); Given_SegName(".data"); Given_Section(".text", SectionHeaderType.SHT_PROGBITS, ElfLoader.SHF_ALLOC | ElfLoader.SHF_EXECINSTR, new byte[] { 0xc3 }); Given_Section(".data", SectionHeaderType.SHT_PROGBITS, ElfLoader.SHF_ALLOC | ElfLoader.SHF_WRITE, new byte[] { 0x01, 0x02, 0x03, 0x04 }); Given_Symbol( "unresolved_global1", 0, 0, ElfLoader32.ELF32_ST_INFO(0, ElfSymbolType.STT_NOTYPE), 0); Given_Symbol( "unresolved_global2", 0, 0, ElfLoader32.ELF32_ST_INFO(0, ElfSymbolType.STT_NOTYPE), 0); Given_Linker(false); linker.ComputeSegmentSizes(); Assert.AreEqual(0x0030, linker.Segments[0].p_pmemsz, "Each external symbol is simulated with 16 bytes and added to executable section"); }
protected void DumpRel32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_REL)) { Debug.Print("REL: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); var symbols = loader.Symbols[section.LinkedSection.FileOffset]; var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rel = Elf32_Rel.Read(rdr); Debug.Print(" off:{0:X8} type:{1,-16} {3,3} {2}", rel.r_offset, RelocationTypeToString(rel.r_info & 0xFF), symbols[(int)(rel.r_info >> 8)].Name, (int)(rel.r_info >> 8)); } } }
protected void DumpRel32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_REL)) { ElfImageLoader.trace.Inform("REL: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); loader.Symbols.TryGetValue(section.LinkedSection.FileOffset, out var symbols); var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rel = Elf32_Rel.Read(rdr); ElfImageLoader.trace.Verbose( " off:{0:X8} type:{1,-16} {3,3} {2}", rel.r_offset, RelocationTypeToString(rel.r_info & 0xFF), symbols != null ? symbols[(int)(rel.r_info >> 8)].Name : "<nosym>", (int)(rel.r_info >> 8)); } } }
protected void DumpRela32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA)) { Debug.Print("RELA: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); var symbols = loader.Symbols[section.LinkedSection]; var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rela = Elf32_Rela.Read(rdr); Debug.Print(" off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2}", rela.r_offset, RelocationTypeToString(rela.r_info & 0xFF), symbols[(int)(rela.r_info >> 8)].Name, rela.r_addend, (int)(rela.r_info >> 8)); } } }
public Avr32Relocator(ElfLoader32 elfLoader, SortedList <Address, ImageSymbol> imageSymbols) : base(elfLoader, imageSymbols) { this.elfLoader = elfLoader; }
public ElfRelocator32(ElfLoader32 loader, SortedList <Address, ImageSymbol> imageSymbols) : base(imageSymbols) { this.loader = loader; this.imageSymbols = imageSymbols; }
public M68kRelocator(ElfLoader32 loader) : base(loader) { }
public void RelocateOld(Program program) { uint nextFakeLibAddr = ~1u; // See R_386_PC32 below; -1 sometimes used for main for (int i = 1; i < loader.Sections.Count; ++i) { var ps = loader.Sections[i]; if (ps.Type == SectionHeaderType.SHT_REL) { // A section such as .rel.dyn or .rel.plt (without an addend field). // Each entry has 2 words: r_offset and r_info. The r_offset is just the offset from the beginning // of the section (section given by the section header's sh_info) to the word to be modified. // r_info has the type in the bottom byte, and a symbol table index in the top 3 bytes. // A symbol table offset of 0 (STN_UNDEF) means use value 0. The symbol table involved comes from // the section header's sh_link field. var pReloc = loader.CreateReader(ps.FileOffset); ulong size = ps.Size; // NOTE: the r_offset is different for .o files (ET_REL in the e_type header field) than for exe's // and shared objects! uint destNatOrigin = 0; uint destHostOrigin = 0; if (loader.Header.e_type == ElfImageLoader.ET_REL) { var destSection = loader.Sections[i].RelocatedSection; destNatOrigin = destSection.Address.ToUInt32(); destHostOrigin = (uint)destSection.FileOffset; } var symSection = loader.Sections[i].LinkedSection; // associated symbol table var strSection = symSection.LinkedSection; // Section index for the string section assoc with this var pStrSection = strSection.FileOffset; var symOrigin = symSection.FileOffset; var relocR = loader.CreateReader(0); var relocW = loader.CreateWriter(0); for (uint u = 0; u < size; u += 2 * sizeof(uint)) { uint r_offset = pReloc.ReadUInt32(); uint info = pReloc.ReadUInt32(); byte relType = (byte)info; uint symTabIndex = info >> 8; uint pRelWord; // Pointer to the word to be relocated if (loader.Header.e_type == ElfImageLoader.ET_REL) { pRelWord = destHostOrigin + r_offset; } else { if (r_offset == 0) { continue; } var destSec = loader.GetSectionInfoByAddr(r_offset); pRelWord = ~0u; // destSec.uHostAddr - destSec.uNativeAddr + r_offset; destNatOrigin = 0; } uint A, S = 0, P; int nsec; var sym = Elf32_Sym.Load(loader.CreateReader(symOrigin + symTabIndex * Elf32_Sym.Size)); switch (relType) { case 0: // R_386_NONE: just ignore (common) break; case 1: // R_386_32: S + A // Read the symTabIndex'th symbol. S = sym.st_value; if (loader.Header.e_type == ElfImageLoader.ET_REL) { nsec = sym.st_shndx; if (nsec >= 0 && nsec < loader.Sections.Count) { S += loader.Sections[nsec].Address.ToUInt32(); } } A = relocR.ReadUInt32(pRelWord); relocW.WriteUInt32(pRelWord, S + A); break; case 2: // R_386_PC32: S + A - P if (ElfLoader32.ELF32_ST_TYPE(sym.st_info) == ElfLoader.STT_SECTION) { nsec = sym.st_shndx; if (nsec >= 0 && nsec < loader.Sections.Count) { S = loader.Sections[nsec].Address.ToUInt32(); } } else { S = sym.st_value; if (S == 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 uint nameOffset = sym.st_name; string pName = loader.ReadAsciiString(pStrSection + nameOffset); // this is too slow, I'm just going to assume it is 0 //S = GetAddressByName(pName); //if (S == (e_type == E_REL ? 0x8000000 : 0)) { S = nextFakeLibAddr--; // Allocate a new fake address loader.AddSymbol(S, pName); //} } else if (loader.Header.e_type == ElfImageLoader.ET_REL) { nsec = sym.st_shndx; if (nsec >= 0 && nsec < loader.Sections.Count) { S += loader.Sections[nsec].Address.ToUInt32(); } } } A = relocR.ReadUInt32(pRelWord); P = destNatOrigin + r_offset; relocW.WriteUInt32(pRelWord, S + A - P); break; case 6: // 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. S = sym.st_value; relocW.WriteUInt32(pRelWord, S); break; case 7: case 8: // R_386_RELATIVE break; // No need to do anything with these, if a shared object default: throw new NotSupportedException("Relocation type " + (int)relType + " not handled yet"); } } } } }
public MipsRelocator(ElfLoader32 loader, SortedList <Address, ImageSymbol> imageSymbols) : base(loader, imageSymbols) { archMips16e = null !; }
public SparcRelocator(ElfLoader32 loader) : base(loader) { this.loader = loader; }
public ArmRelocator(ElfLoader32 loader, SortedList <Address, ImageSymbol> imageSymbols) : base(loader, imageSymbols) { this.currentTlsSlotOffset = 0x0000000; }
public XtensaRelocator(ElfLoader32 loader) : base(loader) { }
public MipsRelocator(ElfLoader32 elfLoader) : base(elfLoader) { this.elfLoader = elfLoader; }
public Sparc32Relocator(ElfLoader32 loader, SortedList <Address, ImageSymbol> imageSymbols) : base(loader, imageSymbols) { importReferences = null !; }
public SuperHRelocator(ElfLoader32 loader) : base(loader) { }
public ElfRelocator32(ElfLoader32 loader) { this.loader = loader; }
public XtensaRelocator(ElfLoader32 elfLoader32) { this.elfLoader32 = elfLoader32; }
public ArmRelocator(ElfLoader32 loader) : base(loader) { this.loader = loader; }
public M68kRelocator(ElfLoader32 loader, SortedList <Address, ImageSymbol> imageSymbols) : base(loader, imageSymbols) { }
public Nios2Relocator(ElfLoader32 elfLoader32, SortedList <Address, ImageSymbol> imageSymbols) : base(elfLoader32, imageSymbols) { }