Skip to content

Commit 00814a3

Browse files
authored
Merge pull request #6460 from apple/🍒/navy/SymbolFileJSON
Cherrypick SymbolFileJSON to stable/20221013
2 parents a1b244d + b97c963 commit 00814a3

File tree

17 files changed

+999
-4
lines changed

17 files changed

+999
-4
lines changed

lldb/include/lldb/Symbol/Symbol.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,23 @@
1111

1212
#include "lldb/Core/AddressRange.h"
1313
#include "lldb/Core/Mangled.h"
14+
#include "lldb/Core/Section.h"
1415
#include "lldb/Symbol/SymbolContextScope.h"
1516
#include "lldb/Utility/UserID.h"
1617
#include "lldb/lldb-private.h"
18+
#include "llvm/Support/JSON.h"
1719

1820
namespace lldb_private {
1921

22+
struct JSONSymbol {
23+
llvm::Optional<uint64_t> address;
24+
llvm::Optional<uint64_t> value;
25+
llvm::Optional<uint64_t> size;
26+
llvm::Optional<uint64_t> id;
27+
llvm::Optional<lldb::SymbolType> type;
28+
std::string name;
29+
};
30+
2031
class Symbol : public SymbolContextScope {
2132
public:
2233
// ObjectFile readers can classify their symbol table entries and searches
@@ -39,6 +50,9 @@ class Symbol : public SymbolContextScope {
3950

4051
const Symbol &operator=(const Symbol &rhs);
4152

53+
static llvm::Expected<Symbol> FromJSON(const JSONSymbol &symbol,
54+
SectionList *section_list);
55+
4256
void Clear();
4357

4458
bool Compare(ConstString name, lldb::SymbolType type) const;
@@ -187,7 +201,7 @@ class Symbol : public SymbolContextScope {
187201

188202
bool IsWeak() const { return m_is_weak; }
189203

190-
void SetIsWeak (bool b) { m_is_weak = b; }
204+
void SetIsWeak(bool b) { m_is_weak = b; }
191205

192206
bool GetByteSizeIsValid() const { return m_size_is_valid; }
193207

@@ -332,4 +346,16 @@ class Symbol : public SymbolContextScope {
332346

333347
} // namespace lldb_private
334348

349+
namespace llvm {
350+
namespace json {
351+
352+
bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
353+
llvm::json::Path path);
354+
355+
bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
356+
llvm::json::Path path);
357+
358+
} // namespace json
359+
} // namespace llvm
360+
335361
#endif // LLDB_SYMBOL_SYMBOL_H

lldb/source/Plugins/ObjectFile/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_subdirectory(Breakpad)
22
add_subdirectory(ELF)
33
add_subdirectory(JIT)
4+
add_subdirectory(JSON)
45
add_subdirectory(Mach-O)
56
add_subdirectory(Minidump)
67
add_subdirectory(PDB)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
add_lldb_library(lldbPluginObjectFileJSON PLUGIN
2+
ObjectFileJSON.cpp
3+
4+
LINK_LIBS
5+
lldbCore
6+
lldbHost
7+
lldbSymbol
8+
lldbUtility
9+
LINK_COMPONENTS
10+
Support
11+
)
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
//===-- ObjectFileJSON.cpp ------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Plugins/ObjectFile/JSON/ObjectFileJSON.h"
10+
#include "lldb/Core/Module.h"
11+
#include "lldb/Core/ModuleSpec.h"
12+
#include "lldb/Core/PluginManager.h"
13+
#include "lldb/Core/Section.h"
14+
#include "lldb/Symbol/Symbol.h"
15+
#include "lldb/Utility/LLDBLog.h"
16+
#include "lldb/Utility/Log.h"
17+
#include "llvm/ADT/DenseSet.h"
18+
#include <optional>
19+
20+
using namespace llvm;
21+
using namespace lldb;
22+
using namespace lldb_private;
23+
24+
LLDB_PLUGIN_DEFINE(ObjectFileJSON)
25+
26+
char ObjectFileJSON::ID;
27+
28+
void ObjectFileJSON::Initialize() {
29+
PluginManager::RegisterPlugin(GetPluginNameStatic(),
30+
GetPluginDescriptionStatic(), CreateInstance,
31+
CreateMemoryInstance, GetModuleSpecifications);
32+
}
33+
34+
void ObjectFileJSON::Terminate() {
35+
PluginManager::UnregisterPlugin(CreateInstance);
36+
}
37+
38+
ObjectFile *
39+
ObjectFileJSON::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,
40+
offset_t data_offset, const FileSpec *file,
41+
offset_t file_offset, offset_t length) {
42+
if (!data_sp) {
43+
data_sp = MapFileData(*file, length, file_offset);
44+
if (!data_sp)
45+
return nullptr;
46+
data_offset = 0;
47+
}
48+
49+
if (!MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
50+
return nullptr;
51+
52+
if (data_sp->GetByteSize() < length) {
53+
data_sp = MapFileData(*file, length, file_offset);
54+
if (!data_sp)
55+
return nullptr;
56+
data_offset = 0;
57+
}
58+
59+
auto text =
60+
llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));
61+
62+
Expected<json::Value> json = json::parse(text);
63+
if (!json) {
64+
llvm::consumeError(json.takeError());
65+
return nullptr;
66+
}
67+
68+
json::Path::Root root;
69+
Header header;
70+
if (!fromJSON(*json, header, root))
71+
return nullptr;
72+
73+
ArchSpec arch(header.triple);
74+
UUID uuid;
75+
uuid.SetFromStringRef(header.uuid);
76+
77+
Body body;
78+
fromJSON(*json, body, root);
79+
80+
return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset,
81+
length, std::move(arch), std::move(uuid),
82+
std::move(body.symbols));
83+
}
84+
85+
ObjectFile *ObjectFileJSON::CreateMemoryInstance(const ModuleSP &module_sp,
86+
WritableDataBufferSP data_sp,
87+
const ProcessSP &process_sp,
88+
addr_t header_addr) {
89+
return nullptr;
90+
}
91+
92+
size_t ObjectFileJSON::GetModuleSpecifications(
93+
const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
94+
offset_t file_offset, offset_t length, ModuleSpecList &specs) {
95+
96+
if (!MagicBytesMatch(data_sp, data_offset, data_sp->GetByteSize()))
97+
return 0;
98+
99+
auto text =
100+
llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));
101+
102+
Expected<json::Value> json = json::parse(text);
103+
if (!json) {
104+
llvm::consumeError(json.takeError());
105+
return 0;
106+
}
107+
108+
json::Path::Root root;
109+
Header header;
110+
if (!fromJSON(*json, header, root))
111+
return 0;
112+
113+
ArchSpec arch(header.triple);
114+
UUID uuid;
115+
uuid.SetFromStringRef(header.uuid);
116+
117+
ModuleSpec spec(file, std::move(arch));
118+
spec.GetUUID() = std::move(uuid);
119+
specs.Append(spec);
120+
return 1;
121+
}
122+
123+
ObjectFileJSON::ObjectFileJSON(const ModuleSP &module_sp, DataBufferSP &data_sp,
124+
offset_t data_offset, const FileSpec *file,
125+
offset_t offset, offset_t length, ArchSpec arch,
126+
UUID uuid, std::vector<JSONSymbol> symbols)
127+
: ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
128+
m_arch(std::move(arch)), m_uuid(std::move(uuid)),
129+
m_symbols(std::move(symbols)) {}
130+
131+
bool ObjectFileJSON::ParseHeader() {
132+
// We already parsed the header during initialization.
133+
return true;
134+
}
135+
136+
void ObjectFileJSON::ParseSymtab(Symtab &symtab) {
137+
Log *log = GetLog(LLDBLog::Symbols);
138+
SectionList *section_list = GetModule()->GetSectionList();
139+
for (JSONSymbol json_symbol : m_symbols) {
140+
llvm::Expected<Symbol> symbol = Symbol::FromJSON(json_symbol, section_list);
141+
if (!symbol) {
142+
LLDB_LOG_ERROR(log, symbol.takeError(), "invalid symbol");
143+
continue;
144+
}
145+
symtab.AddSymbol(*symbol);
146+
}
147+
symtab.Finalize();
148+
}
149+
150+
void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {}
151+
152+
bool ObjectFileJSON::MagicBytesMatch(DataBufferSP data_sp,
153+
lldb::addr_t data_offset,
154+
lldb::addr_t data_length) {
155+
DataExtractor data;
156+
data.SetData(data_sp, data_offset, data_length);
157+
lldb::offset_t offset = 0;
158+
uint32_t magic = data.GetU8(&offset);
159+
return magic == '{';
160+
}
161+
162+
namespace lldb_private {
163+
164+
bool fromJSON(const json::Value &value, ObjectFileJSON::Header &header,
165+
json::Path path) {
166+
json::ObjectMapper o(value, path);
167+
return o && o.map("triple", header.triple) && o.map("uuid", header.uuid);
168+
}
169+
170+
bool fromJSON(const json::Value &value, ObjectFileJSON::Body &body,
171+
json::Path path) {
172+
json::ObjectMapper o(value, path);
173+
return o && o.map("symbols", body.symbols);
174+
}
175+
176+
} // namespace lldb_private
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//===-- ObjectFileJSON.h -------------------------------------- -*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_JSON_OBJECTFILEJSON_H
10+
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_JSON_OBJECTFILEJSON_H
11+
12+
#include "lldb/Symbol/ObjectFile.h"
13+
#include "lldb/Utility/ArchSpec.h"
14+
#include "llvm/Support/JSON.h"
15+
16+
namespace lldb_private {
17+
18+
class ObjectFileJSON : public ObjectFile {
19+
public:
20+
static void Initialize();
21+
static void Terminate();
22+
23+
static llvm::StringRef GetPluginNameStatic() { return "JSON"; }
24+
25+
static const char *GetPluginDescriptionStatic() {
26+
return "JSON object file reader.";
27+
}
28+
29+
static ObjectFile *
30+
CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
31+
lldb::offset_t data_offset, const FileSpec *file,
32+
lldb::offset_t file_offset, lldb::offset_t length);
33+
34+
static ObjectFile *CreateMemoryInstance(const lldb::ModuleSP &module_sp,
35+
lldb::WritableDataBufferSP data_sp,
36+
const lldb::ProcessSP &process_sp,
37+
lldb::addr_t header_addr);
38+
39+
static size_t GetModuleSpecifications(const FileSpec &file,
40+
lldb::DataBufferSP &data_sp,
41+
lldb::offset_t data_offset,
42+
lldb::offset_t file_offset,
43+
lldb::offset_t length,
44+
ModuleSpecList &specs);
45+
46+
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
47+
48+
// LLVM RTTI support
49+
static char ID;
50+
bool isA(const void *ClassID) const override {
51+
return ClassID == &ID || ObjectFile::isA(ClassID);
52+
}
53+
static bool classof(const ObjectFile *obj) { return obj->isA(&ID); }
54+
55+
bool ParseHeader() override;
56+
57+
lldb::ByteOrder GetByteOrder() const override {
58+
return m_arch.GetByteOrder();
59+
}
60+
61+
bool IsExecutable() const override { return false; }
62+
63+
uint32_t GetAddressByteSize() const override {
64+
return m_arch.GetAddressByteSize();
65+
}
66+
67+
AddressClass GetAddressClass(lldb::addr_t file_addr) override {
68+
return AddressClass::eInvalid;
69+
}
70+
71+
void ParseSymtab(lldb_private::Symtab &symtab) override;
72+
73+
bool IsStripped() override { return false; }
74+
75+
void CreateSections(SectionList &unified_section_list) override;
76+
77+
void Dump(Stream *s) override {}
78+
79+
ArchSpec GetArchitecture() override { return m_arch; }
80+
81+
UUID GetUUID() override { return m_uuid; }
82+
83+
uint32_t GetDependentModules(FileSpecList &files) override { return 0; }
84+
85+
Type CalculateType() override { return eTypeDebugInfo; }
86+
87+
Strata CalculateStrata() override { return eStrataUser; }
88+
89+
static bool MagicBytesMatch(lldb::DataBufferSP data_sp, lldb::addr_t offset,
90+
lldb::addr_t length);
91+
92+
struct Header {
93+
std::string triple;
94+
std::string uuid;
95+
};
96+
97+
struct Body {
98+
std::vector<JSONSymbol> symbols;
99+
};
100+
101+
private:
102+
ArchSpec m_arch;
103+
UUID m_uuid;
104+
std::vector<JSONSymbol> m_symbols;
105+
106+
ObjectFileJSON(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
107+
lldb::offset_t data_offset, const FileSpec *file,
108+
lldb::offset_t offset, lldb::offset_t length, ArchSpec arch,
109+
UUID uuid, std::vector<JSONSymbol> symbols);
110+
};
111+
112+
bool fromJSON(const llvm::json::Value &value, ObjectFileJSON::Header &header,
113+
llvm::json::Path path);
114+
115+
bool fromJSON(const llvm::json::Value &value, ObjectFileJSON::Body &body,
116+
llvm::json::Path path);
117+
118+
} // namespace lldb_private
119+
#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_JSON_OBJECTFILEJSON_H
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_subdirectory(Breakpad)
22
add_subdirectory(DWARF)
3+
add_subdirectory(JSON)
34
add_subdirectory(NativePDB)
45
add_subdirectory(PDB)
56
add_subdirectory(Symtab)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
add_lldb_library(lldbPluginSymbolFileJSON PLUGIN
2+
SymbolFileJSON.cpp
3+
4+
LINK_LIBS
5+
lldbCore
6+
lldbSymbol
7+
)

0 commit comments

Comments
 (0)