1 //===-- PlatformPOSIX.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PlatformPOSIX.h" 10 11 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 12 #include "lldb/Core/Debugger.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/ValueObject.h" 15 #include "lldb/Expression/DiagnosticManager.h" 16 #include "lldb/Expression/FunctionCaller.h" 17 #include "lldb/Expression/UserExpression.h" 18 #include "lldb/Expression/UtilityFunction.h" 19 #include "lldb/Host/File.h" 20 #include "lldb/Host/FileCache.h" 21 #include "lldb/Host/FileSystem.h" 22 #include "lldb/Host/Host.h" 23 #include "lldb/Host/HostInfo.h" 24 #include "lldb/Host/ProcessLaunchInfo.h" 25 #include "lldb/Target/DynamicLoader.h" 26 #include "lldb/Target/ExecutionContext.h" 27 #include "lldb/Target/Process.h" 28 #include "lldb/Target/Thread.h" 29 #include "lldb/Utility/DataBufferHeap.h" 30 #include "lldb/Utility/FileSpec.h" 31 #include "lldb/Utility/LLDBLog.h" 32 #include "lldb/Utility/Log.h" 33 #include "lldb/Utility/StreamString.h" 34 #include "llvm/ADT/ScopeExit.h" 35 36 using namespace lldb; 37 using namespace lldb_private; 38 39 /// Default Constructor 40 PlatformPOSIX::PlatformPOSIX(bool is_host) 41 : RemoteAwarePlatform(is_host), // This is the local host platform 42 m_option_group_platform_rsync(new OptionGroupPlatformRSync()), 43 m_option_group_platform_ssh(new OptionGroupPlatformSSH()), 44 m_option_group_platform_caching(new OptionGroupPlatformCaching()) {} 45 46 /// Destructor. 47 /// 48 /// The destructor is virtual since this class is designed to be 49 /// inherited from by the plug-in instance. 50 PlatformPOSIX::~PlatformPOSIX() = default; 51 52 lldb_private::OptionGroupOptions *PlatformPOSIX::GetConnectionOptions( 53 lldb_private::CommandInterpreter &interpreter) { 54 auto iter = m_options.find(&interpreter), end = m_options.end(); 55 if (iter == end) { 56 std::unique_ptr<lldb_private::OptionGroupOptions> options( 57 new OptionGroupOptions()); 58 options->Append(m_option_group_platform_rsync.get()); 59 options->Append(m_option_group_platform_ssh.get()); 60 options->Append(m_option_group_platform_caching.get()); 61 m_options[&interpreter] = std::move(options); 62 } 63 64 return m_options.at(&interpreter).get(); 65 } 66 67 static uint32_t chown_file(Platform *platform, const char *path, 68 uint32_t uid = UINT32_MAX, 69 uint32_t gid = UINT32_MAX) { 70 if (!platform || !path || *path == 0) 71 return UINT32_MAX; 72 73 if (uid == UINT32_MAX && gid == UINT32_MAX) 74 return 0; // pretend I did chown correctly - actually I just didn't care 75 76 StreamString command; 77 command.PutCString("chown "); 78 if (uid != UINT32_MAX) 79 command.Printf("%d", uid); 80 if (gid != UINT32_MAX) 81 command.Printf(":%d", gid); 82 command.Printf("%s", path); 83 int status; 84 platform->RunShellCommand(command.GetData(), FileSpec(), &status, nullptr, 85 nullptr, std::chrono::seconds(10)); 86 return status; 87 } 88 89 lldb_private::Status 90 PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, 91 const lldb_private::FileSpec &destination, uint32_t uid, 92 uint32_t gid) { 93 Log *log = GetLog(LLDBLog::Platform); 94 95 if (IsHost()) { 96 if (source == destination) 97 return Status(); 98 // cp src dst 99 // chown uid:gid dst 100 std::string src_path(source.GetPath()); 101 if (src_path.empty()) 102 return Status("unable to get file path for source"); 103 std::string dst_path(destination.GetPath()); 104 if (dst_path.empty()) 105 return Status("unable to get file path for destination"); 106 StreamString command; 107 command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 108 int status; 109 RunShellCommand(command.GetData(), FileSpec(), &status, nullptr, nullptr, 110 std::chrono::seconds(10)); 111 if (status != 0) 112 return Status("unable to perform copy"); 113 if (uid == UINT32_MAX && gid == UINT32_MAX) 114 return Status(); 115 if (chown_file(this, dst_path.c_str(), uid, gid) != 0) 116 return Status("unable to perform chown"); 117 return Status(); 118 } else if (m_remote_platform_sp) { 119 if (GetSupportsRSync()) { 120 std::string src_path(source.GetPath()); 121 if (src_path.empty()) 122 return Status("unable to get file path for source"); 123 std::string dst_path(destination.GetPath()); 124 if (dst_path.empty()) 125 return Status("unable to get file path for destination"); 126 StreamString command; 127 if (GetIgnoresRemoteHostname()) { 128 if (!GetRSyncPrefix()) 129 command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(), 130 dst_path.c_str()); 131 else 132 command.Printf("rsync %s %s %s%s", GetRSyncOpts(), src_path.c_str(), 133 GetRSyncPrefix(), dst_path.c_str()); 134 } else 135 command.Printf("rsync %s %s %s:%s", GetRSyncOpts(), src_path.c_str(), 136 GetHostname(), dst_path.c_str()); 137 LLDB_LOGF(log, "[PutFile] Running command: %s\n", command.GetData()); 138 int retcode; 139 Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr, 140 nullptr, std::chrono::minutes(1)); 141 if (retcode == 0) { 142 // Don't chown a local file for a remote system 143 // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 144 // return Status("unable to perform chown"); 145 return Status(); 146 } 147 // if we are still here rsync has failed - let's try the slow way before 148 // giving up 149 } 150 } 151 return Platform::PutFile(source, destination, uid, gid); 152 } 153 154 lldb_private::Status PlatformPOSIX::GetFile( 155 const lldb_private::FileSpec &source, // remote file path 156 const lldb_private::FileSpec &destination) // local file path 157 { 158 Log *log = GetLog(LLDBLog::Platform); 159 160 // Check the args, first. 161 std::string src_path(source.GetPath()); 162 if (src_path.empty()) 163 return Status("unable to get file path for source"); 164 std::string dst_path(destination.GetPath()); 165 if (dst_path.empty()) 166 return Status("unable to get file path for destination"); 167 if (IsHost()) { 168 if (source == destination) 169 return Status("local scenario->source and destination are the same file " 170 "path: no operation performed"); 171 // cp src dst 172 StreamString cp_command; 173 cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 174 int status; 175 RunShellCommand(cp_command.GetData(), FileSpec(), &status, nullptr, nullptr, 176 std::chrono::seconds(10)); 177 if (status != 0) 178 return Status("unable to perform copy"); 179 return Status(); 180 } else if (m_remote_platform_sp) { 181 if (GetSupportsRSync()) { 182 StreamString command; 183 if (GetIgnoresRemoteHostname()) { 184 if (!GetRSyncPrefix()) 185 command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(), 186 dst_path.c_str()); 187 else 188 command.Printf("rsync %s %s%s %s", GetRSyncOpts(), GetRSyncPrefix(), 189 src_path.c_str(), dst_path.c_str()); 190 } else 191 command.Printf("rsync %s %s:%s %s", GetRSyncOpts(), 192 m_remote_platform_sp->GetHostname(), src_path.c_str(), 193 dst_path.c_str()); 194 LLDB_LOGF(log, "[GetFile] Running command: %s\n", command.GetData()); 195 int retcode; 196 Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr, 197 nullptr, std::chrono::minutes(1)); 198 if (retcode == 0) 199 return Status(); 200 // If we are here, rsync has failed - let's try the slow way before 201 // giving up 202 } 203 // open src and dst 204 // read/write, read/write, read/write, ... 205 // close src 206 // close dst 207 LLDB_LOGF(log, "[GetFile] Using block by block transfer....\n"); 208 Status error; 209 user_id_t fd_src = OpenFile(source, File::eOpenOptionReadOnly, 210 lldb::eFilePermissionsFileDefault, error); 211 212 if (fd_src == UINT64_MAX) 213 return Status("unable to open source file"); 214 215 uint32_t permissions = 0; 216 error = GetFilePermissions(source, permissions); 217 218 if (permissions == 0) 219 permissions = lldb::eFilePermissionsFileDefault; 220 221 user_id_t fd_dst = FileCache::GetInstance().OpenFile( 222 destination, File::eOpenOptionCanCreate | File::eOpenOptionWriteOnly | 223 File::eOpenOptionTruncate, 224 permissions, error); 225 226 if (fd_dst == UINT64_MAX) { 227 if (error.Success()) 228 error.SetErrorString("unable to open destination file"); 229 } 230 231 if (error.Success()) { 232 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 233 uint64_t offset = 0; 234 error.Clear(); 235 while (error.Success()) { 236 const uint64_t n_read = ReadFile(fd_src, offset, buffer_sp->GetBytes(), 237 buffer_sp->GetByteSize(), error); 238 if (error.Fail()) 239 break; 240 if (n_read == 0) 241 break; 242 if (FileCache::GetInstance().WriteFile(fd_dst, offset, 243 buffer_sp->GetBytes(), n_read, 244 error) != n_read) { 245 if (!error.Fail()) 246 error.SetErrorString("unable to write to destination file"); 247 break; 248 } 249 offset += n_read; 250 } 251 } 252 // Ignore the close error of src. 253 if (fd_src != UINT64_MAX) 254 CloseFile(fd_src, error); 255 // And close the dst file descriptot. 256 if (fd_dst != UINT64_MAX && 257 !FileCache::GetInstance().CloseFile(fd_dst, error)) { 258 if (!error.Fail()) 259 error.SetErrorString("unable to close destination file"); 260 } 261 return error; 262 } 263 return Platform::GetFile(source, destination); 264 } 265 266 std::string PlatformPOSIX::GetPlatformSpecificConnectionInformation() { 267 StreamString stream; 268 if (GetSupportsRSync()) { 269 stream.PutCString("rsync"); 270 if ((GetRSyncOpts() && *GetRSyncOpts()) || 271 (GetRSyncPrefix() && *GetRSyncPrefix()) || GetIgnoresRemoteHostname()) { 272 stream.Printf(", options: "); 273 if (GetRSyncOpts() && *GetRSyncOpts()) 274 stream.Printf("'%s' ", GetRSyncOpts()); 275 stream.Printf(", prefix: "); 276 if (GetRSyncPrefix() && *GetRSyncPrefix()) 277 stream.Printf("'%s' ", GetRSyncPrefix()); 278 if (GetIgnoresRemoteHostname()) 279 stream.Printf("ignore remote-hostname "); 280 } 281 } 282 if (GetSupportsSSH()) { 283 stream.PutCString("ssh"); 284 if (GetSSHOpts() && *GetSSHOpts()) 285 stream.Printf(", options: '%s' ", GetSSHOpts()); 286 } 287 if (GetLocalCacheDirectory() && *GetLocalCacheDirectory()) 288 stream.Printf("cache dir: %s", GetLocalCacheDirectory()); 289 if (stream.GetSize()) 290 return std::string(stream.GetString()); 291 else 292 return ""; 293 } 294 295 const lldb::UnixSignalsSP &PlatformPOSIX::GetRemoteUnixSignals() { 296 if (IsRemote() && m_remote_platform_sp) 297 return m_remote_platform_sp->GetRemoteUnixSignals(); 298 return Platform::GetRemoteUnixSignals(); 299 } 300 301 Status PlatformPOSIX::ConnectRemote(Args &args) { 302 Status error; 303 if (IsHost()) { 304 error.SetErrorStringWithFormatv( 305 "can't connect to the host platform '{0}', always connected", 306 GetPluginName()); 307 } else { 308 if (!m_remote_platform_sp) 309 m_remote_platform_sp = 310 Platform::Create(ConstString("remote-gdb-server"), error); 311 312 if (m_remote_platform_sp && error.Success()) 313 error = m_remote_platform_sp->ConnectRemote(args); 314 else 315 error.SetErrorString("failed to create a 'remote-gdb-server' platform"); 316 317 if (error.Fail()) 318 m_remote_platform_sp.reset(); 319 } 320 321 if (error.Success() && m_remote_platform_sp) { 322 if (m_option_group_platform_rsync.get() && 323 m_option_group_platform_ssh.get() && 324 m_option_group_platform_caching.get()) { 325 if (m_option_group_platform_rsync->m_rsync) { 326 SetSupportsRSync(true); 327 SetRSyncOpts(m_option_group_platform_rsync->m_rsync_opts.c_str()); 328 SetRSyncPrefix(m_option_group_platform_rsync->m_rsync_prefix.c_str()); 329 SetIgnoresRemoteHostname( 330 m_option_group_platform_rsync->m_ignores_remote_hostname); 331 } 332 if (m_option_group_platform_ssh->m_ssh) { 333 SetSupportsSSH(true); 334 SetSSHOpts(m_option_group_platform_ssh->m_ssh_opts.c_str()); 335 } 336 SetLocalCacheDirectory( 337 m_option_group_platform_caching->m_cache_dir.c_str()); 338 } 339 } 340 341 return error; 342 } 343 344 Status PlatformPOSIX::DisconnectRemote() { 345 Status error; 346 347 if (IsHost()) { 348 error.SetErrorStringWithFormatv( 349 "can't disconnect from the host platform '{0}', always connected", 350 GetPluginName()); 351 } else { 352 if (m_remote_platform_sp) 353 error = m_remote_platform_sp->DisconnectRemote(); 354 else 355 error.SetErrorString("the platform is not currently connected"); 356 } 357 return error; 358 } 359 360 lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info, 361 Debugger &debugger, Target *target, 362 Status &error) { 363 lldb::ProcessSP process_sp; 364 Log *log = GetLog(LLDBLog::Platform); 365 366 if (IsHost()) { 367 if (target == nullptr) { 368 TargetSP new_target_sp; 369 370 error = debugger.GetTargetList().CreateTarget( 371 debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); 372 target = new_target_sp.get(); 373 LLDB_LOGF(log, "PlatformPOSIX::%s created new target", __FUNCTION__); 374 } else { 375 error.Clear(); 376 LLDB_LOGF(log, "PlatformPOSIX::%s target already existed, setting target", 377 __FUNCTION__); 378 } 379 380 if (target && error.Success()) { 381 if (log) { 382 ModuleSP exe_module_sp = target->GetExecutableModule(); 383 LLDB_LOGF(log, "PlatformPOSIX::%s set selected target to %p %s", 384 __FUNCTION__, (void *)target, 385 exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() 386 : "<null>"); 387 } 388 389 process_sp = 390 target->CreateProcess(attach_info.GetListenerForProcess(debugger), 391 "gdb-remote", nullptr, true); 392 393 if (process_sp) { 394 ListenerSP listener_sp = attach_info.GetHijackListener(); 395 if (listener_sp == nullptr) { 396 listener_sp = 397 Listener::MakeListener("lldb.PlatformPOSIX.attach.hijack"); 398 attach_info.SetHijackListener(listener_sp); 399 } 400 process_sp->HijackProcessEvents(listener_sp); 401 error = process_sp->Attach(attach_info); 402 } 403 } 404 } else { 405 if (m_remote_platform_sp) 406 process_sp = 407 m_remote_platform_sp->Attach(attach_info, debugger, target, error); 408 else 409 error.SetErrorString("the platform is not currently connected"); 410 } 411 return process_sp; 412 } 413 414 lldb::ProcessSP PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info, 415 Debugger &debugger, Target &target, 416 Status &error) { 417 Log *log = GetLog(LLDBLog::Platform); 418 LLDB_LOG(log, "target {0}", &target); 419 420 ProcessSP process_sp; 421 422 if (!IsHost()) { 423 if (m_remote_platform_sp) 424 process_sp = m_remote_platform_sp->DebugProcess(launch_info, debugger, 425 target, error); 426 else 427 error.SetErrorString("the platform is not currently connected"); 428 return process_sp; 429 } 430 431 // 432 // For local debugging, we'll insist on having ProcessGDBRemote create the 433 // process. 434 // 435 436 // Make sure we stop at the entry point 437 launch_info.GetFlags().Set(eLaunchFlagDebug); 438 439 // We always launch the process we are going to debug in a separate process 440 // group, since then we can handle ^C interrupts ourselves w/o having to 441 // worry about the target getting them as well. 442 launch_info.SetLaunchInSeparateProcessGroup(true); 443 444 // Now create the gdb-remote process. 445 LLDB_LOG(log, "having target create process with gdb-remote plugin"); 446 process_sp = 447 target.CreateProcess(launch_info.GetListener(), "gdb-remote", nullptr, 448 true); 449 450 if (!process_sp) { 451 error.SetErrorString("CreateProcess() failed for gdb-remote process"); 452 LLDB_LOG(log, "error: {0}", error); 453 return process_sp; 454 } 455 456 LLDB_LOG(log, "successfully created process"); 457 // Adjust launch for a hijacker. 458 ListenerSP listener_sp; 459 if (!launch_info.GetHijackListener()) { 460 LLDB_LOG(log, "setting up hijacker"); 461 listener_sp = 462 Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack"); 463 launch_info.SetHijackListener(listener_sp); 464 process_sp->HijackProcessEvents(listener_sp); 465 } 466 467 // Log file actions. 468 if (log) { 469 LLDB_LOG(log, "launching process with the following file actions:"); 470 StreamString stream; 471 size_t i = 0; 472 const FileAction *file_action; 473 while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) { 474 file_action->Dump(stream); 475 LLDB_LOG(log, "{0}", stream.GetData()); 476 stream.Clear(); 477 } 478 } 479 480 // Do the launch. 481 error = process_sp->Launch(launch_info); 482 if (error.Success()) { 483 // Handle the hijacking of process events. 484 if (listener_sp) { 485 const StateType state = process_sp->WaitForProcessToStop( 486 llvm::None, nullptr, false, listener_sp); 487 488 LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state); 489 } 490 491 // Hook up process PTY if we have one (which we should for local debugging 492 // with llgs). 493 int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor(); 494 if (pty_fd != PseudoTerminal::invalid_fd) { 495 process_sp->SetSTDIOFileDescriptor(pty_fd); 496 LLDB_LOG(log, "hooked up STDIO pty to process"); 497 } else 498 LLDB_LOG(log, "not using process STDIO pty"); 499 } else { 500 LLDB_LOG(log, "{0}", error); 501 // FIXME figure out appropriate cleanup here. Do we delete the process? 502 // Does our caller do that? 503 } 504 505 return process_sp; 506 } 507 508 void PlatformPOSIX::CalculateTrapHandlerSymbolNames() { 509 m_trap_handlers.push_back(ConstString("_sigtramp")); 510 } 511 512 Status PlatformPOSIX::EvaluateLibdlExpression( 513 lldb_private::Process *process, const char *expr_cstr, 514 llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { 515 DynamicLoader *loader = process->GetDynamicLoader(); 516 if (loader) { 517 Status error = loader->CanLoadImage(); 518 if (error.Fail()) 519 return error; 520 } 521 522 ThreadSP thread_sp(process->GetThreadList().GetExpressionExecutionThread()); 523 if (!thread_sp) 524 return Status("Selected thread isn't valid"); 525 526 StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); 527 if (!frame_sp) 528 return Status("Frame 0 isn't valid"); 529 530 ExecutionContext exe_ctx; 531 frame_sp->CalculateExecutionContext(exe_ctx); 532 EvaluateExpressionOptions expr_options; 533 expr_options.SetUnwindOnError(true); 534 expr_options.SetIgnoreBreakpoints(true); 535 expr_options.SetExecutionPolicy(eExecutionPolicyAlways); 536 expr_options.SetLanguage(eLanguageTypeC_plus_plus); 537 expr_options.SetTrapExceptions(false); // dlopen can't throw exceptions, so 538 // don't do the work to trap them. 539 expr_options.SetTimeout(process->GetUtilityExpressionTimeout()); 540 541 Status expr_error; 542 ExpressionResults result = 543 UserExpression::Evaluate(exe_ctx, expr_options, expr_cstr, expr_prefix, 544 result_valobj_sp, expr_error); 545 if (result != eExpressionCompleted) 546 return expr_error; 547 548 if (result_valobj_sp->GetError().Fail()) 549 return result_valobj_sp->GetError(); 550 return Status(); 551 } 552 553 std::unique_ptr<UtilityFunction> 554 PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, 555 Status &error) { 556 // Remember to prepend this with the prefix from 557 // GetLibdlFunctionDeclarations. The returned values are all in 558 // __lldb_dlopen_result for consistency. The wrapper returns a void * but 559 // doesn't use it because UtilityFunctions don't work with void returns at 560 // present. 561 // 562 // Use lazy binding so as to not make dlopen()'s success conditional on 563 // forcing every symbol in the library. 564 // 565 // In general, the debugger should allow programs to load & run with 566 // libraries as far as they can, instead of defaulting to being super-picky 567 // about unavailable symbols. 568 // 569 // The value "1" appears to imply lazy binding (RTLD_LAZY) on both Darwin 570 // and other POSIX OSes. 571 static const char *dlopen_wrapper_code = R"( 572 const int RTLD_LAZY = 1; 573 574 struct __lldb_dlopen_result { 575 void *image_ptr; 576 const char *error_str; 577 }; 578 579 extern void *memcpy(void *, const void *, size_t size); 580 extern size_t strlen(const char *); 581 582 583 void * __lldb_dlopen_wrapper (const char *name, 584 const char *path_strings, 585 char *buffer, 586 __lldb_dlopen_result *result_ptr) 587 { 588 // This is the case where the name is the full path: 589 if (!path_strings) { 590 result_ptr->image_ptr = dlopen(name, RTLD_LAZY); 591 if (result_ptr->image_ptr) 592 result_ptr->error_str = nullptr; 593 else 594 result_ptr->error_str = dlerror(); 595 return nullptr; 596 } 597 598 // This is the case where we have a list of paths: 599 size_t name_len = strlen(name); 600 while (path_strings && path_strings[0] != '\0') { 601 size_t path_len = strlen(path_strings); 602 memcpy((void *) buffer, (void *) path_strings, path_len); 603 buffer[path_len] = '/'; 604 char *target_ptr = buffer+path_len+1; 605 memcpy((void *) target_ptr, (void *) name, name_len + 1); 606 result_ptr->image_ptr = dlopen(buffer, RTLD_LAZY); 607 if (result_ptr->image_ptr) { 608 result_ptr->error_str = nullptr; 609 break; 610 } 611 result_ptr->error_str = dlerror(); 612 path_strings = path_strings + path_len + 1; 613 } 614 return nullptr; 615 } 616 )"; 617 618 static const char *dlopen_wrapper_name = "__lldb_dlopen_wrapper"; 619 Process *process = exe_ctx.GetProcessSP().get(); 620 // Insert the dlopen shim defines into our generic expression: 621 std::string expr(std::string(GetLibdlFunctionDeclarations(process))); 622 expr.append(dlopen_wrapper_code); 623 Status utility_error; 624 DiagnosticManager diagnostics; 625 626 auto utility_fn_or_error = process->GetTarget().CreateUtilityFunction( 627 std::move(expr), dlopen_wrapper_name, eLanguageTypeObjC, exe_ctx); 628 if (!utility_fn_or_error) { 629 std::string error_str = llvm::toString(utility_fn_or_error.takeError()); 630 error.SetErrorStringWithFormat("dlopen error: could not create utility" 631 "function: %s", 632 error_str.c_str()); 633 return nullptr; 634 } 635 std::unique_ptr<UtilityFunction> dlopen_utility_func_up = 636 std::move(*utility_fn_or_error); 637 638 Value value; 639 ValueList arguments; 640 FunctionCaller *do_dlopen_function = nullptr; 641 642 // Fetch the clang types we will need: 643 TypeSystemClang *ast = 644 ScratchTypeSystemClang::GetForTarget(process->GetTarget()); 645 if (!ast) 646 return nullptr; 647 648 CompilerType clang_void_pointer_type 649 = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); 650 CompilerType clang_char_pointer_type 651 = ast->GetBasicType(eBasicTypeChar).GetPointerType(); 652 653 // We are passing four arguments, the basename, the list of places to look, 654 // a buffer big enough for all the path + name combos, and 655 // a pointer to the storage we've made for the result: 656 value.SetValueType(Value::ValueType::Scalar); 657 value.SetCompilerType(clang_void_pointer_type); 658 arguments.PushValue(value); 659 value.SetCompilerType(clang_char_pointer_type); 660 arguments.PushValue(value); 661 arguments.PushValue(value); 662 arguments.PushValue(value); 663 664 do_dlopen_function = dlopen_utility_func_up->MakeFunctionCaller( 665 clang_void_pointer_type, arguments, exe_ctx.GetThreadSP(), utility_error); 666 if (utility_error.Fail()) { 667 error.SetErrorStringWithFormat("dlopen error: could not make function" 668 "caller: %s", utility_error.AsCString()); 669 return nullptr; 670 } 671 672 do_dlopen_function = dlopen_utility_func_up->GetFunctionCaller(); 673 if (!do_dlopen_function) { 674 error.SetErrorString("dlopen error: could not get function caller."); 675 return nullptr; 676 } 677 678 // We made a good utility function, so cache it in the process: 679 return dlopen_utility_func_up; 680 } 681 682 uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, 683 const lldb_private::FileSpec &remote_file, 684 const std::vector<std::string> *paths, 685 lldb_private::Status &error, 686 lldb_private::FileSpec *loaded_image) { 687 if (loaded_image) 688 loaded_image->Clear(); 689 690 std::string path; 691 path = remote_file.GetPath(); 692 693 ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); 694 if (!thread_sp) { 695 error.SetErrorString("dlopen error: no thread available to call dlopen."); 696 return LLDB_INVALID_IMAGE_TOKEN; 697 } 698 699 DiagnosticManager diagnostics; 700 701 ExecutionContext exe_ctx; 702 thread_sp->CalculateExecutionContext(exe_ctx); 703 704 Status utility_error; 705 UtilityFunction *dlopen_utility_func; 706 ValueList arguments; 707 FunctionCaller *do_dlopen_function = nullptr; 708 709 // The UtilityFunction is held in the Process. Platforms don't track the 710 // lifespan of the Targets that use them, we can't put this in the Platform. 711 dlopen_utility_func = process->GetLoadImageUtilityFunction( 712 this, [&]() -> std::unique_ptr<UtilityFunction> { 713 return MakeLoadImageUtilityFunction(exe_ctx, error); 714 }); 715 // If we couldn't make it, the error will be in error, so we can exit here. 716 if (!dlopen_utility_func) 717 return LLDB_INVALID_IMAGE_TOKEN; 718 719 do_dlopen_function = dlopen_utility_func->GetFunctionCaller(); 720 if (!do_dlopen_function) { 721 error.SetErrorString("dlopen error: could not get function caller."); 722 return LLDB_INVALID_IMAGE_TOKEN; 723 } 724 arguments = do_dlopen_function->GetArgumentValues(); 725 726 // Now insert the path we are searching for and the result structure into the 727 // target. 728 uint32_t permissions = ePermissionsReadable|ePermissionsWritable; 729 size_t path_len = path.size() + 1; 730 lldb::addr_t path_addr = process->AllocateMemory(path_len, 731 permissions, 732 utility_error); 733 if (path_addr == LLDB_INVALID_ADDRESS) { 734 error.SetErrorStringWithFormat("dlopen error: could not allocate memory" 735 "for path: %s", utility_error.AsCString()); 736 return LLDB_INVALID_IMAGE_TOKEN; 737 } 738 739 // Make sure we deallocate the input string memory: 740 auto path_cleanup = llvm::make_scope_exit([process, path_addr] { 741 // Deallocate the buffer. 742 process->DeallocateMemory(path_addr); 743 }); 744 745 process->WriteMemory(path_addr, path.c_str(), path_len, utility_error); 746 if (utility_error.Fail()) { 747 error.SetErrorStringWithFormat("dlopen error: could not write path string:" 748 " %s", utility_error.AsCString()); 749 return LLDB_INVALID_IMAGE_TOKEN; 750 } 751 752 // Make space for our return structure. It is two pointers big: the token 753 // and the error string. 754 const uint32_t addr_size = process->GetAddressByteSize(); 755 lldb::addr_t return_addr = process->CallocateMemory(2*addr_size, 756 permissions, 757 utility_error); 758 if (utility_error.Fail()) { 759 error.SetErrorStringWithFormat("dlopen error: could not allocate memory" 760 "for path: %s", utility_error.AsCString()); 761 return LLDB_INVALID_IMAGE_TOKEN; 762 } 763 764 // Make sure we deallocate the result structure memory 765 auto return_cleanup = llvm::make_scope_exit([process, return_addr] { 766 // Deallocate the buffer 767 process->DeallocateMemory(return_addr); 768 }); 769 770 // This will be the address of the storage for paths, if we are using them, 771 // or nullptr to signal we aren't. 772 lldb::addr_t path_array_addr = 0x0; 773 llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> 774 path_array_cleanup; 775 776 // This is the address to a buffer large enough to hold the largest path 777 // conjoined with the library name we're passing in. This is a convenience 778 // to avoid having to call malloc in the dlopen function. 779 lldb::addr_t buffer_addr = 0x0; 780 llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> 781 buffer_cleanup; 782 783 // Set the values into our args and write them to the target: 784 if (paths != nullptr) { 785 // First insert the paths into the target. This is expected to be a 786 // continuous buffer with the strings laid out null terminated and 787 // end to end with an empty string terminating the buffer. 788 // We also compute the buffer's required size as we go. 789 size_t buffer_size = 0; 790 std::string path_array; 791 for (auto path : *paths) { 792 // Don't insert empty paths, they will make us abort the path 793 // search prematurely. 794 if (path.empty()) 795 continue; 796 size_t path_size = path.size(); 797 path_array.append(path); 798 path_array.push_back('\0'); 799 if (path_size > buffer_size) 800 buffer_size = path_size; 801 } 802 path_array.push_back('\0'); 803 804 path_array_addr = process->AllocateMemory(path_array.size(), 805 permissions, 806 utility_error); 807 if (path_array_addr == LLDB_INVALID_ADDRESS) { 808 error.SetErrorStringWithFormat("dlopen error: could not allocate memory" 809 "for path array: %s", 810 utility_error.AsCString()); 811 return LLDB_INVALID_IMAGE_TOKEN; 812 } 813 814 // Make sure we deallocate the paths array. 815 path_array_cleanup.emplace([process, path_array_addr]() { 816 // Deallocate the path array. 817 process->DeallocateMemory(path_array_addr); 818 }); 819 820 process->WriteMemory(path_array_addr, path_array.data(), 821 path_array.size(), utility_error); 822 823 if (utility_error.Fail()) { 824 error.SetErrorStringWithFormat("dlopen error: could not write path array:" 825 " %s", utility_error.AsCString()); 826 return LLDB_INVALID_IMAGE_TOKEN; 827 } 828 // Now make spaces in the target for the buffer. We need to add one for 829 // the '/' that the utility function will insert and one for the '\0': 830 buffer_size += path.size() + 2; 831 832 buffer_addr = process->AllocateMemory(buffer_size, 833 permissions, 834 utility_error); 835 if (buffer_addr == LLDB_INVALID_ADDRESS) { 836 error.SetErrorStringWithFormat("dlopen error: could not allocate memory" 837 "for buffer: %s", 838 utility_error.AsCString()); 839 return LLDB_INVALID_IMAGE_TOKEN; 840 } 841 842 // Make sure we deallocate the buffer memory: 843 buffer_cleanup.emplace([process, buffer_addr]() { 844 // Deallocate the buffer. 845 process->DeallocateMemory(buffer_addr); 846 }); 847 } 848 849 arguments.GetValueAtIndex(0)->GetScalar() = path_addr; 850 arguments.GetValueAtIndex(1)->GetScalar() = path_array_addr; 851 arguments.GetValueAtIndex(2)->GetScalar() = buffer_addr; 852 arguments.GetValueAtIndex(3)->GetScalar() = return_addr; 853 854 lldb::addr_t func_args_addr = LLDB_INVALID_ADDRESS; 855 856 diagnostics.Clear(); 857 if (!do_dlopen_function->WriteFunctionArguments(exe_ctx, 858 func_args_addr, 859 arguments, 860 diagnostics)) { 861 error.SetErrorStringWithFormat("dlopen error: could not write function " 862 "arguments: %s", 863 diagnostics.GetString().c_str()); 864 return LLDB_INVALID_IMAGE_TOKEN; 865 } 866 867 // Make sure we clean up the args structure. We can't reuse it because the 868 // Platform lives longer than the process and the Platforms don't get a 869 // signal to clean up cached data when a process goes away. 870 auto args_cleanup = 871 llvm::make_scope_exit([do_dlopen_function, &exe_ctx, func_args_addr] { 872 do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr); 873 }); 874 875 // Now run the caller: 876 EvaluateExpressionOptions options; 877 options.SetExecutionPolicy(eExecutionPolicyAlways); 878 options.SetLanguage(eLanguageTypeC_plus_plus); 879 options.SetIgnoreBreakpoints(true); 880 options.SetUnwindOnError(true); 881 options.SetTrapExceptions(false); // dlopen can't throw exceptions, so 882 // don't do the work to trap them. 883 options.SetTimeout(process->GetUtilityExpressionTimeout()); 884 options.SetIsForUtilityExpr(true); 885 886 Value return_value; 887 // Fetch the clang types we will need: 888 TypeSystemClang *ast = 889 ScratchTypeSystemClang::GetForTarget(process->GetTarget()); 890 if (!ast) { 891 error.SetErrorString("dlopen error: Unable to get TypeSystemClang"); 892 return LLDB_INVALID_IMAGE_TOKEN; 893 } 894 895 CompilerType clang_void_pointer_type 896 = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); 897 898 return_value.SetCompilerType(clang_void_pointer_type); 899 900 ExpressionResults results = do_dlopen_function->ExecuteFunction( 901 exe_ctx, &func_args_addr, options, diagnostics, return_value); 902 if (results != eExpressionCompleted) { 903 error.SetErrorStringWithFormat("dlopen error: failed executing " 904 "dlopen wrapper function: %s", 905 diagnostics.GetString().c_str()); 906 return LLDB_INVALID_IMAGE_TOKEN; 907 } 908 909 // Read the dlopen token from the return area: 910 lldb::addr_t token = process->ReadPointerFromMemory(return_addr, 911 utility_error); 912 if (utility_error.Fail()) { 913 error.SetErrorStringWithFormat("dlopen error: could not read the return " 914 "struct: %s", utility_error.AsCString()); 915 return LLDB_INVALID_IMAGE_TOKEN; 916 } 917 918 // The dlopen succeeded! 919 if (token != 0x0) { 920 if (loaded_image && buffer_addr != 0x0) 921 { 922 // Capture the image which was loaded. We leave it in the buffer on 923 // exit from the dlopen function, so we can just read it from there: 924 std::string name_string; 925 process->ReadCStringFromMemory(buffer_addr, name_string, utility_error); 926 if (utility_error.Success()) 927 loaded_image->SetFile(name_string, llvm::sys::path::Style::posix); 928 } 929 return process->AddImageToken(token); 930 } 931 932 // We got an error, lets read in the error string: 933 std::string dlopen_error_str; 934 lldb::addr_t error_addr 935 = process->ReadPointerFromMemory(return_addr + addr_size, utility_error); 936 if (utility_error.Fail()) { 937 error.SetErrorStringWithFormat("dlopen error: could not read error string: " 938 "%s", utility_error.AsCString()); 939 return LLDB_INVALID_IMAGE_TOKEN; 940 } 941 942 size_t num_chars = process->ReadCStringFromMemory(error_addr + addr_size, 943 dlopen_error_str, 944 utility_error); 945 if (utility_error.Success() && num_chars > 0) 946 error.SetErrorStringWithFormat("dlopen error: %s", 947 dlopen_error_str.c_str()); 948 else 949 error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); 950 951 return LLDB_INVALID_IMAGE_TOKEN; 952 } 953 954 Status PlatformPOSIX::UnloadImage(lldb_private::Process *process, 955 uint32_t image_token) { 956 const addr_t image_addr = process->GetImagePtrFromToken(image_token); 957 if (image_addr == LLDB_INVALID_ADDRESS) 958 return Status("Invalid image token"); 959 960 StreamString expr; 961 expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); 962 llvm::StringRef prefix = GetLibdlFunctionDeclarations(process); 963 lldb::ValueObjectSP result_valobj_sp; 964 Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix, 965 result_valobj_sp); 966 if (error.Fail()) 967 return error; 968 969 if (result_valobj_sp->GetError().Fail()) 970 return result_valobj_sp->GetError(); 971 972 Scalar scalar; 973 if (result_valobj_sp->ResolveValue(scalar)) { 974 if (scalar.UInt(1)) 975 return Status("expression failed: \"%s\"", expr.GetData()); 976 process->ResetImageToken(image_token); 977 } 978 return Status(); 979 } 980 981 llvm::StringRef 982 PlatformPOSIX::GetLibdlFunctionDeclarations(lldb_private::Process *process) { 983 return R"( 984 extern "C" void* dlopen(const char*, int); 985 extern "C" void* dlsym(void*, const char*); 986 extern "C" int dlclose(void*); 987 extern "C" char* dlerror(void); 988 )"; 989 } 990 991 ConstString PlatformPOSIX::GetFullNameForDylib(ConstString basename) { 992 if (basename.IsEmpty()) 993 return basename; 994 995 StreamString stream; 996 stream.Printf("lib%s.so", basename.GetCString()); 997 return ConstString(stream.GetString()); 998 } 999