diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -14,13 +14,16 @@ #define LLVM_OBJECT_ELF_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFTypes.h" #include "llvm/Object/Error.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" #include #include #include @@ -182,6 +185,7 @@ private: StringRef Buf; std::vector FakeSections; + SmallString<0> FakeSectionStrings; ELFFile(StringRef Object); @@ -649,7 +653,7 @@ } if (!Index) // no section string table. - return ""; + return FakeSectionStrings; if (Index >= Sections.size()) return createError("section header string table index " + Twine(Index) + " does not exist"); @@ -770,17 +774,27 @@ if (!PhdrsOrErr) return; + size_t Idx = 0; + StringTableBuilder StrTab(StringTableBuilder::ELF); for (auto Phdr : *PhdrsOrErr) { - if (!(Phdr.p_type & ELF::PT_LOAD) || !(Phdr.p_flags & ELF::PF_X)) + if ((Phdr.p_type != ELF::PT_LOAD) || !(Phdr.p_flags & ELF::PF_X)) { + ++Idx; continue; + } Elf_Shdr FakeShdr = {}; FakeShdr.sh_type = ELF::SHT_PROGBITS; FakeShdr.sh_flags = ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; FakeShdr.sh_addr = Phdr.p_vaddr; FakeShdr.sh_size = Phdr.p_memsz; FakeShdr.sh_offset = Phdr.p_offset; + // Create a section name based on the p_type and index. + FakeShdr.sh_name = StrTab.add("PT_LOAD#" + std::to_string(Idx)); FakeSections.push_back(FakeShdr); + ++Idx; } + StrTab.finalizeInOrder(); + raw_svector_ostream Strs(FakeSectionStrings); + StrTab.write(Strs); } template diff --git a/llvm/test/Object/objdump-no-sectionheaders.test b/llvm/test/Object/objdump-no-sectionheaders.test --- a/llvm/test/Object/objdump-no-sectionheaders.test +++ b/llvm/test/Object/objdump-no-sectionheaders.test @@ -1,8 +1,38 @@ -; RUN: llvm-objdump -h %p/Inputs/no-sections.elf-x86-64 \ -; RUN: | FileCheck %s +## This test checks llvm-objdump -h can handle ELF files without section info. +## Only PT_LOAD program with PF_X flag will be display corresponding fake sections. -; CHECK: Sections: -; CHECK-NEXT: Idx Name Size VMA Type -; CHECK-NEXT: 0 000006ec 0000000000400000 TEXT -; CHECK-NEXT: 1 00000000 0000000000000000 TEXT -; CHECK-NOT: {{.}} +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump -h %t | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size VMA Type +# CHECK-NEXT: 0 PT_LOAD#1 00012300 0000000000100000 TEXT +# CHECK-NEXT: 1 PT_LOAD#3 00098700 0000000000300000 TEXT +# CHECK-NOT: {{.}} + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_CORE + Machine: EM_X86_64 +Sections: + - Type: SectionHeaderTable + NoHeaders: true +ProgramHeaders: + - Type: PT_PHDR + Flags: [ PF_X ] + VAddr: 0x100000 + MemSize: 0x1000 + - Type: PT_LOAD + Flags: [ PF_X ] + VAddr: 0x100000 + MemSize: 0x12300 + - Type: PT_LOAD + Flags: [ PF_R ] + VAddr: 0x200000 + MemSize: 0x1000 + - Type: PT_LOAD + Flags: [ PF_R, PF_X ] + VAddr: 0x300000 + MemSize: 0x98700 diff --git a/llvm/test/tools/llvm-objdump/X86/disassemble-no-section.test b/llvm/test/tools/llvm-objdump/X86/disassemble-no-section.test --- a/llvm/test/tools/llvm-objdump/X86/disassemble-no-section.test +++ b/llvm/test/tools/llvm-objdump/X86/disassemble-no-section.test @@ -6,9 +6,9 @@ # RUN: yaml2obj %s -o %t # RUN: llvm-objdump -d %t | FileCheck %s -# CHECK: Disassembly of section : +# CHECK: Disassembly of section PT_LOAD#0: # CHECK-EMPTY: -# CHECK-NEXT: <>: +# CHECK-NEXT: : # CHECK-NEXT: 55 pushq %rbp # CHECK-NEXT: 48 89 e5 movq %rsp, %rbp # CHECK-NEXT: 0f 1f 40 00 nopl (%rax) @@ -22,9 +22,9 @@ # RANGE: no section overlaps the range # RANGE-EMPTY: -# RANGE-NEXT: Disassembly of section : +# RANGE-NEXT: Disassembly of section PT_LOAD#0: # RANGE-EMPTY: -# RANGE-NEXT: <>: +# RANGE-NEXT: : # RANGE-NEXT: 55 pushq %rbp # RANGE-NEXT: 48 89 e5 movq %rsp, %rbp # RANGE-EMPTY: diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2026,6 +2026,9 @@ } void objdump::printSectionHeaders(ObjectFile &Obj) { + if (Obj.isELF() && Obj.sections().empty()) + createFakeELFSections(Obj); + size_t NameWidth = getMaxSectionNameWidth(Obj); size_t AddressWidth = 2 * Obj.getBytesInAddress(); bool HasLMAColumn = shouldDisplayLMA(Obj); @@ -2038,9 +2041,6 @@ outs() << "Idx " << left_justify("Name", NameWidth) << " Size " << left_justify("VMA", AddressWidth) << " Type\n"; - if (Obj.isELF() && Obj.sections().empty()) - createFakeELFSections(Obj); - uint64_t Idx; for (const SectionRef &Section : ToolSectionFilter(Obj, &Idx)) { StringRef Name = unwrapOrError(Section.getName(), Obj.getFileName());