X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Famd64-linux-nat.c;h=b9d5833c7845d937b7e284266b3cc249b14f2321;hb=d62d0f5fc2156db337ac3cbbc3c05ca76565dbd3;hp=149ba2fc674576191499b31ea5b3ed86083b9ef7;hpb=9bb9e8ade770027f5cced2856574e2d317b15254;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index 149ba2fc67..b9d5833c78 100644 --- a/gdb/amd64-linux-nat.c +++ b/gdb/amd64-linux-nat.c @@ -1,6 +1,6 @@ /* Native-dependent code for GNU/Linux x86-64. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. @@ -270,6 +270,8 @@ amd64_linux_dr_get (ptid_t ptid, int regnum) return value; } +/* Set debug register REGNUM to VALUE in only the one LWP of PTID. */ + static void amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value) { @@ -286,6 +288,8 @@ amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value) perror_with_name (_("Couldn't write debug register")); } +/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST. */ + static void amd64_linux_dr_set_control (unsigned long control) { @@ -297,6 +301,8 @@ amd64_linux_dr_set_control (unsigned long control) amd64_linux_dr_set (ptid, DR_CONTROL, control); } +/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST. */ + static void amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr) { @@ -310,18 +316,41 @@ amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr) amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); } +/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST. */ + static void amd64_linux_dr_reset_addr (int regnum) { amd64_linux_dr_set_addr (regnum, 0); } +/* Get DR_STATUS from only the one LWP of INFERIOR_PTID. */ + static unsigned long amd64_linux_dr_get_status (void) { return amd64_linux_dr_get (inferior_ptid, DR_STATUS); } +/* Unset MASK bits in DR_STATUS in all LWPs of LWP_LIST. */ + +static void +amd64_linux_dr_unset_status (unsigned long mask) +{ + struct lwp_info *lp; + ptid_t ptid; + + ALL_LWPS (lp, ptid) + { + unsigned long value; + + value = amd64_linux_dr_get (ptid, DR_STATUS); + value &= ~mask; + amd64_linux_dr_set (ptid, DR_STATUS, value); + } +} + + static void amd64_linux_new_thread (ptid_t ptid) { @@ -341,7 +370,7 @@ ps_err_e ps_get_thread_area (const struct ps_prochandle *ph, lwpid_t lwpid, int idx, void **base) { - if (gdbarch_ptr_bit (current_gdbarch) == 32) + if (gdbarch_ptr_bit (target_gdbarch) == 32) { /* The full structure is found in . The second integer is the LDT's base_address and that is used to locate @@ -645,6 +674,39 @@ amd64_linux_siginfo_fixup (struct siginfo *native, gdb_byte *inf, int direction) return 0; } +/* Get Linux/x86 target description from running target. + + Value of CS segment register: + 1. 64bit process: 0x33. + 2. 32bit process: 0x23. + */ + +#define AMD64_LINUX_USER64_CS 0x33 + +static const struct target_desc * +amd64_linux_read_description (struct target_ops *ops) +{ + unsigned long cs; + int tid; + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Get CS register. */ + errno = 0; + cs = ptrace (PTRACE_PEEKUSER, tid, + offsetof (struct user_regs_struct, cs), 0); + if (errno != 0) + perror_with_name (_("Couldn't get CS register")); + + if (cs == AMD64_LINUX_USER64_CS) + return tdesc_amd64_linux; + else + return tdesc_i386_linux; +} + /* Provide a prototype to silence -Wmissing-prototypes. */ void _initialize_amd64_linux_nat (void); @@ -672,6 +734,7 @@ _initialize_amd64_linux_nat (void) i386_dr_low.set_addr = amd64_linux_dr_set_addr; i386_dr_low.reset_addr = amd64_linux_dr_reset_addr; i386_dr_low.get_status = amd64_linux_dr_get_status; + i386_dr_low.unset_status = amd64_linux_dr_unset_status; i386_set_debug_register_length (8); /* Override the GNU/Linux inferior startup hook. */ @@ -682,6 +745,8 @@ _initialize_amd64_linux_nat (void) t->to_fetch_registers = amd64_linux_fetch_inferior_registers; t->to_store_registers = amd64_linux_store_inferior_registers; + t->to_read_description = amd64_linux_read_description; + /* Register the target. */ linux_nat_add_target (t); linux_nat_set_new_thread (t, amd64_linux_new_thread);