1 /* Darwin support for GDB, the GNU debugger.
2 Copyright (C) 2008 Free Software Foundation, Inc.
4 Contributed by AdaCore.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 #include "gdbthread.h"
34 #include "event-top.h"
37 #include "exceptions.h"
38 #include "inf-child.h"
40 #include "arch-utils.h"
43 #include <sys/ptrace.h>
44 #include <sys/signal.h>
45 #include <machine/setjmp.h>
46 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/sysctl.h>
55 #include <mach/mach_error.h>
56 #include <mach/mach_vm.h>
57 #include <mach/mach_init.h>
58 #include <mach/vm_map.h>
59 #include <mach/task.h>
60 #include <mach/mach_port.h>
61 #include <mach/thread_act.h>
62 #include <mach/port.h>
64 #include "darwin-nat.h"
67 Darwin kernel is Mach + BSD derived kernel. Note that they share the
68 same memory space and are linked together (ie there is no micro-kernel).
70 Although ptrace(2) is available on Darwin, it is not complete. We have
71 to use Mach calls to read and write memory and to modify registers. We
72 also use Mach to get inferior faults. As we cannot use select(2) or
73 signals with Mach port (the Mach communication channel), signals are
74 reported to gdb as an exception. Furthermore we detect death of the
75 inferior through a Mach notification message. This way we only wait
78 Some Mach documentation is available for Apple xnu source package or
82 #define PTRACE(CMD, PID, ADDR, SIG) \
83 darwin_ptrace(#CMD, CMD, (PID), (ADDR), (SIG))
85 extern boolean_t
exc_server (mach_msg_header_t
*in
, mach_msg_header_t
*out
);
87 static void darwin_stop (ptid_t
);
89 static void darwin_resume (ptid_t ptid
, int step
,
90 enum target_signal signal
);
92 static ptid_t
darwin_wait (ptid_t ptid
, struct target_waitstatus
*status
);
94 static void darwin_mourn_inferior (struct target_ops
*ops
);
96 static int darwin_lookup_task (char *args
, task_t
* ptask
, int *ppid
);
98 static void darwin_kill_inferior (void);
100 static void darwin_ptrace_me (void);
102 static void darwin_ptrace_him (int pid
);
104 static void darwin_create_inferior (struct target_ops
*ops
, char *exec_file
,
105 char *allargs
, char **env
, int from_tty
);
107 static void darwin_files_info (struct target_ops
*ops
);
109 static char *darwin_pid_to_str (ptid_t tpid
);
111 static int darwin_thread_alive (ptid_t tpid
);
113 /* Current inferior. */
114 darwin_inferior
*darwin_inf
= NULL
;
116 /* Target operations for Darwin. */
117 static struct target_ops
*darwin_ops
;
119 /* Task identifier of gdb. */
120 static task_t gdb_task
;
122 /* A copy of mach_host_self (). */
123 mach_port_t darwin_host_self
;
125 /* Exception port. */
126 mach_port_t darwin_ex_port
;
128 /* Notification port. */
129 mach_port_t darwin_not_port
;
132 mach_port_t darwin_port_set
;
135 static vm_size_t mach_page_size
;
137 /* If Set, catch all mach exceptions (before they are converted to signals
139 static int enable_mach_exceptions
;
141 #define PAGE_TRUNC(x) ((x) & ~(mach_page_size - 1))
142 #define PAGE_ROUND(x) PAGE_TRUNC((x) + mach_page_size - 1)
144 /* Buffer containing received message and to be sent message. */
147 mach_msg_header_t hdr
;
151 /* Current message state.
152 If the kernel has sent a message it expects a reply and the inferior
153 can't be killed before. */
154 static enum msg_state
{ NO_MESSAGE
, GOT_MESSAGE
, REPLY_SENT
} msg_state
;
156 /* Unmarshalled received message. */
157 static struct exc_msg
162 /* Thread and task taking the exception. */
163 mach_port_t thread_port
;
164 mach_port_t task_port
;
166 /* Type of the exception. */
167 exception_type_t ex_type
;
169 /* Machine dependent details. */
170 mach_msg_type_number_t data_count
;
171 integer_t ex_data
[4];
175 /* This controls output of inferior debugging.
176 1 = basic exception handling
178 3 = thread management
179 4 = pending_event_handler
180 6 = most chatty level. */
182 static int darwin_debug_flag
= 0;
185 inferior_debug (int level
, const char *fmt
, ...)
189 if (darwin_debug_flag
< level
)
193 printf_unfiltered (_("[%d inferior]: "), getpid ());
194 vprintf_unfiltered (fmt
, ap
);
199 mach_check_error (kern_return_t ret
, const char *file
,
200 unsigned int line
, const char *func
)
202 if (ret
== KERN_SUCCESS
)
205 func
= _("[UNKNOWN]");
207 error (_("error on line %u of \"%s\" in function \"%s\": %s (0x%lx)\n"),
208 line
, file
, func
, mach_error_string (ret
), (unsigned long) ret
);
212 unparse_exception_type (unsigned int i
)
214 static char unknown_exception_buf
[32];
219 return "EXC_BAD_ACCESS";
220 case EXC_BAD_INSTRUCTION
:
221 return "EXC_BAD_INSTRUCTION";
223 return "EXC_ARITHMETIC";
225 return "EXC_EMULATION";
227 return "EXC_SOFTWARE";
229 return "EXC_BREAKPOINT";
231 return "EXC_SYSCALL";
232 case EXC_MACH_SYSCALL
:
233 return "EXC_MACH_SYSCALL";
235 return "EXC_RPC_ALERT";
239 snprintf (unknown_exception_buf
, 32, _("unknown (%d)"), i
);
240 return unknown_exception_buf
;
245 darwin_ptrace (const char *name
,
246 int request
, int pid
, PTRACE_TYPE_ARG3 arg3
, int arg4
)
250 ret
= ptrace (request
, pid
, (caddr_t
) arg3
, arg4
);
252 inferior_debug (2, _("ptrace (%s, %d, 0x%x, %d): %d (%s)\n"),
253 name
, pid
, arg3
, arg4
, ret
,
254 (ret
!= 0) ? strerror (errno
) : _("no error"));
259 cmp_thread_t (const void *l
, const void *r
)
261 thread_t lt
= *(const thread_t
*)l
;
262 thread_t lr
= *(const thread_t
*)r
;
263 return (int)(lr
- lt
);
267 darwin_check_new_threads (darwin_inferior
*inf
)
271 thread_array_t thread_list
;
272 unsigned int new_nbr
;
273 unsigned int old_nbr
;
274 unsigned int new_ix
, old_ix
;
275 VEC (thread_t
) *thread_vec
;
277 /* Get list of threads. */
278 kret
= task_threads (inf
->task
, &thread_list
, &new_nbr
);
279 MACH_CHECK_ERROR (kret
);
280 if (kret
!= KERN_SUCCESS
)
284 qsort (thread_list
, new_nbr
, sizeof (thread_t
), cmp_thread_t
);
286 thread_vec
= VEC_alloc (thread_t
, new_nbr
);
289 old_nbr
= VEC_length (thread_t
, inf
->threads
);
293 for (new_ix
= 0, old_ix
= 0; new_ix
< new_nbr
|| old_ix
< old_nbr
;)
295 thread_t new_id
= (new_ix
< new_nbr
) ?
296 thread_list
[new_ix
] : THREAD_NULL
;
297 thread_t old_id
= (old_ix
< old_nbr
) ?
298 VEC_index (thread_t
, inf
->threads
, old_ix
) : THREAD_NULL
;
300 if (old_id
== new_id
)
302 /* Thread still exist. */
303 VEC_safe_push (thread_t
, thread_vec
, old_id
);
307 kret
= mach_port_deallocate (gdb_task
, old_id
);
308 MACH_CHECK_ERROR (kret
);
311 if (new_id
< old_id
|| old_ix
== old_nbr
)
313 /* A thread was created. */
314 struct thread_info
*tp
;
316 tp
= add_thread (ptid_build (inf
->pid
, 0, new_id
));
317 VEC_safe_push (thread_t
, thread_vec
, new_id
);
321 if (new_id
> old_id
|| new_ix
== new_nbr
)
323 /* A thread was removed. */
324 delete_thread (ptid_build (inf
->pid
, 0, old_id
));
325 kret
= mach_port_deallocate (gdb_task
, old_id
);
326 MACH_CHECK_ERROR (kret
);
332 VEC_free (thread_t
, inf
->threads
);
333 inf
->threads
= thread_vec
;
335 kret
= vm_deallocate (gdb_task
, (vm_address_t
) thread_list
,
336 new_nbr
* sizeof (int));
337 MACH_CHECK_ERROR (kret
);
341 darwin_stop (ptid_t t
)
345 ret
= kill (ptid_get_pid (inferior_ptid
), SIGINT
);
349 darwin_resume (ptid_t ptid
, int step
, enum target_signal signal
)
351 struct target_waitstatus status
;
357 /* minus_one_ptid is RESUME_ALL. */
358 if (ptid_equal (ptid
, minus_one_ptid
))
359 ptid
= inferior_ptid
;
361 pid
= ptid_get_pid (ptid
);
362 thread
= ptid_get_tid (ptid
);
365 (2, _("darwin_resume: state=%d, thread=0x%x, step=%d signal=%d\n"),
366 msg_state
, thread
, step
, signal
);
371 switch (exc_msg
.ex_type
)
374 if (exc_msg
.ex_data
[0] == EXC_SOFT_SIGNAL
)
376 int nsignal
= target_signal_to_host (signal
);
377 res
= PTRACE (PT_THUPDATE
, pid
,
378 (void *)exc_msg
.thread_port
, nsignal
);
380 printf_unfiltered (_("ptrace THUP: res=%d\n"), res
);
390 inferior_debug (2, _("darwin_set_sstep (thread=%x, enable=%d)\n"),
392 darwin_set_sstep (thread
, step
);
395 kret
= mach_msg (&msgout
.hdr
, MACH_SEND_MSG
| MACH_SEND_INTERRUPT
,
396 msgout
.hdr
.msgh_size
, 0,
397 MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
,
400 printf_unfiltered (_("mach_msg (reply) ret=%d\n"), kret
);
402 msg_state
= REPLY_SENT
;
407 res
= PTRACE (PT_STEP
, pid
, (caddr_t
)1, 0);
409 res
= PTRACE (PT_CONTINUE
, pid
, (caddr_t
)1, 0);
418 catch_exception_raise_state
420 exception_type_t exception_type
, mach_exception_data_t exception_data
,
421 mach_msg_type_number_t data_count
, thread_state_flavor_t
* state_flavor
,
422 thread_state_t in_state
, mach_msg_type_number_t in_state_count
,
423 thread_state_t out_state
, mach_msg_type_number_t out_state_count
)
429 catch_exception_raise_state_identity
430 (mach_port_t port
, mach_port_t thread_port
, mach_port_t task_port
,
431 exception_type_t exception_type
, mach_exception_data_t exception_data
,
432 mach_msg_type_number_t data_count
, thread_state_flavor_t
* state_flavor
,
433 thread_state_t in_state
, mach_msg_type_number_t in_state_count
,
434 thread_state_t out_state
, mach_msg_type_number_t out_state_count
)
438 kret
= mach_port_deallocate (mach_task_self (), task_port
);
439 MACH_CHECK_ERROR (kret
);
440 kret
= mach_port_deallocate (mach_task_self (), thread_port
);
441 MACH_CHECK_ERROR (kret
);
447 catch_exception_raise (mach_port_t port
,
448 mach_port_t thread_port
,
449 mach_port_t task_port
,
450 exception_type_t exception_type
,
451 exception_data_t exception_data
,
452 mach_msg_type_number_t data_count
)
458 /* We got new rights to the task. Get rid of it. */
459 kret
= mach_port_deallocate (mach_task_self (), task_port
);
460 MACH_CHECK_ERROR (kret
);
463 (7, _("catch_exception_raise: exception_type=%d, data_count=%d\n"),
464 exception_type
, data_count
);
465 if (darwin_debug_flag
> 7)
467 for (i
= 0; i
< data_count
; i
++)
468 printf_unfiltered (" %08x", exception_data
[i
]);
469 printf_unfiltered ("\n");
473 FIXME: this should be in a per-thread variable. */
475 exc_msg
.thread_port
= thread_port
;
476 exc_msg
.task_port
= task_port
;
477 exc_msg
.ex_type
= exception_type
;
478 exc_msg
.data_count
= data_count
;
479 for (i
= 0; i
< data_count
&& i
< 4; i
++)
480 exc_msg
.ex_data
[i
] = exception_data
[i
];
486 darwin_wait (ptid_t ptid
, struct target_waitstatus
*status
)
489 mach_msg_header_t
*hdr
= &msgin
.hdr
;
490 pid_t pid
= ptid_get_pid (inferior_ptid
); /* FIXME. */
492 gdb_assert (msg_state
!= GOT_MESSAGE
);
494 inferior_debug (6, _("darwin_wait: waiting for a message\n"));
496 /* Wait for a message. */
497 kret
= mach_msg (&msgin
.hdr
, MACH_RCV_MSG
| MACH_RCV_INTERRUPT
, 0,
498 sizeof (msgin
.data
), darwin_port_set
, 0, MACH_PORT_NULL
);
500 if (kret
== MACH_RCV_INTERRUPTED
)
502 status
->kind
= TARGET_WAITKIND_IGNORE
;
503 return minus_one_ptid
;
506 if (kret
!= MACH_MSG_SUCCESS
)
508 inferior_debug (1, _("mach_msg: ret=%x\n"), kret
);
509 status
->kind
= TARGET_WAITKIND_SPURIOUS
;
510 return minus_one_ptid
;
513 /* Debug: display message. */
514 if (darwin_debug_flag
> 10)
516 const unsigned long *buf
= (unsigned long *) hdr
;
519 printf_unfiltered (_(" bits: 0x%x"), hdr
->msgh_bits
);
520 printf_unfiltered (_(", size: 0x%x"), hdr
->msgh_size
);
521 printf_unfiltered (_(", remote-port: 0x%x"), hdr
->msgh_remote_port
);
522 printf_unfiltered (_(", local-port: 0x%x"), hdr
->msgh_local_port
);
523 printf_unfiltered (_(", reserved: 0x%x"), hdr
->msgh_reserved
);
524 printf_unfiltered (_(", id: 0x%x\n"), hdr
->msgh_id
);
526 if (darwin_debug_flag
> 11)
528 printf_unfiltered (_(" data:"));
529 for (i
= 0; i
< hdr
->msgh_size
; i
++)
530 printf_unfiltered (" %08lx", buf
[i
]);
531 printf_unfiltered (_("\n"));
535 /* Exception message. */
536 if (hdr
->msgh_local_port
== darwin_ex_port
)
538 /* Handle it via the exception server. */
539 if (!exc_server (&msgin
.hdr
, &msgout
.hdr
))
541 printf_unfiltered (_("exc_server: unknown message (id=%x)\n"),
543 status
->kind
= TARGET_WAITKIND_SPURIOUS
;
544 return minus_one_ptid
;
547 status
->kind
= TARGET_WAITKIND_STOPPED
;
549 inferior_debug (2, _("darwin_wait: thread=%x, got %s\n"),
551 unparse_exception_type (exc_msg
.ex_type
));
553 switch (exc_msg
.ex_type
)
556 status
->value
.sig
= TARGET_EXC_BAD_ACCESS
;
558 case EXC_BAD_INSTRUCTION
:
559 status
->value
.sig
= TARGET_EXC_BAD_INSTRUCTION
;
562 status
->value
.sig
= TARGET_EXC_ARITHMETIC
;
565 status
->value
.sig
= TARGET_EXC_EMULATION
;
568 if (exc_msg
.ex_data
[0] == EXC_SOFT_SIGNAL
)
570 status
->value
.sig
= target_signal_from_host (exc_msg
.ex_data
[1]);
571 inferior_debug (2, _(" (signal %d: %s)\n"),
573 target_signal_to_name (status
->value
.sig
));
576 status
->value
.sig
= TARGET_EXC_SOFTWARE
;
579 /* Many internal GDB routines expect breakpoints to be reported
580 as TARGET_SIGNAL_TRAP, and will report TARGET_EXC_BREAKPOINT
581 as a spurious signal. */
582 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
585 status
->value
.sig
= TARGET_SIGNAL_UNKNOWN
;
589 msg_state
= GOT_MESSAGE
;
591 return ptid_build (pid
, 0, exc_msg
.thread_port
);
593 else if (hdr
->msgh_local_port
== darwin_not_port
)
598 /* FIXME: translate task port to pid. */
599 res
= wait4 (pid
, &wstatus
, 0, NULL
);
602 printf_unfiltered (_("wait4: res=%x\n"), res
);
605 status
->kind
= TARGET_WAITKIND_EXITED
;
606 status
->value
.integer
= WEXITSTATUS (wstatus
);
608 inferior_debug (2, _("darwin_wait: pid=%d exit, status=%x\n"),
611 msg_state
= NO_MESSAGE
;
617 printf_unfiltered (_("Bad local-port: %x\n"), hdr
->msgh_local_port
);
618 status
->kind
= TARGET_WAITKIND_SPURIOUS
;
619 return minus_one_ptid
;
624 darwin_mourn_inferior (struct target_ops
*ops
)
626 struct inferior
*inf
= current_inferior ();
631 unpush_target (darwin_ops
);
633 /* Deallocate threads. */
634 if (darwin_inf
->threads
)
638 for (k
= 0; VEC_iterate (thread_t
, darwin_inf
->threads
, k
, t
); k
++)
640 kret
= mach_port_deallocate (gdb_task
, t
);
641 MACH_CHECK_ERROR (kret
);
643 VEC_free (thread_t
, darwin_inf
->threads
);
644 darwin_inf
->threads
= NULL
;
647 kret
= mach_port_request_notification (gdb_task
, darwin_inf
->task
,
648 MACH_NOTIFY_DEAD_NAME
, 0,
649 darwin_inf
->prev_not_port
,
650 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
652 /* This can fail if the task is dead. */
653 if (kret
== KERN_SUCCESS
)
655 kret
= mach_port_deallocate (gdb_task
, prev
);
656 MACH_CHECK_ERROR (kret
);
659 /* Deallocate saved exception ports. */
660 for (i
= 0; i
< darwin_inf
->exception_info
.count
; i
++)
662 kret
= mach_port_deallocate
663 (gdb_task
, darwin_inf
->exception_info
.ports
[i
]);
664 MACH_CHECK_ERROR (kret
);
666 darwin_inf
->exception_info
.count
= 0;
668 kret
= mach_port_deallocate (gdb_task
, darwin_inf
->task
);
669 MACH_CHECK_ERROR (kret
);
671 darwin_inf
->task
= 0;
674 generic_mourn_inferior ();
678 darwin_stop_inferior (darwin_inferior
*inf
)
680 struct target_waitstatus wstatus
;
686 gdb_assert (inf
!= NULL
);
688 kret
= task_suspend (inf
->task
);
689 MACH_CHECK_ERROR (kret
);
691 if (msg_state
== GOT_MESSAGE
)
692 darwin_resume (inferior_ptid
, 0, 0);
694 res
= kill (inf
->pid
, SIGSTOP
);
696 warning (_("cannot kill: %s\n"), strerror (errno
));
698 ptid
= darwin_wait (inferior_ptid
, &wstatus
);
699 gdb_assert (wstatus
.kind
= TARGET_WAITKIND_STOPPED
);
703 darwin_kill_inferior (void)
705 struct target_waitstatus wstatus
;
711 gdb_assert (darwin_inf
!= NULL
);
713 if (ptid_equal (inferior_ptid
, null_ptid
))
716 darwin_stop_inferior (darwin_inf
);
718 res
= PTRACE (PT_KILL
, darwin_inf
->pid
, 0, 0);
719 gdb_assert (res
== 0);
721 if (msg_state
== GOT_MESSAGE
)
724 darwin_resume (inferior_ptid
, 0, 0);
727 kret
= task_resume (darwin_inf
->task
);
728 MACH_CHECK_ERROR (kret
);
730 ptid
= darwin_wait (inferior_ptid
, &wstatus
);
732 /* This double wait seems required... */
733 res
= waitpid (darwin_inf
->pid
, &status
, 0);
734 gdb_assert (res
== darwin_inf
->pid
);
736 msg_state
= NO_MESSAGE
;
738 target_mourn_inferior ();
741 /* The child must synchronize with gdb: gdb must set the exception port
742 before the child call PTRACE_SIGEXC. We use a pipe to achieve this.
743 FIXME: is there a lighter way ? */
744 static int ptrace_fds
[2];
747 darwin_ptrace_me (void)
752 /* Close write end point. */
753 close (ptrace_fds
[1]);
755 /* Wait until gdb is ready. */
756 res
= read (ptrace_fds
[0], &c
, 1);
757 gdb_assert (res
== 0);
758 close (ptrace_fds
[0]);
760 /* Get rid of privileges. */
764 PTRACE (PT_TRACE_ME
, 0, 0, 0);
766 /* Redirect signals to exception port. */
767 PTRACE (PT_SIGEXC
, 0, 0, 0);
770 /* Dummy function to be sure fork_inferior uses fork(2) and not vfork(2). */
772 darwin_pre_ptrace (void)
774 if (pipe (ptrace_fds
) != 0)
778 error (_("unable to create a pipe: %s"), safe_strerror (errno
));
783 darwin_save_exception_ports (darwin_inferior
*inf
)
787 inf
->exception_info
.count
=
788 sizeof (inf
->exception_info
.ports
) / sizeof (inf
->exception_info
.ports
[0]);
790 kret
= task_get_exception_ports
791 (inf
->task
, EXC_MASK_ALL
, inf
->exception_info
.masks
,
792 &inf
->exception_info
.count
, inf
->exception_info
.ports
,
793 inf
->exception_info
.behaviors
, inf
->exception_info
.flavors
);
798 darwin_restore_exception_ports (darwin_inferior
*inf
)
803 for (i
= 0; i
< inf
->exception_info
.count
; i
++)
805 kret
= task_set_exception_ports
806 (inf
->task
, inf
->exception_info
.masks
[i
], inf
->exception_info
.ports
[i
],
807 inf
->exception_info
.behaviors
[i
], inf
->exception_info
.flavors
[i
]);
808 if (kret
!= KERN_SUCCESS
)
816 darwin_attach_pid (int pid
)
820 mach_port_t prev_port
;
822 exception_mask_t mask
;
824 kret
= task_for_pid (gdb_task
, pid
, &itask
);
825 if (kret
!= KERN_SUCCESS
)
828 struct inferior
*inf
= current_inferior ();
830 if (!inf
->attach_flag
)
833 waitpid (pid
, &status
, 0);
836 error (_("Unable to find Mach task port for process-id %d: %s (0x%lx).\n"
837 " (please check gdb is setgid procmod)"),
838 pid
, mach_error_string (kret
), (unsigned long) kret
);
841 inferior_debug (2, _("inferior task: 0x%08x, pid: %d\n"), itask
, pid
);
843 if (darwin_ex_port
== MACH_PORT_NULL
)
845 /* Create a port to get exceptions. */
846 kret
= mach_port_allocate (gdb_task
, MACH_PORT_RIGHT_RECEIVE
,
848 gdb_assert (kret
== KERN_SUCCESS
);
850 kret
= mach_port_insert_right (gdb_task
, darwin_ex_port
, darwin_ex_port
,
851 MACH_MSG_TYPE_MAKE_SEND
);
852 gdb_assert (kret
== KERN_SUCCESS
);
854 /* Create a port set and put ex_port in it. */
855 kret
= mach_port_allocate (gdb_task
, MACH_PORT_RIGHT_PORT_SET
,
857 gdb_assert (kret
== KERN_SUCCESS
);
859 kret
= mach_port_move_member (gdb_task
, darwin_ex_port
, darwin_port_set
);
860 gdb_assert (kret
== KERN_SUCCESS
);
862 /* Create a port to be notified when the child task terminates. */
863 kret
= mach_port_allocate (gdb_task
, MACH_PORT_RIGHT_RECEIVE
,
865 gdb_assert (kret
== KERN_SUCCESS
);
867 kret
= mach_port_insert_right (gdb_task
, darwin_not_port
, darwin_not_port
,
868 MACH_MSG_TYPE_MAKE_SEND
);
869 gdb_assert (kret
== KERN_SUCCESS
);
871 kret
= mach_port_move_member (gdb_task
, darwin_not_port
, darwin_port_set
);
872 gdb_assert (kret
== KERN_SUCCESS
);
875 kret
= mach_port_request_notification (gdb_task
, itask
,
876 MACH_NOTIFY_DEAD_NAME
, 0,
878 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
879 &darwin_inf
->prev_not_port
);
880 gdb_assert (kret
== KERN_SUCCESS
);
882 darwin_inf
->task
= itask
;
883 darwin_inf
->pid
= pid
;
885 kret
= darwin_save_exception_ports (darwin_inf
);
886 gdb_assert (kret
== KERN_SUCCESS
);
888 /* Set exception port. */
889 if (enable_mach_exceptions
)
892 mask
= EXC_MASK_SOFTWARE
;
893 kret
= task_set_exception_ports
894 (itask
, mask
, darwin_ex_port
, EXCEPTION_DEFAULT
, THREAD_STATE_NONE
);
895 gdb_assert (kret
== KERN_SUCCESS
);
897 push_target (darwin_ops
);
901 darwin_init_thread_list (darwin_inferior
*inf
)
905 darwin_check_new_threads (inf
);
907 gdb_assert (inf
->threads
&& VEC_length (thread_t
, inf
->threads
) > 0);
908 thread
= VEC_index (thread_t
, inf
->threads
, 0);
909 inferior_ptid
= ptid_build (inf
->pid
, 0, thread
);
913 darwin_ptrace_him (int pid
)
917 mach_port_t prev_port
;
920 darwin_attach_pid (pid
);
922 /* Let's the child run. */
923 close (ptrace_fds
[0]);
924 close (ptrace_fds
[1]);
926 /* fork_inferior automatically add a thread - but it uses a wrong tid. */
927 delete_thread_silent (inferior_ptid
);
928 darwin_init_thread_list (darwin_inf
);
930 startup_inferior (START_INFERIOR_TRAPS_EXPECTED
);
934 darwin_create_inferior (struct target_ops
*ops
, char *exec_file
,
935 char *allargs
, char **env
, int from_tty
)
937 /* Do the hard work. */
938 fork_inferior (exec_file
, allargs
, env
, darwin_ptrace_me
, darwin_ptrace_him
,
939 darwin_pre_ptrace
, NULL
);
941 /* Return now in case of error. */
942 if (ptid_equal (inferior_ptid
, null_ptid
))
947 /* Attach to process PID, then initialize for debugging it
948 and wait for the trace-trap that results from attaching. */
950 darwin_attach (struct target_ops
*ops
, char *args
, int from_tty
)
956 struct inferior
*inf
;
958 gdb_assert (msg_state
== NO_MESSAGE
);
961 error_no_arg (_("process-id to attach"));
965 if (pid
== getpid ()) /* Trying to masturbate? */
966 error (_("I refuse to debug myself!"));
969 printf_unfiltered (_("Attaching to pid %d\n"), pid
);
971 res
= PTRACE (PT_ATTACHEXC
, pid
, 0, 0);
973 error (_("Unable to attach to process-id %d: %s (%d)"),
974 pid
, strerror (errno
), errno
);
976 inf
= add_inferior (pid
);
977 inf
->attach_flag
= 1;
979 darwin_attach_pid (pid
);
981 pid2
= wait4 (pid
, &wstatus
, WUNTRACED
, NULL
);
982 gdb_assert (pid2
== pid
);
983 inferior_debug (1, _("darwin_attach: wait4 pid=%d, status=0x%x\n"),
987 darwin_init_thread_list (darwin_inf
);
989 darwin_check_osabi (darwin_inf
, ptid_get_tid (inferior_ptid
));
991 /* Looks strange, but the kernel doesn't stop the process...
994 /* FIXME: doesn't look to work with multi-threads!! */
998 /* Take a program previously attached to and detaches it.
999 The program resumes execution and will no longer stop
1000 on signals, etc. We'd better not have left any breakpoints
1001 in the program or it'll die when it hits one. For this
1002 to work, it may be necessary for the process to have been
1003 previously attached. It *might* work if the program was
1004 started via fork. */
1006 darwin_detach (struct target_ops
*ops
, char *args
, int from_tty
)
1013 char *exec_file
= get_exec_file (0);
1016 printf_unfiltered (_("Detaching from program: %s, %d\n"), exec_file
,
1017 ptid_get_pid (inferior_ptid
));
1018 gdb_flush (gdb_stdout
);
1021 darwin_stop_inferior (darwin_inf
);
1023 kret
= darwin_restore_exception_ports (darwin_inf
);
1024 MACH_CHECK_ERROR (kret
);
1026 if (msg_state
== GOT_MESSAGE
)
1028 exc_msg
.ex_type
= 0;
1029 darwin_resume (inferior_ptid
, 0, 0);
1032 kret
= task_resume (darwin_inf
->task
);
1033 gdb_assert (kret
== KERN_SUCCESS
);
1035 res
= PTRACE (PT_DETACH
, darwin_inf
->pid
, 0, 0);
1037 printf_unfiltered (_("Unable to detach from process-id %d: %s (%d)"),
1038 darwin_inf
->pid
, strerror (errno
), errno
);
1040 msg_state
= NO_MESSAGE
;
1042 darwin_mourn_inferior (ops
);
1046 darwin_files_info (struct target_ops
*ops
)
1048 gdb_assert (darwin_inf
!= NULL
);
1052 darwin_pid_to_str (ptid_t ptid
)
1054 static char buf
[128];
1056 snprintf (buf
, sizeof (buf
),
1057 _("process %d gdb-thread 0x%lx"),
1058 (unsigned) ptid_get_pid (ptid
),
1059 (unsigned long) ptid_get_tid (ptid
));
1064 darwin_thread_alive (ptid_t ptid
)
1069 /* If RDADDR is not NULL, read inferior task's LEN bytes from ADDR and
1070 copy it to RDADDR in gdb's address space.
1071 If WRADDR is not NULL, write gdb's LEN bytes from WRADDR and copy it
1072 to ADDR in inferior task's address space.
1073 Return 0 on failure; number of bytes read / writen otherwise. */
1075 darwin_read_write_inferior (task_t task
, CORE_ADDR addr
,
1076 char *rdaddr
, const char *wraddr
, int length
)
1079 mach_vm_address_t offset
= addr
& (mach_page_size
- 1);
1080 mach_vm_address_t low_address
= (mach_vm_address_t
) (addr
- offset
);
1081 mach_vm_size_t aligned_length
= (mach_vm_size_t
) PAGE_ROUND (offset
+ length
);
1084 mach_vm_size_t remaining_length
;
1085 mach_vm_address_t region_address
;
1086 mach_vm_size_t region_length
;
1088 inferior_debug (8, _("darwin_read_write_inferior(%s, len=%d)\n"),
1089 core_addr_to_string (addr
), length
);
1091 /* Get memory from inferior with page aligned addresses */
1092 err
= mach_vm_read (task
, low_address
, aligned_length
,
1093 &copied
, ©_count
);
1094 if (err
!= KERN_SUCCESS
)
1096 warning (_("darwin_read_write_inferior: vm_read failed: %s"),
1097 mach_error_string (err
));
1102 memcpy (rdaddr
, (char *)copied
+ offset
, length
);
1107 memcpy ((char *)copied
+ offset
, wraddr
, length
);
1109 /* Do writes atomically.
1110 First check for holes and unwritable memory. */
1111 for (region_address
= low_address
, remaining_length
= aligned_length
;
1112 region_address
< low_address
+ aligned_length
;
1113 region_address
+= region_length
, remaining_length
-= region_length
)
1115 vm_region_basic_info_data_64_t info
;
1116 mach_port_t object_name
;
1117 mach_vm_address_t old_address
= region_address
;
1118 mach_msg_type_number_t count
;
1120 region_length
= remaining_length
;
1121 count
= VM_REGION_BASIC_INFO_COUNT_64
;
1122 err
= mach_vm_region (task
, ®ion_address
, ®ion_length
,
1123 VM_REGION_BASIC_INFO_64
,
1124 (vm_region_info_t
) &info
, &count
, &object_name
);
1126 if (err
!= KERN_SUCCESS
)
1128 warning (_("darwin_write_inferior: mach_vm_region failed: %s"),
1129 mach_error_string (err
));
1133 /* Check for holes in memory */
1134 if (region_address
> old_address
)
1136 warning (_("No memory at %s (vs %s+0x%x). Nothing written"),
1137 core_addr_to_string (old_address
),
1138 core_addr_to_string (region_address
),
1139 (unsigned)region_length
);
1144 if (!(info
.max_protection
& VM_PROT_WRITE
))
1146 warning (_("Memory at address %s is unwritable. Nothing written"),
1147 core_addr_to_string (old_address
));
1152 if (!(info
.protection
& VM_PROT_WRITE
))
1154 err
= mach_vm_protect (task
, old_address
, region_length
,
1155 FALSE
, info
.protection
| VM_PROT_WRITE
);
1156 if (err
!= KERN_SUCCESS
)
1159 (_("darwin_read_write_inferior: mach_vm_protect failed: %s"),
1160 mach_error_string (err
));
1167 err
= mach_vm_write (task
, low_address
, copied
, aligned_length
);
1169 if (err
!= KERN_SUCCESS
)
1171 warning (_("darwin_read_write_inferior: mach_vm_write failed: %s"),
1172 mach_error_string (err
));
1176 mach_vm_deallocate (mach_task_self (), copied
, copy_count
);
1181 /* Return 0 on failure, number of bytes handled otherwise. TARGET
1184 darwin_xfer_memory (CORE_ADDR memaddr
, gdb_byte
*myaddr
, int len
, int write
,
1185 struct mem_attrib
*attrib
, struct target_ops
*target
)
1187 task_t task
= darwin_inf
->task
;
1189 if (task
== MACH_PORT_NULL
)
1192 inferior_debug (8, _("darwin_xfer_memory(%s, %d, %c)\n"),
1193 core_addr_to_string (memaddr
), len
, write
? 'w' : 'r');
1196 return darwin_read_write_inferior (task
, memaddr
, NULL
, myaddr
, len
);
1198 return darwin_read_write_inferior (task
, memaddr
, myaddr
, NULL
, len
);
1202 darwin_xfer_partial (struct target_ops
*ops
,
1203 enum target_object object
, const char *annex
,
1204 gdb_byte
*readbuf
, const gdb_byte
*writebuf
,
1205 ULONGEST offset
, LONGEST len
)
1207 inferior_debug (8, _("darwin_xfer_partial(%s, %d, rbuf=%p, wbuf=%p)\n"),
1208 core_addr_to_string (offset
), (int)len
, readbuf
, writebuf
);
1210 if (object
!= TARGET_OBJECT_MEMORY
)
1213 return darwin_read_write_inferior (darwin_inf
->task
, offset
,
1214 readbuf
, writebuf
, len
);
1218 set_enable_mach_exceptions (char *args
, int from_tty
,
1219 struct cmd_list_element
*c
)
1221 if (darwin_inf
&& darwin_inf
->task
!= TASK_NULL
)
1223 exception_mask_t mask
;
1226 if (enable_mach_exceptions
)
1227 mask
= EXC_MASK_ALL
;
1230 darwin_restore_exception_ports (darwin_inf
);
1231 mask
= EXC_MASK_SOFTWARE
;
1233 kret
= task_set_exception_ports (darwin_inf
->task
, mask
, darwin_ex_port
,
1234 EXCEPTION_DEFAULT
, THREAD_STATE_NONE
);
1235 MACH_CHECK_ERROR (kret
);
1240 _initialize_darwin_inferior ()
1244 gdb_assert (darwin_inf
== NULL
);
1246 gdb_task
= mach_task_self ();
1247 darwin_host_self
= mach_host_self ();
1249 /* Read page size. */
1250 kret
= host_page_size (darwin_host_self
, &mach_page_size
);
1251 if (kret
!= KERN_SUCCESS
)
1253 mach_page_size
= 0x1000;
1254 MACH_CHECK_ERROR (kret
);
1257 darwin_inf
= (struct darwin_inferior
*)
1258 xmalloc (sizeof (struct darwin_inferior
));
1260 memset (darwin_inf
, 0, sizeof (*darwin_inf
));
1262 darwin_ops
= inf_child_target ();
1264 darwin_ops
->to_shortname
= "darwin-child";
1265 darwin_ops
->to_longname
= _("Darwin child process");
1266 darwin_ops
->to_doc
=
1267 _("Darwin child process (started by the \"run\" command).");
1268 darwin_ops
->to_create_inferior
= darwin_create_inferior
;
1269 darwin_ops
->to_attach
= darwin_attach
;
1270 darwin_ops
->to_attach_no_wait
= 0;
1271 darwin_ops
->to_detach
= darwin_detach
;
1272 darwin_ops
->to_files_info
= darwin_files_info
;
1273 darwin_ops
->to_wait
= darwin_wait
;
1274 darwin_ops
->to_mourn_inferior
= darwin_mourn_inferior
;
1275 darwin_ops
->to_kill
= darwin_kill_inferior
;
1276 darwin_ops
->to_stop
= darwin_stop
;
1277 darwin_ops
->to_resume
= darwin_resume
;
1278 darwin_ops
->to_thread_alive
= darwin_thread_alive
;
1279 darwin_ops
->to_pid_to_str
= darwin_pid_to_str
;
1280 darwin_ops
->to_load
= NULL
;
1281 darwin_ops
->deprecated_xfer_memory
= darwin_xfer_memory
;
1282 darwin_ops
->to_xfer_partial
= darwin_xfer_partial
;
1283 darwin_ops
->to_has_thread_control
= tc_schedlock
/*| tc_switch */;
1285 darwin_complete_target (darwin_ops
);
1287 add_target (darwin_ops
);
1289 inferior_debug (2, _("GDB task: 0x%lx, pid: %d\n"), mach_task_self (),
1292 add_setshow_zinteger_cmd ("darwin", class_obscure
,
1293 &darwin_debug_flag
, _("\
1294 Set if printing inferior communication debugging statements."), _("\
1295 Show if printing inferior communication debugging statements."), NULL
,
1297 &setdebuglist
, &showdebuglist
);
1299 add_setshow_boolean_cmd ("mach-exceptions", class_support
,
1300 &enable_mach_exceptions
, _("\
1301 Set if mach exceptions are caught."), _("\
1302 Show if mach exceptions are caught."), _("\
1303 When this mode is on, all low level exceptions are reported before being\n\
1304 reported by the kernel."),
1305 &set_enable_mach_exceptions
, NULL
,
1306 &setlist
, &showlist
);