aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2019-01-07 11:14:08 +0000
committerPavel Labath <pavel@labath.sk>2019-01-07 11:14:08 +0000
commited42ea4707c3c564b3bd52a23c11b81988156c07 (patch)
tree6e143c4ce177f8faaeb89ced83fe4b13b29fe88e /lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
parentcb8c699802f39aee10c27d4d73de5e14c7dfd09c (diff)
downloadllvm-ed42ea4707c3c564b3bd52a23c11b81988156c07.tar.gz
llvm-ed42ea4707c3c564b3bd52a23c11b81988156c07.tar.bz2
llvm-ed42ea4707c3c564b3bd52a23c11b81988156c07.zip
ObjectFileBreakpad: Implement sections
Summary: This patch allows ObjectFileBreakpad to parse the contents of Breakpad files into sections. This sounds slightly odd at first, but in essence its not too different from how other object files handle things. For example in elf files, the symtab section consists of a number of "records", where each record represents a single symbol. The same is true for breakpad's PUBLIC section, except in this case, the records will be textual instead of binary. To keep sections contiguous, I create a new section every time record type changes. Normally, the breakpad processor will group all records of the same type in one block, but the format allows them to be intermixed, so in general, the "object file" may contain multiple sections with the same record type. Reviewers: clayborg, zturner, lemo, markmentovai, amccarth Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D55434 llvm-svn: 350511
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp')
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp79
1 files changed, 77 insertions, 2 deletions
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
index 7eebac2c6935..917025030ada 100644
--- a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
+++ b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
@@ -10,6 +10,7 @@
#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
#include "lldb/Utility/DataBuffer.h"
#include "llvm/ADT/StringExtras.h"
@@ -23,8 +24,41 @@ struct Header {
UUID uuid;
static llvm::Optional<Header> parse(llvm::StringRef text);
};
+
+enum class Token { Unknown, Module, Info, File, Func, Public, Stack };
} // namespace
+static Token toToken(llvm::StringRef str) {
+ return llvm::StringSwitch<Token>(str)
+ .Case("MODULE", Token::Module)
+ .Case("INFO", Token::Info)
+ .Case("FILE", Token::File)
+ .Case("FUNC", Token::Func)
+ .Case("PUBLIC", Token::Public)
+ .Case("STACK", Token::Stack)
+ .Default(Token::Unknown);
+}
+
+static llvm::StringRef toString(Token t) {
+ switch (t) {
+ case Token::Unknown:
+ return "";
+ case Token::Module:
+ return "MODULE";
+ case Token::Info:
+ return "INFO";
+ case Token::File:
+ return "FILE";
+ case Token::Func:
+ return "FUNC";
+ case Token::Public:
+ return "PUBLIC";
+ case Token::Stack:
+ return "STACK";
+ }
+ llvm_unreachable("Unknown token!");
+}
+
static llvm::Triple::OSType toOS(llvm::StringRef str) {
using llvm::Triple;
return llvm::StringSwitch<Triple::OSType>(str)
@@ -103,7 +137,7 @@ llvm::Optional<Header> Header::parse(llvm::StringRef text) {
llvm::StringRef token, line;
std::tie(line, text) = text.split('\n');
std::tie(token, line) = getToken(line);
- if (token != "MODULE")
+ if (toToken(token) != Token::Module)
return llvm::None;
std::tie(token, line) = getToken(line);
@@ -236,5 +270,46 @@ bool ObjectFileBreakpad::GetUUID(UUID *uuid) {
}
void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
- // TODO
+ if (m_sections_ap)
+ return;
+ m_sections_ap = llvm::make_unique<SectionList>();
+
+ Token current_section = Token::Unknown;
+ offset_t section_start;
+ llvm::StringRef text = toStringRef(m_data.GetData());
+ uint32_t next_section_id = 1;
+ auto maybe_add_section = [&](const uint8_t *end_ptr) {
+ if (current_section == Token::Unknown)
+ return; // We have been called before parsing the first line.
+
+ offset_t end_offset = end_ptr - m_data.GetDataStart();
+ auto section_sp = std::make_shared<Section>(
+ GetModule(), this, next_section_id++,
+ ConstString(toString(current_section)), eSectionTypeOther,
+ /*file_vm_addr*/ 0, /*vm_size*/ 0, section_start,
+ end_offset - section_start, /*log2align*/ 0, /*flags*/ 0);
+ m_sections_ap->AddSection(section_sp);
+ unified_section_list.AddSection(section_sp);
+ };
+ while (!text.empty()) {
+ llvm::StringRef line;
+ std::tie(line, text) = text.split('\n');
+
+ Token token = toToken(getToken(line).first);
+ if (token == Token::Unknown) {
+ // We assume this is a line record, which logically belongs to the Func
+ // section. Errors will be handled when parsing the Func section.
+ token = Token::Func;
+ }
+ if (token == current_section)
+ continue;
+
+ // Changing sections, finish off the previous one, if there was any.
+ maybe_add_section(line.bytes_begin());
+ // And start a new one.
+ current_section = token;
+ section_start = line.bytes_begin() - m_data.GetDataStart();
+ }
+ // Finally, add the last section.
+ maybe_add_section(m_data.GetDataEnd());
}