diff options
author | Tom Tromey <tom@tromey.com> | 2018-06-28 11:57:39 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2018-07-03 09:28:26 -0600 |
commit | a50c11c666e07b922d64aa5bb2747f180ce17c03 (patch) | |
tree | 80d95fd601e4a2aadee6e5bc34d1f921f306333f | |
parent | b8a6ced79668ec8af3180e50b76f7517ebbab0d9 (diff) | |
download | binutils-a50c11c666e07b922d64aa5bb2747f180ce17c03.zip binutils-a50c11c666e07b922d64aa5bb2747f180ce17c03.tar.gz binutils-a50c11c666e07b922d64aa5bb2747f180ce17c03.tar.bz2 |
Fix crash in "run" on macOS when gdb is not signed
On macOS, when gdb is not code-signed, it will throw an exception from
darwin_attach_pid. However, gdb also then crashes:
thread.c:93: internal-error: struct thread_info *inferior_thread(): Assertion `tp' failed.
I think the problem here is that darwin_attach_pid does not clean up
inferior_ptid and inf->pid on failure. This leads to a situation
where gdb tries to find a thread, but cannot.
In other cases, gdb would mourn the inferior at this point; but here
this is not possible because the target has not been pushed. Instead
this patch works by simply updating the inferior and inferior_ptid on
failure.
Tested by building an unsigned gdb on macOS and trying to run an
inferior.
gdb/ChangeLog
2018-07-03 Tom Tromey <tom@tromey.com>
PR cli/23340:
* darwin-nat.c (darwin_attach_pid): Reset inferior and
inferior_ptid on error.
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/darwin-nat.c | 119 |
2 files changed, 73 insertions, 52 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7bb4100..8ecf370 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2018-07-03 Tom Tromey <tom@tromey.com> + + PR cli/23340: + * darwin-nat.c (darwin_attach_pid): Reset inferior and + inferior_ptid on error. + 2018-07-02 Maciej W. Rozycki <macro@mips.com> Simon Marchi <simon.marchi@polymtl.ca> diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c index 7dccce7..6fb1088 100644 --- a/gdb/darwin-nat.c +++ b/gdb/darwin-nat.c @@ -1583,77 +1583,92 @@ darwin_attach_pid (struct inferior *inf) darwin_inferior *priv = new darwin_inferior; inf->priv.reset (priv); - kret = task_for_pid (gdb_task, inf->pid, &priv->task); - if (kret != KERN_SUCCESS) + TRY { - int status; - - if (!inf->attach_flag) + kret = task_for_pid (gdb_task, inf->pid, &priv->task); + if (kret != KERN_SUCCESS) { - kill (inf->pid, 9); - waitpid (inf->pid, &status, 0); - } + int status; + + if (!inf->attach_flag) + { + kill (inf->pid, 9); + waitpid (inf->pid, &status, 0); + } - error (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n" + error + (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n" " (please check gdb is codesigned - see taskgated(8))"), - inf->pid, mach_error_string (kret), (unsigned long) kret); - } + inf->pid, mach_error_string (kret), (unsigned long) kret); + } - inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"), - priv->task, inf->pid); + inferior_debug (2, _("inferior task: 0x%x, pid: %d\n"), + priv->task, inf->pid); - if (darwin_ex_port == MACH_PORT_NULL) - { - /* Create a port to get exceptions. */ - kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE, - &darwin_ex_port); - if (kret != KERN_SUCCESS) - error (_("Unable to create exception port, mach_port_allocate " - "returned: %d"), - kret); + if (darwin_ex_port == MACH_PORT_NULL) + { + /* Create a port to get exceptions. */ + kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE, + &darwin_ex_port); + if (kret != KERN_SUCCESS) + error (_("Unable to create exception port, mach_port_allocate " + "returned: %d"), + kret); - kret = mach_port_insert_right (gdb_task, darwin_ex_port, darwin_ex_port, - MACH_MSG_TYPE_MAKE_SEND); - if (kret != KERN_SUCCESS) - error (_("Unable to create exception port, mach_port_insert_right " - "returned: %d"), - kret); + kret = mach_port_insert_right (gdb_task, darwin_ex_port, + darwin_ex_port, + MACH_MSG_TYPE_MAKE_SEND); + if (kret != KERN_SUCCESS) + error (_("Unable to create exception port, mach_port_insert_right " + "returned: %d"), + kret); - /* Create a port set and put ex_port in it. */ - kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_PORT_SET, - &darwin_port_set); + /* Create a port set and put ex_port in it. */ + kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_PORT_SET, + &darwin_port_set); + if (kret != KERN_SUCCESS) + error (_("Unable to create port set, mach_port_allocate " + "returned: %d"), + kret); + + kret = mach_port_move_member (gdb_task, darwin_ex_port, + darwin_port_set); + if (kret != KERN_SUCCESS) + error (_("Unable to move exception port into new port set, " + "mach_port_move_member\n" + "returned: %d"), + kret); + } + + /* Create a port to be notified when the child task terminates. */ + kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE, + &priv->notify_port); if (kret != KERN_SUCCESS) - error (_("Unable to create port set, mach_port_allocate " + error (_("Unable to create notification port, mach_port_allocate " "returned: %d"), kret); - kret = mach_port_move_member (gdb_task, darwin_ex_port, darwin_port_set); + kret = mach_port_move_member (gdb_task, + priv->notify_port, darwin_port_set); if (kret != KERN_SUCCESS) - error (_("Unable to move exception port into new port set, " + error (_("Unable to move notification port into new port set, " "mach_port_move_member\n" "returned: %d"), kret); - } - - /* Create a port to be notified when the child task terminates. */ - kret = mach_port_allocate (gdb_task, MACH_PORT_RIGHT_RECEIVE, - &priv->notify_port); - if (kret != KERN_SUCCESS) - error (_("Unable to create notification port, mach_port_allocate " - "returned: %d"), - kret); - kret = mach_port_move_member (gdb_task, - priv->notify_port, darwin_port_set); - if (kret != KERN_SUCCESS) - error (_("Unable to move notification port into new port set, " - "mach_port_move_member\n" - "returned: %d"), - kret); + darwin_setup_request_notification (inf); - darwin_setup_request_notification (inf); + darwin_setup_exceptions (inf); + } + CATCH (ex, RETURN_MASK_ALL) + { + inf->pid = 0; + inf->priv.reset (); + inferior_ptid = null_ptid; - darwin_setup_exceptions (inf); + throw_exception (ex); + } + END_CATCH target_ops *darwin_ops = get_native_target (); if (!target_is_pushed (darwin_ops)) |