Skip to content

Commit 1cf23e1

Browse files
committedJan 11, 2019
Introduce SymbolFileBreakpad and use it to fill symtab
Summary: This commit adds the glue code necessary to integrate the SymbolFileBreakpad into the plugin system. Most of the methods are stubbed out. The only method implemented method is AddSymbols, which parses the PUBLIC "section" of the breakpad "object file", and fills out the Module's symtab. To enable testing this, I've made two additional changes: - dump Symtab from the SymbolVendor class. The symtab was already being dumped as a part of the object file dump, but that happened before symbol vendor kicked in, so it did not reflect any symbols added there. - add ability to explicitly specify the external symbol file in lldb-test (so that the object file could be linked with the breakpad symbol file). To make things simpler, I've changed lldb-test from consuming multiple inputs (and dumping their symbols) to having it just process a single file per invocation. This was not a problem since everyone was using it that way already. Reviewers: clayborg, zturner, lemo, markmentovai, amccarth Subscribers: mgorny, lldb-commits Differential Revision: https://reviews.llvm.org/D56173 llvm-svn: 350924
1 parent 43ddbc0 commit 1cf23e1

File tree

11 files changed

+482
-23
lines changed

11 files changed

+482
-23
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# A very basic ELF file to serve as a recipient of breakpad info
2+
3+
--- !ELF
4+
FileHeader:
5+
Class: ELFCLASS64
6+
Data: ELFDATA2LSB
7+
Type: ET_EXEC
8+
Machine: EM_X86_64
9+
Entry: 0x00000000004000D0
10+
Sections:
11+
- Name: .text1
12+
Type: SHT_PROGBITS
13+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
14+
Address: 0x0000000000400000
15+
AddressAlign: 0x0000000000001000
16+
Size: 0xb0
17+
- Name: .text2
18+
Type: SHT_PROGBITS
19+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
20+
Address: 0x00000000004000B0
21+
AddressAlign: 0x0000000000000010
22+
Size: 0x42
23+
Symbols:
24+
DynamicSymbols:
25+
ProgramHeaders:
26+
- Type: PT_LOAD
27+
Flags: [ PF_X, PF_R ]
28+
VAddr: 0x400000
29+
Align: 0x1000
30+
Sections:
31+
- Section: .text1
32+
- Section: .text2
33+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
MODULE Linux x86_64 761550E08086333960A9074A9CE2895C0 a.out
2+
INFO CODE_ID E05015768680393360A9074A9CE2895C
3+
FILE 0 /tmp/a.c
4+
PUBLIC b0 0 f1
5+
PUBLIC m c0 0 f2
6+
PUBLIC d0 0 _start
7+
PUBLIC ff 0 _out_of_range_ignored
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# RUN: yaml2obj %S/Inputs/basic-elf.yaml > %T/symtab.out
2+
# RUN: %lldb %T/symtab.out -o "target symbols add -s symtab.out %S/Inputs/symtab.syms" \
3+
# RUN: -s %s | FileCheck %s
4+
5+
# CHECK-LABEL: (lldb) image dump symtab symtab.out
6+
# CHECK: Symtab, file = {{.*}}symtab.out, num_symbols = 3:
7+
# CHECK: Index UserID DSX Type File Address/Value Load Address Size Flags Name
8+
# CHECK: [ 0] 0 X Code 0x00000000004000b0 0x0000000000000010 0x00000000 f1
9+
# CHECK: [ 1] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2
10+
# CHECK: [ 2] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start
11+
12+
# CHECK-LABEL: (lldb) image lookup -a 0x4000b0 -v
13+
# CHECK: Address: symtab.out[0x00000000004000b0] (symtab.out.PT_LOAD[0]..text2 + 0)
14+
# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000b0-0x00000000004000c0), name="f1"
15+
16+
# CHECK-LABEL: (lldb) image lookup -n f2 -v
17+
# CHECK: Address: symtab.out[0x00000000004000c0] (symtab.out.PT_LOAD[0]..text2 + 16)
18+
# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000c0-0x00000000004000d0), name="f2"
19+
20+
image dump symtab symtab.out
21+
image lookup -a 0x4000b0 -v
22+
image lookup -n f2 -v
23+
exit

