Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
39642 views
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
// Update the data to contain the entire file if it doesn't already.
53
if (data_sp->GetByteSize() < length) {
54
data_sp = MapFileData(*file, length, file_offset);
55
if (!data_sp)
56
return nullptr;
57
data_offset = 0;
58
}
59
60
Log *log = GetLog(LLDBLog::Symbols);
61
62
auto text =
63
llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));
64
65
Expected<json::Value> json = json::parse(text);
66
if (!json) {
67
LLDB_LOG_ERROR(log, json.takeError(),
68
"failed to parse JSON object file: {0}");
69
return nullptr;
70
}
71
72
json::Path::Root root;
73
Header header;
74
if (!fromJSON(*json, header, root)) {
75
LLDB_LOG_ERROR(log, root.getError(),
76
"failed to parse JSON object file header: {0}");
77
return nullptr;
78
}
79
80
ArchSpec arch(header.triple);
81
UUID uuid;
82
uuid.SetFromStringRef(header.uuid);
83
Type type = header.type.value_or(eTypeDebugInfo);
84
85
Body body;
86
if (!fromJSON(*json, body, root)) {
87
LLDB_LOG_ERROR(log, root.getError(),
88
"failed to parse JSON object file body: {0}");
89
return nullptr;
90
}
91
92
return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset,
93
length, std::move(arch), std::move(uuid), type,
94
std::move(body.symbols), std::move(body.sections));
95
}
96
97
ObjectFile *ObjectFileJSON::CreateMemoryInstance(const ModuleSP &module_sp,
98
WritableDataBufferSP data_sp,
99
const ProcessSP &process_sp,
100
addr_t header_addr) {
101
return nullptr;
102
}
103
104
size_t ObjectFileJSON::GetModuleSpecifications(
105
const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
106
offset_t file_offset, offset_t length, ModuleSpecList &specs) {
107
if (!MagicBytesMatch(data_sp, data_offset, data_sp->GetByteSize()))
108
return 0;
109
110
// Update the data to contain the entire file if it doesn't already.
111
if (data_sp->GetByteSize() < length) {
112
data_sp = MapFileData(file, length, file_offset);
113
if (!data_sp)
114
return 0;
115
data_offset = 0;
116
}
117
118
Log *log = GetLog(LLDBLog::Symbols);
119
120
auto text =
121
llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));
122
123
Expected<json::Value> json = json::parse(text);
124
if (!json) {
125
LLDB_LOG_ERROR(log, json.takeError(),
126
"failed to parse JSON object file: {0}");
127
return 0;
128
}
129
130
json::Path::Root root;
131
Header header;
132
if (!fromJSON(*json, header, root)) {
133
LLDB_LOG_ERROR(log, root.getError(),
134
"failed to parse JSON object file header: {0}");
135
return 0;
136
}
137
138
ArchSpec arch(header.triple);
139
UUID uuid;
140
uuid.SetFromStringRef(header.uuid);
141
142
ModuleSpec spec(file, std::move(arch));
143
spec.GetUUID() = std::move(uuid);
144
specs.Append(spec);
145
return 1;
146
}
147
148
ObjectFileJSON::ObjectFileJSON(const ModuleSP &module_sp, DataBufferSP &data_sp,
149
offset_t data_offset, const FileSpec *file,
150
offset_t offset, offset_t length, ArchSpec arch,
151
UUID uuid, Type type,
152
std::vector<JSONSymbol> symbols,
153
std::vector<JSONSection> sections)
154
: ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
155
m_arch(std::move(arch)), m_uuid(std::move(uuid)), m_type(type),
156
m_symbols(std::move(symbols)), m_sections(std::move(sections)) {}
157
158
bool ObjectFileJSON::ParseHeader() {
159
// We already parsed the header during initialization.
160
return true;
161
}
162
163
void ObjectFileJSON::ParseSymtab(Symtab &symtab) {
164
Log *log = GetLog(LLDBLog::Symbols);
165
SectionList *section_list = GetModule()->GetSectionList();
166
for (JSONSymbol json_symbol : m_symbols) {
167
llvm::Expected<Symbol> symbol = Symbol::FromJSON(json_symbol, section_list);
168
if (!symbol) {
169
LLDB_LOG_ERROR(log, symbol.takeError(), "invalid symbol: {0}");
170
continue;
171
}
172
symtab.AddSymbol(*symbol);
173
}
174
symtab.Finalize();
175
}
176
177
void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {
178
if (m_sections_up)
179
return;
180
m_sections_up = std::make_unique<SectionList>();
181
182
lldb::user_id_t id = 1;
183
for (const auto &section : m_sections) {
184
auto section_sp = std::make_shared<Section>(
185
GetModule(), this, id++, ConstString(section.name),
186
section.type.value_or(eSectionTypeCode), 0, section.size.value_or(0), 0,
187
section.size.value_or(0), /*log2align*/ 0, /*flags*/ 0);
188
m_sections_up->AddSection(section_sp);
189
unified_section_list.AddSection(section_sp);
190
}
191
}
192
193
bool ObjectFileJSON::MagicBytesMatch(DataBufferSP data_sp,
194
lldb::addr_t data_offset,
195
lldb::addr_t data_length) {
196
DataExtractor data;
197
data.SetData(data_sp, data_offset, data_length);
198
lldb::offset_t offset = 0;
199
uint32_t magic = data.GetU8(&offset);
200
return magic == '{';
201
}
202
203
namespace lldb_private {
204
205
bool fromJSON(const json::Value &value, ObjectFileJSON::Header &header,
206
json::Path path) {
207
json::ObjectMapper o(value, path);
208
return o && o.map("triple", header.triple) && o.map("uuid", header.uuid) &&
209
o.map("type", header.type);
210
}
211
212
bool fromJSON(const json::Value &value, ObjectFileJSON::Body &body,
213
json::Path path) {
214
json::ObjectMapper o(value, path);
215
return o && o.mapOptional("symbols", body.symbols) &&
216
o.mapOptional("sections", body.sections);
217
}
218
219
} // namespace lldb_private
220
221