[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

llvm-svn: 312409
This commit is contained in:
Alexander Shaposhnikov 2017-09-02 08:19:01 +00:00
parent b4812cf126
commit 64af7a22c4
9 changed files with 148 additions and 3 deletions

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.

View File

@ -0,0 +1,97 @@
REQUIRES: shell
RUN: rm -rf %t
RUN: mkdir %t
RUN: cd %t
RUN: cp %p/../Inputs/dwos_list_from_exec/a.dwo a.dwo
RUN: cp %p/../Inputs/dwos_list_from_exec/b.dwo b.dwo
RUN: cp %p/../Inputs/dwos_list_from_exec/c.dwo c.dwo
RUN: cp %p/../Inputs/dwos_list_from_exec/d.dwo d.dwo
RUN: cp %p/../Inputs/dwos_list_from_exec/e.dwo e.dwo
RUN: cp %p/../Inputs/dwos_list_from_exec/main main
RUN: cp %p/../Inputs/dwos_list_from_exec/libd.so libd.so
RUN: llvm-dwp c.dwo e.dwo -e main -e libd.so -o pkg.dwp
RUN: llvm-dwarfdump pkg.dwp | FileCheck %s
Build commands for the test binaries:
clang++ -Xclang -fdebug-compilation-dir -Xclang "./" -g -O0 -gsplit-dwarf a.cpp b.cpp -o main
clang++ -g -O0 -gsplit-dwarf -c c.cpp -o c.o
clang++ -Xclang -fdebug-compilation-dir -Xclang "./" -g -O0 -gsplit-dwarf -fPIC -shared d.cpp -o libd.so
clang++ -g -O0 -gsplit-dwarf -c e.cpp -o e.o
sources:
a.cpp:
void a() {}
b.cpp:
void b() {}
int main() {
return 0;
}
c.cpp:
void c() {}
d.cpp:
void d() {}
e.cpp:
void e() {}
CHECK-LABEL: .debug_abbrev.dwo contents:
CHECK-LABEL: Abbrev table for offset:
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_subprogram
CHECK-LABEL: Abbrev table for offset:
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_subprogram
CHECK-LABEL: Abbrev table for offset:
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_subprogram
CHECK-LABEL: Abbrev table for offset:
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_subprogram
CHECK-LABEL: Abbrev table for offset:
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_subprogram
CHECK: .debug_info.dwo contents:
CHECK: [[AOFF:0x[0-9a-f]*]]:
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
CHECK: DW_TAG_compile_unit
CHECK: DW_AT_name {{.*}} "c.cpp"
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "c"
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
CHECK: DW_TAG_compile_unit
CHECK: DW_AT_name {{.*}} "e.cpp"
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "e"
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
CHECK: DW_TAG_compile_unit
CHECK: DW_AT_name {{.*}} "a.cpp"
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "a"
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
CHECK: DW_TAG_compile_unit
CHECK: DW_AT_name {{.*}} "b.cpp"
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "b"
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "main"
CHECK-LABEL: Compile Unit: length = {{.*}} version = 0x0004
CHECK: DW_TAG_compile_unit
CHECK: DW_AT_name {{.*}} "d.cpp"
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "d"

View File

@ -17,6 +17,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/MC/MCAsmInfo.h"
@ -36,6 +37,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Options.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
@ -49,9 +51,14 @@ using namespace llvm::object;
using namespace cl;
OptionCategory DwpCategory("Specific Options");
static list<std::string> InputFiles(Positional, OneOrMore,
static list<std::string> InputFiles(Positional, ZeroOrMore,
desc("<input files>"), cat(DwpCategory));
static list<std::string> ExecFilenames(
"e", ZeroOrMore,
desc("Specify the executable/library files to get the list of *.dwo from"),
value_desc("filename"), cat(DwpCategory));
static opt<std::string> OutputFilename(Required, "o",
desc("Specify the output file."),
value_desc("filename"),
@ -113,7 +120,7 @@ struct CompileUnitIdentifiers {
};
static Expected<const char *>
getIndexedString(dwarf::Form Form, DataExtractor InfoData,
getIndexedString(dwarf::Form Form, DataExtractor InfoData,
uint32_t &InfoOffset, StringRef StrOffsets, StringRef Str) {
if (Form == dwarf::DW_FORM_string)
return InfoData.getCStr(&InfoOffset);
@ -463,6 +470,35 @@ buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
" and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
}
static Expected<SmallVector<std::string, 16>>
getDWOFilenames(StringRef ExecFilename) {
auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
if (!ErrOrObj)
return ErrOrObj.takeError();
const ObjectFile &Obj = *ErrOrObj.get().getBinary();
std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
SmallVector<std::string, 16> DWOPaths;
for (const auto &CU : DWARFCtx->compile_units()) {
const DWARFDie &Die = CU->getUnitDIE();
std::string DWOName = dwarf::toString(
Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
if (DWOName.empty())
continue;
std::string DWOCompDir =
dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
if (!DWOCompDir.empty()) {
SmallString<16> DWOPath;
sys::path::append(DWOPath, DWOCompDir, DWOName);
DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
} else {
DWOPaths.push_back(std::move(DWOName));
}
}
return std::move(DWOPaths);
}
static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
const auto &MCOFI = *Out.getContext().getObjectFileInfo();
MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
@ -676,7 +712,19 @@ int main(int argc, char **argv) {
if (!MS)
return error("no object streamer for target " + TripleName, Context);
if (auto Err = write(*MS, InputFiles)) {
std::vector<std::string> DWOFilenames = InputFiles;
for (const auto &ExecFilename : ExecFilenames) {
auto DWOs = getDWOFilenames(ExecFilename);
if (!DWOs) {
logAllUnhandledErrors(DWOs.takeError(), errs(), "error: ");
return 1;
}
DWOFilenames.insert(DWOFilenames.end(),
std::make_move_iterator(DWOs->begin()),
std::make_move_iterator(DWOs->end()));
}
if (auto Err = write(*MS, DWOFilenames)) {
logAllUnhandledErrors(std::move(Err), errs(), "error: ");
return 1;
}