Skip to content

Commit cd2c409

Browse files
author
Georgii Rymar
committed
[llvm-readobj] - Implement --dependent-libraries flag.
There is no way to dump SHT_LLVM_DEPENDENT_LIBRARIES sections currently. This patch implements this. The section is described here: https://llvm.org/docs/Extensions.html#sht-llvm-dependent-libraries-section-dependent-libraries Differential revision: https://reviews.llvm.org/D70665
1 parent 6b11760 commit cd2c409

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed

llvm/docs/CommandGuide/llvm-readobj.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ The following options are implemented only for the ELF file format.
152152

153153
Display demangled symbol names in the output.
154154

155+
.. option:: --dependent-libraries
156+
157+
Display the dependent libraries section.
158+
155159
.. option:: --dyn-relocations
156160

157161
Display the dynamic relocation entries.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
## Check that we can use the --dependent-libraries option
2+
## to dump SHT_LLVM_DEPENDENT_LIBRARIES sections.
3+
4+
## Check how we dump a file that has a single valid SHT_LLVM_DEPENDENT_LIBRARIES
5+
## section with multiple entries.
6+
7+
# RUN: yaml2obj --docnum=1 %s -o %t1
8+
# RUN: llvm-readobj --dependent-libraries %t1 2>&1 | FileCheck %s -DFILE=%t
9+
10+
# CHECK: DependentLibs [
11+
# CHECK-NEXT: foo
12+
# CHECK-NEXT: bar
13+
# CHECK-NEXT: foo
14+
# CHECK-NEXT: ]
15+
16+
--- !ELF
17+
FileHeader:
18+
Class: ELFCLASS64
19+
Data: ELFDATA2LSB
20+
Type: ET_REL
21+
Machine: EM_X86_64
22+
Sections:
23+
- Name: .deplibs
24+
Type: SHT_LLVM_DEPENDENT_LIBRARIES
25+
Libraries: [ foo, bar, foo ]
26+
27+
## Now, check how we dump a mix of valid, empty and invalid SHT_LLVM_DEPENDENT_LIBRARIES sections.
28+
29+
# RUN: yaml2obj --docnum=2 %s -o %t2
30+
# RUN: llvm-readobj --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX -DFILE=%t2
31+
32+
# MIX: DependentLibs [
33+
# MIX-EMPTY:
34+
# MIX-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
35+
# MIX-NEXT: abc
36+
# MIX-EMPTY:
37+
# 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)
38+
# MIX-NEXT: bar
39+
# MIX-NEXT: xxx
40+
# MIX-NEXT: ]
41+
42+
--- !ELF
43+
FileHeader:
44+
Class: ELFCLASS64
45+
Data: ELFDATA2LSB
46+
Type: ET_REL
47+
Machine: EM_X86_64
48+
Sections:
49+
## Case 1: test we report a warning for a non-null-terminated section.
50+
- Name: .deplibs.nonul
51+
Type: SHT_LLVM_DEPENDENT_LIBRARIES
52+
Content: "666f6f" ## 'f', 'o', 'o'
53+
## Case 2: test we can dump an entry from a valid section that has a single entry.
54+
- Name: .deplibs.single
55+
Type: SHT_LLVM_DEPENDENT_LIBRARIES
56+
Libraries: [ abc ]
57+
## Case 3: test we do not display warnings for an empty section.
58+
- Name: .deplibs.empty
59+
Type: SHT_LLVM_DEPENDENT_LIBRARIES
60+
Content: ""
61+
## Case 4: test we report a warning when the section offset is invalid.
62+
- Name: .deplibs.broken.shoffset
63+
Type: SHT_LLVM_DEPENDENT_LIBRARIES
64+
Libraries: [ yyy ]
65+
ShOffset: 0xffff0000
66+
## Case 5: test we can dump all entries from a valid section that has more than one entry.
67+
- Name: .deplibs.multiple
68+
Type: SHT_LLVM_DEPENDENT_LIBRARIES
69+
Libraries: [ bar, xxx ]
70+
71+
## llvm-readelf doesn't support --dependent-libraries yet.
72+
# RUN: llvm-readelf --dependent-libraries %t1 2>&1 | FileCheck %s --check-prefix=READELF
73+
74+
# READELF: printDependentLibs not implemented!

