brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 33673f1 Raw
170 lines · cpp
1//===-- ObjectFileBreakpad.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/Breakpad/ObjectFileBreakpad.h"10#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"11#include "lldb/Core/ModuleSpec.h"12#include "lldb/Core/PluginManager.h"13#include "lldb/Core/Section.h"14#include <optional>15 16using namespace lldb;17using namespace lldb_private;18using namespace lldb_private::breakpad;19 20LLDB_PLUGIN_DEFINE(ObjectFileBreakpad)21 22namespace {23struct Header {24  ArchSpec arch;25  UUID uuid;26  static std::optional<Header> parse(llvm::StringRef text);27};28} // namespace29 30std::optional<Header> Header::parse(llvm::StringRef text) {31  llvm::StringRef line;32  std::tie(line, text) = text.split('\n');33  auto Module = ModuleRecord::parse(line);34  if (!Module)35    return std::nullopt;36 37  llvm::Triple triple;38  triple.setArch(Module->Arch);39  triple.setOS(Module->OS);40 41  std::tie(line, text) = text.split('\n');42 43  auto Info = InfoRecord::parse(line);44  UUID uuid = Info && Info->ID ? Info->ID : Module->ID;45  return Header{ArchSpec(triple), std::move(uuid)};46}47 48char ObjectFileBreakpad::ID;49 50void ObjectFileBreakpad::Initialize() {51  PluginManager::RegisterPlugin(GetPluginNameStatic(),52                                GetPluginDescriptionStatic(), CreateInstance,53                                CreateMemoryInstance, GetModuleSpecifications);54}55 56void ObjectFileBreakpad::Terminate() {57  PluginManager::UnregisterPlugin(CreateInstance);58}59 60ObjectFile *ObjectFileBreakpad::CreateInstance(61    const ModuleSP &module_sp, DataBufferSP data_sp, offset_t data_offset,62    const FileSpec *file, offset_t file_offset, offset_t length) {63  if (!data_sp) {64    data_sp = MapFileData(*file, length, file_offset);65    if (!data_sp)66      return nullptr;67    data_offset = 0;68  }69  auto text = toStringRef(data_sp->GetData());70  std::optional<Header> header = Header::parse(text);71  if (!header)72    return nullptr;73 74  // Update the data to contain the entire file if it doesn't already75  if (data_sp->GetByteSize() < length) {76    data_sp = MapFileData(*file, length, file_offset);77    if (!data_sp)78      return nullptr;79    data_offset = 0;80  }81 82  return new ObjectFileBreakpad(module_sp, data_sp, data_offset, file,83                                file_offset, length, std::move(header->arch),84                                std::move(header->uuid));85}86 87ObjectFile *ObjectFileBreakpad::CreateMemoryInstance(88    const ModuleSP &module_sp, WritableDataBufferSP data_sp,89    const ProcessSP &process_sp, addr_t header_addr) {90  return nullptr;91}92 93size_t ObjectFileBreakpad::GetModuleSpecifications(94    const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,95    offset_t file_offset, offset_t length, ModuleSpecList &specs) {96  auto text = toStringRef(data_sp->GetData());97  std::optional<Header> header = Header::parse(text);98  if (!header)99    return 0;100  ModuleSpec spec(file, std::move(header->arch));101  spec.GetUUID() = std::move(header->uuid);102  specs.Append(spec);103  return 1;104}105 106ObjectFileBreakpad::ObjectFileBreakpad(const ModuleSP &module_sp,107                                       DataBufferSP &data_sp,108                                       offset_t data_offset,109                                       const FileSpec *file, offset_t offset,110                                       offset_t length, ArchSpec arch,111                                       UUID uuid)112    : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),113      m_arch(std::move(arch)), m_uuid(std::move(uuid)) {}114 115bool ObjectFileBreakpad::ParseHeader() {116  // We already parsed the header during initialization.117  return true;118}119 120void ObjectFileBreakpad::ParseSymtab(Symtab &symtab) {121  // Nothing to do for breakpad files, all information is parsed as debug info122  // which means "lldb_private::Function" objects are used, or symbols are added123  // by the SymbolFileBreakpad::AddSymbols(...) function in the symbol file.124}125 126void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {127  if (m_sections_up)128    return;129  m_sections_up = std::make_unique<SectionList>();130 131  std::optional<Record::Kind> current_section;132  offset_t section_start;133  llvm::StringRef text = toStringRef(m_data.GetData());134  uint32_t next_section_id = 1;135  auto maybe_add_section = [&](const uint8_t *end_ptr) {136    if (!current_section)137      return; // We have been called before parsing the first line.138 139    offset_t end_offset = end_ptr - m_data.GetDataStart();140    auto section_sp = std::make_shared<Section>(141        GetModule(), this, next_section_id++,142        ConstString(toString(*current_section)), eSectionTypeOther,143        /*file_vm_addr*/ 0, /*vm_size*/ 0, section_start,144        end_offset - section_start, /*log2align*/ 0, /*flags*/ 0);145    m_sections_up->AddSection(section_sp);146    unified_section_list.AddSection(section_sp);147  };148  while (!text.empty()) {149    llvm::StringRef line;150    std::tie(line, text) = text.split('\n');151 152    std::optional<Record::Kind> next_section = Record::classify(line);153    if (next_section == Record::Line || next_section == Record::Inline) {154      // Line/Inline records logically belong to the preceding Func record, so155      // we put them in the same section.156      next_section = Record::Func;157    }158    if (next_section == current_section)159      continue;160 161    // Changing sections, finish off the previous one, if there was any.162    maybe_add_section(line.bytes_begin());163    // And start a new one.164    current_section = next_section;165    section_start = line.bytes_begin() - m_data.GetDataStart();166  }167  // Finally, add the last section.168  maybe_add_section(m_data.GetDataEnd());169}170