‎lldb/source/API/SystemInitializerFull.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
#include "Plugins/Process/mach-core/ProcessMachCore.h"
8484
#include "Plugins/Process/minidump/ProcessMinidump.h"
8585
#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
86+
#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
8687
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
8788
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
8889
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
@@ -343,6 +344,7 @@ SystemInitializerFull::Initialize(const InitializerOptions &options) {
343344
MainThreadCheckerRuntime::Initialize();
344345

345346
SymbolVendorELF::Initialize();
347+
breakpad::SymbolFileBreakpad::Initialize();
346348
SymbolFileDWARF::Initialize();
347349
SymbolFilePDB::Initialize();
348350
SymbolFileSymtab::Initialize();
@@ -471,6 +473,7 @@ void SystemInitializerFull::Terminate() {
471473
UndefinedBehaviorSanitizerRuntime::Terminate();
472474
MainThreadCheckerRuntime::Terminate();
473475
SymbolVendorELF::Terminate();
476+
breakpad::SymbolFileBreakpad::Terminate();
474477
SymbolFileDWARF::Terminate();
475478
SymbolFilePDB::Terminate();
476479
SymbolFileSymtab::Terminate();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_lldb_library(lldbPluginSymbolFileBreakpad PLUGIN
2+
SymbolFileBreakpad.cpp
3+
4+
LINK_LIBS
5+
lldbCore
6+
lldbHost
7+
lldbSymbol
8+
lldbUtility
9+
lldbPluginObjectFileBreakpad
10+
LINK_COMPONENTS
11+
Support
12+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
//===-- SymbolFileBreakpad.cpp ----------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
11+
#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
12+
#include "lldb/Core/Module.h"
13+
#include "lldb/Core/PluginManager.h"
14+
#include "lldb/Core/Section.h"
15+
#include "lldb/Host/FileSystem.h"
16+
#include "lldb/Symbol/ObjectFile.h"
17+
#include "lldb/Symbol/TypeMap.h"
18+
#include "lldb/Utility/Log.h"
19+
#include "llvm/ADT/StringExtras.h"
20+
21+
using namespace lldb;
22+
using namespace lldb_private;
23+
using namespace lldb_private::breakpad;
24+
25+
namespace {
26+
class LineIterator {
27+
public:
28+
// begin iterator for sections of given type
29+
LineIterator(ObjectFile &obj, ConstString section_type)
30+
: m_obj(&obj), m_section_type(section_type), m_next_section_idx(0) {
31+
++*this;
32+
}
33+
34+
// end iterator
35+
explicit LineIterator(ObjectFile &obj)
36+
: m_obj(&obj),
37+
m_next_section_idx(m_obj->GetSectionList()->GetNumSections(0)) {}
38+
39+
friend bool operator!=(const LineIterator &lhs, const LineIterator &rhs) {
40+
assert(lhs.m_obj == rhs.m_obj);
41+
if (lhs.m_next_section_idx != rhs.m_next_section_idx)
42+
return true;
43+
if (lhs.m_next_text.data() != rhs.m_next_text.data())
44+
return true;
45+
assert(lhs.m_current_text == rhs.m_current_text);
46+
assert(rhs.m_next_text == rhs.m_next_text);
47+
return false;
48+
}
49+
50+
const LineIterator &operator++();
51+
llvm::StringRef operator*() const { return m_current_text; }
52+
53+
private:
54+
ObjectFile *m_obj;
55+
ConstString m_section_type;
56+
uint32_t m_next_section_idx;
57+
llvm::StringRef m_current_text;
58+
llvm::StringRef m_next_text;
59+
};
60+
} // namespace
61+
62+
const LineIterator &LineIterator::operator++() {
63+
const SectionList &list = *m_obj->GetSectionList();
64+
size_t num_sections = list.GetNumSections(0);
65+
while (m_next_text.empty() && m_next_section_idx < num_sections) {
66+
Section &sect = *list.GetSectionAtIndex(m_next_section_idx++);
67+
if (sect.GetName() != m_section_type)
68+
continue;
69+
DataExtractor data;
70+
m_obj->ReadSectionData(&sect, data);
71+
m_next_text =
72+
llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
73+
data.GetByteSize());
74+
}
75+
std::tie(m_current_text, m_next_text) = m_next_text.split('\n');
76+
return *this;
77+
}
78+
79+
static llvm::iterator_range<LineIterator> lines(ObjectFile &obj,
80+
ConstString section_type) {
81+
return llvm::make_range(LineIterator(obj, section_type), LineIterator(obj));
82+
}
83+
84+
void SymbolFileBreakpad::Initialize() {
85+
PluginManager::RegisterPlugin(GetPluginNameStatic(),
86+
GetPluginDescriptionStatic(), CreateInstance,
87+
DebuggerInitialize);
88+
}
89+
90+
void SymbolFileBreakpad::Terminate() {
91+
PluginManager::UnregisterPlugin(CreateInstance);
92+
}
93+
94+
ConstString SymbolFileBreakpad::GetPluginNameStatic() {
95+
static ConstString g_name("breakpad");
96+
return g_name;
97+
}
98+
99+
uint32_t SymbolFileBreakpad::CalculateAbilities() {
100+
if (!m_obj_file)
101+
return 0;
102+
if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic())
103+
return 0;
104+
105+
return CompileUnits | Functions;
106+
}
107+
108+
uint32_t SymbolFileBreakpad::GetNumCompileUnits() {
109+
// TODO
110+
return 0;
111+
}
112+
113+
CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {
114+
// TODO
115+
return nullptr;
116+
}
117+
118+
size_t SymbolFileBreakpad::ParseCompileUnitFunctions(const SymbolContext &sc) {
119+
// TODO
120+
return 0;
121+
}
122+
123+
bool SymbolFileBreakpad::ParseCompileUnitLineTable(const SymbolContext &sc) {
124+
// TODO
125+
return 0;
126+
}
127+
128+
uint32_t
129+
SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
130+
SymbolContextItem resolve_scope,
131+
SymbolContext &sc) {
132+
// TODO
133+
return 0;
134+
}
135+
136+
uint32_t SymbolFileBreakpad::FindFunctions(
137+
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
138+
FunctionNameType name_type_mask, bool include_inlines, bool append,
139+
SymbolContextList &sc_list) {
140+
// TODO
141+
if (!append)
142+
sc_list.Clear();
143+
return sc_list.GetSize();
144+
}
145+
146+
uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression &regex,
147+
bool include_inlines, bool append,
148+
SymbolContextList &sc_list) {
149+
// TODO
150+
if (!append)
151+
sc_list.Clear();
152+
return sc_list.GetSize();
153+
}
154+
155+
uint32_t SymbolFileBreakpad::FindTypes(
156+
const SymbolContext &sc, const ConstString &name,
157+
const CompilerDeclContext *parent_decl_ctx, bool append,
158+
uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
159+
TypeMap &types) {
160+
if (!append)
161+
types.Clear();
162+
return types.GetSize();
163+
}
164+
165+
size_t
166+
SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context,
167+
bool append, TypeMap &types) {
168+
if (!append)
169+
types.Clear();
170+
return types.GetSize();
171+
}
172+
173+
void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
174+
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
175+
Module &module = *m_obj_file->GetModule();
176+
addr_t base = module.GetObjectFile()->GetBaseAddress().GetFileAddress();
177+
if (base == LLDB_INVALID_ADDRESS) {
178+
LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping "
179+
"symtab population.");
180+
return;
181+
}
182+
183+
const SectionList &list = *module.GetSectionList();
184+
for (llvm::StringRef line : lines(*m_obj_file, ConstString("PUBLIC"))) {
185+
// PUBLIC [m] address param_size name
186+
// skip PUBLIC keyword
187+
line = getToken(line).second;
188+
llvm::StringRef token;
189+
std::tie(token, line) = getToken(line);
190+
if (token == "m")
191+
std::tie(token, line) = getToken(line);
192+
193+
addr_t address;
194+
if (!to_integer(token, address, 16))
195+
continue;
196+
address += base;
197+
198+
// skip param_size
199+
line = getToken(line).second;
200+
201+
llvm::StringRef name = line.trim();
202+
203+
SectionSP section_sp = list.FindSectionContainingFileAddress(address);
204+
if (!section_sp) {
205+
LLDB_LOG(log,
206+
"Ignoring symbol {0}, whose address ({1}) is outside of the "
207+
"object file. Mismatched symbol file?",
208+
name, address);
209+
continue;
210+
}
211+
212+
symtab.AddSymbol(Symbol(
213+
/*symID*/ 0, Mangled(name, /*is_mangled*/ false), eSymbolTypeCode,
214+
/*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false,
215+
/*is_artificial*/ false,
216+
AddressRange(section_sp, address - section_sp->GetFileAddress(), 0),
217+
/*size_is_valid*/ 0, /*contains_linker_annotations*/ false,
218+
/*flags*/ 0));
219+
}
220+
221+
// TODO: Process FUNC records as well.
222+
223+
symtab.CalculateSymbolSizes();
224+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
//===-- SymbolFileBreakpad.h ------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
11+
#define LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
12+
13+
#include "lldb/Symbol/SymbolFile.h"
14+
15+
namespace lldb_private {
16+
17+
namespace breakpad {
18+
19+
class SymbolFileBreakpad : public SymbolFile {
20+
public:
21+
//------------------------------------------------------------------
22+
// Static Functions
23+
//------------------------------------------------------------------
24+
static void Initialize();
25+
static void Terminate();
26+
static void DebuggerInitialize(Debugger &debugger) {}
27+
static ConstString GetPluginNameStatic();
28+
29+
static const char *GetPluginDescriptionStatic() {
30+
return "Breakpad debug symbol file reader.";
31+
}
32+
33+
static SymbolFile *CreateInstance(ObjectFile *obj_file) {
34+
return new SymbolFileBreakpad(obj_file);
35+
}
36+
37+
//------------------------------------------------------------------
38+
// Constructors and Destructors
39+
//------------------------------------------------------------------
40+
SymbolFileBreakpad(ObjectFile *object_file) : SymbolFile(object_file) {}
41+
42+
~SymbolFileBreakpad() override {}
43+
44+
uint32_t CalculateAbilities() override;
45+
46+
void InitializeObject() override {}
47+
48+
//------------------------------------------------------------------
49+
// Compile Unit function calls
50+
//------------------------------------------------------------------
51+
52+
uint32_t GetNumCompileUnits() override;
53+
54+
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
55+
56+
lldb::LanguageType
57+
ParseCompileUnitLanguage(const SymbolContext &sc) override {
58+
return lldb::eLanguageTypeUnknown;
59+
}
60+
61+
size_t ParseCompileUnitFunctions(const SymbolContext &sc) override;
62+
63+
bool ParseCompileUnitLineTable(const SymbolContext &sc) override;
64+
65+
bool ParseCompileUnitDebugMacros(const SymbolContext &sc) override {
66+
return false;
67+
}
68+
69+
bool ParseCompileUnitSupportFiles(const SymbolContext &sc,
70+
FileSpecList &support_files) override {
71+
return false;
72+
}
73+
74+
bool
75+
ParseImportedModules(const SymbolContext &sc,
76+
std::vector<ConstString> &imported_modules) override {
77+
return false;
78+
}
79+
80+
size_t ParseFunctionBlocks(const SymbolContext &sc) override { return 0; }
81+
82+
uint32_t FindGlobalVariables(const ConstString &name,
83+
const CompilerDeclContext *parent_decl_ctx,
84+
uint32_t max_matches,
85+
VariableList &variables) override {
86+
return 0;
87+
}
88+
89+
size_t ParseTypesForCompileUnit(CompileUnit &cu) override { return 0; }
90+
size_t ParseVariablesForContext(const SymbolContext &sc) override {
91+
return 0;
92+
}
93+
Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; }
94+
llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
95+
lldb::user_id_t type_uid,
96+
const lldb_private::ExecutionContext *exe_ctx) override {
97+
return llvm::None;
98+
}
99+
100+
bool CompleteType(CompilerType &compiler_type) override { return false; }
101+
uint32_t ResolveSymbolContext(const Address &so_addr,
102+
lldb::SymbolContextItem resolve_scope,
103+
SymbolContext &sc) override;
104+
105+
size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
106+
TypeList &type_list) override {
107+
return 0;
108+
}
109+
110+
uint32_t FindFunctions(const ConstString &name,
111+
const CompilerDeclContext *parent_decl_ctx,
112+
lldb::FunctionNameType name_type_mask,
113+
bool include_inlines, bool append,
114+
SymbolContextList &sc_list) override;
115+
116+
uint32_t FindFunctions(const RegularExpression &regex, bool include_inlines,
117+
bool append, SymbolContextList &sc_list) override;
118+
119+
uint32_t FindTypes(const SymbolContext &sc, const ConstString &name,
120+
const CompilerDeclContext *parent_decl_ctx, bool append,
121+
uint32_t max_matches,
122+
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
123+
TypeMap &types) override;
124+
125+
size_t FindTypes(const std::vector<CompilerContext> &context, bool append,
126+
TypeMap &types) override;
127+
128+
TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override {
129+
return nullptr;
130+
}
131+
132+
CompilerDeclContext
133+
FindNamespace(const SymbolContext &sc, const ConstString &name,
134+
const CompilerDeclContext *parent_decl_ctx) override {
135+
return CompilerDeclContext();
136+
}
137+
138+
void AddSymbols(Symtab &symtab) override;
139+
140+
ConstString GetPluginName() override { return GetPluginNameStatic(); }
141+
uint32_t GetPluginVersion() override { return 1; }
142+
143+
private:
144+
};
145+
146+
} // namespace breakpad
147+
} // namespace lldb_private
148+
149+
#endif

