Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
39642 views
//===-- ObjectFileJSON.cpp ------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Plugins/ObjectFile/JSON/ObjectFileJSON.h"9#include "lldb/Core/Module.h"10#include "lldb/Core/ModuleSpec.h"11#include "lldb/Core/PluginManager.h"12#include "lldb/Core/Section.h"13#include "lldb/Symbol/Symbol.h"14#include "lldb/Utility/LLDBLog.h"15#include "lldb/Utility/Log.h"16#include "llvm/ADT/DenseSet.h"17#include <optional>1819using namespace llvm;20using namespace lldb;21using namespace lldb_private;2223LLDB_PLUGIN_DEFINE(ObjectFileJSON)2425char ObjectFileJSON::ID;2627void ObjectFileJSON::Initialize() {28PluginManager::RegisterPlugin(GetPluginNameStatic(),29GetPluginDescriptionStatic(), CreateInstance,30CreateMemoryInstance, GetModuleSpecifications);31}3233void ObjectFileJSON::Terminate() {34PluginManager::UnregisterPlugin(CreateInstance);35}3637ObjectFile *38ObjectFileJSON::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,39offset_t data_offset, const FileSpec *file,40offset_t file_offset, offset_t length) {41if (!data_sp) {42data_sp = MapFileData(*file, length, file_offset);43if (!data_sp)44return nullptr;45data_offset = 0;46}4748if (!MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))49return nullptr;5051// Update the data to contain the entire file if it doesn't already.52if (data_sp->GetByteSize() < length) {53data_sp = MapFileData(*file, length, file_offset);54if (!data_sp)55return nullptr;56data_offset = 0;57}5859Log *log = GetLog(LLDBLog::Symbols);6061auto text =62llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));6364Expected<json::Value> json = json::parse(text);65if (!json) {66LLDB_LOG_ERROR(log, json.takeError(),67"failed to parse JSON object file: {0}");68return nullptr;69}7071json::Path::Root root;72Header header;73if (!fromJSON(*json, header, root)) {74LLDB_LOG_ERROR(log, root.getError(),75"failed to parse JSON object file header: {0}");76return nullptr;77}7879ArchSpec arch(header.triple);80UUID uuid;81uuid.SetFromStringRef(header.uuid);82Type type = header.type.value_or(eTypeDebugInfo);8384Body body;85if (!fromJSON(*json, body, root)) {86LLDB_LOG_ERROR(log, root.getError(),87"failed to parse JSON object file body: {0}");88return nullptr;89}9091return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset,92length, std::move(arch), std::move(uuid), type,93std::move(body.symbols), std::move(body.sections));94}9596ObjectFile *ObjectFileJSON::CreateMemoryInstance(const ModuleSP &module_sp,97WritableDataBufferSP data_sp,98const ProcessSP &process_sp,99addr_t header_addr) {100return nullptr;101}102103size_t ObjectFileJSON::GetModuleSpecifications(104const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,105offset_t file_offset, offset_t length, ModuleSpecList &specs) {106if (!MagicBytesMatch(data_sp, data_offset, data_sp->GetByteSize()))107return 0;108109// Update the data to contain the entire file if it doesn't already.110if (data_sp->GetByteSize() < length) {111data_sp = MapFileData(file, length, file_offset);112if (!data_sp)113return 0;114data_offset = 0;115}116117Log *log = GetLog(LLDBLog::Symbols);118119auto text =120llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));121122Expected<json::Value> json = json::parse(text);123if (!json) {124LLDB_LOG_ERROR(log, json.takeError(),125"failed to parse JSON object file: {0}");126return 0;127}128129json::Path::Root root;130Header header;131if (!fromJSON(*json, header, root)) {132LLDB_LOG_ERROR(log, root.getError(),133"failed to parse JSON object file header: {0}");134return 0;135}136137ArchSpec arch(header.triple);138UUID uuid;139uuid.SetFromStringRef(header.uuid);140141ModuleSpec spec(file, std::move(arch));142spec.GetUUID() = std::move(uuid);143specs.Append(spec);144return 1;145}146147ObjectFileJSON::ObjectFileJSON(const ModuleSP &module_sp, DataBufferSP &data_sp,148offset_t data_offset, const FileSpec *file,149offset_t offset, offset_t length, ArchSpec arch,150UUID uuid, Type type,151std::vector<JSONSymbol> symbols,152std::vector<JSONSection> sections)153: ObjectFile(module_sp, file, offset, length, data_sp, data_offset),154m_arch(std::move(arch)), m_uuid(std::move(uuid)), m_type(type),155m_symbols(std::move(symbols)), m_sections(std::move(sections)) {}156157bool ObjectFileJSON::ParseHeader() {158// We already parsed the header during initialization.159return true;160}161162void ObjectFileJSON::ParseSymtab(Symtab &symtab) {163Log *log = GetLog(LLDBLog::Symbols);164SectionList *section_list = GetModule()->GetSectionList();165for (JSONSymbol json_symbol : m_symbols) {166llvm::Expected<Symbol> symbol = Symbol::FromJSON(json_symbol, section_list);167if (!symbol) {168LLDB_LOG_ERROR(log, symbol.takeError(), "invalid symbol: {0}");169continue;170}171symtab.AddSymbol(*symbol);172}173symtab.Finalize();174}175176void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {177if (m_sections_up)178return;179m_sections_up = std::make_unique<SectionList>();180181lldb::user_id_t id = 1;182for (const auto §ion : m_sections) {183auto section_sp = std::make_shared<Section>(184GetModule(), this, id++, ConstString(section.name),185section.type.value_or(eSectionTypeCode), 0, section.size.value_or(0), 0,186section.size.value_or(0), /*log2align*/ 0, /*flags*/ 0);187m_sections_up->AddSection(section_sp);188unified_section_list.AddSection(section_sp);189}190}191192bool ObjectFileJSON::MagicBytesMatch(DataBufferSP data_sp,193lldb::addr_t data_offset,194lldb::addr_t data_length) {195DataExtractor data;196data.SetData(data_sp, data_offset, data_length);197lldb::offset_t offset = 0;198uint32_t magic = data.GetU8(&offset);199return magic == '{';200}201202namespace lldb_private {203204bool fromJSON(const json::Value &value, ObjectFileJSON::Header &header,205json::Path path) {206json::ObjectMapper o(value, path);207return o && o.map("triple", header.triple) && o.map("uuid", header.uuid) &&208o.map("type", header.type);209}210211bool fromJSON(const json::Value &value, ObjectFileJSON::Body &body,212json::Path path) {213json::ObjectMapper o(value, path);214return o && o.mapOptional("symbols", body.symbols) &&215o.mapOptional("sections", body.sections);216}217218} // namespace lldb_private219220221