Skip to content

Commit f06e656

Browse files
committed
[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
1 parent 151ed6a commit f06e656

File tree

2 files changed

+148
-49
lines changed

2 files changed

+148
-49
lines changed

llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@
55
## section with multiple entries.
66

77
# RUN: yaml2obj --docnum=1 %s -o %t1
8-
# RUN: llvm-readobj --dependent-libraries %t1 2>&1 | FileCheck %s -DFILE=%t
8+
# RUN: llvm-readobj --dependent-libraries %t1 | \
9+
# RUN: FileCheck %s --check-prefix=LLVM --strict-whitespace --match-full-lines
10+
# RUN: llvm-readelf --dependent-libraries %t1 | \
11+
# RUN: FileCheck %s --check-prefix=GNU --strict-whitespace --match-full-lines --implicit-check-not="Dependent libraries"
912

10-
# CHECK: DependentLibs [
11-
# CHECK-NEXT: foo
12-
# CHECK-NEXT: bar
13-
# CHECK-NEXT: foo
14-
# CHECK-NEXT: ]
13+
# LLVM:DependentLibs [
14+
# LLVM-NEXT: foo
15+
# LLVM-NEXT: bar
16+
# LLVM-NEXT: foo
17+
# LLVM-NEXT:]
18+
19+
# GNU:Dependent libraries section .deplibs at offset 0x40 contains 3 entries:
20+
# GNU-NEXT: [ 0] foo
21+
# GNU-NEXT: [ 4] bar
22+
# GNU-NEXT: [ 8] foo
1523

1624
--- !ELF
1725
FileHeader:
@@ -27,15 +35,36 @@ Sections:
2735
## Now, check how we dump a mix of valid, empty and invalid SHT_LLVM_DEPENDENT_LIBRARIES sections.
2836

2937
# RUN: yaml2obj --docnum=2 %s -o %t2
30-
# RUN: llvm-readobj --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX -DFILE=%t2
38+
# RUN: llvm-readobj --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX-LLVM -DFILE=%t2
39+
# RUN: llvm-readelf --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX-GNU -DFILE=%t2
40+
41+
# MIX-LLVM: DependentLibs [
42+
# MIX-LLVM-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
43+
# MIX-LLVM-NEXT: abc
44+
# 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)
45+
# MIX-LLVM-NEXT: bar
46+
# MIX-LLVM-NEXT: xxx
47+
# MIX-LLVM-NEXT: baz
48+
# MIX-LLVM-NEXT: ]
3149

32-
# MIX: DependentLibs [
33-
# MIX-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
34-
# MIX-NEXT: abc
35-
# 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)
36-
# MIX-NEXT: bar
37-
# MIX-NEXT: xxx
38-
# MIX-NEXT: ]
50+
# MIX-GNU: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
51+
# MIX-GNU-NEXT: Dependent libraries section .deplibs.nonul at offset 0x40 contains 0 entries:
52+
# MIX-GNU-EMPTY:
53+
# MIX-GNU-NEXT: Dependent libraries section .deplibs.single at offset 0x43 contains 1 entries:
54+
# MIX-GNU-NEXT: [ 0] abc
55+
# MIX-GNU-EMPTY:
56+
# MIX-GNU-NEXT: Dependent libraries section .deplibs.empty at offset 0x47 contains 0 entries:
57+
# MIX-GNU-EMPTY:
58+
# 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)
59+
# MIX-GNU-NEXT: Dependent libraries section .deplibs.broken.shoffset at offset 0xffff0000 contains 0 entries:
60+
# MIX-GNU-EMPTY:
61+
# MIX-GNU-NEXT: Dependent libraries section .deplibs.multiple at offset 0x4b contains 2 entries:
62+
# MIX-GNU-NEXT: [ 0] bar
63+
# MIX-GNU-NEXT: [ 4] xxx
64+
# MIX-GNU-EMPTY:
65+
# 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
66+
# MIX-GNU-NEXT: Dependent libraries section <?> at offset 0x53 contains 1 entries:
67+
# MIX-GNU-NEXT: [ 0] baz
3968

4069
--- !ELF
4170
FileHeader:
@@ -65,8 +94,22 @@ Sections:
6594
- Name: .deplibs.multiple
6695
Type: SHT_LLVM_DEPENDENT_LIBRARIES
6796
Libraries: [ bar, xxx ]
97+
## Case 6: test we report a warning in GNU mode if the section name can't be read.
98+
- ShName: 0x10000
99+
Type: SHT_LLVM_DEPENDENT_LIBRARIES
100+
Libraries: [ baz ]
68101

69-
## llvm-readelf doesn't support --dependent-libraries yet.
70-
# RUN: llvm-readelf --dependent-libraries %t1 2>&1 | FileCheck %s --check-prefix=READELF
102+
## Show the output when there are no dependent library sections.
103+
# RUN: yaml2obj --docnum=3 %s -o %t3
104+
# RUN: llvm-readobj --dependent-libraries %t3 2>&1 | FileCheck %s --check-prefix=NONE
105+
# RUN: llvm-readelf --dependent-libraries %t3 2>&1 | FileCheck %s --allow-empty --implicit-check-not={{.}}
71106

72-
# READELF: printDependentLibs not implemented!
107+
# NONE: DependentLibs [
108+
# NONE-NEXT: ]
109+
110+
--- !ELF
111+
FileHeader:
112+
Class: ELFCLASS64
113+
Data: ELFDATA2LSB
114+
Type: ET_REL
115+
Machine: EM_X86_64

llvm/tools/llvm-readobj/ELFDumper.cpp

Lines changed: 88 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,11 @@ template <typename ELFT> class DumpStyle {
767767
const ELFDumper<ELFT> *dumper() const { return Dumper; }
768768

769769
protected:
770+
void printDependentLibsHelper(
771+
const ELFFile<ELFT> *Obj,
772+
function_ref<void(const Elf_Shdr &)> OnSectionStart,
773+
function_ref<void(StringRef, uint64_t)> OnSectionEntry);
774+
770775
void reportUniqueWarning(Error Err) const;
771776
StringRef FileName;
772777

@@ -5310,9 +5315,88 @@ void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
53105315
OS << "printELFLinkerOptions not implemented!\n";
53115316
}
53125317

5318+
template <class ELFT>
5319+
void DumpStyle<ELFT>::printDependentLibsHelper(
5320+
const ELFFile<ELFT> *Obj,
5321+
function_ref<void(const Elf_Shdr &)> OnSectionStart,
5322+
function_ref<void(StringRef, uint64_t)> OnLibEntry) {
5323+
auto Warn = [this](unsigned SecNdx, StringRef Msg) {
5324+
this->reportUniqueWarning(
5325+
createError("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
5326+
Twine(SecNdx) + " is broken: " + Msg));
5327+
};
5328+
5329+
unsigned I = -1;
5330+
for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
5331+
++I;
5332+
if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
5333+
continue;
5334+
5335+
OnSectionStart(Shdr);
5336+
5337+
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(&Shdr);
5338+
if (!ContentsOrErr) {
5339+
Warn(I, toString(ContentsOrErr.takeError()));
5340+
continue;
5341+
}
5342+
5343+
ArrayRef<uint8_t> Contents = *ContentsOrErr;
5344+
if (!Contents.empty() && Contents.back() != 0) {
5345+
Warn(I, "the content is not null-terminated");
5346+
continue;
5347+
}
5348+
5349+
for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
5350+
StringRef Lib((const char *)I);
5351+
OnLibEntry(Lib, I - Contents.begin());
5352+
I += Lib.size() + 1;
5353+
}
5354+
}
5355+
}
5356+
53135357
template <class ELFT>
53145358
void GNUStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
5315-
OS << "printDependentLibs not implemented!\n";
5359+
bool SectionStarted = false;
5360+
struct NameOffset {
5361+
StringRef Name;
5362+
uint64_t Offset;
5363+
};
5364+
std::vector<NameOffset> SecEntries;
5365+
NameOffset Current;
5366+
auto PrintSection = [&]() {
5367+
OS << "Dependent libraries section " << Current.Name << " at offset "
5368+
<< format_hex(Current.Offset, 1) << " contains " << SecEntries.size()
5369+
<< " entries:\n";
5370+
for (NameOffset Entry : SecEntries)
5371+
OS << " [" << format("%6tx", Entry.Offset) << "] " << Entry.Name
5372+
<< "\n";
5373+
OS << "\n";
5374+
SecEntries.clear();
5375+
};
5376+
5377+
auto OnSectionStart = [&](const Elf_Shdr &Shdr) {
5378+
if (SectionStarted)
5379+
PrintSection();
5380+
SectionStarted = true;
5381+
Current.Offset = Shdr.sh_offset;
5382+
Expected<StringRef> Name = Obj->getSectionName(&Shdr);
5383+
if (!Name) {
5384+
Current.Name = "<?>";
5385+
this->reportUniqueWarning(
5386+
createError("cannot get section name of "
5387+
"SHT_LLVM_DEPENDENT_LIBRARIES section: " +
5388+
toString(Name.takeError())));
5389+
} else {
5390+
Current.Name = *Name;
5391+
}
5392+
};
5393+
auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) {
5394+
SecEntries.push_back(NameOffset{Lib, Offset});
5395+
};
5396+
5397+
printDependentLibsHelper(Obj, OnSectionStart, OnLibEntry);
5398+
if (SectionStarted)
5399+
PrintSection();
53165400
}
53175401

