This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] i386 segment base support


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 <main+20>
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  <teawater@gmail.com>

	* 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 @@
 <!DOCTYPE feature SYSTEM "gdb-target.dtd">
 <feature name="org.gnu.gdb.i386.linux">
   <reg name="orig_eax" bitsize="32" type="int" regnum="41"/>
+  <reg name="cs_base" bitsize="32" type="int"/>
+  <reg name="ss_base" bitsize="32" type="int"/>
+  <reg name="ds_base" bitsize="32" type="int"/>
+  <reg name="es_base" bitsize="32" type="int"/>
+  <reg name="fs_base" bitsize="32" type="int"/>
+  <reg name="gs_base" bitsize="32" type="int"/>
 </feature>
--- 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]