Index: include/lldb/Core/RangeMap.h =================================================================== --- include/lldb/Core/RangeMap.h +++ include/lldb/Core/RangeMap.h @@ -1123,7 +1123,7 @@ // Calculate the byte size of ranges with zero byte sizes by finding // the next entry with a base address > the current base address void - CalculateSizesOfZeroByteSizeRanges () + CalculateSizesOfZeroByteSizeRanges (S full_size = 0) { #ifdef ASSERT_RANGEMAP_ARE_SORTED assert (IsSorted()); @@ -1148,6 +1148,8 @@ break; } } + if (next == end && full_size > curr_base) + pos->SetByteSize (full_size - curr_base); } } } @@ -1305,6 +1307,22 @@ return nullptr; } + const Entry* + FindEntryStartsAt (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (!m_entries.empty()) + { + auto begin = m_entries.begin(), end = m_entries.end(); + auto pos = std::lower_bound (begin, end, Entry(addr, 1), BaseLessThan); + if (pos != end && pos->base == addr) + return &(*pos); + } + return nullptr; + } + Entry * Back() { Index: include/lldb/Symbol/DWARFCallFrameInfo.h =================================================================== --- include/lldb/Symbol/DWARFCallFrameInfo.h +++ include/lldb/Symbol/DWARFCallFrameInfo.h @@ -73,6 +73,9 @@ void GetFunctionAddressAndSizeVector (FunctionAddressAndSizeVector &function_info); + void + ForEachFDEEntries(const std::function& callback); + private: enum { Index: include/lldb/Symbol/Symtab.h =================================================================== --- include/lldb/Symbol/Symtab.h +++ include/lldb/Symbol/Symtab.h @@ -79,7 +79,7 @@ size_t FindAllSymbolsWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector& symbol_indexes); size_t FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector& symbol_indexes); Symbol * FindFirstSymbolWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility); - Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes); + Symbol * FindSymbolAtFileAddress (lldb::addr_t file_addr); Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr); void ForEachSymbolContainingFileAddress(lldb::addr_t file_addr, std::function const &callback); size_t FindFunctionSymbols (const ConstString &name, uint32_t name_type_mask, SymbolContextList& sc_list); Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.h =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -150,9 +150,6 @@ lldb_private::Symtab * GetSymtab() override; - lldb_private::Symbol * - ResolveSymbolForAddress(const lldb_private::Address& so_addr, bool verify_unique) override; - bool IsStripped () override; @@ -349,6 +346,10 @@ const ELFSectionHeaderInfo *rela_hdr, lldb::user_id_t section_id); + void + ParseUnwindSymbols(lldb_private::Symtab *symbol_table, + lldb_private::DWARFCallFrameInfo* eh_frame); + /// Relocates debug sections unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, lldb::user_id_t rel_id); Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2323,11 +2323,11 @@ mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) ); } - // In ELF all symbol should have a valid size but it is not true for some code symbols - // coming from hand written assembly. As none of the code symbol should have 0 size we try - // to calculate the size for these symbols in the symtab with saying that their original + // In ELF all symbol should have a valid size but it is not true for some function symbols + // coming from hand written assembly. As none of the function symbol should have 0 size we + // try to calculate the size for these symbols in the symtab with saying that their original // size is not valid. - bool symbol_size_valid = symbol.st_size != 0 || symbol_type != eSymbolTypeCode; + bool symbol_size_valid = symbol.st_size != 0 || symbol.getType() != STT_FUNC; Symbol dc_symbol( i + start_id, // ID is the original symbol table index. @@ -2854,6 +2854,14 @@ } } + DWARFCallFrameInfo* eh_frame = GetUnwindTable().GetEHFrameInfo(); + if (eh_frame) + { + if (m_symtab_ap == nullptr) + m_symtab_ap.reset(new Symtab(this)); + ParseUnwindSymbols (m_symtab_ap.get(), eh_frame); + } + // If we still don't have any symtab then create an empty instance to avoid do the section // lookup next time. if (m_symtab_ap == nullptr) @@ -2883,57 +2891,63 @@ return m_symtab_ap.get(); } -Symbol * -ObjectFileELF::ResolveSymbolForAddress(const Address& so_addr, bool verify_unique) +void +ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, DWARFCallFrameInfo* eh_frame) { - if (!m_symtab_ap.get()) - return nullptr; // GetSymtab() should be called first. - - const SectionList *section_list = GetSectionList(); + SectionList* section_list = GetSectionList(); if (!section_list) - return nullptr; + return; - if (DWARFCallFrameInfo *eh_frame = GetUnwindTable().GetEHFrameInfo()) - { - AddressRange range; - if (eh_frame->GetAddressRange (so_addr, range)) + // First we save the new symbols into a separate list and add them to the symbol table after + // we colleced all symbols we want to add. This is neccessary because adding a new symbol + // invalidates the internal index of the symtab what causing the next lookup to be slow because + // it have to recalculate the index first. + std::vector new_symbols; + + eh_frame->ForEachFDEEntries( + [symbol_table, section_list, &new_symbols](lldb::addr_t file_addr, + uint32_t size, + dw_offset_t) { + Symbol* symbol = symbol_table->FindSymbolAtFileAddress(file_addr); + if (symbol) { - const addr_t file_addr = range.GetBaseAddress().GetFileAddress(); - Symbol * symbol = verify_unique ? m_symtab_ap->FindSymbolContainingFileAddress(file_addr) : nullptr; - if (symbol) - return symbol; - - // Note that a (stripped) symbol won't be found by GetSymtab()... - lldb::SectionSP eh_sym_section_sp = section_list->FindSectionContainingFileAddress(file_addr); - if (eh_sym_section_sp.get()) + if (!symbol->GetByteSizeIsValid()) { - addr_t section_base = eh_sym_section_sp->GetFileAddress(); - addr_t offset = file_addr - section_base; - uint64_t symbol_id = m_symtab_ap->GetNumSymbols(); - + symbol->SetByteSize(size); + symbol->SetSizeIsSynthesized(true); + } + } + else + { + SectionSP section_sp = section_list->FindSectionContainingFileAddress(file_addr); + if (section_sp) + { + addr_t offset = file_addr - section_sp->GetFileAddress();; + uint64_t symbol_id = symbol_table->GetNumSymbols(); Symbol eh_symbol( - symbol_id, // Symbol table index. - "???", // Symbol name. - false, // Is the symbol name mangled? - eSymbolTypeCode, // Type of this symbol. - true, // Is this globally visible? - false, // Is this symbol debug info? - false, // Is this symbol a trampoline? - true, // Is this symbol artificial? - eh_sym_section_sp, // Section in which this symbol is defined or null. - offset, // Offset in section or symbol value. - range.GetByteSize(), // Size in bytes of this symbol. - true, // Size is valid. - false, // Contains linker annotations? - 0); // Symbol flags. - if (symbol_id == m_symtab_ap->AddSymbol(eh_symbol)) - return m_symtab_ap->SymbolAtIndex(symbol_id); + symbol_id, // Symbol table index. + "???", // Symbol name. + false, // Is the symbol name mangled? + eSymbolTypeCode, // Type of this symbol. + true, // Is this globally visible? + false, // Is this symbol debug info? + false, // Is this symbol a trampoline? + true, // Is this symbol artificial? + section_sp, // Section in which this symbol is defined or null. + offset, // Offset in section or symbol value. + 0, // Size: Don't specify the size as an FDE can + false, // Size is valid: cover multiple symbols. + false, // Contains linker annotations? + 0); // Symbol flags. + new_symbols.push_back(eh_symbol); } } - } - return nullptr; -} + return true; + }); + for (const Symbol& s : new_symbols) + symbol_table->AddSymbol(s); +} bool ObjectFileELF::IsStripped () Index: source/Symbol/DWARFCallFrameInfo.cpp =================================================================== --- source/Symbol/DWARFCallFrameInfo.cpp +++ source/Symbol/DWARFCallFrameInfo.cpp @@ -899,3 +899,17 @@ } return false; } + +void +DWARFCallFrameInfo::ForEachFDEEntries( + const std::function& callback) +{ + GetFDEIndex(); + + for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) + { + const FDEEntryMap::Entry& entry = m_fde_index.GetEntryRef(i); + if (!callback(entry.base, entry.size, entry.data)) + break; + } +} Index: source/Symbol/Symtab.cpp =================================================================== --- source/Symbol/Symtab.cpp +++ source/Symbol/Symtab.cpp @@ -944,43 +944,33 @@ m_file_addr_to_index.Append(entry); } } + + lldb::addr_t total_size = 0; + const size_t num_entries = m_file_addr_to_index.GetSize(); if (num_entries > 0) { m_file_addr_to_index.Sort(); - m_file_addr_to_index.CalculateSizesOfZeroByteSizeRanges(); - + // Now our last symbols might not have had sizes because there // was no subsequent symbol to calculate the size from. If this is // the case, then calculate the size by capping it at the end of the // section in which the symbol resides for (int i = num_entries - 1; i >= 0; --i) { - const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i); - // As we iterate backwards, as soon as we find a symbol with a valid - // byte size, we are done + const FileRangeToIndexMap::Entry& entry = m_file_addr_to_index.GetEntryRef(i); + + // As we iterate backwards, as soon as we find a symbol with a valid byte size, we + // are done. if (entry.GetByteSize() > 0) break; - // Cap the size to the end of the section in which the symbol resides - SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (entry.GetRangeBase())); - if (section_sp) - { - const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize(); - const lldb::addr_t symbol_file_addr = entry.GetRangeBase(); - if (end_section_file_addr > symbol_file_addr) - { - Symbol &symbol = m_symbols[entry.data]; - if (!symbol.GetByteSizeIsValid()) - { - symbol.SetByteSize(end_section_file_addr - symbol_file_addr); - symbol.SetSizeIsSynthesized(true); - } - } - } + const Address& address = m_symbols[entry.data].GetAddressRef(); + if (SectionSP section_sp = address.GetSection()) + total_size = entry.base + section_sp->GetByteSize() - address.GetOffset(); } - // Sort again in case the range size changes the ordering - m_file_addr_to_index.Sort(); + + m_file_addr_to_index.CalculateSizesOfZeroByteSizeRanges(total_size); } } } @@ -1020,37 +1010,18 @@ } Symbol * -Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) +Symtab::FindSymbolAtFileAddress (addr_t file_addr) { Mutex::Locker locker (m_mutex); + if (!m_file_addr_to_index_computed) + InitAddressIndexes(); - - SymbolSearchInfo info = { this, file_addr, nullptr, nullptr, 0 }; - - ::bsearch (&info, - indexes, - num_indexes, - sizeof(uint32_t), - (ComparisonFunction)SymbolWithClosestFileAddress); - - if (info.match_symbol) + const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryStartsAt(file_addr); + if (entry) { - if (info.match_offset == 0) - { - // We found an exact match! - return info.match_symbol; - } - - if (!info.match_symbol->GetByteSizeIsValid()) - { - // The matched symbol dosn't have a valid byte size so lets just go with that match... - return info.match_symbol; - } - - // We were able to figure out a symbol size so lets make sure our - // offset puts "file_addr" in the symbol's address range. - if (info.match_offset < info.match_symbol->GetByteSize()) - return info.match_symbol; + Symbol* symbol = SymbolAtIndex(entry->data); + if (symbol->GetFileAddress() == file_addr) + return symbol; } return nullptr; } @@ -1088,8 +1059,12 @@ for (size_t i = 0; i < addr_match_count; ++i) { - if (!callback(SymbolAtIndex(all_addr_indexes[i]))) - break; + Symbol* symbol = SymbolAtIndex(all_addr_indexes[i]); + if (symbol->ContainsFileAddress(file_addr)) + { + if (!callback(symbol)) + break; + } } }