JDevlieghere created this revision. JDevlieghere added reviewers: jingham, clayborg, labath, DavidSpickett, mib. Herald added a subscriber: kristof.beyls. Herald added a project: All. JDevlieghere requested review of this revision. Herald added a reviewer: jdoerfert. Herald added a subscriber: sstefan1. Herald added a project: LLDB.
Introduce a new object and symbol file format with the goal of mapping addresses to symbol names. I'd like to think of is as an extremely simple textual syntab. The new file format is extremely simple, it contains a triple, a UUID and a list of address to symbol name mapping. JSON is used for the encoding, but that's mostly an implementation detail: any other encoding could achieve the same thing. However I did purposely pick a human readable format. The new format is motivated by two use cases: 1. Stripped binaries: when a binary is stripped, you lose the ability to do thing like setting symbolic breakpoints. You can keep the unstripped binary around, but if all you need is the stripped symbols then that's a lot of overhead. Instead, we could save the stripped symbols to a file and load them in the debugger when needed. I want to extend `llvm-strip` to have a mode where it emits this new file format. 2. Interactive crashlogs: with interactive crashlogs, if we don't have the binary or the dSYM for a particular module, we currently show an unnamed symbol for those frames. This is a regression compared to the textual format, that has these frames pre-symbolicated. Given that this information is available in the JSON crashlog, we need a way to tell LLDB about it. With the new symbol file format, we can easily synthesize a symbol file for each of those modules and load them to symbolicate those frames. Here's an example of the file format: { "triple": "arm64-apple-macosx13.0.0", "uuid": "36D0CCE7-8ED2-3CA3-96B0-48C1764DA908", "symbols": [ { "name": "main", "addr": 4294983568 }, { "name": "foo", "addr": 4294983560 } ] } I've added a test case that illustrates the stripped binary workflow. For the interactive crashlogs, we'll need to extend the crashlog script. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D145180 Files: 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/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,80 @@ +""" 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) + + data = { + "triple": unstripped_module.GetTriple(), + "uuid": unstripped_module.GetUUIDString(), + "symbols": list() + } + data['symbols'].append({ + "name": + "main", + "addr": + unstripped_module.FindSymbol("main").addr.GetFileAddress() + }) + data['symbols'].append({ + "name": + "foo", + "addr": + unstripped_module.FindSymbol("foo").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/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,120 @@ +//===-- 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) { + auto json_object_file = dyn_cast_or_null<ObjectFileJSON>(m_objfile_sp.get()); + if (!json_object_file) + return; + + Log *log = GetLog(LLDBLog::Symbols); + Module &module = *m_objfile_sp->GetModule(); + const SectionList &list = *module.GetSectionList(); + + llvm::DenseSet<addr_t> found_symbol_addresses; + + for (ObjectFileJSON::Symbol symbol : json_object_file->GetSymbols()) { + SectionSP section_sp = list.FindSectionContainingFileAddress(symbol.addr); + if (!section_sp) { + LLDB_LOG(log, + "Ignoring symbol '{0}', whose address ({1:x}) is outside of the " + "object file. Mismatched symbol file?", + symbol.name, symbol.addr); + continue; + } + // Keep track of what addresses were already added so far and only add + // the symbol with the first address. + if (!found_symbol_addresses.insert(symbol.addr).second) + continue; + symtab.AddSymbol(Symbol( + /*symID*/ 0, Mangled(symbol.name), eSymbolTypeCode, + /*is_global*/ true, /*is_debug*/ false, + /*is_trampoline*/ false, /*is_artificial*/ false, + AddressRange(section_sp, symbol.addr - section_sp->GetFileAddress(), 0), + false, /*contains_linker_annotations*/ false, /*flags*/ 0)); + } + + 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,129 @@ +//===-- 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 Symbol { + uint64_t addr; + std::string name; + }; + + struct Symbols { + std::vector<Symbol> symbols; + }; + + std::vector<Symbol> GetSymbols() { return m_symbols; } + +private: + ArchSpec m_arch; + UUID m_uuid; + std::vector<Symbol> 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<Symbol> symbols); +}; + +bool fromJSON(const llvm::json::Value &value, ObjectFileJSON::Header &header, + llvm::json::Path path); + +bool fromJSON(const llvm::json::Value &value, ObjectFileJSON::Symbol &symbol, + llvm::json::Path path); + +bool fromJSON(const llvm::json::Value &value, ObjectFileJSON::Symbols &symbols, + 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,168 @@ +//===-- 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/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.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); + + json::Path::Root symbols_path("header"); + Symbols symbols; + fromJSON(*json, symbols, symbols_path); + + return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset, + length, std::move(arch), std::move(uuid), + std::move(symbols.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<Symbol> 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) { + // Nothing to do for JSON files, all information is parsed as debug info. +} + +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::Symbol &symbol, + json::Path path) { + json::ObjectMapper o(value, path); + return o && o.map("addr", symbol.addr) && o.map("name", symbol.name); +} + +bool fromJSON(const json::Value &value, ObjectFileJSON::Symbols &symbols, + json::Path path) { + json::ObjectMapper o(value, path); + return o && o.map("symbols", symbols.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)
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits