Index: llvm/lib/InterfaceStub/ELFObjHandler.cpp =================================================================== --- llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -502,13 +502,59 @@ return Error::success(); } +/// Returns the in-memory pointer to either the content of DynStr or DynSym +/// from an ElfFile. +/// @param ElfFile Reference to the ELFFile object. +/// @param EntAddr Value of the d_ptr field from .dynamic section. +/// @param Type of the Data. Only accept SHT_STRTAB and SHT_DYNSYM. +template +static Expected getDataFromDynSym(const ELFFile &ElfFile, + uint64_t EntAddr, + unsigned Type) { + using Elf_Shdr_Range = typename ELFT::ShdrRange; + using Elf_Shdr = typename ELFT::Shdr; + + if (Type != ELF::SHT_STRTAB && Type != ELF::SHT_DYNSYM) + return createError("unknown type supplied"); + // Look for DynSym from section headers. + Expected Shdrs = ElfFile.sections(); + if (!Shdrs) + return Shdrs.takeError(); + + if (Shdrs.get().size()) { + for (const Elf_Shdr &Sec : *Shdrs) { + if (Sec.sh_type == ELF::SHT_DYNSYM) { + // If multiple .dynsym are present, use the first one. + // This behavior aligns with llvm::object::ELFFile::getDynSymtabSize() + if (Type == ELF::SHT_STRTAB) { + Expected StrTabRef = + ElfFile.getStringTableForSymtab(Sec, *Shdrs); + if (!StrTabRef) + return StrTabRef.takeError(); + return reinterpret_cast(StrTabRef.get().data()); + } else { + return ElfFile.base() + Sec.sh_offset; + } + } + } + } + // Fallback to use offsets from .dynamic as .dynsym was not found. + Expected SecPtr = ElfFile.toMappedAddr(EntAddr); + if (!SecPtr) { + std::string ErrMsg("when locating "); + ErrMsg += (Type == ELF::SHT_STRTAB ? ".dynstr" : ".dynsym"); + ErrMsg += " section contents"; + return appendToError(SecPtr.takeError(), ErrMsg); + } + return SecPtr.get(); +} + /// Returns a new IFSStub with all members populated from an ELFObjectFile. /// @param ElfObj Source ELFObjectFile. template static Expected> buildStub(const ELFObjectFile &ElfObj) { using Elf_Dyn_Range = typename ELFT::DynRange; - using Elf_Phdr_Range = typename ELFT::PhdrRange; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Sym = typename ELFT::Sym; std::unique_ptr DestStub = std::make_unique(); @@ -519,24 +565,17 @@ return DynTable.takeError(); } - // Fetch program headers. - Expected PHdrs = ElfFile.program_headers(); - if (!PHdrs) { - return PHdrs.takeError(); - } - // Collect relevant .dynamic entries. DynamicEntries DynEnt; if (Error Err = populateDynamic(DynEnt, *DynTable)) return std::move(Err); - // Get pointer to in-memory location of .dynstr section. - Expected DynStrPtr = ElfFile.toMappedAddr(DynEnt.StrTabAddr); - if (!DynStrPtr) - return appendToError(DynStrPtr.takeError(), - "when locating .dynstr section contents"); + Expected EDynStr = + getDataFromDynSym(ElfFile, DynEnt.StrTabAddr, ELF::SHT_STRTAB); + if (!EDynStr) + return EDynStr.takeError(); - StringRef DynStr(reinterpret_cast(DynStrPtr.get()), + StringRef DynStr(reinterpret_cast(EDynStr.get()), DynEnt.StrSize); // Populate Arch from ELF header. @@ -574,7 +613,7 @@ if (*SymCount > 0) { // Get pointer to in-memory location of .dynsym section. Expected DynSymPtr = - ElfFile.toMappedAddr(DynEnt.DynSymAddr); + getDataFromDynSym(ElfFile, DynEnt.DynSymAddr, ELF::SHT_DYNSYM); if (!DynSymPtr) return appendToError(DynSymPtr.takeError(), "when locating .dynsym section contents"); Index: llvm/test/tools/llvm-ifs/ifs-elf-conversion.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-ifs/ifs-elf-conversion.test @@ -0,0 +1,25 @@ +## Test writing stub ELF from IFS and read stub ELF to regenerate IFS. + +# RUN: llvm-ifs --output-elf=%t.elf64l --arch=x86_64 --bitwidth=64 --endianness=little %s + +# RUN: llvm-ifs --output-ifs=- --strip-ifs-target %t.elf64l | FileCheck %s + +--- !ifs-v1 +IfsVersion: 3.0 +NeededLibs: + - libc.so.6 +Symbols: + - { Name: bar, Type: Object, Size: 42 } + - { Name: baz, Type: TLS, Size: 3 } + - { Name: plus, Type: Func } +... + +# CHECK: --- !ifs-v1 +# CHECK-NEXT: IfsVersion: 3.0 +# CHECK-NEXT: NeededLibs: +# CHECK-NEXT: - libc.so.6 +# CHECK-NEXT: Symbols: +# CHECK-NEXT: - { Name: bar, Type: Object, Size: 42 } +# CHECK-NEXT: - { Name: baz, Type: TLS, Size: 3 } +# CHECK-NEXT: - { Name: plus, Type: Func } +# CHECK-NEXT: ...