‎lldb/source/Plugins/SymbolFile/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
add_subdirectory(Breakpad)
12
add_subdirectory(DWARF)
23
add_subdirectory(Symtab)
34
add_subdirectory(NativePDB)

‎lldb/source/Symbol/SymbolVendor.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ void SymbolVendor::Dump(Stream *s) {
377377
s->Indent();
378378
s->PutCString("SymbolVendor");
379379
if (m_sym_file_ap.get()) {
380+
*s << " " << m_sym_file_ap->GetPluginName();
380381
ObjectFile *objfile = m_sym_file_ap->GetObjectFile();
381382
if (objfile) {
382383
const FileSpec &objfile_file_spec = objfile->GetFileSpec();
@@ -401,6 +402,9 @@ void SymbolVendor::Dump(Stream *s) {
401402
(*cu_pos)->Dump(s, show_context);
402403
}
403404

405+
if (Symtab *symtab = GetSymtab())
406+
symtab->Dump(s, nullptr, eSortOrderNone);
407+
404408
s->IndentLess();
405409
}
406410
}

‎lldb/tools/lldb-test/SystemInitializerTest.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
7171
#include "Plugins/Process/minidump/ProcessMinidump.h"
7272
#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
73+
#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
7374
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
7475
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
7576
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
@@ -176,6 +177,7 @@ SystemInitializerTest::Initialize(const InitializerOptions &options) {
176177
MainThreadCheckerRuntime::Initialize();
177178

178179
SymbolVendorELF::Initialize();
180+
breakpad::SymbolFileBreakpad::Initialize();
179181
SymbolFileDWARF::Initialize();
180182
SymbolFilePDB::Initialize();
181183
SymbolFileSymtab::Initialize();
@@ -274,6 +276,7 @@ void SystemInitializerTest::Terminate() {
274276
UndefinedBehaviorSanitizerRuntime::Terminate();
275277
MainThreadCheckerRuntime::Terminate();
276278
SymbolVendorELF::Terminate();
279+
breakpad::SymbolFileBreakpad::Terminate();
277280
SymbolFileDWARF::Terminate();
278281
SymbolFilePDB::Terminate();
279282
SymbolFileSymtab::Terminate();

‎lldb/tools/lldb-test/lldb-test.cpp

+23-23
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,14 @@ cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
100100
} // namespace object
101101

102102
namespace symbols {
103-
static cl::list<std::string> InputFilenames(cl::Positional,
104-
cl::desc("<input files>"),
105-
cl::OneOrMore,
106-
cl::sub(SymbolsSubcommand));
103+
static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
104+
cl::Required, cl::sub(SymbolsSubcommand));
105+
106+
static cl::opt<std::string>
107+
SymbolPath("symbol-file",
108+
cl::desc("The file from which to fetch symbol information."),
109+
cl::value_desc("file"), cl::sub(SymbolsSubcommand));
110+
107111
enum class FindType {
108112
None,
109113
Function,
@@ -692,28 +696,24 @@ int opts::symbols::dumpSymbols(Debugger &Dbg) {
692696
}
693697
auto Action = *ActionOr;
694698

695-
int HadErrors = 0;
696-
for (const auto &File : InputFilenames) {
697-
outs() << "Module: " << File << "\n";
698-
ModuleSpec Spec{FileSpec(File)};
699-
Spec.GetSymbolFileSpec().SetFile(File, FileSpec::Style::native);
700-
701-
auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
702-
SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
703-
if (!Vendor) {
704-
WithColor::error() << "Module has no symbol vendor.\n";
705-
HadErrors = 1;
706-
continue;
707-
}
699+
outs() << "Module: " << InputFile << "\n";
700+
ModuleSpec Spec{FileSpec(InputFile)};
701+
StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
702+
Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
708703

709-
if (Error E = Action(*ModulePtr)) {
710-
WithColor::error() << toString(std::move(E)) << "\n";
711-
HadErrors = 1;
712-
}
704+
auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
705+
SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
706+
if (!Vendor) {
707+
WithColor::error() << "Module has no symbol vendor.\n";
708+
return 1;
709+
}
713710

714-
outs().flush();
711+
if (Error E = Action(*ModulePtr)) {
712+
WithColor::error() << toString(std::move(E)) << "\n";
713+
return 1;
715714
}
716-
return HadErrors;
715+
716+
return 0;
717717
}
718718

719719
static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {

0 commit comments

Comments
 (0)
Please sign in to comment.