From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9648 invoked by alias); 20 May 2010 07:34:53 -0000 Received: (qmail 9617 invoked by uid 22791); 20 May 2010 07:34:46 -0000 X-SWARE-Spam-Status: No, hits=-1.5 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,TW_BF,TW_EB,TW_EG,TW_FP,TW_PX,TW_XB,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-px0-f169.google.com (HELO mail-px0-f169.google.com) (209.85.212.169) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 20 May 2010 07:34:39 +0000 Received: by pxi12 with SMTP id 12so8433239pxi.0 for ; Thu, 20 May 2010 00:34:37 -0700 (PDT) Received: by 10.142.9.15 with SMTP id 15mr6373719wfi.235.1274340877158; Thu, 20 May 2010 00:34:37 -0700 (PDT) MIME-Version: 1.0 Received: by 10.143.45.13 with HTTP; Thu, 20 May 2010 00:34:17 -0700 (PDT) From: Hui Zhu Date: Thu, 20 May 2010 07:45:00 -0000 Message-ID: Subject: [RFA] i386 segment base support To: gdb-patches@sourceware.org Cc: Mark Kettenis , dje@google.com, msnyder@vmware.com, dan@codesourcery.com, eliz@gnu.org Content-Type: text/plain; charset=ISO-8859-1 X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-05/txt/msg00410.txt.bz2 Hi guys, I update the old patch that I post to support segment base value. Now, it will not show when info reg. For example: (gdb) info reg eax 0x1 1 ecx 0xbffff510 -1073744624 edx 0xbffff530 -1073744592 ebx 0xb7fb5ff4 -1208262668 esp 0xbffff4a0 0xbffff4a0 ebp 0xbffff4f8 0xbffff4f8 esi 0xb7ffece0 -1207964448 edi 0x0 0 eip 0x8048388 0x8048388 eflags 0x286 [ PF SF IF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) info reg cs_base cs_base 0x0 0 (gdb) info reg gs_base gs_base 0xb7e6a6b0 -1209620816 Please help me review it. Thanks, Hui 2010-05-20 Hui Zhu * features/i386/32bit-linux.xml (org.gnu.gdb.i386.linux): Add cs_base, ss_base, ds_base, es_base, fs_base and gs_base. * amd64-linux-nat.c (user-regs.h): New include. (GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX): New marco. (ps_get_thread_area): New extern. (amd64_linux_fetch_inferior_registers): Add code to get 32 bits segment registers base. * i386-linux-nat.c (user-regs.h): New include. (GDT_ENTRY_TLS_ENTRIES, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX): New marco. (ps_get_thread_area): New extern. (i386_linux_fetch_inferior_registers): Add code to get segment registers base. * i386-linux-tdep.c (user-regs.h): New include. (i386_linux_register_reggroup_p): Add check for segment base registers. --- amd64-linux-nat.c | 40 ++++++++++++++++++++++++++++++++++++++++ features/i386/32bit-linux.xml | 6 ++++++ features/i386/i386-linux.c | 6 ++++++ i386-linux-nat.c | 40 ++++++++++++++++++++++++++++++++++++++++ i386-linux-tdep.c | 8 ++++++++ 5 files changed, 100 insertions(+) --- a/amd64-linux-nat.c +++ b/amd64-linux-nat.c @@ -26,6 +26,7 @@ #include "regset.h" #include "linux-nat.h" #include "amd64-linux-tdep.h" +#include "user-regs.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -146,12 +147,19 @@ fill_fpregset (const struct regcache *re this for all registers (including the floating point and SSE registers). */ +#define GDT_ENTRY_TLS_MIN 12 +#define GDT_ENTRY_TLS_MAX 14 + +extern ps_err_e ps_get_thread_area (const struct ps_prochandle *ph, + lwpid_t lwpid, int idx, void **base); + static void amd64_linux_fetch_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { struct gdbarch *gdbarch = get_regcache_arch (regcache); int tid; + int cs_base; /* GNU/Linux LWP ID's are process ID's. */ tid = TIDGET (inferior_ptid); @@ -195,6 +203,38 @@ amd64_linux_fetch_inferior_registers (st amd64_supply_fxsave (regcache, -1, &fpregs); } } + + /* Get the base of segment registers. */ + cs_base = user_reg_map_name_to_regnum (get_regcache_arch (regcache), + "cs_base", 7); + if (gdbarch_ptr_bit (gdbarch) == 32 + && regnum >= cs_base && regnum <= cs_base + 5) + { + ULONGEST idx; + int base; + + /* Get the idx. */ + base = user_reg_map_name_to_regnum (get_regcache_arch (regcache), + "cs", 2); + regcache_raw_read_unsigned (regcache, + regnum - cs_base + base, + &idx); + idx >>= 3; + + /* The base will be 0 if the idx is not TLS. */ + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + { + regcache_raw_supply (regcache, regnum, NULL); + return; + } + + /* Get the base. */ + if (ps_get_thread_area (NULL, tid, idx, (void *)&base) == PS_ERR) + perror_with_name (_("Couldn't get registers")); + + regcache_raw_supply (regcache, regnum, &base); + return; + } } /* Store register REGNUM back into the child process. If REGNUM is --- a/features/i386/32bit-linux.xml +++ b/features/i386/32bit-linux.xml @@ -8,4 +8,10 @@ + + + + + + --- a/features/i386/i386-linux.c +++ b/features/i386/i386-linux.c @@ -71,6 +71,12 @@ initialize_tdesc_i386_linux (void) feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux"); tdesc_create_reg (feature, "orig_eax", 41, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "cs_base", 42, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "ss_base", 43, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "ds_base", 44, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "es_base", 45, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "fs_base", 46, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "gs_base", 47, 1, NULL, 32, "int"); feature = tdesc_create_feature (result, "org.gnu.gdb.i386.sse"); field_type = tdesc_named_type (feature, "ieee_single"); --- a/i386-linux-nat.c +++ b/i386-linux-nat.c @@ -26,6 +26,7 @@ #include "regset.h" #include "target.h" #include "linux-nat.h" +#include "user-regs.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -506,11 +507,19 @@ static int store_fpxregs (const struct r this for all registers (including the floating point and SSE registers). */ +#define GDT_ENTRY_TLS_ENTRIES 3 +#define GDT_ENTRY_TLS_MIN 6 +#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) + +extern ps_err_e ps_get_thread_area (const struct ps_prochandle *ph, + lwpid_t lwpid, int idx, void **base); + static void i386_linux_fetch_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regno) { int tid; + int cs_base; /* Use the old method of peeking around in `struct user' if the GETREGS request isn't available. */ @@ -580,6 +589,37 @@ i386_linux_fetch_inferior_registers (str return; } + /* Get the base of segment registers. */ + cs_base = user_reg_map_name_to_regnum (get_regcache_arch (regcache), + "cs_base", 7); + if (regno >= cs_base && regno <= cs_base + 5) + { + ULONGEST idx; + int base; + + /* Get the idx. */ + base = user_reg_map_name_to_regnum (get_regcache_arch (regcache), + "cs", 2); + regcache_raw_read_unsigned (regcache, + regno - cs_base + base, + &idx); + idx >>= 3; + + /* The base will be 0 if the idx is not TLS. */ + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + { + regcache_raw_supply (regcache, regno, NULL); + return; + } + + /* Get the base. */ + if (ps_get_thread_area (NULL, tid, idx, (void *)&base) == PS_ERR) + perror_with_name (_("Couldn't get registers")); + + regcache_raw_supply (regcache, regno, &base); + return; + } + internal_error (__FILE__, __LINE__, _("Got request for bad register number %d."), regno); } --- a/i386-linux-tdep.c +++ b/i386-linux-tdep.c @@ -42,6 +42,8 @@ #include "i387-tdep.h" #include "i386-xstate.h" +#include "user-regs.h" + /* The syscall's XML filename for i386. */ #define XML_SYSCALL_FILENAME_I386 "syscalls/i386-linux.xml" @@ -81,6 +83,12 @@ static int i386_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum, struct reggroup *group) { + int cs_base = user_reg_map_name_to_regnum (gdbarch, + "cs_base", 7); + + if (regnum >= cs_base && regnum <= cs_base + 5) + return (group == all_reggroup); + if (regnum == I386_LINUX_ORIG_EAX_REGNUM) return (group == system_reggroup || group == save_reggroup