Skip to content

Commit dce71c7

Browse files
[llvm-dwp] Implement -e option
The binutils utility dwp has an option "-e" https://gcc.gnu.org/wiki/DebugFissionDWP to specify an executable/library to get the list of *.dwo files from it. This option is particularly useful when someone runs the tool manually outside of a build system. This diff adds an implementation of "-e" to llvm-dwp. Test plan: make check-all Differential revision: https://reviews.llvm.org/D37371 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312409 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 2ce7ffd commit dce71c7

File tree

9 files changed

+148
-3
lines changed

9 files changed

+148
-3
lines changed
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
REQUIRES: shell
2+
3+
RUN: rm -rf %t
4+
RUN: mkdir %t
5+
RUN: cd %t
6+
RUN: cp %p/../Inputs/dwos_list_from_exec/a.dwo a.dwo
7+
RUN: cp %p/../Inputs/dwos_list_from_exec/b.dwo b.dwo
8+
RUN: cp %p/../Inputs/dwos_list_from_exec/c.dwo c.dwo
9+
RUN: cp %p/../Inputs/dwos_list_from_exec/d.dwo d.dwo
10+
RUN: cp %p/../Inputs/dwos_list_from_exec/e.dwo e.dwo
11+
RUN: cp %p/../Inputs/dwos_list_from_exec/main main
12+
RUN: cp %p/../Inputs/dwos_list_from_exec/libd.so libd.so
13+
RUN: llvm-dwp c.dwo e.dwo -e main -e libd.so -o pkg.dwp
14+
RUN: llvm-dwarfdump pkg.dwp | FileCheck %s
15+
16+
Build commands for the test binaries:
17+
18+
clang++ -Xclang -fdebug-compilation-dir -Xclang "./" -g -O0 -gsplit-dwarf a.cpp b.cpp -o main
19+
clang++ -g -O0 -gsplit-dwarf -c c.cpp -o c.o
20+
clang++ -Xclang -fdebug-compilation-dir -Xclang "./" -g -O0 -gsplit-dwarf -fPIC -shared d.cpp -o libd.so
21+
clang++ -g -O0 -gsplit-dwarf -c e.cpp -o e.o
22+
23+
sources:
24+
a.cpp:
25+
void a() {}
26+
27+
b.cpp:
28+
void b() {}
29+
int main() {
30+
return 0;
31+
}
32+
33+
c.cpp:
34+
void c() {}
35+
36+
d.cpp:
37+
void d() {}
38+
39+
e.cpp:
40+
void e() {}
41+
42+
CHECK-LABEL: .debug_abbrev.dwo contents:
43+
44+
CHECK-LABEL: Abbrev table for offset:
45+
CHECK: DW_TAG_compile_unit
46+
CHECK: DW_TAG_subprogram
47+
48+
CHECK-LABEL: Abbrev table for offset:
49+
CHECK: DW_TAG_compile_unit
50+
CHECK: DW_TAG_subprogram
51+
52+
CHECK-LABEL: Abbrev table for offset:
53+
CHECK: DW_TAG_compile_unit
54+
CHECK: DW_TAG_subprogram
55+
56+
CHECK-LABEL: Abbrev table for offset:
57+
CHECK: DW_TAG_compile_unit
58+
CHECK: DW_TAG_subprogram
59+
60+
CHECK-LABEL: Abbrev table for offset:
61+
CHECK: DW_TAG_compile_unit
62+
CHECK: DW_TAG_subprogram
63+
64+
CHECK: .debug_info.dwo contents:
65+
CHECK: [[AOFF:0x[0-9a-f]*]]:
66+
67+
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
68+
CHECK: DW_TAG_compile_unit
69+
CHECK: DW_AT_name {{.*}} "c.cpp"
70+
CHECK: DW_TAG_subprogram
71+
CHECK: DW_AT_name {{.*}} "c"
72+
73+
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
74+
CHECK: DW_TAG_compile_unit
75+
CHECK: DW_AT_name {{.*}} "e.cpp"
76+
CHECK: DW_TAG_subprogram
77+
CHECK: DW_AT_name {{.*}} "e"
78+
79+
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
80+
CHECK: DW_TAG_compile_unit
81+
CHECK: DW_AT_name {{.*}} "a.cpp"
82+
CHECK: DW_TAG_subprogram
83+
CHECK: DW_AT_name {{.*}} "a"
84+
85+
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
86+
CHECK: DW_TAG_compile_unit
87+
CHECK: DW_AT_name {{.*}} "b.cpp"
88+
CHECK: DW_TAG_subprogram
89+
CHECK: DW_AT_name {{.*}} "b"
90+
CHECK: DW_TAG_subprogram
91+
CHECK: DW_AT_name {{.*}} "main"
92+
93+
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
94+
CHECK: DW_TAG_compile_unit
95+
CHECK: DW_AT_name {{.*}} "d.cpp"
96+
CHECK: DW_TAG_subprogram
97+
CHECK: DW_AT_name {{.*}} "d"

