brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.1 KiB · 69885aa Raw
298 lines · cpp
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-exception6//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/Target/Target.h"16#include "lldb/Utility/LLDBLog.h"17#include "lldb/Utility/Log.h"18#include "llvm/ADT/DenseSet.h"19#include <optional>20 21using namespace llvm;22using namespace lldb;23using namespace lldb_private;24 25LLDB_PLUGIN_DEFINE(ObjectFileJSON)26 27char ObjectFileJSON::ID;28 29void ObjectFileJSON::Initialize() {30  PluginManager::RegisterPlugin(GetPluginNameStatic(),31                                GetPluginDescriptionStatic(), CreateInstance,32                                CreateMemoryInstance, GetModuleSpecifications);33}34 35void ObjectFileJSON::Terminate() {36  PluginManager::UnregisterPlugin(CreateInstance);37}38 39ObjectFile *40ObjectFileJSON::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,41                               offset_t data_offset, const FileSpec *file,42                               offset_t file_offset, offset_t length) {43  if (!data_sp) {44    data_sp = MapFileData(*file, length, file_offset);45    if (!data_sp)46      return nullptr;47    data_offset = 0;48  }49 50  if (!MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))51    return nullptr;52 53  // Update the data to contain the entire file if it doesn't already.54  if (data_sp->GetByteSize() < length) {55    data_sp = MapFileData(*file, length, file_offset);56    if (!data_sp)57      return nullptr;58    data_offset = 0;59  }60 61  Log *log = GetLog(LLDBLog::Symbols);62 63  auto text =64      llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));65 66  Expected<json::Value> json = json::parse(text);67  if (!json) {68    LLDB_LOG_ERROR(log, json.takeError(),69                   "failed to parse JSON object file: {0}");70    return nullptr;71  }72 73  json::Path::Root root;74  Header header;75  if (!fromJSON(*json, header, root)) {76    LLDB_LOG_ERROR(log, root.getError(),77                   "failed to parse JSON object file header: {0}");78    return nullptr;79  }80 81  ArchSpec arch(header.triple);82  UUID uuid;83  uuid.SetFromStringRef(header.uuid);84  Type type = header.type.value_or(eTypeDebugInfo);85 86  Body body;87  if (!fromJSON(*json, body, root)) {88    LLDB_LOG_ERROR(log, root.getError(),89                   "failed to parse JSON object file body: {0}");90    return nullptr;91  }92 93  return new ObjectFileJSON(module_sp, data_sp, data_offset, file, file_offset,94                            length, std::move(arch), std::move(uuid), type,95                            std::move(body.symbols), std::move(body.sections));96}97 98ObjectFile *ObjectFileJSON::CreateMemoryInstance(const ModuleSP &module_sp,99                                                 WritableDataBufferSP data_sp,100                                                 const ProcessSP &process_sp,101                                                 addr_t header_addr) {102  return nullptr;103}104 105size_t ObjectFileJSON::GetModuleSpecifications(106    const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,107    offset_t file_offset, offset_t length, ModuleSpecList &specs) {108  if (!MagicBytesMatch(data_sp, data_offset, data_sp->GetByteSize()))109    return 0;110 111  // Update the data to contain the entire file if it doesn't already.112  if (data_sp->GetByteSize() < length) {113    data_sp = MapFileData(file, length, file_offset);114    if (!data_sp)115      return 0;116    data_offset = 0;117  }118 119  Log *log = GetLog(LLDBLog::Symbols);120 121  auto text =122      llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes()));123 124  Expected<json::Value> json = json::parse(text);125  if (!json) {126    LLDB_LOG_ERROR(log, json.takeError(),127                   "failed to parse JSON object file: {0}");128    return 0;129  }130 131  json::Path::Root root;132  Header header;133  if (!fromJSON(*json, header, root)) {134    LLDB_LOG_ERROR(log, root.getError(),135                   "failed to parse JSON object file header: {0}");136    return 0;137  }138 139  ArchSpec arch(header.triple);140  UUID uuid;141  uuid.SetFromStringRef(header.uuid);142 143  ModuleSpec spec(file, std::move(arch));144  spec.GetUUID() = std::move(uuid);145  specs.Append(spec);146  return 1;147}148 149ObjectFileJSON::ObjectFileJSON(const ModuleSP &module_sp, DataBufferSP &data_sp,150                               offset_t data_offset, const FileSpec *file,151                               offset_t offset, offset_t length, ArchSpec arch,152                               UUID uuid, Type type,153                               std::vector<JSONSymbol> symbols,154                               std::vector<JSONSection> sections)155    : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),156      m_arch(std::move(arch)), m_uuid(std::move(uuid)), m_type(type),157      m_symbols(std::move(symbols)), m_sections(std::move(sections)) {}158 159bool ObjectFileJSON::ParseHeader() {160  // We already parsed the header during initialization.161  return true;162}163 164void ObjectFileJSON::ParseSymtab(Symtab &symtab) {165  Log *log = GetLog(LLDBLog::Symbols);166  SectionList *section_list = GetModule()->GetSectionList();167  for (JSONSymbol json_symbol : m_symbols) {168    llvm::Expected<Symbol> symbol = Symbol::FromJSON(json_symbol, section_list);169    if (!symbol) {170      LLDB_LOG_ERROR(log, symbol.takeError(), "invalid symbol: {0}");171      continue;172    }173    symtab.AddSymbol(*symbol);174  }175  symtab.Finalize();176}177 178void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {179  if (m_sections_up)180    return;181  m_sections_up = std::make_unique<SectionList>();182 183  lldb::user_id_t id = 0;184  for (const auto &json_section : m_sections) {185    auto make_section = [this, &id](const JSONSection &section,186                                    SectionSP parent_section_sp =187                                        nullptr) -> SectionSP {188      SectionSP section_sp;189      auto sect_id = section.user_id.value_or(id + 1);190      if (!section.user_id.has_value())191        ++id;192      const auto name = ConstString(section.name);193      const auto sect_type = section.type.value_or(eSectionTypeCode);194      const auto vm_addr = section.address.value_or(0);195      const auto vm_size = section.size.value_or(0);196      const auto file_offset = section.file_offset.value_or(0);197      const auto file_size = section.file_size.value_or(0);198      const auto log2align = section.log2align.value_or(0);199      const auto flags = section.flags.value_or(0);200      if (parent_section_sp) {201        section_sp = std::make_shared<Section>(202            parent_section_sp, GetModule(), this, sect_id, name, sect_type,203            vm_addr - parent_section_sp->GetFileAddress(), vm_size, file_offset,204            file_size, log2align, flags);205 206      } else {207        section_sp = std::make_shared<Section>(208            GetModule(), this, sect_id, name, sect_type, vm_addr, vm_size,209            file_offset, file_size, log2align, flags);210      }211      // Set permissions212      uint32_t permissions = 0;213      if (section.read.value_or(0))214        permissions |= lldb::ePermissionsReadable;215      if (section.write.value_or(0))216        permissions |= lldb::ePermissionsWritable;217      if (section.execute.value_or(0))218        permissions |= lldb::ePermissionsExecutable;219      if (permissions)220        section_sp->SetPermissions(permissions);221      section_sp->SetIsFake(section.fake.value_or(false));222      section_sp->SetIsEncrypted(section.encrypted.value_or(false));223      section_sp->SetIsThreadSpecific(section.thread_specific.value_or(false));224      return section_sp;225    };226    auto section_sp = make_section(json_section);227    for (const auto &subsection : json_section.subsections) {228      SectionSP subsection_sp = make_section(subsection, section_sp);229      section_sp->GetChildren().AddSection(subsection_sp);230    }231 232    m_sections_up->AddSection(section_sp);233    unified_section_list.AddSection(section_sp);234  }235}236 237bool ObjectFileJSON::SetLoadAddress(Target &target, lldb::addr_t value,238                                    bool value_is_offset) {239  Log *log(GetLog(LLDBLog::DynamicLoader));240  if (!m_sections_up)241    return true;242 243  addr_t slide = value;244  if (!value_is_offset) {245    addr_t lowest_addr = LLDB_INVALID_ADDRESS;246    for (const SectionSP &section_sp : *m_sections_up) {247      addr_t section_load_addr = section_sp->GetFileAddress();248      lowest_addr = std::min(lowest_addr, section_load_addr);249    }250    if (lowest_addr == LLDB_INVALID_ADDRESS)251      return false;252    slide = value - lowest_addr;253  }254 255  // Apply slide to each section's file address.256  for (const SectionSP &section_sp : *m_sections_up) {257    addr_t section_load_addr = section_sp->GetFileAddress();258    if (section_load_addr != LLDB_INVALID_ADDRESS) {259      LLDB_LOGF(260          log,261          "ObjectFileJSON::SetLoadAddress section %s to load addr 0x%" PRIx64,262          section_sp->GetName().AsCString(), section_load_addr + slide);263      target.SetSectionLoadAddress(section_sp, section_load_addr + slide,264                                   /*warn_multiple=*/true);265    }266  }267 268  return true;269}270 271bool ObjectFileJSON::MagicBytesMatch(DataBufferSP data_sp,272                                     lldb::addr_t data_offset,273                                     lldb::addr_t data_length) {274  DataExtractor data;275  data.SetData(data_sp, data_offset, data_length);276  lldb::offset_t offset = 0;277  uint32_t magic = data.GetU8(&offset);278  return magic == '{';279}280 281namespace lldb_private {282 283bool fromJSON(const json::Value &value, ObjectFileJSON::Header &header,284              json::Path path) {285  json::ObjectMapper o(value, path);286  return o && o.map("triple", header.triple) && o.map("uuid", header.uuid) &&287         o.map("type", header.type);288}289 290bool fromJSON(const json::Value &value, ObjectFileJSON::Body &body,291              json::Path path) {292  json::ObjectMapper o(value, path);293  return o && o.mapOptional("symbols", body.symbols) &&294         o.mapOptional("sections", body.sections);295}296 297} // namespace lldb_private298