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 ConstString ObjectFileBreakpad::GetPluginNameStatic() {
60  static ConstString g_name("breakpad");
61  return g_name;
62 }
63 
64 ObjectFile *ObjectFileBreakpad::CreateInstance(
65  const ModuleSP &module_sp, DataBufferSP &data_sp, offset_t data_offset,
66  const FileSpec *file, offset_t file_offset, offset_t length) {
67  if (!data_sp) {
68  data_sp = MapFileData(*file, length, file_offset);
69  if (!data_sp)
70  return nullptr;
71  data_offset = 0;
72  }
73  auto text = toStringRef(data_sp->GetData());
74  llvm::Optional<Header> header = Header::parse(text);
75  if (!header)
76  return nullptr;
77 
78  // Update the data to contain the entire file if it doesn't already
79  if (data_sp->GetByteSize() < length) {
80  data_sp = MapFileData(*file, length, file_offset);
81  if (!data_sp)
82  return nullptr;
83  data_offset = 0;
84  }
85 
86  return new ObjectFileBreakpad(module_sp, data_sp, data_offset, file,
87  file_offset, length, std::move(header->arch),
88  std::move(header->uuid));
89 }
90 
91 ObjectFile *ObjectFileBreakpad::CreateMemoryInstance(
92  const ModuleSP &module_sp, DataBufferSP &data_sp,
93  const ProcessSP &process_sp, addr_t header_addr) {
94  return nullptr;
95 }
96 
97 size_t ObjectFileBreakpad::GetModuleSpecifications(
98  const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
99  offset_t file_offset, offset_t length, ModuleSpecList &specs) {
100  auto text = toStringRef(data_sp->GetData());
101  llvm::Optional<Header> header = Header::parse(text);
102  if (!header)
103  return 0;
104  ModuleSpec spec(file, std::move(header->arch));
105  spec.GetUUID() = std::move(header->uuid);
106  specs.Append(spec);
107  return 1;
108 }
109 
110 ObjectFileBreakpad::ObjectFileBreakpad(const ModuleSP &module_sp,
111  DataBufferSP &data_sp,
112  offset_t data_offset,
113  const FileSpec *file, offset_t offset,
114  offset_t length, ArchSpec arch,
115  UUID uuid)
116  : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
117  m_arch(std::move(arch)), m_uuid(std::move(uuid)) {}
118 
120  // We already parsed the header during initialization.
121  return true;
122 }
123 
125  // TODO
126  return nullptr;
127 }
128 
129 void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
130  if (m_sections_up)
131  return;
132  m_sections_up = std::make_unique<SectionList>();
133 
134  llvm::Optional<Record::Kind> current_section;
135  offset_t section_start;
136  llvm::StringRef text = toStringRef(m_data.GetData());
137  uint32_t next_section_id = 1;
138  auto maybe_add_section = [&](const uint8_t *end_ptr) {
139  if (!current_section)
140  return; // We have been called before parsing the first line.
141 
142  offset_t end_offset = end_ptr - m_data.GetDataStart();
143  auto section_sp = std::make_shared<Section>(
144  GetModule(), this, next_section_id++,
145  ConstString(toString(*current_section)), eSectionTypeOther,
146  /*file_vm_addr*/ 0, /*vm_size*/ 0, section_start,
147  end_offset - section_start, /*log2align*/ 0, /*flags*/ 0);
148  m_sections_up->AddSection(section_sp);
149  unified_section_list.AddSection(section_sp);
150  };
151  while (!text.empty()) {
152  llvm::StringRef line;
153  std::tie(line, text) = text.split('\n');
154 
155  llvm::Optional<Record::Kind> next_section = Record::classify(line);
156  if (next_section == Record::Line) {
157  // Line records logically belong to the preceding Func record, so we put
158  // them in the same section.
159  next_section = Record::Func;
160  }
161  if (next_section == current_section)
162  continue;
163 
164  // Changing sections, finish off the previous one, if there was any.
165  maybe_add_section(line.bytes_begin());
166  // And start a new one.
167  current_section = next_section;
168  section_start = line.bytes_begin() - m_data.GetDataStart();
169  }
170  // Finally, add the last section.
171  maybe_add_section(m_data.GetDataEnd());
172 }
lldb_private::breakpad::Record::Line
@ Line
Definition: BreakpadRecords.h:23
lldb_private::UUID
Definition: UUID.h:23
lldb_private::ArchSpec
Definition: ArchSpec.h:33
ModuleSpec.h
lldb_private::ModuleSpecList
Definition: ModuleSpec.h:280
lldb_private::ModuleSpecList::Append
void Append(const ModuleSpec &spec)
Definition: ModuleSpec.h:313
lldb_private::Module
Definition: Module.h:84
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:104
lldb_private::SectionList::AddSection
size_t AddSection(const lldb::SectionSP &section_sp)
Definition: Section.cpp:407
lldb_private::FileSpec
Definition: FileSpec.h:56
ID
static char ID
Definition: IRDynamicChecks.cpp:32
lldb_private::breakpad::toString
llvm::StringRef toString(Record::Kind K)
Definition: BreakpadRecords.cpp:483
lldb_private::DataExtractor::GetDataEnd
const uint8_t * GetDataEnd() const
Get the data end pointer.
Definition: DataExtractor.h:406
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:119
lldb_private::breakpad::ObjectFileBreakpad::GetSymtab
Symtab * GetSymtab() override
Gets the symbol table for the currently selected architecture (and object for archives).
Definition: ObjectFileBreakpad.cpp:124
lldb::eSectionTypeOther
@ eSectionTypeOther
Definition: lldb-enumerations.h:697
lldb_private::breakpad
Definition: BreakpadRecords.h:19
lldb_private::ModuleSpec
Definition: ModuleSpec.h:26
lldb_private::Symtab
Definition: Symtab.h:22
lldb_private::breakpad::ObjectFileBreakpad::CreateSections
void CreateSections(SectionList &unified_section_list) override
Definition: ObjectFileBreakpad.cpp:129
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:706
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:23
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:125
lldb_private::breakpad::ObjectFileBreakpad
Definition: ObjectFileBreakpad.h:18
BreakpadRecords.h
lldb
Definition: SBAddress.h:15
ObjectFileBreakpad.h
lldb_private::ObjectFile
Definition: ObjectFile.h:58
lldb_private::ObjectFile::m_sections_up
std::unique_ptr< lldb_private::SectionList > m_sections_up
Definition: ObjectFile.h:709