[llvm] f06e656 - [llvm-readobj] Implement --dependent-libraries for GNU output
James Henderson via llvm-commits
llvm-commits at lists.llvm.org
Fri May 15 07:20:56 PDT 2020
Author: James Henderson
Date: 2020-05-15T15:11:22+01:00
New Revision: f06e6564a1554338ca00a4b9c3acdcffa212c743
URL: https://github.com/llvm/llvm-project/commit/f06e6564a1554338ca00a4b9c3acdcffa212c743
DIFF: https://github.com/llvm/llvm-project/commit/f06e6564a1554338ca00a4b9c3acdcffa212c743.diff
LOG: [llvm-readobj] Implement --dependent-libraries for GNU output
Previously, the option was only implemented for LLVM output. This fixes
https://bugs.llvm.org/show_bug.cgi?id=45695.
At the current time, GNU readelf does not support this option.
Consequently, this patch simply attempts to roughly follow the output
style for similar options like --syms/--notes etc, combined with
--string-dump output.
Reviewed by: MaskRay, grimar
Differential Revision: https://reviews.llvm.org/D79939
Added:
Modified:
llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
llvm/tools/llvm-readobj/ELFDumper.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test b/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
index 724f108e63d7..97f8a7578139 100644
--- a/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
+++ b/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
@@ -5,13 +5,21 @@
## section with multiple entries.
# RUN: yaml2obj --docnum=1 %s -o %t1
-# RUN: llvm-readobj --dependent-libraries %t1 2>&1 | FileCheck %s -DFILE=%t
+# RUN: llvm-readobj --dependent-libraries %t1 | \
+# RUN: FileCheck %s --check-prefix=LLVM --strict-whitespace --match-full-lines
+# RUN: llvm-readelf --dependent-libraries %t1 | \
+# RUN: FileCheck %s --check-prefix=GNU --strict-whitespace --match-full-lines --implicit-check-not="Dependent libraries"
-# CHECK: DependentLibs [
-# CHECK-NEXT: foo
-# CHECK-NEXT: bar
-# CHECK-NEXT: foo
-# CHECK-NEXT: ]
+# LLVM:DependentLibs [
+# LLVM-NEXT: foo
+# LLVM-NEXT: bar
+# LLVM-NEXT: foo
+# LLVM-NEXT:]
+
+# GNU:Dependent libraries section .deplibs at offset 0x40 contains 3 entries:
+# GNU-NEXT: [ 0] foo
+# GNU-NEXT: [ 4] bar
+# GNU-NEXT: [ 8] foo
--- !ELF
FileHeader:
@@ -27,15 +35,36 @@ Sections:
## Now, check how we dump a mix of valid, empty and invalid SHT_LLVM_DEPENDENT_LIBRARIES sections.
# RUN: yaml2obj --docnum=2 %s -o %t2
-# RUN: llvm-readobj --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX -DFILE=%t2
+# RUN: llvm-readobj --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX-LLVM -DFILE=%t2
+# RUN: llvm-readelf --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX-GNU -DFILE=%t2
+
+# MIX-LLVM: DependentLibs [
+# MIX-LLVM-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
+# MIX-LLVM-NEXT: abc
+# MIX-LLVM-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 4 is broken: section [index 4] has a sh_offset (0xffff0000) + sh_size (0x4) that is greater than the file size (0x308)
+# MIX-LLVM-NEXT: bar
+# MIX-LLVM-NEXT: xxx
+# MIX-LLVM-NEXT: baz
+# MIX-LLVM-NEXT: ]
-# MIX: DependentLibs [
-# MIX-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
-# MIX-NEXT: abc
-# MIX-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 4 is broken: section [index 4] has a sh_offset (0xffff0000) + sh_size (0x4) that is greater than the file size (0x2c0)
-# MIX-NEXT: bar
-# MIX-NEXT: xxx
-# MIX-NEXT: ]
+# MIX-GNU: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.nonul at offset 0x40 contains 0 entries:
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.single at offset 0x43 contains 1 entries:
+# MIX-GNU-NEXT: [ 0] abc
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.empty at offset 0x47 contains 0 entries:
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 4 is broken: section [index 4] has a sh_offset (0xffff0000) + sh_size (0x4) that is greater than the file size (0x308)
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.broken.shoffset at offset 0xffff0000 contains 0 entries:
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.multiple at offset 0x4b contains 2 entries:
+# MIX-GNU-NEXT: [ 0] bar
+# MIX-GNU-NEXT: [ 4] xxx
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: warning: '[[FILE]]': cannot get section name of SHT_LLVM_DEPENDENT_LIBRARIES section: a section [index 6] has an invalid sh_name (0x10000) offset which goes past the end of the section name string table
+# MIX-GNU-NEXT: Dependent libraries section <?> at offset 0x53 contains 1 entries:
+# MIX-GNU-NEXT: [ 0] baz
--- !ELF
FileHeader:
@@ -65,8 +94,22 @@ Sections:
- Name: .deplibs.multiple
Type: SHT_LLVM_DEPENDENT_LIBRARIES
Libraries: [ bar, xxx ]
+## Case 6: test we report a warning in GNU mode if the section name can't be read.
+ - ShName: 0x10000
+ Type: SHT_LLVM_DEPENDENT_LIBRARIES
+ Libraries: [ baz ]
-## llvm-readelf doesn't support --dependent-libraries yet.
-# RUN: llvm-readelf --dependent-libraries %t1 2>&1 | FileCheck %s --check-prefix=READELF
+## Show the output when there are no dependent library sections.
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-readobj --dependent-libraries %t3 2>&1 | FileCheck %s --check-prefix=NONE
+# RUN: llvm-readelf --dependent-libraries %t3 2>&1 | FileCheck %s --allow-empty --implicit-check-not={{.}}
-# READELF: printDependentLibs not implemented!
+# NONE: DependentLibs [
+# NONE-NEXT: ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 21ba0f09bb38..a0ac37ac6c31 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -767,6 +767,11 @@ template <typename ELFT> class DumpStyle {
const ELFDumper<ELFT> *dumper() const { return Dumper; }
protected:
+ void printDependentLibsHelper(
+ const ELFFile<ELFT> *Obj,
+ function_ref<void(const Elf_Shdr &)> OnSectionStart,
+ function_ref<void(StringRef, uint64_t)> OnSectionEntry);
+
void reportUniqueWarning(Error Err) const;
StringRef FileName;
@@ -5310,9 +5315,88 @@ void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
OS << "printELFLinkerOptions not implemented!\n";
}
+template <class ELFT>
+void DumpStyle<ELFT>::printDependentLibsHelper(
+ const ELFFile<ELFT> *Obj,
+ function_ref<void(const Elf_Shdr &)> OnSectionStart,
+ function_ref<void(StringRef, uint64_t)> OnLibEntry) {
+ auto Warn = [this](unsigned SecNdx, StringRef Msg) {
+ this->reportUniqueWarning(
+ createError("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
+ Twine(SecNdx) + " is broken: " + Msg));
+ };
+
+ unsigned I = -1;
+ for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
+ ++I;
+ if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
+ continue;
+
+ OnSectionStart(Shdr);
+
+ Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(&Shdr);
+ if (!ContentsOrErr) {
+ Warn(I, toString(ContentsOrErr.takeError()));
+ continue;
+ }
+
+ ArrayRef<uint8_t> Contents = *ContentsOrErr;
+ if (!Contents.empty() && Contents.back() != 0) {
+ Warn(I, "the content is not null-terminated");
+ continue;
+ }
+
+ for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
+ StringRef Lib((const char *)I);
+ OnLibEntry(Lib, I - Contents.begin());
+ I += Lib.size() + 1;
+ }
+ }
+}
+
template <class ELFT>
void GNUStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
- OS << "printDependentLibs not implemented!\n";
+ bool SectionStarted = false;
+ struct NameOffset {
+ StringRef Name;
+ uint64_t Offset;
+ };
+ std::vector<NameOffset> SecEntries;
+ NameOffset Current;
+ auto PrintSection = [&]() {
+ OS << "Dependent libraries section " << Current.Name << " at offset "
+ << format_hex(Current.Offset, 1) << " contains " << SecEntries.size()
+ << " entries:\n";
+ for (NameOffset Entry : SecEntries)
+ OS << " [" << format("%6tx", Entry.Offset) << "] " << Entry.Name
+ << "\n";
+ OS << "\n";
+ SecEntries.clear();
+ };
+
+ auto OnSectionStart = [&](const Elf_Shdr &Shdr) {
+ if (SectionStarted)
+ PrintSection();
+ SectionStarted = true;
+ Current.Offset = Shdr.sh_offset;
+ Expected<StringRef> Name = Obj->getSectionName(&Shdr);
+ if (!Name) {
+ Current.Name = "<?>";
+ this->reportUniqueWarning(
+ createError("cannot get section name of "
+ "SHT_LLVM_DEPENDENT_LIBRARIES section: " +
+ toString(Name.takeError())));
+ } else {
+ Current.Name = *Name;
+ }
+ };
+ auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) {
+ SecEntries.push_back(NameOffset{Lib, Offset});
+ };
+
+ printDependentLibsHelper(Obj, OnSectionStart, OnLibEntry);
+ if (SectionStarted)
+ PrintSection();
}
// Used for printing section names in places where possible errors can be
@@ -6582,37 +6666,9 @@ void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
template <class ELFT>
void LLVMStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
ListScope L(W, "DependentLibs");
-
- auto Warn = [this](unsigned SecNdx, StringRef Msg) {
- this->reportUniqueWarning(
- createError("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
- Twine(SecNdx) + " is broken: " + Msg));
- };
-
- unsigned I = -1;
- for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
- ++I;
- if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
- continue;
-
- Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(&Shdr);
- if (!ContentsOrErr) {
- Warn(I, toString(ContentsOrErr.takeError()));
- continue;
- }
-
- ArrayRef<uint8_t> Contents = *ContentsOrErr;
- if (!Contents.empty() && Contents.back() != 0) {
- Warn(I, "the content is not null-terminated");
- continue;
- }
-
- for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
- StringRef Lib((const char *)I);
- W.printString(Lib);
- I += Lib.size() + 1;
- }
- }
+ printDependentLibsHelper(
+ Obj, [](const Elf_Shdr &) {},
+ [this](StringRef Lib, uint64_t) { W.printString(Lib); });
}
template <class ELFT>
More information about the llvm-commits
mailing list