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; }
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; }
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; }
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 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(); }
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; }
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; }
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; }
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 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; }
void SystemRuntimeMacOSX::ParseLdiHeaders () { if (m_ldi_header.initialized) return; static ConstString ldi_header_symbol ("ldi_infos"); SymbolContextList sc_list; if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (ldi_header_symbol, eSymbolTypeData, sc_list) > 0) { SymbolContext sc; sc_list.GetContextAtIndex (0, sc); AddressRange addr_range; sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range); Error error; Address ldi_header_addr = addr_range.GetBaseAddress(); uint8_t version_buf[6]; // version, ldi_header_size, initialized fields DataExtractor data (version_buf, sizeof(version_buf), m_process->GetByteOrder(), m_process->GetAddressByteSize()); const size_t count = sizeof (version_buf); const bool prefer_file_cache = false; if (m_process->GetTarget().ReadMemory (ldi_header_addr, prefer_file_cache, version_buf, count, error) == sizeof (version_buf)) { int version, initialized, ldi_header_size; offset_t offset = 0; version = data.GetU16(&offset); ldi_header_size = data.GetU16(&offset); initialized = data.GetU16(&offset); if (initialized) { DataBufferHeap ldi_header (ldi_header_size, 0); DataExtractor ldi_extractor (ldi_header.GetBytes(), ldi_header.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize()); if (m_process->GetTarget().ReadMemory (ldi_header_addr, prefer_file_cache, ldi_header.GetBytes(), ldi_header.GetByteSize(), error) == ldi_header.GetByteSize()) { offset = 0; m_ldi_header.version = ldi_extractor.GetU16(&offset); m_ldi_header.ldi_header_size = ldi_extractor.GetU16(&offset); m_ldi_header.initialized = ldi_extractor.GetU16(&offset); m_ldi_header.queue_size = ldi_extractor.GetU16(&offset); m_ldi_header.item_size = ldi_extractor.GetU16(&offset); // 6 bytes of padding here offset += 6; m_ldi_header.queues_head_ptr_address = ldi_extractor.GetU64(&offset); m_ldi_header.items_head_ptr_address = ldi_extractor.GetU64(&offset); m_ldi_header.queue_offsets.next = ldi_extractor.GetU16(&offset); m_ldi_header.queue_offsets.prev = ldi_extractor.GetU16(&offset); m_ldi_header.queue_offsets.queue_id = ldi_extractor.GetU16(&offset); m_ldi_header.queue_offsets.current_item_ptr = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.next = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.prev = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.type = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.identifier = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.stop_id = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.backtrace_length = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.backtrace_ptr = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.thread_name_ptr = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.queue_name_ptr = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.unique_thread_id = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.pthread_id = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.enqueueing_thread_dispatch_queue_t = ldi_extractor.GetU16(&offset); m_ldi_header.item_offsets.enqueueing_thread_dispatch_block_ptr = ldi_extractor.GetU16(&offset); if (ldi_header.GetByteSize () > offset) { m_ldi_header.item_offsets.queue_id_from_thread_info = ldi_extractor.GetU16(&offset); } else { m_ldi_header.item_offsets.queue_id_from_thread_info = 0xffff; } } } } } }
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; const bool stop_other_threads = true; const bool unwind_on_error = true; const bool ignore_breakpoints = true; const bool try_all_threads = true; const uint32_t timeout_usec = 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; } if (flags & eMmapFlagsPrivate) flags_arg |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_arg |= MAP_ANON; AddressRange mmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) { ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); ThreadPlanCallFunction *call_function_thread_plan = new ThreadPlanCallFunction (*thread, mmap_range.GetBaseAddress(), clang_void_ptr_type, stop_other_threads, unwind_on_error, ignore_breakpoints, &addr, &length, &prot_arg, &flags_arg, &fd, &offset); lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); 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); Frame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); ExecutionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, stop_other_threads, try_all_threads, unwind_on_error, ignore_breakpoints, timeout_usec, error_strm); if (result == eExecutionCompleted) { 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; }
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; const bool stop_other_threads = true; const bool unwind_on_error = true; const bool ignore_breakpoints = true; const bool try_all_threads = true; const uint32_t timeout_usec = 500000; AddressRange munmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) { lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, munmap_range.GetBaseAddress(), ClangASTType(), stop_other_threads, unwind_on_error, ignore_breakpoints, &addr, &length)); 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); Frame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); ExecutionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, stop_other_threads, try_all_threads, unwind_on_error, ignore_breakpoints, timeout_usec, error_strm); if (result == eExecutionCompleted) { return true; } } } } } } return false; }