This is the mail archive of the gdb-patches@sources.redhat.com 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]

Re: [RFA] New bitflags type and eflags on i386/x86-64


Attatched is an old and related patch I've dug out of an old branch of GDB that Red Hat was providing for a customer.

I don't actually care what the type of eflags ends up being (the attached looks like):

(top-gdb) info registers
....
eflags {eflags = 0x216, bits = {ID = 0x0, VIP = 0x0, VIF = 0x0,
AC = 0x0, VM = 0x0, RF = 0x0, NT = 0x0, IOPL = 0x0, OF = 0x0, DF = 0x0,
IF = 0x1, TF = 0x0, SF = 0x0, ZF = 0x0, AF = 0x1, PF = 0x1,
CF = 0x0}} {eflags = 534, bits = {ID = 0, VIP = 0, VIF = 0, AC = 0,
VM = 0, RF = 0, NT = 0, IOPL = 0, OF = 0, DF = 0, IF = 1, TF = 0, SF = 0,
ZF = 0, AF = 1, PF = 1, CF = 0}}

However, given that there are two implementations, I get the feeling that [possibly fee paying] users want something.

Andrew

(that reminds me, ``AC'' et.al. should be in lower case).
2002-08-27  Andrew Cagney  <cagney@redhat.com>

	* i386-tdep.h (EFLAGS_REGNUM): Define.
	* i386-tdep.c (builtin_type_i386_eflags): New function.  Based on
	code by Fernando Nasser.
	(i386_register_virtual_type): Return builtin_type_i386_eflags when
	EFLAGS_REGNUM.

Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.83
diff -u -r1.83 i386-tdep.c
--- i386-tdep.c	23 Aug 2002 19:26:14 -0000	1.83
+++ i386-tdep.c	27 Aug 2002 19:06:18 -0000
@@ -1090,6 +1090,174 @@
 					type);
 }
 
