Index: lit/SymbolFile/Breakpad/Inputs/symtab.syms =================================================================== --- lit/SymbolFile/Breakpad/Inputs/symtab.syms +++ lit/SymbolFile/Breakpad/Inputs/symtab.syms @@ -5,3 +5,5 @@ PUBLIC m c0 0 f2 PUBLIC d0 0 _start PUBLIC ff 0 _out_of_range_ignored +FUNC b0 c 0 f1_func +FUNC m a0 d 0 func_only Index: lit/SymbolFile/Breakpad/symtab.test =================================================================== --- lit/SymbolFile/Breakpad/symtab.test +++ lit/SymbolFile/Breakpad/symtab.test @@ -3,15 +3,16 @@ # RUN: -s %s | FileCheck %s # CHECK-LABEL: (lldb) image dump symtab symtab.out -# CHECK: Symtab, file = {{.*}}symtab.out, num_symbols = 3: +# CHECK: Symtab, file = {{.*}}symtab.out, num_symbols = 4: # CHECK: Index UserID DSX Type File Address/Value Load Address Size Flags Name -# CHECK: [ 0] 0 X Code 0x00000000004000b0 0x0000000000000010 0x00000000 f1 -# CHECK: [ 1] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2 -# CHECK: [ 2] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start +# CHECK: [ 0] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2 +# CHECK: [ 1] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start +# CHECK: [ 2] 0 X Code 0x00000000004000a0 0x000000000000000d 0x00000000 func_only +# CHECK: [ 3] 0 X Code 0x00000000004000b0 0x000000000000000c 0x00000000 f1_func # CHECK-LABEL: (lldb) image lookup -a 0x4000b0 -v # CHECK: Address: symtab.out[0x00000000004000b0] (symtab.out.PT_LOAD[0]..text2 + 0) -# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000b0-0x00000000004000c0), name="f1" +# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000b0-0x00000000004000bc), name="f1_func" # CHECK-LABEL: (lldb) image lookup -n f2 -v # CHECK: Address: symtab.out[0x00000000004000c0] (symtab.out.PT_LOAD[0]..text2 + 16) Index: source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h =================================================================== --- source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h +++ source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h @@ -17,6 +17,11 @@ namespace lldb_private { namespace breakpad { +enum class Token { Unknown, Module, Info, File, Func, Public, Stack }; + +Token toToken(llvm::StringRef str); +llvm::StringRef toString(Token t); + class ObjectFileBreakpad : public ObjectFile { public: //------------------------------------------------------------------ Index: source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp =================================================================== --- source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp +++ source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp @@ -24,11 +24,9 @@ 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) { +Token breakpad::toToken(llvm::StringRef str) { return llvm::StringSwitch(str) .Case("MODULE", Token::Module) .Case("INFO", Token::Info) @@ -39,7 +37,7 @@ .Default(Token::Unknown); } -static llvm::StringRef toString(Token t) { +llvm::StringRef breakpad::toString(Token t) { switch (t) { case Token::Unknown: return ""; Index: source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp =================================================================== --- source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -26,8 +26,9 @@ 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) { + LineIterator(ObjectFile &obj, Token section_type) + : m_obj(&obj), m_section_type(toString(section_type)), + m_next_section_idx(0) { ++*this; } @@ -77,7 +78,7 @@ } static llvm::iterator_range lines(ObjectFile &obj, - ConstString section_type) { + Token section_type) { return llvm::make_range(LineIterator(obj, section_type), LineIterator(obj)); } @@ -181,10 +182,11 @@ } const SectionList &list = *module.GetSectionList(); - for (llvm::StringRef line : lines(*m_obj_file, ConstString("PUBLIC"))) { - // PUBLIC [m] address param_size name - // skip PUBLIC keyword - line = getToken(line).second; + llvm::DenseMap symbols; + + auto parse = [&](llvm::StringRef line, bool is_func) { + // [m] address {size} param_size name + // {size} is present in FUNC records. llvm::StringRef token; std::tie(token, line) = getToken(line); if (token == "m") @@ -192,9 +194,18 @@ addr_t address; if (!to_integer(token, address, 16)) - continue; + return; address += base; + addr_t size = 0; + bool size_is_valid = false; + if (is_func) { + std::tie(token, line) = getToken(line); + if (!to_integer(token, size, 16)) + return; + size_is_valid = true; + } + // skip param_size line = getToken(line).second; @@ -206,19 +217,36 @@ "Ignoring symbol {0}, whose address ({1}) is outside of the " "object file. Mismatched symbol file?", name, address); - continue; + return; } - symtab.AddSymbol(Symbol( - /*symID*/ 0, Mangled(name, /*is_mangled*/ false), eSymbolTypeCode, + symbols.try_emplace( + address, /*symID*/ 0, Mangled(name, /*is_mangled*/ false), + eSymbolTypeCode, /*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false, /*is_artificial*/ false, - AddressRange(section_sp, address - section_sp->GetFileAddress(), 0), - /*size_is_valid*/ 0, /*contains_linker_annotations*/ false, - /*flags*/ 0)); + AddressRange(section_sp, address - section_sp->GetFileAddress(), size), + size_is_valid, /*contains_linker_annotations*/ false, + /*flags*/ 0); + }; + for (llvm::StringRef line: lines(*m_obj_file, Token::Func)) { + // Here we can get either FUNC records (starting with FUNC), or line records + // (starting with a hex number). + llvm::StringRef token_str; + std::tie(token_str, line) = getToken(line); + if (toToken(token_str) != Token::Func) + continue; // Skip line records. + + parse(line, true); } - // TODO: Process FUNC records as well. + for (llvm::StringRef line : lines(*m_obj_file, Token::Public)) { + // PUBLIC [m] address param_size name + // skip PUBLIC keyword + parse(getToken(line).second, false); + } + for (auto &KV : symbols) + symtab.AddSymbol(std::move(KV.second)); symtab.CalculateSymbolSizes(); }