summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
blob: 855653ec5ff95d865ac4237f05e4be5adb5150fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
//===-- SymbolFileBreakpad.cpp ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
#include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Utility/Log.h"
#include "llvm/ADT/StringExtras.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::breakpad;

namespace {
class LineIterator {
public:
  // begin iterator for sections of given type
  LineIterator(ObjectFile &obj, ConstString section_type)
      : m_obj(&obj), m_section_type(section_type), m_next_section_idx(0) {
    ++*this;
  }

  // end iterator
  explicit LineIterator(ObjectFile &obj)
      : m_obj(&obj),
        m_next_section_idx(m_obj->GetSectionList()->GetNumSections(0)) {}

  friend bool operator!=(const LineIterator &lhs, const LineIterator &rhs) {
    assert(lhs.m_obj == rhs.m_obj);
    if (lhs.m_next_section_idx != rhs.m_next_section_idx)
      return true;
    if (lhs.m_next_text.data() != rhs.m_next_text.data())
      return true;
    assert(lhs.m_current_text == rhs.m_current_text);
    assert(rhs.m_next_text == rhs.m_next_text);
    return false;
  }

  const LineIterator &operator++();
  llvm::StringRef operator*() const { return m_current_text; }

private:
  ObjectFile *m_obj;
  ConstString m_section_type;
  uint32_t m_next_section_idx;
  llvm::StringRef m_current_text;
  llvm::StringRef m_next_text;
};
} // namespace

const LineIterator &LineIterator::operator++() {
  const SectionList &list = *m_obj->GetSectionList();
  size_t num_sections = list.GetNumSections(0);
  while (m_next_text.empty() && m_next_section_idx < num_sections) {
    Section &sect = *list.GetSectionAtIndex(m_next_section_idx++);
    if (sect.GetName() != m_section_type)
      continue;
    DataExtractor data;
    m_obj->ReadSectionData(&sect, data);
    m_next_text =
        llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
                        data.GetByteSize());
  }
  std::tie(m_current_text, m_next_text) = m_next_text.split('\n');
  return *this;
}

static llvm::iterator_range<LineIterator> lines(ObjectFile &obj,
                                                ConstString section_type) {
  return llvm::make_range(LineIterator(obj, section_type), LineIterator(obj));
}

void SymbolFileBreakpad::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                DebuggerInitialize);
}

void SymbolFileBreakpad::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

ConstString SymbolFileBreakpad::GetPluginNameStatic() {
  static ConstString g_name("breakpad");
  return g_name;
}

uint32_t SymbolFileBreakpad::CalculateAbilities() {
  if (!m_obj_file)
    return 0;
  if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic())
    return 0;

  return CompileUnits | Functions;
}

uint32_t SymbolFileBreakpad::GetNumCompileUnits() {
  // TODO
  return 0;
}

CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {
  // TODO
  return nullptr;
}

size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) {
  // TODO
  return 0;
}

bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) {
  // TODO
  return 0;
}

uint32_t
SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
                                         SymbolContextItem resolve_scope,
                                         SymbolContext &sc) {
  // TODO
  return 0;
}

uint32_t SymbolFileBreakpad::FindFunctions(
    const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
    FunctionNameType name_type_mask, bool include_inlines, bool append,
    SymbolContextList &sc_list) {
  // TODO
  if (!append)
    sc_list.Clear();
  return sc_list.GetSize();
}

uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression &regex,
                                           bool include_inlines, bool append,
                                           SymbolContextList &sc_list) {
  // TODO
  if (!append)
    sc_list.Clear();
  return sc_list.GetSize();
}

uint32_t SymbolFileBreakpad::FindTypes(
    const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
    bool append, uint32_t max_matches,
    llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
  if (!append)
    types.Clear();
  return types.GetSize();
}

size_t
SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context,
                              bool append, TypeMap &types) {
  if (!append)
    types.Clear();
  return types.GetSize();
}

void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
  Module &module = *m_obj_file->GetModule();
  addr_t base = module.GetObjectFile()->GetBaseAddress().GetFileAddress();
  if (base == LLDB_INVALID_ADDRESS) {
    LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping "
                  "symtab population.");
    return;
  }

  const SectionList &list = *module.GetSectionList();
  for (llvm::StringRef line : lines(*m_obj_file, ConstString("PUBLIC"))) {
    auto record = PublicRecord::parse(line);
    if (!record) {
      LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", line);
      continue;
    }
    addr_t file_address = base + record->getAddress();

    SectionSP section_sp = list.FindSectionContainingFileAddress(file_address);
    if (!section_sp) {
      LLDB_LOG(log,
               "Ignoring symbol {0}, whose address ({1}) is outside of the "
               "object file. Mismatched symbol file?",
               record->getName(), file_address);
      continue;
    }

    symtab.AddSymbol(Symbol(
        /*symID*/ 0, Mangled(record->getName(), /*is_mangled*/ false),
        eSymbolTypeCode,
        /*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false,
        /*is_artificial*/ false,
        AddressRange(section_sp, file_address - section_sp->GetFileAddress(),
                     0),
        /*size_is_valid*/ 0, /*contains_linker_annotations*/ false,
        /*flags*/ 0));
  }

  // TODO: Process FUNC records as well.

  symtab.CalculateSymbolSizes();
}
OpenPOWER on IntegriCloud