LLDB  mainline
ObjectFileBreakpad.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
11 #include "lldb/Core/ModuleSpec.h"
13 #include "lldb/Core/Section.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 using namespace lldb_private::breakpad;
18 
20 
21 namespace {
22 struct Header {
23  ArchSpec arch;
24  UUID uuid;
25  static llvm::Optional<Header> parse(llvm::StringRef text);
26 };
27 } // namespace
28 
29 llvm::Optional<Header> Header::parse(llvm::StringRef text) {
30  llvm::StringRef line;
31  std::tie(line, text) = text.split('\n');
32  auto Module = ModuleRecord::parse(line);
33  if (!Module)
34  return llvm::None;
35 
36  llvm::Triple triple;
37  triple.setArch(Module->Arch);
38  triple.setOS(Module->OS);
39 
40  std::tie(line, text) = text.split('\n');
41 
42  auto Info = InfoRecord::parse(line);
43  UUID uuid = Info && Info->ID ? Info->ID : Module->ID;
44  return Header{ArchSpec(triple), std::move(uuid)};
45 }
46 
48 
49 void ObjectFileBreakpad::Initialize() {
50  PluginManager::RegisterPlugin(GetPluginNameStatic(),
51  GetPluginDescriptionStatic(), CreateInstance,
52  CreateMemoryInstance, GetModuleSpecifications);
53 }
54 
55 void ObjectFileBreakpad::Terminate() {
56  PluginManager::UnregisterPlugin(CreateInstance);
57 }
58 
59 ObjectFile *ObjectFileBreakpad::CreateInstance(
60  const ModuleSP &module_sp, DataBufferSP data_sp, offset_t data_offset,
61  const FileSpec *file, offset_t file_offset, offset_t length) {
62  if (!data_sp) {
63  data_sp = MapFileData(*file, length, file_offset);
64  if (!data_sp)
65  return nullptr;
66  data_offset = 0;
67  }
68  auto text = toStringRef(data_sp->GetData());
69  llvm::Optional<Header> header = Header::parse(text);
70  if (!header)
71  return nullptr;
72 
73  // Update the data to contain the entire file if it doesn't already
74  if (data_sp->GetByteSize() < length) {
75  data_sp = MapFileData(*file, length, file_offset);
76  if (!data_sp)
77  return nullptr;
78  data_offset = 0;
79  }
80 
81  return new ObjectFileBreakpad(module_sp, data_sp, data_offset, file,
82  file_offset, length, std::move(header->arch),
83  std::move(header->uuid));
84 }
85 
86 ObjectFile *ObjectFileBreakpad::CreateMemoryInstance(
87  const ModuleSP &module_sp, WritableDataBufferSP data_sp,
88  const ProcessSP &process_sp, addr_t header_addr) {
89  return nullptr;
90 }
91 
92 size_t ObjectFileBreakpad::GetModuleSpecifications(
93  const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
94  offset_t file_offset, offset_t length, ModuleSpecList &specs) {
95  auto text = toStringRef(data_sp->GetData());
96  llvm::Optional<Header> header = Header::parse(text);
97  if (!header)
98  return 0;
99  ModuleSpec spec(file, std::move(header->arch));
100  spec.GetUUID() = std::move(header->uuid);
101  specs.Append(spec);
102  return 1;
103 }
104 
105 ObjectFileBreakpad::ObjectFileBreakpad(const ModuleSP &module_sp,
106  DataBufferSP &data_sp,
107  offset_t data_offset,
108  const FileSpec *file, offset_t offset,
109  offset_t length, ArchSpec arch,
110  UUID uuid)
111  : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
112  m_arch(std::move(arch)), m_uuid(std::move(uuid)) {}
113 
115  // We already parsed the header during initialization.
116  return true;
117 }
118 
120  // Nothing to do for breakpad files, all information is parsed as debug info
121  // which means "lldb_private::Function" objects are used, or symbols are added
122  // by the SymbolFileBreakpad::AddSymbols(...) function in the symbol file.
123 }
124 
125 void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
126  if (m_sections_up)
127  return;
128  m_sections_up = std::make_unique<SectionList>();
129 
130  llvm::Optional<Record::Kind> current_section;
131  offset_t section_start;
132  llvm::StringRef text = toStringRef(m_data.GetData());
133  uint32_t next_section_id = 1;
134  auto maybe_add_section = [&](const uint8_t *end_ptr) {
135  if (!current_section)
136  return; // We have been called before parsing the first line.
137 
138  offset_t end_offset = end_ptr - m_data.GetDataStart();
139  auto section_sp = std::make_shared<Section>(
140  GetModule(), this, next_section_id++,
141  ConstString(toString(*current_section)), eSectionTypeOther,
142  /*file_vm_addr*/ 0, /*vm_size*/ 0, section_start,
143  end_offset - section_start, /*log2align*/ 0, /*flags*/ 0);
144  m_sections_up->AddSection(section_sp);
145  unified_section_list.AddSection(section_sp);
146  };
147  while (!text.empty()) {
148  llvm::StringRef line;
149  std::tie(line, text) = text.split('\n');
150 
151  llvm::Optional<Record::Kind> next_section = Record::classify(line);
152  if (next_section == Record::Line || next_section == Record::Inline) {
153  // Line/Inline records logically belong to the preceding Func record, so
154  // we put them in the same section.
155  next_section = Record::Func;
156  }
157  if (next_section == current_section)
158  continue;
159 
160  // Changing sections, finish off the previous one, if there was any.
161  maybe_add_section(line.bytes_begin());
162  // And start a new one.
163  current_section = next_section;
164  section_start = line.bytes_begin() - m_data.GetDataStart();
165  }
166  // Finally, add the last section.
167  maybe_add_section(m_data.GetDataEnd());
168 }
lldb_private::breakpad::Record::Line
@ Line
Definition: BreakpadRecords.h:30
lldb_private::UUID
Definition: UUID.h:23
lldb_private::ArchSpec
Definition: ArchSpec.h:33
ModuleSpec.h
lldb_private::ModuleSpecList
Definition: ModuleSpec.h:275
lldb_private::ModuleSpecList::Append
void Append(const ModuleSpec &spec)
Definition: ModuleSpec.h:308
lldb_private::Module
Definition: Module.h:85
lldb_private::SectionList
Definition: Section.h:34
lldb::offset_t
uint64_t offset_t
Definition: lldb-types.h:87
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
Section.h
lldb_private::ModuleSpec::GetUUID
UUID & GetUUID()
Definition: ModuleSpec.h:99
lldb_private::SectionList::AddSection
size_t AddSection(const lldb::SectionSP &section_sp)
Definition: Section.cpp:469
lldb_private::FileSpec
Definition: FileSpec.h:56
ID
static char ID
Definition: IRDynamicChecks.cpp:33
lldb_private::breakpad::toString
llvm::StringRef toString(Record::Kind K)
Definition: BreakpadRecords.cpp:560
lldb_private::DataExtractor::GetDataEnd
const uint8_t * GetDataEnd() const
Get the data end pointer.
Definition: DataExtractor.h:406
lldb_private::breakpad::Record::Inline
@ Inline
Definition: BreakpadRecords.h:28
lldb_private::DataExtractor::GetDataStart
const uint8_t * GetDataStart() const
Get the data start pointer.
Definition: DataExtractor.h:422
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::breakpad::ObjectFileBreakpad::ParseHeader
bool ParseHeader() override
Attempts to parse the object header.
Definition: ObjectFileBreakpad.cpp:114
lldb_private::breakpad::ObjectFileBreakpad::ParseSymtab
void ParseSymtab(lldb_private::Symtab &symtab) override
Parse the symbol table into the provides symbol table object.
Definition: ObjectFileBreakpad.cpp:119
lldb::eSectionTypeOther
@ eSectionTypeOther
Definition: lldb-enumerations.h:705
lldb_private::breakpad
Definition: BreakpadRecords.h:19
lldb_private::ModuleSpec
Definition: ModuleSpec.h:27
lldb_private::Symtab
Definition: Symtab.h:22
lldb_private::breakpad::ObjectFileBreakpad::CreateSections
void CreateSections(SectionList &unified_section_list) override
Definition: ObjectFileBreakpad.cpp:125
uint32_t
lldb_private::ObjectFile::m_data
DataExtractor m_data
The data for this object file so things can be parsed lazily.
Definition: ObjectFile.h:738
lldb_private::ModuleChild::GetModule
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
Definition: ModuleChild.cpp:24
PluginManager.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::breakpad::Record::Func
@ Func
Definition: BreakpadRecords.h:27
lldb_private::DataExtractor::GetData
const void * GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const
Extract length bytes from *offset_ptr.
Definition: DataExtractor.h:337
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::breakpad::Record::classify
static llvm::Optional< Kind > classify(llvm::StringRef Line)
Attempt to guess the kind of the record present in the argument without doing a full parse.
Definition: BreakpadRecords.cpp:129
lldb_private::breakpad::ObjectFileBreakpad
Definition: ObjectFileBreakpad.h:18
BreakpadRecords.h
lldb
Definition: SBAddress.h:15
ObjectFileBreakpad.h
lldb_private::ObjectFile
Definition: ObjectFile.h:60
lldb_private::ObjectFile::m_sections_up
std::unique_ptr< lldb_private::SectionList > m_sections_up
Definition: ObjectFile.h:742