forked from OSchip/llvm-project
Improve the handling of missing elf symtab and missing symbol sizes
* Generate artificial symbol names from eh_fame during symbol parsing so these symbols are already present when we calcualte the size of the symbols where 0 is specified. * Fix symbol size calculation for the last symbol in the file where it have to last until the end of the parent section. This is the re-commit of the original change after fixing some test failures on OSX. Differential revision: http://reviews.llvm.org/D16996 llvm-svn: 261205
This commit is contained in:
parent
a6560ebe4c
commit
6b63b14851
|
@ -1123,7 +1123,7 @@ namespace lldb_private {
|
|||
// 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 @@ namespace lldb_private {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (next == end && full_size > curr_base)
|
||||
pos->SetByteSize (full_size - curr_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1305,6 +1307,22 @@ namespace lldb_private {
|
|||
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()
|
||||
{
|
||||
|
|
|
@ -73,6 +73,9 @@ public:
|
|||
void
|
||||
GetFunctionAddressAndSizeVector (FunctionAddressAndSizeVector &function_info);
|
||||
|
||||
void
|
||||
ForEachFDEEntries(const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)>& callback);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -860,6 +860,7 @@ protected:
|
|||
const lldb::addr_t m_memory_addr;
|
||||
std::unique_ptr<lldb_private::SectionList> m_sections_ap;
|
||||
std::unique_ptr<lldb_private::Symtab> m_symtab_ap;
|
||||
uint32_t m_synthetic_symbol_idx;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Sets the architecture for a module. At present the architecture
|
||||
|
@ -873,7 +874,11 @@ protected:
|
|||
/// Returns \b true if the architecture was changed, \b
|
||||
/// false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool SetModulesArchitecture (const ArchSpec &new_arch);
|
||||
bool
|
||||
SetModulesArchitecture (const ArchSpec &new_arch);
|
||||
|
||||
ConstString
|
||||
GetNextSyntheticSymbolName();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (ObjectFile);
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
size_t FindAllSymbolsWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes);
|
||||
size_t FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& 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<bool(Symbol *)> const &callback);
|
||||
size_t FindFunctionSymbols (const ConstString &name, uint32_t name_type_mask, SymbolContextList& sc_list);
|
||||
|
|
|
@ -2332,11 +2332,11 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
|
|||
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.
|
||||
|
@ -2863,6 +2863,14 @@ ObjectFileELF::GetSymtab()
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -2892,57 +2900,64 @@ ObjectFileELF::GetSymtab()
|
|||
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<Symbol> new_symbols;
|
||||
|
||||
eh_frame->ForEachFDEEntries(
|
||||
[this, 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 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->SetByteSize(size);
|
||||
symbol->SetSizeIsSynthesized(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
SectionSP section_sp = section_list->FindSectionContainingFileAddress(file_addr);
|
||||
if (section_sp)
|
||||
{
|
||||
addr_t offset = file_addr - section_sp->GetFileAddress();
|
||||
const char* symbol_name = GetNextSyntheticSymbolName().GetCString();
|
||||
uint64_t symbol_id = symbol_table->GetNumSymbols();
|
||||
Symbol eh_symbol(
|
||||
symbol_id, // Symbol table index.
|
||||
symbol_name, // 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 true;
|
||||
});
|
||||
|
||||
for (const Symbol& s : new_symbols)
|
||||
symbol_table->AddSymbol(s);
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectFileELF::IsStripped ()
|
||||
|
|
|
@ -150,9 +150,6 @@ public:
|
|||
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 @@ private:
|
|||
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);
|
||||
|
|
|
@ -4518,7 +4518,6 @@ ObjectFileMachO::ParseSymtab ()
|
|||
|
||||
if (function_starts_count > 0)
|
||||
{
|
||||
char synthetic_function_symbol[PATH_MAX];
|
||||
uint32_t num_synthetic_function_symbols = 0;
|
||||
for (i=0; i<function_starts_count; ++i)
|
||||
{
|
||||
|
@ -4533,7 +4532,6 @@ ObjectFileMachO::ParseSymtab ()
|
|||
num_syms = sym_idx + num_synthetic_function_symbols;
|
||||
sym = symtab->Resize (num_syms);
|
||||
}
|
||||
uint32_t synthetic_function_symbol_idx = 0;
|
||||
for (i=0; i<function_starts_count; ++i)
|
||||
{
|
||||
const FunctionStarts::Entry *func_start_entry = function_starts.GetEntryAtIndex (i);
|
||||
|
@ -4568,13 +4566,8 @@ ObjectFileMachO::ParseSymtab ()
|
|||
{
|
||||
symbol_byte_size = section_end_file_addr - symbol_file_addr;
|
||||
}
|
||||
snprintf (synthetic_function_symbol,
|
||||
sizeof(synthetic_function_symbol),
|
||||
"___lldb_unnamed_function%u$$%s",
|
||||
++synthetic_function_symbol_idx,
|
||||
module_sp->GetFileSpec().GetFilename().GetCString());
|
||||
sym[sym_idx].SetID (synthetic_sym_id++);
|
||||
sym[sym_idx].GetMangled().SetDemangledName(ConstString(synthetic_function_symbol));
|
||||
sym[sym_idx].GetMangled().SetDemangledName(GetNextSyntheticSymbolName());
|
||||
sym[sym_idx].SetType (eSymbolTypeCode);
|
||||
sym[sym_idx].SetIsSynthetic (true);
|
||||
sym[sym_idx].GetAddressRef() = symbol_addr;
|
||||
|
|
|
@ -899,3 +899,17 @@ DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DWARFCallFrameInfo::ForEachFDEEntries(
|
||||
const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)>& 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,8 +241,7 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
|
|||
lldb::offset_t file_offset,
|
||||
lldb::offset_t length,
|
||||
const lldb::DataBufferSP& data_sp,
|
||||
lldb::offset_t data_offset
|
||||
) :
|
||||
lldb::offset_t data_offset) :
|
||||
ModuleChild (module_sp),
|
||||
m_file (), // This file could be different from the original module's file
|
||||
m_type (eTypeInvalid),
|
||||
|
@ -254,7 +253,8 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
|
|||
m_process_wp(),
|
||||
m_memory_addr (LLDB_INVALID_ADDRESS),
|
||||
m_sections_ap(),
|
||||
m_symtab_ap ()
|
||||
m_symtab_ap (),
|
||||
m_synthetic_symbol_idx (0)
|
||||
{
|
||||
if (file_spec_ptr)
|
||||
m_file = *file_spec_ptr;
|
||||
|
@ -286,7 +286,8 @@ ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
|
|||
m_process_wp (process_sp),
|
||||
m_memory_addr (header_addr),
|
||||
m_sections_ap(),
|
||||
m_symtab_ap ()
|
||||
m_symtab_ap (),
|
||||
m_synthetic_symbol_idx (0)
|
||||
{
|
||||
if (header_data_sp)
|
||||
m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
|
||||
|
@ -653,3 +654,13 @@ ObjectFile::GetSymbolTypeFromName (llvm::StringRef name,
|
|||
}
|
||||
return symbol_type_hint;
|
||||
}
|
||||
|
||||
ConstString
|
||||
ObjectFile::GetNextSyntheticSymbolName()
|
||||
{
|
||||
StreamString ss;
|
||||
ConstString file_name = GetModule()->GetFileSpec().GetFilename();
|
||||
ss.Printf("___lldb_unnamed_symbol%u$$%s", ++m_synthetic_symbol_idx, file_name.GetCString());
|
||||
return ConstString(ss.GetData());
|
||||
}
|
||||
|
||||
|
|
|
@ -894,35 +894,6 @@ typedef struct
|
|||
addr_t match_offset;
|
||||
} SymbolSearchInfo;
|
||||
|
||||
static int
|
||||
SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
|
||||
{
|
||||
const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
|
||||
if (symbol == nullptr)
|
||||
return -1;
|
||||
|
||||
const addr_t info_file_addr = info->file_addr;
|
||||
if (symbol->ValueIsAddress())
|
||||
{
|
||||
const addr_t curr_file_addr = symbol->GetAddressRef().GetFileAddress();
|
||||
if (info_file_addr < curr_file_addr)
|
||||
return -1;
|
||||
|
||||
// Since we are finding the closest symbol that is greater than or equal
|
||||
// to 'info->file_addr' we set the symbol here. This will get set
|
||||
// multiple times, but after the search is done it will contain the best
|
||||
// symbol match
|
||||
info->match_symbol = const_cast<Symbol *>(symbol);
|
||||
info->match_index_ptr = index_ptr;
|
||||
info->match_offset = info_file_addr - curr_file_addr;
|
||||
|
||||
if (info_file_addr > curr_file_addr)
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
Symtab::InitAddressIndexes()
|
||||
{
|
||||
|
@ -944,43 +915,26 @@ Symtab::InitAddressIndexes()
|
|||
m_file_addr_to_index.Append(entry);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// Now our last address range 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)
|
||||
lldb::addr_t total_size = 0;
|
||||
const FileRangeToIndexMap::Entry* entry = m_file_addr_to_index.Back();
|
||||
if (entry->GetByteSize() == 0)
|
||||
{
|
||||
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 +974,18 @@ Symtab::CalculateSymbolSizes ()
|
|||
}
|
||||
|
||||
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 +1023,12 @@ Symtab::ForEachSymbolContainingFileAddress(addr_t file_addr, std::function<bool(
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue