Add initial type alignment support
This adds some basic type alignment support to gdb. It changes struct type to store the alignment, and updates dwarf2read.c to handle DW_AT_alignment. It also adds a new gdbarch method and updates i386-tdep.c. None of this new functionality is used anywhere yet, so tests will wait until the next patch. 2018-04-30 Tom Tromey <tom@tromey.com> * i386-tdep.c (i386_type_align): New function. (i386_gdbarch_init): Update. * gdbarch.sh (type_align): New method. * gdbarch.c, gdbarch.h: Rebuild. * arch-utils.h (default_type_align): Declare. * arch-utils.c (default_type_align): New function. * gdbtypes.h (TYPE_ALIGN_BITS): New define. (struct type) <align_log2>: New field. <instance_flags>: Now a bitfield. (TYPE_RAW_ALIGN): New macro. (type_align, type_raw_align, set_type_align): Declare. * gdbtypes.c (type_align, type_raw_align, set_type_align): New functions. * dwarf2read.c (quirk_rust_enum): Set type alignment. (get_alignment, maybe_set_alignment): New functions. (read_structure_type, read_enumeration_type, read_array_type) (read_set_type, read_tag_pointer_type, read_tag_reference_type) (read_subrange_type, read_base_type): Set type alignment.
This commit is contained in:
parent
fe944acf8f
commit
2b4424c35b
10 changed files with 359 additions and 5 deletions
|
@ -1,3 +1,24 @@
|
||||||
|
2018-04-30 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
|
* i386-tdep.c (i386_type_align): New function.
|
||||||
|
(i386_gdbarch_init): Update.
|
||||||
|
* gdbarch.sh (type_align): New method.
|
||||||
|
* gdbarch.c, gdbarch.h: Rebuild.
|
||||||
|
* arch-utils.h (default_type_align): Declare.
|
||||||
|
* arch-utils.c (default_type_align): New function.
|
||||||
|
* gdbtypes.h (TYPE_ALIGN_BITS): New define.
|
||||||
|
(struct type) <align_log2>: New field.
|
||||||
|
<instance_flags>: Now a bitfield.
|
||||||
|
(TYPE_RAW_ALIGN): New macro.
|
||||||
|
(type_align, type_raw_align, set_type_align): Declare.
|
||||||
|
* gdbtypes.c (type_align, type_raw_align, set_type_align): New
|
||||||
|
functions.
|
||||||
|
* dwarf2read.c (quirk_rust_enum): Set type alignment.
|
||||||
|
(get_alignment, maybe_set_alignment): New functions.
|
||||||
|
(read_structure_type, read_enumeration_type, read_array_type)
|
||||||
|
(read_set_type, read_tag_pointer_type, read_tag_reference_type)
|
||||||
|
(read_subrange_type, read_base_type): Set type alignment.
|
||||||
|
|
||||||
2018-04-30 Simon Marchi <simon.marchi@ericsson.com>
|
2018-04-30 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
* dwarf2read.c (read_index_from_section): Use bool.
|
* dwarf2read.c (read_index_from_section): Use bool.
|
||||||
|
|
|
@ -987,6 +987,14 @@ default_in_indirect_branch_thunk (gdbarch *gdbarch, CORE_ADDR pc)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See arch-utils.h. */
|
||||||
|
|
||||||
|
ULONGEST
|
||||||
|
default_type_align (struct gdbarch *gdbarch, struct type *type)
|
||||||
|
{
|
||||||
|
return TYPE_LENGTH (check_typedef (type));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_gdbarch_utils (void)
|
_initialize_gdbarch_utils (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -267,4 +267,8 @@ extern CORE_ADDR gdbarch_skip_prologue_noexcept (gdbarch *gdbarch,
|
||||||
extern bool default_in_indirect_branch_thunk (gdbarch *gdbarch,
|
extern bool default_in_indirect_branch_thunk (gdbarch *gdbarch,
|
||||||
CORE_ADDR pc);
|
CORE_ADDR pc);
|
||||||
|
|
||||||
|
/* Default implementation of gdbarch type_align method. */
|
||||||
|
extern ULONGEST default_type_align (struct gdbarch *gdbarch,
|
||||||
|
struct type *type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
117
gdb/dwarf2read.c
117
gdb/dwarf2read.c
|
@ -9907,6 +9907,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
|
||||||
TYPE_FIELDS (union_type)
|
TYPE_FIELDS (union_type)
|
||||||
= (struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field));
|
= (struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field));
|
||||||
TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
|
TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
|
||||||
|
set_type_align (union_type, TYPE_RAW_ALIGN (type));
|
||||||
|
|
||||||
/* Put the discriminant must at index 0. */
|
/* Put the discriminant must at index 0. */
|
||||||
TYPE_FIELD_TYPE (union_type, 0) = field_type;
|
TYPE_FIELD_TYPE (union_type, 0) = field_type;
|
||||||
|
@ -9962,6 +9963,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
|
||||||
TYPE_CODE (union_type) = TYPE_CODE_UNION;
|
TYPE_CODE (union_type) = TYPE_CODE_UNION;
|
||||||
TYPE_NFIELDS (union_type) = TYPE_NFIELDS (type);
|
TYPE_NFIELDS (union_type) = TYPE_NFIELDS (type);
|
||||||
TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
|
TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
|
||||||
|
set_type_align (union_type, TYPE_RAW_ALIGN (type));
|
||||||
TYPE_FIELDS (union_type) = TYPE_FIELDS (type);
|
TYPE_FIELDS (union_type) = TYPE_FIELDS (type);
|
||||||
|
|
||||||
struct type *field_type = TYPE_FIELD_TYPE (union_type, 0);
|
struct type *field_type = TYPE_FIELD_TYPE (union_type, 0);
|
||||||
|
@ -10027,6 +10029,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
|
||||||
TYPE_CODE (union_type) = TYPE_CODE_UNION;
|
TYPE_CODE (union_type) = TYPE_CODE_UNION;
|
||||||
TYPE_NFIELDS (union_type) = 1 + TYPE_NFIELDS (type);
|
TYPE_NFIELDS (union_type) = 1 + TYPE_NFIELDS (type);
|
||||||
TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
|
TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
|
||||||
|
set_type_align (union_type, TYPE_RAW_ALIGN (type));
|
||||||
TYPE_FIELDS (union_type)
|
TYPE_FIELDS (union_type)
|
||||||
= (struct field *) TYPE_ZALLOC (union_type,
|
= (struct field *) TYPE_ZALLOC (union_type,
|
||||||
(TYPE_NFIELDS (union_type)
|
(TYPE_NFIELDS (union_type)
|
||||||
|
@ -15578,6 +15581,82 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
|
||||||
smash_to_methodptr_type (type, new_type);
|
smash_to_methodptr_type (type, new_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the DIE has a DW_AT_alignment attribute, return its value, doing
|
||||||
|
appropriate error checking and issuing complaints if there is a
|
||||||
|
problem. */
|
||||||
|
|
||||||
|
static ULONGEST
|
||||||
|
get_alignment (struct dwarf2_cu *cu, struct die_info *die)
|
||||||
|
{
|
||||||
|
struct attribute *attr = dwarf2_attr (die, DW_AT_alignment, cu);
|
||||||
|
|
||||||
|
if (attr == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!attr_form_is_constant (attr))
|
||||||
|
{
|
||||||
|
complaint (&symfile_complaints,
|
||||||
|
_("DW_AT_alignment must have constant form"
|
||||||
|
" - DIE at %s [in module %s]"),
|
||||||
|
sect_offset_str (die->sect_off),
|
||||||
|
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONGEST align;
|
||||||
|
if (attr->form == DW_FORM_sdata)
|
||||||
|
{
|
||||||
|
LONGEST val = DW_SND (attr);
|
||||||
|
if (val < 0)
|
||||||
|
{
|
||||||
|
complaint (&symfile_complaints,
|
||||||
|
_("DW_AT_alignment value must not be negative"
|
||||||
|
" - DIE at %s [in module %s]"),
|
||||||
|
sect_offset_str (die->sect_off),
|
||||||
|
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
align = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
align = DW_UNSND (attr);
|
||||||
|
|
||||||
|
if (align == 0)
|
||||||
|
{
|
||||||
|
complaint (&symfile_complaints,
|
||||||
|
_("DW_AT_alignment value must not be zero"
|
||||||
|
" - DIE at %s [in module %s]"),
|
||||||
|
sect_offset_str (die->sect_off),
|
||||||
|
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((align & (align - 1)) != 0)
|
||||||
|
{
|
||||||
|
complaint (&symfile_complaints,
|
||||||
|
_("DW_AT_alignment value must be a power of 2"
|
||||||
|
" - DIE at %s [in module %s]"),
|
||||||
|
sect_offset_str (die->sect_off),
|
||||||
|
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return align;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the DIE has a DW_AT_alignment attribute, use its value to set
|
||||||
|
the alignment for TYPE. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_set_alignment (struct dwarf2_cu *cu, struct die_info *die,
|
||||||
|
struct type *type)
|
||||||
|
{
|
||||||
|
if (!set_type_align (type, get_alignment (cu, die)))
|
||||||
|
complaint (&symfile_complaints,
|
||||||
|
_("DW_AT_alignment value too large"
|
||||||
|
" - DIE at %s [in module %s]"),
|
||||||
|
sect_offset_str (die->sect_off),
|
||||||
|
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
|
||||||
|
}
|
||||||
|
|
||||||
/* Called when we find the DIE that starts a structure or union scope
|
/* Called when we find the DIE that starts a structure or union scope
|
||||||
(definition) to create a type for the structure or union. Fill in
|
(definition) to create a type for the structure or union. Fill in
|
||||||
|
@ -15688,6 +15767,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
TYPE_LENGTH (type) = 0;
|
TYPE_LENGTH (type) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybe_set_alignment (cu, die, type);
|
||||||
|
|
||||||
if (producer_is_icc_lt_14 (cu) && (TYPE_LENGTH (type) == 0))
|
if (producer_is_icc_lt_14 (cu) && (TYPE_LENGTH (type) == 0))
|
||||||
{
|
{
|
||||||
/* ICC<14 does not output the required DW_AT_declaration on
|
/* ICC<14 does not output the required DW_AT_declaration on
|
||||||
|
@ -16132,6 +16213,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
TYPE_LENGTH (type) = 0;
|
TYPE_LENGTH (type) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybe_set_alignment (cu, die, type);
|
||||||
|
|
||||||
/* The enumeration DIE can be incomplete. In Ada, any type can be
|
/* The enumeration DIE can be incomplete. In Ada, any type can be
|
||||||
declared as private in the package spec, and then defined only
|
declared as private in the package spec, and then defined only
|
||||||
inside the package body. Such types are known as Taft Amendment
|
inside the package body. Such types are known as Taft Amendment
|
||||||
|
@ -16157,6 +16240,9 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
|
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
|
||||||
if (TYPE_LENGTH (type) == 0)
|
if (TYPE_LENGTH (type) == 0)
|
||||||
TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
|
TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
|
||||||
|
if (TYPE_RAW_ALIGN (type) == 0
|
||||||
|
&& TYPE_RAW_ALIGN (TYPE_TARGET_TYPE (type)) != 0)
|
||||||
|
set_type_align (type, TYPE_RAW_ALIGN (TYPE_TARGET_TYPE (type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
|
TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
|
||||||
|
@ -16381,6 +16467,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
if (name)
|
if (name)
|
||||||
TYPE_NAME (type) = name;
|
TYPE_NAME (type) = name;
|
||||||
|
|
||||||
|
maybe_set_alignment (cu, die, type);
|
||||||
|
|
||||||
/* Install the type in the die. */
|
/* Install the type in the die. */
|
||||||
set_die_type (die, type, cu);
|
set_die_type (die, type, cu);
|
||||||
|
|
||||||
|
@ -16445,6 +16533,8 @@ read_set_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
if (attr)
|
if (attr)
|
||||||
TYPE_LENGTH (set_type) = DW_UNSND (attr);
|
TYPE_LENGTH (set_type) = DW_UNSND (attr);
|
||||||
|
|
||||||
|
maybe_set_alignment (cu, die, set_type);
|
||||||
|
|
||||||
return set_die_type (die, set_type, cu);
|
return set_die_type (die, set_type, cu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16816,10 +16906,15 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
else
|
else
|
||||||
addr_class = DW_ADDR_none;
|
addr_class = DW_ADDR_none;
|
||||||
|
|
||||||
/* If the pointer size or address class is different than the
|
ULONGEST alignment = get_alignment (cu, die);
|
||||||
default, create a type variant marked as such and set the
|
|
||||||
length accordingly. */
|
/* If the pointer size, alignment, or address class is different
|
||||||
if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
|
than the default, create a type variant marked as such and set
|
||||||
|
the length accordingly. */
|
||||||
|
if (TYPE_LENGTH (type) != byte_size
|
||||||
|
|| (alignment != 0 && TYPE_RAW_ALIGN (type) != 0
|
||||||
|
&& alignment != TYPE_RAW_ALIGN (type))
|
||||||
|
|| addr_class != DW_ADDR_none)
|
||||||
{
|
{
|
||||||
if (gdbarch_address_class_type_flags_p (gdbarch))
|
if (gdbarch_address_class_type_flags_p (gdbarch))
|
||||||
{
|
{
|
||||||
|
@ -16836,6 +16931,14 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
complaint (&symfile_complaints,
|
complaint (&symfile_complaints,
|
||||||
_("invalid pointer size %d"), byte_size);
|
_("invalid pointer size %d"), byte_size);
|
||||||
}
|
}
|
||||||
|
else if (TYPE_RAW_ALIGN (type) != alignment)
|
||||||
|
{
|
||||||
|
complaint (&symfile_complaints,
|
||||||
|
_("Invalid DW_AT_alignment"
|
||||||
|
" - DIE at %s [in module %s]"),
|
||||||
|
sect_offset_str (die->sect_off),
|
||||||
|
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Should we also complain about unhandled address classes? */
|
/* Should we also complain about unhandled address classes? */
|
||||||
|
@ -16843,6 +16946,7 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPE_LENGTH (type) = byte_size;
|
TYPE_LENGTH (type) = byte_size;
|
||||||
|
set_type_align (type, alignment);
|
||||||
return set_die_type (die, type, cu);
|
return set_die_type (die, type, cu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16912,6 +17016,7 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
|
||||||
{
|
{
|
||||||
TYPE_LENGTH (type) = cu_header->addr_size;
|
TYPE_LENGTH (type) = cu_header->addr_size;
|
||||||
}
|
}
|
||||||
|
maybe_set_alignment (cu, die, type);
|
||||||
return set_die_type (die, type, cu);
|
return set_die_type (die, type, cu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17398,6 +17503,8 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
if (name && strcmp (name, "char") == 0)
|
if (name && strcmp (name, "char") == 0)
|
||||||
TYPE_NOSIGN (type) = 1;
|
TYPE_NOSIGN (type) = 1;
|
||||||
|
|
||||||
|
maybe_set_alignment (cu, die, type);
|
||||||
|
|
||||||
return set_die_type (die, type, cu);
|
return set_die_type (die, type, cu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17660,6 +17767,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||||
if (attr)
|
if (attr)
|
||||||
TYPE_LENGTH (range_type) = DW_UNSND (attr);
|
TYPE_LENGTH (range_type) = DW_UNSND (attr);
|
||||||
|
|
||||||
|
maybe_set_alignment (cu, die, range_type);
|
||||||
|
|
||||||
set_die_type (die, range_type, cu);
|
set_die_type (die, range_type, cu);
|
||||||
|
|
||||||
/* set_die_type should be already done. */
|
/* set_die_type should be already done. */
|
||||||
|
|
|
@ -353,6 +353,7 @@ struct gdbarch
|
||||||
gdbarch_addressable_memory_unit_size_ftype *addressable_memory_unit_size;
|
gdbarch_addressable_memory_unit_size_ftype *addressable_memory_unit_size;
|
||||||
char ** disassembler_options;
|
char ** disassembler_options;
|
||||||
const disasm_options_t * valid_disassembler_options;
|
const disasm_options_t * valid_disassembler_options;
|
||||||
|
gdbarch_type_align_ftype *type_align;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create a new ``struct gdbarch'' based on information provided by
|
/* Create a new ``struct gdbarch'' based on information provided by
|
||||||
|
@ -465,6 +466,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
|
||||||
gdbarch->gcc_target_options = default_gcc_target_options;
|
gdbarch->gcc_target_options = default_gcc_target_options;
|
||||||
gdbarch->gnu_triplet_regexp = default_gnu_triplet_regexp;
|
gdbarch->gnu_triplet_regexp = default_gnu_triplet_regexp;
|
||||||
gdbarch->addressable_memory_unit_size = default_addressable_memory_unit_size;
|
gdbarch->addressable_memory_unit_size = default_addressable_memory_unit_size;
|
||||||
|
gdbarch->type_align = default_type_align;
|
||||||
/* gdbarch_alloc() */
|
/* gdbarch_alloc() */
|
||||||
|
|
||||||
return gdbarch;
|
return gdbarch;
|
||||||
|
@ -716,6 +718,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||||
/* Skip verify of addressable_memory_unit_size, invalid_p == 0 */
|
/* Skip verify of addressable_memory_unit_size, invalid_p == 0 */
|
||||||
/* Skip verify of disassembler_options, invalid_p == 0 */
|
/* Skip verify of disassembler_options, invalid_p == 0 */
|
||||||
/* Skip verify of valid_disassembler_options, invalid_p == 0 */
|
/* Skip verify of valid_disassembler_options, invalid_p == 0 */
|
||||||
|
/* Skip verify of type_align, invalid_p == 0 */
|
||||||
if (!log.empty ())
|
if (!log.empty ())
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
_("verify_gdbarch: the following are invalid ...%s"),
|
_("verify_gdbarch: the following are invalid ...%s"),
|
||||||
|
@ -1441,6 +1444,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||||
fprintf_unfiltered (file,
|
fprintf_unfiltered (file,
|
||||||
"gdbarch_dump: target_desc = %s\n",
|
"gdbarch_dump: target_desc = %s\n",
|
||||||
host_address_to_string (gdbarch->target_desc));
|
host_address_to_string (gdbarch->target_desc));
|
||||||
|
fprintf_unfiltered (file,
|
||||||
|
"gdbarch_dump: type_align = <%s>\n",
|
||||||
|
host_address_to_string (gdbarch->type_align));
|
||||||
fprintf_unfiltered (file,
|
fprintf_unfiltered (file,
|
||||||
"gdbarch_dump: gdbarch_unwind_pc_p() = %d\n",
|
"gdbarch_dump: gdbarch_unwind_pc_p() = %d\n",
|
||||||
gdbarch_unwind_pc_p (gdbarch));
|
gdbarch_unwind_pc_p (gdbarch));
|
||||||
|
@ -5100,6 +5106,23 @@ set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch,
|
||||||
gdbarch->valid_disassembler_options = valid_disassembler_options;
|
gdbarch->valid_disassembler_options = valid_disassembler_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONGEST
|
||||||
|
gdbarch_type_align (struct gdbarch *gdbarch, struct type *type)
|
||||||
|
{
|
||||||
|
gdb_assert (gdbarch != NULL);
|
||||||
|
gdb_assert (gdbarch->type_align != NULL);
|
||||||
|
if (gdbarch_debug >= 2)
|
||||||
|
fprintf_unfiltered (gdb_stdlog, "gdbarch_type_align called\n");
|
||||||
|
return gdbarch->type_align (gdbarch, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_gdbarch_type_align (struct gdbarch *gdbarch,
|
||||||
|
gdbarch_type_align_ftype type_align)
|
||||||
|
{
|
||||||
|
gdbarch->type_align = type_align;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Keep a registry of per-architecture data-pointers required by GDB
|
/* Keep a registry of per-architecture data-pointers required by GDB
|
||||||
modules. */
|
modules. */
|
||||||
|
|
|
@ -1560,6 +1560,12 @@ extern void set_gdbarch_disassembler_options (struct gdbarch *gdbarch, char ** d
|
||||||
extern const disasm_options_t * gdbarch_valid_disassembler_options (struct gdbarch *gdbarch);
|
extern const disasm_options_t * gdbarch_valid_disassembler_options (struct gdbarch *gdbarch);
|
||||||
extern void set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch, const disasm_options_t * valid_disassembler_options);
|
extern void set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch, const disasm_options_t * valid_disassembler_options);
|
||||||
|
|
||||||
|
/* Type alignment. */
|
||||||
|
|
||||||
|
typedef ULONGEST (gdbarch_type_align_ftype) (struct gdbarch *gdbarch, struct type *type);
|
||||||
|
extern ULONGEST gdbarch_type_align (struct gdbarch *gdbarch, struct type *type);
|
||||||
|
extern void set_gdbarch_type_align (struct gdbarch *gdbarch, gdbarch_type_align_ftype *type_align);
|
||||||
|
|
||||||
/* Definition for an unknown syscall, used basically in error-cases. */
|
/* Definition for an unknown syscall, used basically in error-cases. */
|
||||||
#define UNKNOWN_SYSCALL (-1)
|
#define UNKNOWN_SYSCALL (-1)
|
||||||
|
|
||||||
|
|
|
@ -1163,6 +1163,9 @@ m;int;addressable_memory_unit_size;void;;;default_addressable_memory_unit_size;;
|
||||||
v;char **;disassembler_options;;;0;0;;0;pstring_ptr (gdbarch->disassembler_options)
|
v;char **;disassembler_options;;;0;0;;0;pstring_ptr (gdbarch->disassembler_options)
|
||||||
v;const disasm_options_t *;valid_disassembler_options;;;0;0;;0;host_address_to_string (gdbarch->valid_disassembler_options)
|
v;const disasm_options_t *;valid_disassembler_options;;;0;0;;0;host_address_to_string (gdbarch->valid_disassembler_options)
|
||||||
|
|
||||||
|
# Type alignment.
|
||||||
|
m;ULONGEST;type_align;struct type *type;type;;default_type_align;;0
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
122
gdb/gdbtypes.c
122
gdb/gdbtypes.c
|
@ -3013,6 +3013,128 @@ init_pointer_type (struct objfile *objfile,
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See gdbtypes.h. */
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
type_raw_align (struct type *type)
|
||||||
|
{
|
||||||
|
if (type->align_log2 != 0)
|
||||||
|
return 1 << (type->align_log2 - 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See gdbtypes.h. */
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
type_align (struct type *type)
|
||||||
|
{
|
||||||
|
unsigned raw_align = type_raw_align (type);
|
||||||
|
if (raw_align != 0)
|
||||||
|
return raw_align;
|
||||||
|
|
||||||
|
ULONGEST align = 0;
|
||||||
|
switch (TYPE_CODE (type))
|
||||||
|
{
|
||||||
|
case TYPE_CODE_PTR:
|
||||||
|
case TYPE_CODE_FUNC:
|
||||||
|
case TYPE_CODE_FLAGS:
|
||||||
|
case TYPE_CODE_INT:
|
||||||
|
case TYPE_CODE_FLT:
|
||||||
|
case TYPE_CODE_ENUM:
|
||||||
|
case TYPE_CODE_REF:
|
||||||
|
case TYPE_CODE_RVALUE_REF:
|
||||||
|
case TYPE_CODE_CHAR:
|
||||||
|
case TYPE_CODE_BOOL:
|
||||||
|
case TYPE_CODE_DECFLOAT:
|
||||||
|
{
|
||||||
|
struct gdbarch *arch = get_type_arch (type);
|
||||||
|
align = gdbarch_type_align (arch, type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_CODE_ARRAY:
|
||||||
|
case TYPE_CODE_COMPLEX:
|
||||||
|
case TYPE_CODE_TYPEDEF:
|
||||||
|
align = type_align (TYPE_TARGET_TYPE (type));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_CODE_STRUCT:
|
||||||
|
case TYPE_CODE_UNION:
|
||||||
|
{
|
||||||
|
if (TYPE_NFIELDS (type) == 0)
|
||||||
|
{
|
||||||
|
/* An empty struct has alignment 1. */
|
||||||
|
align = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < TYPE_NFIELDS (type); ++i)
|
||||||
|
{
|
||||||
|
ULONGEST f_align = type_align (TYPE_FIELD_TYPE (type, i));
|
||||||
|
if (f_align == 0)
|
||||||
|
{
|
||||||
|
/* Don't pretend we know something we don't. */
|
||||||
|
align = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (f_align > align)
|
||||||
|
align = f_align;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_CODE_SET:
|
||||||
|
case TYPE_CODE_RANGE:
|
||||||
|
case TYPE_CODE_STRING:
|
||||||
|
/* Not sure what to do here, and these can't appear in C or C++
|
||||||
|
anyway. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_CODE_METHODPTR:
|
||||||
|
case TYPE_CODE_MEMBERPTR:
|
||||||
|
align = TYPE_LENGTH (type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_CODE_VOID:
|
||||||
|
align = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_CODE_ERROR:
|
||||||
|
case TYPE_CODE_METHOD:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((align & (align - 1)) != 0)
|
||||||
|
{
|
||||||
|
/* Not a power of 2, so pass. */
|
||||||
|
align = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return align;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See gdbtypes.h. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
set_type_align (struct type *type, ULONGEST align)
|
||||||
|
{
|
||||||
|
/* Must be a power of 2. Zero is ok. */
|
||||||
|
gdb_assert ((align & (align - 1)) == 0);
|
||||||
|
|
||||||
|
unsigned result = 0;
|
||||||
|
while (align != 0)
|
||||||
|
{
|
||||||
|
++result;
|
||||||
|
align >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result >= (1 << TYPE_ALIGN_BITS))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
type->align_log2 = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Queries on types. */
|
/* Queries on types. */
|
||||||
|
|
||||||
|
|
|
@ -802,6 +802,10 @@ struct main_type
|
||||||
struct dynamic_prop_list *dyn_prop_list;
|
struct dynamic_prop_list *dyn_prop_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* * Number of bits allocated for alignment. */
|
||||||
|
|
||||||
|
#define TYPE_ALIGN_BITS 8
|
||||||
|
|
||||||
/* * A ``struct type'' describes a particular instance of a type, with
|
/* * A ``struct type'' describes a particular instance of a type, with
|
||||||
some particular qualification. */
|
some particular qualification. */
|
||||||
|
|
||||||
|
@ -831,6 +835,14 @@ struct type
|
||||||
|
|
||||||
struct type *chain;
|
struct type *chain;
|
||||||
|
|
||||||
|
/* * The alignment for this type. Zero means that the alignment was
|
||||||
|
not specified in the debug info. Note that this is stored in a
|
||||||
|
funny way: as the log base 2 (plus 1) of the alignment; so a
|
||||||
|
value of 1 means the alignment is 1, and a value of 9 means the
|
||||||
|
alignment is 256. */
|
||||||
|
|
||||||
|
unsigned align_log2 : TYPE_ALIGN_BITS;
|
||||||
|
|
||||||
/* * Flags specific to this instance of the type, indicating where
|
/* * Flags specific to this instance of the type, indicating where
|
||||||
on the ring we are.
|
on the ring we are.
|
||||||
|
|
||||||
|
@ -841,7 +853,7 @@ struct type
|
||||||
instance flags are completely inherited from the target type. No
|
instance flags are completely inherited from the target type. No
|
||||||
qualifiers can be cleared by the typedef. See also
|
qualifiers can be cleared by the typedef. See also
|
||||||
check_typedef. */
|
check_typedef. */
|
||||||
int instance_flags;
|
unsigned instance_flags : 9;
|
||||||
|
|
||||||
/* * Length of storage for a value of this type. The value is the
|
/* * Length of storage for a value of this type. The value is the
|
||||||
expression in host bytes of what sizeof(type) would return. This
|
expression in host bytes of what sizeof(type) would return. This
|
||||||
|
@ -1292,6 +1304,26 @@ extern void allocate_gnat_aux_type (struct type *);
|
||||||
so you only have to call check_typedef once. Since allocate_value
|
so you only have to call check_typedef once. Since allocate_value
|
||||||
calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */
|
calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */
|
||||||
#define TYPE_LENGTH(thistype) (thistype)->length
|
#define TYPE_LENGTH(thistype) (thistype)->length
|
||||||
|
|
||||||
|
/* * Return the alignment of the type in target addressable memory
|
||||||
|
units, or 0 if no alignment was specified. */
|
||||||
|
#define TYPE_RAW_ALIGN(thistype) type_raw_align (thistype)
|
||||||
|
|
||||||
|
/* * Return the alignment of the type in target addressable memory
|
||||||
|
units, or 0 if no alignment was specified. */
|
||||||
|
extern unsigned type_raw_align (struct type *);
|
||||||
|
|
||||||
|
/* * Return the alignment of the type in target addressable memory
|
||||||
|
units. Return 0 if the alignment cannot be determined; but note
|
||||||
|
that this makes an effort to compute the alignment even it it was
|
||||||
|
not specified in the debug info. */
|
||||||
|
extern unsigned type_align (struct type *);
|
||||||
|
|
||||||
|
/* * Set the alignment of the type. The alignment must be a power of
|
||||||
|
2. Returns false if the given value does not fit in the available
|
||||||
|
space in struct type. */
|
||||||
|
extern bool set_type_align (struct type *, ULONGEST);
|
||||||
|
|
||||||
/* * Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you want the real
|
/* * Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you want the real
|
||||||
type, you need to do TYPE_CODE (check_type (this_type)). */
|
type, you need to do TYPE_CODE (check_type (this_type)). */
|
||||||
#define TYPE_CODE(thistype) TYPE_MAIN_TYPE(thistype)->code
|
#define TYPE_CODE(thistype) TYPE_MAIN_TYPE(thistype)->code
|
||||||
|
|
|
@ -8346,6 +8346,31 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
|
||||||
return valid_p;
|
return valid_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Implement the type_align gdbarch function. */
|
||||||
|
|
||||||
|
static ULONGEST
|
||||||
|
i386_type_align (struct gdbarch *gdbarch, struct type *type)
|
||||||
|
{
|
||||||
|
type = check_typedef (type);
|
||||||
|
|
||||||
|
if (gdbarch_ptr_bit (gdbarch) == 32)
|
||||||
|
{
|
||||||
|
if ((TYPE_CODE (type) == TYPE_CODE_INT
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||||
|
&& TYPE_LENGTH (type) > 4)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
/* Handle x86's funny long double. */
|
||||||
|
if (TYPE_CODE (type) == TYPE_CODE_FLT
|
||||||
|
&& gdbarch_long_double_bit (gdbarch) == TYPE_LENGTH (type) * 8)
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TYPE_LENGTH (type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Note: This is called for both i386 and amd64. */
|
/* Note: This is called for both i386 and amd64. */
|
||||||
|
|
||||||
|
@ -8405,6 +8430,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||||
tdep->record_regmap = i386_record_regmap;
|
tdep->record_regmap = i386_record_regmap;
|
||||||
|
|
||||||
set_gdbarch_long_long_align_bit (gdbarch, 32);
|
set_gdbarch_long_long_align_bit (gdbarch, 32);
|
||||||
|
set_gdbarch_type_align (gdbarch, i386_type_align);
|
||||||
|
|
||||||
/* The format used for `long double' on almost all i386 targets is
|
/* The format used for `long double' on almost all i386 targets is
|
||||||
the i387 extended floating-point format. In fact, of all targets
|
the i387 extended floating-point format. In fact, of all targets
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue