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 if (data_sp->GetByteSize() < length) { 53 data_sp = MapFileData(*file, length, file_offset); 54 if (!data_sp) 55 return nullptr; 56 data_offset = 0; 57 } 58 59 auto text = 60 llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes())); 61 62 Expected<json::Value> json = json::parse(text); 63 if (!json) { 64 llvm::consumeError(json.takeError()); 65 return nullptr; 66 } 67 68 json::Path::Root root; 69 Header header; 70 if (!fromJSON(*json, header, root)) 71 return nullptr; 72 73 ArchSpec arch(header.triple); 74 UUID uuid; 75 uuid.SetFromStringRef(header.uuid); 76 77 Body body; 78 fromJSON(*json, body, root); 79 80 return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset, 81 length, std::move(arch), std::move(uuid), 82 std::move(body.symbols)); 83 } 84 85 ObjectFile *ObjectFileJSON::CreateMemoryInstance(const ModuleSP &module_sp, 86 WritableDataBufferSP data_sp, 87 const ProcessSP &process_sp, 88 addr_t header_addr) { 89 return nullptr; 90 } 91 92 size_t ObjectFileJSON::GetModuleSpecifications( 93 const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset, 94 offset_t file_offset, offset_t length, ModuleSpecList &specs) { 95 96 if (!MagicBytesMatch(data_sp, data_offset, data_sp->GetByteSize())) 97 return 0; 98 99 auto text = 100 llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes())); 101 102 Expected<json::Value> json = json::parse(text); 103 if (!json) { 104 llvm::consumeError(json.takeError()); 105 return 0; 106 } 107 108 json::Path::Root root; 109 Header header; 110 if (!fromJSON(*json, header, root)) 111 return 0; 112 113 ArchSpec arch(header.triple); 114 UUID uuid; 115 uuid.SetFromStringRef(header.uuid); 116 117 ModuleSpec spec(file, std::move(arch)); 118 spec.GetUUID() = std::move(uuid); 119 specs.Append(spec); 120 return 1; 121 } 122 123 ObjectFileJSON::ObjectFileJSON(const ModuleSP &module_sp, DataBufferSP &data_sp, 124 offset_t data_offset, const FileSpec *file, 125 offset_t offset, offset_t length, ArchSpec arch, 126 UUID uuid, std::vector<JSONSymbol> symbols) 127 : ObjectFile(module_sp, file, offset, length, data_sp, data_offset), 128 m_arch(std::move(arch)), m_uuid(std::move(uuid)), 129 m_symbols(std::move(symbols)) {} 130 131 bool ObjectFileJSON::ParseHeader() { 132 // We already parsed the header during initialization. 133 return true; 134 } 135 136 void ObjectFileJSON::ParseSymtab(Symtab &symtab) { 137 Log *log = GetLog(LLDBLog::Symbols); 138 SectionList *section_list = GetModule()->GetSectionList(); 139 for (JSONSymbol json_symbol : m_symbols) { 140 llvm::Expected<Symbol> symbol = Symbol::FromJSON(json_symbol, section_list); 141 if (!symbol) { 142 LLDB_LOG_ERROR(log, symbol.takeError(), "invalid symbol"); 143 continue; 144 } 145 symtab.AddSymbol(*symbol); 146 } 147 symtab.Finalize(); 148 } 149 150 void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {} 151 152 bool ObjectFileJSON::MagicBytesMatch(DataBufferSP data_sp, 153 lldb::addr_t data_offset, 154 lldb::addr_t data_length) { 155 DataExtractor data; 156 data.SetData(data_sp, data_offset, data_length); 157 lldb::offset_t offset = 0; 158 uint32_t magic = data.GetU8(&offset); 159 return magic == '{'; 160 } 161 162 namespace lldb_private { 163 164 bool fromJSON(const json::Value &value, ObjectFileJSON::Header &header, 165 json::Path path) { 166 json::ObjectMapper o(value, path); 167 return o && o.map("triple", header.triple) && o.map("uuid", header.uuid); 168 } 169 170 bool fromJSON(const json::Value &value, ObjectFileJSON::Body &body, 171 json::Path path) { 172 json::ObjectMapper o(value, path); 173 return o && o.map("symbols", body.symbols); 174 } 175 176 } // namespace lldb_private 177