+/* Construct some standard GDB types.  */
+
+static struct type *
+builtin_type_i386_eflags (void)
+{
+  /* Construct a type for the EFLAGS register.  The type we're
+     building is this: */
+#if 0     
+  union builtin_type_i386_eflags
+  {
+    int32_t eflags;
+    struct __builtin_i386_eflags_bits
+    {
+      /* We skip the 10 reserved bits here.  */
+      unsigned ID:1;
+      unsigned VIP:1;
+      unsigned VIF:1;
+      unsigned AC:1;
+      unsigned VM:1;
+      unsigned RF:1;
+      /* We skip one reserved bit here.  */
+      unsigned NT:1;
+      unsigned IOPL:2;
+      unsigned OF:1;
+      unsigned DF:1;
+      unsigned IF:1;
+      unsigned TF:1;
+      unsigned SF:1;
+      unsigned ZF:1;
+      /* We skip one reserved bit here.  */
+      unsigned AF:1;
+      /* We skip one reserved bit here.  */
+      unsigned PF:1;
+      /* We skip one reserved bit here.  */
+      unsigned CF:1;
+    } bits;
+  };
+#endif
+  /* Note that we cannot create a structure like that in C because we
+     could not skip the reserved bits and the order would be the
+     reverse of what we want (we want to see bit names from left to
+     right, as in a manual figure).  */
+
+  static struct type *t;	/* The type we are creating. */
+  struct type *tp;	/* The type of the pointer part. */
+  struct type *tb;	/* The type of the bitfields part. */
+  struct field *fu;	/* Fields of the union. */
+  struct field *fs;	/* Fields of the struct. */
+
+  if (t != NULL)
+    return t;
+
+  /* Create fields for each group of bits. */
+  fs = (struct field *) xmalloc (sizeof (*fs) * 17);
+  memset (fs, 0, sizeof (*fs) * 17);
+
+  /* Note that we reverse the order of the fields so they are printed
+     as we would see then in a manual figure, left to right. */
+
+  FIELD_TYPE (fs[16]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[16]) = "CF";
+  FIELD_BITPOS (fs[16]) = 0;
+  FIELD_BITSIZE (fs[16]) = 1;
+
+  FIELD_TYPE (fs[15]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[15]) = "PF";
+  FIELD_BITPOS (fs[15]) = 2;
+  FIELD_BITSIZE (fs[15]) = 1;
+
+  FIELD_TYPE (fs[14]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[14]) = "AF";
+  FIELD_BITPOS (fs[14]) = 4;
+  FIELD_BITSIZE (fs[14]) = 1;
+
+  FIELD_TYPE (fs[13]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[13]) = "ZF";
+  FIELD_BITPOS (fs[13]) = 6;
+  FIELD_BITSIZE (fs[13]) = 1;
+
+  FIELD_TYPE (fs[12]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[12]) = "SF";
+  FIELD_BITPOS (fs[12]) = 7;
+  FIELD_BITSIZE (fs[12]) = 1;
+
+  FIELD_TYPE (fs[11]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[11]) = "TF";
+  FIELD_BITPOS (fs[11]) = 8;
+  FIELD_BITSIZE (fs[11]) = 1;
+
+  FIELD_TYPE (fs[10]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[10]) = "IF";
+  FIELD_BITPOS (fs[10]) = 9;
+  FIELD_BITSIZE (fs[10]) = 1;
+
+  FIELD_TYPE (fs[9]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[9]) = "DF";
+  FIELD_BITPOS (fs[9]) = 10;
+  FIELD_BITSIZE (fs[9]) = 1;
+
+  FIELD_TYPE (fs[8]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[8]) = "OF";
+  FIELD_BITPOS (fs[8]) = 11;
+  FIELD_BITSIZE (fs[8]) = 1;
+
+  FIELD_TYPE (fs[7]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[7]) = "IOPL";
+  FIELD_BITPOS (fs[7]) = 12;
+  FIELD_BITSIZE (fs[7]) = 2;
+
+  FIELD_TYPE (fs[6]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[6]) = "NT";
+  FIELD_BITPOS (fs[6]) = 14;
+  FIELD_BITSIZE (fs[6]) = 1;
+
+  FIELD_TYPE (fs[5]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[5]) = "RF";
+  FIELD_BITPOS (fs[5]) = 16;
+  FIELD_BITSIZE (fs[5]) = 1;
+
+  FIELD_TYPE (fs[4]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[4]) = "VM";
+  FIELD_BITPOS (fs[4]) = 17;
+  FIELD_BITSIZE (fs[4]) = 1;
+
+  FIELD_TYPE (fs[3]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[3]) = "AC";
+  FIELD_BITPOS (fs[3]) = 18;
+  FIELD_BITSIZE (fs[3]) = 1;
+
+  FIELD_TYPE (fs[2]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[2]) = "VIF";
+  FIELD_BITPOS (fs[2]) = 19;
+  FIELD_BITSIZE (fs[2]) = 1;
+
+  FIELD_TYPE (fs[1]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[1]) = "VIP";
+  FIELD_BITPOS (fs[1]) = 20;
+  FIELD_BITSIZE (fs[1]) = 1;
+
+  FIELD_TYPE (fs[0]) = builtin_type_unsigned_int;
+  FIELD_NAME (fs[0]) = "ID";
+  FIELD_BITPOS (fs[0]) = 21;
+  FIELD_BITSIZE (fs[0]) = 1;
+
+  /* Build a struct type with these bitfields.  */
+  tb = init_type (TYPE_CODE_STRUCT, 4, 0, 0, 0);
+  TYPE_NFIELDS (tb) = 17;
+  TYPE_FIELDS (tb) = fs;
+  TYPE_TAG_NAME (tb) = "builtin_type_i386_eflags_bits";
+
+  /* Now make our type as the union of the pointer and the bitfield parts. */
+  fu = (struct field *) xmalloc (sizeof (*fu) * 2);
+  memset (fu, 0, sizeof (*fu) * 2);
+
+  FIELD_TYPE (fu[0]) = builtin_type_int32;
+  FIELD_NAME (fu[0]) = "eflags";
+
+  FIELD_TYPE (fu[1]) = tb;
+  FIELD_NAME (fu[1]) = "bits";
+
+  /* Build a union type with those fields.  */
+  t = init_type (TYPE_CODE_UNION, 4, 0, 0, 0);
+  TYPE_NFIELDS (t) = 2;
+  TYPE_FIELDS (t) = fu;
+  TYPE_TAG_NAME (t) = "builtin_type_i386_eflags";
+
+  return t;
+}
 
 /* Return the GDB type object for the "standard" data type of data in
    register REGNUM.  Perhaps %esi and %edi should go here, but
@@ -1100,6 +1268,9 @@
 {
   if (regnum == PC_REGNUM || regnum == FP_REGNUM || regnum == SP_REGNUM)
     return lookup_pointer_type (builtin_type_void);
+
+  if (regnum == EFLAGS_REGNUM)
+    return builtin_type_i386_eflags ();
 
   if (IS_FP_REGNUM (regnum))
     return builtin_type_i387_ext;
Index: i386-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.h,v
retrieving revision 1.13
diff -u -r1.13 i386-tdep.h
--- i386-tdep.h	20 Aug 2002 17:59:50 -0000	1.13
+++ i386-tdep.h	27 Aug 2002 19:06:18 -0000
@@ -77,6 +77,9 @@
   int sc_sp_offset;
 };
 
+/* The EFLAGS register.  */
+enum { EFLAGS_REGNUM = 9 };
+
 /* Floating-point registers.  */
 
 #define FPU_REG_RAW_SIZE 10
