diff options
Diffstat (limited to 'source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp')
| -rw-r--r-- | source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp | 257 | 
1 files changed, 185 insertions, 72 deletions
| diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index d4258274a38c..f84cf0c5368d 100644 --- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -15,7 +15,6 @@  #include "lldb/Host/FileSystem.h"  #include "lldb/Symbol/CompileUnit.h"  #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/PostfixExpression.h"  #include "lldb/Symbol/SymbolVendor.h"  #include "lldb/Symbol/TypeMap.h"  #include "lldb/Utility/Log.h" @@ -126,8 +125,8 @@ SymbolFileBreakpad::LineIterator::operator++() {  llvm::iterator_range<SymbolFileBreakpad::LineIterator>  SymbolFileBreakpad::lines(Record::Kind section_type) { -  return llvm::make_range(LineIterator(*m_obj_file, section_type), -                          LineIterator(*m_obj_file)); +  return llvm::make_range(LineIterator(*m_objfile_sp, section_type), +                          LineIterator(*m_objfile_sp));  }  namespace { @@ -179,15 +178,13 @@ ConstString SymbolFileBreakpad::GetPluginNameStatic() {  }  uint32_t SymbolFileBreakpad::CalculateAbilities() { -  if (!m_obj_file) -    return 0; -  if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic()) +  if (!m_objfile_sp || !llvm::isa<ObjectFileBreakpad>(*m_objfile_sp))      return 0;    return CompileUnits | Functions | LineTables;  } -uint32_t SymbolFileBreakpad::GetNumCompileUnits() { +uint32_t SymbolFileBreakpad::CalculateNumCompileUnits() {    ParseCUData();    return m_cu_data->GetSize();  } @@ -204,7 +201,8 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {    // The FileSpec of the compile unit will be the file corresponding to the    // first LINE record. -  LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); +  LineIterator It(*m_objfile_sp, Record::Func, data.bookmark), +      End(*m_objfile_sp);    assert(Record::classify(*It) == Record::Func);    ++It; // Skip FUNC record.    if (It != End) { @@ -213,12 +211,12 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {        spec = (*m_files)[record->FileNum];    } -  auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), +  auto cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(),                                               /*user_data*/ nullptr, spec, index,                                               eLanguageTypeUnknown,                                               /*is_optimized*/ eLazyBoolNo); -  GetSymbolVendor().SetCompileUnitAtIndex(index, cu_sp); +  SetCompileUnitAtIndex(index, cu_sp);    return cu_sp;  } @@ -228,6 +226,7 @@ size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) {  }  bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { +  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());    CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data;    if (!data.line_table_up) @@ -239,6 +238,7 @@ bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) {  bool SymbolFileBreakpad::ParseSupportFiles(CompileUnit &comp_unit,                                             FileSpecList &support_files) { +  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());    CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data;    if (!data.support_files)      ParseLineTableAndSupportFiles(comp_unit, data); @@ -251,6 +251,7 @@ uint32_t  SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,                                           SymbolContextItem resolve_scope,                                           SymbolContext &sc) { +  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());    if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry)))      return 0; @@ -260,7 +261,7 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,    if (idx == UINT32_MAX)      return 0; -  sc.comp_unit = GetSymbolVendor().GetCompileUnitAtIndex(idx).get(); +  sc.comp_unit = GetCompileUnitAtIndex(idx).get();    SymbolContextItem result = eSymbolContextCompUnit;    if (resolve_scope & eSymbolContextLineEntry) {      if (sc.comp_unit->GetLineTable()->FindLineEntryByAddress(so_addr, @@ -275,57 +276,43 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,  uint32_t SymbolFileBreakpad::ResolveSymbolContext(      const FileSpec &file_spec, uint32_t line, bool check_inlines,      lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { +  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());    if (!(resolve_scope & eSymbolContextCompUnit))      return 0;    uint32_t old_size = sc_list.GetSize();    for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) { -    CompileUnit &cu = *GetSymbolVendor().GetCompileUnitAtIndex(i); +    CompileUnit &cu = *GetCompileUnitAtIndex(i);      cu.ResolveSymbolContext(file_spec, line, check_inlines,                              /*exact*/ false, resolve_scope, sc_list);    }    return sc_list.GetSize() - old_size;  } -uint32_t SymbolFileBreakpad::FindFunctions( +void SymbolFileBreakpad::FindFunctions(      ConstString name, const CompilerDeclContext *parent_decl_ctx, -    FunctionNameType name_type_mask, bool include_inlines, bool append, +    FunctionNameType name_type_mask, bool include_inlines,      SymbolContextList &sc_list) {    // TODO -  if (!append) -    sc_list.Clear(); -  return sc_list.GetSize();  } -uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, -                                           bool include_inlines, bool append, -                                           SymbolContextList &sc_list) { +void SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, +                                       bool include_inlines, +                                       SymbolContextList &sc_list) {    // TODO -  if (!append) -    sc_list.Clear(); -  return sc_list.GetSize();  } -uint32_t SymbolFileBreakpad::FindTypes( +void SymbolFileBreakpad::FindTypes(      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(); -} +    uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, +    TypeMap &types) {} -size_t -SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context, -                              bool append, TypeMap &types) { -  if (!append) -    types.Clear(); -  return types.GetSize(); -} +void SymbolFileBreakpad::FindTypes(llvm::ArrayRef<CompilerContext> pattern, +                                   LanguageSet languages, TypeMap &types) {}  void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {    Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); -  Module &module = *m_obj_file->GetModule(); +  Module &module = *m_objfile_sp->GetModule();    addr_t base = GetBaseFileAddress();    if (base == LLDB_INVALID_ADDRESS) {      LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping " @@ -347,8 +334,8 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {        return;      }      symbols.try_emplace( -        address, /*symID*/ 0, Mangled(name, /*is_mangled*/ false), -        eSymbolTypeCode, /*is_global*/ true, /*is_debug*/ false, +        address, /*symID*/ 0, Mangled(name), eSymbolTypeCode, +        /*is_global*/ true, /*is_debug*/ false,          /*is_trampoline*/ false, /*is_artificial*/ false,          AddressRange(section_sp, address - section_sp->GetFileAddress(),                       size.getValueOr(0)), @@ -372,6 +359,20 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {    symtab.CalculateSymbolSizes();  } +llvm::Expected<lldb::addr_t> +SymbolFileBreakpad::GetParameterStackSize(Symbol &symbol) { +  ParseUnwindData(); +  if (auto *entry = m_unwind_data->win.FindEntryThatContains( +          symbol.GetAddress().GetFileAddress())) { +    auto record = StackWinRecord::parse( +        *LineIterator(*m_objfile_sp, Record::StackWin, entry->data)); +    assert(record.hasValue()); +    return record->ParameterSize; +  } +  return llvm::createStringError(llvm::inconvertibleErrorCode(), +                                 "Parameter size unknown."); +} +  static llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>>  GetRule(llvm::StringRef &unwind_rules) {    // Unwind rules are of the form @@ -418,7 +419,17 @@ ResolveRegisterOrRA(const SymbolFile::RegisterInfoResolver &resolver,    return ResolveRegister(resolver, name);  } -bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, +llvm::ArrayRef<uint8_t> SymbolFileBreakpad::SaveAsDWARF(postfix::Node &node) { +  ArchSpec arch = m_objfile_sp->GetArchitecture(); +  StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(), +                     arch.GetByteOrder()); +  ToDWARF(node, dwarf); +  uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize()); +  std::memcpy(saved, dwarf.GetData(), dwarf.GetSize()); +  return {saved, dwarf.GetSize()}; +} + +bool SymbolFileBreakpad::ParseCFIUnwindRow(llvm::StringRef unwind_rules,                                          const RegisterInfoResolver &resolver,                                          UnwindPlan::Row &row) {    Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); @@ -427,7 +438,7 @@ bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules,    while (auto rule = GetRule(unwind_rules)) {      node_alloc.Reset();      llvm::StringRef lhs = rule->first; -    postfix::Node *rhs = postfix::Parse(rule->second, node_alloc); +    postfix::Node *rhs = postfix::ParseOneExpression(rule->second, node_alloc);      if (!rhs) {        LLDB_LOG(log, "Could not parse `{0}` as unwind rhs.", rule->second);        return false; @@ -451,18 +462,12 @@ bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules,        return false;      } -    ArchSpec arch = m_obj_file->GetArchitecture(); -    StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(), -                       arch.GetByteOrder()); -    ToDWARF(*rhs, dwarf); -    uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize()); -    std::memcpy(saved, dwarf.GetData(), dwarf.GetSize()); - +    llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*rhs);      if (lhs == ".cfa") { -      row.GetCFAValue().SetIsDWARFExpression(saved, dwarf.GetSize()); +      row.GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size());      } else if (const RegisterInfo *info = ResolveRegisterOrRA(resolver, lhs)) {        UnwindPlan::Row::RegisterLocation loc; -      loc.SetIsDWARFExpression(saved, dwarf.GetSize()); +      loc.SetIsDWARFExpression(saved.data(), saved.size());        row.SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc);      } else        LLDB_LOG(log, "Invalid register `{0}` in unwind rule.", lhs); @@ -478,31 +483,40 @@ UnwindPlanSP  SymbolFileBreakpad::GetUnwindPlan(const Address &address,                                    const RegisterInfoResolver &resolver) {    ParseUnwindData(); -  const UnwindMap::Entry *entry = -      m_unwind_data->FindEntryThatContains(address.GetFileAddress()); -  if (!entry) -    return nullptr; +  if (auto *entry = +          m_unwind_data->cfi.FindEntryThatContains(address.GetFileAddress())) +    return ParseCFIUnwindPlan(entry->data, resolver); +  if (auto *entry = +          m_unwind_data->win.FindEntryThatContains(address.GetFileAddress())) +    return ParseWinUnwindPlan(entry->data, resolver); +  return nullptr; +} +UnwindPlanSP +SymbolFileBreakpad::ParseCFIUnwindPlan(const Bookmark &bookmark, +                                       const RegisterInfoResolver &resolver) {    addr_t base = GetBaseFileAddress();    if (base == LLDB_INVALID_ADDRESS)      return nullptr; -  LineIterator It(*m_obj_file, Record::StackCFI, entry->data), End(*m_obj_file); +  LineIterator It(*m_objfile_sp, Record::StackCFI, bookmark), +      End(*m_objfile_sp);    llvm::Optional<StackCFIRecord> init_record = StackCFIRecord::parse(*It); -  assert(init_record.hasValue()); -  assert(init_record->Size.hasValue()); +  assert(init_record.hasValue() && init_record->Size.hasValue() && +         "Record already parsed successfully in ParseUnwindData!");    auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB);    plan_sp->SetSourceName("breakpad STACK CFI");    plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); +  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);    plan_sp->SetSourcedFromCompiler(eLazyBoolYes);    plan_sp->SetPlanValidAddressRange(        AddressRange(base + init_record->Address, *init_record->Size, -                   m_obj_file->GetModule()->GetSectionList())); +                   m_objfile_sp->GetModule()->GetSectionList()));    auto row_sp = std::make_shared<UnwindPlan::Row>();    row_sp->SetOffset(0); -  if (!ParseUnwindRow(init_record->UnwindRules, resolver, *row_sp)) +  if (!ParseCFIUnwindRow(init_record->UnwindRules, resolver, *row_sp))      return nullptr;    plan_sp->AppendRow(row_sp);    for (++It; It != End; ++It) { @@ -514,19 +528,107 @@ SymbolFileBreakpad::GetUnwindPlan(const Address &address,      row_sp = std::make_shared<UnwindPlan::Row>(*row_sp);      row_sp->SetOffset(record->Address - init_record->Address); -    if (!ParseUnwindRow(record->UnwindRules, resolver, *row_sp)) +    if (!ParseCFIUnwindRow(record->UnwindRules, resolver, *row_sp))        return nullptr;      plan_sp->AppendRow(row_sp);    }    return plan_sp;  } -SymbolVendor &SymbolFileBreakpad::GetSymbolVendor() { -  return *m_obj_file->GetModule()->GetSymbolVendor(); +UnwindPlanSP +SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark &bookmark, +                                       const RegisterInfoResolver &resolver) { +  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); +  addr_t base = GetBaseFileAddress(); +  if (base == LLDB_INVALID_ADDRESS) +    return nullptr; + +  LineIterator It(*m_objfile_sp, Record::StackWin, bookmark); +  llvm::Optional<StackWinRecord> record = StackWinRecord::parse(*It); +  assert(record.hasValue() && +         "Record already parsed successfully in ParseUnwindData!"); + +  auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB); +  plan_sp->SetSourceName("breakpad STACK WIN"); +  plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); +  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo); +  plan_sp->SetSourcedFromCompiler(eLazyBoolYes); +  plan_sp->SetPlanValidAddressRange( +      AddressRange(base + record->RVA, record->CodeSize, +                   m_objfile_sp->GetModule()->GetSectionList())); + +  auto row_sp = std::make_shared<UnwindPlan::Row>(); +  row_sp->SetOffset(0); + +  llvm::BumpPtrAllocator node_alloc; +  std::vector<std::pair<llvm::StringRef, postfix::Node *>> program = +      postfix::ParseFPOProgram(record->ProgramString, node_alloc); + +  if (program.empty()) { +    LLDB_LOG(log, "Invalid unwind rule: {0}.", record->ProgramString); +    return nullptr; +  } +  auto it = program.begin(); +  const auto &symbol_resolver = +      [&](postfix::SymbolNode &symbol) -> postfix::Node * { +    llvm::StringRef name = symbol.GetName(); +    for (const auto &rule : llvm::make_range(program.begin(), it)) { +      if (rule.first == name) +        return rule.second; +    } +    if (const RegisterInfo *info = ResolveRegister(resolver, name)) +      return postfix::MakeNode<postfix::RegisterNode>( +          node_alloc, info->kinds[eRegisterKindLLDB]); +    return nullptr; +  }; + +  // We assume the first value will be the CFA. It is usually called T0, but +  // clang will use T1, if it needs to realign the stack. +  auto *symbol = llvm::dyn_cast<postfix::SymbolNode>(it->second); +  if (symbol && symbol->GetName() == ".raSearch") { +    row_sp->GetCFAValue().SetRaSearch(record->LocalSize + +                                      record->SavedRegisterSize); +  } else { +    if (!postfix::ResolveSymbols(it->second, symbol_resolver)) { +      LLDB_LOG(log, "Resolving symbols in `{0}` failed.", +               record->ProgramString); +      return nullptr; +    } +    llvm::ArrayRef<uint8_t> saved  = SaveAsDWARF(*it->second); +    row_sp->GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size()); +  } + +  // Replace the node value with InitialValueNode, so that subsequent +  // expressions refer to the CFA value instead of recomputing the whole +  // expression. +  it->second = postfix::MakeNode<postfix::InitialValueNode>(node_alloc); + + +  // Now process the rest of the assignments. +  for (++it; it != program.end(); ++it) { +    const RegisterInfo *info = ResolveRegister(resolver, it->first); +    // It is not an error if the resolution fails because the program may +    // contain temporary variables. +    if (!info) +      continue; +    if (!postfix::ResolveSymbols(it->second, symbol_resolver)) { +      LLDB_LOG(log, "Resolving symbols in `{0}` failed.", +               record->ProgramString); +      return nullptr; +    } + +    llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*it->second); +    UnwindPlan::Row::RegisterLocation loc; +    loc.SetIsDWARFExpression(saved.data(), saved.size()); +    row_sp->SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc); +  } + +  plan_sp->AppendRow(row_sp); +  return plan_sp;  }  addr_t SymbolFileBreakpad::GetBaseFileAddress() { -  return m_obj_file->GetModule() +  return m_objfile_sp->GetModule()        ->GetObjectFile()        ->GetBaseAddress()        .GetFileAddress(); @@ -569,8 +671,8 @@ void SymbolFileBreakpad::ParseCUData() {    // We shall create one compile unit for each FUNC record. So, count the number    // of FUNC records, and store them in m_cu_data, together with their ranges. -  for (LineIterator It(*m_obj_file, Record::Func), End(*m_obj_file); It != End; -       ++It) { +  for (LineIterator It(*m_objfile_sp, Record::Func), End(*m_objfile_sp); +       It != End; ++It) {      if (auto record = FuncRecord::parse(*It)) {        m_cu_data->Append(CompUnitMap::Entry(base + record->Address, record->Size,                                             CompUnitData(It.GetBookmark()))); @@ -589,7 +691,7 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu,           "How did we create compile units without a base address?");    SupportFileMap map; -  data.line_table_up = llvm::make_unique<LineTable>(&cu); +  data.line_table_up = std::make_unique<LineTable>(&cu);    std::unique_ptr<LineSequence> line_seq_up(        data.line_table_up->CreateLineSequenceContainer());    llvm::Optional<addr_t> next_addr; @@ -603,7 +705,8 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu,      line_seq_up->Clear();    }; -  LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); +  LineIterator It(*m_objfile_sp, Record::Func, data.bookmark), +      End(*m_objfile_sp);    assert(Record::classify(*It) == Record::Func);    for (++It; It != End; ++It) {      auto record = LineRecord::parse(*It); @@ -631,8 +734,8 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu,  void SymbolFileBreakpad::ParseUnwindData() {    if (m_unwind_data)      return; -    m_unwind_data.emplace(); +    Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);    addr_t base = GetBaseFileAddress();    if (base == LLDB_INVALID_ADDRESS) { @@ -640,14 +743,24 @@ void SymbolFileBreakpad::ParseUnwindData() {                    "of object file.");    } -  for (LineIterator It(*m_obj_file, Record::StackCFI), End(*m_obj_file); +  for (LineIterator It(*m_objfile_sp, Record::StackCFI), End(*m_objfile_sp);         It != End; ++It) {      if (auto record = StackCFIRecord::parse(*It)) {        if (record->Size) -        m_unwind_data->Append(UnwindMap::Entry( +        m_unwind_data->cfi.Append(UnwindMap::Entry(              base + record->Address, *record->Size, It.GetBookmark()));      } else        LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It);    } -  m_unwind_data->Sort(); +  m_unwind_data->cfi.Sort(); + +  for (LineIterator It(*m_objfile_sp, Record::StackWin), End(*m_objfile_sp); +       It != End; ++It) { +    if (auto record = StackWinRecord::parse(*It)) { +      m_unwind_data->win.Append(UnwindMap::Entry( +          base + record->RVA, record->CodeSize, It.GetBookmark())); +    } else +      LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It); +  } +  m_unwind_data->win.Sort();  } | 
