bool SymbolContext::GetAddressRange (uint32_t scope, AddressRange &range) const { if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) { range = line_entry.range; return true; } else if ((scope & eSymbolContextFunction) && function != NULL) { range = function->GetAddressRange(); return true; } else if ((scope & eSymbolContextSymbol) && symbol != NULL && symbol->GetAddressRangePtr()) { range = *symbol->GetAddressRangePtr(); if (range.GetByteSize() == 0) { if (module_sp) { ObjectFile *objfile = module_sp->GetObjectFile(); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) range.SetByteSize(symtab->CalculateSymbolSize (symbol)); } } } return true; } range.Clear(); return false; }
size_t Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are // already thread safe. Timer scoped_timer(__PRETTY_FUNCTION__, "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", name.AsCString(), symbol_type); const size_t initial_size = sc_list.GetSize(); ObjectFile *objfile = GetObjectFile (); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes); SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); } } return sc_list.GetSize() - initial_size; }
// Find the load address of a symbol static lldb::addr_t findSymbolAddress( Process *proc, ConstString findName ) { assert( proc != nullptr ); ModuleSP module = proc->GetTarget().GetExecutableModule(); assert( module.get() != nullptr ); ObjectFile *exe = module->GetObjectFile(); assert( exe != nullptr ); lldb_private::Symtab *symtab = exe->GetSymtab( ); assert( symtab != nullptr ); for ( size_t i = 0; i < symtab->GetNumSymbols( ); i++ ) { const Symbol* sym = symtab->SymbolAtIndex( i ); assert( sym != nullptr ); const ConstString &symName = sym->GetName( ); if ( ConstString::Compare( findName, symName ) == 0 ) { Address addr = sym->GetAddress(); return addr.GetLoadAddress( & proc->GetTarget() ); } } return LLDB_INVALID_ADDRESS; }
Symtab *SymbolVendor::GetSymtab() { ModuleSP module_sp(GetModule()); if (module_sp) { ObjectFile *objfile = module_sp->GetObjectFile(); if (objfile) { // Get symbol table from unified section list. return objfile->GetSymtab(); } } return nullptr; }
uint32_t Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) { Mutex::Locker locker (m_mutex); uint32_t resolved_flags = 0; // Clear the result symbol context in case we don't find anything sc.Clear(); // Get the section from the section/offset address. const Section *section = so_addr.GetSection(); // Make sure the section matches this module before we try and match anything if (section && section->GetModule() == this) { // If the section offset based address resolved itself, then this // is the right module. sc.module_sp = GetSP(); resolved_flags |= eSymbolContextModule; // Resolve the compile unit, function, block, line table or line // entry if requested. if (resolve_scope & eSymbolContextCompUnit || resolve_scope & eSymbolContextFunction || resolve_scope & eSymbolContextBlock || resolve_scope & eSymbolContextLineEntry ) { SymbolVendor *symbols = GetSymbolVendor (); if (symbols) resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc); } // Resolve the symbol if requested, but don't re-look it up if we've already found it. if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol)) { ObjectFile* ofile = GetObjectFile(); if (ofile) { Symtab *symtab = ofile->GetSymtab(); if (symtab) { if (so_addr.IsSectionOffset()) { sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); if (sc.symbol) resolved_flags |= eSymbolContextSymbol; } } } } } return resolved_flags; }
const Symbol * Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type) { Timer scoped_timer(__PRETTY_FUNCTION__, "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)", name.AsCString(), symbol_type); ObjectFile *objfile = GetObjectFile(); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) return symtab->FindFirstSymbolWithNameAndType (name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); } return NULL; }
uint32_t Module::FindFunctions (const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_symbols, bool include_inlines, bool append, SymbolContextList& sc_list) { if (!append) sc_list.Clear(); const uint32_t start_size = sc_list.GetSize(); // Find all the functions (not symbols, but debug information functions... SymbolVendor *symbols = GetSymbolVendor (); if (symbols) symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list); // Now check our symbol table for symbols that are code symbols if requested if (include_symbols) { ObjectFile *objfile = GetObjectFile(); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); const uint32_t num_matches = symbol_indexes.size(); if (num_matches) { const bool merge_symbol_into_function = true; SymbolContext sc(this); for (uint32_t i=0; i<num_matches; i++) { sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); sc_list.AppendIfUnique (sc, merge_symbol_into_function); } } } } } return sc_list.GetSize() - start_size; }
uint32_t Module::FindFunctions (const RegularExpression& regex, bool include_symbols, bool include_inlines, bool append, SymbolContextList& sc_list) { if (!append) sc_list.Clear(); const uint32_t start_size = sc_list.GetSize(); SymbolVendor *symbols = GetSymbolVendor (); if (symbols) symbols->FindFunctions(regex, include_inlines, append, sc_list); // Now check our symbol table for symbols that are code symbols if requested if (include_symbols) { ObjectFile *objfile = GetObjectFile(); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->AppendSymbolIndexesMatchingRegExAndType (regex, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); const uint32_t num_matches = symbol_indexes.size(); if (num_matches) { const bool merge_symbol_into_function = true; SymbolContext sc(this); for (uint32_t i=0; i<num_matches; i++) { sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); sc_list.AppendIfUnique (sc, merge_symbol_into_function); } } } } } return sc_list.GetSize() - start_size; }
size_t Module::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, SymbolType symbol_type, SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are // already thread safe. Timer scoped_timer(__PRETTY_FUNCTION__, "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)", regex.GetText(), symbol_type); const size_t initial_size = sc_list.GetSize(); ObjectFile *objfile = GetObjectFile (); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); } } return sc_list.GetSize() - initial_size; }
bool Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const { // If the section was NULL, only load address is going to work unless we are // trying to deref a pointer SectionSP section_sp (GetSection()); if (!section_sp && style != DumpStyleResolvedPointerDescription) style = DumpStyleLoadAddress; ExecutionContext exe_ctx (exe_scope); Target *target = exe_ctx.GetTargetPtr(); // If addr_byte_size is UINT32_MAX, then determine the correct address // byte size for the process or default to the size of addr_t if (addr_size == UINT32_MAX) { if (target) addr_size = target->GetArchitecture().GetAddressByteSize (); else addr_size = sizeof(addr_t); } Address so_addr; switch (style) { case DumpStyleInvalid: return false; case DumpStyleSectionNameOffset: if (section_sp) { section_sp->DumpName(s); s->Printf (" + %llu", m_offset); } else { s->Address(m_offset, addr_size); } break; case DumpStyleSectionPointerOffset: s->Printf("(Section *)%p + ", section_sp.get()); s->Address(m_offset, addr_size); break; case DumpStyleModuleWithFileAddress: if (section_sp) s->Printf("%s[", section_sp->GetModule()->GetFileSpec().GetFilename().AsCString()); // Fall through case DumpStyleFileAddress: { addr_t file_addr = GetFileAddress(); if (file_addr == LLDB_INVALID_ADDRESS) { if (fallback_style != DumpStyleInvalid) return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); return false; } s->Address (file_addr, addr_size); if (style == DumpStyleModuleWithFileAddress && section_sp) s->PutChar(']'); } break; case DumpStyleLoadAddress: { addr_t load_addr = GetLoadAddress (target); if (load_addr == LLDB_INVALID_ADDRESS) { if (fallback_style != DumpStyleInvalid) return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); return false; } s->Address (load_addr, addr_size); } break; case DumpStyleResolvedDescription: case DumpStyleResolvedDescriptionNoModule: if (IsSectionOffset()) { uint32_t pointer_size = 4; ModuleSP module_sp (GetModule()); if (target) pointer_size = target->GetArchitecture().GetAddressByteSize(); else if (module_sp) pointer_size = module_sp->GetArchitecture().GetAddressByteSize(); bool showed_info = false; if (section_sp) { SectionType sect_type = section_sp->GetType(); switch (sect_type) { case eSectionTypeData: if (module_sp) { ObjectFile *objfile = module_sp->GetObjectFile(); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { const addr_t file_Addr = GetFileAddress(); Symbol *symbol = symtab->FindSymbolContainingFileAddress (file_Addr); if (symbol) { const char *symbol_name = symbol->GetName().AsCString(); if (symbol_name) { s->PutCString(symbol_name); addr_t delta = file_Addr - symbol->GetAddress().GetFileAddress(); if (delta) s->Printf(" + %llu", delta); showed_info = true; } } } } } break; case eSectionTypeDataCString: // Read the C string from memory and display it showed_info = true; ReadCStringFromMemory (exe_scope, *this, s); break; case eSectionTypeDataCStringPointers: { if (ReadAddress (exe_scope, *this, pointer_size, so_addr)) { #if VERBOSE_OUTPUT s->PutCString("(char *)"); so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); s->PutCString(": "); #endif showed_info = true; ReadCStringFromMemory (exe_scope, so_addr, s); } } break; case eSectionTypeDataObjCMessageRefs: { if (ReadAddress (exe_scope, *this, pointer_size, so_addr)) { if (target && so_addr.IsSectionOffset()) { SymbolContext func_sc; target->GetImages().ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, func_sc); if (func_sc.function || func_sc.symbol) { showed_info = true; #if VERBOSE_OUTPUT s->PutCString ("(objc_msgref *) -> { (func*)"); so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); #else s->PutCString ("{ "); #endif Address cstr_addr(*this); cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size); func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false); if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr)) { #if VERBOSE_OUTPUT s->PutCString("), (char *)"); so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); s->PutCString(" ("); #else s->PutCString(", "); #endif ReadCStringFromMemory (exe_scope, so_addr, s); } #if VERBOSE_OUTPUT s->PutCString(") }"); #else s->PutCString(" }"); #endif } } } } break; case eSectionTypeDataObjCCFStrings: { Address cfstring_data_addr(*this); cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() + (2 * pointer_size)); if (ReadAddress (exe_scope, cfstring_data_addr, pointer_size, so_addr)) { #if VERBOSE_OUTPUT s->PutCString("(CFString *) "); cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); s->PutCString(" -> @"); #else s->PutChar('@'); #endif if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription)) showed_info = true; } } break; case eSectionTypeData4: // Read the 4 byte data and display it showed_info = true; s->PutCString("(uint32_t) "); DumpUInt (exe_scope, *this, 4, s); break; case eSectionTypeData8: // Read the 8 byte data and display it showed_info = true; s->PutCString("(uint64_t) "); DumpUInt (exe_scope, *this, 8, s); break; case eSectionTypeData16: // Read the 16 byte data and display it showed_info = true; s->PutCString("(uint128_t) "); DumpUInt (exe_scope, *this, 16, s); break; case eSectionTypeDataPointers: // Read the pointer data and display it { if (ReadAddress (exe_scope, *this, pointer_size, so_addr)) { s->PutCString ("(void *)"); so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); showed_info = true; if (so_addr.IsSectionOffset()) { SymbolContext pointer_sc; if (target) { target->GetImages().ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, pointer_sc); if (pointer_sc.function || pointer_sc.symbol) { s->PutCString(": "); pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false); } } } } } break; default: break; } } if (!showed_info) { if (module_sp) { SymbolContext sc; module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); if (sc.function || sc.symbol) { bool show_stop_context = true; const bool show_module = (style == DumpStyleResolvedDescription); const bool show_fullpaths = false; const bool show_inlined_frames = true; if (sc.function == NULL && sc.symbol != NULL) { // If we have just a symbol make sure it is in the right section if (sc.symbol->ValueIsAddress()) { if (sc.symbol->GetAddress().GetSection() != GetSection()) { // don't show the module if the symbol is a trampoline symbol show_stop_context = false; } } } if (show_stop_context) { // We have a function or a symbol from the same // sections as this address. sc.DumpStopContext (s, exe_scope, *this, show_fullpaths, show_module, show_inlined_frames); } else { // We found a symbol but it was in a different // section so it isn't the symbol we should be // showing, just show the section name + offset Dump (s, exe_scope, DumpStyleSectionNameOffset); } } } } } else { if (fallback_style != DumpStyleInvalid) return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); return false; } break; case DumpStyleDetailedSymbolContext: if (IsSectionOffset()) { ModuleSP module_sp (GetModule()); if (module_sp) { SymbolContext sc; module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); if (sc.symbol) { // If we have just a symbol make sure it is in the same section // as our address. If it isn't, then we might have just found // the last symbol that came before the address that we are // looking up that has nothing to do with our address lookup. if (sc.symbol->ValueIsAddress() && sc.symbol->GetAddress().GetSection() != GetSection()) sc.symbol = NULL; } sc.GetDescription(s, eDescriptionLevelBrief, target); if (sc.block) { bool can_create = true; bool get_parent_variables = true; bool stop_if_block_is_inlined_function = false; VariableList variable_list; sc.block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, &variable_list); uint32_t num_variables = variable_list.GetSize(); for (uint32_t var_idx = 0; var_idx < num_variables; ++var_idx) { Variable *var = variable_list.GetVariableAtIndex (var_idx).get(); if (var && var->LocationIsValidForAddress (*this)) { s->Indent(); s->Printf (" Variable: id = {0x%8.8llx}, name = \"%s\", type= \"%s\", location =", var->GetID(), var->GetName().GetCString(), var->GetType()->GetName().GetCString()); var->DumpLocationForAddress(s, *this); s->PutCString(", decl = "); var->GetDeclaration().DumpStopContext(s, false); s->EOL(); } } } } } else { if (fallback_style != DumpStyleInvalid) return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); return false; } break; case DumpStyleResolvedPointerDescription: { Process *process = exe_ctx.GetProcessPtr(); if (process) { addr_t load_addr = GetLoadAddress (target); if (load_addr != LLDB_INVALID_ADDRESS) { Error memory_error; addr_t dereferenced_load_addr = process->ReadPointerFromMemory(load_addr, memory_error); if (dereferenced_load_addr != LLDB_INVALID_ADDRESS) { Address dereferenced_addr; if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr, target)) { StreamString strm; if (dereferenced_addr.Dump (&strm, exe_scope, DumpStyleResolvedDescription, DumpStyleInvalid, addr_size)) { s->Address (dereferenced_load_addr, addr_size, " -> ", " "); s->Write(strm.GetData(), strm.GetSize()); return true; } } } } } if (fallback_style != DumpStyleInvalid) return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); return false; } break; } return true; }