This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] New bitflags type and eflags on i386/x86-64
- From: Michal Ludvig <mludvig at suse dot cz>
- To: gdb-patches at sources dot redhat dot com
- Date: Mon, 22 Apr 2002 17:34:56 +0200
- Subject: [RFA] New bitflags type and eflags on i386/x86-64
- Organization: SuSE CR
(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},