virtual bool Execute (Args& command, CommandReturnObject &result) { Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; if (process == NULL) { result.AppendError("need a process to read memory"); result.SetStatus(eReturnStatusFailed); return false; } const size_t argc = command.GetArgumentCount(); if (m_options.m_infile) { if (argc < 1) { result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } } else if (argc < 2) { result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } StreamString buffer (Stream::eBinary, process->GetTarget().GetArchitecture().GetAddressByteSize(), process->GetTarget().GetArchitecture().GetByteOrder()); size_t item_byte_size = m_options.m_byte_size; lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); if (addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0)); result.SetStatus(eReturnStatusFailed); return false; } if (m_options.m_infile) { size_t length = SIZE_MAX; if (m_options.m_byte_size > 0) length = m_options.m_byte_size; lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length)); if (data_sp) { length = data_sp->GetByteSize(); if (length > 0) { Error error; size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); if (bytes_written == length) { // All bytes written result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr); result.SetStatus(eReturnStatusSuccessFinishResult); } else if (bytes_written > 0) { // Some byte written result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr); result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); result.SetStatus(eReturnStatusFailed); } } } else { result.AppendErrorWithFormat ("Unable to read contents of file.\n"); result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } else if (m_options.m_byte_size == 0) { if (m_options.m_format == eFormatPointer) item_byte_size = buffer.GetAddressByteSize(); else item_byte_size = 1; } command.Shift(); // shift off the address argument uint64_t uval64; int64_t sval64; bool success = false; const uint32_t num_value_args = command.GetArgumentCount(); uint32_t i; for (i=0; i<num_value_args; ++i) { const char *value_str = command.GetArgumentAtIndex(i); switch (m_options.m_format) { case eFormatFloat: // TODO: add support for floats soon case eFormatCharPrintable: case eFormatBytesWithASCII: case eFormatComplex: case eFormatEnum: case eFormatUnicode16: case eFormatUnicode32: case eFormatVectorOfChar: case eFormatVectorOfSInt8: case eFormatVectorOfUInt8: case eFormatVectorOfSInt16: case eFormatVectorOfUInt16: case eFormatVectorOfSInt32: case eFormatVectorOfUInt32: case eFormatVectorOfSInt64: case eFormatVectorOfUInt64: case eFormatVectorOfFloat32: case eFormatVectorOfFloat64: case eFormatVectorOfUInt128: result.AppendError("unsupported format for writing memory"); result.SetStatus(eReturnStatusFailed); return false; case eFormatDefault: case eFormatBytes: case eFormatHex: case eFormatPointer: // Decode hex bytes uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); result.SetStatus(eReturnStatusFailed); return false; } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } buffer.PutMaxHex64 (uval64, item_byte_size); break; case eFormatBoolean: uval64 = Args::StringToBoolean(value_str, false, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); result.SetStatus(eReturnStatusFailed); return false; } buffer.PutMaxHex64 (uval64, item_byte_size); break; case eFormatBinary: uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); result.SetStatus(eReturnStatusFailed); return false; } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } buffer.PutMaxHex64 (uval64, item_byte_size); break; case eFormatChar: case eFormatCString: if (value_str[0]) { size_t len = strlen (value_str); // Include the NULL for C strings... if (m_options.m_format == eFormatCString) ++len; Error error; if (process->WriteMemory (addr, value_str, len, error) == len) { addr += len; } else { result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } } break; case eFormatDecimal: sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); result.SetStatus(eReturnStatusFailed); return false; } else if (!SIntValueIsValidForSize (sval64, item_byte_size)) { result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } buffer.PutMaxHex64 (sval64, item_byte_size); break; case eFormatUnsigned: uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); result.SetStatus(eReturnStatusFailed); return false; } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } buffer.PutMaxHex64 (uval64, item_byte_size); break; case eFormatOctal: uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); result.SetStatus(eReturnStatusFailed); return false; } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } buffer.PutMaxHex64 (uval64, item_byte_size); break; } } if (!buffer.GetString().empty()) { Error error; if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) return true; else { result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } } return true; }
bool CommandObjectFile::Execute ( CommandInterpreter &interpreter, Args& command, CommandReturnObject &result ) { const char *file_path = command.GetArgumentAtIndex(0); Timer scoped_timer(__PRETTY_FUNCTION__, "(dbg) file '%s'", file_path); const int argc = command.GetArgumentCount(); if (argc == 1) { FileSpec file_spec (file_path); if (! file_spec.Exists()) { result.AppendErrorWithFormat ("File '%s' does not exist.\n", file_path); result.SetStatus (eReturnStatusFailed); return result.Succeeded(); } TargetSP target_sp; ArchSpec arch; if (m_options.m_arch.IsValid()) arch = m_options.m_arch; else { arch = lldb_private::GetDefaultArchitecture (); if (!arch.IsValid()) arch = LLDB_ARCH_DEFAULT; } Debugger &debugger = interpreter.GetDebugger(); Error error = debugger.GetTargetList().CreateTarget (debugger, file_spec, arch, NULL, true, target_sp); if (error.Fail() && !m_options.m_arch.IsValid()) { if (arch == LLDB_ARCH_DEFAULT_32BIT) arch = LLDB_ARCH_DEFAULT_64BIT; else arch = LLDB_ARCH_DEFAULT_32BIT; error = debugger.GetTargetList().CreateTarget (debugger, file_spec, arch, NULL, true, target_sp); } if (target_sp) { debugger.GetTargetList().SetCurrentTarget(target_sp.get()); result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, arch.AsCString()); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { result.AppendError(error.AsCString()); result.SetStatus (eReturnStatusFailed); } } else { result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str()); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); }
bool DoExecute (Args& command, CommandReturnObject &result) { const size_t argc = command.GetArgumentCount(); if (argc == 0) { if (!m_command_byte.GetOptionValue().OptionWasSet()) { result.AppendError ("the --command option must be set to a valid command byte"); result.SetStatus (eReturnStatusFailed); } else { const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0); if (command_byte > 0 && command_byte <= UINT8_MAX) { ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); if (process) { const StateType state = process->GetState(); if (StateIsStoppedState (state, true)) { std::vector<uint8_t> payload_bytes; const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue(); if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { StringExtractor extractor(ascii_hex_bytes_cstr); const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size(); if (ascii_hex_bytes_cstr_len & 1) { result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr); result.SetStatus (eReturnStatusFailed); return false; } payload_bytes.resize(ascii_hex_bytes_cstr_len/2); if (extractor.GetHexBytes(&payload_bytes[0], payload_bytes.size(), '\xdd') != payload_bytes.size()) { result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr); result.SetStatus (eReturnStatusFailed); return false; } } Error error; DataExtractor reply; process->GetCommunication().SendRawRequest (command_byte, payload_bytes.empty() ? NULL : payload_bytes.data(), payload_bytes.size(), reply, error); if (error.Success()) { // Copy the binary bytes into a hex ASCII string for the result StreamString packet; packet.PutBytesAsRawHex8(reply.GetDataStart(), reply.GetByteSize(), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); result.AppendMessage(packet.GetString().c_str()); result.SetStatus (eReturnStatusSuccessFinishResult); return true; } else { const char *error_cstr = error.AsCString(); if (error_cstr && error_cstr[0]) result.AppendError (error_cstr); else result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError()); result.SetStatus (eReturnStatusFailed); return false; } } else { result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state)); result.SetStatus (eReturnStatusFailed); } } else { result.AppendError ("invalid process"); result.SetStatus (eReturnStatusFailed); } } else { result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte); result.SetStatus (eReturnStatusFailed); } } } else { result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str()); result.SetStatus (eReturnStatusFailed); } return false; }
virtual bool DoExecute (Args& args, CommandReturnObject &result) { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { Error error; const uint32_t argc = args.GetArgumentCount(); Target *target = m_exe_ctx.GetTargetPtr(); Module *exe_module = target->GetExecutableModulePointer(); if (exe_module) { m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec(); char exe_path[PATH_MAX]; if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path))) m_options.launch_info.GetArguments().AppendArgument (exe_path); m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); } if (argc > 0) { if (m_options.launch_info.GetExecutableFile ()) { // We already have an executable file, so we will use this // and all arguments to this function are extra arguments m_options.launch_info.GetArguments().AppendArguments (args); } else { // We don't have any file yet, so the first argument is our // executable, and the rest are program arguments const bool first_arg_is_executable = true; m_options.launch_info.SetArguments (args, first_arg_is_executable); } } if (m_options.launch_info.GetExecutableFile ()) { Debugger &debugger = m_interpreter.GetDebugger(); if (argc == 0) target->GetRunArguments(m_options.launch_info.GetArguments()); ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, debugger, target, debugger.GetListener(), error)); if (process_sp && process_sp->IsAlive()) { result.SetStatus (eReturnStatusSuccessFinishNoResult); return true; } if (error.Success()) result.AppendError ("process launch failed"); else result.AppendError (error.AsCString()); result.SetStatus (eReturnStatusFailed); } else { result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command"); result.SetStatus (eReturnStatusFailed); return false; } } else { result.AppendError ("no platform is selected\n"); } return result.Succeeded(); }
virtual bool DoExecute (Args& args, CommandReturnObject &result) { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { const size_t argc = args.GetArgumentCount(); if (argc > 0) { Error error; if (platform_sp->IsConnected()) { Stream &ostrm = result.GetOutputStream(); bool success; for (size_t i=0; i<argc; ++ i) { const char *arg = args.GetArgumentAtIndex(i); lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success); if (success) { ProcessInstanceInfo proc_info; if (platform_sp->GetProcessInfo (pid, proc_info)) { ostrm.Printf ("Process information for process %" PRIu64 ":\n", pid); proc_info.Dump (ostrm, platform_sp.get()); } else { ostrm.Printf ("error: no process information is available for process %" PRIu64 "\n", pid); } ostrm.EOL(); } else { result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg); result.SetStatus (eReturnStatusFailed); break; } } } else { // Not connected... result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName()); result.SetStatus (eReturnStatusFailed); } } else { // No args result.AppendError ("one or more process id(s) must be specified"); result.SetStatus (eReturnStatusFailed); } } else { result.AppendError ("no platform is currently selected"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); }
bool DoExecute(Args& command, CommandReturnObject &result) override { StringList commands; commands.AppendString("thread backtrace"); Thread *thread = m_exe_ctx.GetThreadPtr(); if (thread) { char command_buffer[256]; uint32_t frame_count = thread->GetStackFrameCount(); for (uint32_t i = 0; i < frame_count; ++i) { StackFrameSP frame = thread->GetStackFrameAtIndex(i); lldb::addr_t pc = frame->GetStackID().GetPC(); snprintf(command_buffer, sizeof(command_buffer), "disassemble --bytes --address 0x%" PRIx64, pc); commands.AppendString(command_buffer); snprintf(command_buffer, sizeof(command_buffer), "image show-unwind --address 0x%" PRIx64, pc); commands.AppendString(command_buffer); } } const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); if (outfile_spec) { char path[PATH_MAX]; outfile_spec.GetPath (path, sizeof(path)); uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionAppend | File::eOpenOptionCloseOnExec; const bool append = m_outfile_options.GetAppend().GetCurrentValue(); if (!append) open_options |= File::eOpenOptionTruncate; StreamFileSP outfile_stream = std::make_shared<StreamFile>(); Error error = outfile_stream->GetFile().Open(path, open_options); if (error.Fail()) { result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", path, append ? "append" : "write", error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } result.SetImmediateOutputStream(outfile_stream); } CommandInterpreterRunOptions options; options.SetStopOnError(false); options.SetEchoCommands(true); options.SetPrintResults(true); options.SetAddToHistory(false); m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); return result.Succeeded(); }
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 CommandObjectHelp::Execute (Args& command, CommandReturnObject &result) { CommandObject::CommandMap::iterator pos; CommandObject *cmd_obj; const int argc = command.GetArgumentCount (); // 'help' doesn't take any options or arguments, other than command names. If argc is 0, we show the user // all commands and aliases. Otherwise every argument must be the name of a command or a sub-command. if (argc == 0) { result.SetStatus (eReturnStatusSuccessFinishNoResult); m_interpreter.GetHelp (result); // General help, for ALL commands. } else { // Get command object for the first command argument. Only search built-in command dictionary. StringList matches; cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches); bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0)); std::string alias_name = command.GetArgumentAtIndex(0); if (cmd_obj != NULL) { StringList matches; bool all_okay = true; CommandObject *sub_cmd_obj = cmd_obj; // Loop down through sub_command dictionaries until we find the command object that corresponds // to the help command entered. for (int i = 1; i < argc && all_okay; ++i) { std::string sub_command = command.GetArgumentAtIndex(i); matches.Clear(); if (! sub_cmd_obj->IsMultiwordObject ()) { all_okay = false; } else { CommandObject *found_cmd; found_cmd = ((CommandObjectMultiword *) sub_cmd_obj)->GetSubcommandObject(sub_command.c_str(), &matches); if (found_cmd == NULL) all_okay = false; else if (matches.GetSize() > 1) all_okay = false; else sub_cmd_obj = found_cmd; } } if (!all_okay || (sub_cmd_obj == NULL)) { std::string cmd_string; command.GetCommandString (cmd_string); if (matches.GetSize() < 2) { result.AppendErrorWithFormat("'%s' is not a known command.\n" "Try 'help' to see a current list of commands.\n", cmd_string.c_str()); } else { StreamString s; s.Printf ("ambiguous command %s", cmd_string.c_str()); size_t num_matches = matches.GetSize(); for (size_t match_idx = 0; match_idx < num_matches; match_idx++) { s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx)); } s.Printf ("\n"); result.AppendError(s.GetData()); } result.SetStatus (eReturnStatusFailed); } else { Stream &output_strm = result.GetOutputStream(); if (sub_cmd_obj->GetOptions() != NULL) { if (sub_cmd_obj->WantsRawCommandString()) { std::string help_text (sub_cmd_obj->GetHelp()); help_text.append (" This command takes 'raw' input (no need to quote stuff)."); m_interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1); } else m_interpreter.OutputFormattedHelpText (output_strm, "", "", sub_cmd_obj->GetHelp(), 1); output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax()); sub_cmd_obj->GetOptions()->GenerateOptionUsage (m_interpreter, output_strm, sub_cmd_obj); const char *long_help = sub_cmd_obj->GetHelpLong(); if ((long_help != NULL) && (strlen (long_help) > 0)) output_strm.Printf ("\n%s", long_help); // Mark this help command with a success status. if (sub_cmd_obj->WantsRawCommandString()) { m_interpreter.OutputFormattedHelpText (output_strm, "", "", "\nIMPORTANT NOTE: Because this command takes 'raw' input, if you use any command options you must use ' -- ' between the end of the command options and the beginning of the raw input.", 1); } result.SetStatus (eReturnStatusSuccessFinishNoResult); } else if (sub_cmd_obj->IsMultiwordObject()) { if (sub_cmd_obj->WantsRawCommandString()) { std::string help_text (sub_cmd_obj->GetHelp()); help_text.append (" This command takes 'raw' input (no need to quote stuff)."); m_interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1); } else m_interpreter.OutputFormattedHelpText (output_strm, "", "", sub_cmd_obj->GetHelp(), 1); ((CommandObjectMultiword *) sub_cmd_obj)->GenerateHelpText (result); } else { const char *long_help = sub_cmd_obj->GetHelpLong(); if ((long_help != NULL) && (strlen (long_help) > 0)) output_strm.Printf ("\n%s", long_help); else if (sub_cmd_obj->WantsRawCommandString()) { std::string help_text (sub_cmd_obj->GetHelp()); help_text.append (" This command takes 'raw' input (no need to quote stuff)."); m_interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1); } else m_interpreter.OutputFormattedHelpText (output_strm, "", "", sub_cmd_obj->GetHelp(), 1); output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax()); // Mark this help command with a success status. result.SetStatus (eReturnStatusSuccessFinishNoResult); } } if (is_alias_command) { StreamString sstr; m_interpreter.GetAliasHelp (alias_name.c_str(), cmd_obj->GetCommandName(), sstr); result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData()); } } else if (matches.GetSize() > 0) { Stream &output_strm = result.GetOutputStream(); output_strm.Printf("Help requested with ambiguous command name, possible completions:\n"); const uint32_t match_count = matches.GetSize(); for (uint32_t i = 0; i < match_count; i++) { output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i)); } } else { // Maybe the user is asking for help about a command argument rather than a command. const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0)); if (arg_type != eArgTypeLastArg) { Stream &output_strm = result.GetOutputStream (); CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n", command.GetArgumentAtIndex(0)); result.SetStatus (eReturnStatusFailed); } } } return result.Succeeded(); }
void CommandInterpreter::BuildAliasCommandArgs ( CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args, CommandReturnObject &result ) { OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); if (option_arg_vector_sp.get()) { // Make sure that the alias name is the 0th element in cmd_args std::string alias_name_str = alias_name; if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) cmd_args.Unshift (alias_name); Args new_args (alias_cmd_obj->GetCommandName()); if (new_args.GetArgumentCount() == 2) new_args.Shift(); OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); int old_size = cmd_args.GetArgumentCount(); int *used = (int *) malloc ((old_size + 1) * sizeof (int)); memset (used, 0, (old_size + 1) * sizeof (int)); used[0] = 1; for (int i = 0; i < option_arg_vector->size(); ++i) { OptionArgPair option_pair = (*option_arg_vector)[i]; std::string option = option_pair.first; std::string value = option_pair.second; if (option.compare ("<argument>") == 0) new_args.AppendArgument (value.c_str()); else { new_args.AppendArgument (option.c_str()); if (value.compare ("<no-argument>") != 0) { int index = GetOptionArgumentPosition (value.c_str()); if (index == 0) // value was NOT a positional argument; must be a real value new_args.AppendArgument (value.c_str()); else if (index >= cmd_args.GetArgumentCount()) { result.AppendErrorWithFormat ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", index); result.SetStatus (eReturnStatusFailed); return; } else { new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); used[index] = 1; } } } } for (int j = 0; j < cmd_args.GetArgumentCount(); ++j) { if (!used[j]) new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); } cmd_args.Clear(); cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); } else { result.SetStatus (eReturnStatusSuccessFinishNoResult); // This alias was not created with any options; nothing further needs to be done. return; } result.SetStatus (eReturnStatusSuccessFinishNoResult); return; }
virtual bool DoExecute (Args& command, CommandReturnObject &result) { Stream &strm = result.GetOutputStream(); RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); const RegisterInfo *reg_info = NULL; if (command.GetArgumentCount() == 0) { size_t set_idx; size_t num_register_sets = 1; const size_t set_array_size = m_command_options.set_indexes.GetSize(); if (set_array_size > 0) { for (size_t i=0; i<set_array_size; ++i) { set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL); if (set_idx < reg_ctx->GetRegisterSetCount()) { if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx)) { if (errno) result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno)); else result.AppendError ("unknown error while reading registers.\n"); result.SetStatus (eReturnStatusFailed); break; } } else { result.AppendErrorWithFormat ("invalid register set index: %zu\n", set_idx); result.SetStatus (eReturnStatusFailed); break; } } } else { if (m_command_options.dump_all_sets) num_register_sets = reg_ctx->GetRegisterSetCount(); for (set_idx = 0; set_idx < num_register_sets; ++set_idx) { // When dump_all_sets option is set, dump primitive as well as derived registers. DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue()); } } } else { if (m_command_options.dump_all_sets) { result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n"); result.SetStatus (eReturnStatusFailed); } else if (m_command_options.set_indexes.GetSize() > 0) { result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n"); result.SetStatus (eReturnStatusFailed); } else { const char *arg_cstr; for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx) { // in most LLDB commands we accept $rbx as the name for register RBX - and here we would // reject it and non-existant. we should be more consistent towards the user and allow them // to say reg read $rbx - internally, however, we should be strict and not allow ourselves // to call our registers $rbx in our own API if (*arg_cstr == '$') arg_cstr = arg_cstr+1; reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr); if (reg_info) { if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info)) strm.Printf("%-12s = error: unavailable\n", reg_info->name); } else { result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr); } } } } return result.Succeeded(); }
virtual bool DoExecute(Args& command, CommandReturnObject &result) { DataExtractor reg_data; RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); if (command.GetArgumentCount() != 2) { result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>"); result.SetStatus (eReturnStatusFailed); } else { const char *reg_name = command.GetArgumentAtIndex(0); const char *value_str = command.GetArgumentAtIndex(1); // in most LLDB commands we accept $rbx as the name for register RBX - and here we would // reject it and non-existant. we should be more consistent towards the user and allow them // to say reg write $rbx - internally, however, we should be strict and not allow ourselves // to call our registers $rbx in our own API if (reg_name && *reg_name == '$') reg_name = reg_name+1; const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); if (reg_info) { RegisterValue reg_value; Error error (reg_value.SetValueFromCString (reg_info, value_str)); if (error.Success()) { if (reg_ctx->WriteRegister (reg_info, reg_value)) { // Toss all frames and anything else in the thread // after a register has been written. m_exe_ctx.GetThreadRef().Flush(); result.SetStatus (eReturnStatusSuccessFinishNoResult); return true; } } if (error.AsCString()) { result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n", reg_name, value_str, error.AsCString()); } else { result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'", reg_name, value_str); } result.SetStatus (eReturnStatusFailed); } else { result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name); result.SetStatus (eReturnStatusFailed); } } return result.Succeeded(); }
virtual bool DoExecute (Args& command, CommandReturnObject &result) { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) { result.AppendError ("Invalid target. No current target or watchpoints."); result.SetStatus (eReturnStatusSuccessFinishNoResult); return true; } if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) { uint32_t num_supported_hardware_watchpoints; Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints); if (error.Success()) result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n", num_supported_hardware_watchpoints); } const WatchpointList &watchpoints = target->GetWatchpointList(); Mutex::Locker locker; target->GetWatchpointList().GetListMutex(locker); size_t num_watchpoints = watchpoints.GetSize(); if (num_watchpoints == 0) { result.AppendMessage("No watchpoints currently set."); result.SetStatus(eReturnStatusSuccessFinishNoResult); return true; } Stream &output_stream = result.GetOutputStream(); if (command.GetArgumentCount() == 0) { // No watchpoint selected; show info about all currently set watchpoints. result.AppendMessage ("Current watchpoints:"); for (size_t i = 0; i < num_watchpoints; ++i) { Watchpoint *wp = watchpoints.GetByIndex(i).get(); AddWatchpointDescription(&output_stream, wp, m_options.m_level); } result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { // Particular watchpoints selected; enable them. std::vector<uint32_t> wp_ids; if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) { result.AppendError("Invalid watchpoints specification."); result.SetStatus(eReturnStatusFailed); return false; } const size_t size = wp_ids.size(); for (size_t i = 0; i < size; ++i) { Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); if (wp) AddWatchpointDescription(&output_stream, wp, m_options.m_level); result.SetStatus(eReturnStatusSuccessFinishNoResult); } } return result.Succeeded(); }
virtual bool DoExecute (Args& command, CommandReturnObject &result) { ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == NULL) { result.AppendError ("you must be stopped in a valid stack frame to view frame variables."); result.SetStatus (eReturnStatusFailed); return false; } Stream &s = result.GetOutputStream(); bool get_file_globals = true; // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList // for the thread. So hold onto a shared pointer to the frame so it stays alive. VariableList *variable_list = frame->GetVariableList (get_file_globals); VariableSP var_sp; ValueObjectSP valobj_sp; const char *name_cstr = NULL; size_t idx; TypeSummaryImplSP summary_format_sp; if (!m_option_variable.summary.IsCurrentValueEmpty()) DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp); else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue())); ValueObject::DumpValueObjectOptions options; options.SetMaximumPointerDepth(m_varobj_options.ptr_depth) .SetMaximumDepth(m_varobj_options.max_depth) .SetShowTypes(m_varobj_options.show_types) .SetShowLocation(m_varobj_options.show_location) .SetUseObjectiveC(m_varobj_options.use_objc) .SetUseDynamicType(m_varobj_options.use_dynamic) .SetUseSyntheticValue(m_varobj_options.use_synth) .SetFlatOutput(m_varobj_options.flat_output) .SetOmitSummaryDepth(m_varobj_options.no_summary_depth) .SetIgnoreCap(m_varobj_options.ignore_cap) .SetSummary(summary_format_sp); if (m_varobj_options.be_raw) options.SetRawDisplay(true); if (variable_list) { const Format format = m_option_format.GetFormat(); options.SetFormat(format); if (command.GetArgumentCount() > 0) { VariableList regex_var_list; // If we have any args to the variable command, we will make // variable objects from them... for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx) { if (m_option_variable.use_regex) { const uint32_t regex_start_index = regex_var_list.GetSize(); RegularExpression regex (name_cstr); if (regex.Compile(name_cstr)) { size_t num_matches = 0; const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, num_matches); if (num_new_regex_vars > 0) { for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); regex_idx < end_index; ++regex_idx) { var_sp = regex_var_list.GetVariableAtIndex (regex_idx); if (var_sp) { valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat (format); if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { bool show_fullpaths = false; bool show_module = true; if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString (": "); } ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), options); } } } } else if (num_matches == 0) { result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr); } } else { char regex_error[1024]; if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) result.GetErrorStream().Printf ("error: %s\n", regex_error); else result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr); } } else // No regex, either exact variable names or variable expressions. { Error error; uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr, m_varobj_options.use_dynamic, expr_path_options, var_sp, error); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat (format); if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } options.SetFormat(format); Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL); ValueObject::DumpValueObject (output_stream, valobj_sp.get(), options); } else { const char *error_cstr = error.AsCString(NULL); if (error_cstr) result.GetErrorStream().Printf("error: %s\n", error_cstr); else result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr); } } } } else // No command arg specified. Use variable_list, instead. { const uint32_t num_variables = variable_list->GetSize(); if (num_variables > 0) { for (uint32_t i=0; i<num_variables; i++) { var_sp = variable_list->GetVariableAtIndex(i); bool dump_variable = true; switch (var_sp->GetScope()) { case eValueTypeVariableGlobal: dump_variable = m_option_variable.show_globals; if (dump_variable && m_option_variable.show_scope) s.PutCString("GLOBAL: "); break; case eValueTypeVariableStatic: dump_variable = m_option_variable.show_globals; if (dump_variable && m_option_variable.show_scope) s.PutCString("STATIC: "); break; case eValueTypeVariableArgument: dump_variable = m_option_variable.show_args; if (dump_variable && m_option_variable.show_scope) s.PutCString(" ARG: "); break; case eValueTypeVariableLocal: dump_variable = m_option_variable.show_locals; if (dump_variable && m_option_variable.show_scope) s.PutCString(" LOCAL: "); break; default: break; } if (dump_variable) { // Use the variable object code to make sure we are // using the same APIs as the the public API will be // using... valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat (format); // When dumping all variables, don't print any variables // that are not in scope to avoid extra unneeded output if (valobj_sp->IsInScope ()) { if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } options.SetFormat(format); options.SetRootValueObjectName(name_cstr); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), options); } } } } } } result.SetStatus (eReturnStatusSuccessFinishResult); } if (m_interpreter.TruncationWarningNecessary()) { result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), m_cmd_name.c_str()); m_interpreter.TruncationWarningGiven(); } return result.Succeeded(); }
bool DoExecute (Args& command, CommandReturnObject &result) { ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); Thread *thread = exe_ctx.GetThreadPtr(); if (thread) { uint32_t frame_idx = UINT32_MAX; if (m_options.relative_frame_offset != INT32_MIN) { // The one and only argument is a signed relative frame index frame_idx = thread->GetSelectedFrameIndex (); if (frame_idx == UINT32_MAX) frame_idx = 0; if (m_options.relative_frame_offset < 0) { if (frame_idx >= -m_options.relative_frame_offset) frame_idx += m_options.relative_frame_offset; else { if (frame_idx == 0) { //If you are already at the bottom of the stack, then just warn and don't reset the frame. result.AppendError("Already at the bottom of the stack"); result.SetStatus(eReturnStatusFailed); return false; } else frame_idx = 0; } } else if (m_options.relative_frame_offset > 0) { // I don't want "up 20" where "20" takes you past the top of the stack to produce // an error, but rather to just go to the top. So I have to count the stack here... const uint32_t num_frames = thread->GetStackFrameCount(); if (num_frames - frame_idx > m_options.relative_frame_offset) frame_idx += m_options.relative_frame_offset; else { if (frame_idx == num_frames - 1) { //If we are already at the top of the stack, just warn and don't reset the frame. result.AppendError("Already at the top of the stack"); result.SetStatus(eReturnStatusFailed); return false; } else frame_idx = num_frames - 1; } } } else { if (command.GetArgumentCount() == 1) { const char *frame_idx_cstr = command.GetArgumentAtIndex(0); frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0); } else if (command.GetArgumentCount() == 0) { frame_idx = thread->GetSelectedFrameIndex (); if (frame_idx == UINT32_MAX) { frame_idx = 0; } } else { result.AppendError ("invalid arguments.\n"); m_options.GenerateOptionUsage (result.GetErrorStream(), this); } } const bool broadcast = true; bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast); if (success) { exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); StackFrame *frame = exe_ctx.GetFramePtr(); if (frame) { bool already_shown = false; SymbolContext frame_sc(frame->GetSymbolContext(eSymbolContextLineEntry)); if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0) { already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line); } bool show_frame_info = true; bool show_source = !already_shown; if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source)) { result.SetStatus (eReturnStatusSuccessFinishResult); return result.Succeeded(); } } } result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx); } else { result.AppendError ("no current thread"); } result.SetStatus (eReturnStatusFailed); return false; }
bool CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result) { CommandObject::CommandMap::iterator pos; CommandObject *cmd_obj; const size_t argc = command.GetArgumentCount (); // 'help' doesn't take any arguments, other than command names. If argc is 0, we show the user // all commands (aliases and user commands if asked for). Otherwise every argument must be the name of a command or a sub-command. if (argc == 0) { uint32_t cmd_types = CommandInterpreter::eCommandTypesBuiltin; if (m_options.m_show_aliases) cmd_types |= CommandInterpreter::eCommandTypesAliases; if (m_options.m_show_user_defined) cmd_types |= CommandInterpreter::eCommandTypesUserDef; if (m_options.m_show_hidden) cmd_types |= CommandInterpreter::eCommandTypesHidden; result.SetStatus (eReturnStatusSuccessFinishNoResult); m_interpreter.GetHelp (result, cmd_types); // General help } else { // Get command object for the first command argument. Only search built-in command dictionary. StringList matches; cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex (0), &matches); bool is_alias_command = m_interpreter.AliasExists (command.GetArgumentAtIndex (0)); std::string alias_name = command.GetArgumentAtIndex(0); if (cmd_obj != nullptr) { StringList matches; bool all_okay = true; CommandObject *sub_cmd_obj = cmd_obj; // Loop down through sub_command dictionaries until we find the command object that corresponds // to the help command entered. std::string sub_command; for (size_t i = 1; i < argc && all_okay; ++i) { sub_command = command.GetArgumentAtIndex(i); matches.Clear(); if (sub_cmd_obj->IsAlias()) sub_cmd_obj = ((CommandAlias*)sub_cmd_obj)->GetUnderlyingCommand().get(); if (! sub_cmd_obj->IsMultiwordObject ()) { all_okay = false; } else { CommandObject *found_cmd; found_cmd = sub_cmd_obj->GetSubcommandObject(sub_command.c_str(), &matches); if (found_cmd == nullptr) all_okay = false; else if (matches.GetSize() > 1) all_okay = false; else sub_cmd_obj = found_cmd; } } if (!all_okay || (sub_cmd_obj == nullptr)) { std::string cmd_string; command.GetCommandString (cmd_string); if (matches.GetSize() >= 2) { StreamString s; s.Printf ("ambiguous command %s", cmd_string.c_str()); size_t num_matches = matches.GetSize(); for (size_t match_idx = 0; match_idx < num_matches; match_idx++) { s.Printf ("\n\t%s", matches.GetStringAtIndex(match_idx)); } s.Printf ("\n"); result.AppendError(s.GetData()); result.SetStatus (eReturnStatusFailed); return false; } else if (!sub_cmd_obj) { StreamString error_msg_stream; GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, cmd_string.c_str(), m_interpreter.GetCommandPrefix(), sub_command.c_str()); result.AppendErrorWithFormat("%s",error_msg_stream.GetData()); result.SetStatus (eReturnStatusFailed); return false; } else { GenerateAdditionalHelpAvenuesMessage(&result.GetOutputStream(), cmd_string.c_str(), m_interpreter.GetCommandPrefix(), sub_command.c_str()); result.GetOutputStream().Printf("\nThe closest match is '%s'. Help on it follows.\n\n", sub_cmd_obj->GetCommandName()); } } sub_cmd_obj->GenerateHelpText(result); if (is_alias_command) { StreamString sstr; m_interpreter.GetAlias(alias_name.c_str())->GetAliasExpansion(sstr); result.GetOutputStream().Printf ("\n'%s' is an abbreviation for %s\n", alias_name.c_str(), sstr.GetData()); } } else if (matches.GetSize() > 0) { Stream &output_strm = result.GetOutputStream(); output_strm.Printf("Help requested with ambiguous command name, possible completions:\n"); const size_t match_count = matches.GetSize(); for (size_t i = 0; i < match_count; i++) { output_strm.Printf("\t%s\n", matches.GetStringAtIndex(i)); } } else { // Maybe the user is asking for help about a command argument rather than a command. const CommandArgumentType arg_type = CommandObject::LookupArgumentName (command.GetArgumentAtIndex (0)); if (arg_type != eArgTypeLastArg) { Stream &output_strm = result.GetOutputStream (); CommandObject::GetArgumentHelp (output_strm, arg_type, m_interpreter); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { StreamString error_msg_stream; GenerateAdditionalHelpAvenuesMessage(&error_msg_stream, command.GetArgumentAtIndex(0), m_interpreter.GetCommandPrefix()); result.AppendErrorWithFormat("%s",error_msg_stream.GetData()); result.SetStatus (eReturnStatusFailed); } } } return result.Succeeded(); }
bool CommandInterpreter::HandleCommand ( const char *command_line, bool add_to_history, CommandReturnObject &result, ExecutionContext *override_context ) { // FIXME: there should probably be a mutex to make sure only one thread can // run the interpreter at a time. // TODO: this should be a logging channel in lldb. // if (DebugSelf()) // { // result.AppendMessageWithFormat ("Processing command: %s\n", command_line); // } m_debugger.UpdateExecutionContext (override_context); if (command_line == NULL || command_line[0] == '\0') { if (m_command_history.empty()) { result.AppendError ("empty command"); result.SetStatus(eReturnStatusFailed); return false; } else { command_line = m_repeat_command.c_str(); if (m_repeat_command.empty()) { result.AppendErrorWithFormat("No auto repeat.\n"); result.SetStatus (eReturnStatusFailed); return false; } } add_to_history = false; } Args command_args(command_line); if (command_args.GetArgumentCount() > 0) { const char *command_cstr = command_args.GetArgumentAtIndex(0); if (command_cstr) { // We're looking up the command object here. So first find an exact match to the // command in the commands. CommandObject *command_obj = GetCommandObject(command_cstr); if (command_obj != NULL) { if (command_obj->IsAlias()) { BuildAliasCommandArgs (command_obj, command_cstr, command_args, result); if (!result.Succeeded()) return false; } if (add_to_history) { const char *repeat_command = command_obj->GetRepeatCommand(command_args, 0); if (repeat_command != NULL) m_repeat_command.assign(repeat_command); else m_repeat_command.assign(command_line); m_command_history.push_back (command_line); } if (command_obj->WantsRawCommandString()) { const char *stripped_command = ::strstr (command_line, command_cstr); if (stripped_command) { stripped_command += strlen(command_cstr); while (isspace(*stripped_command)) ++stripped_command; command_obj->ExecuteRawCommandString (*this, stripped_command, result); } } else { // Remove the command from the args. command_args.Shift(); command_obj->ExecuteWithOptions (*this, command_args, result); } } else { // We didn't find the first command object, so complete the first argument. StringList matches; int num_matches; int cursor_index = 0; int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0)); bool word_complete; num_matches = HandleCompletionMatches (command_args, cursor_index, cursor_char_position, 0, -1, word_complete, matches); if (num_matches > 0) { std::string error_msg; error_msg.assign ("ambiguous command '"); error_msg.append(command_cstr); error_msg.append ("'."); error_msg.append (" Possible completions:"); for (int i = 0; i < num_matches; i++) { error_msg.append ("\n\t"); error_msg.append (matches.GetStringAtIndex (i)); } error_msg.append ("\n"); result.AppendRawError (error_msg.c_str(), error_msg.size()); } else result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_cstr); result.SetStatus (eReturnStatusFailed); } } } return result.Succeeded(); }
bool CommandObjectDisassemble::Execute ( CommandInterpreter &interpreter, Args& command, CommandReturnObject &result ) { Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); if (target == NULL) { result.AppendError ("invalid target, set executable file using 'file' command"); result.SetStatus (eReturnStatusFailed); return false; } ArchSpec arch(target->GetArchitecture()); if (!arch.IsValid()) { result.AppendError ("target needs valid architecure in order to be able to disassemble"); result.SetStatus (eReturnStatusFailed); return false; } Disassembler *disassembler = Disassembler::FindPlugin(arch); if (disassembler == NULL) { result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for %s architecture.\n", arch.AsCString()); result.SetStatus (eReturnStatusFailed); return false; } result.SetStatus (eReturnStatusSuccessFinishResult); if (command.GetArgumentCount() != 0) { result.AppendErrorWithFormat ("\"disassemble\" doesn't take any arguments.\n"); result.SetStatus (eReturnStatusFailed); return false; } ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext()); if (m_options.show_mixed && m_options.num_lines_context == 0) m_options.num_lines_context = 3; if (!m_options.m_func_name.empty()) { ConstString name(m_options.m_func_name.c_str()); if (Disassembler::Disassemble (interpreter.GetDebugger(), arch, exe_ctx, name, NULL, // Module * m_options.show_mixed ? m_options.num_lines_context : 0, m_options.show_bytes, result.GetOutputStream())) { result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString()); result.SetStatus (eReturnStatusFailed); } } else { AddressRange range; if (m_options.m_start_addr != LLDB_INVALID_ADDRESS) { range.GetBaseAddress().SetOffset (m_options.m_start_addr); if (m_options.m_end_addr != LLDB_INVALID_ADDRESS) { if (m_options.m_end_addr < m_options.m_start_addr) { result.AppendErrorWithFormat ("End address before start address.\n"); result.SetStatus (eReturnStatusFailed); return false; } range.SetByteSize (m_options.m_end_addr - m_options.m_start_addr); } else range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE); } else { if (exe_ctx.frame) { SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); if (sc.function) range = sc.function->GetAddressRange(); else if (sc.symbol && sc.symbol->GetAddressRangePtr()) range = *sc.symbol->GetAddressRangePtr(); else range.GetBaseAddress() = exe_ctx.frame->GetPC(); } else { result.AppendError ("invalid frame"); result.SetStatus (eReturnStatusFailed); return false; } } if (range.GetByteSize() == 0) range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); if (Disassembler::Disassemble (interpreter.GetDebugger(), arch, exe_ctx, range, m_options.show_mixed ? m_options.num_lines_context : 0, m_options.show_bytes, result.GetOutputStream())) { result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr); result.SetStatus (eReturnStatusFailed); } } return result.Succeeded(); }
void Args::ParseAliasOptions ( Options &options, CommandReturnObject &result, OptionArgVector *option_arg_vector ) { StreamString sstr; int i; struct option *long_options = options.GetLongOptions(); if (long_options == NULL) { result.AppendError ("invalid long options"); result.SetStatus (eReturnStatusFailed); return; } for (i = 0; long_options[i].name != NULL; ++i) { if (long_options[i].flag == NULL) { sstr << (char) long_options[i].val; switch (long_options[i].has_arg) { default: case no_argument: break; case required_argument: sstr << ":"; break; case optional_argument: sstr << "::"; break; } } } #ifdef __GLIBC__ optind = 0; #else optreset = 1; optind = 1; #endif int val; while (1) { int long_options_index = -1; val = ::getopt_long (GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options, &long_options_index); if (val == -1) break; if (val == '?') { result.AppendError ("unknown or ambiguous option"); result.SetStatus (eReturnStatusFailed); break; } if (val == 0) continue; ((Options *) &options)->OptionSeen (val); // Look up the long option index if (long_options_index == -1) { for (int j = 0; long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val; ++j) { if (long_options[j].val == val) { long_options_index = j; break; } } } // See if the option takes an argument, and see if one was supplied. if (long_options_index >= 0) { StreamString option_str; option_str.Printf ("-%c", (char) val); switch (long_options[long_options_index].has_arg) { case no_argument: option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), "<no-argument>")); break; case required_argument: if (optarg != NULL) { option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), std::string (optarg))); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n", option_str.GetData()); result.SetStatus (eReturnStatusFailed); } break; case optional_argument: if (optarg != NULL) { option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), std::string (optarg))); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), "<no-argument>")); result.SetStatus (eReturnStatusSuccessFinishNoResult); } break; default: result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", (char) val); result.SetStatus (eReturnStatusFailed); break; } } else { result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", (char) val); result.SetStatus (eReturnStatusFailed); } if (!result.Succeeded()) break; } }
bool CommandObjectArgs::DoExecute(Args &args, CommandReturnObject &result) { ConstString target_triple; Process *process = m_exe_ctx.GetProcessPtr(); if (!process) { result.AppendError("Args found no process."); result.SetStatus(eReturnStatusFailed); return false; } const ABI *abi = process->GetABI().get(); if (!abi) { result.AppendError("The current process has no ABI."); result.SetStatus(eReturnStatusFailed); return false; } if (args.empty()) { result.AppendError("args requires at least one argument"); result.SetStatus(eReturnStatusFailed); return false; } Thread *thread = m_exe_ctx.GetThreadPtr(); if (!thread) { result.AppendError("args found no thread."); result.SetStatus(eReturnStatusFailed); return false; } lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame(); if (!thread_cur_frame) { result.AppendError("The current thread has no current frame."); result.SetStatus(eReturnStatusFailed); return false; } ModuleSP thread_module_sp( thread_cur_frame->GetFrameCodeAddress().GetModule()); if (!thread_module_sp) { result.AppendError("The PC has no associated module."); result.SetStatus(eReturnStatusFailed); return false; } TypeSystem *type_system = thread_module_sp->GetTypeSystemForLanguage(eLanguageTypeC); if (type_system == nullptr) { result.AppendError("Unable to create C type system."); result.SetStatus(eReturnStatusFailed); return false; } ValueList value_list; for (auto &arg_entry : args.entries()) { llvm::StringRef arg_type = arg_entry.ref; Value value; value.SetValueType(Value::eValueTypeScalar); CompilerType compiler_type; std::size_t int_pos = arg_type.find("int"); if (int_pos != llvm::StringRef::npos) { Encoding encoding = eEncodingSint; int width = 0; if (int_pos > 1) { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } if (int_pos == 1 && arg_type[0] != 'u') { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } if (arg_type[0] == 'u') { encoding = eEncodingUint; } llvm::StringRef width_spec = arg_type.drop_front(int_pos + 3); auto exp_result = llvm::StringSwitch<llvm::Optional<int>>(width_spec) .Case("8_t", 8) .Case("16_t", 16) .Case("32_t", 32) .Case("64_t", 64) .Default(llvm::None); if (!exp_result.hasValue()) { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } width = *exp_result; compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize(encoding, width); if (!compiler_type.IsValid()) { result.AppendErrorWithFormat( "Couldn't get Clang type for format %s (%s integer, width %d).\n", arg_entry.c_str(), (encoding == eEncodingSint ? "signed" : "unsigned"), width); result.SetStatus(eReturnStatusFailed); return false; } } else if (arg_type == "void*") { compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); } else if (arg_type == "char*") { compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeChar).GetPointerType(); } else { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } value.SetCompilerType(compiler_type); value_list.PushValue(value); } if (!abi->GetArgumentValues(*thread, value_list)) { result.AppendError("Couldn't get argument values"); result.SetStatus(eReturnStatusFailed); return false; } result.GetOutputStream().Printf("Arguments : \n"); for (auto entry : llvm::enumerate(args.entries())) { result.GetOutputStream().Printf("%" PRIu64 " (%s): ", (uint64_t)entry.Index, entry.Value.c_str()); value_list.GetValueAtIndex(entry.Index)->Dump(&result.GetOutputStream()); result.GetOutputStream().Printf("\n"); } return result.Succeeded(); }
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 CommandObjectSyntax::DoExecute (Args& command, CommandReturnObject &result) { CommandObject::CommandMap::iterator pos; CommandObject *cmd_obj; const size_t argc = command.GetArgumentCount(); if (argc > 0) { cmd_obj = m_interpreter.GetCommandObject (command.GetArgumentAtIndex(0)); bool all_okay = true; for (size_t i = 1; i < argc; ++i) { std::string sub_command = command.GetArgumentAtIndex (i); if (!cmd_obj->IsMultiwordObject()) { all_okay = false; break; } else { cmd_obj = cmd_obj->GetSubcommandObject(sub_command.c_str()); if (!cmd_obj) { all_okay = false; break; } } } if (all_okay && (cmd_obj != NULL)) { Stream &output_strm = result.GetOutputStream(); if (cmd_obj->GetOptions() != NULL) { output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax()); output_strm.Printf ("(Try 'help %s' for more information on command options syntax.)\n", cmd_obj->GetCommandName()); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax()); result.SetStatus (eReturnStatusSuccessFinishNoResult); } } else { std::string cmd_string; command.GetCommandString (cmd_string); result.AppendErrorWithFormat ("'%s' is not a known command.\n", cmd_string.c_str()); result.AppendError ("Try 'help' to see a current list of commands."); result.SetStatus (eReturnStatusFailed); } } else { result.AppendError ("Must call 'syntax' with a valid command."); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); }
void BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, Args &new_args) { std::string range_start; const char *range_end; const char *current_arg; const size_t num_old_args = old_args.GetArgumentCount(); for (size_t i = 0; i < num_old_args; ++i) { bool is_range = false; current_arg = old_args.GetArgumentAtIndex (i); uint32_t range_start_len = 0; uint32_t range_end_pos = 0; if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos)) { is_range = true; range_start = (char *) malloc (range_start_len + 1); range_start.assign (current_arg, range_start_len); range_end = current_arg + range_end_pos; } else if ((i + 2 < num_old_args) && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1)) && BreakpointID::IsValidIDExpression (current_arg) && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2))) { range_start.assign (current_arg); range_end = old_args.GetArgumentAtIndex (i+2); is_range = true; i = i+2; } if (is_range) { break_id_t start_bp_id; break_id_t end_bp_id; break_id_t start_loc_id; break_id_t end_loc_id; BreakpointID::ParseCanonicalReference (range_start.c_str(), &start_bp_id, &start_loc_id); BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id); if ((start_bp_id == LLDB_INVALID_BREAK_ID) || (! target->GetBreakpointByID (start_bp_id))) { new_args.Clear(); result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start.c_str()); result.SetStatus (eReturnStatusFailed); return; } if ((end_bp_id == LLDB_INVALID_BREAK_ID) || (! target->GetBreakpointByID (end_bp_id))) { new_args.Clear(); result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end); result.SetStatus (eReturnStatusFailed); return; } // We have valid range starting & ending breakpoint IDs. Go through all the breakpoints in the // target and find all the breakpoints that fit into this range, and add them to new_args. const BreakpointList& breakpoints = target->GetBreakpointList(); const size_t num_breakpoints = breakpoints.GetSize(); for (size_t j = 0; j < num_breakpoints; ++j) { Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (j).get(); break_id_t cur_bp_id = breakpoint->GetID(); if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id)) continue; const size_t num_locations = breakpoint->GetNumLocations(); if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID)) { for (size_t k = 0; k < num_locations; ++k) { BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); if (bp_loc->GetID() >= start_loc_id) { StreamString canonical_id_str; BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); new_args.AppendArgument (canonical_id_str.GetData()); } } } else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID)) { for (size_t k = 0; k < num_locations; ++k) { BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); if (bp_loc->GetID() <= end_loc_id) { StreamString canonical_id_str; BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); new_args.AppendArgument (canonical_id_str.GetData()); } } } else { StreamString canonical_id_str; BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID); new_args.AppendArgument (canonical_id_str.GetData()); } } } else // else is_range was false { new_args.AppendArgument (current_arg); } } result.SetStatus (eReturnStatusSuccessFinishNoResult); return; }
virtual bool DoExecute (Args& args, CommandReturnObject &result) { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { Error error; if (args.GetArgumentCount() == 0) { if (platform_sp) { Stream &ostrm = result.GetOutputStream(); lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID(); if (pid != LLDB_INVALID_PROCESS_ID) { ProcessInstanceInfo proc_info; if (platform_sp->GetProcessInfo (pid, proc_info)) { ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat ("no process found with pid = %" PRIu64 "\n", pid); result.SetStatus (eReturnStatusFailed); } } else { ProcessInstanceInfoList proc_infos; const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos); const char *match_desc = NULL; const char *match_name = m_options.match_info.GetProcessInfo().GetName(); if (match_name && match_name[0]) { switch (m_options.match_info.GetNameMatchType()) { case eNameMatchIgnore: break; case eNameMatchEquals: match_desc = "matched"; break; case eNameMatchContains: match_desc = "contained"; break; case eNameMatchStartsWith: match_desc = "started with"; break; case eNameMatchEndsWith: match_desc = "ended with"; break; case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break; } } if (matches == 0) { if (match_desc) result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n", match_desc, match_name, platform_sp->GetShortPluginName()); else result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName()); result.SetStatus (eReturnStatusFailed); } else { result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"", matches, matches > 1 ? "es were" : " was", platform_sp->GetName()); if (match_desc) result.AppendMessageWithFormat (" whose name %s \"%s\"", match_desc, match_name); result.AppendMessageWithFormat ("\n"); ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); for (uint32_t i=0; i<matches; ++i) { proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); } } } } } else { result.AppendError ("invalid args: process list takes only options\n"); result.SetStatus (eReturnStatusFailed); } } else { result.AppendError ("no platform is selected\n"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); }
bool DoExecute(Args &command, CommandReturnObject &result) override { m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); }
void ScriptInterpreter::CollectDataForWatchpointCommandCallback( WatchpointOptions *bp_options, CommandReturnObject &result) { result.SetStatus(eReturnStatusFailed); result.AppendError( "ScriptInterpreter::GetScriptCommands(StringList &) is not implemented."); }
bool DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "thread" for validity as eCommandRequiresThread ensures // it is valid Thread *thread = m_exe_ctx.GetThreadPtr(); uint32_t frame_idx = UINT32_MAX; if (m_options.relative_frame_offset != INT32_MIN) { // The one and only argument is a signed relative frame index frame_idx = thread->GetSelectedFrameIndex(); if (frame_idx == UINT32_MAX) frame_idx = 0; if (m_options.relative_frame_offset < 0) { if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset) frame_idx += m_options.relative_frame_offset; else { if (frame_idx == 0) { // If you are already at the bottom of the stack, then just warn and // don't reset the frame. result.AppendError("Already at the bottom of the stack."); result.SetStatus(eReturnStatusFailed); return false; } else frame_idx = 0; } } else if (m_options.relative_frame_offset > 0) { // I don't want "up 20" where "20" takes you past the top of the stack // to produce // an error, but rather to just go to the top. So I have to count the // stack here... const uint32_t num_frames = thread->GetStackFrameCount(); if (static_cast<int32_t>(num_frames - frame_idx) > m_options.relative_frame_offset) frame_idx += m_options.relative_frame_offset; else { if (frame_idx == num_frames - 1) { // If we are already at the top of the stack, just warn and don't // reset the frame. result.AppendError("Already at the top of the stack."); result.SetStatus(eReturnStatusFailed); return false; } else frame_idx = num_frames - 1; } } } else { if (command.GetArgumentCount() == 1) { const char *frame_idx_cstr = command.GetArgumentAtIndex(0); bool success = false; frame_idx = StringConvert::ToUInt32(frame_idx_cstr, UINT32_MAX, 0, &success); if (!success) { result.AppendErrorWithFormat("invalid frame index argument '%s'.", frame_idx_cstr); result.SetStatus(eReturnStatusFailed); return false; } } else if (command.GetArgumentCount() == 0) { frame_idx = thread->GetSelectedFrameIndex(); if (frame_idx == UINT32_MAX) { frame_idx = 0; } } else { result.AppendErrorWithFormat( "too many arguments; expected frame-index, saw '%s'.\n", command.GetArgumentAtIndex(0)); m_options.GenerateOptionUsage( result.GetErrorStream(), this, GetCommandInterpreter().GetDebugger().GetTerminalWidth()); return false; } } bool success = thread->SetSelectedFrameByIndexNoisily( frame_idx, result.GetOutputStream()); if (success) { m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat("Frame index (%u) out of range.\n", frame_idx); result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); }
bool CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) { ConstString target_triple; Process *process = m_exe_ctx.GetProcessPtr(); if (!process) { result.AppendError ("Args found no process."); result.SetStatus (eReturnStatusFailed); return false; } const ABI *abi = process->GetABI().get(); if (!abi) { result.AppendError ("The current process has no ABI."); result.SetStatus (eReturnStatusFailed); return false; } const size_t num_args = args.GetArgumentCount (); size_t arg_index; if (!num_args) { result.AppendError ("args requires at least one argument"); result.SetStatus (eReturnStatusFailed); return false; } Thread *thread = m_exe_ctx.GetThreadPtr(); if (!thread) { result.AppendError ("args found no thread."); result.SetStatus (eReturnStatusFailed); return false; } lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame (); if (!thread_cur_frame) { result.AppendError ("The current thread has no current frame."); result.SetStatus (eReturnStatusFailed); return false; } ModuleSP thread_module_sp (thread_cur_frame->GetFrameCodeAddress ().GetModule()); if (!thread_module_sp) { result.AppendError ("The PC has no associated module."); result.SetStatus (eReturnStatusFailed); return false; } ClangASTContext &ast_context = thread_module_sp->GetClangASTContext(); ValueList value_list; for (arg_index = 0; arg_index < num_args; ++arg_index) { const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index); Value value; value.SetValueType(Value::eValueTypeScalar); void *type; char *int_pos; if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int"))) { Encoding encoding = eEncodingSint; int width = 0; if (int_pos > arg_type_cstr + 1) { result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); result.SetStatus (eReturnStatusFailed); return false; } if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u') { result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); result.SetStatus (eReturnStatusFailed); return false; } if (arg_type_cstr[0] == 'u') { encoding = eEncodingUint; } char *width_pos = int_pos + 3; if (!strcmp (width_pos, "8_t")) width = 8; else if (!strcmp (width_pos, "16_t")) width = 16; else if (!strcmp (width_pos, "32_t")) width = 32; else if (!strcmp (width_pos, "64_t")) width = 64; else { result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); result.SetStatus (eReturnStatusFailed); return false; } type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width); if (!type) { result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n", arg_type_cstr, (encoding == eEncodingSint ? "signed" : "unsigned"), width); result.SetStatus (eReturnStatusFailed); return false; } } else if (strchr (arg_type_cstr, '*')) { if (!strcmp (arg_type_cstr, "void*")) type = ast_context.CreatePointerType (ast_context.GetBuiltInType_void ()); else if (!strcmp (arg_type_cstr, "char*")) type = ast_context.GetCStringType (false); else { result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); result.SetStatus (eReturnStatusFailed); return false; } } else { result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); result.SetStatus (eReturnStatusFailed); return false; } value.SetContext (Value::eContextTypeClangType, type); value_list.PushValue(value); } if (!abi->GetArgumentValues (*thread, value_list)) { result.AppendError ("Couldn't get argument values"); result.SetStatus (eReturnStatusFailed); return false; } result.GetOutputStream ().Printf("Arguments : \n"); for (arg_index = 0; arg_index < num_args; ++arg_index) { result.GetOutputStream ().Printf ("%zu (%s): ", arg_index, args.GetArgumentAtIndex (arg_index)); value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ()); result.GetOutputStream ().Printf("\n"); } return result.Succeeded(); }
bool DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "frame" for validity as eCommandRequiresFrame ensures it // is valid StackFrame *frame = m_exe_ctx.GetFramePtr(); Stream &s = result.GetOutputStream(); // Be careful about the stack frame, if any summary formatter runs code, it // might clear the StackFrameList // for the thread. So hold onto a shared pointer to the frame so it stays // alive. VariableList *variable_list = frame->GetVariableList(m_option_variable.show_globals); VariableSP var_sp; ValueObjectSP valobj_sp; const char *name_cstr = nullptr; size_t idx; TypeSummaryImplSP summary_format_sp; if (!m_option_variable.summary.IsCurrentValueEmpty()) DataVisualization::NamedSummaryFormats::GetSummaryFormat( ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp); else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) summary_format_sp.reset(new StringSummaryFormat( TypeSummaryImpl::Flags(), m_option_variable.summary_string.GetCurrentValue())); DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault, summary_format_sp)); const SymbolContext &sym_ctx = frame->GetSymbolContext(eSymbolContextFunction); if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) m_option_variable.show_globals = true; if (variable_list) { const Format format = m_option_format.GetFormat(); options.SetFormat(format); if (!command.empty()) { VariableList regex_var_list; // If we have any args to the variable command, we will make // variable objects from them... for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != nullptr; ++idx) { if (m_option_variable.use_regex) { const size_t regex_start_index = regex_var_list.GetSize(); llvm::StringRef name_str(name_cstr); RegularExpression regex(name_str); if (regex.Compile(name_str)) { size_t num_matches = 0; const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, num_matches); if (num_new_regex_vars > 0) { for (size_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); regex_idx < end_index; ++regex_idx) { var_sp = regex_var_list.GetVariableAtIndex(regex_idx); if (var_sp) { valobj_sp = frame->GetValueObjectForFrameVariable( var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format // != // eFormatDefault) // valobj_sp->SetFormat // (format); std::string scope_string; if (m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (!scope_string.empty()) s.PutCString(scope_string); if (m_option_variable.show_decl && var_sp->GetDeclaration().GetFile()) { bool show_fullpaths = false; bool show_module = true; if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString(": "); } valobj_sp->Dump(result.GetOutputStream(), options); } } } } else if (num_matches == 0) { result.GetErrorStream().Printf("error: no variables matched " "the regular expression '%s'.\n", name_cstr); } } else { char regex_error[1024]; if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) result.GetErrorStream().Printf("error: %s\n", regex_error); else result.GetErrorStream().Printf( "error: unknown regex error when compiling '%s'\n", name_cstr); } } else // No regex, either exact variable names or variable // expressions. { Error error; uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess | StackFrame::eExpressionPathOptionsInspectAnonymousUnions; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath( name_cstr, m_varobj_options.use_dynamic, expr_path_options, var_sp, error); if (valobj_sp) { std::string scope_string; if (m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (!scope_string.empty()) s.PutCString(scope_string); // if (format != eFormatDefault) // valobj_sp->SetFormat (format); if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration().GetFile()) { var_sp->GetDeclaration().DumpStopContext(&s, false); s.PutCString(": "); } options.SetFormat(format); options.SetVariableFormatDisplayLanguage( valobj_sp->GetPreferredDisplayLanguage()); Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : nullptr); valobj_sp->Dump(output_stream, options); } else { const char *error_cstr = error.AsCString(nullptr); if (error_cstr) result.GetErrorStream().Printf("error: %s\n", error_cstr); else result.GetErrorStream().Printf("error: unable to find any " "variable expression path that " "matches '%s'.\n", name_cstr); } } } } else // No command arg specified. Use variable_list, instead. { const size_t num_variables = variable_list->GetSize(); if (num_variables > 0) { for (size_t i = 0; i < num_variables; i++) { var_sp = variable_list->GetVariableAtIndex(i); bool dump_variable = true; std::string scope_string; if (dump_variable && m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (dump_variable) { // Use the variable object code to make sure we are // using the same APIs as the public API will be // using... valobj_sp = frame->GetValueObjectForFrameVariable( var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat // (format); // When dumping all variables, don't print any variables // that are not in scope to avoid extra unneeded output if (valobj_sp->IsInScope()) { if (!valobj_sp->GetTargetSP() ->GetDisplayRuntimeSupportValues() && valobj_sp->IsRuntimeSupportValue()) continue; if (!scope_string.empty()) s.PutCString(scope_string); if (m_option_variable.show_decl && var_sp->GetDeclaration().GetFile()) { var_sp->GetDeclaration().DumpStopContext(&s, false); s.PutCString(": "); } options.SetFormat(format); options.SetVariableFormatDisplayLanguage( valobj_sp->GetPreferredDisplayLanguage()); options.SetRootValueObjectName(name_cstr); valobj_sp->Dump(result.GetOutputStream(), options); } } } } } } result.SetStatus(eReturnStatusSuccessFinishResult); } if (m_interpreter.TruncationWarningNecessary()) { result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), m_cmd_name.c_str()); m_interpreter.TruncationWarningGiven(); } return result.Succeeded(); }
virtual bool DoExecute (Args& args, CommandReturnObject &result) { const size_t argc = args.GetArgumentCount(); result.SetStatus(eReturnStatusFailed); if (argc == 1) { const char *sub_command = args.GetArgumentAtIndex(0); if (strcasecmp(sub_command, "enable") == 0) { Timer::SetDisplayDepth (UINT32_MAX); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else if (strcasecmp(sub_command, "disable") == 0) { Timer::DumpCategoryTimes (&result.GetOutputStream()); Timer::SetDisplayDepth (0); result.SetStatus(eReturnStatusSuccessFinishResult); } else if (strcasecmp(sub_command, "dump") == 0) { Timer::DumpCategoryTimes (&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); } else if (strcasecmp(sub_command, "reset") == 0) { Timer::ResetCategoryTimes (); result.SetStatus(eReturnStatusSuccessFinishResult); } } else if (argc == 2) { const char *sub_command = args.GetArgumentAtIndex(0); if (strcasecmp(sub_command, "enable") == 0) { bool success; uint32_t depth = StringConvert::ToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success); if (success) { Timer::SetDisplayDepth (depth); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else result.AppendError("Could not convert enable depth to an unsigned integer."); } if (strcasecmp(sub_command, "increment") == 0) { bool success; bool increment = Args::StringToBoolean(args.GetArgumentAtIndex(1), false, &success); if (success) { Timer::SetQuiet (!increment); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else result.AppendError("Could not convert increment value to boolean."); } } if (!result.Succeeded()) { result.AppendError("Missing subcommand"); result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str()); } return result.Succeeded(); }
virtual bool Execute (Args& command, CommandReturnObject &result) { Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; if (process == NULL) { result.AppendError("need a process to read memory"); result.SetStatus(eReturnStatusFailed); return false; } const size_t argc = command.GetArgumentCount(); if (argc == 0 || argc > 2) { result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } size_t item_byte_size = m_options.m_byte_size; if (item_byte_size == 0) { if (m_options.m_format == eFormatPointer) item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize(); else item_byte_size = 1; } size_t item_count = m_options.m_count; size_t num_per_line = m_options.m_num_per_line; if (num_per_line == 0) { num_per_line = (16/item_byte_size); if (num_per_line == 0) num_per_line = 1; } size_t total_byte_size = m_options.m_count * item_byte_size; if (total_byte_size == 0) total_byte_size = 32; lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); if (addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); result.SetStatus(eReturnStatusFailed); return false; } if (argc == 2) { lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); result.SetStatus(eReturnStatusFailed); return false; } else if (end_addr <= addr) { result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); result.SetStatus(eReturnStatusFailed); return false; } else if (item_count != 0) { result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count); result.SetStatus(eReturnStatusFailed); return false; } total_byte_size = end_addr - addr; item_count = total_byte_size / item_byte_size; } else { if (item_count == 0) item_count = 32; } DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0')); Error error; size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error); if (bytes_read == 0) { result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr); result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } if (bytes_read < total_byte_size) result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); result.SetStatus(eReturnStatusSuccessFinishResult); DataExtractor data (data_sp, process->GetTarget().GetArchitecture().GetByteOrder(), process->GetTarget().GetArchitecture().GetAddressByteSize()); StreamFile outfile_stream; Stream *output_stream = NULL; if (m_options.m_outfile_filespec) { char path[PATH_MAX]; m_options.m_outfile_filespec.GetPath (path, sizeof(path)); char mode[16] = { 'w', '\0' }; if (m_options.m_append_to_outfile) mode[0] = 'a'; if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) { if (m_options.m_output_as_binary) { int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); if (bytes_written > 0) { result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", bytes_written, m_options.m_append_to_outfile ? "appended" : "written", path); return true; } else { result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path); result.SetStatus(eReturnStatusFailed); return false; } } else { // We are going to write ASCII to the file just point the // output_stream to our outfile_stream... output_stream = &outfile_stream; } } else { result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode); result.SetStatus(eReturnStatusFailed); return false; } } else { output_stream = &result.GetOutputStream(); } assert (output_stream); data.Dump (output_stream, 0, m_options.m_format, item_byte_size, item_count, num_per_line, addr, 0, 0); output_stream->EOL(); return true; }