Translate DW_TAG_const_type and DW_TAG_volatile_type DIEs into LF_MODIFIER symbols.
gcc/ * dwarf2codeview.cc (struct codeview_custom_type): Add lf_modifier to union. (write_cv_padding, write_lf_modifier): New functions. (write_custom_types): Call write_lf_modifier. (get_type_num_const_type): New function. (get_type_num_volatile_type): Likewise. (get_type_num): Handle DW_TAG_const_type and DW_TAG_volatile_type DIEs. * dwarf2codeview.h (MOD_const, MOD_volatile): Define. (LF_MODIFIER): Likewise. --- gcc/dwarf2codeview.cc | 157 ++++++++++++++++++++++++++++++++++++++++++ gcc/dwarf2codeview.h | 5 ++ 2 files changed, 162 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 51401f2d5bc..05f5f60997e 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -183,6 +183,11 @@ struct codeview_custom_type uint32_t base_type; uint32_t attributes; } lf_pointer; + struct + { + uint32_t base_type; + uint16_t modifier; + } lf_modifier; }; }; @@ -903,6 +908,76 @@ write_lf_pointer (codeview_custom_type *t) asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num); } +/* All CodeView type definitions have to be aligned to a four-byte boundary, + so write some padding bytes if necessary. These have to be specific values: + f3, f2, f1. */ + +static void +write_cv_padding (size_t padding) +{ + if (padding == 4 || padding == 0) + return; + + if (padding == 3) + { + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, 0xf3); + putc ('\n', asm_out_file); + } + + if (padding >= 2) + { + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, 0xf2); + putc ('\n', asm_out_file); + } + + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, 0xf1); + putc ('\n', asm_out_file); +} + +/* Write an LF_MODIFIER type, representing a const and/or volatile modification + of another type. */ + +static void +write_lf_modifier (codeview_custom_type *t) +{ + /* This is lf_modifier in binutils and lfModifier in Microsoft's cvinfo.h: + + struct lf_modifier + { + uint16_t size; + uint16_t kind; + uint32_t base_type; + uint16_t modifier; + uint16_t padding; + } ATTRIBUTE_PACKED; + */ + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n", + t->num, t->num); + + asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, t->kind); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_modifier.base_type); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_modifier.modifier); + putc ('\n', asm_out_file); + + write_cv_padding (2); + + asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num); +} + /* Write the .debug$T section, which contains all of our custom type definitions. */ @@ -924,6 +999,10 @@ write_custom_types (void) case LF_POINTER: write_lf_pointer (custom_types); break; + + case LF_MODIFIER: + write_lf_modifier (custom_types); + break; } free (custom_types); @@ -1159,6 +1238,76 @@ get_type_num_pointer_type (dw_die_ref type) return ct->num; } +/* Process a DW_TAG_const_type DIE, adding an LF_MODIFIER type and returning + its number. */ + +static uint32_t +get_type_num_const_type (dw_die_ref type) +{ + dw_die_ref base_type; + uint32_t base_type_num; + codeview_custom_type *ct; + bool is_volatile = false; + + base_type = get_AT_ref (type, DW_AT_type); + if (!base_type) + return 0; + + /* Handle case when this is a const volatile type - we only need one + LF_MODIFIER for this. */ + if (dw_get_die_tag (base_type) == DW_TAG_volatile_type) + { + is_volatile = true; + + base_type = get_AT_ref (base_type, DW_AT_type); + if (!base_type) + return 0; + } + + base_type_num = get_type_num (base_type); + if (base_type_num == 0) + return 0; + + ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type)); + + ct->next = NULL; + ct->kind = LF_MODIFIER; + ct->lf_modifier.base_type = base_type_num; + ct->lf_modifier.modifier = MOD_const; + + if (is_volatile) + ct->lf_modifier.modifier |= MOD_volatile; + + add_custom_type (ct); + + return ct->num; +} + +/* Process a DW_TAG_volatile_type DIE, adding an LF_MODIFIER type and + returning its number. */ + +static uint32_t +get_type_num_volatile_type (dw_die_ref type) +{ + uint32_t base_type_num; + codeview_custom_type *ct; + + base_type_num = get_type_num (get_AT_ref (type, DW_AT_type)); + if (base_type_num == 0) + return 0; + + ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type)); + + ct->next = NULL; + ct->kind = LF_MODIFIER; + ct->lf_modifier.base_type = base_type_num; + ct->lf_modifier.modifier = MOD_volatile; + + add_custom_type (ct); + + return ct->num; +} + /* Process a DIE representing a type definition, add a CodeView type if necessary, and return its number. If it's something we can't handle, return 0. We keep a hash table so that we're not adding the same type multiple @@ -1201,6 +1350,14 @@ get_type_num (dw_die_ref type) t->num = get_type_num_pointer_type (type); break; + case DW_TAG_const_type: + t->num = get_type_num_const_type (type); + break; + + case DW_TAG_volatile_type: + t->num = get_type_num_volatile_type (type); + break; + default: t->num = 0; break; diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h index 0af4c98250f..d48cfbebc32 100644 --- a/gcc/dwarf2codeview.h +++ b/gcc/dwarf2codeview.h @@ -56,7 +56,12 @@ along with GCC; see the file COPYING3. If not see #define CV_PTR_NEAR32 0x0a #define CV_PTR_64 0x0c +/* LF_MODIFIER values. */ +#define MOD_const 0x1 +#define MOD_volatile 0x2 + /* Constants for type definitions. */ +#define LF_MODIFIER 0x1001 #define LF_POINTER 0x1002 /* Debug Format Interface. Used in dwarf2out.cc. */ -- 2.44.2