summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Utility/DataExtractor.h5
-rw-r--r--lldb/lit/Modules/Breakpad/Inputs/discontiguous-sections.syms5
-rw-r--r--lldb/lit/Modules/Breakpad/Inputs/sections-trailing-func.syms8
-rw-r--r--lldb/lit/Modules/Breakpad/Inputs/sections.syms12
-rw-r--r--lldb/lit/Modules/Breakpad/discontiguous-sections.test27
-rw-r--r--lldb/lit/Modules/Breakpad/sections-trailing-func.test15
-rw-r--r--lldb/lit/Modules/Breakpad/sections.test89
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp79
8 files changed, 238 insertions, 2 deletions
diff --git a/lldb/include/lldb/Utility/DataExtractor.h b/lldb/include/lldb/Utility/DataExtractor.h
index 2a269ab72c1..37f4cddca6e 100644
--- a/lldb/include/lldb/Utility/DataExtractor.h
+++ b/lldb/include/lldb/Utility/DataExtractor.h
@@ -14,6 +14,7 @@
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"
+#include "llvm/ADT/ArrayRef.h"
#include <cassert>
#include <stdint.h>
@@ -1094,6 +1095,10 @@ public:
void Checksum(llvm::SmallVectorImpl<uint8_t> &dest, uint64_t max_data = 0);
+ llvm::ArrayRef<uint8_t> GetData() const {
+ return {GetDataStart(), GetByteSize()};
+ }
+
protected:
//------------------------------------------------------------------
// Member variables
diff --git a/lldb/lit/Modules/Breakpad/Inputs/discontiguous-sections.syms b/lldb/lit/Modules/Breakpad/Inputs/discontiguous-sections.syms
new file mode 100644
index 00000000000..bf0a21bc6e0
--- /dev/null
+++ b/lldb/lit/Modules/Breakpad/Inputs/discontiguous-sections.syms
@@ -0,0 +1,5 @@
+MODULE Linux x86_64 0000000024B5D199F0F766FFFFFF5DC30 linux.out
+INFO CODE_ID 00000000B52499D1F0F766FFFFFF5DC3
+FILE 0 /tmp/a.c
+PUBLIC 1010 0 _start
+FILE 1 /tmp/b.c
diff --git a/lldb/lit/Modules/Breakpad/Inputs/sections-trailing-func.syms b/lldb/lit/Modules/Breakpad/Inputs/sections-trailing-func.syms
new file mode 100644
index 00000000000..6176d35143c
--- /dev/null
+++ b/lldb/lit/Modules/Breakpad/Inputs/sections-trailing-func.syms
@@ -0,0 +1,8 @@
+MODULE Linux x86_64 0000000024B5D199F0F766FFFFFF5DC30 linux.out
+INFO CODE_ID 00000000B52499D1F0F766FFFFFF5DC3
+FILE 0 /tmp/a.c
+FUNC 1010 10 0 _start
+1010 4 4 0
+1014 5 5 0
+1019 5 6 0
+101e 2 7 0
diff --git a/lldb/lit/Modules/Breakpad/Inputs/sections.syms b/lldb/lit/Modules/Breakpad/Inputs/sections.syms
new file mode 100644
index 00000000000..121cca439b0
--- /dev/null
+++ b/lldb/lit/Modules/Breakpad/Inputs/sections.syms
@@ -0,0 +1,12 @@
+MODULE Linux x86_64 0000000024B5D199F0F766FFFFFF5DC30 linux.out
+INFO CODE_ID 00000000B52499D1F0F766FFFFFF5DC3
+FILE 0 /tmp/a.c
+FUNC 1010 10 0 _start
+1010 4 4 0
+1014 5 5 0
+1019 5 6 0
+101e 2 7 0
+PUBLIC 1010 0 _start
+STACK CFI INIT 1010 10 .cfa: $rsp 8 + .ra: .cfa -8 + ^
+STACK CFI 1011 $rbp: .cfa -16 + ^ .cfa: $rsp 16 +
+STACK CFI 1014 .cfa: $rbp 16 +
diff --git a/lldb/lit/Modules/Breakpad/discontiguous-sections.test b/lldb/lit/Modules/Breakpad/discontiguous-sections.test
new file mode 100644
index 00000000000..0c9aeea08d7
--- /dev/null
+++ b/lldb/lit/Modules/Breakpad/discontiguous-sections.test
@@ -0,0 +1,27 @@
+# Test handling discontiguous sections.
+RUN: lldb-test object-file %p/Inputs/discontiguous-sections.syms -contents | FileCheck %s
+
+CHECK: Showing 5 sections
+
+CHECK: ID: 0x1
+CHECK-NEXT: Name: MODULE
+
+CHECK: ID: 0x2
+CHECK-NEXT: Name: INFO
+
+CHECK: ID: 0x3
+CHECK-NEXT: Name: FILE
+CHECK: File size: 16
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46494C45 2030202F 746D702F 612E630A |FILE 0 /tmp/a.c.|
+CHECK-NEXT: )
+
+CHECK: ID: 0x4
+CHECK-NEXT: Name: PUBLIC
+
+CHECK: ID: 0x5
+CHECK-NEXT: Name: FILE
+CHECK: File size: 16
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46494C45 2031202F 746D702F 622E630A |FILE 1 /tmp/b.c.|
+CHECK-NEXT: )
diff --git a/lldb/lit/Modules/Breakpad/sections-trailing-func.test b/lldb/lit/Modules/Breakpad/sections-trailing-func.test
new file mode 100644
index 00000000000..9ea5c9da781
--- /dev/null
+++ b/lldb/lit/Modules/Breakpad/sections-trailing-func.test
@@ -0,0 +1,15 @@
+# Test handling of a (valid) breakpad file, which ends with a line without a
+# recognised keyword.
+
+RUN: lldb-test object-file %p/Inputs/sections-trailing-func.syms -contents | FileCheck %s
+
+CHECK: Showing 4 sections
+
+CHECK: ID: 0x4
+CHECK-NEXT: Name: FUNC
+CHECK: File size: 66
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46554E43 20313031 30203130 2030205F 73746172 740A3130 31302034 20342030 |FUNC 1010 10 0 _start.1010 4 4 0|
+CHECK-NEXT: 0020: 0A313031 34203520 3520300A 31303139 20352036 20300A31 30316520 32203720 |.1014 5 5 0.1019 5 6 0.101e 2 7 |
+CHECK-NEXT: 0040: 300A |0.|
+CHECK-NEXT: )
diff --git a/lldb/lit/Modules/Breakpad/sections.test b/lldb/lit/Modules/Breakpad/sections.test
new file mode 100644
index 00000000000..32ccf848db6
--- /dev/null
+++ b/lldb/lit/Modules/Breakpad/sections.test
@@ -0,0 +1,89 @@
+RUN: lldb-test object-file %p/Inputs/sections.syms -contents | FileCheck %s
+
+CHECK: Showing 6 sections
+
+CHECK: Index: 0
+CHECK-NEXT: ID: 0x1
+CHECK-NEXT: Name: MODULE
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 64
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 4D4F4455 4C45204C 696E7578 20783836 5F363420 30303030 30303030 32344235 |MODULE Linux x86_64 0000000024B5|
+CHECK-NEXT: 0020: 44313939 46304637 36364646 46464646 35444333 30206C69 6E75782E 6F75740A |D199F0F766FFFFFF5DC30 linux.out.|
+CHECK-NEXT: )
+
+CHECK: Index: 1
+CHECK-NEXT: ID: 0x2
+CHECK-NEXT: Name: INFO
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 46
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 494E464F 20434F44 455F4944 20303030 30303030 30423532 34393944 31463046 |INFO CODE_ID 00000000B52499D1F0F|
+CHECK-NEXT: 0020: 37363646 46464646 46354443 330A |766FFFFFF5DC3.|
+CHECK-NEXT: )
+
+CHECK: Index: 2
+CHECK-NEXT: ID: 0x3
+CHECK-NEXT: Name: FILE
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 16
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46494C45 2030202F 746D702F 612E630A |FILE 0 /tmp/a.c.|
+CHECK-NEXT: )
+
+CHECK: Index: 3
+CHECK-NEXT: ID: 0x4
+CHECK-NEXT: Name: FUNC
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 66
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46554E43 20313031 30203130 2030205F 73746172 740A3130 31302034 20342030 |FUNC 1010 10 0 _start.1010 4 4 0|
+CHECK-NEXT: 0020: 0A313031 34203520 3520300A 31303139 20352036 20300A31 30316520 32203720 |.1014 5 5 0.1019 5 6 0.101e 2 7 |
+CHECK-NEXT: 0040: 300A |0.|
+CHECK-NEXT: )
+
+CHECK: Index: 4
+CHECK-NEXT: ID: 0x5
+CHECK-NEXT: Name: PUBLIC
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 21
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 5055424C 49432031 30313020 30205F73 74617274 0A |PUBLIC 1010 0 _start.|
+CHECK-NEXT: )
+
+CHECK: Index: 5
+CHECK-NEXT: ID: 0x6
+CHECK-NEXT: Name: STACK
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 136
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 53544143 4B204346 4920494E 49542031 30313020 3130202E 6366613A 20247273 |STACK CFI INIT 1010 10 .cfa: $rs|
+CHECK-NEXT: 0020: 70203820 2B202E72 613A202E 63666120 2D38202B 205E0A53 5441434B 20434649 |p 8 + .ra: .cfa -8 + ^.STACK CFI|
+CHECK-NEXT: 0040: 20313031 31202472 62703A20 2E636661 202D3136 202B205E 202E6366 613A2024 | 1011 $rbp: .cfa -16 + ^ .cfa: $|
+CHECK-NEXT: 0060: 72737020 3136202B 0A535441 434B2043 46492031 30313420 2E636661 3A202472 |rsp 16 +.STACK CFI 1014 .cfa: $r|
+CHECK-NEXT: 0080: 62702031 36202B0A |bp 16 +.|
+CHECK-NEXT: )
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
index 7eebac2c693..917025030ad 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());
}
OpenPOWER on IntegriCloud