void handle_attach_to_pid (GDBRemoteCommunicationServerLLGS &gdb_server, lldb::pid_t pid) { Error error = gdb_server.AttachToProcess (pid); if (error.Fail ()) { fprintf (stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid, error.AsCString()); exit(1); } }
Error PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode) { Error error = m_gdb_client.MakeDirectory(file_spec, mode); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); if (log) log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)", file_spec.GetCString(), mode, error.GetError(), error.AsCString()); return error; }
Error PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { Error error = m_gdb_client.Unlink(file_spec); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); if (log) log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", file_spec.GetCString(), error.GetError(), error.AsCString()); return error; }
Error PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) { Error error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); if (log) log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString()); return error; }
lldb::ExpressionResults GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); Target *target = exe_ctx.GetTargetPtr(); if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [GoUserExpression::Evaluate] Expression may not run, " "but is not constant =="); diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression needed to run but couldn't"); return execution_results; } } m_interpreter->set_use_dynamic(options.GetUseDynamic()); ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx); Error err = m_interpreter->error(); m_interpreter.reset(); if (!result_val_sp) { const char *error_cstr = err.AsCString(); if (error_cstr && error_cstr[0]) diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); return lldb::eExpressionDiscarded; } result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); result->m_live_sp = result->m_frozen_sp = result_val_sp; result->m_flags |= ExpressionVariable::EVIsProgramReference; PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo); if (pv != nullptr) { result->SetName(pv->GetNextPersistentVariableName()); pv->AddVariable(result); } return lldb::eExpressionCompleted; }
size_t GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec) { uint8_t buffer[8192]; Error error; Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE)); // Check for a packet from our cache first without trying any reading... if (CheckForPacket (NULL, 0, packet)) return packet.GetStringRef().size(); bool timed_out = false; while (IsConnected() && !timed_out) { lldb::ConnectionStatus status = eConnectionStatusNoConnection; size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); if (log) log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, __PRETTY_FUNCTION__, timeout_usec, Communication::ConnectionStatusAsCString (status), error.AsCString(), (uint64_t)bytes_read); if (bytes_read > 0) { if (CheckForPacket (buffer, bytes_read, packet)) return packet.GetStringRef().size(); } else { switch (status) { case eConnectionStatusTimedOut: timed_out = true; break; case eConnectionStatusSuccess: //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); break; case eConnectionStatusEndOfFile: case eConnectionStatusNoConnection: case eConnectionStatusLostConnection: case eConnectionStatusError: Disconnect(); break; } } } packet.Clear (); return 0; }
Error PlatformRemoteGDBServer::CreateSymlink(const FileSpec &src, // The name of the link is in src const FileSpec &dst) // The symlink points to dst { Error error = m_gdb_client.CreateSymlink(src, dst); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); if (log) log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)", src.GetCString(), dst.GetCString(), error.GetError(), error.AsCString()); return error; }
Error ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid, const ProcessAttachInfo &attach_info) { m_session_data.reset(new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); DebuggerThreadSP debugger(new DebuggerThread(delegate)); m_session_data->m_debugger = debugger; DWORD process_id = static_cast<DWORD>(pid); Error error = debugger->DebugAttach(process_id, attach_info); if (error.Fail()) { WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an error occurred initiating the asynchronous attach. %s", error.AsCString()); return error; } HostProcess process; error = WaitForDebuggerConnection(debugger, process); if (error.Fail()) { WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an error waiting for the debugger to connect. %s", error.AsCString()); return error; } WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID successfully attached to process with pid=%u", process_id); // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the private state // should already be set to eStateStopped as a result of hitting the initial breakpoint. If // it was not set, the breakpoint should have already been resumed from and the private state // should already be eStateRunning. SetID(process.GetProcessId()); return error; }
lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess( ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use // existing one Error &error) { lldb::ProcessSP process_sp; if (IsRemote()) { if (IsConnected()) { lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string connect_url; if (!LaunchGDBServer(debugserver_pid, connect_url)) { error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", GetHostname()); } else { if (target == NULL) { TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget( debugger, NULL, NULL, false, NULL, new_target_sp); target = new_target_sp.get(); } else error.Clear(); if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); // The darwin always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! process_sp = target->CreateProcess( launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL); if (process_sp) { error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); // Retry the connect remote one time... if (error.Fail()) error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); if (error.Success()) error = process_sp->Launch(launch_info); else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) { printf("error: connect remote failed (%s)\n", error.AsCString()); KillSpawnedProcess(debugserver_pid); } } } } } else { error.SetErrorString("not connected to remote gdb server"); } } return process_sp; }
Error OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef name, llvm::StringRef value) { Error error; const bool will_modify = true; lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error)); if (value_sp) error = value_sp->SetValueFromString(value, op); else { if (error.AsCString() == nullptr) error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str()); } return error; }
Error ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) { WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite called with bp_site 0x%p " "(id=%d, addr=0x%x)", bp_site->GetID(), bp_site->GetLoadAddress()); Error error = EnableSoftwareBreakpoint(bp_site); if (!error.Success()) { WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", error.AsCString()); } return error; }
size_t Disassembler::ParseInstructions (const ExecutionContext *exe_ctx, const AddressRange &range, Stream *error_strm_ptr, bool prefer_file_cache) { if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); const addr_t byte_size = range.GetByteSize(); if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid()) return 0; DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); DataBufferSP data_sp(heap_buffer); Error error; lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), prefer_file_cache, heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error, &load_addr); if (bytes_read > 0) { if (bytes_read != heap_buffer->GetByteSize()) heap_buffer->SetByteSize (bytes_read); DataExtractor data (data_sp, m_arch.GetByteOrder(), m_arch.GetAddressByteSize()); const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false, data_from_file); } else if (error_strm_ptr) { const char *error_cstr = error.AsCString(); if (error_cstr) { error_strm_ptr->Printf("error: %s\n", error_cstr); } } } else if (error_strm_ptr) { error_strm_ptr->PutCString("error: invalid execution context\n"); } return 0; }
Error MachException::Message::Receive(mach_port_t port, mach_msg_option_t options, mach_msg_timeout_t timeout, mach_port_t notify_port) { Error error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); mach_msg_timeout_t mach_msg_timeout = options & MACH_RCV_TIMEOUT ? timeout : 0; if (log && ((options & MACH_RCV_TIMEOUT) == 0)) { // Dump this log message if we have no timeout in case it never returns log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " "local_port = %#x, reserved = 0x%x, id = 0x%x}, " "option = %#x, send_size = 0, rcv_size = %llu, " "rcv_name = %#x, timeout = %u, notify = %#x)", exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout, notify_port); } mach_msg_return_t mach_err = ::mach_msg(&exc_msg.hdr, options, // options 0, // Send size sizeof(exc_msg.data), // Receive size port, // exception port to watch for // exception on mach_msg_timeout, // timeout in msec (obeyed only // if MACH_RCV_TIMEOUT is ORed // into the options parameter) notify_port); error.SetError(mach_err, eErrorTypeMachKernel); // Dump any errors we get if (error.Fail() && log) { log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " "local_port = %#x, reserved = 0x%x, id = 0x%x}, " "option = %#x, send_size = %u, rcv_size = %lu, rcv_name " "= %#x, timeout = %u, notify = %#x) failed: %s", exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, sizeof(exc_msg.data), port, mach_msg_timeout, notify_port, error.AsCString()); } return error; }
bool CommandObject::ParseOptions ( Args& args, CommandReturnObject &result ) { // See if the subclass has options? Options *options = GetOptions(); if (options != NULL) { Error error; options->NotifyOptionParsingStarting(); // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1, // so we need to push a dummy value into position zero. args.Unshift("dummy_string"); error = args.ParseOptions (*options); // The "dummy_string" will have already been removed by ParseOptions, // so no need to remove it. if (error.Success()) error = options->NotifyOptionParsingFinished(); if (error.Success()) { if (options->VerifyOptions (result)) return true; } else { const char *error_cstr = error.AsCString(); if (error_cstr) { // We got an error string, lets use that result.AppendError(error_cstr); } else { // No error string, output the usage information into result options->GenerateOptionUsage (result.GetErrorStream(), this); } } result.SetStatus (eReturnStatusFailed); return false; } return true; }
void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) { llvm::sys::ScopedLock lock(m_mutex); if (m_session_data->m_initial_stop_received) { // This happened while debugging. Do we shutdown the debugging session, try to continue, // or do something else? WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. Unexpected behavior may result. %s", error.GetError(), error.AsCString()); } else { // If we haven't actually launched the process yet, this was an error launching the // process. Set the internal error and signal the initial stop event so that the DoLaunch // method wakes up and returns a failure. m_session_data->m_launch_error = error; ::SetEvent(m_session_data->m_initial_stop_event); WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred launching the process before the initial stop. %s", error.GetError(), error.AsCString()); return; } }
Error OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOperationType op, const char *name, const char *value) { Error error; const bool will_modify = true; lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); if (value_sp) error = value_sp->SetValueFromString(value, op); else { if (error.AsCString() == nullptr) error.SetErrorStringWithFormat("invalid value path '%s'", name); } return error; }
Error DebuggerThread::DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info) { WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid); Error error; DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, context, &error)); if (!error.Success()) { WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid, error.AsCString()); } return error; }
Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread::DebugLaunch launching '%s'", launch_info.GetExecutableFile().GetPath().c_str()); Error error; DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, context, &error)); if (!error.Success()) { WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugLaunch couldn't launch debugger thread. %s", error.AsCString()); } return error; }
Error Socket::Write (const void *buf, size_t &num_bytes) { Error error; int bytes_sent = 0; do { if (m_protocol == ProtocolUdp) { bytes_sent = ::sendto (m_socket, static_cast<const char*>(buf), num_bytes, 0, m_udp_send_sockaddr, m_udp_send_sockaddr.GetLength()); } else bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0); } while (bytes_sent < 0 && IsInterrupted ()); if (bytes_sent < 0) { SetLastError (error); num_bytes = 0; } else num_bytes = bytes_sent; Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); if (log) { log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)", static_cast<void*>(this), static_cast<uint64_t>(m_socket), buf, static_cast<uint64_t>(num_bytes), static_cast<int64_t>(bytes_sent), error.AsCString()); } return error; }
void ConnectionFileDescriptor::OpenCommandPipe() { CloseCommandPipe(); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); // Make the command file descriptor here: Error result = m_pipe.CreateNew(m_child_processes_inherit); if (!result.Success()) { if (log) log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast<void *>(this), result.AsCString()); } else { if (log) log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast<void *>(this), m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor()); } }
Error MachException::PortInfo::Restore(task_t task) { Error error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) log->Printf("MachException::PortInfo::Restore(task = 0x%4.4x)", task); uint32_t i = 0; if (count > 0) { for (i = 0; i < count; i++) { auto mach_err = ::task_set_exception_ports(task, masks[i], ports[i], behaviors[i], flavors[i]); if (mach_err) error.SetError(mach_err, eErrorTypeMachKernel); if (log) { if (error.Success()) { log->Printf("::task_set_exception_ports(task = 0x%4.4x, " "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " "behavior = 0x%8.8x, new_flavor = 0x%8.8x)", task, masks[i], ports[i], behaviors[i], flavors[i]); } else { log->Printf("::task_set_exception_ports(task = 0x%4.4x, " "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " "behavior = 0x%8.8x, new_flavor = 0x%8.8x): " "error %u (%s)", task, masks[i], ports[i], behaviors[i], flavors[i], error.GetError(), error.AsCString()); } } // Bail if we encounter any errors if (error.Fail()) break; } } count = 0; return error; }
ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid, Error &error) { const auto lock_dir_spec = JoinPath(root_dir_spec, kLockDirName); error = MakeDirectory(lock_dir_spec); if (error.Fail()) return; m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str()); m_file.Open(m_file_spec.GetCString(), File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec); if (!m_file) { error.SetErrorToErrno(); return; } m_lock.reset(new lldb_private::LockFile(m_file.GetDescriptor())); error = m_lock->WriteLock(0, 1); if (error.Fail()) error.SetErrorStringWithFormat("Failed to lock file: %s", error.AsCString()); }
virtual bool DoExecute (const char *raw_command_line, CommandReturnObject &result) { // TODO: Implement "Platform::RunShellCommand()" and switch over to using // the current platform when it is in the interface. const char *working_dir = NULL; std::string output; int status = -1; int signo = -1; Error error (Host::RunShellCommand (raw_command_line, working_dir, &status, &signo, &output, 10)); if (!output.empty()) result.GetOutputStream().PutCString(output.c_str()); if (status > 0) { if (signo > 0) { const char *signo_cstr = Host::GetSignalAsCString(signo); if (signo_cstr) result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); else result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); } else result.GetOutputStream().Printf("error: command returned with status %i\n", status); } if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus (eReturnStatusFailed); } else { result.SetStatus (eReturnStatusSuccessFinishResult); } return true; }
virtual bool DoExecute (Args& args, CommandReturnObject &result) { if (args.GetArgumentCount() == 1) { const char *platform_name = args.GetArgumentAtIndex (0); if (platform_name && platform_name[0]) { const bool select = true; m_platform_options.SetPlatformName (platform_name); Error error; ArchSpec platform_arch; PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch)); if (platform_sp) { platform_sp->GetStatus (result.GetOutputStream()); result.SetStatus (eReturnStatusSuccessFinishResult); } else { result.AppendError(error.AsCString()); result.SetStatus (eReturnStatusFailed); } } else { result.AppendError ("invalid platform name"); result.SetStatus (eReturnStatusFailed); } } else { result.AppendError ("platform create takes a platform name as an argument\n"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); }
SBStringList SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger_instance_name) { SBStringList ret_value; SettableVariableType var_type; Error err; UserSettingsControllerSP root_settings_controller = Debugger::GetSettingsController(); StringList value = root_settings_controller->GetVariable (var_name, var_type, debugger_instance_name, err); if (err.Success()) { for (unsigned i = 0; i != value.GetSize(); ++i) ret_value.AppendString (value.GetStringAtIndex(i)); } else { ret_value.AppendString (err.AsCString()); } return ret_value; }
bool ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; InstallContext(exe_ctx); ScanContext(exe_ctx, err); if (!err.Success()) { error_stream.Printf("warning: %s\n", err.AsCString()); } StreamString m_transformed_stream; //////////////////////////////////// // Generate the expression // ApplyObjcCastHack(m_expr_text); //ApplyUnicharHack(m_expr_text); std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str())); lldb::LanguageType lang_type; if (m_cplusplus) lang_type = lldb::eLanguageTypeC_plus_plus; else if(m_objectivec) lang_type = lldb::eLanguageTypeObjC; else lang_type = lldb::eLanguageTypeC; if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method, exe_ctx)) { error_stream.PutCString ("error: couldn't construct expression body"); return false; } if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { error_stream.PutCString ("error: invalid target\n"); return false; } ////////////////////////// // Parse the expression // m_materializer_ap.reset(new Materializer()); m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); class OnExit { public: typedef std::function <void (void)> Callback; OnExit (Callback const &callback) : m_callback(callback) { } ~OnExit () { m_callback(); } private: Callback m_callback; }; OnExit on_exit([this]() { m_expr_decl_map.reset(); }); if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get())) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. return false; } Process *process = exe_ctx.GetProcessPtr(); ExecutionContextScope *exe_scope = process; if (!exe_scope) exe_scope = exe_ctx.GetTargetPtr(); ClangExpressionParser parser(exe_scope, *this, generate_debug_info); unsigned num_errors = parser.Parse (error_stream); if (num_errors) { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. return false; } ////////////////////////////////////////////////////////////////////////////////////////// // Prepare the output of the parser for execution, evaluating it statically if possible // Error jit_error = parser.PrepareForExecution (m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, m_can_interpret, execution_policy); if (generate_debug_info) { lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); if (jit_module_sp) { ConstString const_func_name(FunctionName()); FileSpec jit_file; jit_file.GetFilename() = const_func_name; jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); m_jit_module_wp = jit_module_sp; target->GetImages().Append(jit_module_sp); } // lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile(); // StreamFile strm (stdout, false); // if (jit_obj_file) // { // jit_obj_file->GetSectionList(); // jit_obj_file->GetSymtab(); // jit_obj_file->Dump(&strm); // } // lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor(); // if (jit_sym_vendor) // { // lldb_private::SymbolContextList sc_list; // jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list); // sc_list.Dump(&strm, target); // jit_sym_vendor->Dump(&strm); // } } m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. if (jit_error.Success()) { if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) error_stream.Printf ("error: %s\n", error_cstr); else error_stream.Printf ("error: expression can't be interpreted or run\n"); return false; } }
/// Locates the address of the rendezvous structure. Returns the address on /// success and LLDB_INVALID_ADDRESS on failure. static addr_t ResolveRendezvousAddress(Process *process) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); addr_t info_location; addr_t info_addr; Error error; if (!process) { if (log) log->Printf ("%s null process provided", __FUNCTION__); return LLDB_INVALID_ADDRESS; } // Try to get it from our process. This might be a remote process and might // grab it via some remote-specific mechanism. info_location = process->GetImageInfoAddress(); if (log) log->Printf ("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); // If the process fails to return an address, fall back to seeing if the local object file can help us find it. if (info_location == LLDB_INVALID_ADDRESS) { Target *target = &process->GetTarget(); if (target) { ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); Address addr = obj_file->GetImageInfoAddress(target); if (addr.IsValid()) { info_location = addr.GetLoadAddress(target); if (log) log->Printf ("%s resolved via direct object file approach to 0x%" PRIx64, __FUNCTION__, info_location); } else { if (log) log->Printf ("%s FAILED - direct object file approach did not yield a valid address", __FUNCTION__); } } } if (info_location == LLDB_INVALID_ADDRESS) { if (log) log->Printf ("%s FAILED - invalid info address", __FUNCTION__); return LLDB_INVALID_ADDRESS; } if (log) log->Printf ("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, __FUNCTION__, process->GetAddressByteSize(), info_location); info_addr = process->ReadPointerFromMemory(info_location, error); if (error.Fail()) { if (log) log->Printf ("%s FAILED - could not read from the info location: %s", __FUNCTION__, error.AsCString ()); return LLDB_INVALID_ADDRESS; } if (info_addr == 0) { if (log) log->Printf ("%s FAILED - the rendezvous address contained at 0x%" PRIx64 " returned a null value", __FUNCTION__, info_location); return LLDB_INVALID_ADDRESS; } return info_addr; }
Error IRExecutionUnit::DisassembleFunction (Stream &stream, lldb::ProcessSP &process_wp) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); ExecutionContext exe_ctx(process_wp); Error ret; ret.Clear(); lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; for (JittedFunction &function : m_jitted_functions) { if (strstr(function.m_name.c_str(), m_name.AsCString())) { func_local_addr = function.m_local_addr; func_remote_addr = function.m_remote_addr; } } if (func_local_addr == LLDB_INVALID_ADDRESS) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString()); return ret; } if (log) log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair <lldb::addr_t, lldb::addr_t> func_range; func_range = GetRemoteRangeForLocal(func_local_addr); if (func_range.first == 0 && func_range.second == 0) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString()); return ret; } if (log) log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second); Target *target = exe_ctx.GetTargetPtr(); if (!target) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the target"); return ret; } lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); Process *process = exe_ctx.GetProcessPtr(); Error err; process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); if (!err.Success()) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); return ret; } ArchSpec arch(target->GetArchitecture()); const char *plugin_name = NULL; const char *flavor_string = NULL; lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name); if (!disassembler_sp) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName()); return ret; } if (!process) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the process"); return ret; } DataExtractor extractor(buffer_sp, process->GetByteOrder(), target->GetArchitecture().GetAddressByteSize()); if (log) { log->Printf("Function data has contents:"); extractor.PutToLog (log, 0, extractor.GetByteSize(), func_remote_addr, 16, DataExtractor::TypeUInt8); } disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false); InstructionList &instruction_list = disassembler_sp->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); const char *disassemble_format = "${addr-file-or-load}: "; if (exe_ctx.HasTargetScope()) { disassemble_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); } for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize(); instruction_index < num_instructions; ++instruction_index) { Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get(); instruction->Dump (&stream, max_opcode_byte_size, true, true, &exe_ctx, NULL, NULL, disassemble_format); stream.PutChar('\n'); } // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. // I'll fix that but for now, just clear the list and it will go away nicely. disassembler_sp->GetInstructionList().Clear(); return ret; }
void IRExecutionUnit::GetRunnableInfo(Error &error, lldb::addr_t &func_addr, lldb::addr_t &func_end) { lldb::ProcessSP process_sp(GetProcessWP().lock()); static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive); func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; if (!process_sp) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid"); return; } if (m_did_jit) { func_addr = m_function_load_addr; func_end = m_function_end_load_addr; return; }; Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex); m_did_jit = true; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); std::string error_string; if (log) { std::string s; llvm::raw_string_ostream oss(s); m_module->print(oss, NULL); oss.flush(); log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } llvm::Triple triple(m_module->getTargetTriple()); llvm::Function *function = m_module->getFunction (m_name.AsCString()); llvm::Reloc::Model relocModel; llvm::CodeModel::Model codeModel; if (triple.isOSBinFormatELF()) { relocModel = llvm::Reloc::Static; // This will be small for 32-bit and large for 64-bit. codeModel = llvm::CodeModel::JITDefault; } else { relocModel = llvm::Reloc::PIC_; codeModel = llvm::CodeModel::Small; } m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error); llvm::EngineBuilder builder(std::move(m_module_ap)); builder.setEngineKind(llvm::EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(relocModel) .setMCJITMemoryManager(std::unique_ptr<MemoryManager>(new MemoryManager(*this))) .setCodeModel(codeModel) .setOptLevel(llvm::CodeGenOpt::Less); llvm::StringRef mArch; llvm::StringRef mCPU; llvm::SmallVector<std::string, 0> mAttrs; for (std::string &feature : m_cpu_features) mAttrs.push_back(feature); llvm::TargetMachine *target_machine = builder.selectTarget(triple, mArch, mCPU, mAttrs); m_execution_engine_ap.reset(builder.create(target_machine)); if (!m_execution_engine_ap.get()) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return; } // Make sure we see all sections, including ones that don't have relocations... m_execution_engine_ap->setProcessAllSections(true); m_execution_engine_ap->DisableLazyCompilation(); // We don't actually need the function pointer here, this just forces it to get resolved. void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function); if (!error.Success()) { // We got an error through our callback! return; } if (!function) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString()); return; } if (!fun_ptr) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString()); return; } m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr)); CommitAllocations(process_sp); ReportAllocations(*m_execution_engine_ap); WriteData(process_sp); for (JittedFunction &jitted_function : m_jitted_functions) { jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr); if (!jitted_function.m_name.compare(m_name.AsCString())) { AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr); m_function_end_load_addr = func_range.first + func_range.second; m_function_load_addr = jitted_function.m_remote_addr; } } if (log) { log->Printf("Code can be run in the target."); StreamString disassembly_stream; Error err = DisassembleFunction(disassembly_stream, process_sp); if (!err.Success()) { log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); } else { log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); } log->Printf("Sections: "); for (AllocationRecord &record : m_records) { if (record.m_process_address != LLDB_INVALID_ADDRESS) { record.dump(log); DataBufferHeap my_buffer(record.m_size, 0); Error err; ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err); if (err.Success()) { DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8); my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8); } } } } func_addr = m_function_load_addr; func_end = m_function_end_load_addr; return; }
lldb::REPLSP SwiftREPL::CreateInstance (Error &err, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options) { if (language != eLanguageTypeSwift) { return lldb::REPLSP(); } if (target) { // Sanity check the target to make sure a REPL would work here. if (!target->GetProcessSP() || !target->GetProcessSP()->IsAlive()) { err.SetErrorString ("can't launch a Swift REPL without a running process"); return lldb::REPLSP(); } SymbolContextList sc_list; target->GetImages().FindSymbolsWithNameAndType(ConstString("_swift_release"), eSymbolTypeAny, sc_list); if (!sc_list.GetSize()) { err.SetErrorString ("can't launch a Swift REPL in a process that doesn't have the Swift standard library"); return lldb::REPLSP(); } // Sanity checks succeeded. Go ahead. SwiftREPL *repl = new SwiftREPL(*target); REPLSP repl_sp(repl); repl->SetCompilerOptions(repl_options); return repl_sp; } else if (debugger) { const char *bp_name = "repl_main"; FileSpec repl_executable; if (HostInfo::GetLLDBPath (ePathTypeSupportExecutableDir, repl_executable)) { repl_executable.GetFilename().SetCString("repl_swift"); std::string repl_exe_path(repl_executable.GetPath()); if (repl_executable.Exists()) { const char *target_triple = NULL; bool add_dependent_modules = true; TargetSP target_sp; err = debugger->GetTargetList().CreateTarget (*debugger, repl_exe_path.c_str(), target_triple, add_dependent_modules, NULL, target_sp); if (err.Success()) { // Limit the breakpoint to our executable module FileSpecList containingModules; ModuleSP exe_module_sp (target_sp->GetExecutableModule()); if (exe_module_sp) { FileSpec exe_spec(exe_module_sp->GetFileSpec()); containingModules.Append(exe_spec); BreakpointSP main_bp_sp = target_sp->CreateBreakpoint (&containingModules, // Limit to these modules NULL, // Don't limit the breakpoint to any source files bp_name, // Function name eFunctionNameTypeAuto, // Name type eLanguageTypeUnknown, // Language 0, // offset eLazyBoolYes, // skip_prologue, true, // internal false); // request_hardware if (main_bp_sp->GetNumLocations() > 0) { main_bp_sp->SetBreakpointKind("REPL"); assert (main_bp_sp->IsInternal()); // We made an internal breakpoint above, it better say it is internal lldb_private::ProcessLaunchInfo launch_info; const char *target_settings_argv0 = target_sp->GetArg0(); if (target_sp->GetDisableASLR()) launch_info.GetFlags().Set (eLaunchFlagDisableASLR); if (target_sp->GetDisableSTDIO()) launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); if (target_settings_argv0) { launch_info.GetArguments().AppendArgument (target_settings_argv0); launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false); } else { launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true); } debugger->SetAsyncExecution(false); err = target_sp->Launch(launch_info, nullptr); debugger->SetAsyncExecution(true); if (err.Success()) { ProcessSP process_sp (target_sp->GetProcessSP()); if (process_sp) { // Start handling process events automatically debugger->StartEventHandlerThread(); StateType state = process_sp->GetState(); if (state == eStateStopped) { ThreadList &thread_list = process_sp->GetThreadList(); const uint32_t num_threads = thread_list.GetSize(); if (num_threads > 0) { ThreadSP thread_sp = thread_list.GetSelectedThread(); if (!thread_sp) { thread_sp = thread_list.GetThreadAtIndex(0); thread_list.SetSelectedThreadByID(thread_sp->GetID()); } if (thread_sp) { thread_sp->SetSelectedFrameByIndex(0); std::string swift_full_version(swift::version::getSwiftFullVersion()); printf ("Welcome to %s. Type :help for assistance.\n", swift_full_version.c_str()); REPLSP repl_sp(new SwiftREPL(*target_sp)); ((SwiftREPL*)repl_sp.get())->SetCompilerOptions(repl_options); target_sp->SetREPL(lldb::eLanguageTypeSwift, repl_sp); return repl_sp; } } else { err.SetErrorString ("process is not in valid state (no threads)"); } } else { err.SetErrorString ("failed to stop process at REPL breakpoint"); } process_sp->Destroy(false); debugger->StopEventHandlerThread(); } else { err.SetErrorString ("failed to launch REPL process"); } } else { err.SetErrorStringWithFormat ("failed to launch REPL process: %s", err.AsCString()); } } else { err.SetErrorStringWithFormat ("failed to resolve REPL breakpoint for '%s'", bp_name); } } else { err.SetErrorString ("unable to resolve REPL executable module"); target_sp->Destroy(); } } else { err.SetErrorStringWithFormat ("failed to create REPL target: %s", err.AsCString()); } } else { err.SetErrorStringWithFormat ("REPL executable does not exist: '%s'", repl_exe_path.c_str()); } } else { err.SetErrorString ("unable to locate REPL executable"); } return lldb::REPLSP(); } else { err.SetErrorString ("must have a debugger or a target to create a REPL"); return lldb::REPLSP(); } }