X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fprocfs.c;h=e5df8866d223762546c79ff3e3c68246d1e3fa0d;hb=4c490650431f854ef3559d0d5a01e0ebfda8226c;hp=36d0e476a6b2b3f20441c1c981052dbe59f9cba8;hpb=37da21bceb17dfd7b123d4bf9d6d5d0f4da25589;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/procfs.c b/gdb/procfs.c index 36d0e476a6..e5df8866d2 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -1,6 +1,6 @@ /* Machine independent support for SVR4 /proc (process file system) for GDB. - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009 + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Written by Michael Snyder at Cygnus Solutions. @@ -50,6 +50,7 @@ #include "gdb_assert.h" #include "inflow.h" #include "auxv.h" +#include "procfs.h" /* * PROCFS.C @@ -128,7 +129,7 @@ static void procfs_mourn_inferior (struct target_ops *ops); static void procfs_create_inferior (struct target_ops *, char *, char *, char **, int); static ptid_t procfs_wait (struct target_ops *, - ptid_t, struct target_waitstatus *); + ptid_t, struct target_waitstatus *, int); static int procfs_xfer_memory (CORE_ADDR, gdb_byte *, int, int, struct mem_attrib *attrib, struct target_ops *); @@ -161,6 +162,7 @@ static int procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) { + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); gdb_byte *ptr = *readptr; if (endptr == ptr) @@ -169,11 +171,11 @@ procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr, if (endptr - ptr < 8 * 2) return -1; - *typep = extract_unsigned_integer (ptr, 4); + *typep = extract_unsigned_integer (ptr, 4, byte_order); ptr += 8; /* The size of data is always 64-bit. If the application is 32-bit, it will be zero extended, as expected. */ - *valp = extract_unsigned_integer (ptr, 8); + *valp = extract_unsigned_integer (ptr, 8, byte_order); ptr += 8; *readptr = ptr; @@ -181,7 +183,7 @@ procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr, } #endif -static struct target_ops * +struct target_ops * procfs_target (void) { struct target_ops *t = inf_child_target (); @@ -212,7 +214,6 @@ procfs_target (void) t->to_has_thread_control = tc_schedlock; t->to_find_memory_regions = proc_find_memory_regions; t->to_make_corefile_notes = procfs_make_note_section; - t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint; #if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64) t->to_auxv_parse = procfs_auxv_parse; @@ -2504,7 +2505,7 @@ proc_set_current_signal (procinfo *pi, int signo) /* Use char array to avoid alignment issues. */ char sinfo[sizeof (gdb_siginfo_t)]; } arg; - gdb_siginfo_t *mysinfo; + gdb_siginfo_t mysinfo; ptid_t wait_ptid; struct target_waitstatus wait_status; @@ -2529,7 +2530,6 @@ proc_set_current_signal (procinfo *pi, int signo) #endif /* The pointer is just a type alias. */ - mysinfo = (gdb_siginfo_t *) &arg.sinfo; get_last_target_status (&wait_ptid, &wait_status); if (ptid_equal (wait_ptid, inferior_ptid) && wait_status.kind == TARGET_WAITKIND_STOPPED @@ -2544,16 +2544,17 @@ proc_set_current_signal (procinfo *pi, int signo) /* Use the siginfo associated with the signal being redelivered. */ #ifdef NEW_PROC_API - memcpy (mysinfo, &pi->prstatus.pr_lwp.pr_info, sizeof (gdb_siginfo_t)); + memcpy (arg.sinfo, &pi->prstatus.pr_lwp.pr_info, sizeof (gdb_siginfo_t)); #else - memcpy (mysinfo, &pi->prstatus.pr_info, sizeof (gdb_siginfo_t)); + memcpy (arg.sinfo, &pi->prstatus.pr_info, sizeof (gdb_siginfo_t)); #endif else { - mysinfo->si_signo = signo; - mysinfo->si_code = 0; - mysinfo->si_pid = getpid (); /* ?why? */ - mysinfo->si_uid = getuid (); /* ?why? */ + mysinfo.si_signo = signo; + mysinfo.si_code = 0; + mysinfo.si_pid = getpid (); /* ?why? */ + mysinfo.si_uid = getuid (); /* ?why? */ + memcpy (arg.sinfo, &mysinfo, sizeof (gdb_siginfo_t)); } #ifdef NEW_PROC_API @@ -2596,16 +2597,16 @@ proc_clear_current_signal (procinfo *pi) /* Use char array to avoid alignment issues. */ char sinfo[sizeof (gdb_siginfo_t)]; } arg; - gdb_siginfo_t *mysinfo; + gdb_siginfo_t mysinfo; arg.cmd = PCSSIG; /* The pointer is just a type alias. */ - mysinfo = (gdb_siginfo_t *) &arg.sinfo; - mysinfo->si_signo = 0; - mysinfo->si_code = 0; - mysinfo->si_errno = 0; - mysinfo->si_pid = getpid (); /* ?why? */ - mysinfo->si_uid = getuid (); /* ?why? */ + mysinfo.si_signo = 0; + mysinfo.si_code = 0; + mysinfo.si_errno = 0; + mysinfo.si_pid = getpid (); /* ?why? */ + mysinfo.si_uid = getuid (); /* ?why? */ + memcpy (arg.sinfo, &mysinfo, sizeof (gdb_siginfo_t)); win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg)); } @@ -2902,7 +2903,10 @@ procfs_address_to_host_pointer (CORE_ADDR addr) int proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags) { -#if !defined (TARGET_HAS_HARDWARE_WATCHPOINTS) +#if !defined (PCWATCH) && !defined (PIOCSWATCH) + /* If neither or these is defined, we can't support watchpoints. + This just avoids possibly failing to compile the below on such + systems. */ return 0; #else /* Horrible hack! Detect Solaris 2.5, because this doesn't work on 2.5 */ @@ -2913,25 +2917,25 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags) procfs_ctl_t cmd; char watch[sizeof (prwatch_t)]; } arg; - prwatch_t *pwatch; + prwatch_t pwatch; - pwatch = (prwatch_t *) &arg.watch; /* NOTE: cagney/2003-02-01: Even more horrible hack. Need to convert a target address into something that can be stored in a native data structure. */ #ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */ - pwatch->pr_vaddr = (uintptr_t) procfs_address_to_host_pointer (addr); + pwatch.pr_vaddr = (uintptr_t) procfs_address_to_host_pointer (addr); #else - pwatch->pr_vaddr = (caddr_t) procfs_address_to_host_pointer (addr); + pwatch.pr_vaddr = (caddr_t) procfs_address_to_host_pointer (addr); #endif - pwatch->pr_size = len; - pwatch->pr_wflags = wflags; + pwatch.pr_size = len; + pwatch.pr_wflags = wflags; #if defined(NEW_PROC_API) && defined (PCWATCH) arg.cmd = PCWATCH; + memcpy (arg.watch, &pwatch, sizeof (prwatch_t)); return (write (pi->ctl_fd, &arg, sizeof (arg)) == sizeof (arg)); #else #if defined (PIOCSWATCH) - return (ioctl (pi->ctl_fd, PIOCSWATCH, pwatch) >= 0); + return (ioctl (pi->ctl_fd, PIOCSWATCH, &pwatch) >= 0); #else return 0; /* Fail */ #endif @@ -3701,7 +3705,8 @@ do_attach (ptid_t ptid) if ((fail = procfs_debug_inferior (pi)) != 0) dead_procinfo (pi, "do_attach: failed in procfs_debug_inferior", NOKILL); - inf = add_inferior (pi->pid); + inf = current_inferior (); + inferior_appeared (inf, pi->pid); /* Let GDB know that the inferior was attached. */ inf->attach_flag = 1; @@ -3947,7 +3952,7 @@ syscall_is_lwp_create (procinfo *pi, int scall) static ptid_t procfs_wait (struct target_ops *ops, - ptid_t ptid, struct target_waitstatus *status) + ptid_t ptid, struct target_waitstatus *status, int options) { /* First cut: loosely based on original version 2.1 */ procinfo *pi; @@ -4278,7 +4283,8 @@ wait_again: then remove it. See comments in procfs_init_inferior() for more details. */ if (dbx_link_bpt_addr != 0 - && dbx_link_bpt_addr == read_pc ()) + && dbx_link_bpt_addr + == regcache_read_pc (get_current_regcache ())) remove_dbx_link_breakpoint (); wstat = (SIGTRAP << 8) | 0177; @@ -4469,7 +4475,7 @@ invalidate_cache (procinfo *parent, procinfo *pi, void *ptr) if (!proc_set_gregs (pi)) /* flush gregs cache */ proc_warn (pi, "target_resume, set_gregs", __LINE__); - if (gdbarch_fp0_regnum (current_gdbarch) >= 0) + if (gdbarch_fp0_regnum (target_gdbarch) >= 0) if (pi->fpregs_dirty) if (parent == NULL || proc_get_current_thread (parent) != pi->tid) @@ -4689,7 +4695,7 @@ procfs_files_info (struct target_ops *ignore) static void procfs_stop (ptid_t ptid) { - kill (-inferior_process_group, SIGINT); + kill (-inferior_process_group (), SIGINT); } /* @@ -4799,7 +4805,7 @@ procfs_mourn_inferior (struct target_ops *ops) if (dbx_link_bpt != NULL) { - deprecated_remove_raw_breakpoint (dbx_link_bpt); + deprecated_remove_raw_breakpoint (target_gdbarch, dbx_link_bpt); dbx_link_bpt_addr = 0; dbx_link_bpt = NULL; } @@ -5288,14 +5294,11 @@ procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag, Note: procfs_can_use_hw_breakpoint() is not yet used by all procfs.c targets due to the fact that some of them still define - TARGET_CAN_USE_HARDWARE_WATCHPOINT. */ + target_can_use_hardware_watchpoint. */ static int procfs_can_use_hw_breakpoint (int type, int cnt, int othertype) { -#ifndef TARGET_HAS_HARDWARE_WATCHPOINTS - return 0; -#else /* Due to the way that proc_set_watchpoint() is implemented, host and target pointers must be of the same size. If they are not, we can't use hardware watchpoints. This limitation is due to the @@ -5311,7 +5314,6 @@ procfs_can_use_hw_breakpoint (int type, int cnt, int othertype) /* Other tests here??? */ return 1; -#endif } /* @@ -5321,13 +5323,12 @@ procfs_can_use_hw_breakpoint (int type, int cnt, int othertype) * else returns zero. */ -int -procfs_stopped_by_watchpoint (ptid_t ptid) +static int +procfs_stopped_by_watchpoint (void) { procinfo *pi; - pi = find_procinfo_or_die (PIDGET (ptid) == -1 ? - PIDGET (inferior_ptid) : PIDGET (ptid), 0); + pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); if (!pi) /* If no process, then not stopped by watchpoint! */ return 0; @@ -5349,6 +5350,54 @@ procfs_stopped_by_watchpoint (ptid_t ptid) return 0; } +static int +procfs_insert_watchpoint (CORE_ADDR addr, int len, int type) +{ + if (!target_have_steppable_watchpoint + && !gdbarch_have_nonsteppable_watchpoint (target_gdbarch)) + { + /* When a hardware watchpoint fires off the PC will be left at + the instruction following the one which caused the + watchpoint. It will *NOT* be necessary for GDB to step over + the watchpoint. */ + return procfs_set_watchpoint (inferior_ptid, addr, len, type, 1); + } + else + { + /* When a hardware watchpoint fires off the PC will be left at + the instruction which caused the watchpoint. It will be + necessary for GDB to step over the watchpoint. */ + return procfs_set_watchpoint (inferior_ptid, addr, len, type, 0); + } +} + +static int +procfs_remove_watchpoint (CORE_ADDR addr, int len, int type) +{ + return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0); +} + +static int +procfs_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) +{ + /* The man page for proc(4) on Solaris 2.6 and up says that the + system can support "thousands" of hardware watchpoints, but gives + no method for finding out how many; It doesn't say anything about + the allowed size for the watched area either. So we just tell + GDB 'yes'. */ + return 1; +} + +void +procfs_use_watchpoints (struct target_ops *t) +{ + t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint; + t->to_insert_watchpoint = procfs_insert_watchpoint; + t->to_remove_watchpoint = procfs_remove_watchpoint; + t->to_region_ok_for_hw_watchpoint = procfs_region_ok_for_hw_watchpoint; + t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint; +} + /* * Memory Mappings Functions: */ @@ -5473,32 +5522,7 @@ int solib_mappings_callback (struct prmap *map, no file, so the ioctl may return failure, but that's not a problem. */ #endif - return (*func) (fd, (CORE_ADDR) (uintptr_t) map->pr_vaddr); -} - -/* - * Function: proc_iterate_over_mappings - * - * Uses the unified "iterate_over_mappings" function - * to implement the exported interface to solib-svr4.c. - * - * Given a pointer to a function, call that function once for every - * mapped address space in the process. The callback function - * receives an open file descriptor for the file corresponding to - * that mapped address space (if there is one), and the base address - * of the mapped space. Quit when the callback function returns a - * nonzero value, or at teh end of the mappings. - * - * Returns: the first non-zero return value of the callback function, - * or zero. - */ - -int -proc_iterate_over_mappings (int (*func) (int, CORE_ADDR)) -{ - procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); - - return iterate_over_mappings (pi, func, pi, solib_mappings_callback); + return (*func) (fd, (CORE_ADDR) map->pr_vaddr); } /* @@ -5524,7 +5548,7 @@ find_memory_regions_callback (struct prmap *map, void *), void *data) { - return (*func) ((CORE_ADDR) (uintptr_t) map->pr_vaddr, + return (*func) ((CORE_ADDR) map->pr_vaddr, map->pr_size, (map->pr_mflags & MA_READ) != 0, (map->pr_mflags & MA_WRITE) != 0, @@ -5570,7 +5594,7 @@ remove_dbx_link_breakpoint (void) if (dbx_link_bpt_addr == 0) return; - if (deprecated_remove_raw_breakpoint (dbx_link_bpt) != 0) + if (deprecated_remove_raw_breakpoint (target_gdbarch, dbx_link_bpt) != 0) warning (_("Unable to remove __dbx_link breakpoint.")); dbx_link_bpt_addr = 0; @@ -5642,7 +5666,8 @@ insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored) { /* Insert the breakpoint. */ dbx_link_bpt_addr = sym_addr; - dbx_link_bpt = deprecated_insert_raw_breakpoint (sym_addr); + dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch, NULL, + sym_addr); if (dbx_link_bpt == NULL) { warning (_("Failed to insert dbx_link breakpoint.")); @@ -5734,7 +5759,7 @@ info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused) pr_off = map->pr_off; #endif - if (gdbarch_addr_bit (current_gdbarch) == 32) + if (gdbarch_addr_bit (target_gdbarch) == 32) printf_filtered ("\t%#10lx %#10lx %#10lx %#10x %7s\n", (unsigned long) map->pr_vaddr, (unsigned long) map->pr_vaddr + map->pr_size - 1, @@ -5765,7 +5790,7 @@ info_proc_mappings (procinfo *pi, int summary) return; /* No output for summary mode. */ printf_filtered (_("Mapped address spaces:\n\n")); - if (gdbarch_ptr_bit (current_gdbarch) == 32) + if (gdbarch_ptr_bit (target_gdbarch) == 32) printf_filtered ("\t%10s %10s %10s %10s %7s\n", "Start Addr", " End Addr", @@ -5966,12 +5991,6 @@ proc_untrace_sysexit_cmd (char *args, int from_tty) void _initialize_procfs (void) { - struct target_ops * t; - - t = procfs_target (); - - add_target (t); - add_info ("proc", info_proc_cmd, _("\ Show /proc process information about any running process.\n\ Specify process id, or use the program being debugged by default.\n\ @@ -6041,11 +6060,21 @@ procfs_do_thread_registers (bfd *obfd, ptid_t ptid, gdb_gregset_t gregs; gdb_fpregset_t fpregs; unsigned long merged_pid; + struct cleanup *old_chain; merged_pid = TIDGET (ptid) << 16 | PIDGET (ptid); + /* This part is the old method for fetching registers. + It should be replaced by the newer one using regsets + once it is implemented in this platform: + gdbarch_regset_from_core_section() and regset->collect_regset(). */ + + old_chain = save_inferior_ptid (); + inferior_ptid = ptid; + target_fetch_registers (regcache, -1); + fill_gregset (regcache, &gregs, -1); -#if defined (UNIXWARE) +#if defined (NEW_PROC_API) note_data = (char *) elfcore_write_lwpstatus (obfd, note_data, note_size, @@ -6066,6 +6095,9 @@ procfs_do_thread_registers (bfd *obfd, ptid_t ptid, note_size, &fpregs, sizeof (fpregs)); + + do_cleanups (old_chain); + return note_data; } @@ -6083,13 +6115,11 @@ procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data) if (pi != NULL) { - ptid_t saved_ptid = inferior_ptid; - inferior_ptid = MERGEPID (pi->pid, thread->tid); - args->note_data = procfs_do_thread_registers (args->obfd, inferior_ptid, + ptid_t ptid = MERGEPID (pi->pid, thread->tid); + args->note_data = procfs_do_thread_registers (args->obfd, ptid, args->note_data, args->note_size, args->stop_signal); - inferior_ptid = saved_ptid; } return 0; } @@ -6108,6 +6138,7 @@ procfs_make_note_section (bfd *obfd, int *note_size) struct procfs_corefile_thread_data thread_args; gdb_byte *auxv; int auxv_len; + enum target_signal stop_signal; if (get_exec_file (0)) { @@ -6132,6 +6163,8 @@ procfs_make_note_section (bfd *obfd, int *note_size) fname, psargs); + stop_signal = find_stop_signal (); + #ifdef UNIXWARE fill_gregset (get_current_regcache (), &gregs, -1); note_data = elfcore_write_pstatus (obfd, note_data, note_size, @@ -6142,7 +6175,7 @@ procfs_make_note_section (bfd *obfd, int *note_size) thread_args.obfd = obfd; thread_args.note_data = note_data; thread_args.note_size = note_size; - thread_args.stop_signal = find_stop_signal (); + thread_args.stop_signal = stop_signal; proc_iterate_over_threads (pi, procfs_corefile_thread_callback, &thread_args); /* There should be always at least one thread. */