size_t Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_mixed_context_lines, bool show_bytes, Stream &strm ) { size_t success_count = 0; const size_t count = sc_list.GetSize(); SymbolContext sc; AddressRange range; for (size_t i=0; i<count; ++i) { if (sc_list.GetContextAtIndex(i, sc) == false) break; if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range)) { if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm)) { ++success_count; strm.EOL(); } } } return success_count; }
size_t ModuleList::FindFunctionSymbols (const ConstString &name, uint32_t name_type_mask, SymbolContextList& sc_list) { const size_t old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeAuto) { ConstString lookup_name; uint32_t lookup_name_type_mask = 0; bool match_name_after_lookup = false; Module::PrepareForFunctionNameLookup (name, name_type_mask, eLanguageTypeUnknown, // TODO: add support lookup_name, lookup_name_type_mask, match_name_after_lookup); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctionSymbols (lookup_name, lookup_name_type_mask, sc_list); } if (match_name_after_lookup) { SymbolContext sc; size_t i = old_size; while (i < sc_list.GetSize()) { if (sc_list.GetContextAtIndex(i, sc)) { const char *func_name = sc.GetFunctionName().GetCString(); if (func_name != nullptr && strstr(func_name, name.GetCString()) == nullptr) { // Remove the current context sc_list.RemoveContextAtIndex(i); // Don't increment i and continue in the loop continue; } } ++i; } } } else { Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list); } } return sc_list.GetSize() - old_size; }
bool Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) { bool dumped_declaration_info = false; if (m_owner_scope) { SymbolContext sc; m_owner_scope->CalculateSymbolContext(&sc); sc.block = nullptr; sc.line_entry.Clear(); bool show_inlined_frames = false; const bool show_function_arguments = true; const bool show_function_name = true; dumped_declaration_info = sc.DumpStopContext (s, nullptr, Address(), show_fullpaths, show_module, show_inlined_frames, show_function_arguments, show_function_name); if (sc.function) s->PutChar(':'); } if (m_declaration.DumpStopContext (s, false)) dumped_declaration_info = true; return dumped_declaration_info; }
Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool complete) { if (context.module_sp) { SymbolContextList sc_list; const bool include_symbols = true; const bool include_inlines = true; const bool append = true; context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list); SymbolContext sc; // Now add the functions & symbols to the list - only add if unique: for (uint32_t i = 0; i < sc_list.GetSize(); i++) { if (sc_list.GetContextAtIndex(i, sc)) { ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); if (!func_name.IsEmpty()) m_match_set.insert (func_name); } } } return Searcher::eCallbackReturnContinue; }
ThreadPlanSP DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) { LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); ThreadPlanSP thread_plan_sp; StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); Symbol *sym = context.symbol; if (sym == NULL || !sym->IsTrampoline()) return thread_plan_sp; const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); if (!sym_name) return thread_plan_sp; SymbolContextList target_symbols; Target &target = thread.GetProcess().GetTarget(); ModuleList &images = target.GetImages(); images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); size_t num_targets = target_symbols.GetSize(); if (!num_targets) return thread_plan_sp; typedef std::vector<lldb::addr_t> AddressVector; AddressVector addrs; for (size_t i = 0; i < num_targets; ++i) { SymbolContext context; AddressRange range; if (target_symbols.GetContextAtIndex(i, context)) { context.GetAddressRange(eSymbolContextEverything, 0, false, range); lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); if (addr != LLDB_INVALID_ADDRESS) addrs.push_back(addr); } } if (addrs.size() > 0) { AddressVector::iterator start = addrs.begin(); AddressVector::iterator end = addrs.end(); std::sort(start, end); addrs.erase(std::unique(start, end), end); thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); } return thread_plan_sp; }
bool ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, FrameComparison operation, void *baton) { bool should_stop_here = true; StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); // First see if the ThreadPlanShouldStopHere default implementation thinks we should get out of here: should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (current_plan, flags, operation, baton); if (!should_stop_here) return should_stop_here; if (should_stop_here && current_plan->GetKind() == eKindStepInRange && operation == eFrameCompareYounger) { ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); if (step_in_range_plan->m_step_into_target) { SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); if (sc.symbol != NULL) { // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare. if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) { should_stop_here = true; } else { const char *target_name = step_in_range_plan->m_step_into_target.AsCString(); const char *function_name = sc.GetFunctionName().AsCString(); if (function_name == NULL) should_stop_here = false; else if (strstr (function_name, target_name) == NULL) should_stop_here = false; } if (log && !should_stop_here) log->Printf("Stepping out of frame %s which did not match step into target %s.", sc.GetFunctionName().AsCString(), step_in_range_plan->m_step_into_target.AsCString()); } } if (should_stop_here) { ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria. should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria (); } } return should_stop_here; }
bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread (ThreadSP thread_sp) { if (thread_sp && thread_sp->GetStackFrameCount() > 0 && thread_sp->GetFrameWithConcreteFrameIndex(0)) { const SymbolContext sym_ctx (thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext (eSymbolContextSymbol)); static ConstString g_select_symbol ("__select"); if (sym_ctx.GetFunctionName() == g_select_symbol) { return false; } } return true; }
size_t Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { size_t success_count = 0; const size_t count = sc_list.GetSize(); SymbolContext sc; AddressRange range; const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = true; for (size_t i=0; i<count; ++i) { if (sc_list.GetContextAtIndex(i, sc) == false) break; for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx) { if (Disassemble (debugger, arch, plugin_name, flavor, exe_ctx, range, num_instructions, num_mixed_context_lines, options, strm)) { ++success_count; strm.EOL(); } } } return success_count; }
void StackTrace::OutputToStream(std::ostream* os) { SymbolContext* context = SymbolContext::Get(); DWORD error = context->init_error(); if(error != ERROR_SUCCESS) { (*os) << "Error initializing symbols (" << error << "). Dumping unresolved backtrace:\n"; for(int i=0; (i<count_)&&os->good(); ++i) { (*os) << "\t" << trace_[i] << "\n"; } } else { (*os) << "Backtrace:\n"; context->OutputTraceToStream(trace_, count_, os); } }
bool ThreadPlanStepInRange::FrameMatchesAvoidRegexp () { StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); if (avoid_regexp_to_use == NULL) avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); if (avoid_regexp_to_use != NULL) { SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); if (sc.symbol != NULL) { const char *frame_function_name = sc.GetFunctionName().GetCString(); if (frame_function_name) return avoid_regexp_to_use->Execute(frame_function_name); } } return false; }
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; }
void BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const { if (match_name_after_lookup && name) { SymbolContext sc; size_t i = start_idx; while (i < sc_list.GetSize()) { if (!sc_list.GetContextAtIndex(i, sc)) break; ConstString full_name (sc.GetFunctionName()); if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL) { sc_list.RemoveContextAtIndex(i); } else { ++i; } } } }
FuncUnwindersSP UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc) { FuncUnwindersSP no_unwind_found; Initialize(); AddressRange range; if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid()) { // Does the eh_frame unwind info has a function bounds for this addr? if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range)) { return no_unwind_found; } } FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range)); return func_unwinder_sp; }
llvm::Optional<AddressRange> UnwindTable::GetAddressRange(const Address &addr, SymbolContext &sc) { AddressRange range; // First check the symbol context if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) && range.GetBaseAddress().IsValid()) return range; // Does the eh_frame unwind info has a function bounds for this addr? if (m_eh_frame_up && m_eh_frame_up->GetAddressRange(addr, range)) return range; // Try debug_frame as well if (m_debug_frame_up && m_debug_frame_up->GetAddressRange(addr, range)) return range; return llvm::None; }
FuncUnwindersSP UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc) { FuncUnwindersSP no_unwind_found; Initialize(); // There is an UnwindTable per object file, so we can safely use file handles addr_t file_addr = addr.GetFileAddress(); iterator end = m_unwinds.end (); iterator insert_pos = end; if (!m_unwinds.empty()) { insert_pos = m_unwinds.lower_bound (file_addr); iterator pos = insert_pos; if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr)) --pos; if (pos->second->ContainsAddress (addr)) return pos->second; } AddressRange range; if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid()) { // Does the eh_frame unwind info has a function bounds for this addr? if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range)) { return no_unwind_found; } } FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range)); m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp)); // StreamFile s(stdout); // Dump (s); return func_unwinder_sp; }
bool lldb_private::InferiorCallMunmap (Process *process, addr_t addr, addr_t length) { Thread *thread = process->GetThreadList().GetSelectedThread().get(); if (thread == NULL) return false; const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; const uint32_t count = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; EvaluateExpressionOptions options; options.SetStopOthers(true); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetDebug (false); options.SetTimeoutUsec(500000); AddressRange munmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) { lldb::addr_t args[] = { addr, length }; lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, munmap_range.GetBaseAddress(), CompilerType(), args, options)); if (call_plan_sp) { StreamFile error_strm; // This plan is a utility plan, so set it to discard itself when done. call_plan_sp->SetIsMasterPlan (true); call_plan_sp->SetOkayToDiscard(true); StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, error_strm); if (result == eExpressionCompleted) { return true; } } } } } } return false; }
Searcher::CallbackReturn BreakpointResolverName::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) { SymbolContextList func_list; // SymbolContextList sym_list; uint32_t i; bool new_location; Address break_addr; assert(m_breakpoint != nullptr); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (m_class_name) { if (log) log->Warning("Class/method function specification not supported yet.\n"); return Searcher::eCallbackReturnStop; } bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; bool filter_by_language = (m_language != eLanguageTypeUnknown); const bool include_symbols = !filter_by_cu; const bool include_inlines = true; const bool append = true; switch (m_match_type) { case Breakpoint::Exact: if (context.module_sp) { for (const auto &lookup : m_lookups) { const size_t start_func_idx = func_list.GetSize(); context.module_sp->FindFunctions( lookup.GetLookupName(), nullptr, lookup.GetNameTypeMask(), include_symbols, include_inlines, append, func_list); const size_t end_func_idx = func_list.GetSize(); if (start_func_idx < end_func_idx) lookup.Prune(func_list, start_func_idx); } } break; case Breakpoint::Regexp: if (context.module_sp) { context.module_sp->FindFunctions( m_regex, !filter_by_cu, // include symbols only if we aren't filtering by CU include_inlines, append, func_list); } break; case Breakpoint::Glob: if (log) log->Warning("glob is not supported yet."); break; } // If the filter specifies a Compilation Unit, remove the ones that don't // pass at this point. if (filter_by_cu || filter_by_language) { uint32_t num_functions = func_list.GetSize(); for (size_t idx = 0; idx < num_functions; idx++) { bool remove_it = false; SymbolContext sc; func_list.GetContextAtIndex(idx, sc); if (filter_by_cu) { if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) remove_it = true; } if (filter_by_language) { LanguageType sym_language = sc.GetLanguage(); if ((Language::GetPrimaryLanguage(sym_language) != Language::GetPrimaryLanguage(m_language)) && (sym_language != eLanguageTypeUnknown)) { remove_it = true; } } if (remove_it) { func_list.RemoveContextAtIndex(idx); num_functions--; idx--; } } } // Remove any duplicates between the function list and the symbol list SymbolContext sc; if (func_list.GetSize()) { for (i = 0; i < func_list.GetSize(); i++) { if (func_list.GetContextAtIndex(i, sc)) { bool is_reexported = false; if (sc.block && sc.block->GetInlinedFunctionInfo()) { if (!sc.block->GetStartAddress(break_addr)) break_addr.Clear(); } else if (sc.function) { break_addr = sc.function->GetAddressRange().GetBaseAddress(); if (m_skip_prologue && break_addr.IsValid()) { const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); if (prologue_byte_size) break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); } } else if (sc.symbol) { if (sc.symbol->GetType() == eSymbolTypeReExported) { const Symbol *actual_symbol = sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget()); if (actual_symbol) { is_reexported = true; break_addr = actual_symbol->GetAddress(); } } else { break_addr = sc.symbol->GetAddress(); } if (m_skip_prologue && break_addr.IsValid()) { const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); if (prologue_byte_size) break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); else { const Architecture *arch = m_breakpoint->GetTarget().GetArchitecturePlugin(); if (arch) arch->AdjustBreakpointAddress(*sc.symbol, break_addr); } } } if (break_addr.IsValid()) { if (filter.AddressPasses(break_addr)) { BreakpointLocationSP bp_loc_sp( AddLocation(break_addr, &new_location)); bp_loc_sp->SetIsReExported(is_reexported); if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) { if (log) { StreamString s; bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); log->Printf("Added location: %s\n", s.GetData()); } } } } } } } return Searcher::eCallbackReturnContinue; }
bool Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, const AddressRange &disasm_range, uint32_t num_mixed_context_lines, bool show_bytes, Stream &strm ) { if (disasm_range.GetByteSize()) { Disassembler *disassembler = Disassembler::FindPlugin(arch); if (disassembler) { AddressRange range(disasm_range); Process *process = exe_ctx.process; // If we weren't passed in a section offset address range, // try and resolve it to something if (range.GetBaseAddress().IsSectionOffset() == false) { if (process && process->IsAlive()) { process->ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress()); } else if (exe_ctx.target) { exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress()); } } DataExtractor data; size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data); if (bytes_disassembled == 0) { return false; } else { // We got some things disassembled... size_t num_instructions = disassembler->GetInstructionList().GetSize(); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; if (num_mixed_context_lines) strm.IndentMore (); Address addr(range.GetBaseAddress()); // We extract the section to make sure we don't transition out // of the current section when disassembling const Section *addr_section = addr.GetSection(); Module *range_module = range.GetBaseAddress().GetModule(); for (size_t i=0; i<num_instructions; ++i) { Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i); if (inst) { addr_t file_addr = addr.GetFileAddress(); if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false) { if (range_module) range_module->ResolveFileAddress (file_addr, addr); else if (exe_ctx.target) exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr); addr_section = addr.GetSection(); } prev_sc = sc; if (addr_section) { Module *module = addr_section->GetModule(); uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol) { if (prev_sc.function || prev_sc.symbol) strm.EOL(); strm << sc.module_sp->GetFileSpec().GetFilename(); if (sc.function) strm << '`' << sc.function->GetMangled().GetName(); else if (sc.symbol) strm << '`' << sc.symbol->GetMangled().GetName(); strm << ":\n"; } if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (eSymbolContextEverything, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, process, addr); if (sc.comp_unit && sc.line_entry.IsValid()) { debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, num_mixed_context_lines ? "->" : "", &strm); } } } } else { sc.Clear(); } } if (num_mixed_context_lines) strm.IndentMore (); strm.Indent(); size_t inst_byte_size = inst->GetByteSize(); inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes); strm.EOL(); offset += inst_byte_size; addr.SetOffset (addr.GetOffset() + inst_byte_size); if (num_mixed_context_lines) strm.IndentLess (); } else { break; } } if (num_mixed_context_lines) strm.IndentLess (); } } return true; } return false; }
bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const { // If the section was nullptr, 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(" + %" PRIu64, m_offset); } else { s->Address(m_offset, addr_size); } break; case DumpStyleSectionPointerOffset: s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get())); s->Address(m_offset, addr_size); break; case DumpStyleModuleWithFileAddress: if (section_sp) { ModuleSP module_sp = section_sp->GetModule(); if (module_sp) s->Printf("%s[", module_sp->GetFileSpec().GetFilename().AsCString( "<Unknown>")); else s->Printf("%s[", "<Unknown>"); } LLVM_FALLTHROUGH; 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); /* * MIPS: * Display address in compressed form for MIPS16 or microMIPS * if the address belongs to eAddressClassCodeAlternateISA. */ if (target) { const llvm::Triple::ArchType llvm_arch = target->GetArchitecture().GetMachine(); if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el) load_addr = GetCallableLoadAddress(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: case DumpStyleResolvedDescriptionNoFunctionArguments: case DumpStyleNoFunctionName: 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) { SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); if (sym_vendor) { Symtab *symtab = sym_vendor->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->GetAddressRef().GetFileAddress(); if (delta) s->Printf(" + %" PRIu64, 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 != nullptr || func_sc.symbol != nullptr) { 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, true, true); 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 != nullptr || pointer_sc.symbol != nullptr) { s->PutCString(": "); pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false, true, true); } } } } 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; const bool show_function_arguments = (style != DumpStyleResolvedDescriptionNoFunctionArguments); const bool show_function_name = (style != DumpStyleNoFunctionName); if (sc.function == nullptr && sc.symbol != nullptr) { // If we have just a symbol make sure it is in the right section if (sc.symbol->ValueIsAddress()) { if (sc.symbol->GetAddressRef().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, show_function_arguments, show_function_name); } 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 | eSymbolContextVariable, 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->GetAddressRef().GetSection() != GetSection()) sc.symbol = nullptr; } 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 *) { return true; }, &variable_list); const size_t num_variables = variable_list.GetSize(); for (size_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.8" PRIx64 "}, name = \"%s\"", var->GetID(), var->GetName().GetCString()); Type *type = var->GetType(); if (type) s->Printf(", type = \"%s\"", type->GetName().GetCString()); else s->PutCString(", type = <unknown>"); s->PutCString(", location = "); 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; }
bool DoExecute (Args& command, CommandReturnObject &result) { const int argc = command.GetArgumentCount(); if (argc != 0) { result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName()); result.SetStatus (eReturnStatusFailed); return false; } ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); Target *target = exe_ctx.GetTargetPtr(); if (target == NULL) target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) { result.AppendError ("invalid target, create a debug target using the 'target create' command"); result.SetStatus (eReturnStatusFailed); return false; } SymbolContextList sc_list; if (!m_options.symbol_name.empty()) { // Displaying the source for a symbol: ConstString name(m_options.symbol_name.c_str()); bool include_symbols = false; bool include_inlines = true; bool append = true; size_t num_matches = 0; if (m_options.modules.size() > 0) { ModuleList matching_modules; for (unsigned i = 0, e = m_options.modules.size(); i != e; i++) { FileSpec module_file_spec(m_options.modules[i].c_str(), false); if (module_file_spec) { ModuleSpec module_spec (module_file_spec); matching_modules.Clear(); target->GetImages().FindModules (module_spec, matching_modules); num_matches += matching_modules.FindFunctions (name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); } } } else { num_matches = target->GetImages().FindFunctions (name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); } SymbolContext sc; if (num_matches == 0) { result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str()); result.SetStatus (eReturnStatusFailed); return false; } sc_list.GetContextAtIndex (0, sc); FileSpec start_file; uint32_t start_line; uint32_t end_line; FileSpec end_file; if (sc.function != NULL) { sc.function->GetStartLineSourceInfo (start_file, start_line); if (start_line == 0) { result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", m_options.symbol_name.c_str()); result.SetStatus (eReturnStatusFailed); return false; } sc.function->GetEndLineSourceInfo (end_file, end_line); } else { result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str()); result.SetStatus (eReturnStatusFailed); return false; } if (num_matches > 1) { // This could either be because there are multiple functions of this name, in which case // we'll have to specify this further... Or it could be because there are multiple inlined instances // of one function. So run through the matches and if they all have the same file & line then we can just // list one. bool found_multiple = false; for (size_t i = 1; i < num_matches; i++) { SymbolContext scratch_sc; sc_list.GetContextAtIndex (i, scratch_sc); if (scratch_sc.function != NULL) { FileSpec scratch_file; uint32_t scratch_line; scratch_sc.function->GetStartLineSourceInfo (scratch_file, scratch_line); if (scratch_file != start_file || scratch_line != start_line) { found_multiple = true; break; } } } if (found_multiple) { StreamString s; for (size_t i = 0; i < num_matches; i++) { SymbolContext scratch_sc; sc_list.GetContextAtIndex (i, scratch_sc); if (scratch_sc.function != NULL) { s.Printf("\n%lu: ", i); scratch_sc.function->Dump (&s, true); } } result.AppendErrorWithFormat("Multiple functions found matching: %s: \n%s\n", m_options.symbol_name.c_str(), s.GetData()); result.SetStatus (eReturnStatusFailed); return false; } } // This is a little hacky, but the first line table entry for a function points to the "{" that // starts the function block. It would be nice to actually get the function // declaration in there too. So back up a bit, but not further than what you're going to display. size_t lines_to_back_up = m_options.num_lines >= 10 ? 5 : m_options.num_lines/2; uint32_t line_no; if (start_line <= lines_to_back_up) line_no = 1; else line_no = start_line - lines_to_back_up; // For fun, if the function is shorter than the number of lines we're supposed to display, // only display the function... if (end_line != 0) { if (m_options.num_lines > end_line - line_no) m_options.num_lines = end_line - line_no; } char path_buf[PATH_MAX]; start_file.GetPath(path_buf, sizeof(path_buf)); if (m_options.show_bp_locs) { const bool show_inlines = true; m_breakpoint_locations.Reset (start_file, 0, show_inlines); SearchFilter target_search_filter (exe_ctx.GetTargetSP()); target_search_filter.Search (m_breakpoint_locations); } else m_breakpoint_locations.Clear(); result.AppendMessageWithFormat("File: %s.\n", path_buf); target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file, line_no, 0, m_options.num_lines, "", &result.GetOutputStream(), GetBreakpointLocations ()); result.SetStatus (eReturnStatusSuccessFinishResult); return true; } else if (m_options.address != LLDB_INVALID_ADDRESS) { SymbolContext sc; Address so_addr; StreamString error_strm; if (target->GetSectionLoadList().IsEmpty()) { // The target isn't loaded yet, we need to lookup the file address // in all modules const ModuleList &module_list = target->GetImages(); const uint32_t num_modules = module_list.GetSize(); for (uint32_t i=0; i<num_modules; ++i) { ModuleSP module_sp (module_list.GetModuleAtIndex(i)); if (module_sp && module_sp->ResolveFileAddress(m_options.address, so_addr)) { sc.Clear(); if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry) sc_list.Append(sc); } } if (sc_list.GetSize() == 0) { result.AppendErrorWithFormat("no modules have source information for file address 0x%" PRIx64 ".\n", m_options.address); result.SetStatus (eReturnStatusFailed); return false; } } else { // The target has some things loaded, resolve this address to a // compile unit + file + line and display if (target->GetSectionLoadList().ResolveLoadAddress (m_options.address, so_addr)) { ModuleSP module_sp (so_addr.GetModule()); if (module_sp) { sc.Clear(); if (module_sp->ResolveSymbolContextForAddress (so_addr, eSymbolContextEverything, sc) & eSymbolContextLineEntry) { sc_list.Append(sc); } else { so_addr.Dump(&error_strm, NULL, Address::DumpStyleModuleWithFileAddress); result.AppendErrorWithFormat("address resolves to %s, but there is no line table information available for this address.\n", error_strm.GetData()); result.SetStatus (eReturnStatusFailed); return false; } } } if (sc_list.GetSize() == 0) { result.AppendErrorWithFormat("no modules contain load address 0x%" PRIx64 ".\n", m_options.address); result.SetStatus (eReturnStatusFailed); return false; } } uint32_t num_matches = sc_list.GetSize(); for (uint32_t i=0; i<num_matches; ++i) { sc_list.GetContextAtIndex(i, sc); if (sc.comp_unit) { if (m_options.show_bp_locs) { m_breakpoint_locations.Clear(); const bool show_inlines = true; m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); SearchFilter target_search_filter (target->shared_from_this()); target_search_filter.Search (m_breakpoint_locations); } bool show_fullpaths = true; bool show_module = true; bool show_inlined_frames = true; sc.DumpStopContext(&result.GetOutputStream(), exe_ctx.GetBestExecutionContextScope(), sc.line_entry.range.GetBaseAddress(), show_fullpaths, show_module, show_inlined_frames); result.GetOutputStream().EOL(); size_t lines_to_back_up = m_options.num_lines >= 10 ? 5 : m_options.num_lines/2; target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit, sc.line_entry.line, lines_to_back_up, m_options.num_lines - lines_to_back_up, "->", &result.GetOutputStream(), GetBreakpointLocations ()); result.SetStatus (eReturnStatusSuccessFinishResult); } } } else if (m_options.file_name.empty()) { // Last valid source manager context, or the current frame if no // valid last context in source manager. // One little trick here, if you type the exact same list command twice in a row, it is // more likely because you typed it once, then typed it again if (m_options.start_line == 0) { if (target->GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream(), GetBreakpointLocations ())) { result.SetStatus (eReturnStatusSuccessFinishResult); } } else { if (m_options.show_bp_locs) { SourceManager::FileSP last_file_sp (target->GetSourceManager().GetLastFile ()); if (last_file_sp) { const bool show_inlines = true; m_breakpoint_locations.Reset (last_file_sp->GetFileSpec(), 0, show_inlines); SearchFilter target_search_filter (target->shared_from_this()); target_search_filter.Search (m_breakpoint_locations); } } else m_breakpoint_locations.Clear(); if (target->GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile( m_options.start_line, // Line to display 0, // Lines before line to display m_options.num_lines, // Lines after line to display "", // Don't mark "line" &result.GetOutputStream(), GetBreakpointLocations ())) { result.SetStatus (eReturnStatusSuccessFinishResult); } } } else { const char *filename = m_options.file_name.c_str(); bool check_inlines = false; SymbolContextList sc_list; size_t num_matches = 0; if (m_options.modules.size() > 0) { ModuleList matching_modules; for (unsigned i = 0, e = m_options.modules.size(); i != e; i++) { FileSpec module_file_spec(m_options.modules[i].c_str(), false); if (module_file_spec) { ModuleSpec module_spec (module_file_spec); matching_modules.Clear(); target->GetImages().FindModules (module_spec, matching_modules); num_matches += matching_modules.ResolveSymbolContextForFilePath (filename, 0, check_inlines, eSymbolContextModule | eSymbolContextCompUnit, sc_list); } } } else { num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename, 0, check_inlines, eSymbolContextModule | eSymbolContextCompUnit, sc_list); } if (num_matches == 0) { result.AppendErrorWithFormat("Could not find source file \"%s\".\n", m_options.file_name.c_str()); result.SetStatus (eReturnStatusFailed); return false; } if (num_matches > 1) { SymbolContext sc; bool got_multiple = false; FileSpec *test_cu_spec = NULL; for (unsigned i = 0; i < num_matches; i++) { sc_list.GetContextAtIndex(i, sc); if (sc.comp_unit) { if (test_cu_spec) { if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit)) got_multiple = true; break; } else test_cu_spec = sc.comp_unit; } } if (got_multiple) { result.AppendErrorWithFormat("Multiple source files found matching: \"%s.\"\n", m_options.file_name.c_str()); result.SetStatus (eReturnStatusFailed); return false; } } SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { if (sc.comp_unit) { if (m_options.show_bp_locs) { const bool show_inlines = true; m_breakpoint_locations.Reset (*sc.comp_unit, 0, show_inlines); SearchFilter target_search_filter (target->shared_from_this()); target_search_filter.Search (m_breakpoint_locations); } else m_breakpoint_locations.Clear(); target->GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit, m_options.start_line, 0, m_options.num_lines, "", &result.GetOutputStream(), GetBreakpointLocations ()); result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n", m_options.file_name.c_str()); result.SetStatus (eReturnStatusFailed); return false; } } } return result.Succeeded(); }
void BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) { SymbolContext sc; // If the description level is "initial" then the breakpoint is printing out our initial state, // and we should let it decide how it wants to print our label. if (level != eDescriptionLevelInitial) { s->Indent(); BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); } if (level == lldb::eDescriptionLevelBrief) return; if (level != eDescriptionLevelInitial) s->PutCString(": "); if (level == lldb::eDescriptionLevelVerbose) s->IndentMore(); if (m_address.IsSectionOffset()) { m_address.CalculateSymbolContext(&sc); if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial) { if (IsReExported()) s->PutCString ("re-exported target = "); else s->PutCString("where = "); sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false, true, true); } else { if (sc.module_sp) { s->EOL(); s->Indent("module = "); sc.module_sp->GetFileSpec().Dump (s); } if (sc.comp_unit != NULL) { s->EOL(); s->Indent("compile unit = "); static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); if (sc.function != NULL) { s->EOL(); s->Indent("function = "); s->PutCString (sc.function->GetName().AsCString("<unknown>")); } if (sc.line_entry.line > 0) { s->EOL(); s->Indent("location = "); sc.line_entry.DumpStopContext (s, true); } } else { // If we don't have a comp unit, see if we have a symbol we can print. if (sc.symbol) { s->EOL(); if (IsReExported()) s->Indent ("re-exported target = "); else s->Indent("symbol = "); s->PutCString(sc.symbol->GetName().AsCString("<unknown>")); } } } } if (level == lldb::eDescriptionLevelVerbose) { s->EOL(); s->Indent(); } if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)) s->Printf (", "); s->Printf ("address = "); ExecutionContextScope *exe_scope = NULL; Target *target = &m_owner.GetTarget(); if (target) exe_scope = target->GetProcessSP().get(); if (exe_scope == NULL) exe_scope = target; if (level == eDescriptionLevelInitial) m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); else m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); if (IsIndirect() && m_bp_site_sp) { Address resolved_address; resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target); Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol(); if (resolved_symbol) { if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial) s->Printf (", "); else if (level == lldb::eDescriptionLevelVerbose) { s->EOL(); s->Indent(); } s->Printf ("indirect target = %s", resolved_symbol->GetName().GetCString()); } } if (level == lldb::eDescriptionLevelVerbose) { s->EOL(); s->Indent(); s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); s->Indent(); s->Printf ("hit count = %-4u\n", GetHitCount()); if (m_options_ap.get()) { s->Indent(); m_options_ap->GetDescription (s, level); s->EOL(); } s->IndentLess(); } else if (level != eDescriptionLevelInitial) { s->Printf(", %sresolved, hit count = %u ", (IsResolved() ? "" : "un"), GetHitCount()); if (m_options_ap.get()) { m_options_ap->GetDescription (s, level); } } }
bool Disassembler::PrintInstructions ( Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { // We got some things disassembled... size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); if (num_instructions > 0 && num_instructions < num_instructions_found) num_instructions_found = num_instructions; const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; const Address *pc_addr_ptr = NULL; ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); Frame *frame = exe_ctx.GetFramePtr(); TargetSP target_sp (exe_ctx.GetTargetSP()); SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); if (frame) pc_addr_ptr = &frame->GetFrameCodeAddress(); const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; for (size_t i=0; i<num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; prev_sc = sc; ModuleSP module_sp (addr.GetModule()); if (module_sp) { uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (num_mixed_context_lines) { if (!sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false); strm.EOL(); if (sc.comp_unit && sc.line_entry.IsValid()) { source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), &strm); } } } } else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol)) { if (prev_sc.function || prev_sc.symbol) strm.EOL(); bool show_fullpaths = false; bool show_module = true; bool show_inlined_frames = true; sc.DumpStopContext (&strm, exe_scope, addr, show_fullpaths, show_module, show_inlined_frames); strm << ":\n"; } } else { sc.Clear(true); } } if ((options & eOptionMarkPCAddress) && pc_addr_ptr) { strm.PutCString(inst_is_at_pc ? "-> " : " "); } const bool show_bytes = (options & eOptionShowBytes) != 0; inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx); strm.EOL(); } else { break; } } return true; }
bool ThreadPlanStepInRange::FrameMatchesAvoidCriteria () { StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); // Check the library list first, as that's cheapest: bool libraries_say_avoid = false; FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid()); size_t num_libraries = libraries_to_avoid.GetSize(); if (num_libraries > 0) { SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule)); FileSpec frame_library(sc.module_sp->GetFileSpec()); if (frame_library) { for (size_t i = 0; i < num_libraries; i++) { const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i)); if (FileSpec::Equal (file_spec, frame_library, false)) { libraries_say_avoid = true; break; } } } } if (libraries_say_avoid) return true; const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); if (avoid_regexp_to_use == NULL) avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); if (avoid_regexp_to_use != NULL) { SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); if (sc.symbol != NULL) { const char *frame_function_name = sc.GetFunctionName().GetCString(); if (frame_function_name) { size_t num_matches = 0; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); if (log) num_matches = 1; RegularExpression::Match regex_match(num_matches); bool return_value = avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); if (return_value) { if (log) { std::string match; regex_match.GetMatchAtIndex(frame_function_name,0, match); log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".", frame_function_name, avoid_regexp_to_use->GetText(), match.c_str()); } } return return_value; } } } return false; }
bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized () { if (m_lib_backtrace_recording_info.queue_info_version != 0) return true; addr_t queue_info_version_address = LLDB_INVALID_ADDRESS; addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS; addr_t item_info_version_address = LLDB_INVALID_ADDRESS; addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS; Target &target = m_process->GetTarget(); static ConstString introspection_dispatch_queue_info_version ("__introspection_dispatch_queue_info_version"); SymbolContextList sc_list; if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) > 0) { SymbolContext sc; sc_list.GetContextAtIndex (0, sc); AddressRange addr_range; sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range); queue_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target); } sc_list.Clear(); static ConstString introspection_dispatch_queue_info_data_offset ("__introspection_dispatch_queue_info_data_offset"); if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_data_offset, eSymbolTypeData, sc_list) > 0) { SymbolContext sc; sc_list.GetContextAtIndex (0, sc); AddressRange addr_range; sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range); queue_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target); } sc_list.Clear(); static ConstString introspection_dispatch_item_info_version ("__introspection_dispatch_item_info_version"); if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > 0) { SymbolContext sc; sc_list.GetContextAtIndex (0, sc); AddressRange addr_range; sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range); item_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target); } sc_list.Clear(); static ConstString introspection_dispatch_item_info_data_offset ("__introspection_dispatch_item_info_data_offset"); if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list) > 0) { SymbolContext sc; sc_list.GetContextAtIndex (0, sc); AddressRange addr_range; sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range); item_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target); } if (queue_info_version_address != LLDB_INVALID_ADDRESS && queue_info_data_offset_address != LLDB_INVALID_ADDRESS && item_info_version_address != LLDB_INVALID_ADDRESS && item_info_data_offset_address != LLDB_INVALID_ADDRESS) { Error error; m_lib_backtrace_recording_info.queue_info_version = m_process->ReadUnsignedIntegerFromMemory (queue_info_version_address, 2, 0, error); if (error.Success()) { m_lib_backtrace_recording_info.queue_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (queue_info_data_offset_address, 2, 0, error); if (error.Success()) { m_lib_backtrace_recording_info.item_info_version = m_process->ReadUnsignedIntegerFromMemory (item_info_version_address, 2, 0, error); if (error.Success()) { m_lib_backtrace_recording_info.item_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (item_info_data_offset_address, 2, 0, error); if (!error.Success()) { m_lib_backtrace_recording_info.queue_info_version = 0; } } else { m_lib_backtrace_recording_info.queue_info_version = 0; } } else { m_lib_backtrace_recording_info.queue_info_version = 0; } } } return m_lib_backtrace_recording_info.queue_info_version != 0; }
bool CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) { result.AppendError ("invalid target, create a debug target using the 'target create' command"); result.SetStatus (eReturnStatusFailed); return false; } if (!m_options.arch.IsValid()) m_options.arch = target->GetArchitecture(); if (!m_options.arch.IsValid()) { result.AppendError ("use the --arch option or set the target architecure to disassemble"); result.SetStatus (eReturnStatusFailed); return false; } const char *plugin_name = m_options.GetPluginName (); const char *flavor_string = m_options.GetFlavorString(); DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); if (!disassembler) { if (plugin_name) { result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", plugin_name, m_options.arch.GetArchitectureName()); } else result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", m_options.arch.GetArchitectureName()); result.SetStatus (eReturnStatusFailed); return false; } else if (flavor_string != NULL && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string)) result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string); result.SetStatus (eReturnStatusSuccessFinishResult); if (command.GetArgumentCount() != 0) { result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n"); GetOptions()->GenerateOptionUsage (result.GetErrorStream(), this); result.SetStatus (eReturnStatusFailed); return false; } if (m_options.show_mixed && m_options.num_lines_context == 0) m_options.num_lines_context = 1; // Always show the PC in the disassembly uint32_t options = Disassembler::eOptionMarkPCAddress; // Mark the source line for the current PC only if we are doing mixed source and assembly if (m_options.show_mixed) options |= Disassembler::eOptionMarkPCSourceLine; if (m_options.show_bytes) options |= Disassembler::eOptionShowBytes; if (m_options.raw) options |= Disassembler::eOptionRawOuput; if (!m_options.func_name.empty()) { ConstString name(m_options.func_name.c_str()); if (Disassembler::Disassemble (m_interpreter.GetDebugger(), m_options.arch, plugin_name, flavor_string, m_exe_ctx, name, NULL, // Module * m_options.num_instructions, m_options.show_mixed ? m_options.num_lines_context : 0, options, result.GetOutputStream())) { result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString()); result.SetStatus (eReturnStatusFailed); } } else { std::vector<AddressRange> ranges; AddressRange range; StackFrame *frame = m_exe_ctx.GetFramePtr(); if (m_options.frame_line) { if (frame == NULL) { result.AppendError ("Cannot disassemble around the current line without a selected frame.\n"); result.SetStatus (eReturnStatusFailed); return false; } LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); if (pc_line_entry.IsValid()) { range = pc_line_entry.range; } else { m_options.at_pc = true; // No line entry, so just disassemble around the current pc m_options.show_mixed = false; } } else if (m_options.current_function) { if (frame == NULL) { result.AppendError ("Cannot disassemble around the current function without a selected frame.\n"); result.SetStatus (eReturnStatusFailed); return false; } Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; if (symbol) { range.GetBaseAddress() = symbol->GetAddress(); range.SetByteSize(symbol->GetByteSize()); } } // Did the "m_options.frame_line" find a valid range already? If so // skip the rest... if (range.GetByteSize() == 0) { if (m_options.at_pc) { if (frame == NULL) { result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n"); result.SetStatus (eReturnStatusFailed); return false; } range.GetBaseAddress() = frame->GetFrameCodeAddress(); if (m_options.num_instructions == 0) { // Disassembling at the PC always disassembles some number of instructions (not the whole function). m_options.num_instructions = DEFAULT_DISASM_NUM_INS; } ranges.push_back(range); } else { range.GetBaseAddress().SetOffset (m_options.start_addr); if (range.GetBaseAddress().IsValid()) { if (m_options.end_addr != LLDB_INVALID_ADDRESS) { if (m_options.end_addr <= m_options.start_addr) { result.AppendErrorWithFormat ("End address before start address.\n"); result.SetStatus (eReturnStatusFailed); return false; } range.SetByteSize (m_options.end_addr - m_options.start_addr); } ranges.push_back(range); } else { if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS && target) { if (!target->GetSectionLoadList().IsEmpty()) { bool failed = false; Address symbol_containing_address; if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address)) { ModuleSP module_sp (symbol_containing_address.GetModule()); SymbolContext sc; bool resolve_tail_call_address = true; // PC can be one past the address range of the function. module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc, resolve_tail_call_address); if (sc.function || sc.symbol) { sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); } else { failed = true; } } else { failed = true; } if (failed) { result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr); result.SetStatus (eReturnStatusFailed); return false; } ranges.push_back(range); } else { for (lldb::ModuleSP module_sp : target->GetImages().Modules()) { lldb::addr_t file_addr = m_options.symbol_containing_addr; Address file_address; if (module_sp->ResolveFileAddress(file_addr, file_address)) { SymbolContext sc; bool resolve_tail_call_address = true; // PC can be one past the address range of the function. module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address); if (sc.function || sc.symbol) { sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); ranges.push_back(range); } } } } } } } } else ranges.push_back(range); if (m_options.num_instructions != 0) { if (ranges.size() == 0) { // The default action is to disassemble the current frame function. if (frame) { SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); if (sc.function) range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress(); else if (sc.symbol && sc.symbol->ValueIsAddress()) range.GetBaseAddress() = sc.symbol->GetAddress(); else range.GetBaseAddress() = frame->GetFrameCodeAddress(); } if (!range.GetBaseAddress().IsValid()) { result.AppendError ("invalid frame"); result.SetStatus (eReturnStatusFailed); return false; } } bool print_sc_header = ranges.size() > 1; for (AddressRange cur_range : ranges) { if (Disassembler::Disassemble (m_interpreter.GetDebugger(), m_options.arch, plugin_name, flavor_string, m_exe_ctx, cur_range.GetBaseAddress(), m_options.num_instructions, m_options.show_mixed ? m_options.num_lines_context : 0, options, result.GetOutputStream())) { result.SetStatus (eReturnStatusSuccessFinishResult); } else { if (m_options.start_addr != LLDB_INVALID_ADDRESS) result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr); result.SetStatus (eReturnStatusFailed); } } if (print_sc_header) result.AppendMessage("\n"); } else { if (ranges.size() == 0) { // The default action is to disassemble the current frame function. if (frame) { SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); if (sc.function) range = sc.function->GetAddressRange(); else if (sc.symbol && sc.symbol->ValueIsAddress()) { range.GetBaseAddress() = sc.symbol->GetAddress(); range.SetByteSize (sc.symbol->GetByteSize()); } else range.GetBaseAddress() = frame->GetFrameCodeAddress(); } else { result.AppendError ("invalid frame"); result.SetStatus (eReturnStatusFailed); return false; } ranges.push_back(range); } bool print_sc_header = ranges.size() > 1; for (AddressRange cur_range : ranges) { if (cur_range.GetByteSize() == 0) cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); if (Disassembler::Disassemble (m_interpreter.GetDebugger(), m_options.arch, plugin_name, flavor_string, m_exe_ctx, cur_range, m_options.num_instructions, m_options.show_mixed ? m_options.num_lines_context : 0, options, result.GetOutputStream())) { result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); result.SetStatus (eReturnStatusFailed); } if (print_sc_header) result.AppendMessage("\n"); } } } return result.Succeeded(); }
size_t ModuleList::FindFunctions (const ConstString &name, uint32_t name_type_mask, bool include_symbols, bool include_inlines, bool append, SymbolContextList &sc_list) const { if (!append) sc_list.Clear(); const size_t old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeAuto) { ConstString lookup_name; uint32_t lookup_name_type_mask = 0; bool match_name_after_lookup = false; Module::PrepareForFunctionNameLookup (name, name_type_mask, lookup_name, lookup_name_type_mask, match_name_after_lookup); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions (lookup_name, NULL, lookup_name_type_mask, include_symbols, include_inlines, true, sc_list); } if (match_name_after_lookup) { SymbolContext sc; size_t i = old_size; while (i<sc_list.GetSize()) { if (sc_list.GetContextAtIndex(i, sc)) { const char *func_name = sc.GetFunctionName().GetCString(); if (func_name && strstr (func_name, name.GetCString()) == NULL) { // Remove the current context sc_list.RemoveContextAtIndex(i); // Don't increment i and continue in the loop continue; } } ++i; } } } else { Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list); } } return sc_list.GetSize() - old_size; }
bool Disassembler::PrintInstructions ( Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { // We got some things disassembled... size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); if (num_instructions > 0 && num_instructions < num_instructions_found) num_instructions_found = num_instructions; const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; const Address *pc_addr_ptr = NULL; StackFrame *frame = exe_ctx.GetFramePtr(); TargetSP target_sp (exe_ctx.GetTargetSP()); SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); if (frame) { pc_addr_ptr = &frame->GetFrameCodeAddress(); } const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; const FormatEntity::Entry *disassembly_format = NULL; FormatEntity::Entry format; if (exe_ctx.HasTargetScope()) { disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat (); } else { FormatEntity::Parse("${addr}: ", format); disassembly_format = &format; } // First pass: step through the list of instructions, // find how long the initial addresses strings are, insert padding // in the second pass so the opcodes all line up nicely. size_t address_text_size = 0; for (size_t i = 0; i < num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); ModuleSP module_sp (addr.GetModule()); if (module_sp) { const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol; uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); if (resolved_mask) { StreamString strmstr; Debugger::FormatDisassemblerAddress (disassembly_format, &sc, NULL, &exe_ctx, &addr, strmstr); size_t cur_line = strmstr.GetSizeOfLastLine(); if (cur_line > address_text_size) address_text_size = cur_line; } sc.Clear(false); } } } for (size_t i = 0; i < num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; prev_sc = sc; ModuleSP module_sp (addr.GetModule()); if (module_sp) { uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (num_mixed_context_lines) { if (!sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true); strm.EOL(); if (sc.comp_unit && sc.line_entry.IsValid()) { source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), &strm); } } } } } else { sc.Clear(true); } } const bool show_bytes = (options & eOptionShowBytes) != 0; inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL, address_text_size); strm.EOL(); } else { break; } } return true; }
void BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) { SymbolContext sc; s->Indent(); BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); if (level == lldb::eDescriptionLevelBrief) return; s->PutCString(": "); if (level == lldb::eDescriptionLevelVerbose) s->IndentMore(); if (m_address.IsSectionOffset()) { m_address.CalculateSymbolContext(&sc); if (level == lldb::eDescriptionLevelFull) { s->PutCString("where = "); sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false); } else { if (sc.module_sp) { s->EOL(); s->Indent("module = "); sc.module_sp->GetFileSpec().Dump (s); } if (sc.comp_unit != NULL) { s->EOL(); s->Indent("compile unit = "); static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s); if (sc.function != NULL) { s->EOL(); s->Indent("function = "); s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>")); } if (sc.line_entry.line > 0) { s->EOL(); s->Indent("location = "); sc.line_entry.DumpStopContext (s, true); } } else { // If we don't have a comp unit, see if we have a symbol we can print. if (sc.symbol) { s->EOL(); s->Indent("symbol = "); s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>")); } } } } if (level == lldb::eDescriptionLevelVerbose) { s->EOL(); s->Indent(); } s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : ""); ExecutionContextScope *exe_scope = NULL; Target *target = &m_owner.GetTarget(); if (target) exe_scope = target->GetProcessSP().get(); if (exe_scope == NULL) exe_scope = target; m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); if (level == lldb::eDescriptionLevelVerbose) { s->EOL(); s->Indent(); s->Printf("resolved = %s\n", IsResolved() ? "true" : "false"); s->Indent(); s->Printf ("hit count = %-4u\n", GetHitCount()); if (m_options_ap.get()) { s->Indent(); m_options_ap->GetDescription (s, level); s->EOL(); } s->IndentLess(); } else { s->Printf(", %sresolved, hit count = %u ", (IsResolved() ? "" : "un"), GetHitCount()); if (m_options_ap.get()) { m_options_ap->GetDescription (s, level); } } }
bool SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc, SymbolContext &next_frame_sc, Address &next_frame_pc) const { next_frame_sc.Clear(false); next_frame_pc.Clear(); if (block) { //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress(); // In order to get the parent of an inlined function we first need to // see if we are in an inlined block as "this->block" could be an // inlined block, or a parent of "block" could be. So lets check if // this block or one of this blocks parents is an inlined function. Block *curr_inlined_block = block->GetContainingInlinedBlock(); if (curr_inlined_block) { // "this->block" is contained in an inline function block, so to // get the scope above the inlined block, we get the parent of the // inlined block itself Block *next_frame_block = curr_inlined_block->GetParent(); // Now calculate the symbol context of the containing block next_frame_block->CalculateSymbolContext (&next_frame_sc); // If we get here we weren't able to find the return line entry using the nesting of the blocks and // the line table. So just use the call site info from our inlined block. AddressRange range; if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range)) { // To see there this new frame block it, we need to look at the // call site information from const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo(); next_frame_pc = range.GetBaseAddress(); next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc; next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile(); next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine(); next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn(); return true; } else { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); if (log) { log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64, curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); } #ifdef LLDB_CONFIGURATION_DEBUG else { ObjectFile *objfile = NULL; if (module_sp) { SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); if (symbol_vendor) { SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); if (symbol_file) objfile = symbol_file->GetObjectFile(); } } if (objfile) { Host::SystemLog (Host::eSystemLogWarning, "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n", curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress(), objfile->GetFileSpec().GetPath().c_str()); } else { Host::SystemLog (Host::eSystemLogWarning, "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n", curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); } } #endif } } } return false; }
bool lldb_private::InferiorCallMmap (Process *process, addr_t &allocated_addr, addr_t addr, addr_t length, unsigned prot, unsigned flags, addr_t fd, addr_t offset) { Thread *thread = process->GetThreadList().GetSelectedThread().get(); if (thread == NULL) return false; const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; const uint32_t count = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; EvaluateExpressionOptions options; options.SetStopOthers(true); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetDebug (false); options.SetTimeoutUsec(500000); addr_t prot_arg, flags_arg = 0; if (prot == eMmapProtNone) prot_arg = PROT_NONE; else { prot_arg = 0; if (prot & eMmapProtExec) prot_arg |= PROT_EXEC; if (prot & eMmapProtRead) prot_arg |= PROT_READ; if (prot & eMmapProtWrite) prot_arg |= PROT_WRITE; } const ArchSpec arch = process->GetTarget().GetArchitecture(); flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,flags); AddressRange mmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) { ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, mmap_range.GetBaseAddress(), clang_void_ptr_type, args, options)); if (call_plan_sp) { StreamFile error_strm; // This plan is a utility plan, so set it to discard itself when done. call_plan_sp->SetIsMasterPlan (true); call_plan_sp->SetOkayToDiscard(true); StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, error_strm); if (result == eExpressionCompleted) { allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (process->GetAddressByteSize() == 4) { if (allocated_addr == UINT32_MAX) return false; } else if (process->GetAddressByteSize() == 8) { if (allocated_addr == UINT64_MAX) return false; } return true; } } } } } } return false; }