--- Begin Message --- (Once again, now with Changelog :-)

Hi all,
I've created a new typecode TYPE_CODE_FLAGS with appropriate functions and used it in builtin_type_i386_eflags type. I did this to be able to print i386's and x86-64's FLAGS register in a symbolic form, instead of printing it in a hexadecimal and decimal notation.

Now it looks like this:
(gdb) info registers eflags
eflags 0x747 [ DF IF TF ZF PF CF ]

I've chosen quite a generic way for implementation, so that the others could use this for their types as well. For now I'm using this type only on x86-64, but using it on i386 should be possible without modifications. (BTW Should I do it or the maintainer will?)

2002-04-22 Michal Ludvig <mludvig@suse.cz>

* c-valprint.c (c_val_print): Added handling of TYPE_CODE_FLAGS.
* gdbtypes.c (builtin_type_i386_eflags): Added.
(add_flag_ignore, add_flag_name, init_flags_type): Added.
(is_integral_type, rank_one_type, recursive_dump_type): Added
TYPE_CODE_FLAGS handling.
(build_gdbtypes): Added builtin_type_i386_eflags initialization.
* gdbtypes.h (type_code): Added TYPE_CODE_FLAGS.
(builtin_type_i386_eflags): Added.
* values.c (unpack_long: Added TYPE_CODE_FLAGS handling.
* x86-64-tdep.c (x86_64_register_info_table): Changed type of
eflags.

Any comments? Can I commit?

Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* +420 2 9654 5373 * http://www.suse.cz
Index: c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.13
diff -u -r1.13 c-valprint.c
--- c-valprint.c	5 Feb 2002 21:41:29 -0000	1.13
+++ c-valprint.c	22 Apr 2002 14:50:12 -0000
@@ -70,6 +70,7 @@
 	     int deref_ref, int recurse, enum val_prettyprint pretty)
 {
   register unsigned int i = 0;	/* Number of characters printed */
+  register int j;
   unsigned len;
   struct type *elttype;
   unsigned eltlen;
@@ -483,6 +484,30 @@
 			TYPE_TARGET_TYPE (type),
 			stream);
       fprintf_filtered (stream, " * I");
+      break;
+
+    case TYPE_CODE_FLAGS:
+      if (format)
+	{
+	  print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+	  break;
+	}
+      len = TYPE_NFIELDS (type);
+      val = unpack_long (type, valaddr + embedded_offset);
+      fputs_filtered("[", stream);
+      for (j = len-1; j >= 0; j--)
+	{
+	  QUIT;
+	  if (TYPE_FIELD_BITPOS (type, j) != -1 && val & (1 << j))
+	  {
+		  if(TYPE_FIELD_NAME (type, j))
+			  fprintf_filtered (stream, " %s", TYPE_FIELD_NAME (type, j));
+		  else
+			  fprintf_filtered (stream, " #%d", j);
+				  
+	  }
+	}
+      fputs_filtered(" ]", stream);
       break;
 
     default:
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.43
diff -u -r1.43 gdbtypes.c
--- gdbtypes.c	20 Apr 2002 01:09:28 -0000	1.43
+++ gdbtypes.c	22 Apr 2002 14:50:13 -0000
@@ -99,6 +99,7 @@
 struct type *builtin_type_void_func_ptr;
 struct type *builtin_type_CORE_ADDR;
 struct type *builtin_type_bfd_vma;