llvm/tools/llvm-readobj/ELFDumper.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
193193
void printFileHeaders() override;
194194
void printSectionHeaders() override;
195195
void printRelocations() override;
196+
void printDependentLibs() override;
196197
void printDynamicRelocations() override;
197198
void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
198199
void printHashSymbols() override;
@@ -617,6 +618,7 @@ template <typename ELFT> class DumpStyle {
617618
virtual void printSymbols(const ELFFile<ELFT> *Obj, bool PrintSymbols,
618619
bool PrintDynamicSymbols) = 0;
619620
virtual void printHashSymbols(const ELFFile<ELFT> *Obj) {}
621+
virtual void printDependentLibs(const ELFFile<ELFT> *Obj) = 0;
620622
virtual void printDynamic(const ELFFile<ELFT> *Obj) {}
621623
virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0;
622624
virtual void printSymtabMessage(const ELFFile<ELFT> *Obj, StringRef Name,
@@ -687,6 +689,7 @@ template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> {
687689
void printSymbols(const ELFO *Obj, bool PrintSymbols,
688690
bool PrintDynamicSymbols) override;
689691
void printHashSymbols(const ELFO *Obj) override;
692+
void printDependentLibs(const ELFFile<ELFT> *Obj) override;
690693
void printDynamic(const ELFFile<ELFT> *Obj) override;
691694
void printDynamicRelocations(const ELFO *Obj) override;
692695
void printSymtabMessage(const ELFO *Obj, StringRef Name, size_t Offset,
@@ -807,6 +810,7 @@ template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> {
807810
void printSectionHeaders(const ELFO *Obj) override;
808811
void printSymbols(const ELFO *Obj, bool PrintSymbols,
809812
bool PrintDynamicSymbols) override;
813+
void printDependentLibs(const ELFFile<ELFT> *Obj) override;
810814
void printDynamic(const ELFFile<ELFT> *Obj) override;
811815
void printDynamicRelocations(const ELFO *Obj) override;
812816
void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders,
@@ -2054,6 +2058,10 @@ template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() {
20542058
SymbolVersionNeedSection);
20552059
}
20562060

2061+
template <class ELFT> void ELFDumper<ELFT>::printDependentLibs() {
2062+
ELFDumperStyle->printDependentLibs(ObjF->getELFFile());
2063+
}
2064+
20572065
template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() {
20582066
ELFDumperStyle->printDynamicRelocations(ObjF->getELFFile());
20592067
}
@@ -4873,6 +4881,11 @@ void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
48734881
OS << "printELFLinkerOptions not implemented!\n";
48744882
}
48754883

4884+
template <class ELFT>
4885+
void GNUStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
4886+
OS << "printDependentLibs not implemented!\n";
4887+
}
4888+
48764889
// Used for printing section names in places where possible errors can be
48774890
// ignored.
48784891
static StringRef getSectionName(const SectionRef &Sec) {
@@ -6143,6 +6156,42 @@ void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
61436156
}
61446157
}
61456158

6159+
template <class ELFT>
6160+
void LLVMStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
6161+
ListScope L(W, "DependentLibs");
6162+
6163+
auto Warn = [this](unsigned SecNdx, StringRef Msg) {
6164+
this->reportUniqueWarning(
6165+
createError("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
6166+
Twine(SecNdx) + " is broken: " + Msg));
6167+
};
6168+
6169+
unsigned I = -1;
6170+
for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
6171+
++I;
6172+
if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
6173+
continue;
6174+
6175+
Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(&Shdr);
6176+
if (!ContentsOrErr) {
6177+
Warn(I, toString(ContentsOrErr.takeError()));
6178+
continue;
6179+
}
6180+
6181+
ArrayRef<uint8_t> Contents = *ContentsOrErr;
6182+
if (!Contents.empty() && Contents.back() != 0) {
6183+
Warn(I, "the content is not null-terminated");
6184+
continue;
6185+
}
6186+
6187+
for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
6188+
StringRef Lib((const char *)I);
6189+
W.printString(Lib);
6190+
I += Lib.size() + 1;
6191+
}
6192+
}
6193+
}
6194+
61466195
template <class ELFT>
61476196
void LLVMStyle<ELFT>::printStackSizes(const ELFObjectFile<ELFT> *Obj) {
61486197
ListScope L(W, "StackSizes");

llvm/tools/llvm-readobj/ObjDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ObjDumper {
5353
virtual void printUnwindInfo() = 0;
5454

5555
// Only implemented for ELF at this time.
56+
virtual void printDependentLibs() {}
5657
virtual void printDynamicRelocations() { }
5758
virtual void printDynamicTable() { }
5859
virtual void printNeededLibraries() { }

llvm/tools/llvm-readobj/llvm-readobj.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ namespace opts {
5858
"--section-groups and --elf-hash-histogram."));
5959
cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All));
6060

61+
// --dependent-libraries
62+
cl::opt<bool>
63+
DependentLibraries("dependent-libraries",
64+
cl::desc("Display the dependent libraries section"));
65+
6166
// --headers -e
6267
cl::opt<bool>
6368
Headers("headers",
@@ -489,6 +494,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer,
489494
if (opts::VersionInfo)
490495
Dumper->printVersionInfo();
491496
if (Obj->isELF()) {
497+
if (opts::DependentLibraries)
498+
Dumper->printDependentLibs();
492499
if (opts::ELFLinkerOptions)
493500
Dumper->printELFLinkerOptions();
494501
if (opts::ArchSpecificInfo)

0 commit comments

Comments
 (0)