1 //===-- NativeProcessDarwin.cpp ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "NativeProcessDarwin.h"
13 #include <mach/mach_init.h>
14 #include <mach/mach_traps.h>
15 #include <sys/ptrace.h>
17 #include <sys/sysctl.h>
18 #include <sys/types.h>
22 #include "lldb/Core/State.h"
23 #include "lldb/Host/PseudoTerminal.h"
24 #include "lldb/Target/ProcessLaunchInfo.h"
25 #include "lldb/Utility/Log.h"
26 #include "lldb/Utility/StreamString.h"
30 #include "DarwinProcessLauncher.h"
32 #include "MachException.h"
34 #include "llvm/Support/FileSystem.h"
37 using namespace lldb_private;
38 using namespace lldb_private::process_darwin;
39 using namespace lldb_private::darwin_process_launcher;
41 // -----------------------------------------------------------------------------
43 // -----------------------------------------------------------------------------
46 struct hack_task_dyld_info {
47 mach_vm_address_t all_image_info_addr;
48 mach_vm_size_t all_image_info_size;
52 // -----------------------------------------------------------------------------
53 // Public Static Methods
54 // -----------------------------------------------------------------------------
56 Status NativeProcessProtocol::Launch(
57 ProcessLaunchInfo &launch_info,
58 NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
59 NativeProcessProtocolSP &native_process_sp) {
60 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
64 // Verify the working directory is valid if one was specified.
65 FileSpec working_dir(launch_info.GetWorkingDirectory());
67 (!working_dir.ResolvePath() ||
68 !llvm::sys::fs::is_directory(working_dir.GetPath())) {
69 error.SetErrorStringWithFormat("No such file or directory: %s",
70 working_dir.GetCString());
74 // Launch the inferior.
75 int pty_master_fd = -1;
76 LaunchFlavor launch_flavor = LaunchFlavor::Default;
78 error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor);
80 // Handle launch failure.
81 if (!error.Success()) {
83 log->Printf("NativeProcessDarwin::%s() failed to launch process: "
85 __FUNCTION__, error.AsCString());
89 // Handle failure to return a pid.
90 if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
92 log->Printf("NativeProcessDarwin::%s() launch succeeded but no "
93 "pid was returned! Aborting.",
98 // Create the Darwin native process impl.
99 std::shared_ptr<NativeProcessDarwin> np_darwin_sp(
100 new NativeProcessDarwin(launch_info.GetProcessID(), pty_master_fd));
101 if (!np_darwin_sp->RegisterNativeDelegate(native_delegate)) {
102 native_process_sp.reset();
103 error.SetErrorStringWithFormat("failed to register the native delegate");
107 // Finalize the processing needed to debug the launched process with
108 // a NativeProcessDarwin instance.
109 error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop);
110 if (!error.Success()) {
112 log->Printf("NativeProcessDarwin::%s() aborting, failed to finalize"
113 " the launching of the process: %s",
114 __FUNCTION__, error.AsCString());
118 // Return the process and process id to the caller through the launch args.
119 native_process_sp = np_darwin_sp;
123 Status NativeProcessProtocol::Attach(
124 lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
125 MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
126 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
128 log->Printf("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__,
131 // Retrieve the architecture for the running process.
132 ArchSpec process_arch;
133 Status error = ResolveProcessArchitecture(pid, process_arch);
134 if (!error.Success())
137 // TODO get attach to return this value.
138 const int pty_master_fd = -1;
139 std::shared_ptr<NativeProcessDarwin> native_process_darwin_sp(
140 new NativeProcessDarwin(pid, pty_master_fd));
142 if (!native_process_darwin_sp->RegisterNativeDelegate(native_delegate)) {
143 error.SetErrorStringWithFormat("failed to register the native "
148 native_process_darwin_sp->AttachToInferior(mainloop, pid, error);
149 if (!error.Success())
152 native_process_sp = native_process_darwin_sp;
156 // -----------------------------------------------------------------------------
158 // -----------------------------------------------------------------------------
160 NativeProcessDarwin::NativeProcessDarwin(lldb::pid_t pid, int pty_master_fd)
161 : NativeProcessProtocol(pid), m_task(TASK_NULL), m_did_exec(false),
162 m_cpu_type(0), m_exception_port(MACH_PORT_NULL), m_exc_port_info(),
163 m_exception_thread(nullptr), m_exception_messages_mutex(),
164 m_sent_interrupt_signo(0), m_auto_resume_signo(0), m_thread_list(),
165 m_thread_actions(), m_waitpid_pipe(), m_waitpid_thread(nullptr),
166 m_waitpid_reader_handle() {
167 // TODO add this to the NativeProcessProtocol constructor.
168 m_terminal_fd = pty_master_fd;
171 NativeProcessDarwin::~NativeProcessDarwin() {}
173 // -----------------------------------------------------------------------------
175 // -----------------------------------------------------------------------------
177 Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
178 MainLoop &main_loop) {
180 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
186 for (i=0; (arg = argv[i]) != NULL; i++)
187 m_args.push_back(arg);
190 error = StartExceptionThread();
191 if (!error.Success()) {
193 log->Printf("NativeProcessDarwin::%s(): failure starting the "
194 "mach exception port monitor thread: %s",
195 __FUNCTION__, error.AsCString());
197 // Terminate the inferior process. There's nothing meaningful we can
198 // do if we can't receive signals and exceptions. Since we launched
199 // the process, it's fair game for us to kill it.
200 ::ptrace(PT_KILL, m_pid, 0, 0);
201 SetState(eStateExited);
208 if (launch_flavor == LaunchFlavor::PosixSpawn) {
209 SetState(eStateAttaching);
211 int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);
213 // m_flags |= eMachProcessFlagsAttached;
215 log->Printf("NativeProcessDarwin::%s(): successfully spawned "
216 "process with pid %" PRIu64,
217 __FUNCTION__, m_pid);
219 error.SetErrorToErrno();
220 SetState(eStateExited);
222 log->Printf("NativeProcessDarwin::%s(): error: failed to "
223 "attach to spawned pid %" PRIu64 " (error=%d (%s))",
224 __FUNCTION__, m_pid, (int)error.GetError(),
231 log->Printf("NativeProcessDarwin::%s(): new pid is %" PRIu64 "...",
232 __FUNCTION__, m_pid);
234 // Spawn a thread to reap our child inferior process...
235 error = StartWaitpidThread(main_loop);
238 log->Printf("NativeProcessDarwin::%s(): failed to start waitpid() "
240 __FUNCTION__, error.AsCString());
241 kill(SIGKILL, static_cast<::pid_t>(m_pid));
245 if (TaskPortForProcessID(error) == TASK_NULL) {
246 // We failed to get the task for our process ID which is bad.
247 // Kill our process; otherwise, it will be stopped at the entry
248 // point and get reparented to someone else and never go away.
250 log->Printf("NativeProcessDarwin::%s(): could not get task port "
251 "for process, sending SIGKILL and exiting: %s",
252 __FUNCTION__, error.AsCString());
253 kill(SIGKILL, static_cast<::pid_t>(m_pid));
257 // Indicate that we're stopped, as we always launch suspended.
258 SetState(eStateStopped);
264 Status NativeProcessDarwin::SaveExceptionPortInfo() {
265 return m_exc_port_info.Save(m_task);
268 bool NativeProcessDarwin::ProcessUsingSpringBoard() const {
269 // TODO implement flags
270 // return (m_flags & eMachProcessFlagsUsingSBS) != 0;
274 bool NativeProcessDarwin::ProcessUsingBackBoard() const {
275 // TODO implement flags
276 // return (m_flags & eMachProcessFlagsUsingBKS) != 0;
280 // Called by the exception thread when an exception has been received from
281 // our process. The exception message is completely filled and the exception
282 // data has already been copied.
283 void NativeProcessDarwin::ExceptionMessageReceived(
284 const MachException::Message &message) {
285 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
287 std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
288 if (m_exception_messages.empty()) {
289 // Suspend the task the moment we receive our first exception message.
293 // Use a locker to automatically unlock our mutex in case of exceptions
294 // Add the exception to our internal exception stack
295 m_exception_messages.push_back(message);
298 log->Printf("NativeProcessDarwin::%s(): new queued message count: %lu",
299 __FUNCTION__, m_exception_messages.size());
302 void *NativeProcessDarwin::ExceptionThread(void *arg) {
303 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
306 log->Printf("NativeProcessDarwin::%s(): cannot run mach exception "
307 "thread, mandatory process arg was null",
312 return reinterpret_cast<NativeProcessDarwin *>(arg)->DoExceptionThread();
315 void *NativeProcessDarwin::DoExceptionThread() {
316 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
319 log->Printf("NativeProcessDarwin::%s(arg=%p) starting thread...",
322 pthread_setname_np("exception monitoring thread");
324 // Ensure we don't get CPU starved.
325 MaybeRaiseThreadPriority();
327 // We keep a count of the number of consecutive exceptions received so
328 // we know to grab all exceptions without a timeout. We do this to get a
329 // bunch of related exceptions on our exception port so we can process
330 // then together. When we have multiple threads, we can get an exception
331 // per thread and they will come in consecutively. The main loop in this
332 // thread can stop periodically if needed to service things related to this
335 // [did we lose some words here?]
337 // flag set in the options, so we will wait forever for an exception on
338 // 0 our exception port. After we get one exception, we then will use the
339 // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
340 // exceptions for our process. After we have received the last pending
341 // exception, we will get a timeout which enables us to then notify
342 // our main thread that we have an exception bundle available. We then wait
343 // for the main thread to tell this exception thread to start trying to get
344 // exceptions messages again and we start again with a mach_msg read with
347 // We choose to park a thread on this, rather than polling, because the
348 // polling is expensive. On devices, we need to minimize overhead caused
349 // by the process monitor.
350 uint32_t num_exceptions_received = 0;
352 task_t task = m_task;
353 mach_msg_timeout_t periodic_timeout = 0;
355 #if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
356 mach_msg_timeout_t watchdog_elapsed = 0;
357 mach_msg_timeout_t watchdog_timeout = 60 * 1000;
358 ::pid_t pid = (::pid_t)process->GetID();
359 CFReleaser<SBSWatchdogAssertionRef> watchdog;
361 if (process->ProcessUsingSpringBoard()) {
362 // Request a renewal for every 60 seconds if we attached using
364 watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60));
366 log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
368 pid, watchdog.get());
370 if (watchdog.get()) {
371 ::SBSWatchdogAssertionRenew(watchdog.get());
373 CFTimeInterval watchdogRenewalInterval =
374 ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get());
376 log->Printf("::SBSWatchdogAssertionGetRenewalInterval(%p) => "
378 watchdog.get(), watchdogRenewalInterval);
379 if (watchdogRenewalInterval > 0.0) {
380 watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000;
381 if (watchdog_timeout > 3000) {
382 // Give us a second to renew our timeout.
383 watchdog_timeout -= 1000;
384 } else if (watchdog_timeout > 1000) {
385 // Give us a quarter of a second to renew our timeout.
386 watchdog_timeout -= 250;
390 if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout)
391 periodic_timeout = watchdog_timeout;
393 #endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
396 CFReleaser<BKSWatchdogAssertionRef> watchdog;
397 if (process->ProcessUsingBackBoard()) {
398 ::pid_t pid = process->GetID();
399 CFAllocatorRef alloc = kCFAllocatorDefault;
400 watchdog.reset(::BKSWatchdogAssertionCreateForPID(alloc, pid));
402 #endif // #ifdef WITH_BKS
404 // Do we want to use a weak pointer to the NativeProcessDarwin here, in
405 // which case we can guarantee we don't whack the process monitor if we
406 // race between this thread and the main one on shutdown?
407 while (IsExceptionPortValid()) {
408 ::pthread_testcancel();
410 MachException::Message exception_message;
412 if (num_exceptions_received > 0) {
413 // We don't want a timeout here, just receive as many exceptions as
414 // we can since we already have one. We want to get all currently
415 // available exceptions for this task at once.
416 error = exception_message.Receive(
418 MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0);
419 } else if (periodic_timeout > 0) {
420 // We need to stop periodically in this loop, so try and get a mach
421 // message with a valid timeout (ms).
422 error = exception_message.Receive(GetExceptionPort(),
423 MACH_RCV_MSG | MACH_RCV_INTERRUPT |
427 // We don't need to parse all current exceptions or stop
428 // periodically, just wait for an exception forever.
429 error = exception_message.Receive(GetExceptionPort(),
430 MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0);
433 if (error.Success()) {
434 // We successfully received an exception.
435 if (exception_message.CatchExceptionRaise(task)) {
436 ++num_exceptions_received;
437 ExceptionMessageReceived(exception_message);
440 if (error.GetError() == MACH_RCV_INTERRUPTED) {
441 // We were interrupted.
443 // If we have no task port we should exit this thread, as it implies
444 // the inferior went down.
445 if (!IsExceptionPortValid()) {
447 log->Printf("NativeProcessDarwin::%s(): the inferior "
448 "exception port is no longer valid, "
449 "canceling exception thread...",
451 // Should we be setting a process state here?
455 // Make sure the inferior task is still valid.
459 log->Printf("NativeProcessDarwin::%s(): interrupted, but "
460 "the inferior task iss till valid, "
465 // The inferior task is no longer valid. Time to exit as
466 // the process has gone away.
468 log->Printf("NativeProcessDarwin::%s(): the inferior task "
469 "has exited, and so will we...",
471 // Does this race at all with our waitpid()?
472 SetState(eStateExited);
475 } else if (error.GetError() == MACH_RCV_TIMED_OUT) {
476 // We timed out when waiting for exceptions.
478 if (num_exceptions_received > 0) {
479 // We were receiving all current exceptions with a timeout of
480 // zero. It is time to go back to our normal looping mode.
481 num_exceptions_received = 0;
483 // Notify our main thread we have a complete exception message
484 // bundle available. Get the possibly updated task port back
485 // from the process in case we exec'ed and our task port
487 task = ExceptionMessageBundleComplete();
489 // In case we use a timeout value when getting exceptions,
490 // make sure our task is still valid.
491 if (IsTaskValid(task)) {
494 log->Printf("NativeProcessDarwin::%s(): got a timeout, "
499 // The inferior task is no longer valid. Time to exit as
500 // the process has gone away.
502 log->Printf("NativeProcessDarwin::%s(): the inferior "
503 "task has exited, and so will we...",
505 // Does this race at all with our waitpid()?
506 SetState(eStateExited);
511 #if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
512 if (watchdog.get()) {
513 watchdog_elapsed += periodic_timeout;
514 if (watchdog_elapsed >= watchdog_timeout) {
516 log->Printf("SBSWatchdogAssertionRenew(%p)", watchdog.get());
517 ::SBSWatchdogAssertionRenew(watchdog.get());
518 watchdog_elapsed = 0;
524 log->Printf("NativeProcessDarwin::%s(): continuing after "
525 "receiving an unexpected error: %u (%s)",
526 __FUNCTION__, error.GetError(), error.AsCString());
527 // TODO: notify of error?
532 #if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
533 if (watchdog.get()) {
534 // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel
536 // all are up and running on systems that support it. The SBS framework has
538 // that will forward SBSWatchdogAssertionRelease to
539 // SBSWatchdogAssertionCancel for now
540 // so it should still build either way.
541 DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)",
543 ::SBSWatchdogAssertionRelease(watchdog.get());
545 #endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
548 log->Printf("NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__,
553 Status NativeProcessDarwin::StartExceptionThread() {
555 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
557 log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
559 // Make sure we've looked up the inferior port.
560 TaskPortForProcessID(error);
562 // Ensure the inferior task is valid.
563 if (!IsTaskValid()) {
564 error.SetErrorStringWithFormat("cannot start exception thread: "
565 "task 0x%4.4x is not valid",
570 // Get the mach port for the process monitor.
571 mach_port_t task_self = mach_task_self();
573 // Allocate an exception port that we will use to track our child process
574 auto mach_err = ::mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE,
576 error.SetError(mach_err, eErrorTypeMachKernel);
579 log->Printf("NativeProcessDarwin::%s(): mach_port_allocate("
580 "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, "
581 "&m_exception_port) failed: %u (%s)",
582 __FUNCTION__, task_self, error.GetError(), error.AsCString());
586 // Add the ability to send messages on the new exception port
587 mach_err = ::mach_port_insert_right(
588 task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND);
589 error.SetError(mach_err, eErrorTypeMachKernel);
592 log->Printf("NativeProcessDarwin::%s(): mach_port_insert_right("
593 "task_self=0x%4.4x, m_exception_port=0x%4.4x, "
594 "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) "
596 __FUNCTION__, task_self, m_exception_port, m_exception_port,
597 error.GetError(), error.AsCString());
601 // Save the original state of the exception ports for our child process.
602 error = SaveExceptionPortInfo();
603 if (error.Fail() || (m_exc_port_info.mask == 0)) {
605 log->Printf("NativeProcessDarwin::%s(): SaveExceptionPortInfo() "
606 "failed, cannot install exception handler: %s",
607 __FUNCTION__, error.AsCString());
611 // Set the ability to get all exceptions on this port.
612 mach_err = ::task_set_exception_ports(
613 m_task, m_exc_port_info.mask, m_exception_port,
614 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
615 error.SetError(mach_err, eErrorTypeMachKernel);
618 log->Printf("::task_set_exception_ports (task = 0x%4.4x, "
619 "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "
620 "behavior = 0x%8.8x, new_flavor = 0x%8.8x) failed: "
622 m_task, m_exc_port_info.mask, m_exception_port,
623 (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE,
624 error.GetError(), error.AsCString());
628 // Create the exception thread.
630 ::pthread_create(&m_exception_thread, nullptr, ExceptionThread, this);
631 error.SetError(pthread_err, eErrorTypePOSIX);
634 log->Printf("NativeProcessDarwin::%s(): failed to create Mach "
635 "exception-handling thread: %u (%s)",
636 __FUNCTION__, error.GetError(), error.AsCString());
643 NativeProcessDarwin::GetDYLDAllImageInfosAddress(Status &error) const {
646 struct hack_task_dyld_info dyld_info;
647 mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
648 // Make sure that COUNT isn't bigger than our hacked up struct
649 // hack_task_dyld_info. If it is, then make COUNT smaller to match.
650 if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t))) {
651 count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t));
654 TaskPortForProcessID(error);
656 return LLDB_INVALID_ADDRESS;
659 ::task_info(m_task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
660 error.SetError(mach_err, eErrorTypeMachKernel);
661 if (error.Success()) {
662 // We now have the address of the all image infos structure.
663 return dyld_info.all_image_info_addr;
667 return LLDB_INVALID_ADDRESS;
670 uint32_t NativeProcessDarwin::GetCPUTypeForLocalProcess(::pid_t pid) {
671 int mib[CTL_MAXNAME] = {
674 size_t len = CTL_MAXNAME;
676 if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
683 size_t cpu_len = sizeof(cpu);
684 if (::sysctl(mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0))
689 uint32_t NativeProcessDarwin::GetCPUType() const {
690 if (m_cpu_type == 0 && m_pid != 0)
691 m_cpu_type = GetCPUTypeForLocalProcess(m_pid);
695 task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
696 // We have a complete bundle of exceptions for our child process.
698 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
700 std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
702 log->Printf("NativeProcessDarwin::%s(): processing %lu exception "
704 __FUNCTION__, m_exception_messages.size());
706 if (m_exception_messages.empty()) {
707 // Not particularly useful...
711 bool auto_resume = false;
714 // First check for any SIGTRAP and make sure we didn't exec
715 const task_t task = m_task;
718 bool received_interrupt = false;
719 uint32_t num_task_exceptions = 0;
720 for (i = 0; i < m_exception_messages.size(); ++i) {
721 if (m_exception_messages[i].state.task_port != task) {
722 // This is an exception that is not for our inferior, ignore.
726 // This is an exception for the inferior.
727 ++num_task_exceptions;
728 const int signo = m_exception_messages[i].state.SoftSignal();
729 if (signo == SIGTRAP) {
730 // SIGTRAP could mean that we exec'ed. We need to check the
731 // dyld all_image_infos.infoArray to see if it is NULL and if
732 // so, say that we exec'ed.
733 const addr_t aii_addr = GetDYLDAllImageInfosAddress(error);
734 if (aii_addr == LLDB_INVALID_ADDRESS)
737 const addr_t info_array_count_addr = aii_addr + 4;
738 uint32_t info_array_count = 0;
739 size_t bytes_read = 0;
741 read_error = ReadMemory(info_array_count_addr, // source addr
742 &info_array_count, // dest addr
744 bytes_read); // #bytes read
745 if (read_error.Success() && (bytes_read == 4)) {
746 if (info_array_count == 0) {
747 // We got the all infos address, and there are zero
748 // entries. We think we exec'd.
751 // Force the task port to update itself in case the
752 // task port changed after exec
753 const task_t old_task = m_task;
754 const bool force_update = true;
755 const task_t new_task = TaskPortForProcessID(error, force_update);
756 if (old_task != new_task) {
758 log->Printf("exec: inferior task port changed "
759 "from 0x%4.4x to 0x%4.4x",
765 log->Printf("NativeProcessDarwin::%s() warning: "
766 "failed to read all_image_infos."
767 "infoArrayCount from 0x%8.8llx",
768 __FUNCTION__, info_array_count_addr);
770 } else if ((m_sent_interrupt_signo != 0) &&
771 (signo == m_sent_interrupt_signo)) {
772 // We just received the interrupt that we sent to ourselves.
773 received_interrupt = true;
778 cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_pid);
779 if (m_cpu_type != process_cpu_type) {
781 log->Printf("NativeProcessDarwin::%s(): arch changed from "
782 "0x%8.8x to 0x%8.8x",
783 __FUNCTION__, m_cpu_type, process_cpu_type);
784 m_cpu_type = process_cpu_type;
785 // TODO figure out if we need to do something here.
786 // DNBArchProtocol::SetArchitecture (process_cpu_type);
788 m_thread_list.Clear();
790 // TODO hook up breakpoints.
791 // m_breakpoints.DisableAll();
794 if (m_sent_interrupt_signo != 0) {
795 if (received_interrupt) {
797 log->Printf("NativeProcessDarwin::%s(): process "
798 "successfully interrupted with signal %i",
799 __FUNCTION__, m_sent_interrupt_signo);
801 // Mark that we received the interrupt signal
802 m_sent_interrupt_signo = 0;
803 // Now check if we had a case where:
804 // 1 - We called NativeProcessDarwin::Interrupt() but we stopped
805 // for another reason.
806 // 2 - We called NativeProcessDarwin::Resume() (but still
807 // haven't gotten the interrupt signal).
808 // 3 - We are now incorrectly stopped because we are handling
809 // the interrupt signal we missed.
810 // 4 - We might need to resume if we stopped only with the
811 // interrupt signal that we never handled.
812 if (m_auto_resume_signo != 0) {
813 // Only auto_resume if we stopped with _only_ the interrupt
815 if (num_task_exceptions == 1) {
818 log->Printf("NativeProcessDarwin::%s(): auto "
819 "resuming due to unhandled interrupt "
821 __FUNCTION__, m_auto_resume_signo);
823 m_auto_resume_signo = 0;
827 log->Printf("NativeProcessDarwin::%s(): didn't get signal "
828 "%i after MachProcess::Interrupt()",
829 __FUNCTION__, m_sent_interrupt_signo);
834 // Let all threads recover from stopping and do any clean up based
835 // on the previous thread state (if any).
836 m_thread_list.ProcessDidStop(*this);
838 // Let each thread know of any exceptions
839 for (i = 0; i < m_exception_messages.size(); ++i) {
840 // Let the thread list forward all exceptions on down to each thread.
841 if (m_exception_messages[i].state.task_port == task) {
842 // This exception is for our inferior.
843 m_thread_list.NotifyException(m_exception_messages[i].state);
848 m_exception_messages[i].Dump(stream);
850 log->PutCString(stream.GetString().c_str());
856 m_thread_list.Dump(stream);
858 log->PutCString(stream.GetString().c_str());
861 bool step_more = false;
862 if (m_thread_list.ShouldStop(step_more) && (auto_resume == false)) {
863 // TODO - need to hook up event system here. !!!!
865 // Wait for the eEventProcessRunningStateChanged event to be reset
866 // before changing state to stopped to avoid race condition with
867 // very fast start/stops.
868 struct timespec timeout;
870 //DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 ms
871 DNBTimer::OffsetTimeOfDay(&timeout, 1, 0); // Wait for 250 ms
872 m_events.WaitForEventsToReset(eEventProcessRunningStateChanged,
875 SetState(eStateStopped);
877 // Resume without checking our current state.
884 void NativeProcessDarwin::StartSTDIOThread() {
888 Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) {
890 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
892 // Strategy: create a thread that sits on waitpid(), waiting for the
893 // inferior process to die, reaping it in the process. Arrange for
894 // the thread to have a pipe file descriptor that it can send a byte
895 // over when the waitpid completes. Have the main loop have a read
896 // object for the other side of the pipe, and have the callback for
897 // the read do the process termination message sending.
899 // Create a single-direction communication channel.
900 const bool child_inherits = false;
901 error = m_waitpid_pipe.CreateNew(child_inherits);
904 log->Printf("NativeProcessDarwin::%s(): failed to create waitpid "
905 "communication pipe: %s",
906 __FUNCTION__, error.AsCString());
910 // Hook up the waitpid reader callback.
912 // TODO make PipePOSIX derive from IOObject. This is goofy here.
913 const bool transfer_ownership = false;
914 auto io_sp = IOObjectSP(
915 new File(m_waitpid_pipe.GetReadFileDescriptor(), transfer_ownership));
916 m_waitpid_reader_handle = main_loop.RegisterReadObject(
917 io_sp, [this](MainLoopBase &) { HandleWaitpidResult(); }, error);
919 // Create the thread.
921 ::pthread_create(&m_waitpid_thread, nullptr, WaitpidThread, this);
922 error.SetError(pthread_err, eErrorTypePOSIX);
925 log->Printf("NativeProcessDarwin::%s(): failed to create waitpid "
926 "handling thread: %u (%s)",
927 __FUNCTION__, error.GetError(), error.AsCString());
934 void *NativeProcessDarwin::WaitpidThread(void *arg) {
935 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
938 log->Printf("NativeProcessDarwin::%s(): cannot run waitpid "
939 "thread, mandatory process arg was null",
944 return reinterpret_cast<NativeProcessDarwin *>(arg)->DoWaitpidThread();
947 void NativeProcessDarwin::MaybeRaiseThreadPriority() {
948 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
949 struct sched_param thread_param;
950 int thread_sched_policy;
951 if (pthread_getschedparam(pthread_self(), &thread_sched_policy,
952 &thread_param) == 0) {
953 thread_param.sched_priority = 47;
954 pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
959 void *NativeProcessDarwin::DoWaitpidThread() {
960 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
962 if (m_pid == LLDB_INVALID_PROCESS_ID) {
964 log->Printf("NativeProcessDarwin::%s(): inferior process ID is "
965 "not set, cannot waitpid on it",
971 pthread_setname_np("waitpid thread");
973 // Ensure we don't get CPU starved.
974 MaybeRaiseThreadPriority();
981 ::pid_t child_pid = ::waitpid(m_pid, &status, 0);
983 error.SetErrorToErrno();
985 if (error.GetError() == EINTR) {
986 // This is okay, we can keep going.
988 log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
989 ", &status, 0) interrupted, continuing",
990 __FUNCTION__, m_pid);
994 // This error is not okay, abort.
996 log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
997 ", &status, 0) aborting due to error: %u (%s)",
998 __FUNCTION__, m_pid, error.GetError(), error.AsCString());
1002 // Log the successful result.
1004 log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
1005 ", &status, 0) => %i, status = %i",
1006 __FUNCTION__, m_pid, child_pid, status);
1008 // Handle the result.
1009 if (WIFSTOPPED(status)) {
1011 log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
1012 ") received a stop, continuing waitpid() loop",
1013 __FUNCTION__, m_pid);
1015 } else // if (WIFEXITED(status) || WIFSIGNALED(status))
1018 log->Printf("NativeProcessDarwin::%s(pid = %" PRIu64 "): "
1019 "waitpid thread is setting exit status for pid = "
1021 __FUNCTION__, m_pid, child_pid, status);
1023 error = SendInferiorExitStatusToMainLoop(child_pid, status);
1028 // We should never exit as long as our child process is alive. If we
1029 // get here, something completely unexpected went wrong and we should exit.
1032 "NativeProcessDarwin::%s(): internal error: waitpid thread "
1033 "exited out of its main loop in an unexpected way. pid = %" PRIu64
1034 ". Sending exit status of -1.",
1035 __FUNCTION__, m_pid);
1037 error = SendInferiorExitStatusToMainLoop((::pid_t)m_pid, -1);
1041 Status NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid,
1044 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1046 size_t bytes_written = 0;
1049 error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written);
1050 if (error.Fail() || (bytes_written < sizeof(pid))) {
1052 log->Printf("NativeProcessDarwin::%s() - failed to write "
1053 "waitpid exiting pid to the pipe. Client will not "
1054 "hear about inferior exit status!",
1061 error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written);
1062 if (error.Fail() || (bytes_written < sizeof(status))) {
1064 log->Printf("NativeProcessDarwin::%s() - failed to write "
1065 "waitpid exit result to the pipe. Client will not "
1066 "hear about inferior exit status!",
1072 Status NativeProcessDarwin::HandleWaitpidResult() {
1074 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1077 const bool notify_status = true;
1080 size_t bytes_read = 0;
1081 error = m_waitpid_pipe.Read(&pid, sizeof(pid), bytes_read);
1082 if (error.Fail() || (bytes_read < sizeof(pid))) {
1084 log->Printf("NativeProcessDarwin::%s() - failed to read "
1085 "waitpid exiting pid from the pipe. Will notify "
1086 "as if parent process died with exit status -1.",
1088 SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
1095 error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read);
1096 if (error.Fail() || (bytes_read < sizeof(status))) {
1098 log->Printf("NativeProcessDarwin::%s() - failed to read "
1099 "waitpid exit status from the pipe. Will notify "
1100 "as if parent process died with exit status -1.",
1102 SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
1107 // Notify the monitor that our state has changed.
1109 log->Printf("NativeProcessDarwin::%s(): main loop received waitpid "
1110 "exit status info: pid=%i (%s), status=%i",
1112 (pid == m_pid) ? "the inferior" : "not the inferior", status);
1114 ExitType exit_type = eExitTypeInvalid;
1115 int exit_status = -1;
1117 if (WIFEXITED(status)) {
1118 exit_type = eExitTypeExit;
1119 exit_status = WEXITSTATUS(status);
1120 } else if (WIFSIGNALED(status)) {
1121 exit_type = eExitTypeSignal;
1122 exit_status = WTERMSIG(status);
1125 SetExitStatus(exit_type, exit_status, nullptr, notify_status);
1129 task_t NativeProcessDarwin::TaskPortForProcessID(Status &error,
1131 if ((m_task == TASK_NULL) || force) {
1132 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1133 if (m_pid == LLDB_INVALID_PROCESS_ID) {
1135 log->Printf("NativeProcessDarwin::%s(): cannot get task due "
1141 const uint32_t num_retries = 10;
1142 const uint32_t usec_interval = 10000;
1144 mach_port_t task_self = mach_task_self();
1145 task_t task = TASK_NULL;
1147 for (uint32_t i = 0; i < num_retries; i++) {
1148 kern_return_t err = ::task_for_pid(task_self, m_pid, &task);
1150 // Succeeded. Save and return it.
1153 log->Printf("NativeProcessDarwin::%s(): ::task_for_pid("
1154 "stub_port = 0x%4.4x, pid = %llu, &task) "
1155 "succeeded: inferior task port = 0x%4.4x",
1156 __FUNCTION__, task_self, m_pid, m_task);
1159 // Failed to get the task for the inferior process.
1160 error.SetError(err, eErrorTypeMachKernel);
1162 log->Printf("NativeProcessDarwin::%s(): ::task_for_pid("
1163 "stub_port = 0x%4.4x, pid = %llu, &task) "
1164 "failed, err = 0x%8.8x (%s)",
1165 __FUNCTION__, task_self, m_pid, err, error.AsCString());
1169 // Sleep a bit and try again
1170 ::usleep(usec_interval);
1173 // We failed to get the task for the inferior process.
1174 // Ensure that it is cleared out.
1180 void NativeProcessDarwin::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
1182 error.SetErrorString("TODO: implement");
1185 Status NativeProcessDarwin::PrivateResume() {
1187 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1189 std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
1190 m_auto_resume_signo = m_sent_interrupt_signo;
1193 if (m_auto_resume_signo)
1194 log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming (with "
1195 "unhandled interrupt signal %i)...",
1196 __FUNCTION__, m_task, m_auto_resume_signo);
1198 log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming...",
1199 __FUNCTION__, m_task);
1202 error = ReplyToAllExceptions();
1205 log->Printf("NativeProcessDarwin::%s(): aborting, failed to "
1206 "reply to exceptions: %s",
1207 __FUNCTION__, error.AsCString());
1210 // bool stepOverBreakInstruction = step;
1212 // Let the thread prepare to resume and see if any threads want us to
1213 // step over a breakpoint instruction (ProcessWillResume will modify
1214 // the value of stepOverBreakInstruction).
1215 m_thread_list.ProcessWillResume(*this, m_thread_actions);
1217 // Set our state accordingly
1218 if (m_thread_actions.NumActionsWithState(eStateStepping))
1219 SetState(eStateStepping);
1221 SetState(eStateRunning);
1223 // Now resume our task.
1224 error = ResumeTask();
1228 Status NativeProcessDarwin::ReplyToAllExceptions() {
1230 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
1232 TaskPortForProcessID(error);
1235 log->Printf("NativeProcessDarwin::%s(): no task port, aborting",
1240 std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
1241 if (m_exception_messages.empty()) {
1247 for (auto &message : m_exception_messages) {
1249 log->Printf("NativeProcessDarwin::%s(): replying to exception "
1251 __FUNCTION__, index++);
1254 int thread_reply_signal = 0;
1257 m_thread_list.GetThreadIDByMachPortNumber(message.state.thread_port);
1258 const ResumeAction *action = nullptr;
1259 if (tid != LLDB_INVALID_THREAD_ID)
1260 action = m_thread_actions.GetActionForThread(tid, false);
1263 thread_reply_signal = action->signal;
1264 if (thread_reply_signal)
1265 m_thread_actions.SetSignalHandledForThread(tid);
1268 error = message.Reply(m_pid, m_task, thread_reply_signal);
1269 if (error.Fail() && log) {
1270 // We log any error here, but we don't stop the exception
1271 // response handling.
1272 log->Printf("NativeProcessDarwin::%s(): failed to reply to "
1274 __FUNCTION__, error.AsCString());
1279 // Erase all exception message as we should have used and replied
1280 // to them all already.
1281 m_exception_messages.clear();
1285 Status NativeProcessDarwin::ResumeTask() {
1287 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1289 TaskPortForProcessID(error);
1292 log->Printf("NativeProcessDarwin::%s(): failed to get task port "
1293 "for process when attempting to resume: %s",
1294 __FUNCTION__, error.AsCString());
1297 if (m_task == TASK_NULL) {
1298 error.SetErrorString("task port retrieval succeeded but task port is "
1299 "null when attempting to resume the task");
1304 log->Printf("NativeProcessDarwin::%s(): requesting resume of task "
1306 __FUNCTION__, m_task);
1308 // Get the BasicInfo struct to verify that we're suspended before we try
1309 // to resume the task.
1310 struct task_basic_info task_info;
1311 error = GetTaskBasicInfo(m_task, &task_info);
1314 log->Printf("NativeProcessDarwin::%s(): failed to get task "
1315 "BasicInfo when attempting to resume: %s",
1316 __FUNCTION__, error.AsCString());
1320 // task_resume isn't counted like task_suspend calls are, so if the
1321 // task is not suspended, don't try and resume it since it is already
1323 if (task_info.suspend_count > 0) {
1324 auto mach_err = ::task_resume(m_task);
1325 error.SetError(mach_err, eErrorTypeMachKernel);
1327 if (error.Success())
1328 log->Printf("::task_resume(target_task = 0x%4.4x): success", m_task);
1330 log->Printf("::task_resume(target_task = 0x%4.4x) error: %s", m_task,
1335 log->Printf("::task_resume(target_task = 0x%4.4x): ignored, "
1343 bool NativeProcessDarwin::IsTaskValid() const {
1344 if (m_task == TASK_NULL)
1347 struct task_basic_info task_info;
1348 return GetTaskBasicInfo(m_task, &task_info).Success();
1351 bool NativeProcessDarwin::IsTaskValid(task_t task) const {
1352 if (task == TASK_NULL)
1355 struct task_basic_info task_info;
1356 return GetTaskBasicInfo(task, &task_info).Success();
1359 mach_port_t NativeProcessDarwin::GetExceptionPort() const {
1360 return m_exception_port;
1363 bool NativeProcessDarwin::IsExceptionPortValid() const {
1364 return MACH_PORT_VALID(m_exception_port);
1368 NativeProcessDarwin::GetTaskBasicInfo(task_t task,
1369 struct task_basic_info *info) const {
1371 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1375 error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): mandatory "
1381 // Grab the task if we don't already have it.
1382 if (task == TASK_NULL) {
1383 error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): given task "
1388 mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
1389 auto err = ::task_info(m_task, TASK_BASIC_INFO, (task_info_t)info, &count);
1390 error.SetError(err, eErrorTypeMachKernel);
1393 log->Printf("::task_info(target_task = 0x%4.4x, "
1394 "flavor = TASK_BASIC_INFO, task_info_out => %p, "
1395 "task_info_outCnt => %u) failed: %u (%s)",
1396 m_task, info, count, error.GetError(), error.AsCString());
1401 GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
1403 float user = (float)info->user_time.seconds +
1404 (float)info->user_time.microseconds / 1000000.0f;
1405 float system = (float)info->user_time.seconds +
1406 (float)info->user_time.microseconds / 1000000.0f;
1407 verbose_log->Printf("task_basic_info = { suspend_count = %i, "
1408 "virtual_size = 0x%8.8llx, resident_size = "
1409 "0x%8.8llx, user_time = %f, system_time = %f }",
1410 info->suspend_count, (uint64_t)info->virtual_size,
1411 (uint64_t)info->resident_size, user, system);
1416 Status NativeProcessDarwin::SuspendTask() {
1418 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1420 if (m_task == TASK_NULL) {
1421 error.SetErrorString("task port is null, cannot suspend task");
1423 log->Printf("NativeProcessDarwin::%s() failed: %s", __FUNCTION__,
1428 auto mach_err = ::task_suspend(m_task);
1429 error.SetError(mach_err, eErrorTypeMachKernel);
1430 if (error.Fail() && log)
1431 log->Printf("::task_suspend(target_task = 0x%4.4x)", m_task);
1436 Status NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) {
1438 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1441 log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
1444 m_thread_actions = resume_actions;
1445 error = PrivateResume();
1449 auto state = GetState();
1450 if (state == eStateRunning) {
1452 log->Printf("NativeProcessDarwin::%s(): task 0x%x is already "
1453 "running, ignoring...",
1454 __FUNCTION__, TaskPortForProcessID(error));
1458 // We can't resume from this state.
1459 error.SetErrorStringWithFormat("task 0x%x has state %s, can't resume",
1460 TaskPortForProcessID(error),
1461 StateAsCString(state));
1465 Status NativeProcessDarwin::Halt() {
1467 error.SetErrorString("TODO: implement");
1471 Status NativeProcessDarwin::Detach() {
1473 error.SetErrorString("TODO: implement");
1477 Status NativeProcessDarwin::Signal(int signo) {
1479 error.SetErrorString("TODO: implement");
1483 Status NativeProcessDarwin::Interrupt() {
1485 error.SetErrorString("TODO: implement");
1489 Status NativeProcessDarwin::Kill() {
1491 error.SetErrorString("TODO: implement");
1495 Status NativeProcessDarwin::GetMemoryRegionInfo(lldb::addr_t load_addr,
1496 MemoryRegionInfo &range_info) {
1498 error.SetErrorString("TODO: implement");
1502 Status NativeProcessDarwin::ReadMemory(lldb::addr_t addr, void *buf,
1503 size_t size, size_t &bytes_read) {
1505 error.SetErrorString("TODO: implement");
1509 Status NativeProcessDarwin::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
1511 size_t &bytes_read) {
1513 error.SetErrorString("TODO: implement");
1517 Status NativeProcessDarwin::WriteMemory(lldb::addr_t addr, const void *buf,
1518 size_t size, size_t &bytes_written) {
1520 error.SetErrorString("TODO: implement");
1524 Status NativeProcessDarwin::AllocateMemory(size_t size, uint32_t permissions,
1525 lldb::addr_t &addr) {
1527 error.SetErrorString("TODO: implement");
1531 Status NativeProcessDarwin::DeallocateMemory(lldb::addr_t addr) {
1533 error.SetErrorString("TODO: implement");
1537 lldb::addr_t NativeProcessDarwin::GetSharedLibraryInfoAddress() {
1538 return LLDB_INVALID_ADDRESS;
1541 size_t NativeProcessDarwin::UpdateThreads() { return 0; }
1543 bool NativeProcessDarwin::GetArchitecture(ArchSpec &arch) const {
1547 Status NativeProcessDarwin::SetBreakpoint(lldb::addr_t addr, uint32_t size,
1550 error.SetErrorString("TODO: implement");
1554 void NativeProcessDarwin::DoStopIDBumped(uint32_t newBumpId) {}
1556 Status NativeProcessDarwin::GetLoadedModuleFileSpec(const char *module_path,
1557 FileSpec &file_spec) {
1559 error.SetErrorString("TODO: implement");
1563 Status NativeProcessDarwin::GetFileLoadAddress(const llvm::StringRef &file_name,
1564 lldb::addr_t &load_addr) {
1566 error.SetErrorString("TODO: implement");
1570 // -----------------------------------------------------------------
1571 // NativeProcessProtocol protected interface
1572 // -----------------------------------------------------------------
1573 Status NativeProcessDarwin::GetSoftwareBreakpointTrapOpcode(
1574 size_t trap_opcode_size_hint, size_t &actual_opcode_size,
1575 const uint8_t *&trap_opcode_bytes) {
1577 error.SetErrorString("TODO: implement");