+struct type *builtin_type_i386_eflags;
 
 int opaque_type_resolution = 1;
 int overload_debug = 0;
@@ -777,6 +778,67 @@
   return (result_type);
 }
 
+/*
+ * - The following three functions are intended to be used for BitFlags 
+ *   types (ie i386's EFLAGS register).
+ * - As a BitFlag we understand an integer where some bits may have 
+ *   a symbolic names that would be printed when the bit is set.
+ * - Printing is done in c_val_print() under a TYPE_CODE_FLAGS label.
+ * - All bits are set to be ignored (ie. not printed even when set) 
+ *   by default.
+ * - Add a symbolic name of relevant bits using add_flag_name() after 
+ *   an initialisation of your type.
+ */
+void
+add_flag_ignore (struct type *type, int bitpos)
+{
+	TYPE_FIELD_BITPOS (type, bitpos) = -1;
+}
+
+void
+add_flag_name (struct type *type, int bitpos, char *name)
+{
+	int namelen;
+	
+	gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLAGS);
+	gdb_assert (bitpos < TYPE_NFIELDS (type));
+	gdb_assert (bitpos >= 0);
+	
+	namelen=strlen(name)+1;
+	TYPE_FIELD_NAME (type, bitpos) = xmalloc (namelen);
+	snprintf(TYPE_FIELD_NAME (type, bitpos), namelen, "%s", name);	
+
+	TYPE_FIELD_BITPOS (type, bitpos) = bitpos;
+}
+
+struct type *
+init_flags_type (int bitlength, char *name, struct objfile *objfile)
+{
+  register struct type *type;
+  int i;
+  
+  type = alloc_type (objfile);
+  
+  TYPE_CODE (type) = TYPE_CODE_FLAGS;
+  TYPE_LENGTH (type) = bitlength / 8 + ( bitlength % 8 ? 1 : 0 );
+  TYPE_FLAGS (type) = TYPE_FLAG_UNSIGNED;
+  TYPE_NFIELDS (type) = bitlength;
+  TYPE_FIELDS (type) = (struct field *)
+    TYPE_ALLOC (type, bitlength * sizeof (struct field));
+  memset (TYPE_FIELDS (type), 0, sizeof (struct field));
+
+  if ((name != NULL) && (objfile != NULL))
+      TYPE_NAME (type) =
+	obsavestring (name, strlen (name), &objfile->type_obstack);
+  else
+      TYPE_NAME (type) = name;
+  
+  for(i=0; i<bitlength; i++)
+	add_flag_ignore (type, i);
+
+  return (type);
+}
+
 /* Construct and return a type of the form:
 	struct NAME { ELT_TYPE ELT_NAME[N]; }
    We use these types for SIMD registers.  For example, the type of
@@ -1841,6 +1903,7 @@
   return
     ((t != NULL)
      && ((TYPE_CODE (t) == TYPE_CODE_INT)
+	 || (TYPE_CODE (t) == TYPE_CODE_FLAGS)
 	 || (TYPE_CODE (t) == TYPE_CODE_ENUM)
 	 || (TYPE_CODE (t) == TYPE_CODE_CHAR)
 	 || (TYPE_CODE (t) == TYPE_CODE_RANGE)
@@ -2372,6 +2435,7 @@
 	case TYPE_CODE_FUNC:
 	  return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
 	case TYPE_CODE_INT:
+	case TYPE_CODE_FLAGS:
 	case TYPE_CODE_ENUM:
 	case TYPE_CODE_CHAR:
 	case TYPE_CODE_RANGE:
@@ -2448,6 +2512,8 @@
 	    return INTEGER_PROMOTION_BADNESS;
 	  else
 	    return INTEGER_COERCION_BADNESS;
+        case TYPE_CODE_FLAGS:
+	  return 0;
 	case TYPE_CODE_ENUM:
 	case TYPE_CODE_CHAR:
 	case TYPE_CODE_RANGE:
@@ -2898,6 +2964,9 @@
     case TYPE_CODE_INT:
       printf_filtered ("(TYPE_CODE_INT)");
       break;
+    case TYPE_CODE_FLAGS:
+      printf_filtered ("(TYPE_CODE_FLAGS)");
+      break;
     case TYPE_CODE_FLT:
       printf_filtered ("(TYPE_CODE_FLT)");
       break;
@@ -3318,6 +3387,28 @@
     init_type (TYPE_CODE_INT, TARGET_BFD_VMA_BIT / 8,
 	       TYPE_FLAG_UNSIGNED,
 	       "__bfd_vma", (struct objfile *) NULL);
+  builtin_type_i386_eflags = 
+    init_flags_type (32 /* EFLAGS_LENGTH */, 
+    	       "__i386_eflags", (struct objfile *) NULL);
+  add_flag_name (builtin_type_i386_eflags, 0, "CF");
+  add_flag_ignore (builtin_type_i386_eflags, 1);
+  add_flag_name (builtin_type_i386_eflags, 2, "PF");
+  add_flag_name (builtin_type_i386_eflags, 4, "AF");
+  add_flag_name (builtin_type_i386_eflags, 6, "ZF");
+  add_flag_name (builtin_type_i386_eflags, 7, "SF");
+  add_flag_name (builtin_type_i386_eflags, 8, "TF");
+  add_flag_name (builtin_type_i386_eflags, 9, "IF");
+  add_flag_name (builtin_type_i386_eflags, 10, "DF");
+  add_flag_name (builtin_type_i386_eflags, 11, "OF");
+  add_flag_ignore (builtin_type_i386_eflags, 12);
+  add_flag_ignore (builtin_type_i386_eflags, 13);
+  add_flag_name (builtin_type_i386_eflags, 14, "NT");
+  add_flag_name (builtin_type_i386_eflags, 16, "RF");
+  add_flag_name (builtin_type_i386_eflags, 17, "VM");
+  add_flag_name (builtin_type_i386_eflags, 18, "AC");
+  add_flag_name (builtin_type_i386_eflags, 19, "VIF");
+  add_flag_name (builtin_type_i386_eflags, 20, "VIP");
+  add_flag_name (builtin_type_i386_eflags, 21, "ID");
 }
 
 
Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.27
diff -u -r1.27 gdbtypes.h
--- gdbtypes.h	23 Mar 2002 01:24:54 -0000	1.27
+++ gdbtypes.h	22 Apr 2002 14:50:13 -0000
@@ -85,6 +85,7 @@
     TYPE_CODE_ENUM,		/* Enumeration type */
     TYPE_CODE_FUNC,		/* Function type */
     TYPE_CODE_INT,		/* Integer type */
