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; }
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 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(); }
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; }
bool DoExecute (Args& command, CommandReturnObject &result) { const size_t argc = command.GetArgumentCount(); if (argc != 0) { result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName()); result.SetStatus (eReturnStatusFailed); return false; } Target *target = m_exe_ctx.GetTargetPtr(); if (!m_options.symbol_name.empty()) { SymbolContextList sc_list; ConstString name(m_options.symbol_name.c_str()); // Displaying the source for a symbol. Search for function named name. size_t num_matches = FindMatchingFunctions (target, name, sc_list); if (!num_matches) { // If we didn't find any functions with that name, try searching for symbols // that line up exactly with function addresses. SymbolContextList sc_list_symbols; size_t num_symbol_matches = FindMatchingFunctionSymbols (target, name, sc_list_symbols); for (size_t i = 0; i < num_symbol_matches; i++) { SymbolContext sc; sc_list_symbols.GetContextAtIndex (i, sc); if (sc.symbol) { const Address &base_address = sc.symbol->GetAddress(); Function *function = base_address.CalculateSymbolContextFunction(); if (function) { sc_list.Append (SymbolContext(function)); num_matches++; break; } } } } if (num_matches == 0) { result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str()); result.SetStatus (eReturnStatusFailed); return false; } if (num_matches > 1) { std::set<SourceInfo> source_match_set; bool displayed_something = false; for (size_t i = 0; i < num_matches; i++) { SymbolContext sc; sc_list.GetContextAtIndex (i, sc); SourceInfo source_info (sc.GetFunctionName(), sc.GetFunctionStartLineEntry()); if (source_info.IsValid()) { if (source_match_set.find(source_info) == source_match_set.end()) { source_match_set.insert(source_info); if (DisplayFunctionSource (sc, source_info, result)) displayed_something = true; } } } if (displayed_something) result.SetStatus (eReturnStatusSuccessFinishResult); else result.SetStatus (eReturnStatusFailed); } else { SymbolContext sc; sc_list.GetContextAtIndex (0, sc); SourceInfo source_info; if (DisplayFunctionSource (sc, source_info, result)) { result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.SetStatus (eReturnStatusFailed); } } return result.Succeeded(); } else if (m_options.address != LLDB_INVALID_ADDRESS) { Address so_addr; StreamString error_strm; SymbolContextList sc_list; 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 size_t num_modules = module_list.GetSize(); for (size_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)) { SymbolContext sc; sc.Clear(true); 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) { SymbolContext sc; sc.Clear(true); 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) { SymbolContext sc; 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; const bool show_function_arguments = true; sc.DumpStopContext(&result.GetOutputStream(), m_exe_ctx.GetBestExecutionContextScope(), sc.line_entry.range.GetBaseAddress(), show_fullpaths, show_module, show_inlined_frames, show_function_arguments); result.GetOutputStream().EOL(); if (m_options.num_lines == 0) m_options.num_lines = 10; 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(), m_options.num_lines, m_options.reverse, GetBreakpointLocations ())) { result.SetStatus (eReturnStatusSuccessFinishResult); } } else { if (m_options.num_lines == 0) m_options.num_lines = 10; 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 m_options.num_lines, // Lines after line to UINT32_MAX, // Don't mark "line" "", // 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 (size_t 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) { bool got_multiple = false; FileSpec *test_cu_spec = NULL; for (unsigned i = 0; i < num_matches; i++) { SymbolContext sc; 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(); if (m_options.num_lines == 0) m_options.num_lines = 10; 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(); }