Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, lldb::addr_t &func_addr, lldb::addr_t &func_end, ExecutionContext &exe_ctx, IRForTarget::StaticDataAllocator *data_allocator, bool &evaluated_statically, lldb::ClangExpressionVariableSP &const_result, ExecutionPolicy execution_policy) { func_allocation_addr = LLDB_INVALID_ADDRESS; func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; llvm::Module *module = m_code_generator->ReleaseModule(); if (!module) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) std::string function_name; if (!FindFunctionInModule(function_name, module, m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName()); } ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = &target->GetDebugger().GetErrorStream(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), execution_policy, const_result, data_allocator, error_stream, function_name.c_str()); if (!ir_for_target.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't prepare the expression for execution in the target"); return err; } if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess()) { evaluated_statically = true; err.Clear(); return err; } Process *process = exe_ctx.GetProcessPtr(); if (!process || execution_policy == eExecutionPolicyNever) { err.SetErrorToGenericError(); err.SetErrorString("Execution needed to run in the target, but the target can't be run"); return err; } if (execution_policy != eExecutionPolicyNever && m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); StreamString install_errors; if (!dynamic_checkers->Install(install_errors, exe_ctx)) { if (install_errors.GetString().empty()) err.SetErrorString ("couldn't install checkers, unknown error"); else err.SetErrorString (install_errors.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str()); if (!ir_dynamic_checks.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } } // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called // below so we don't need to free it. RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager(); std::string error_string; if (log) { std::string s; raw_string_ostream oss(s); module->print(oss, NULL); oss.flush(); log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } #if defined (USE_STANDARD_JIT) m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, &error_string, jit_memory_manager, CodeGenOpt::Less, true, Reloc::Default, CodeModel::Small)); #else EngineBuilder builder(module); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(llvm::Reloc::PIC_) .setJITMemoryManager(jit_memory_manager) .setOptLevel(CodeGenOpt::Less) .setAllocateGVsWithCode(true) .setCodeModel(CodeModel::Small) .setUseMCJIT(true); m_execution_engine.reset(builder.create()); #endif if (!m_execution_engine.get()) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return err; } m_execution_engine->DisableLazyCompilation(); llvm::Function *function = module->getFunction (function_name.c_str()); // We don't actually need the function pointer here, this just forces it to get resolved. void *fun_ptr = m_execution_engine->getPointerToFunction(function); // Errors usually cause failures in the JIT, but if we're lucky we get here. if (!function) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str()); return err; } if (!fun_ptr) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str()); return err; } m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr)); Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target"); return err; } // Look over the regions allocated for the function compiled. The JIT // tries to allocate the functions & stubs close together, so we should try to // write them that way too... // For now I only write functions with no stubs, globals, exception tables, // etc. So I only need to write the functions. size_t alloc_size = 0; std::map<uint8_t *, uint8_t *>::iterator fun_pos = jit_memory_manager->m_functions.begin(); std::map<uint8_t *, uint8_t *>::iterator fun_end = jit_memory_manager->m_functions.end(); for (; fun_pos != fun_end; ++fun_pos) { size_t mem_size = fun_pos->second - fun_pos->first; if (log) log->Printf ("JIT memory: [%p - %p) size = %zu", fun_pos->first, fun_pos->second, mem_size); alloc_size += mem_size; } Error alloc_error; func_allocation_addr = process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, alloc_error); if (func_allocation_addr == LLDB_INVALID_ADDRESS) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error")); return err; } lldb::addr_t cursor = func_allocation_addr; for (fun_pos = jit_memory_manager->m_functions.begin(); fun_pos != fun_end; fun_pos++) { lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first; lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second; size_t size = lend - lstart; Error write_error; if (process->WriteMemory(cursor, (void *) lstart, size, write_error) != size) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error")); return err; } jit_memory_manager->AddToLocalToRemoteMap (lstart, size, cursor); cursor += size; } std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos != end; pos++) { (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr); if (!(*pos).m_name.compare(function_name.c_str())) { func_end = jit_memory_manager->GetRemoteRangeForLocal ((*pos).m_local_addr).second; func_addr = (*pos).m_remote_addr; } } if (log) { log->Printf("Code can be run in the target."); StreamString disassembly_stream; Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager); if (!err.Success()) { log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); } else { log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); } } err.Clear(); return err; }
bool Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error) { if (info == NULL) return false; posix_spawn_file_actions_t *file_actions = reinterpret_cast<posix_spawn_file_actions_t *>(_file_actions); switch (info->GetAction()) { case FileAction::eFileActionNone: error.Clear(); break; case FileAction::eFileActionClose: if (info->GetFD() == -1) error.SetErrorString( "invalid fd for posix_spawn_file_actions_addclose(...)"); else { error.SetError( ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX); if (log && (error.Fail() || log)) error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)", static_cast<void *>(file_actions), info->GetFD()); } break; case FileAction::eFileActionDuplicate: if (info->GetFD() == -1) error.SetErrorString( "invalid fd for posix_spawn_file_actions_adddup2(...)"); else if (info->GetActionArgument() == -1) error.SetErrorString( "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); else { error.SetError( ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()), eErrorTypePOSIX); if (log && (error.Fail() || log)) error.PutToLog( log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)", static_cast<void *>(file_actions), info->GetFD(), info->GetActionArgument()); } break; case FileAction::eFileActionOpen: if (info->GetFD() == -1) error.SetErrorString( "invalid fd in posix_spawn_file_actions_addopen(...)"); else { int oflag = info->GetActionArgument(); mode_t mode = 0; if (oflag & O_CREAT) mode = 0640; error.SetError(::posix_spawn_file_actions_addopen( file_actions, info->GetFD(), info->GetPath().str().c_str(), oflag, mode), eErrorTypePOSIX); if (error.Fail() || log) error.PutToLog(log, "posix_spawn_file_actions_addopen (action=%p, " "fd=%i, path='%s', oflag=%i, mode=%i)", static_cast<void *>(file_actions), info->GetFD(), info->GetPath().str().c_str(), oflag, mode); } break; } return error.Success(); }
Error PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); Error error; if (log) log->Printf("PlatformRemoteGDBServer::%s() called", __FUNCTION__); auto num_file_actions = launch_info.GetNumFileActions(); for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) { const auto file_action = launch_info.GetFileActionAtIndex(i); if (file_action->GetAction() != FileAction::eFileActionOpen) continue; switch (file_action->GetFD()) { case STDIN_FILENO: m_gdb_client.SetSTDIN(file_action->GetFileSpec()); break; case STDOUT_FILENO: m_gdb_client.SetSTDOUT(file_action->GetFileSpec()); break; case STDERR_FILENO: m_gdb_client.SetSTDERR(file_action->GetFileSpec()); break; } } m_gdb_client.SetDisableASLR( launch_info.GetFlags().Test(eLaunchFlagDisableASLR)); m_gdb_client.SetDetachOnError( launch_info.GetFlags().Test(eLaunchFlagDetachOnError)); FileSpec working_dir = launch_info.GetWorkingDirectory(); if (working_dir) { m_gdb_client.SetWorkingDir(working_dir); } // Send the environment and the program + arguments after we connect const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector(); if (envp) { const char *env_entry; for (int i = 0; (env_entry = envp[i]); ++i) { if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0) break; } } ArchSpec arch_spec = launch_info.GetArchitecture(); const char *arch_triple = arch_spec.GetTriple().str().c_str(); m_gdb_client.SendLaunchArchPacket(arch_triple); if (log) log->Printf( "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); int arg_packet_err; { // Scope for the scoped timeout object process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout( m_gdb_client, std::chrono::seconds(5)); arg_packet_err = m_gdb_client.SendArgumentsPacket(launch_info); } if (arg_packet_err == 0) { std::string error_str; if (m_gdb_client.GetLaunchSuccess(error_str)) { const auto pid = m_gdb_client.GetCurrentProcessID(false); if (pid != LLDB_INVALID_PROCESS_ID) { launch_info.SetProcessID(pid); if (log) log->Printf("PlatformRemoteGDBServer::%s() pid %" PRIu64 " launched successfully", __FUNCTION__, pid); } else { if (log) log->Printf("PlatformRemoteGDBServer::%s() launch succeeded but we " "didn't get a valid process id back!", __FUNCTION__); error.SetErrorString("failed to get PID"); } } else { error.SetErrorString(error_str.c_str()); if (log) log->Printf("PlatformRemoteGDBServer::%s() launch failed: %s", __FUNCTION__, error.AsCString()); } } else { error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err); } return error; }
Error ProcessKDP::DoResume () { Error error; Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); // Only start the async thread if we try to do any process control if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread)) StartAsyncThread (); bool resume = false; // With KDP there is only one thread we can tell what to do ThreadSP kernel_thread_sp (m_thread_list.FindThreadByProtocolID(g_kernel_tid)); if (kernel_thread_sp) { const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState(); if (log) log->Printf ("ProcessKDP::DoResume() thread_resume_state = %s", StateAsCString(thread_resume_state)); switch (thread_resume_state) { case eStateSuspended: // Nothing to do here when a thread will stay suspended // we just leave the CPU mask bit set to zero for the thread if (log) log->Printf ("ProcessKDP::DoResume() = suspended???"); break; case eStateStepping: { lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext()); if (reg_ctx_sp) { if (log) log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); reg_ctx_sp->HardwareSingleStep (true); resume = true; } else { error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID()); } } break; case eStateRunning: { lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext()); if (reg_ctx_sp) { if (log) log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (false);"); reg_ctx_sp->HardwareSingleStep (false); resume = true; } else { error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID()); } } break; default: // The only valid thread resume states are listed above assert (!"invalid thread resume state"); break; } } if (resume) { if (log) log->Printf ("ProcessKDP::DoResume () sending resume"); if (m_comm.SendRequestResume ()) { m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue); SetPrivateState(eStateRunning); } else error.SetErrorString ("KDP resume failed"); } else { error.SetErrorString ("kernel thread is suspended"); } return error; }
bool BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) { Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); Mutex::Locker evaluation_locker(m_condition_mutex); size_t condition_hash; const char *condition_text = GetConditionText(&condition_hash); if (!condition_text) { m_user_expression_sp.reset(); return false; } if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { m_user_expression_sp.reset(new ClangUserExpression(condition_text, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); StreamString errors; if (!m_user_expression_sp->Parse(errors, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true)) { error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s", errors.GetData()); m_user_expression_sp.reset(); return false; } m_condition_hash = condition_hash; } // We need to make sure the user sees any parse errors in their condition, so we'll hook the // constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetRunOthers(true); Error expr_error; StreamString execution_errors; ClangExpressionVariableSP result_variable_sp; ExecutionResults result_code = m_user_expression_sp->Execute(execution_errors, exe_ctx, options, m_user_expression_sp, result_variable_sp); bool ret; if (result_code == eExecutionCompleted) { if (!result_variable_sp) { ret = false; error.SetErrorString("Expression did not return a result"); return false; } result_value_sp = result_variable_sp->GetValueObject(); if (result_value_sp) { Scalar scalar_value; if (result_value_sp->ResolveValue (scalar_value)) { if (scalar_value.ULongLong(1) == 0) ret = false; else ret = true; if (log) log->Printf("Condition successfully evaluated, result is %s.\n", ret ? "true" : "false"); } else { ret = false; error.SetErrorString("Failed to get an integer result from the expression"); } } else { ret = false; error.SetErrorString("Failed to get any result from the expression"); } } else { ret = false; error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData()); } return ret; }
lldb::ExpressionResults ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); const lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); error.SetErrorString ("expression needed to run but couldn't"); return execution_results; } } if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); std::string full_prefix_storage; if (expr_prefix && option_prefix) { full_prefix_storage.assign(expr_prefix); full_prefix_storage.append(option_prefix); if (!full_prefix_storage.empty()) full_prefix = full_prefix_storage.c_str(); } else if (expr_prefix) full_prefix = expr_prefix; else full_prefix = option_prefix; lldb::ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, full_prefix, language, desired_type)); StreamString error_stream; if (log) log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info)) { execution_results = lldb::eExpressionParseError; if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { lldb::ClangExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); if (error_stream.GetString().empty()) error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else { if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } error_stream.GetString().clear(); if (log) log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute (error_stream, exe_ctx, options, user_expression_sp, expr_result); if (options.GetResultIsInternal() && expr_result && process) { process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result); } if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally =="); if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); return lldb::eExpressionInterrupted; } if (result_valobj_sp.get() == NULL) { result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); } return execution_results; }
// For local debugging, Linux will override the debug logic to use llgs-launch rather than // lldb-launch, llgs-attach. This differs from current lldb-launch, debugserver-attach // approach on MacOSX. lldb::ProcessSP PlatformLinux::DebugProcess (ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one Error &error) { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); if (log) log->Printf ("PlatformLinux::%s entered (target %p)", __FUNCTION__, static_cast<void*>(target)); // If we're a remote host, use standard behavior from parent class. if (!IsHost ()) return PlatformPOSIX::DebugProcess (launch_info, debugger, target, error); // // For local debugging, we'll insist on having ProcessGDBRemote create the process. // ProcessSP process_sp; // Make sure we stop at the entry point launch_info.GetFlags ().Set (eLaunchFlagDebug); // We always launch the process we are going to debug in a separate process // group, since then we can handle ^C interrupts ourselves w/o having to worry // about the target getting them as well. launch_info.SetLaunchInSeparateProcessGroup(true); // Ensure we have a target. if (target == nullptr) { if (log) log->Printf ("PlatformLinux::%s creating new target", __FUNCTION__); TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget (debugger, nullptr, nullptr, false, nullptr, new_target_sp); if (error.Fail ()) { if (log) log->Printf ("PlatformLinux::%s failed to create new target: %s", __FUNCTION__, error.AsCString ()); return process_sp; } target = new_target_sp.get(); if (!target) { error.SetErrorString ("CreateTarget() returned nullptr"); if (log) log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); return process_sp; } } else { if (log) log->Printf ("PlatformLinux::%s using provided target", __FUNCTION__); } // Mark target as currently selected target. debugger.GetTargetList().SetSelectedTarget(target); // Now create the gdb-remote process. if (log) log->Printf ("PlatformLinux::%s having target create process with gdb-remote plugin", __FUNCTION__); process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr); if (!process_sp) { error.SetErrorString ("CreateProcess() failed for gdb-remote process"); if (log) log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); return process_sp; } else { if (log) log->Printf ("PlatformLinux::%s successfully created process", __FUNCTION__); } // Adjust launch for a hijacker. ListenerSP listener_sp; if (!launch_info.GetHijackListener ()) { if (log) log->Printf ("PlatformLinux::%s setting up hijacker", __FUNCTION__); listener_sp = Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack"); launch_info.SetHijackListener (listener_sp); process_sp->HijackProcessEvents (listener_sp); } // Log file actions. if (log) { log->Printf ("PlatformLinux::%s launching process with the following file actions:", __FUNCTION__); StreamString stream; size_t i = 0; const FileAction *file_action; while ((file_action = launch_info.GetFileActionAtIndex (i++)) != nullptr) { file_action->Dump (stream); log->PutCString (stream.GetString().c_str ()); stream.Clear(); } } // Do the launch. error = process_sp->Launch(launch_info); if (error.Success ()) { // Handle the hijacking of process events. if (listener_sp) { const StateType state = process_sp->WaitForProcessToStop (NULL, NULL, false, listener_sp); if (state == eStateStopped) { if (log) log->Printf ("PlatformLinux::%s pid %" PRIu64 " state %s\n", __FUNCTION__, process_sp->GetID (), StateAsCString (state)); } else { if (log) log->Printf ("PlatformLinux::%s pid %" PRIu64 " state is not stopped - %s\n", __FUNCTION__, process_sp->GetID (), StateAsCString (state)); } } // Hook up process PTY if we have one (which we should for local debugging with llgs). int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); if (log) log->Printf ("PlatformLinux::%s pid %" PRIu64 " hooked up STDIO pty to process", __FUNCTION__, process_sp->GetID ()); } else { if (log) log->Printf ("PlatformLinux::%s pid %" PRIu64 " not using process STDIO pty", __FUNCTION__, process_sp->GetID ()); } } else { if (log) log->Printf ("PlatformLinux::%s process launch failed: %s", __FUNCTION__, error.AsCString ()); // FIXME figure out appropriate cleanup here. Do we delete the target? Do we delete the process? Does our caller do that? } return process_sp; }
Error PlatformRemoteAppleWatch::GetSymbolFile (const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { char resolved_path[PATH_MAX]; const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion(); if (os_version_dir) { ::snprintf (resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) { if (log) { log->Printf ("Found a copy of %s in the DeviceSupport dir %s", platform_file_path, os_version_dir); } return error; } ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) { if (log) { log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", platform_file_path, os_version_dir); } return error; } ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) { if (log) { log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols", platform_file_path, os_version_dir); } return error; } } local_file = platform_file; if (local_file.Exists()) return error; error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", platform_file_path, GetPluginName().GetCString()); } else { error.SetErrorString ("invalid platform file argument"); } return error; }
lldb::addr_t IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error) { lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); error.Clear(); lldb::ProcessSP process_sp; lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS; lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS; size_t alignment_mask = alignment - 1; size_t allocation_size; if (size == 0) allocation_size = alignment; else allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size; switch (policy) { default: error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: invalid allocation policy"); return LLDB_INVALID_ADDRESS; case eAllocationPolicyHostOnly: allocation_address = FindSpace(allocation_size, zero_memory); if (allocation_address == LLDB_INVALID_ADDRESS) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: address space is full"); return LLDB_INVALID_ADDRESS; } break; case eAllocationPolicyMirror: process_sp = m_process_wp.lock(); if (log) log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false"); if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) { if (!zero_memory) allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); else allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); if (!error.Success()) return LLDB_INVALID_ADDRESS; } else { if (log) log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__); policy = eAllocationPolicyHostOnly; allocation_address = FindSpace(allocation_size, zero_memory); if (allocation_address == LLDB_INVALID_ADDRESS) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: address space is full"); return LLDB_INVALID_ADDRESS; } } break; case eAllocationPolicyProcessOnly: process_sp = m_process_wp.lock(); if (process_sp) { if (process_sp->CanJIT() && process_sp->IsAlive()) { if (!zero_memory) allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); else allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); if (!error.Success()) return LLDB_INVALID_ADDRESS; } else { error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: process doesn't support allocating memory"); return LLDB_INVALID_ADDRESS; } } else { error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process"); return LLDB_INVALID_ADDRESS; } break; } lldb::addr_t mask = alignment - 1; aligned_address = (allocation_address + mask) & (~mask); m_allocations[aligned_address] = Allocation(allocation_address, aligned_address, allocation_size, permissions, alignment, policy); if (log) { const char * policy_string; switch (policy) { default: policy_string = "<invalid policy>"; break; case eAllocationPolicyHostOnly: policy_string = "eAllocationPolicyHostOnly"; break; case eAllocationPolicyProcessOnly: policy_string = "eAllocationPolicyProcessOnly"; break; case eAllocationPolicyMirror: policy_string = "eAllocationPolicyMirror"; break; } log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64, (uint64_t)allocation_size, (uint64_t)alignment, (uint64_t)permissions, policy_string, aligned_address); } return aligned_address; }
Error Value::GetValueAsData (ExecutionContext *exe_ctx, DataExtractor &data, uint32_t data_offset, Module *module) { data.Clear(); Error error; lldb::addr_t address = LLDB_INVALID_ADDRESS; AddressType address_type = eAddressTypeFile; Address file_so_addr; const CompilerType &ast_type = GetCompilerType(); switch (m_value_type) { case eValueTypeVector: if (ast_type.IsValid()) data.SetAddressByteSize (ast_type.GetPointerByteSize()); else data.SetAddressByteSize(sizeof(void *)); data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order); break; case eValueTypeScalar: { data.SetByteOrder (lldb::endian::InlHostByteOrder()); if (ast_type.IsValid()) data.SetAddressByteSize (ast_type.GetPointerByteSize()); else data.SetAddressByteSize(sizeof(void *)); uint32_t limit_byte_size = UINT32_MAX; if (ast_type.IsValid() && ast_type.IsScalarType()) { uint64_t type_encoding_count = 0; lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count); if (type_encoding == eEncodingUint || type_encoding == eEncodingSint) limit_byte_size = ast_type.GetByteSize(nullptr); } if (m_value.GetData (data, limit_byte_size)) return error; // Success; error.SetErrorStringWithFormat("extracting data from value failed"); break; } case eValueTypeLoadAddress: if (exe_ctx == NULL) { error.SetErrorString ("can't read load address (no execution context)"); } else { Process *process = exe_ctx->GetProcessPtr(); if (process == NULL || !process->IsAlive()) { Target *target = exe_ctx->GetTargetPtr(); if (target) { // Allow expressions to run and evaluate things when the target // has memory sections loaded. This allows you to use "target modules load" // to load your executable and any shared libraries, then execute // commands where you can look at types in data sections. const SectionLoadList &target_sections = target->GetSectionLoadList(); if (!target_sections.IsEmpty()) { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); if (target_sections.ResolveLoadAddress(address, file_so_addr)) { address_type = eAddressTypeLoad; data.SetByteOrder(target->GetArchitecture().GetByteOrder()); data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); } else address = LLDB_INVALID_ADDRESS; } // else // { // ModuleSP exe_module_sp (target->GetExecutableModule()); // if (exe_module_sp) // { // address = m_value.ULongLong(LLDB_INVALID_ADDRESS); // if (address != LLDB_INVALID_ADDRESS) // { // if (exe_module_sp->ResolveFileAddress(address, file_so_addr)) // { // data.SetByteOrder(target->GetArchitecture().GetByteOrder()); // data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); // address_type = eAddressTypeFile; // } // else // { // address = LLDB_INVALID_ADDRESS; // } // } // } // } } else { error.SetErrorString ("can't read load address (invalid process)"); } } else { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); address_type = eAddressTypeLoad; data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder()); data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize()); } } break; case eValueTypeFileAddress: if (exe_ctx == NULL) { error.SetErrorString ("can't read file address (no execution context)"); } else if (exe_ctx->GetTargetPtr() == NULL) { error.SetErrorString ("can't read file address (invalid target)"); } else { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); if (address == LLDB_INVALID_ADDRESS) { error.SetErrorString ("invalid file address"); } else { if (module == NULL) { // The only thing we can currently lock down to a module so that // we can resolve a file address, is a variable. Variable *variable = GetVariable(); if (variable) { SymbolContext var_sc; variable->CalculateSymbolContext(&var_sc); module = var_sc.module_sp.get(); } } if (module) { bool resolved = false; ObjectFile *objfile = module->GetObjectFile(); if (objfile) { Address so_addr(address, objfile->GetSectionList()); addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr()); bool process_launched_and_stopped = exe_ctx->GetProcessPtr() ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */) : false; // Don't use the load address if the process has exited. if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped) { resolved = true; address = load_address; address_type = eAddressTypeLoad; data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder()); data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize()); } else { if (so_addr.IsSectionOffset()) { resolved = true; file_so_addr = so_addr; data.SetByteOrder(objfile->GetByteOrder()); data.SetAddressByteSize(objfile->GetAddressByteSize()); } } } if (!resolved) { Variable *variable = GetVariable(); if (module) { if (variable) error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s' in %s", address, variable->GetName().AsCString(""), module->GetFileSpec().GetPath().c_str()); else error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " in %s", address, module->GetFileSpec().GetPath().c_str()); } else { if (variable) error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s'", address, variable->GetName().AsCString("")); else error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64, address); } } } else { // Can't convert a file address to anything valid without more // context (which Module it came from) error.SetErrorString ("can't read memory from file address without more context"); } } } break; case eValueTypeHostAddress: address = m_value.ULongLong(LLDB_INVALID_ADDRESS); address_type = eAddressTypeHost; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) { data.SetByteOrder(target->GetArchitecture().GetByteOrder()); data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); break; } } // fallback to host settings data.SetByteOrder(lldb::endian::InlHostByteOrder()); data.SetAddressByteSize(sizeof(void *)); break; } // Bail if we encountered any errors if (error.Fail()) return error; if (address == LLDB_INVALID_ADDRESS) { error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load"); return error; } // If we got here, we need to read the value from memory size_t byte_size = GetValueByteSize (&error); // Bail if we encountered any errors getting the byte size if (error.Fail()) return error; // Make sure we have enough room within "data", and if we don't make // something large enough that does if (!data.ValidOffsetForDataOfSize (data_offset, byte_size)) { DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0')); data.SetData(data_sp); } uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size)); if (dst != NULL) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it. if (address == 0) { error.SetErrorStringWithFormat("trying to read from host address of 0."); return error; } memcpy (dst, (uint8_t*)NULL + address, byte_size); } else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) { if (file_so_addr.IsValid()) { // We have a file address that we were able to translate into a // section offset address so we might be able to read this from // the object files if we don't have a live process. Lets always // try and read from the process if we have one though since we // want to read the actual value by setting "prefer_file_cache" // to false. const bool prefer_file_cache = false; if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size) { error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed", (uint64_t)address); } } else { // The execution context might have a NULL process, but it // might have a valid process in the exe_ctx->target, so use // the ExecutionContext::GetProcess accessor to ensure we // get the process if there is one. Process *process = exe_ctx->GetProcessPtr(); if (process) { const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error); if (bytes_read != byte_size) error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size); } else { error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (invalid process)", (uint64_t)address); } } } else { error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type); } } else { error.SetErrorStringWithFormat ("out of memory"); } return error; }
Error Host::RunShellCommand (const char *command, const char *working_dir, int *status_ptr, int *signo_ptr, std::string *command_output_ptr, uint32_t timeout_sec) { Error error; ProcessLaunchInfo launch_info; launch_info.SetShell("/bin/bash"); launch_info.GetArguments().AppendArgument(command); const bool localhost = true; const bool will_debug = false; const bool first_arg_is_full_shell_command = true; launch_info.ConvertArgumentsForLaunchingInShell (error, localhost, will_debug, first_arg_is_full_shell_command); if (working_dir) launch_info.SetWorkingDirectory(working_dir); char output_file_path_buffer[L_tmpnam]; const char *output_file_path = NULL; if (command_output_ptr) { // Create a temporary file to get the stdout/stderr and redirect the // output of the command into this file. We will later read this file // if all goes well and fill the data into "command_output_ptr" output_file_path = ::tmpnam(output_file_path_buffer); launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path, false, true); launch_info.AppendDuplicateFileAction(STDERR_FILENO, STDOUT_FILENO); } else { launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); } // The process monitor callback will delete the 'shell_info_ptr' below... std::auto_ptr<ShellInfo> shell_info_ap (new ShellInfo()); const bool monitor_signals = false; launch_info.SetMonitorProcessCallback(MonitorShellCommand, shell_info_ap.get(), monitor_signals); error = LaunchProcess (launch_info); const lldb::pid_t pid = launch_info.GetProcessID(); if (pid != LLDB_INVALID_PROCESS_ID) { // The process successfully launched, so we can defer ownership of // "shell_info" to the MonitorShellCommand callback function that will // get called when the process dies. We release the std::auto_ptr as it // doesn't need to delete the ShellInfo anymore. ShellInfo *shell_info = shell_info_ap.release(); TimeValue timeout_time(TimeValue::Now()); timeout_time.OffsetWithSeconds(timeout_sec); bool timed_out = false; shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out); if (timed_out) { error.SetErrorString("timed out waiting for shell command to complete"); #ifdef _POSIX_SOURCE // Kill the process since it didn't complete withint the timeout specified ::kill (pid, SIGKILL); #endif // Wait for the monitor callback to get the message timeout_time = TimeValue::Now(); timeout_time.OffsetWithSeconds(1); timed_out = false; shell_info->process_reaped.WaitForValueEqualTo(true, &timeout_time, &timed_out); } else { if (status_ptr) *status_ptr = shell_info->status; if (signo_ptr) *signo_ptr = shell_info->signo; if (command_output_ptr) { command_output_ptr->clear(); FileSpec file_spec(output_file_path, File::eOpenOptionRead); uint64_t file_size = file_spec.GetByteSize(); if (file_size > 0) { if (file_size > command_output_ptr->max_size()) { error.SetErrorStringWithFormat("shell command output is too large to fit into a std::string"); } else { command_output_ptr->resize(file_size); file_spec.ReadFileContents(0, &((*command_output_ptr)[0]), command_output_ptr->size(), &error); } } } } shell_info->can_delete.SetValue(true, eBroadcastAlways); } else { error.SetErrorString("failed to get process ID"); } if (output_file_path) ::unlink (output_file_path); // Handshake with the monitor thread, or just let it know in advance that // it can delete "shell_info" in case we timed out and were not able to kill // the process... return error; }
Error ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; if (!new_value_sp) { error.SetErrorString("Empty value object for return value."); return error; } ClangASTType clang_type = new_value_sp->GetClangType(); if (!clang_type) { error.SetErrorString ("Null clang type for return value."); return error; } Thread *thread = frame_sp->GetThread().get(); bool is_signed; uint32_t count; bool is_complex; RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) { DataExtractor data; Error data_error; size_t num_bytes = new_value_sp->GetData(data, data_error); if (data_error.Fail()) { error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); return error; } lldb::offset_t offset = 0; if (num_bytes <= 8) { const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0); if (num_bytes <= 4) { uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value)) set_it_simple = true; } else { uint32_t raw_value = data.GetMaxU32(&offset, 4); if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value)) { const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0); uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); if (reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value)) set_it_simple = true; } } } else { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } else if (clang_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else error.SetErrorString ("We don't support returning float values at present"); } if (!set_it_simple) error.SetErrorString ("We only support setting simple integer return types at present."); return error; }
lldb::ExpressionResults UserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Target *target = exe_ctx.GetTargetPtr(); if (!target) { if (log) log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); return lldb::eExpressionSetupError; } Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); error.SetErrorString ("expression needed to run but couldn't"); return execution_results; } } if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); std::string full_prefix_storage; if (expr_prefix && option_prefix) { full_prefix_storage.assign(expr_prefix); full_prefix_storage.append(option_prefix); if (!full_prefix_storage.empty()) full_prefix = full_prefix_storage.c_str(); } else if (expr_prefix) full_prefix = expr_prefix; else full_prefix = option_prefix; // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, full_prefix, language, desired_type, error)); if (error.Fail()) { if (log) log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } StreamString error_stream; if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info)) { execution_results = lldb::eExpressionParseError; if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created if (jit_module_sp_ptr && user_expression_sp->m_execution_unit_sp) *jit_module_sp_ptr = user_expression_sp->m_execution_unit_sp->GetJITModule(); lldb::ExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); if (error_stream.GetString().empty()) error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else { if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } error_stream.GetString().clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute (error_stream, exe_ctx, options, user_expression_sp, expr_result); if (options.GetResultIsInternal() && expr_result && process) { process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result); } if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); return lldb::eExpressionInterrupted; } if (result_valobj_sp.get() == NULL) { result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); } return execution_results; }
Error ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); const char *name = m_expr.FunctionName(); Error ret; ret.Clear(); lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos < end; pos++) { if (strstr(pos->m_name.c_str(), name)) { func_local_addr = pos->m_local_addr; func_remote_addr = pos->m_remote_addr; } } if (func_local_addr == LLDB_INVALID_ADDRESS) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name); return ret; } if (log) log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair <lldb::addr_t, lldb::addr_t> func_range; func_range = jit_memory_manager->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", name); return ret; } if (log) log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second); Target *target = exe_ctx.GetTargetPtr(); if (!target) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the target"); } lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 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()); Disassembler *disassembler = Disassembler::FindPlugin(arch, NULL); if (disassembler == NULL) { 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.get(), 0, extractor.GetByteSize(), func_remote_addr, 16, DataExtractor::TypeUInt8); } disassembler->DecodeInstructions (Address (NULL, func_remote_addr), extractor, 0, UINT32_MAX, false); InstructionList &instruction_list = disassembler->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); for (uint32_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, true); stream.PutChar('\n'); } return ret; }
lldb::ExpressionResults UserExpression::Evaluate( ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Target *target = exe_ctx.GetTargetPtr(); if (!target) { if (log) log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't " "run expressions."); return lldb::eExpressionSetupError; } Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but " "is not constant =="); error.SetErrorString("expression needed to run but couldn't"); return execution_results; } } if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; // We need to set the expression execution thread here, turns out parse can // call functions in the process of // looking up symbols, which will escape the context set by exe_ctx passed to // Execute. lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher( thread_sp); const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); std::string full_prefix_storage; if (expr_prefix && option_prefix) { full_prefix_storage.assign(expr_prefix); full_prefix_storage.append(option_prefix); if (!full_prefix_storage.empty()) full_prefix = full_prefix_storage.c_str(); } else if (expr_prefix) full_prefix = expr_prefix; else full_prefix = option_prefix; // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } lldb::UserExpressionSP user_expression_sp( target->GetUserExpressionForLanguage(expr_cstr, full_prefix, language, desired_type, options, error)); if (error.Fail()) { if (log) log->Printf("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) { error.SetErrorString("expression interrupted by callback before parse"); result_valobj_sp = ValueObjectConstResult::Create( exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } DiagnosticManager diagnostic_manager; bool parse_success = user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info); // Calculate the fixed expression always, since we need it for errors. std::string tmp_fixed_expression; if (fixed_expression == nullptr) fixed_expression = &tmp_fixed_expression; const char *fixed_text = user_expression_sp->GetFixedText(); if (fixed_text != nullptr) fixed_expression->append(fixed_text); // If there is a fixed expression, try to parse it: if (!parse_success) { execution_results = lldb::eExpressionParseError; if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts()) { lldb::UserExpressionSP fixed_expression_sp( target->GetUserExpressionForLanguage(fixed_expression->c_str(), full_prefix, language, desired_type, options, error)); DiagnosticManager fixed_diagnostic_manager; parse_success = fixed_expression_sp->Parse( fixed_diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info); if (parse_success) { diagnostic_manager.Clear(); user_expression_sp = fixed_expression_sp; } else { // If the fixed expression failed to parse, don't tell the user about, // that won't help. fixed_expression->clear(); } } if (!parse_success) { if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) { error.SetExpressionErrorWithFormat( execution_results, "expression failed to parse, fixed expression suggested:\n %s", fixed_expression->c_str()); } else { if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(execution_results, "expression failed to parse, unknown error"); else error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } } } if (parse_success) { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module // if one was created if (jit_module_sp_ptr) *jit_module_sp_ptr = user_expression_sp->GetJITModule(); lldb::ExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but " "is not constant =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else if (execution_policy == eExecutionPolicyTopLevel) { error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); return lldb::eExpressionCompleted; } else { if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) { error.SetExpressionError( lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); result_valobj_sp = ValueObjectConstResult::Create( exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } diagnostic_manager.Clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed " "abnormally =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError( execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [UserExpression::Evaluate] Execution completed " "normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed " "normally with no result =="); error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { error.SetExpressionError( lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); return lldb::eExpressionInterrupted; } if (result_valobj_sp.get() == NULL) { result_valobj_sp = ValueObjectConstResult::Create( exe_ctx.GetBestExecutionContextScope(), error); } return execution_results; }
void IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error) { error.Clear(); AllocationMap::iterator iter = FindAllocation(process_address, size); if (iter == m_allocations.end()) { lldb::ProcessSP process_sp = m_process_wp.lock(); if (process_sp) { process_sp->WriteMemory(process_address, bytes, size, error); return; } error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist"); return; } Allocation &allocation = iter->second; uint64_t offset = process_address - allocation.m_process_start; lldb::ProcessSP process_sp; switch (allocation.m_policy) { default: error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: invalid allocation policy"); return; case eAllocationPolicyHostOnly: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: data buffer is empty"); return; } ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size); break; case eAllocationPolicyMirror: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: data buffer is empty"); return; } ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size); process_sp = m_process_wp.lock(); if (process_sp) { process_sp->WriteMemory(process_address, bytes, size, error); if (!error.Success()) return; } break; case eAllocationPolicyProcessOnly: process_sp = m_process_wp.lock(); if (process_sp) { process_sp->WriteMemory(process_address, bytes, size, error); if (!error.Success()) return; } break; } if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")", (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, (uint64_t)allocation.m_process_start, (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); } }
Error OptionValueFileSpecList::SetValueFromString (llvm::StringRef value, VarSetOperationType op) { Error error; Args args(value.str().c_str()); const size_t argc = args.GetArgumentCount(); switch (op) { case eVarSetOperationClear: Clear (); NotifyValueChanged(); break; case eVarSetOperationReplace: if (argc > 1) { uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = m_current_value.GetSize(); if (idx > count) { error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count); } else { for (size_t i=1; i<argc; ++i, ++idx) { FileSpec file (args.GetArgumentAtIndex(i), false); if (idx < count) m_current_value.Replace(idx, file); else m_current_value.Append(file); } NotifyValueChanged(); } } else { error.SetErrorString("replace operation takes an array index followed by one or more values"); } break; case eVarSetOperationAssign: m_current_value.Clear(); // Fall through to append case case eVarSetOperationAppend: if (argc > 0) { m_value_was_set = true; for (size_t i=0; i<argc; ++i) { FileSpec file (args.GetArgumentAtIndex(i), false); m_current_value.Append(file); } NotifyValueChanged(); } else { error.SetErrorString("assign operation takes at least one file path argument"); } break; case eVarSetOperationInsertBefore: case eVarSetOperationInsertAfter: if (argc > 1) { uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = m_current_value.GetSize(); if (idx > count) { error.SetErrorStringWithFormat("invalid insert file list index %u, index must be 0 through %u", idx, count); } else { if (op == eVarSetOperationInsertAfter) ++idx; for (size_t i=1; i<argc; ++i, ++idx) { FileSpec file (args.GetArgumentAtIndex(i), false); m_current_value.Insert (idx, file); } NotifyValueChanged(); } } else { error.SetErrorString("insert operation takes an array index followed by one or more values"); } break; case eVarSetOperationRemove: if (argc > 0) { std::vector<int> remove_indexes; bool all_indexes_valid = true; size_t i; for (i=0; all_indexes_valid && i<argc; ++i) { const int idx = StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); if (idx == INT32_MAX) all_indexes_valid = false; else remove_indexes.push_back(idx); } if (all_indexes_valid) { size_t num_remove_indexes = remove_indexes.size(); if (num_remove_indexes) { // Sort and then erase in reverse so indexes are always valid std::sort(remove_indexes.begin(), remove_indexes.end()); for (size_t j=num_remove_indexes-1; j<num_remove_indexes; ++j) { m_current_value.Remove (j); } } NotifyValueChanged(); } else { error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i)); } } else { error.SetErrorString("remove operation takes one or more array index"); } break; case eVarSetOperationInvalid: error = OptionValue::SetValueFromString (value, op); break; } return error; }
void IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error) { error.Clear(); AllocationMap::iterator iter = FindAllocation(process_address, size); if (iter == m_allocations.end()) { lldb::ProcessSP process_sp = m_process_wp.lock(); if (process_sp) { process_sp->ReadMemory(process_address, bytes, size, error); return; } lldb::TargetSP target_sp = m_target_wp.lock(); if (target_sp) { Address absolute_address(process_address); target_sp->ReadMemory(absolute_address, false, bytes, size, error); return; } error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist"); return; } Allocation &allocation = iter->second; uint64_t offset = process_address - allocation.m_process_start; if (offset > allocation.m_size) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: data is not in the allocation"); return; } lldb::ProcessSP process_sp; switch (allocation.m_policy) { default: error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: invalid allocation policy"); return; case eAllocationPolicyHostOnly: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: data buffer is empty"); return; } if (allocation.m_data.GetByteSize() < offset + size) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: not enough underlying data"); return; } ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size); break; case eAllocationPolicyMirror: process_sp = m_process_wp.lock(); if (process_sp) { process_sp->ReadMemory(process_address, bytes, size, error); if (!error.Success()) return; } else { if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: data buffer is empty"); return; } ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size); } break; case eAllocationPolicyProcessOnly: process_sp = m_process_wp.lock(); if (process_sp) { process_sp->ReadMemory(process_address, bytes, size, error); if (!error.Success()) return; } break; } if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")", (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, (uint64_t)allocation.m_process_start, (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); } }
void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (log) log->Printf("ClangUserExpression::ScanContext()"); m_target = exe_ctx.GetTargetPtr(); if (!(m_allow_cxx || m_allow_objc)) { if (log) log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); return; } StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == NULL) { if (log) log->Printf(" [CUE::SC] Null stack frame"); return; } SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); if (!sym_ctx.function) { if (log) log->Printf(" [CUE::SC] Null function"); return; } // Find the block that defines the function represented by "sym_ctx" Block *function_block = sym_ctx.GetFunctionBlock(); if (!function_block) { if (log) log->Printf(" [CUE::SC] Null function block"); return; } clang::DeclContext *decl_context = function_block->GetClangDeclContext(); if (!decl_context) { if (log) log->Printf(" [CUE::SC] Null decl context"); return; } if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context)) { if (m_allow_cxx && method_decl->isInstance()) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(thisErrorString); return; } lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); if (!this_var_sp || !this_var_sp->IsInScope(frame) || !this_var_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(thisErrorString); return; } } m_in_cplusplus_method = true; m_needs_object_ptr = true; } } else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context)) { if (m_allow_objc) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(selfErrorString); return; } lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); if (!self_variable_sp || !self_variable_sp->IsInScope(frame) || !self_variable_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(selfErrorString); return; } } m_in_objectivec_method = true; m_needs_object_ptr = true; if (!method_decl->isInstanceMethod()) m_in_static_method = true; } } else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_context)) { // We might also have a function that said in the debug information that it captured an // object pointer. The best way to deal with getting to the ivars at present is by pretending // that this is a method of a class in whatever runtime the debug info says the object pointer // belongs to. Do that here. ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl); if (metadata && metadata->HasObjectPtr()) { lldb::LanguageType language = metadata->GetObjectPtrLanguage(); if (language == lldb::eLanguageTypeC_plus_plus) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(thisErrorString); return; } lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); if (!this_var_sp || !this_var_sp->IsInScope(frame) || !this_var_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(thisErrorString); return; } } m_in_cplusplus_method = true; m_needs_object_ptr = true; } else if (language == lldb::eLanguageTypeObjC) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(selfErrorString); return; } lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); if (!self_variable_sp || !self_variable_sp->IsInScope(frame) || !self_variable_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(selfErrorString); return; } Type *self_type = self_variable_sp->GetType(); if (!self_type) { err.SetErrorString(selfErrorString); return; } ClangASTType self_clang_type = self_type->GetClangForwardType(); if (!self_clang_type) { err.SetErrorString(selfErrorString); return; } if (self_clang_type.IsObjCClassType()) { return; } else if (self_clang_type.IsObjCObjectPointerType()) { m_in_objectivec_method = true; m_needs_object_ptr = true; } else { err.SetErrorString(selfErrorString); return; } } else { m_in_objectivec_method = true; m_needs_object_ptr = true; } } } } }
void IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error) { error.Clear(); if (size > 0) { AllocationMap::iterator iter = FindAllocation(process_address, size); if (iter == m_allocations.end()) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size); return; } Allocation &allocation = iter->second; switch (allocation.m_policy) { default: error.SetErrorToGenericError(); error.SetErrorString("Couldn't get memory data: invalid allocation policy"); return; case eAllocationPolicyProcessOnly: error.SetErrorToGenericError(); error.SetErrorString("Couldn't get memory data: memory is only in the target"); return; case eAllocationPolicyMirror: { lldb::ProcessSP process_sp = m_process_wp.lock(); if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't get memory data: data buffer is empty"); return; } if (process_sp) { process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error); if (!error.Success()) return; uint64_t offset = process_address - allocation.m_process_start; extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); return; } } case eAllocationPolicyHostOnly: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't get memory data: data buffer is empty"); return; } uint64_t offset = process_address - allocation.m_process_start; extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); return; } } else { error.SetErrorToGenericError(); error.SetErrorString ("Couldn't get memory data: its size was zero"); return; } }
Error ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url) { Error error; // Don't let any JIT happen when doing KDP as we can't allocate // memory and we don't want to be mucking with threads that might // already be handling exceptions SetCanJIT(false); if (remote_url == NULL || remote_url[0] == '\0') { error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url); return error; } std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); if (conn_ap.get()) { // Only try once for now. // TODO: check if we should be retrying? const uint32_t max_retry_count = 1; for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count) { if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) break; usleep (100000); } } if (conn_ap->IsConnected()) { const Socket& socket = static_cast<const Socket&>(*conn_ap->GetReadObject()); const uint16_t reply_port = socket.GetPortNumber(); if (reply_port != 0) { m_comm.SetConnection(conn_ap.release()); if (m_comm.SendRequestReattach(reply_port)) { if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB...")) { m_comm.GetVersion(); uint32_t cpu = m_comm.GetCPUType(); uint32_t sub = m_comm.GetCPUSubtype(); ArchSpec kernel_arch; kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub); m_target.SetArchitecture(kernel_arch); /* Get the kernel's UUID and load address via KDP_KERNELVERSION packet. */ /* An EFI kdp session has neither UUID nor load address. */ UUID kernel_uuid = m_comm.GetUUID (); addr_t kernel_load_addr = m_comm.GetLoadAddress (); if (m_comm.RemoteIsEFI ()) { // Select an invalid plugin name for the dynamic loader so one doesn't get used // since EFI does its own manual loading via python scripting static ConstString g_none_dynamic_loader("none"); m_dyld_plugin_name = g_none_dynamic_loader; if (kernel_uuid.IsValid()) { // If EFI passed in a UUID= try to lookup UUID // The slide will not be provided. But the UUID // lookup will be used to launch EFI debug scripts // from the dSYM, that can load all of the symbols. ModuleSpec module_spec; module_spec.GetUUID() = kernel_uuid; module_spec.GetArchitecture() = m_target.GetArchitecture(); // Lookup UUID locally, before attempting dsymForUUID like action module_spec.GetSymbolFileSpec() = Symbols::LocateExecutableSymbolFile(module_spec); if (module_spec.GetSymbolFileSpec()) module_spec.GetFileSpec() = Symbols::LocateExecutableObjectFile (module_spec); if (!module_spec.GetSymbolFileSpec() || !module_spec.GetSymbolFileSpec()) Symbols::DownloadObjectAndSymbolFile (module_spec, true); if (module_spec.GetFileSpec().Exists()) { ModuleSP module_sp(new Module (module_spec.GetFileSpec(), m_target.GetArchitecture())); if (module_sp.get() && module_sp->MatchesModuleSpec (module_spec)) { // Get the current target executable ModuleSP exe_module_sp (m_target.GetExecutableModule ()); // Make sure you don't already have the right module loaded and they will be uniqued if (exe_module_sp.get() != module_sp.get()) m_target.SetExecutableModule (module_sp, false); } } } } else if (m_comm.RemoteIsDarwinKernel ()) { m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); if (kernel_load_addr != LLDB_INVALID_ADDRESS) { m_kernel_load_addr = kernel_load_addr; } } // Set the thread ID UpdateThreadListIfNeeded (); SetID (1); GetThreadList (); SetPrivateState (eStateStopped); StreamSP async_strm_sp(m_target.GetDebugger().GetAsyncOutputStream()); if (async_strm_sp) { const char *cstr; if ((cstr = m_comm.GetKernelVersion ()) != NULL) { async_strm_sp->Printf ("Version: %s\n", cstr); async_strm_sp->Flush(); } // if ((cstr = m_comm.GetImagePath ()) != NULL) // { // async_strm_sp->Printf ("Image Path: %s\n", cstr); // async_strm_sp->Flush(); // } } } else { error.SetErrorString("KDP_REATTACH failed"); } } else { error.SetErrorString("KDP_REATTACH failed"); } } else { error.SetErrorString("invalid reply port from UDP connection"); } } else { if (error.Success()) error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url); } if (error.Fail()) m_comm.Disconnect(); return error; }
Error ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) { Error error; if (wp) { user_id_t watchID = wp->GetID(); addr_t addr = wp->GetLoadAddress(); Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); if (log) log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", watchID); if (wp->IsEnabled()) { if (log) log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", watchID, (uint64_t)addr); return error; } // Try to find a vacant watchpoint slot in the inferiors' main thread uint32_t wp_hw_index = LLDB_INVALID_INDEX32; Mutex::Locker lock(m_thread_list.GetMutex()); FreeBSDThread *thread = static_cast<FreeBSDThread*>( m_thread_list.GetThreadAtIndex(0, false).get()); if (thread) wp_hw_index = thread->FindVacantWatchpointIndex(); if (wp_hw_index == LLDB_INVALID_INDEX32) { error.SetErrorString("Setting hardware watchpoint failed."); } else { wp->SetHardwareIndex(wp_hw_index); bool wp_enabled = true; uint32_t thread_count = m_thread_list.GetSize(false); for (uint32_t i = 0; i < thread_count; ++i) { thread = static_cast<FreeBSDThread*>( m_thread_list.GetThreadAtIndex(i, false).get()); if (thread) wp_enabled &= thread->EnableHardwareWatchpoint(wp); else wp_enabled = false; } if (wp_enabled) { wp->SetEnabled(true, notify); return error; } else { // Watchpoint enabling failed on at least one // of the threads so roll back all of them DisableWatchpoint(wp, false); error.SetErrorString("Setting hardware watchpoint failed"); } } } else error.SetErrorString("Watchpoint argument was NULL."); return error; }
lldb::addr_t ProcessKDP::DoAllocateMemory (size_t size, uint32_t permissions, Error &error) { error.SetErrorString ("memory allocation not suppported in kdp remote debugging"); return LLDB_INVALID_ADDRESS; }
Error RegisterValue::SetValueFromData(const RegisterInfo *reg_info, DataExtractor &src, lldb::offset_t src_offset, bool partial_data_ok) { Error error; if (src.GetByteSize() == 0) { error.SetErrorString("empty data."); return error; } if (reg_info->byte_size == 0) { error.SetErrorString("invalid register info."); return error; } uint32_t src_len = src.GetByteSize() - src_offset; if (!partial_data_ok && (src_len < reg_info->byte_size)) { error.SetErrorString("not enough data."); return error; } // Cap the data length if there is more than enough bytes for this register // value if (src_len > reg_info->byte_size) src_len = reg_info->byte_size; // Zero out the value in case we get partial data... memset(buffer.bytes, 0, sizeof(buffer.bytes)); type128 int128; m_type = eTypeInvalid; switch (reg_info->encoding) { case eEncodingInvalid: break; case eEncodingUint: case eEncodingSint: if (reg_info->byte_size == 1) SetUInt8(src.GetMaxU32(&src_offset, src_len)); else if (reg_info->byte_size <= 2) SetUInt16(src.GetMaxU32(&src_offset, src_len)); else if (reg_info->byte_size <= 4) SetUInt32(src.GetMaxU32(&src_offset, src_len)); else if (reg_info->byte_size <= 8) SetUInt64(src.GetMaxU64(&src_offset, src_len)); else if (reg_info->byte_size <= 16) { uint64_t data1 = src.GetU64(&src_offset); uint64_t data2 = src.GetU64(&src_offset); if (src.GetByteSize() == eByteOrderBig) { int128.x[0] = data1; int128.x[1] = data2; } else { int128.x[0] = data2; int128.x[1] = data1; } SetUInt128(llvm::APInt(128, 2, int128.x)); } break; case eEncodingIEEE754: if (reg_info->byte_size == sizeof(float)) SetFloat(src.GetFloat(&src_offset)); else if (reg_info->byte_size == sizeof(double)) SetDouble(src.GetDouble(&src_offset)); else if (reg_info->byte_size == sizeof(long double)) SetLongDouble(src.GetLongDouble(&src_offset)); break; case eEncodingVector: { m_type = eTypeBytes; buffer.length = reg_info->byte_size; buffer.byte_order = src.GetByteOrder(); assert(buffer.length <= kMaxRegisterByteSize); if (buffer.length > kMaxRegisterByteSize) buffer.length = kMaxRegisterByteSize; if (src.CopyByteOrderedData( src_offset, // offset within "src" to start extracting data src_len, // src length buffer.bytes, // dst buffer buffer.length, // dst length buffer.byte_order) == 0) // dst byte order { error.SetErrorStringWithFormat( "failed to copy data for register write of %s", reg_info->name); return error; } } } if (m_type == eTypeInvalid) error.SetErrorStringWithFormat( "invalid register value type for register %s", reg_info->name); return error; }
Error Host::RunShellCommand(const Args &args, const FileSpec &working_dir, int *status_ptr, int *signo_ptr, std::string *command_output_ptr, uint32_t timeout_sec, bool run_in_default_shell) { Error error; ProcessLaunchInfo launch_info; launch_info.SetArchitecture(HostInfo::GetArchitecture()); if (run_in_default_shell) { // Run the command in a shell launch_info.SetShell(HostInfo::GetDefaultShell()); launch_info.GetArguments().AppendArguments(args); const bool localhost = true; const bool will_debug = false; const bool first_arg_is_full_shell_command = false; launch_info.ConvertArgumentsForLaunchingInShell( error, localhost, will_debug, first_arg_is_full_shell_command, 0); } else { // No shell, just run it const bool first_arg_is_executable = true; launch_info.SetArguments(args, first_arg_is_executable); } if (working_dir) launch_info.SetWorkingDirectory(working_dir); llvm::SmallString<PATH_MAX> output_file_path; if (command_output_ptr) { // Create a temporary file to get the stdout/stderr and redirect the // output of the command into this file. We will later read this file // if all goes well and fill the data into "command_output_ptr" FileSpec tmpdir_file_spec; if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { tmpdir_file_spec.AppendPathComponent("lldb-shell-output.%%%%%%"); llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), output_file_path); } else { llvm::sys::fs::createTemporaryFile("lldb-shell-output.%%%%%%", "", output_file_path); } } FileSpec output_file_spec{output_file_path.c_str(), false}; launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); if (output_file_spec) { launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_spec, false, true); launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO); } else { launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); } std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo()); const bool monitor_signals = false; launch_info.SetMonitorProcessCallback( std::bind(MonitorShellCommand, shell_info_sp, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), monitor_signals); error = LaunchProcess(launch_info); const lldb::pid_t pid = launch_info.GetProcessID(); if (error.Success() && pid == LLDB_INVALID_PROCESS_ID) error.SetErrorString("failed to get process ID"); if (error.Success()) { bool timed_out = false; shell_info_sp->process_reaped.WaitForValueEqualTo( true, std::chrono::seconds(timeout_sec), &timed_out); if (timed_out) { error.SetErrorString("timed out waiting for shell command to complete"); // Kill the process since it didn't complete within the timeout specified Kill(pid, SIGKILL); // Wait for the monitor callback to get the message timed_out = false; shell_info_sp->process_reaped.WaitForValueEqualTo( true, std::chrono::seconds(1), &timed_out); } else { if (status_ptr) *status_ptr = shell_info_sp->status; if (signo_ptr) *signo_ptr = shell_info_sp->signo; if (command_output_ptr) { command_output_ptr->clear(); uint64_t file_size = output_file_spec.GetByteSize(); if (file_size > 0) { if (file_size > command_output_ptr->max_size()) { error.SetErrorStringWithFormat( "shell command output is too large to fit into a std::string"); } else { std::vector<char> command_output(file_size); output_file_spec.ReadFileContents(0, command_output.data(), file_size, &error); if (error.Success()) command_output_ptr->assign(command_output.data(), file_size); } } } } } if (FileSystem::GetFileExists(output_file_spec)) FileSystem::Unlink(output_file_spec); return error; }
Error RegisterValue::SetValueFromCString(const RegisterInfo *reg_info, const char *value_str) { Error error; if (reg_info == nullptr) { error.SetErrorString("Invalid register info argument."); return error; } if (value_str == nullptr || value_str[0] == '\0') { error.SetErrorString("Invalid c-string value string."); return error; } bool success = false; const uint32_t byte_size = reg_info->byte_size; static float flt_val; static double dbl_val; static long double ldbl_val; switch (reg_info->encoding) { case eEncodingInvalid: error.SetErrorString("Invalid encoding."); break; case eEncodingUint: if (byte_size <= sizeof(uint64_t)) { uint64_t uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); if (!success) error.SetErrorStringWithFormat( "'%s' is not a valid unsigned integer string value", value_str); else if (!Args::UInt64ValueIsValidForByteSize(uval64, byte_size)) error.SetErrorStringWithFormat( "value 0x%" PRIx64 " is too large to fit in a %u byte unsigned integer value", uval64, byte_size); else { if (!SetUInt(uval64, reg_info->byte_size)) error.SetErrorStringWithFormat( "unsupported unsigned integer byte size: %u", byte_size); } } else { error.SetErrorStringWithFormat( "unsupported unsigned integer byte size: %u", byte_size); return error; } break; case eEncodingSint: if (byte_size <= sizeof(long long)) { uint64_t sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); if (!success) error.SetErrorStringWithFormat( "'%s' is not a valid signed integer string value", value_str); else if (!Args::SInt64ValueIsValidForByteSize(sval64, byte_size)) error.SetErrorStringWithFormat( "value 0x%" PRIx64 " is too large to fit in a %u byte signed integer value", sval64, byte_size); else { if (!SetUInt(sval64, reg_info->byte_size)) error.SetErrorStringWithFormat( "unsupported signed integer byte size: %u", byte_size); } } else { error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", byte_size); return error; } break; case eEncodingIEEE754: if (byte_size == sizeof(float)) { if (::sscanf(value_str, "%f", &flt_val) == 1) { m_scalar = flt_val; m_type = eTypeFloat; } else error.SetErrorStringWithFormat("'%s' is not a valid float string value", value_str); } else if (byte_size == sizeof(double)) { if (::sscanf(value_str, "%lf", &dbl_val) == 1) { m_scalar = dbl_val; m_type = eTypeDouble; } else error.SetErrorStringWithFormat("'%s' is not a valid float string value", value_str); } else if (byte_size == sizeof(long double)) { if (::sscanf(value_str, "%Lf", &ldbl_val) == 1) { m_scalar = ldbl_val; m_type = eTypeLongDouble; } else error.SetErrorStringWithFormat("'%s' is not a valid float string value", value_str); } else { error.SetErrorStringWithFormat("unsupported float byte size: %u", byte_size); return error; } break; case eEncodingVector: if (!ParseVectorEncoding(reg_info, value_str, byte_size, this)) error.SetErrorString("unrecognized vector encoding string value."); break; } if (error.Fail()) m_type = eTypeInvalid; return error; }
Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, std::shared_ptr<IRExecutionUnit> &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); if (!llvm_module_ap.get()) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) ConstString function_name; if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), m_compiler->getTargetOpts().Features)); ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = target->GetDebugger().GetErrorFile().get(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); Error interpret_error; can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error); Process *process = exe_ctx.GetProcessPtr(); if (!ir_can_run) { err.SetErrorString("The expression could not be prepared to run in the target"); return err; } if (!can_interpret && execution_policy == eExecutionPolicyNever) { err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); return err; } if (!process && execution_policy == eExecutionPolicyAlways) { err.SetErrorString("Expression needed to run in the target, but the target can't be run"); return err; } if (execution_policy == eExecutionPolicyAlways || !can_interpret) { if (m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); StreamString install_errors; if (!dynamic_checkers->Install(install_errors, exe_ctx)) { if (install_errors.GetString().empty()) err.SetErrorString ("couldn't install checkers, unknown error"); else err.SetErrorString (install_errors.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } else { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } return err; }
Error RegisterContext::ReadRegisterValueFromMemory (const RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value) { Error error; if (reg_info == NULL) { error.SetErrorString ("invalid register info argument."); return error; } // Moving from addr into a register // // Case 1: src_len == dst_len // // |AABBCCDD| Address contents // |AABBCCDD| Register contents // // Case 2: src_len > dst_len // // Error! (The register should always be big enough to hold the data) // // Case 3: src_len < dst_len // // |AABB| Address contents // |AABB0000| Register contents [on little-endian hardware] // |0000AABB| Register contents [on big-endian hardware] if (src_len > RegisterValue::kMaxRegisterByteSize) { error.SetErrorString ("register too small to receive memory data"); return error; } const uint32_t dst_len = reg_info->byte_size; if (src_len > dst_len) { error.SetErrorStringWithFormat("%u bytes is too big to store in register %s (%u bytes)", src_len, reg_info->name, dst_len); return error; } ProcessSP process_sp (m_thread.GetProcess()); if (process_sp) { uint8_t src[RegisterValue::kMaxRegisterByteSize]; // Read the memory const uint32_t bytes_read = process_sp->ReadMemory (src_addr, src, src_len, error); // Make sure the memory read succeeded... if (bytes_read != src_len) { if (error.Success()) { // This might happen if we read _some_ bytes but not all error.SetErrorStringWithFormat("read %u of %u bytes", bytes_read, src_len); } return error; } // We now have a memory buffer that contains the part or all of the register // value. Set the register value using this memory data. // TODO: we might need to add a parameter to this function in case the byte // order of the memory data doesn't match the process. For now we are assuming // they are the same. reg_value.SetFromMemoryData (reg_info, src, src_len, process_sp->GetByteOrder(), error); } else error.SetErrorString("invalid process"); return error; }
//---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Error ProcessElfCore::DoLoadCore () { Error error; if (!m_core_module_sp) { error.SetErrorString ("invalid core module"); return error; } ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); if (core == NULL) { error.SetErrorString ("invalid core object file"); return error; } const uint32_t num_segments = core->GetProgramHeaderCount(); if (num_segments == 0) { error.SetErrorString ("core file has no segments"); return error; } SetCanJIT(false); m_thread_data_valid = true; bool ranges_are_sorted = true; lldb::addr_t vm_addr = 0; /// Walk through segments and Thread and Address Map information. /// PT_NOTE - Contains Thread and Register information /// PT_LOAD - Contains a contiguous range of Process Address Space for(uint32_t i = 1; i <= num_segments; i++) { const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i); assert(header != NULL); DataExtractor data = core->GetSegmentDataByIndex(i); // Parse thread contexts and auxv structure if (header->p_type == llvm::ELF::PT_NOTE) ParseThreadContextsFromNoteSegment(header, data); // PT_LOAD segments contains address map if (header->p_type == llvm::ELF::PT_LOAD) { lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header); if (vm_addr > last_addr) ranges_are_sorted = false; vm_addr = last_addr; } } if (!ranges_are_sorted) { m_core_aranges.Sort(); m_core_range_infos.Sort(); } // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.IsValid()) GetTarget().SetArchitecture(arch); SetUnixSignals(UnixSignals::Create(GetArchitecture())); // Core files are useless without the main executable. See if we can locate the main // executable using data we found in the core file notes. lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); if (!exe_module_sp) { // The first entry in the NT_FILE might be our executable if (!m_nt_file_entries.empty()) { ModuleSpec exe_module_spec; exe_module_spec.GetArchitecture() = arch; exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path.GetCString(), false); if (exe_module_spec.GetFileSpec()) { exe_module_sp = GetTarget().GetSharedModule(exe_module_spec); if (exe_module_sp) GetTarget().SetExecutableModule(exe_module_sp, false); } } } return error; }
//---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Error ProcessElfCore::DoLoadCore () { Error error; if (!m_core_module_sp) { error.SetErrorString ("invalid core module"); return error; } ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); if (core == NULL) { error.SetErrorString ("invalid core object file"); return error; } const uint32_t num_segments = core->GetProgramHeaderCount(); if (num_segments == 0) { error.SetErrorString ("core file has no segments"); return error; } SetCanJIT(false); m_thread_data_valid = true; bool ranges_are_sorted = true; lldb::addr_t vm_addr = 0; /// Walk through segments and Thread and Address Map information. /// PT_NOTE - Contains Thread and Register information /// PT_LOAD - Contains a contiguous range of Process Address Space for(uint32_t i = 1; i <= num_segments; i++) { const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i); assert(header != NULL); DataExtractor data = core->GetSegmentDataByIndex(i); // Parse thread contexts and auxv structure if (header->p_type == llvm::ELF::PT_NOTE) ParseThreadContextsFromNoteSegment(header, data); // PT_LOAD segments contains address map if (header->p_type == llvm::ELF::PT_LOAD) { lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header); if (vm_addr > last_addr) ranges_are_sorted = false; vm_addr = last_addr; } } if (!ranges_are_sorted) m_core_aranges.Sort(); // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch (m_core_module_sp->GetArchitecture()); if (arch.IsValid()) m_target.SetArchitecture(arch); SetUnixSignals(UnixSignals::Create(GetArchitecture())); return error; }