53185402
// Used for printing section names in places where possible errors can be
@@ -6582,37 +6666,9 @@ void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
65826666
template <class ELFT>
65836667
void LLVMStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
65846668
ListScope L(W, "DependentLibs");
6585-
6586-
auto Warn = [this](unsigned SecNdx, StringRef Msg) {
6587-
this->reportUniqueWarning(
6588-
createError("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
6589-
Twine(SecNdx) + " is broken: " + Msg));
6590-
};
6591-
6592-
unsigned I = -1;
6593-
for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
6594-
++I;
6595-
if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
6596-
continue;
6597-
6598-
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(&Shdr);
6599-
if (!ContentsOrErr) {
6600-
Warn(I, toString(ContentsOrErr.takeError()));
6601-
continue;
6602-
}
6603-
6604-
ArrayRef<uint8_t> Contents = *ContentsOrErr;
6605-
if (!Contents.empty() && Contents.back() != 0) {
6606-
Warn(I, "the content is not null-terminated");
6607-
continue;
6608-
}
6609-
6610-
for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
6611-
StringRef Lib((const char *)I);
6612-
W.printString(Lib);
6613-
I += Lib.size() + 1;
6614-
}
6615-
}
6669+
printDependentLibsHelper(
6670+
Obj, [](const Elf_Shdr &) {},
6671+
[this](StringRef Lib, uint64_t) { W.printString(Lib); });
66166672
}
66176673

66186674
template <class ELFT>

0 commit comments

Comments
 (0)