JDevlieghere updated this revision to Diff 502330.
JDevlieghere marked 3 inline comments as done.
JDevlieghere added a comment.
Address Greg's feedback
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D145180/new/
https://reviews.llvm.org/D145180
Files:
lldb/include/lldb/Symbol/Symbol.h
lldb/source/Plugins/ObjectFile/CMakeLists.txt
lldb/source/Plugins/ObjectFile/JSON/CMakeLists.txt
lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h
lldb/source/Plugins/SymbolFile/CMakeLists.txt
lldb/source/Plugins/SymbolFile/JSON/CMakeLists.txt
lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.cpp
lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h
lldb/source/Symbol/Symbol.cpp
lldb/test/API/macosx/symbols/Makefile
lldb/test/API/macosx/symbols/TestSymbolFileJSON.py
lldb/test/API/macosx/symbols/main.c
Index: lldb/test/API/macosx/symbols/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/macosx/symbols/main.c
@@ -0,0 +1,2 @@
+int foo() { return 1; }
+int main() { return foo(); }
Index: lldb/test/API/macosx/symbols/TestSymbolFileJSON.py
===================================================================
--- /dev/null
+++ lldb/test/API/macosx/symbols/TestSymbolFileJSON.py
@@ -0,0 +1,82 @@
+""" Testing symbol loading via JSON file. """
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TargetSymbolsFileJSON(TestBase):
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.source = 'main.c'
+
+ @no_debug_info_test # Prevent the genaration of the dwarf version of this test
+ def test_symbol_file_json(self):
+ """Test that 'target symbols add' can load the symbols from a JSON file."""
+
+ self.build()
+ stripped = self.getBuildArtifact("stripped.out")
+ unstripped = self.getBuildArtifact("a.out")
+
+ # Create a JSON symbol file from the unstripped target.
+ unstripped_target = self.dbg.CreateTarget(unstripped)
+ self.assertTrue(unstripped_target, VALID_TARGET)
+
+ unstripped_module = unstripped_target.GetModuleAtIndex(0)
+ main_symbol = unstripped_module.FindSymbol("main")
+ foo_symbol = unstripped_module.FindSymbol("foo")
+
+ data = {
+ "triple": unstripped_module.GetTriple(),
+ "uuid": unstripped_module.GetUUIDString(),
+ "symbols": list()
+ }
+ data['symbols'].append({
+ "name": "main",
+ "type": "code",
+ "size": main_symbol.GetSize(),
+ "value": main_symbol.addr.GetFileAddress(),
+ })
+ data['symbols'].append({
+ "name": "foo",
+ "type": "code",
+ "size": foo_symbol.GetSize(),
+ "value": foo_symbol.addr.GetFileAddress(),
+ })
+
+ json_object = json.dumps(data, indent=4)
+ json_symbol_file = self.getBuildArtifact("a.json")
+ with open(json_symbol_file, "w") as outfile:
+ outfile.write(json_object)
+
+ # Create a stripped target.
+ stripped_target = self.dbg.CreateTarget(stripped)
+ self.assertTrue(stripped_target, VALID_TARGET)
+
+ # Ensure there's no symbol for main and foo.
+ stripped_module = stripped_target.GetModuleAtIndex(0)
+ self.assertFalse(stripped_module.FindSymbol("main").IsValid())
+ self.assertFalse(stripped_module.FindSymbol("foo").IsValid())
+
+ main_bp = stripped_target.BreakpointCreateByName(
+ "main", "stripped.out")
+ self.assertTrue(main_bp, VALID_BREAKPOINT)
+ self.assertEqual(main_bp.num_locations, 0)
+
+ # Load the JSON symbol file.
+ self.runCmd("target symbols add -s %s %s" %
+ (stripped, self.getBuildArtifact("a.json")))
+
+ # Ensure main and foo are available now.
+ self.assertTrue(stripped_module.FindSymbol("main").IsValid())
+ self.assertTrue(stripped_module.FindSymbol("foo").IsValid())
+ self.assertEqual(main_bp.num_locations, 1)
+
+ # Ensure the file address matches between the stripped and unstripped target.
+ self.assertEqual(
+ stripped_module.FindSymbol("main").addr.GetFileAddress(),
+ unstripped_module.FindSymbol("main").addr.GetFileAddress())
+ self.assertEqual(
+ stripped_module.FindSymbol("foo").addr.GetFileAddress(),
+ unstripped_module.FindSymbol("foo").addr.GetFileAddress())
Index: lldb/test/API/macosx/symbols/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/macosx/symbols/Makefile
@@ -0,0 +1,8 @@
+C_SOURCES := main.c
+
+all: stripped.out
+
+stripped.out : a.out
+ strip a.out -o stripped.out
+
+include Makefile.rules
Index: lldb/source/Symbol/Symbol.cpp
===================================================================
--- lldb/source/Symbol/Symbol.cpp
+++ lldb/source/Symbol/Symbol.cpp
@@ -19,6 +19,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataEncoder.h"
#include "lldb/Utility/Stream.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace lldb;
using namespace lldb_private;
@@ -31,6 +32,38 @@
m_is_weak(false), m_type(eSymbolTypeInvalid), m_mangled(),
m_addr_range() {}
+Symbol::Symbol(const JSONSymbol &symbol, SectionList *section_list)
+ : SymbolContextScope(), m_uid(symbol.id.value_or(0)),
+ m_type_data_resolved(false), m_is_synthetic(false), m_is_debug(false),
+ m_is_external(false), m_size_is_sibling(false),
+ m_size_is_synthesized(false), m_size_is_valid(symbol.size.has_value()),
+ m_demangled_is_synthesized(false), m_contains_linker_annotations(false),
+ m_is_weak(false), m_type(symbol.type.value_or(eSymbolTypeAny)),
+ m_mangled(symbol.name), m_addr_range() {
+ // Without a section list there's nothing more we can do.
+ if (!section_list)
+ return;
+
+ const uint64_t size = symbol.size.value_or(0);
+
+ // If we're given a section ID, assume the value is an offset.
+ if (symbol.section_id && section_list) {
+ if (SectionSP section_sp =
+ section_list->FindSectionByID(*symbol.section_id)) {
+ m_addr_range = AddressRange(section_sp, symbol.value, size);
+ return;
+ }
+ }
+
+ // If we're only given a value, assume the value is an address.
+ if (SectionSP section_sp =
+ section_list->FindSectionContainingFileAddress(symbol.value)) {
+ m_addr_range = AddressRange(
+ section_sp, symbol.value - section_sp->GetFileAddress(), size);
+ return;
+ }
+}
+
Symbol::Symbol(uint32_t symID, llvm::StringRef name, SymbolType type,
bool external, bool is_debug, bool is_trampoline,
bool is_artificial, const lldb::SectionSP §ion_sp,
@@ -622,14 +655,14 @@
const bool is_addr = data.GetU8(offset_ptr) != 0;
const uint64_t value = data.GetU64(offset_ptr);
if (is_addr) {
- m_addr_range.GetBaseAddress().ResolveAddressUsingFileSections(
- value, section_list);
+ m_addr_range.GetBaseAddress().ResolveAddressUsingFileSections(value,
+ section_list);
} else {
m_addr_range.GetBaseAddress().Clear();
m_addr_range.GetBaseAddress().SetOffset(value);
}
m_addr_range.SetByteSize(data.GetU64(offset_ptr));
- m_flags = data.GetU32(offset_ptr);
+ m_flags = data.GetU32(offset_ptr);
return true;
}
@@ -723,3 +756,55 @@
return false;
return true;
}
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
+ llvm::json::Path path) {
+ llvm::json::ObjectMapper o(value, path);
+ return o && o.map("value", symbol.value) && o.map("size", symbol.size) &&
+ o.map("id", symbol.id) && o.map("section_id", symbol.section_id) &&
+ o.map("type", symbol.type) && o.map("name", symbol.name);
+}
+
+bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
+ llvm::json::Path path) {
+ if (auto str = value.getAsString()) {
+ type = llvm::StringSwitch<lldb::SymbolType>(*str)
+ .Case("absolute", eSymbolTypeAbsolute)
+ .Case("code", eSymbolTypeCode)
+ .Case("resolver", eSymbolTypeResolver)
+ .Case("data", eSymbolTypeData)
+ .Case("trampoline", eSymbolTypeTrampoline)
+ .Case("runtime", eSymbolTypeRuntime)
+ .Case("exception", eSymbolTypeException)
+ .Case("sourcefile", eSymbolTypeSourceFile)
+ .Case("headerfile", eSymbolTypeHeaderFile)
+ .Case("objectfile", eSymbolTypeObjectFile)
+ .Case("commonblock", eSymbolTypeCommonBlock)
+ .Case("block", eSymbolTypeBlock)
+ .Case("local", eSymbolTypeLocal)
+ .Case("param", eSymbolTypeParam)
+ .Case("variable", eSymbolTypeVariable)
+ .Case("variableType", eSymbolTypeVariableType)
+ .Case("lineentry", eSymbolTypeLineEntry)
+ .Case("lineheader", eSymbolTypeLineHeader)
+ .Case("scopebegin", eSymbolTypeScopeBegin)
+ .Case("scopeend", eSymbolTypeScopeEnd)
+ .Case("additional,", eSymbolTypeAdditional)
+ .Case("compiler", eSymbolTypeCompiler)
+ .Case("instrumentation", eSymbolTypeInstrumentation)
+ .Case("undefined", eSymbolTypeUndefined)
+ .Case("objcclass", eSymbolTypeObjCClass)
+ .Case("objcmetaClass", eSymbolTypeObjCMetaClass)
+ .Case("objcivar", eSymbolTypeObjCIVar)
+ .Case("reexporte", eSymbolTypeReExported)
+ .Default(eSymbolTypeInvalid);
+ return true;
+ }
+ path.report("expected string");
+ return false;
+}
+} // namespace json
+} // namespace llvm
Index: lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h
@@ -0,0 +1,110 @@
+//===-- SymbolFileJSON.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_SYMBOLFILE_JSON_SYMBOLFILETEXT_H
+#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_JSON_SYMBOLFILETEXT_H
+
+#include <map>
+#include <optional>
+#include <vector>
+
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+namespace lldb_private {
+
+class SymbolFileJSON : public lldb_private::SymbolFileCommon {
+ /// LLVM RTTI support.
+ static char ID;
+
+public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFileCommon::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
+ SymbolFileJSON(lldb::ObjectFileSP objfile_sp);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic() { return "text"; }
+
+ static llvm::StringRef GetPluginDescriptionStatic();
+
+ static lldb_private::SymbolFile *
+ CreateInstance(lldb::ObjectFileSP objfile_sp);
+
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+ uint32_t CalculateAbilities() override;
+
+ lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override {
+ return lldb::eLanguageTypeUnknown;
+ }
+
+ size_t ParseFunctions(CompileUnit &comp_unit) override { return 0; }
+
+ bool ParseLineTable(CompileUnit &comp_unit) override { return false; }
+
+ bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; }
+
+ bool ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) override {
+ return false;
+ }
+
+ size_t ParseTypes(CompileUnit &cu) override { return 0; }
+
+ bool ParseImportedModules(
+ const SymbolContext &sc,
+ std::vector<lldb_private::SourceModule> &imported_modules) override {
+ return false;
+ }
+
+ size_t ParseBlocksRecursive(Function &func) override { return 0; }
+
+ size_t ParseVariablesForContext(const SymbolContext &sc) override {
+ return 0;
+ }
+
+ uint32_t CalculateNumCompileUnits() override { return 0; }
+
+ lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
+
+ Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; }
+ std::optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override {
+ return std::nullopt;
+ }
+
+ bool CompleteType(CompilerType &compiler_type) override { return false; }
+
+ uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContext &sc) override;
+
+ void GetTypes(lldb_private::SymbolContextScope *sc_scope,
+ lldb::TypeClass type_mask,
+ lldb_private::TypeList &type_list) override;
+
+ void AddSymbols(Symtab &symtab) override;
+
+private:
+ lldb::addr_t GetBaseFileAddress();
+
+ std::vector<std::pair<uint64_t, std::string>> m_symbols;
+};
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_JSON_SYMBOLFILETEXT_H
Index: lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.cpp
@@ -0,0 +1,105 @@
+//===-- SymbolFileJSON.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 "SymbolFileJSON.h"
+
+#include "Plugins/ObjectFile/JSON/ObjectFileJSON.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Symtab.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Timer.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <memory>
+#include <optional>
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(SymbolFileJSON)
+
+char SymbolFileJSON::ID;
+
+SymbolFileJSON::SymbolFileJSON(lldb::ObjectFileSP objfile_sp)
+ : SymbolFileCommon(std::move(objfile_sp)) {}
+
+void SymbolFileJSON::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+}
+
+void SymbolFileJSON::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+llvm::StringRef SymbolFileJSON::GetPluginDescriptionStatic() {
+ return "Reads debug symbols from a textual symbol table.";
+}
+
+SymbolFile *SymbolFileJSON::CreateInstance(ObjectFileSP objfile_sp) {
+ return new SymbolFileJSON(std::move(objfile_sp));
+}
+
+uint32_t SymbolFileJSON::CalculateAbilities() {
+ if (!m_objfile_sp || !llvm::isa<ObjectFileJSON>(*m_objfile_sp))
+ return 0;
+
+ return GlobalVariables | Functions;
+}
+
+uint32_t SymbolFileJSON::ResolveSymbolContext(const Address &so_addr,
+ SymbolContextItem resolve_scope,
+ SymbolContext &sc) {
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ if (m_objfile_sp->GetSymtab() == nullptr)
+ return 0;
+
+ uint32_t resolved_flags = 0;
+ if (resolve_scope & eSymbolContextSymbol) {
+ sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress(
+ so_addr.GetFileAddress());
+ if (sc.symbol)
+ resolved_flags |= eSymbolContextSymbol;
+ }
+ return resolved_flags;
+}
+
+CompUnitSP SymbolFileJSON::ParseCompileUnitAtIndex(uint32_t idx) { return {}; }
+
+void SymbolFileJSON::GetTypes(SymbolContextScope *sc_scope, TypeClass type_mask,
+ lldb_private::TypeList &type_list) {}
+
+void SymbolFileJSON::AddSymbols(Symtab &symtab) {
+ if (!m_objfile_sp)
+ return;
+
+ Symtab *json_symtab = m_objfile_sp->GetSymtab();
+ if (!json_symtab)
+ return;
+
+ if (&symtab == json_symtab)
+ return;
+
+ // Merge the two symbol tables.
+ const size_t num_new_symbols = json_symtab->GetNumSymbols();
+ for (size_t i = 0; i < num_new_symbols; ++i) {
+ Symbol *s = json_symtab->SymbolAtIndex(i);
+ symtab.AddSymbol(*s);
+ }
+ symtab.Finalize();
+}
Index: lldb/source/Plugins/SymbolFile/JSON/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/JSON/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_lldb_library(lldbPluginSymbolFileJSON PLUGIN
+ SymbolFileJSON.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbSymbol
+ )
Index: lldb/source/Plugins/SymbolFile/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/SymbolFile/CMakeLists.txt
+++ lldb/source/Plugins/SymbolFile/CMakeLists.txt
@@ -1,5 +1,6 @@
add_subdirectory(Breakpad)
add_subdirectory(DWARF)
+add_subdirectory(JSON)
add_subdirectory(NativePDB)
add_subdirectory(PDB)
add_subdirectory(Symtab)
Index: lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h
@@ -0,0 +1,119 @@
+//===-- 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 eTypeDebugInfo; }
+
+ 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;
+ };
+
+ struct Body {
+ std::vector<JSONSymbol> symbols;
+ };
+
+private:
+ ArchSpec m_arch;
+ UUID m_uuid;
+ std::vector<JSONSymbol> m_symbols;
+
+ 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, std::vector<JSONSymbol> symbols);
+};
+
+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
Index: lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
@@ -0,0 +1,169 @@
+//===-- 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;
+
+ if (data_sp->GetByteSize() < length) {
+ data_sp = MapFileData(*file, length, file_offset);
+ if (!data_sp)
+ return nullptr;
+ data_offset = 0;
+ }
+
+ auto text =
+ llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));
+
+ Expected<json::Value> json = json::parse(text);
+ if (!json) {
+ llvm::consumeError(json.takeError());
+ return nullptr;
+ }
+
+ json::Path::Root root;
+ Header header;
+ if (!fromJSON(*json, header, root))
+ return nullptr;
+
+ ArchSpec arch(header.triple);
+ UUID uuid;
+ uuid.SetFromStringRef(header.uuid);
+
+ Body body;
+ fromJSON(*json, body, root);
+
+ return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset,
+ length, std::move(arch), std::move(uuid),
+ std::move(body.symbols));
+}
+
+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;
+
+ auto text =
+ llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));
+
+ Expected<json::Value> json = json::parse(text);
+ if (!json) {
+ llvm::consumeError(json.takeError());
+ return 0;
+ }
+
+ json::Path::Root root;
+ Header header;
+ if (!fromJSON(*json, header, root))
+ 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, std::vector<JSONSymbol> symbols)
+ : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
+ m_arch(std::move(arch)), m_uuid(std::move(uuid)),
+ m_symbols(std::move(symbols)) {}
+
+bool ObjectFileJSON::ParseHeader() {
+ // We already parsed the header during initialization.
+ return true;
+}
+
+void ObjectFileJSON::ParseSymtab(Symtab &symtab) {
+ SectionList *section_list = GetModule()->GetSectionList();
+ for (JSONSymbol symbol : m_symbols)
+ symtab.AddSymbol(Symbol(symbol, section_list));
+ symtab.Finalize();
+}
+
+void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {}
+
+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);
+}
+
+bool fromJSON(const json::Value &value, ObjectFileJSON::Body &body,
+ json::Path path) {
+ json::ObjectMapper o(value, path);
+ return o && o.map("symbols", body.symbols);
+}
+
+} // namespace lldb_private
Index: lldb/source/Plugins/ObjectFile/JSON/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/JSON/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_lldb_library(lldbPluginObjectFileJSON PLUGIN
+ ObjectFileJSON.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+ TargetParser
+ )
Index: lldb/source/Plugins/ObjectFile/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/ObjectFile/CMakeLists.txt
+++ lldb/source/Plugins/ObjectFile/CMakeLists.txt
@@ -1,6 +1,7 @@
add_subdirectory(Breakpad)
add_subdirectory(ELF)
add_subdirectory(JIT)
+add_subdirectory(JSON)
add_subdirectory(Mach-O)
add_subdirectory(Minidump)
add_subdirectory(PDB)
Index: lldb/include/lldb/Symbol/Symbol.h
===================================================================
--- lldb/include/lldb/Symbol/Symbol.h
+++ lldb/include/lldb/Symbol/Symbol.h
@@ -11,12 +11,23 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Mangled.h"
+#include "lldb/Core/Section.h"
#include "lldb/Symbol/SymbolContextScope.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
+#include "llvm/Support/JSON.h"
namespace lldb_private {
+struct JSONSymbol {
+ uint64_t value;
+ std::optional<uint64_t> size;
+ std::optional<uint64_t> id;
+ std::optional<uint64_t> section_id;
+ std::optional<lldb::SymbolType> type;
+ std::string name;
+};
+
class Symbol : public SymbolContextScope {
public:
// ObjectFile readers can classify their symbol table entries and searches
@@ -24,6 +35,8 @@
// drastically different meanings and sorting requirements.
Symbol();
+ Symbol(const JSONSymbol &symbol, SectionList *section_list);
+
Symbol(uint32_t symID, llvm::StringRef name, lldb::SymbolType type,
bool external, bool is_debug, bool is_trampoline, bool is_artificial,
const lldb::SectionSP §ion_sp, lldb::addr_t value,
@@ -187,7 +200,7 @@
bool IsWeak() const { return m_is_weak; }
- void SetIsWeak (bool b) { m_is_weak = b; }
+ void SetIsWeak(bool b) { m_is_weak = b; }
bool GetByteSizeIsValid() const { return m_size_is_valid; }
@@ -332,4 +345,16 @@
} // namespace lldb_private
+namespace llvm {
+namespace json {
+
+bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
+ llvm::json::Path path);
+
+bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
+ llvm::json::Path path);
+
+} // namespace json
+} // namespace llvm
+
#endif // LLDB_SYMBOL_SYMBOL_H
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits