This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [PATCH RFA/RFC] Address class support
- From: Jim Blandy <jimb at redhat dot com>
- To: Kevin Buettner <kevinb at redhat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: 16 Oct 2002 02:06:41 -0500
- Subject: Re: [PATCH RFA/RFC] Address class support
- References: <1021016004200.ZM22063@localhost.localdomain>
The dwarf2read.c part is approved.
Kevin Buettner <kevinb@redhat.com> writes:
> The patch below supercedes the "Short pointer support" patch that
> I sent to the list last week:
>
> http://sources.redhat.com/ml/gdb-patches/2002-10/msg00239.html
>
> Instead, due in part to Jim Blandy's comments on my previous patch,
> I've implemented a more general (and robust) solution that will
> hopefully prove to have more uses than my immediate need for it (which
> is still short pointer support). E.g, it could be used to implement
> the near16/far16/huge16/near32/far32 address distinctions for x86. (I
> suspect though that other work would be necessary too.)
>
> As before, I'll need approval on the dwarf2read.c changes from
> either Jim or Elena and I'll need Eli's okay on the Docs changes.
>
> Kevin
>
> * dwarf2read.c (dwarf2_invalid_pointer_size): New complaint.
> (read_tag_pointer_type): Add address class support.
> * gdbarch.sh (ADDRESS_CLASS_TYPE_FLAGS)
> (ADDRESS_CLASS_TYPE_FLAGS_TO_NAME, ADDRESS_CLASS_NAME_TO_TYPE_FLAGS):
> New methods.
> * gdbarch.h, gdbarch.c: Regenerate.
> * gdbtypes.c (address_space_name_to_int, address_space_int_to_name)
> (make_type_with_address_space, recursive_type_dump): Add address
> class support.
> * gdbtypes.h (TYPE_FLAG_ADDRESS_CLASS_1, TYPE_FLAG_ADDRESS_CLASS_2)
> (TYPE_FLAG_ADDRESS_CLASS_ALL, TYPE_ADDRESS_CLASS_1)
> (TYPE_ADDRESS_CLASS_2, TYPE_ADDRESS_CLASS_ALL): New defines
>
> Index: dwarf2read.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/dwarf2read.c,v
> retrieving revision 1.68
> diff -u -p -r1.68 dwarf2read.c
> --- dwarf2read.c 9 Oct 2002 04:43:49 -0000 1.68
> +++ dwarf2read.c 16 Oct 2002 00:15:07 -0000
> @@ -683,6 +683,10 @@ static struct complaint dwarf2_invalid_a
> {
> "invalid attribute class or form for '%s' in '%s'", 0, 0
> };
> +static struct complaint dwarf2_invalid_pointer_size =
> +{
> + "invalid pointer size %d", 0, 0
> +};
>
> /* local function prototypes */
>
> @@ -2925,7 +2929,9 @@ read_tag_pointer_type (struct die_info *
> const struct comp_unit_head *cu_header)
> {
> struct type *type;
> - struct attribute *attr;
> + struct attribute *attr_byte_size;
> + struct attribute *attr_address_class;
> + int byte_size, addr_class;
>
> if (die->type)
> {
> @@ -2933,15 +2939,42 @@ read_tag_pointer_type (struct die_info *
> }
>
> type = lookup_pointer_type (die_type (die, objfile, cu_header));
> - attr = dwarf_attr (die, DW_AT_byte_size);
> - if (attr)
> - {
> - TYPE_LENGTH (type) = DW_UNSND (attr);
> - }
> +
> + attr_byte_size = dwarf_attr (die, DW_AT_byte_size);
> + if (attr_byte_size)
> + byte_size = DW_UNSND (attr_byte_size);
> else
> + byte_size = cu_header->addr_size;
> +
> + attr_address_class = dwarf_attr (die, DW_AT_address_class);
> + if (attr_address_class)
> + addr_class = DW_UNSND (attr_address_class);
> + else
> + addr_class = DW_ADDR_none;
> +
> + /* If the pointer size or address class is different than the
> + default, create a type variant marked as such and set the
> + length accordingly. */
> + if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
> {
> - TYPE_LENGTH (type) = cu_header->addr_size;
> + if (ADDRESS_CLASS_TYPE_FLAGS_P ())
> + {
> + int type_flags;
> +
> + type_flags = ADDRESS_CLASS_TYPE_FLAGS (byte_size, addr_class);
> + gdb_assert ((type_flags & ~TYPE_FLAG_ADDRESS_CLASS_ALL) == 0);
> + type = make_type_with_address_space (type, type_flags);
> + }
> + else if (TYPE_LENGTH (type) != byte_size)
> + {
> + complain (&dwarf2_invalid_pointer_size, byte_size);
> + }
> + else {
> + /* Should we also complain about unhandled address classes? */
> + }
> }
> +
> + TYPE_LENGTH (type) = byte_size;
> die->type = type;
> }
>
> Index: gdbarch.sh
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbarch.sh,v
> retrieving revision 1.164
> diff -u -p -r1.164 gdbarch.sh
> --- gdbarch.sh 9 Oct 2002 11:59:54 -0000 1.164
> +++ gdbarch.sh 16 Oct 2002 00:15:09 -0000
> @@ -664,6 +664,9 @@ f:2:COFF_MAKE_MSYMBOL_SPECIAL:void:coff_
> v::NAME_OF_MALLOC:const char *:name_of_malloc::::"malloc":"malloc"::0
> v::CANNOT_STEP_BREAKPOINT:int:cannot_step_breakpoint::::0:0::0
> v::HAVE_NONSTEPPABLE_WATCHPOINT:int:have_nonsteppable_watchpoint::::0:0::0
> +F:2:ADDRESS_CLASS_TYPE_FLAGS:int:address_class_type_flags:int byte_size, int dwarf2_addr_class:byte_size, dwarf2_addr_class
> +F:2:ADDRESS_CLASS_TYPE_FLAGS_TO_NAME:char *:address_class_type_flags_to_name:int type_flags:type_flags
> +F:2:ADDRESS_CLASS_NAME_TO_TYPE_FLAGS:int:address_class_name_to_type_flags:char *name, int *type_flags_ptr:name, type_flags_ptr
> EOF
> }
>
> Index: gdbtypes.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbtypes.c,v
> retrieving revision 1.59
> diff -u -p -r1.59 gdbtypes.c
> --- gdbtypes.c 2 Oct 2002 22:01:53 -0000 1.59
> +++ gdbtypes.c 16 Oct 2002 00:15:10 -0000
> @@ -397,11 +397,15 @@ lookup_function_type (struct type *type)
> extern int
> address_space_name_to_int (char *space_identifier)
> {
> + int type_flags;
> /* Check for known address space delimiters. */
> if (!strcmp (space_identifier, "code"))
> return TYPE_FLAG_CODE_SPACE;
> else if (!strcmp (space_identifier, "data"))
> return TYPE_FLAG_DATA_SPACE;
> + else if (ADDRESS_CLASS_NAME_TO_TYPE_FLAGS_P ()
> + && ADDRESS_CLASS_NAME_TO_TYPE_FLAGS (space_identifier, &type_flags))
> + return type_flags;
> else
> error ("Unknown address space specifier: \"%s\"", space_identifier);
> }
> @@ -416,6 +420,9 @@ address_space_int_to_name (int space_fla
> return "code";
> else if (space_flag & TYPE_FLAG_DATA_SPACE)
> return "data";
> + else if ((space_flag & TYPE_FLAG_ADDRESS_CLASS_ALL)
> + && ADDRESS_CLASS_TYPE_FLAGS_TO_NAME_P ())
> + return ADDRESS_CLASS_TYPE_FLAGS_TO_NAME (space_flag);
> else
> return NULL;
> }
> @@ -465,14 +472,17 @@ make_qualified_type (struct type *type,
> is identical to the one supplied except that it has an address
> space attribute attached to it (such as "code" or "data").
>
> - This is for Harvard architectures. */
> + The space attributes "code" and "data" are for Harvard architectures.
> + The address space attributes are for architectures which have
> + alternately sized pointers or pointers with alternate representations. */
>
> struct type *
> make_type_with_address_space (struct type *type, int space_flag)
> {
> struct type *ntype;
> int new_flags = ((TYPE_INSTANCE_FLAGS (type)
> - & ~(TYPE_FLAG_CODE_SPACE | TYPE_FLAG_DATA_SPACE))
> + & ~(TYPE_FLAG_CODE_SPACE | TYPE_FLAG_DATA_SPACE
> + | TYPE_FLAG_ADDRESS_CLASS_ALL))
> | space_flag);
>
> return make_qualified_type (type, new_flags, NULL);
> @@ -3139,6 +3149,14 @@ recursive_dump_type (struct type *type,
> if (TYPE_DATA_SPACE (type))
> {
> puts_filtered (" TYPE_FLAG_DATA_SPACE");
> + }
> + if (TYPE_ADDRESS_CLASS_1 (type))
> + {
> + puts_filtered (" TYPE_FLAG_ADDRESS_CLASS_1");
> + }
> + if (TYPE_ADDRESS_CLASS_2 (type))
> + {
> + puts_filtered (" TYPE_FLAG_ADDRESS_CLASS_2");
> }
> puts_filtered ("\n");
> printfi_filtered (spaces, "flags 0x%x", TYPE_FLAGS (type));
> Index: gdbtypes.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbtypes.h,v
> retrieving revision 1.36
> diff -u -p -r1.36 gdbtypes.h
> --- gdbtypes.h 14 Sep 2002 02:09:39 -0000 1.36
> +++ gdbtypes.h 16 Oct 2002 00:15:10 -0000
> @@ -253,6 +253,22 @@ enum type_code
> #define TYPE_FLAG_VECTOR (1 << 12)
> #define TYPE_VECTOR(t) (TYPE_FLAGS (t) & TYPE_FLAG_VECTOR)
>
> +/* Address class flags. Some environments provide for pointers whose
> + size is different from that of a normal pointer or address types
> + where the bits are interpreted differently than normal addresses. The
> + TYPE_FLAG_ADDRESS_CLASS_n flags may be used in target specific
> + ways to represent these different types of address classes. */
> +#define TYPE_FLAG_ADDRESS_CLASS_1 (1 << 13)
> +#define TYPE_ADDRESS_CLASS_1(t) (TYPE_INSTANCE_FLAGS(t) \
> + & TYPE_FLAG_ADDRESS_CLASS_1)
> +#define TYPE_FLAG_ADDRESS_CLASS_2 (1 << 14)
> +#define TYPE_ADDRESS_CLASS_2(t) (TYPE_INSTANCE_FLAGS(t) \
> + & TYPE_FLAG_ADDRESS_CLASS_2)
> +#define TYPE_FLAG_ADDRESS_CLASS_ALL (TYPE_FLAG_ADDRESS_CLASS_1 \
> + | TYPE_FLAG_ADDRESS_CLASS_2)
> +#define TYPE_ADDRESS_CLASS_ALL(t) (TYPE_INSTANCE_FLAGS(t) \
> + & TYPE_FLAG_ADDRESS_CLASS_ALL)
> +
> struct main_type
> {
> /* Code for kind of type */
> Index: doc/gdbint.texinfo
> ===================================================================
> RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
> retrieving revision 1.104
> diff -u -p -r1.104 gdbint.texinfo
> --- doc/gdbint.texinfo 11 Oct 2002 14:01:04 -0000 1.104
> +++ doc/gdbint.texinfo 16 Oct 2002 00:15:13 -0000
> @@ -2630,6 +2630,89 @@ This function may safely assume that @va
> C@t{++} reference type.
> @end deftypefn
>
> +@section Address Classes
> +@cindex address classes
> +@cindex DW_AT_byte_size
> +@cindex DW_AT_address_class
> +
> +Sometimes information about different kinds of addresses is available
> +via the debug information. For example, some programming environments
> +define addresses of several different sizes. If the debug information
> +distinguishes these kinds of address classes through either the size
> +info (e.g, @code{DW_AT_byte_size} in DWARF 2) or through an explicit
> +address class attribute (e.g, @code{DW_AT_address_class} in DWARF 2), the
> +following macros should be defined in order to disambiguate these
> +types within @value{GDBN} as well as provide the added information to
> +a @value{GDBN} user when printing type expressions.
> +
> +@deftypefn {Target Macro} int ADDRESS_CLASS_TYPE_FLAGS (int @var{byte_size}, int @var{dwarf2_addr_class})
> +Returns the type flags needed to construct a pointer type whose size
> +is @var{byte_size} and whose address class is @var{dwarf2_addr_class}.
> +This function is normally called from within a symbol reader. See
> +@file{dwarf2read.c}.
> +@end deftypefn
> +
> +@deftypefn {Target Macro} char *ADDRESS_CLASS_TYPE_FLAGS_TO_NAME (int @var{type_flags})
> +Given the type flags representing an address class qualifier, return
> +its name.
> +@end deftypefn
> +@deftypefn {Target Macro} int ADDRESS_CLASS_NAME_to_TYPE_FLAGS (int @var{name}, int *var{type_flags_ptr})
> +Given an address qualifier name, set the @code{int} refererenced by @var{type_flags_ptr} to the type flags
> +for that address class qualifier.
> +@end deftypefn
> +
> +Since the need for address classes is rather rare, none of
> +the address class macros defined by default. Predicate
> +macros are provided to detect when they are defined.
> +
> +Consider a hypothetical architecture in which addresses are normally
> +32-bits wide, but 16-bit addresses are also supported. Furthermore,
> +suppose that the DWARF 2 information for this architecture simply
> +uses a @code{DW_AT_byte_size} value of 2 to indicate the use of one
> +of these "short" pointers. The following functions could be defined
> +to implement the address class macros:
> +
> +@smallexample
> +somearch_address_class_type_flags (int byte_size, int dwarf2_addr_class)
> +{
> + if (byte_size == 2)
> + return TYPE_FLAG_ADDRESS_CLASS_1;
> + else
> + return 0;
> +}
> +
> +static char *
> +somearch_address_class_type_flags_to_name (int type_flags)
> +{
> + if (type_flags & TYPE_FLAG_ADDRESS_CLASS_1)
> + return "short";
> + else
> + return NULL;
> +}
> +
> +int
> +somearch_address_class_name_to_type_flags (char *name, int *type_flags_ptr)
> +{
> + if (strcmp (name, "short") == 0)
> + {
> + *type_flags_ptr = TYPE_FLAG_ADDRESS_CLASS_1;
> + return 1;
> + }
> + else
> + return 0;
> +}
> +@end smallexample
> +
> +The qualifier @code{@@short} is used in @value{GDBN}'s type expressions
> +to indicate the presence of one of these "short" pointers. E.g, if
> +the debug information indicates that @code{short_ptr_var} is one of these
> +short pointers, @value{GDBN} might show the following behavior:
> +
> +@smallexample
> +(gdb) ptype short_ptr_var
> +type = int * @@short
> +@end smallexample
> +
>
> @section Raw and Virtual Register Representations
> @cindex raw register representation
> @@ -2856,6 +2939,49 @@ instruction. Since instructions must al
> boundaries, the processor masks out these bits to generate the actual
> address of the instruction. ADDR_BITS_REMOVE should filter out these
> bits with an expression such as @code{((addr) & ~3)}.
> +
> +@item ADDRESS_CLASS_NAME_TO_TYPE_FLAGS (@var{name}, @var{type_flags_ptr})
> +@findex ADDRESS_CLASS_NAME_TO_TYPE_FLAGS
> +If @var{name} is a valid address class qualifier name, set the @code{int}
> +referenced by @var{type_flags_ptr} to the mask representing the qualifier
> +and return 1. If @var{name} is not a valid address class qualifier name,
> +return 0.
> +
> +The value for @var{type_flags_ptr} should be one of
> +@code{TYPE_FLAG_ADDRESS_CLASS_1}, @code{TYPE_FLAG_ADDRESS_CLASS_2}, or
> +possibly some combination of these values or'd together.
> +@xref{Target Architecture Definition, , Address Classes}.
> +
> +@item ADDRESS_CLASS_NAME_TO_TYPE_FLAGS_P ()
> +@findex ADDRESS_CLASS_NAME_TO_TYPE_FLAGS_P
> +Predicate which indicates whether @code{ADDRESS_CLASS_NAME_TO_TYPE_FLAGS}
> +has been defined.
> +
> +@item ADDRESS_CLASS_TYPE_FLAGS (@var{byte_size}, @var{dwarf2_addr_class})
> +@findex ADDRESS_CLASS_TYPE_FLAGS (@var{byte_size}, @var{dwarf2_addr_class})
> +Given a pointers byte size (as described by the debug information) and
> +the possible @code{DW_AT_address_class} value, return the type flags
> +used by @value{GDBN} to represent this address class. The value
> +returned should be one of @code{TYPE_FLAG_ADDRESS_CLASS_1},
> +@code{TYPE_FLAG_ADDRESS_CLASS_2}, or possibly some combination of these
> +values or'd together.
> +@xref{Target Architecture Definition, , Address Classes}.
> +
> +@item ADDRESS_CLASS_TYPE_FLAGS_P ()
> +@findex ADDRESS_CLASS_TYPE_FLAGS_P
> +Predicate which indicates whether @code{ADDRESS_CLASS_TYPE_FLAGS} has
> +been defined.
> +
> +@item ADDRESS_CLASS_TYPE_FLAGS_TO_NAME (@var{type_flags})
> +@findex ADDRESS_CLASS_TYPE_FLAGS_TO_NAME
> +Return the name of the address class qualifier associated with the type
> +flags given by @var{type_flags}.
> +
> +@item ADDRESS_CLASS_TYPE_FLAGS_TO_NAME_P ()
> +@findex ADDRESS_CLASS_TYPE_FLAGS_TO_NAME_P
> +Predicate which indicates whether @code{ADDRESS_CLASS_TYPE_FLAGS_TO_NAME} has
> +been defined.
> +@xref{Target Architecture Definition, , Address Classes}.
>
> @item ADDRESS_TO_POINTER (@var{type}, @var{buf}, @var{addr})
> @findex ADDRESS_TO_POINTER