tools/llvm-dwp/llvm-dwp.cpp

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ADT/STLExtras.h"
1818
#include "llvm/ADT/StringSet.h"
1919
#include "llvm/CodeGen/AsmPrinter.h"
20+
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
2021
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
2122
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
2223
#include "llvm/MC/MCAsmInfo.h"
@@ -36,6 +37,7 @@
3637
#include "llvm/Support/MathExtras.h"
3738
#include "llvm/Support/MemoryBuffer.h"
3839
#include "llvm/Support/Options.h"
40+
#include "llvm/Support/Path.h"
3941
#include "llvm/Support/TargetRegistry.h"
4042
#include "llvm/Support/TargetSelect.h"
4143
#include "llvm/Support/raw_ostream.h"
@@ -49,9 +51,14 @@ using namespace llvm::object;
4951
using namespace cl;
5052

5153
OptionCategory DwpCategory("Specific Options");
52-
static list<std::string> InputFiles(Positional, OneOrMore,
54+
static list<std::string> InputFiles(Positional, ZeroOrMore,
5355
desc("<input files>"), cat(DwpCategory));
5456

57+
static list<std::string> ExecFilenames(
58+
"e", ZeroOrMore,
59+
desc("Specify the executable/library files to get the list of *.dwo from"),
60+
value_desc("filename"), cat(DwpCategory));
61+
5562
static opt<std::string> OutputFilename(Required, "o",
5663
desc("Specify the output file."),
5764
value_desc("filename"),
@@ -113,7 +120,7 @@ struct CompileUnitIdentifiers {
113120
};
114121

115122
static Expected<const char *>
116-
getIndexedString(dwarf::Form Form, DataExtractor InfoData,
123+
getIndexedString(dwarf::Form Form, DataExtractor InfoData,
117124
uint32_t &InfoOffset, StringRef StrOffsets, StringRef Str) {
118125
if (Form == dwarf::DW_FORM_string)
119126
return InfoData.getCStr(&InfoOffset);
@@ -463,6 +470,35 @@ buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
463470
" and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
464471
}
465472

473+
static Expected<SmallVector<std::string, 16>>
474+
getDWOFilenames(StringRef ExecFilename) {
475+
auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
476+
if (!ErrOrObj)
477+
return ErrOrObj.takeError();
478+
479+
const ObjectFile &Obj = *ErrOrObj.get().getBinary();
480+
std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
481+
482+
SmallVector<std::string, 16> DWOPaths;
483+
for (const auto &CU : DWARFCtx->compile_units()) {
484+
const DWARFDie &Die = CU->getUnitDIE();
485+
std::string DWOName = dwarf::toString(
486+
Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
487+
if (DWOName.empty())
488+
continue;
489+
std::string DWOCompDir =
490+
dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
491+
if (!DWOCompDir.empty()) {
492+
SmallString<16> DWOPath;
493+
sys::path::append(DWOPath, DWOCompDir, DWOName);
494+
DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
495+
} else {
496+
DWOPaths.push_back(std::move(DWOName));
497+
}
498+
}
499+
return std::move(DWOPaths);
500+
}
501+
466502
static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
467503
const auto &MCOFI = *Out.getContext().getObjectFileInfo();
468504
MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
@@ -676,7 +712,19 @@ int main(int argc, char **argv) {
676712
if (!MS)
677713
return error("no object streamer for target " + TripleName, Context);
678714

679-
if (auto Err = write(*MS, InputFiles)) {
715+
std::vector<std::string> DWOFilenames = InputFiles;
716+
for (const auto &ExecFilename : ExecFilenames) {
717+
auto DWOs = getDWOFilenames(ExecFilename);
718+
if (!DWOs) {
719+
logAllUnhandledErrors(DWOs.takeError(), errs(), "error: ");
720+
return 1;
721+
}
722+
DWOFilenames.insert(DWOFilenames.end(),
723+
std::make_move_iterator(DWOs->begin()),
724+
std::make_move_iterator(DWOs->end()));
725+
}
726+
727+
if (auto Err = write(*MS, DWOFilenames)) {
680728
logAllUnhandledErrors(std::move(Err), errs(), "error: ");
681729
return 1;
682730
}

0 commit comments

Comments
 (0)