+    TYPE_CODE_FLAGS,		/* BitFlags type */
 
     /* Floating type.  This is *NOT* a complex type.  Beware, there are parts
        of GDB which bogusly assume that TYPE_CODE_FLT can mean complex.  */
@@ -930,6 +931,10 @@
 
 /* The target CPU's address type.  This is the ISA address size. */
 extern struct type *builtin_type_CORE_ADDR;
+
+/* Type for i386 EFLAGS register.  */
+extern struct type *builtin_type_i386_eflags;
+
 /* The symbol table address type.  Some object file formats have a 32
    bit address type even though the TARGET has a 64 bit pointer type
    (cf MIPS). */
Index: values.c
===================================================================
RCS file: /cvs/src/src/gdb/values.c,v
retrieving revision 1.34
diff -u -r1.34 values.c
--- values.c	29 Jan 2002 03:08:26 -0000	1.34
+++ values.c	22 Apr 2002 14:50:14 -0000
@@ -697,6 +697,7 @@
     case TYPE_CODE_ENUM:
     case TYPE_CODE_BOOL:
     case TYPE_CODE_INT:
+    case TYPE_CODE_FLAGS:
     case TYPE_CODE_CHAR:
     case TYPE_CODE_RANGE:
       if (nosign)
Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.13
diff -u -r1.13 x86-64-tdep.c
--- x86-64-tdep.c	6 Apr 2002 00:02:50 -0000	1.13
+++ x86-64-tdep.c	22 Apr 2002 14:50:22 -0000
@@ -66,7 +66,7 @@
   {8, "r14", &builtin_type_int64},
   {8, "r15", &builtin_type_int64},
   {8, "rip", &builtin_type_void_func_ptr},
-  {4, "eflags", &builtin_type_int32},
+  {4, "eflags", &builtin_type_i386_eflags},
   {4, "ds", &builtin_type_int32},
   {4, "es", &builtin_type_int32},
   {4, "fs", &builtin_type_int32},
--- End Message ---

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