diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp | 219 | ||||
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h | 125 |
2 files changed, 344 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp new file mode 100644 index 000000000000..ffbd87714242 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp @@ -0,0 +1,219 @@ +//===-- ObjectFileJSON.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/ObjectFile/JSON/ObjectFileJSON.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "llvm/ADT/DenseSet.h" +#include <optional> + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ObjectFileJSON) + +char ObjectFileJSON::ID; + +void ObjectFileJSON::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + CreateMemoryInstance, GetModuleSpecifications); +} + +void ObjectFileJSON::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ObjectFile * +ObjectFileJSON::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp, + offset_t data_offset, const FileSpec *file, + offset_t file_offset, offset_t length) { + if (!data_sp) { + data_sp = MapFileData(*file, length, file_offset); + if (!data_sp) + return nullptr; + data_offset = 0; + } + + if (!MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) + return nullptr; + + // Update the data to contain the entire file if it doesn't already. + if (data_sp->GetByteSize() < length) { + data_sp = MapFileData(*file, length, file_offset); + if (!data_sp) + return nullptr; + data_offset = 0; + } + + Log *log = GetLog(LLDBLog::Symbols); + + auto text = + llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes())); + + Expected<json::Value> json = json::parse(text); + if (!json) { + LLDB_LOG_ERROR(log, json.takeError(), + "failed to parse JSON object file: {0}"); + return nullptr; + } + + json::Path::Root root; + Header header; + if (!fromJSON(*json, header, root)) { + LLDB_LOG_ERROR(log, root.getError(), + "failed to parse JSON object file header: {0}"); + return nullptr; + } + + ArchSpec arch(header.triple); + UUID uuid; + uuid.SetFromStringRef(header.uuid); + Type type = header.type.value_or(eTypeDebugInfo); + + Body body; + if (!fromJSON(*json, body, root)) { + LLDB_LOG_ERROR(log, root.getError(), + "failed to parse JSON object file body: {0}"); + return nullptr; + } + + return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset, + length, std::move(arch), std::move(uuid), type, + std::move(body.symbols), std::move(body.sections)); +} + +ObjectFile *ObjectFileJSON::CreateMemoryInstance(const ModuleSP &module_sp, + WritableDataBufferSP data_sp, + const ProcessSP &process_sp, + addr_t header_addr) { + return nullptr; +} + +size_t ObjectFileJSON::GetModuleSpecifications( + const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset, + offset_t file_offset, offset_t length, ModuleSpecList &specs) { + if (!MagicBytesMatch(data_sp, data_offset, data_sp->GetByteSize())) + return 0; + + // Update the data to contain the entire file if it doesn't already. + if (data_sp->GetByteSize() < length) { + data_sp = MapFileData(file, length, file_offset); + if (!data_sp) + return 0; + data_offset = 0; + } + + Log *log = GetLog(LLDBLog::Symbols); + + auto text = + llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes())); + + Expected<json::Value> json = json::parse(text); + if (!json) { + LLDB_LOG_ERROR(log, json.takeError(), + "failed to parse JSON object file: {0}"); + return 0; + } + + json::Path::Root root; + Header header; + if (!fromJSON(*json, header, root)) { + LLDB_LOG_ERROR(log, root.getError(), + "failed to parse JSON object file header: {0}"); + return 0; + } + + ArchSpec arch(header.triple); + UUID uuid; + uuid.SetFromStringRef(header.uuid); + + ModuleSpec spec(file, std::move(arch)); + spec.GetUUID() = std::move(uuid); + specs.Append(spec); + return 1; +} + +ObjectFileJSON::ObjectFileJSON(const ModuleSP &module_sp, DataBufferSP &data_sp, + offset_t data_offset, const FileSpec *file, + offset_t offset, offset_t length, ArchSpec arch, + UUID uuid, Type type, + std::vector<JSONSymbol> symbols, + std::vector<JSONSection> sections) + : ObjectFile(module_sp, file, offset, length, data_sp, data_offset), + m_arch(std::move(arch)), m_uuid(std::move(uuid)), m_type(type), + m_symbols(std::move(symbols)), m_sections(std::move(sections)) {} + +bool ObjectFileJSON::ParseHeader() { + // We already parsed the header during initialization. + return true; +} + +void ObjectFileJSON::ParseSymtab(Symtab &symtab) { + Log *log = GetLog(LLDBLog::Symbols); + SectionList *section_list = GetModule()->GetSectionList(); + for (JSONSymbol json_symbol : m_symbols) { + llvm::Expected<Symbol> symbol = Symbol::FromJSON(json_symbol, section_list); + if (!symbol) { + LLDB_LOG_ERROR(log, symbol.takeError(), "invalid symbol: {0}"); + continue; + } + symtab.AddSymbol(*symbol); + } + symtab.Finalize(); +} + +void ObjectFileJSON::CreateSections(SectionList &unified_section_list) { + if (m_sections_up) + return; + m_sections_up = std::make_unique<SectionList>(); + + lldb::user_id_t id = 1; + for (const auto §ion : m_sections) { + auto section_sp = std::make_shared<Section>( + GetModule(), this, id++, ConstString(section.name), + section.type.value_or(eSectionTypeCode), 0, section.size.value_or(0), 0, + section.size.value_or(0), /*log2align*/ 0, /*flags*/ 0); + m_sections_up->AddSection(section_sp); + unified_section_list.AddSection(section_sp); + } +} + +bool ObjectFileJSON::MagicBytesMatch(DataBufferSP data_sp, + lldb::addr_t data_offset, + lldb::addr_t data_length) { + DataExtractor data; + data.SetData(data_sp, data_offset, data_length); + lldb::offset_t offset = 0; + uint32_t magic = data.GetU8(&offset); + return magic == '{'; +} + +namespace lldb_private { + +bool fromJSON(const json::Value &value, ObjectFileJSON::Header &header, + json::Path path) { + json::ObjectMapper o(value, path); + return o && o.map("triple", header.triple) && o.map("uuid", header.uuid) && + o.map("type", header.type); +} + +bool fromJSON(const json::Value &value, ObjectFileJSON::Body &body, + json::Path path) { + json::ObjectMapper o(value, path); + return o && o.mapOptional("symbols", body.symbols) && + o.mapOptional("sections", body.sections); +} + +} // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h new file mode 100644 index 000000000000..b72565f46886 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h @@ -0,0 +1,125 @@ +//===-- ObjectFileJSON.h -------------------------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_JSON_OBJECTFILEJSON_H +#define LLDB_SOURCE_PLUGINS_OBJECTFILE_JSON_OBJECTFILEJSON_H + +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" +#include "llvm/Support/JSON.h" + +namespace lldb_private { + +class ObjectFileJSON : public ObjectFile { +public: + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "JSON"; } + + static const char *GetPluginDescriptionStatic() { + return "JSON object file reader."; + } + + static ObjectFile * + CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, + lldb::offset_t data_offset, const FileSpec *file, + lldb::offset_t file_offset, lldb::offset_t length); + + static ObjectFile *CreateMemoryInstance(const lldb::ModuleSP &module_sp, + lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr); + + static size_t GetModuleSpecifications(const FileSpec &file, + lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + ModuleSpecList &specs); + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + + bool ParseHeader() override; + + lldb::ByteOrder GetByteOrder() const override { + return m_arch.GetByteOrder(); + } + + bool IsExecutable() const override { return false; } + + uint32_t GetAddressByteSize() const override { + return m_arch.GetAddressByteSize(); + } + + AddressClass GetAddressClass(lldb::addr_t file_addr) override { + return AddressClass::eInvalid; + } + + void ParseSymtab(lldb_private::Symtab &symtab) override; + + bool IsStripped() override { return false; } + + void CreateSections(SectionList &unified_section_list) override; + + void Dump(Stream *s) override {} + + ArchSpec GetArchitecture() override { return m_arch; } + + UUID GetUUID() override { return m_uuid; } + + uint32_t GetDependentModules(FileSpecList &files) override { return 0; } + + Type CalculateType() override { return m_type; } + + Strata CalculateStrata() override { return eStrataUser; } + + static bool MagicBytesMatch(lldb::DataBufferSP data_sp, lldb::addr_t offset, + lldb::addr_t length); + + struct Header { + std::string triple; + std::string uuid; + std::optional<ObjectFile::Type> type; + }; + + struct Body { + std::vector<JSONSection> sections; + std::vector<JSONSymbol> symbols; + }; + +private: + ArchSpec m_arch; + UUID m_uuid; + ObjectFile::Type m_type; + std::optional<uint64_t> m_size; + std::vector<JSONSymbol> m_symbols; + std::vector<JSONSection> m_sections; + + ObjectFileJSON(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, const FileSpec *file, + lldb::offset_t offset, lldb::offset_t length, ArchSpec arch, + UUID uuid, Type type, std::vector<JSONSymbol> symbols, + std::vector<JSONSection> sections); +}; + +bool fromJSON(const llvm::json::Value &value, ObjectFileJSON::Header &header, + llvm::json::Path path); + +bool fromJSON(const llvm::json::Value &value, ObjectFileJSON::Body &body, + llvm::json::Path path); + +} // namespace lldb_private +#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_JSON_OBJECTFILEJSON_H |