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