Index: include/lldb/Utility/DataExtractor.h =================================================================== --- include/lldb/Utility/DataExtractor.h +++ 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 #include @@ -1094,6 +1095,10 @@ void Checksum(llvm::SmallVectorImpl &dest, uint64_t max_data = 0); + llvm::ArrayRef GetData() const { + return {GetDataStart(), GetByteSize()}; + } + protected: //------------------------------------------------------------------ // Member variables Index: lit/Modules/Breakpad/Inputs/discontiguous-sections.syms =================================================================== --- /dev/null +++ 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 Index: lit/Modules/Breakpad/Inputs/sections-trailing-func.syms =================================================================== --- /dev/null +++ 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 Index: lit/Modules/Breakpad/Inputs/sections.syms =================================================================== --- /dev/null +++ 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 + Index: lit/Modules/Breakpad/discontiguous-sections.test =================================================================== --- /dev/null +++ lit/Modules/Breakpad/discontiguous-sections.test @@ -0,0 +1,31 @@ +# Test handling discontiguous sections. +RUN: lldb-test object-file %p/Inputs/discontiguous-sections.syms -contents | FileCheck %s + +CHECK: Showing 5 sections + +CHECK: Index: 0 +CHECK-NEXT: Name: MODULE + +CHECK: Index: 1 +CHECK-NEXT: Name: INFO + +CHECK: Index: 2 +CHECK-NEXT: Name: FILE +CHECK-NEXT: Type: regular +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: Name: PUBLIC + +CHECK: Index: 4 +CHECK-NEXT: Name: FILE +CHECK-NEXT: Type: regular +CHECK-NEXT: VM size: 0 +CHECK-NEXT: File size: 16 +CHECK-NEXT: Data: ( +CHECK-NEXT: 0000: 46494C45 2031202F 746D702F 622E630A |FILE 1 /tmp/b.c.| +CHECK-NEXT: ) Index: lit/Modules/Breakpad/sections-trailing-func.test =================================================================== --- /dev/null +++ lit/Modules/Breakpad/sections-trailing-func.test @@ -0,0 +1,17 @@ +# 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: Index: 3 +CHECK-NEXT: Name: FUNC +CHECK-NEXT: Type: regular +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: ) Index: lit/Modules/Breakpad/sections.test =================================================================== --- /dev/null +++ lit/Modules/Breakpad/sections.test @@ -0,0 +1,65 @@ +RUN: lldb-test object-file %p/Inputs/sections.syms -contents | FileCheck %s + +CHECK: Showing 6 sections + +CHECK: Index: 0 +CHECK-NEXT: Name: MODULE +CHECK-NEXT: Type: regular +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: Name: INFO +CHECK-NEXT: Type: regular +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: Name: FILE +CHECK-NEXT: Type: regular +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: Name: FUNC +CHECK-NEXT: Type: regular +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: Name: PUBLIC +CHECK-NEXT: Type: regular +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: Name: STACK +CHECK-NEXT: Type: regular +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: ) Index: source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp =================================================================== --- source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp +++ 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 @@ UUID uuid; static llvm::Optional
parse(llvm::StringRef text); }; + +enum class Token { Unknown, Module, Info, File, Func, Public, Stack }; } // namespace +static Token toToken(llvm::StringRef str) { + return llvm::StringSwitch(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(str) @@ -103,7 +137,7 @@ 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); @@ -235,5 +269,46 @@ } void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) { - // TODO + if (m_sections_ap) + return; + m_sections_ap = llvm::make_unique(); + + Token current_section = Token::Unknown; + offset_t section_start; + llvm::StringRef text = toStringRef(m_data.GetData()); + uint32_t next_section_id = 0; + 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
( + 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()); }