diff --git a/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp --- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -226,6 +226,7 @@ // Poplulate dynamic table. size_t DynSymIndex = DynTab.Content.addAddr(DT_SYMTAB, 0); size_t DynStrIndex = DynTab.Content.addAddr(DT_STRTAB, 0); + DynTab.Content.addValue(DT_STRSZ, DynSym.Size); for (const std::string &Lib : Stub.NeededLibs) DynTab.Content.addValue(DT_NEEDED, DynStr.Content.getOffset(Lib)); if (Stub.SoName) @@ -523,6 +524,10 @@ if (!PHdrs) { return PHdrs.takeError(); } + // Stub generated from llvm-ifs has an empty list of program headers. + // APIs from llvm ELF object will have issues to determine the in-memory + // addresses of various sections. + bool HasPhdr = PHdrs.get().size() > 0; // Collect relevant .dynamic entries. DynamicEntries DynEnt; @@ -530,13 +535,16 @@ 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"); - - StringRef DynStr(reinterpret_cast(DynStrPtr.get()), - DynEnt.StrSize); + const uint8_t *DynStrPtr = ElfFile.base() + DynEnt.StrTabAddr; + if (HasPhdr) { + Expected EDynStrPtr = + ElfFile.toMappedAddr(DynEnt.StrTabAddr); + if (!EDynStrPtr) + return appendToError(EDynStrPtr.takeError(), + "when locating .dynstr section contents"); + DynStrPtr = EDynStrPtr.get(); + } + StringRef DynStr(reinterpret_cast(DynStrPtr), DynEnt.StrSize); // Populate Arch from ELF header. DestStub->Target.Arch = static_cast(ElfFile.getHeader().e_machine); @@ -572,13 +580,18 @@ return SymCount.takeError(); if (*SymCount > 0) { // Get pointer to in-memory location of .dynsym section. - Expected DynSymPtr = - ElfFile.toMappedAddr(DynEnt.DynSymAddr); - if (!DynSymPtr) - return appendToError(DynSymPtr.takeError(), - "when locating .dynsym section contents"); + const uint8_t *DynSymPtr = ElfFile.base() + DynEnt.DynSymAddr; + if (HasPhdr) { + Expected EDynSymPtr = + ElfFile.toMappedAddr(DynEnt.DynSymAddr); + if (!EDynSymPtr) + return appendToError(EDynSymPtr.takeError(), + "when locating .dynsym section contents"); + DynSymPtr = EDynSymPtr.get(); + } + Elf_Sym_Range DynSyms = ArrayRef( - reinterpret_cast(*DynSymPtr), *SymCount); + reinterpret_cast(DynSymPtr), *SymCount); Error SymReadError = populateSymbols(*DestStub, DynSyms, DynStr); if (SymReadError) return appendToError(std::move(SymReadError), diff --git a/llvm/test/tools/llvm-ifs/ifs-elf-conversion.test b/llvm/test/tools/llvm-ifs/ifs-elf-conversion.test new file mode 100644 --- /dev/null +++ b/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: ... diff --git a/llvm/test/tools/llvm-ifs/write-stub.test b/llvm/test/tools/llvm-ifs/write-stub.test --- a/llvm/test/tools/llvm-ifs/write-stub.test +++ b/llvm/test/tools/llvm-ifs/write-stub.test @@ -142,10 +142,11 @@ # CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: } -# CHECK: DynamicSection [ (4 entries) +# CHECK: DynamicSection [ (5 entries) # CHECK-NEXT: Tag Type Name/Value # CHECK-NEXT: 0x[[DYNTABZ]]0000006 SYMTAB # CHECK-NEXT: 0x[[DYNTABZ]]0000005 STRTAB +# CHECK-NEXT: 0x[[DYNTABZ]]000000A STRSZ # CHECK-NEXT: 0x[[DYNTABZ]]0000001 NEEDED Shared library: [libc.so.6] # CHECK-NEXT: 0x[[DYNTABZ]]0000000 NULL # CHECK-NEXT: ]