GDB (API)
|
00001 /* Low-level child interface to ttrace. 00002 00003 Copyright (C) 2004-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 00022 /* The ttrace(2) system call didn't exist before HP-UX 10.30. Don't 00023 try to compile this code unless we have it. */ 00024 #ifdef HAVE_TTRACE 00025 00026 #include "command.h" 00027 #include "gdbcore.h" 00028 #include "gdbthread.h" 00029 #include "inferior.h" 00030 #include "terminal.h" 00031 #include "target.h" 00032 00033 #include "gdb_assert.h" 00034 #include "gdb_string.h" 00035 #include <sys/mman.h> 00036 #include <sys/ttrace.h> 00037 #include <signal.h> 00038 00039 #include "inf-child.h" 00040 #include "inf-ttrace.h" 00041 #include "common/filestuff.h" 00042 00043 00044 00045 /* HP-UX uses a threading model where each user-space thread 00046 corresponds to a kernel thread. These kernel threads are called 00047 lwps. The ttrace(2) interface gives us almost full control over 00048 the threads, which makes it very easy to support them in GDB. We 00049 identify the threads by process ID and lwp ID. The ttrace(2) also 00050 provides us with a thread's user ID (in the `tts_user_tid' member 00051 of `ttstate_t') but we don't use that (yet) as it isn't necessary 00052 to uniquely label the thread. */ 00053 00054 /* Number of active lwps. */ 00055 static int inf_ttrace_num_lwps; 00056 00057 00058 /* On HP-UX versions that have the ttrace(2) system call, we can 00059 implement "hardware" watchpoints by fiddling with the protection of 00060 pages in the address space that contain the variable being watched. 00061 In order to implement this, we keep a dictionary of pages for which 00062 we have changed the protection. */ 00063 00064 struct inf_ttrace_page 00065 { 00066 CORE_ADDR addr; /* Page address. */ 00067 int prot; /* Protection. */ 00068 int refcount; /* Reference count. */ 00069 struct inf_ttrace_page *next; 00070 struct inf_ttrace_page *prev; 00071 }; 00072 00073 struct inf_ttrace_page_dict 00074 { 00075 struct inf_ttrace_page buckets[128]; 00076 int pagesize; /* Page size. */ 00077 int count; /* Number of pages in this dictionary. */ 00078 } inf_ttrace_page_dict; 00079 00080 struct inf_ttrace_private_thread_info 00081 { 00082 int dying; 00083 }; 00084 00085 /* Number of lwps that are currently in a system call. */ 00086 static int inf_ttrace_num_lwps_in_syscall; 00087 00088 /* Flag to indicate whether we should re-enable page protections after 00089 the next wait. */ 00090 static int inf_ttrace_reenable_page_protections; 00091 00092 /* Enable system call events for process PID. */ 00093 00094 static void 00095 inf_ttrace_enable_syscall_events (pid_t pid) 00096 { 00097 ttevent_t tte; 00098 ttstate_t tts; 00099 00100 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); 00101 00102 if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0, 00103 (uintptr_t)&tte, sizeof tte, 0) == -1) 00104 perror_with_name (("ttrace")); 00105 00106 tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN); 00107 00108 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, 00109 (uintptr_t)&tte, sizeof tte, 0) == -1) 00110 perror_with_name (("ttrace")); 00111 00112 if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0, 00113 (uintptr_t)&tts, sizeof tts, 0) == -1) 00114 perror_with_name (("ttrace")); 00115 00116 if (tts.tts_flags & TTS_INSYSCALL) 00117 inf_ttrace_num_lwps_in_syscall++; 00118 00119 /* FIXME: Handle multiple threads. */ 00120 } 00121 00122 /* Disable system call events for process PID. */ 00123 00124 static void 00125 inf_ttrace_disable_syscall_events (pid_t pid) 00126 { 00127 ttevent_t tte; 00128 00129 gdb_assert (inf_ttrace_page_dict.count == 0); 00130 00131 if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0, 00132 (uintptr_t)&tte, sizeof tte, 0) == -1) 00133 perror_with_name (("ttrace")); 00134 00135 tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN); 00136 00137 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, 00138 (uintptr_t)&tte, sizeof tte, 0) == -1) 00139 perror_with_name (("ttrace")); 00140 00141 inf_ttrace_num_lwps_in_syscall = 0; 00142 } 00143 00144 /* Get information about the page at address ADDR for process PID from 00145 the dictionary. */ 00146 00147 static struct inf_ttrace_page * 00148 inf_ttrace_get_page (pid_t pid, CORE_ADDR addr) 00149 { 00150 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); 00151 const int pagesize = inf_ttrace_page_dict.pagesize; 00152 int bucket; 00153 struct inf_ttrace_page *page; 00154 00155 bucket = (addr / pagesize) % num_buckets; 00156 page = &inf_ttrace_page_dict.buckets[bucket]; 00157 while (page) 00158 { 00159 if (page->addr == addr) 00160 break; 00161 00162 page = page->next; 00163 } 00164 00165 return page; 00166 } 00167 00168 /* Add the page at address ADDR for process PID to the dictionary. */ 00169 00170 static struct inf_ttrace_page * 00171 inf_ttrace_add_page (pid_t pid, CORE_ADDR addr) 00172 { 00173 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); 00174 const int pagesize = inf_ttrace_page_dict.pagesize; 00175 int bucket; 00176 struct inf_ttrace_page *page; 00177 struct inf_ttrace_page *prev = NULL; 00178 00179 bucket = (addr / pagesize) % num_buckets; 00180 page = &inf_ttrace_page_dict.buckets[bucket]; 00181 while (page) 00182 { 00183 if (page->addr == addr) 00184 break; 00185 00186 prev = page; 00187 page = page->next; 00188 } 00189 00190 if (!page) 00191 { 00192 int prot; 00193 00194 if (ttrace (TT_PROC_GET_MPROTECT, pid, 0, 00195 addr, 0, (uintptr_t)&prot) == -1) 00196 perror_with_name (("ttrace")); 00197 00198 page = XMALLOC (struct inf_ttrace_page); 00199 page->addr = addr; 00200 page->prot = prot; 00201 page->refcount = 0; 00202 page->next = NULL; 00203 00204 page->prev = prev; 00205 prev->next = page; 00206 00207 inf_ttrace_page_dict.count++; 00208 if (inf_ttrace_page_dict.count == 1) 00209 inf_ttrace_enable_syscall_events (pid); 00210 00211 if (inf_ttrace_num_lwps_in_syscall == 0) 00212 { 00213 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0, 00214 addr, pagesize, prot & ~PROT_WRITE) == -1) 00215 perror_with_name (("ttrace")); 00216 } 00217 } 00218 00219 return page; 00220 } 00221 00222 /* Insert the page at address ADDR of process PID to the dictionary. */ 00223 00224 static void 00225 inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr) 00226 { 00227 struct inf_ttrace_page *page; 00228 00229 page = inf_ttrace_get_page (pid, addr); 00230 if (!page) 00231 page = inf_ttrace_add_page (pid, addr); 00232 00233 page->refcount++; 00234 } 00235 00236 /* Remove the page at address ADDR of process PID from the dictionary. */ 00237 00238 static void 00239 inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr) 00240 { 00241 const int pagesize = inf_ttrace_page_dict.pagesize; 00242 struct inf_ttrace_page *page; 00243 00244 page = inf_ttrace_get_page (pid, addr); 00245 page->refcount--; 00246 00247 gdb_assert (page->refcount >= 0); 00248 00249 if (page->refcount == 0) 00250 { 00251 if (inf_ttrace_num_lwps_in_syscall == 0) 00252 { 00253 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0, 00254 addr, pagesize, page->prot) == -1) 00255 perror_with_name (("ttrace")); 00256 } 00257 00258 inf_ttrace_page_dict.count--; 00259 if (inf_ttrace_page_dict.count == 0) 00260 inf_ttrace_disable_syscall_events (pid); 00261 00262 page->prev->next = page->next; 00263 if (page->next) 00264 page->next->prev = page->prev; 00265 00266 xfree (page); 00267 } 00268 } 00269 00270 /* Mask the bits in PROT from the page protections that are currently 00271 in the dictionary for process PID. */ 00272 00273 static void 00274 inf_ttrace_mask_page_protections (pid_t pid, int prot) 00275 { 00276 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); 00277 const int pagesize = inf_ttrace_page_dict.pagesize; 00278 int bucket; 00279 00280 for (bucket = 0; bucket < num_buckets; bucket++) 00281 { 00282 struct inf_ttrace_page *page; 00283 00284 page = inf_ttrace_page_dict.buckets[bucket].next; 00285 while (page) 00286 { 00287 if (ttrace (TT_PROC_SET_MPROTECT, pid, 0, 00288 page->addr, pagesize, page->prot & ~prot) == -1) 00289 perror_with_name (("ttrace")); 00290 00291 page = page->next; 00292 } 00293 } 00294 } 00295 00296 /* Write-protect the pages in the dictionary for process PID. */ 00297 00298 static void 00299 inf_ttrace_enable_page_protections (pid_t pid) 00300 { 00301 inf_ttrace_mask_page_protections (pid, PROT_WRITE); 00302 } 00303 00304 /* Restore the protection of the pages in the dictionary for process 00305 PID. */ 00306 00307 static void 00308 inf_ttrace_disable_page_protections (pid_t pid) 00309 { 00310 inf_ttrace_mask_page_protections (pid, 0); 00311 } 00312 00313 /* Insert a "hardware" watchpoint for LEN bytes at address ADDR of 00314 type TYPE. */ 00315 00316 static int 00317 inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type, 00318 struct expression *cond) 00319 { 00320 const int pagesize = inf_ttrace_page_dict.pagesize; 00321 pid_t pid = ptid_get_pid (inferior_ptid); 00322 CORE_ADDR page_addr; 00323 int num_pages; 00324 int page; 00325 00326 gdb_assert (type == hw_write); 00327 00328 page_addr = (addr / pagesize) * pagesize; 00329 num_pages = (len + pagesize - 1) / pagesize; 00330 00331 for (page = 0; page < num_pages; page++, page_addr += pagesize) 00332 inf_ttrace_insert_page (pid, page_addr); 00333 00334 return 1; 00335 } 00336 00337 /* Remove a "hardware" watchpoint for LEN bytes at address ADDR of 00338 type TYPE. */ 00339 00340 static int 00341 inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type, 00342 struct expression *cond) 00343 { 00344 const int pagesize = inf_ttrace_page_dict.pagesize; 00345 pid_t pid = ptid_get_pid (inferior_ptid); 00346 CORE_ADDR page_addr; 00347 int num_pages; 00348 int page; 00349 00350 gdb_assert (type == hw_write); 00351 00352 page_addr = (addr / pagesize) * pagesize; 00353 num_pages = (len + pagesize - 1) / pagesize; 00354 00355 for (page = 0; page < num_pages; page++, page_addr += pagesize) 00356 inf_ttrace_remove_page (pid, page_addr); 00357 00358 return 1; 00359 } 00360 00361 static int 00362 inf_ttrace_can_use_hw_breakpoint (int type, int len, int ot) 00363 { 00364 return (type == bp_hardware_watchpoint); 00365 } 00366 00367 static int 00368 inf_ttrace_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) 00369 { 00370 return 1; 00371 } 00372 00373 /* Return non-zero if the current inferior was (potentially) stopped 00374 by hitting a "hardware" watchpoint. */ 00375 00376 static int 00377 inf_ttrace_stopped_by_watchpoint (void) 00378 { 00379 pid_t pid = ptid_get_pid (inferior_ptid); 00380 lwpid_t lwpid = ptid_get_lwp (inferior_ptid); 00381 ttstate_t tts; 00382 00383 if (inf_ttrace_page_dict.count > 0) 00384 { 00385 if (ttrace (TT_LWP_GET_STATE, pid, lwpid, 00386 (uintptr_t)&tts, sizeof tts, 0) == -1) 00387 perror_with_name (("ttrace")); 00388 00389 if (tts.tts_event == TTEVT_SIGNAL 00390 && tts.tts_u.tts_signal.tts_signo == SIGBUS) 00391 { 00392 const int pagesize = inf_ttrace_page_dict.pagesize; 00393 void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr; 00394 CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize; 00395 00396 if (inf_ttrace_get_page (pid, page_addr)) 00397 return 1; 00398 } 00399 } 00400 00401 return 0; 00402 } 00403 00404 00405 /* When tracking a vfork(2), we cannot detach from the parent until 00406 after the child has called exec(3) or has exited. If we are still 00407 attached to the parent, this variable will be set to the process ID 00408 of the parent. Otherwise it will be set to zero. */ 00409 static pid_t inf_ttrace_vfork_ppid = -1; 00410 00411 static int 00412 inf_ttrace_follow_fork (struct target_ops *ops, int follow_child, 00413 int detach_fork) 00414 { 00415 pid_t pid, fpid; 00416 lwpid_t lwpid, flwpid; 00417 ttstate_t tts; 00418 struct thread_info *tp = inferior_thread (); 00419 00420 gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED 00421 || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED); 00422 00423 pid = ptid_get_pid (inferior_ptid); 00424 lwpid = ptid_get_lwp (inferior_ptid); 00425 00426 /* Get all important details that core GDB doesn't (and shouldn't) 00427 know about. */ 00428 if (ttrace (TT_LWP_GET_STATE, pid, lwpid, 00429 (uintptr_t)&tts, sizeof tts, 0) == -1) 00430 perror_with_name (("ttrace")); 00431 00432 gdb_assert (tts.tts_event == TTEVT_FORK || tts.tts_event == TTEVT_VFORK); 00433 00434 if (tts.tts_u.tts_fork.tts_isparent) 00435 { 00436 pid = tts.tts_pid; 00437 lwpid = tts.tts_lwpid; 00438 fpid = tts.tts_u.tts_fork.tts_fpid; 00439 flwpid = tts.tts_u.tts_fork.tts_flwpid; 00440 } 00441 else 00442 { 00443 pid = tts.tts_u.tts_fork.tts_fpid; 00444 lwpid = tts.tts_u.tts_fork.tts_flwpid; 00445 fpid = tts.tts_pid; 00446 flwpid = tts.tts_lwpid; 00447 } 00448 00449 if (follow_child) 00450 { 00451 struct inferior *inf; 00452 struct inferior *parent_inf; 00453 00454 parent_inf = find_inferior_pid (pid); 00455 00456 inferior_ptid = ptid_build (fpid, flwpid, 0); 00457 inf = add_inferior (fpid); 00458 inf->attach_flag = parent_inf->attach_flag; 00459 inf->pspace = parent_inf->pspace; 00460 inf->aspace = parent_inf->aspace; 00461 copy_terminal_info (inf, parent_inf); 00462 detach_breakpoints (ptid_build (pid, lwpid, 0)); 00463 00464 target_terminal_ours (); 00465 fprintf_unfiltered (gdb_stdlog, 00466 _("Attaching after fork to child process %ld.\n"), 00467 (long)fpid); 00468 } 00469 else 00470 { 00471 inferior_ptid = ptid_build (pid, lwpid, 0); 00472 /* Detach any remaining breakpoints in the child. In the case 00473 of fork events, we do not need to do this, because breakpoints 00474 should have already been removed earlier. */ 00475 if (tts.tts_event == TTEVT_VFORK) 00476 detach_breakpoints (ptid_build (fpid, flwpid, 0)); 00477 00478 target_terminal_ours (); 00479 fprintf_unfiltered (gdb_stdlog, 00480 _("Detaching after fork from child process %ld.\n"), 00481 (long)fpid); 00482 } 00483 00484 if (tts.tts_event == TTEVT_VFORK) 00485 { 00486 gdb_assert (!tts.tts_u.tts_fork.tts_isparent); 00487 00488 if (follow_child) 00489 { 00490 /* We can't detach from the parent yet. */ 00491 inf_ttrace_vfork_ppid = pid; 00492 00493 reattach_breakpoints (fpid); 00494 } 00495 else 00496 { 00497 if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1) 00498 perror_with_name (("ttrace")); 00499 00500 /* Wait till we get the TTEVT_VFORK event in the parent. 00501 This indicates that the child has called exec(3) or has 00502 exited and that the parent is ready to be traced again. */ 00503 if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1) 00504 perror_with_name (("ttrace_wait")); 00505 gdb_assert (tts.tts_event == TTEVT_VFORK); 00506 gdb_assert (tts.tts_u.tts_fork.tts_isparent); 00507 00508 reattach_breakpoints (pid); 00509 } 00510 } 00511 else 00512 { 00513 gdb_assert (tts.tts_u.tts_fork.tts_isparent); 00514 00515 if (follow_child) 00516 { 00517 if (ttrace (TT_PROC_DETACH, pid, 0, 0, 0, 0) == -1) 00518 perror_with_name (("ttrace")); 00519 } 00520 else 00521 { 00522 if (ttrace (TT_PROC_DETACH, fpid, 0, 0, 0, 0) == -1) 00523 perror_with_name (("ttrace")); 00524 } 00525 } 00526 00527 if (follow_child) 00528 { 00529 struct thread_info *ti; 00530 00531 /* The child will start out single-threaded. */ 00532 inf_ttrace_num_lwps = 1; 00533 inf_ttrace_num_lwps_in_syscall = 0; 00534 00535 /* Delete parent. */ 00536 delete_thread_silent (ptid_build (pid, lwpid, 0)); 00537 detach_inferior (pid); 00538 00539 /* Add child thread. inferior_ptid was already set above. */ 00540 ti = add_thread_silent (inferior_ptid); 00541 ti->private = 00542 xmalloc (sizeof (struct inf_ttrace_private_thread_info)); 00543 memset (ti->private, 0, 00544 sizeof (struct inf_ttrace_private_thread_info)); 00545 } 00546 00547 return 0; 00548 } 00549 00550 00551 /* File descriptors for pipes used as semaphores during initial 00552 startup of an inferior. */ 00553 static int inf_ttrace_pfd1[2]; 00554 static int inf_ttrace_pfd2[2]; 00555 00556 static void 00557 do_cleanup_pfds (void *dummy) 00558 { 00559 close (inf_ttrace_pfd1[0]); 00560 close (inf_ttrace_pfd1[1]); 00561 close (inf_ttrace_pfd2[0]); 00562 close (inf_ttrace_pfd2[1]); 00563 00564 unmark_fd_no_cloexec (inf_ttrace_pfd1[0]); 00565 unmark_fd_no_cloexec (inf_ttrace_pfd1[1]); 00566 unmark_fd_no_cloexec (inf_ttrace_pfd2[0]); 00567 unmark_fd_no_cloexec (inf_ttrace_pfd2[1]); 00568 } 00569 00570 static void 00571 inf_ttrace_prepare (void) 00572 { 00573 if (pipe (inf_ttrace_pfd1) == -1) 00574 perror_with_name (("pipe")); 00575 00576 if (pipe (inf_ttrace_pfd2) == -1) 00577 { 00578 close (inf_ttrace_pfd1[0]); 00579 close (inf_ttrace_pfd2[0]); 00580 perror_with_name (("pipe")); 00581 } 00582 00583 mark_fd_no_cloexec (inf_ttrace_pfd1[0]); 00584 mark_fd_no_cloexec (inf_ttrace_pfd1[1]); 00585 mark_fd_no_cloexec (inf_ttrace_pfd2[0]); 00586 mark_fd_no_cloexec (inf_ttrace_pfd2[1]); 00587 } 00588 00589 /* Prepare to be traced. */ 00590 00591 static void 00592 inf_ttrace_me (void) 00593 { 00594 struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0); 00595 char c; 00596 00597 /* "Trace me, Dr. Memory!" */ 00598 if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1) 00599 perror_with_name (("ttrace")); 00600 00601 /* Tell our parent that we are ready to be traced. */ 00602 if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c) 00603 perror_with_name (("write")); 00604 00605 /* Wait until our parent has set the initial event mask. */ 00606 if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c) 00607 perror_with_name (("read")); 00608 00609 do_cleanups (old_chain); 00610 } 00611 00612 /* Start tracing PID. */ 00613 00614 static void 00615 inf_ttrace_him (struct target_ops *ops, int pid) 00616 { 00617 struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0); 00618 ttevent_t tte; 00619 char c; 00620 00621 /* Wait until our child is ready to be traced. */ 00622 if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c) 00623 perror_with_name (("read")); 00624 00625 /* Set the initial event mask. */ 00626 memset (&tte, 0, sizeof (tte)); 00627 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK; 00628 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE; 00629 #ifdef TTEVT_BPT_SSTEP 00630 tte.tte_events |= TTEVT_BPT_SSTEP; 00631 #endif 00632 tte.tte_opts |= TTEO_PROC_INHERIT; 00633 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, 00634 (uintptr_t)&tte, sizeof tte, 0) == -1) 00635 perror_with_name (("ttrace")); 00636 00637 /* Tell our child that we have set the initial event mask. */ 00638 if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c) 00639 perror_with_name (("write")); 00640 00641 do_cleanups (old_chain); 00642 00643 push_target (ops); 00644 00645 /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, and will 00646 be 1 or 2 depending on whether we're starting without or with a 00647 shell. */ 00648 startup_inferior (START_INFERIOR_TRAPS_EXPECTED); 00649 00650 /* On some targets, there must be some explicit actions taken after 00651 the inferior has been started up. */ 00652 target_post_startup_inferior (pid_to_ptid (pid)); 00653 } 00654 00655 static void 00656 inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file, 00657 char *allargs, char **env, int from_tty) 00658 { 00659 int pid; 00660 00661 gdb_assert (inf_ttrace_num_lwps == 0); 00662 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); 00663 gdb_assert (inf_ttrace_page_dict.count == 0); 00664 gdb_assert (inf_ttrace_reenable_page_protections == 0); 00665 gdb_assert (inf_ttrace_vfork_ppid == -1); 00666 00667 pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL, 00668 inf_ttrace_prepare, NULL, NULL); 00669 00670 inf_ttrace_him (ops, pid); 00671 } 00672 00673 static void 00674 inf_ttrace_mourn_inferior (struct target_ops *ops) 00675 { 00676 const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); 00677 int bucket; 00678 00679 inf_ttrace_num_lwps = 0; 00680 inf_ttrace_num_lwps_in_syscall = 0; 00681 00682 for (bucket = 0; bucket < num_buckets; bucket++) 00683 { 00684 struct inf_ttrace_page *page; 00685 struct inf_ttrace_page *next; 00686 00687 page = inf_ttrace_page_dict.buckets[bucket].next; 00688 while (page) 00689 { 00690 next = page->next; 00691 xfree (page); 00692 page = next; 00693 } 00694 } 00695 inf_ttrace_page_dict.count = 0; 00696 00697 unpush_target (ops); 00698 generic_mourn_inferior (); 00699 } 00700 00701 /* Assuming we just attached the debugger to a new inferior, create 00702 a new thread_info structure for each thread, and add it to our 00703 list of threads. */ 00704 00705 static void 00706 inf_ttrace_create_threads_after_attach (int pid) 00707 { 00708 int status; 00709 ptid_t ptid; 00710 ttstate_t tts; 00711 struct thread_info *ti; 00712 00713 status = ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0, 00714 (uintptr_t) &tts, sizeof (ttstate_t), 0); 00715 if (status < 0) 00716 perror_with_name (_("TT_PROC_GET_FIRST_LWP_STATE ttrace call failed")); 00717 gdb_assert (tts.tts_pid == pid); 00718 00719 /* Add the stopped thread. */ 00720 ptid = ptid_build (pid, tts.tts_lwpid, 0); 00721 ti = add_thread (ptid); 00722 ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info)); 00723 inf_ttrace_num_lwps++; 00724 00725 /* We use the "first stopped thread" as the currently active thread. */ 00726 inferior_ptid = ptid; 00727 00728 /* Iterative over all the remaining threads. */ 00729 00730 for (;;) 00731 { 00732 ptid_t ptid; 00733 00734 status = ttrace (TT_PROC_GET_NEXT_LWP_STATE, pid, 0, 00735 (uintptr_t) &tts, sizeof (ttstate_t), 0); 00736 if (status < 0) 00737 perror_with_name (_("TT_PROC_GET_NEXT_LWP_STATE ttrace call failed")); 00738 if (status == 0) 00739 break; /* End of list. */ 00740 00741 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); 00742 ti = add_thread (ptid); 00743 ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info)); 00744 inf_ttrace_num_lwps++; 00745 } 00746 } 00747 00748 static void 00749 inf_ttrace_attach (struct target_ops *ops, char *args, int from_tty) 00750 { 00751 char *exec_file; 00752 pid_t pid; 00753 ttevent_t tte; 00754 struct inferior *inf; 00755 00756 pid = parse_pid_to_attach (args); 00757 00758 if (pid == getpid ()) /* Trying to masturbate? */ 00759 error (_("I refuse to debug myself!")); 00760 00761 if (from_tty) 00762 { 00763 exec_file = get_exec_file (0); 00764 00765 if (exec_file) 00766 printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, 00767 target_pid_to_str (pid_to_ptid (pid))); 00768 else 00769 printf_unfiltered (_("Attaching to %s\n"), 00770 target_pid_to_str (pid_to_ptid (pid))); 00771 00772 gdb_flush (gdb_stdout); 00773 } 00774 00775 gdb_assert (inf_ttrace_num_lwps == 0); 00776 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); 00777 gdb_assert (inf_ttrace_vfork_ppid == -1); 00778 00779 if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1) 00780 perror_with_name (("ttrace")); 00781 00782 inf = current_inferior (); 00783 inferior_appeared (inf, pid); 00784 inf->attach_flag = 1; 00785 00786 /* Set the initial event mask. */ 00787 memset (&tte, 0, sizeof (tte)); 00788 tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK; 00789 tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE; 00790 #ifdef TTEVT_BPT_SSTEP 00791 tte.tte_events |= TTEVT_BPT_SSTEP; 00792 #endif 00793 tte.tte_opts |= TTEO_PROC_INHERIT; 00794 if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, 00795 (uintptr_t)&tte, sizeof tte, 0) == -1) 00796 perror_with_name (("ttrace")); 00797 00798 push_target (ops); 00799 00800 inf_ttrace_create_threads_after_attach (pid); 00801 } 00802 00803 static void 00804 inf_ttrace_detach (struct target_ops *ops, char *args, int from_tty) 00805 { 00806 pid_t pid = ptid_get_pid (inferior_ptid); 00807 int sig = 0; 00808 00809 if (from_tty) 00810 { 00811 char *exec_file = get_exec_file (0); 00812 if (exec_file == 0) 00813 exec_file = ""; 00814 printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file, 00815 target_pid_to_str (pid_to_ptid (pid))); 00816 gdb_flush (gdb_stdout); 00817 } 00818 if (args) 00819 sig = atoi (args); 00820 00821 /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we 00822 can pass a signal number here. Does this really work? */ 00823 if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1) 00824 perror_with_name (("ttrace")); 00825 00826 if (inf_ttrace_vfork_ppid != -1) 00827 { 00828 if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1) 00829 perror_with_name (("ttrace")); 00830 inf_ttrace_vfork_ppid = -1; 00831 } 00832 00833 inf_ttrace_num_lwps = 0; 00834 inf_ttrace_num_lwps_in_syscall = 0; 00835 00836 inferior_ptid = null_ptid; 00837 detach_inferior (pid); 00838 00839 unpush_target (ops); 00840 } 00841 00842 static void 00843 inf_ttrace_kill (struct target_ops *ops) 00844 { 00845 pid_t pid = ptid_get_pid (inferior_ptid); 00846 00847 if (pid == 0) 00848 return; 00849 00850 if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1) 00851 perror_with_name (("ttrace")); 00852 /* ??? Is it necessary to call ttrace_wait() here? */ 00853 00854 if (inf_ttrace_vfork_ppid != -1) 00855 { 00856 if (ttrace (TT_PROC_DETACH, inf_ttrace_vfork_ppid, 0, 0, 0, 0) == -1) 00857 perror_with_name (("ttrace")); 00858 inf_ttrace_vfork_ppid = -1; 00859 } 00860 00861 target_mourn_inferior (); 00862 } 00863 00864 /* Check is a dying thread is dead by now, and delete it from GDBs 00865 thread list if so. */ 00866 static int 00867 inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg) 00868 { 00869 lwpid_t lwpid; 00870 struct inf_ttrace_private_thread_info *p; 00871 00872 if (is_exited (info->ptid)) 00873 return 0; 00874 00875 lwpid = ptid_get_lwp (info->ptid); 00876 p = (struct inf_ttrace_private_thread_info *) info->private; 00877 00878 /* Check if an lwp that was dying is still there or not. */ 00879 if (p->dying && (kill (lwpid, 0) == -1)) 00880 /* It's gone now. */ 00881 delete_thread (info->ptid); 00882 00883 return 0; 00884 } 00885 00886 /* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal 00887 SIG. */ 00888 00889 static void 00890 inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig) 00891 { 00892 pid_t pid = ptid_get_pid (info->ptid); 00893 lwpid_t lwpid = ptid_get_lwp (info->ptid); 00894 00895 if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1) 00896 { 00897 struct inf_ttrace_private_thread_info *p 00898 = (struct inf_ttrace_private_thread_info *) info->private; 00899 if (p->dying && errno == EPROTO) 00900 /* This is expected, it means the dying lwp is really gone 00901 by now. If ttrace had an event to inform the debugger 00902 the lwp is really gone, this wouldn't be needed. */ 00903 delete_thread (info->ptid); 00904 else 00905 /* This was really unexpected. */ 00906 perror_with_name (("ttrace")); 00907 } 00908 } 00909 00910 /* Callback for iterate_over_threads. */ 00911 00912 static int 00913 inf_ttrace_resume_callback (struct thread_info *info, void *arg) 00914 { 00915 if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid)) 00916 inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0); 00917 00918 return 0; 00919 } 00920 00921 static void 00922 inf_ttrace_resume (struct target_ops *ops, 00923 ptid_t ptid, int step, enum gdb_signal signal) 00924 { 00925 int resume_all; 00926 ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE; 00927 int sig = gdb_signal_to_host (signal); 00928 struct thread_info *info; 00929 00930 /* A specific PTID means `step only this process id'. */ 00931 resume_all = (ptid_equal (ptid, minus_one_ptid)); 00932 00933 /* If resuming all threads, it's the current thread that should be 00934 handled specially. */ 00935 if (resume_all) 00936 ptid = inferior_ptid; 00937 00938 info = find_thread_ptid (ptid); 00939 inf_ttrace_resume_lwp (info, request, sig); 00940 00941 if (resume_all) 00942 /* Let all the other threads run too. */ 00943 iterate_over_threads (inf_ttrace_resume_callback, NULL); 00944 } 00945 00946 static ptid_t 00947 inf_ttrace_wait (struct target_ops *ops, 00948 ptid_t ptid, struct target_waitstatus *ourstatus, int options) 00949 { 00950 pid_t pid = ptid_get_pid (ptid); 00951 lwpid_t lwpid = ptid_get_lwp (ptid); 00952 ttstate_t tts; 00953 struct thread_info *ti; 00954 ptid_t related_ptid; 00955 00956 /* Until proven otherwise. */ 00957 ourstatus->kind = TARGET_WAITKIND_SPURIOUS; 00958 00959 if (pid == -1) 00960 pid = lwpid = 0; 00961 00962 gdb_assert (pid != 0 || lwpid == 0); 00963 00964 do 00965 { 00966 set_sigint_trap (); 00967 00968 if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1) 00969 perror_with_name (("ttrace_wait")); 00970 00971 if (tts.tts_event == TTEVT_VFORK && tts.tts_u.tts_fork.tts_isparent) 00972 { 00973 if (inf_ttrace_vfork_ppid != -1) 00974 { 00975 gdb_assert (inf_ttrace_vfork_ppid == tts.tts_pid); 00976 00977 if (ttrace (TT_PROC_DETACH, tts.tts_pid, 0, 0, 0, 0) == -1) 00978 perror_with_name (("ttrace")); 00979 inf_ttrace_vfork_ppid = -1; 00980 } 00981 00982 tts.tts_event = TTEVT_NONE; 00983 } 00984 00985 clear_sigint_trap (); 00986 } 00987 while (tts.tts_event == TTEVT_NONE); 00988 00989 /* Now that we've waited, we can re-enable the page protections. */ 00990 if (inf_ttrace_reenable_page_protections) 00991 { 00992 gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); 00993 inf_ttrace_enable_page_protections (tts.tts_pid); 00994 inf_ttrace_reenable_page_protections = 0; 00995 } 00996 00997 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); 00998 00999 if (inf_ttrace_num_lwps == 0) 01000 { 01001 struct thread_info *ti; 01002 01003 inf_ttrace_num_lwps = 1; 01004 01005 /* This is the earliest we hear about the lwp member of 01006 INFERIOR_PTID, after an attach or fork_inferior. */ 01007 gdb_assert (ptid_get_lwp (inferior_ptid) == 0); 01008 01009 /* We haven't set the private member on the main thread yet. Do 01010 it now. */ 01011 ti = find_thread_ptid (inferior_ptid); 01012 gdb_assert (ti != NULL && ti->private == NULL); 01013 ti->private = 01014 xmalloc (sizeof (struct inf_ttrace_private_thread_info)); 01015 memset (ti->private, 0, 01016 sizeof (struct inf_ttrace_private_thread_info)); 01017 01018 /* Notify the core that this ptid changed. This changes 01019 inferior_ptid as well. */ 01020 thread_change_ptid (inferior_ptid, ptid); 01021 } 01022 01023 switch (tts.tts_event) 01024 { 01025 #ifdef TTEVT_BPT_SSTEP 01026 case TTEVT_BPT_SSTEP: 01027 /* Make it look like a breakpoint. */ 01028 ourstatus->kind = TARGET_WAITKIND_STOPPED; 01029 ourstatus->value.sig = GDB_SIGNAL_TRAP; 01030 break; 01031 #endif 01032 01033 case TTEVT_EXEC: 01034 ourstatus->kind = TARGET_WAITKIND_EXECD; 01035 ourstatus->value.execd_pathname = 01036 xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1); 01037 if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0, 01038 (uintptr_t)ourstatus->value.execd_pathname, 01039 tts.tts_u.tts_exec.tts_pathlen, 0) == -1) 01040 perror_with_name (("ttrace")); 01041 ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0; 01042 01043 /* At this point, all inserted breakpoints are gone. Doing this 01044 as soon as we detect an exec prevents the badness of deleting 01045 a breakpoint writing the current "shadow contents" to lift 01046 the bp. That shadow is NOT valid after an exec. */ 01047 mark_breakpoints_out (); 01048 break; 01049 01050 case TTEVT_EXIT: 01051 store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode); 01052 inf_ttrace_num_lwps = 0; 01053 break; 01054 01055 case TTEVT_FORK: 01056 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, 01057 tts.tts_u.tts_fork.tts_flwpid, 0); 01058 01059 ourstatus->kind = TARGET_WAITKIND_FORKED; 01060 ourstatus->value.related_pid = related_ptid; 01061 01062 /* Make sure the other end of the fork is stopped too. */ 01063 if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid, 01064 tts.tts_u.tts_fork.tts_flwpid, 01065 TTRACE_WAITOK, &tts, sizeof tts) == -1) 01066 perror_with_name (("ttrace_wait")); 01067 01068 gdb_assert (tts.tts_event == TTEVT_FORK); 01069 if (tts.tts_u.tts_fork.tts_isparent) 01070 { 01071 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, 01072 tts.tts_u.tts_fork.tts_flwpid, 0); 01073 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); 01074 ourstatus->value.related_pid = related_ptid; 01075 } 01076 break; 01077 01078 case TTEVT_VFORK: 01079 gdb_assert (!tts.tts_u.tts_fork.tts_isparent); 01080 01081 related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, 01082 tts.tts_u.tts_fork.tts_flwpid, 0); 01083 01084 ourstatus->kind = TARGET_WAITKIND_VFORKED; 01085 ourstatus->value.related_pid = related_ptid; 01086 01087 /* HACK: To avoid touching the parent during the vfork, switch 01088 away from it. */ 01089 inferior_ptid = ptid; 01090 break; 01091 01092 case TTEVT_LWP_CREATE: 01093 lwpid = tts.tts_u.tts_thread.tts_target_lwpid; 01094 ptid = ptid_build (tts.tts_pid, lwpid, 0); 01095 ti = add_thread (ptid); 01096 ti->private = 01097 xmalloc (sizeof (struct inf_ttrace_private_thread_info)); 01098 memset (ti->private, 0, 01099 sizeof (struct inf_ttrace_private_thread_info)); 01100 inf_ttrace_num_lwps++; 01101 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); 01102 /* Let the lwp_create-caller thread continue. */ 01103 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), 01104 ptid_get_lwp (ptid), TT_NOPC, 0, 0); 01105 /* Return without stopping the whole process. */ 01106 ourstatus->kind = TARGET_WAITKIND_IGNORE; 01107 return ptid; 01108 01109 case TTEVT_LWP_EXIT: 01110 if (print_thread_events) 01111 printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid)); 01112 ti = find_thread_ptid (ptid); 01113 gdb_assert (ti != NULL); 01114 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1; 01115 inf_ttrace_num_lwps--; 01116 /* Let the thread really exit. */ 01117 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), 01118 ptid_get_lwp (ptid), TT_NOPC, 0, 0); 01119 /* Return without stopping the whole process. */ 01120 ourstatus->kind = TARGET_WAITKIND_IGNORE; 01121 return ptid; 01122 01123 case TTEVT_LWP_TERMINATE: 01124 lwpid = tts.tts_u.tts_thread.tts_target_lwpid; 01125 ptid = ptid_build (tts.tts_pid, lwpid, 0); 01126 if (print_thread_events) 01127 printf_unfiltered(_("[%s has been terminated]\n"), 01128 target_pid_to_str (ptid)); 01129 ti = find_thread_ptid (ptid); 01130 gdb_assert (ti != NULL); 01131 ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1; 01132 inf_ttrace_num_lwps--; 01133 01134 /* Resume the lwp_terminate-caller thread. */ 01135 ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); 01136 ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), 01137 ptid_get_lwp (ptid), TT_NOPC, 0, 0); 01138 /* Return without stopping the whole process. */ 01139 ourstatus->kind = TARGET_WAITKIND_IGNORE; 01140 return ptid; 01141 01142 case TTEVT_SIGNAL: 01143 ourstatus->kind = TARGET_WAITKIND_STOPPED; 01144 ourstatus->value.sig = 01145 gdb_signal_from_host (tts.tts_u.tts_signal.tts_signo); 01146 break; 01147 01148 case TTEVT_SYSCALL_ENTRY: 01149 gdb_assert (inf_ttrace_reenable_page_protections == 0); 01150 inf_ttrace_num_lwps_in_syscall++; 01151 if (inf_ttrace_num_lwps_in_syscall == 1) 01152 { 01153 /* A thread has just entered a system call. Disable any 01154 page protections as the kernel can't deal with them. */ 01155 inf_ttrace_disable_page_protections (tts.tts_pid); 01156 } 01157 ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY; 01158 ourstatus->value.syscall_number = tts.tts_scno; 01159 break; 01160 01161 case TTEVT_SYSCALL_RETURN: 01162 if (inf_ttrace_num_lwps_in_syscall > 0) 01163 { 01164 /* If the last thread has just left the system call, this 01165 would be a logical place to re-enable the page 01166 protections, but that doesn't work. We can't re-enable 01167 them until we've done another wait. */ 01168 inf_ttrace_reenable_page_protections = 01169 (inf_ttrace_num_lwps_in_syscall == 1); 01170 inf_ttrace_num_lwps_in_syscall--; 01171 } 01172 ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN; 01173 ourstatus->value.syscall_number = tts.tts_scno; 01174 break; 01175 01176 default: 01177 gdb_assert (!"Unexpected ttrace event"); 01178 break; 01179 } 01180 01181 /* Make sure all threads within the process are stopped. */ 01182 if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1) 01183 perror_with_name (("ttrace")); 01184 01185 /* Now that the whole process is stopped, check if any dying thread 01186 is really dead by now. If a dying thread is still alive, it will 01187 be stopped too, and will still show up in `info threads', tagged 01188 with "(Exiting)". We could make `info threads' prune dead 01189 threads instead via inf_ttrace_thread_alive, but doing this here 01190 has the advantage that a frontend is notificed sooner of thread 01191 exits. Note that a dying lwp is still alive, it still has to be 01192 resumed, like any other lwp. */ 01193 iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL); 01194 01195 return ptid; 01196 } 01197 01198 /* Transfer LEN bytes from ADDR in the inferior's memory into READBUF, 01199 and transfer LEN bytes from WRITEBUF into the inferior's memory at 01200 ADDR. Either READBUF or WRITEBUF may be null, in which case the 01201 corresponding transfer doesn't happen. Return the number of bytes 01202 actually transferred (which may be zero if an error occurs). */ 01203 01204 static LONGEST 01205 inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len, 01206 void *readbuf, const void *writebuf) 01207 { 01208 pid_t pid = ptid_get_pid (inferior_ptid); 01209 01210 /* HP-UX treats text space and data space differently. GDB however, 01211 doesn't really know the difference. Therefore we try both. Try 01212 text space before data space though because when we're writing 01213 into text space the instruction cache might need to be flushed. */ 01214 01215 if (readbuf 01216 && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1 01217 && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1) 01218 return 0; 01219 01220 if (writebuf 01221 && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1 01222 && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1) 01223 return 0; 01224 01225 return len; 01226 } 01227 01228 static LONGEST 01229 inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object, 01230 const char *annex, gdb_byte *readbuf, 01231 const gdb_byte *writebuf, 01232 ULONGEST offset, LONGEST len) 01233 { 01234 switch (object) 01235 { 01236 case TARGET_OBJECT_MEMORY: 01237 return inf_ttrace_xfer_memory (offset, len, readbuf, writebuf); 01238 01239 case TARGET_OBJECT_UNWIND_TABLE: 01240 return -1; 01241 01242 case TARGET_OBJECT_AUXV: 01243 return -1; 01244 01245 case TARGET_OBJECT_WCOOKIE: 01246 return -1; 01247 01248 default: 01249 return -1; 01250 } 01251 } 01252 01253 /* Print status information about what we're accessing. */ 01254 01255 static void 01256 inf_ttrace_files_info (struct target_ops *ignore) 01257 { 01258 struct inferior *inf = current_inferior (); 01259 printf_filtered (_("\tUsing the running image of %s %s.\n"), 01260 inf->attach_flag ? "attached" : "child", 01261 target_pid_to_str (inferior_ptid)); 01262 } 01263 01264 static int 01265 inf_ttrace_thread_alive (struct target_ops *ops, ptid_t ptid) 01266 { 01267 return 1; 01268 } 01269 01270 /* Return a string describing the state of the thread specified by 01271 INFO. */ 01272 01273 static char * 01274 inf_ttrace_extra_thread_info (struct thread_info *info) 01275 { 01276 struct inf_ttrace_private_thread_info* private = 01277 (struct inf_ttrace_private_thread_info *) info->private; 01278 01279 if (private != NULL && private->dying) 01280 return "Exiting"; 01281 01282 return NULL; 01283 } 01284 01285 static char * 01286 inf_ttrace_pid_to_str (struct target_ops *ops, ptid_t ptid) 01287 { 01288 pid_t pid = ptid_get_pid (ptid); 01289 lwpid_t lwpid = ptid_get_lwp (ptid); 01290 static char buf[128]; 01291 01292 if (lwpid == 0) 01293 xsnprintf (buf, sizeof buf, "process %ld", 01294 (long) pid); 01295 else 01296 xsnprintf (buf, sizeof buf, "process %ld, lwp %ld", 01297 (long) pid, (long) lwpid); 01298 return buf; 01299 } 01300 01301 01302 /* Implement the get_ada_task_ptid target_ops method. */ 01303 01304 static ptid_t 01305 inf_ttrace_get_ada_task_ptid (long lwp, long thread) 01306 { 01307 return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0); 01308 } 01309 01310 01311 struct target_ops * 01312 inf_ttrace_target (void) 01313 { 01314 struct target_ops *t = inf_child_target (); 01315 01316 t->to_attach = inf_ttrace_attach; 01317 t->to_detach = inf_ttrace_detach; 01318 t->to_resume = inf_ttrace_resume; 01319 t->to_wait = inf_ttrace_wait; 01320 t->to_files_info = inf_ttrace_files_info; 01321 t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint; 01322 t->to_insert_watchpoint = inf_ttrace_insert_watchpoint; 01323 t->to_remove_watchpoint = inf_ttrace_remove_watchpoint; 01324 t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint; 01325 t->to_region_ok_for_hw_watchpoint = 01326 inf_ttrace_region_ok_for_hw_watchpoint; 01327 t->to_kill = inf_ttrace_kill; 01328 t->to_create_inferior = inf_ttrace_create_inferior; 01329 t->to_follow_fork = inf_ttrace_follow_fork; 01330 t->to_mourn_inferior = inf_ttrace_mourn_inferior; 01331 t->to_thread_alive = inf_ttrace_thread_alive; 01332 t->to_extra_thread_info = inf_ttrace_extra_thread_info; 01333 t->to_pid_to_str = inf_ttrace_pid_to_str; 01334 t->to_xfer_partial = inf_ttrace_xfer_partial; 01335 t->to_get_ada_task_ptid = inf_ttrace_get_ada_task_ptid; 01336 01337 return t; 01338 } 01339 #endif 01340 01341 01342 /* Prevent warning from -Wmissing-prototypes. */ 01343 void _initialize_inf_ttrace (void); 01344 01345 void 01346 _initialize_inf_ttrace (void) 01347 { 01348 #ifdef HAVE_TTRACE 01349 inf_ttrace_page_dict.pagesize = getpagesize(); 01350 #endif 01351 }