[PATCH 09/11] Handle arrays for CodeView

Translates DW_TAG_array_type DIEs into LF_ARRAY symbols.

gcc/
	* dwarf2codeview.cc (struct codeview_custom_type): Add lf_array to
	union.
	(write_lf_array): New function.
	(write_custom_types): Call write_lf_array.
	(get_type_num_array_type): New function.
	(get_type_num): Handle DW_TAG_array_type DIEs.
	* dwarf2codeview.h (LF_ARRAY): Define.
This commit is contained in:
Mark Harmstone 2024-06-25 17:31:24 -06:00 committed by Jeff Law
parent 0a5f559fb3
commit 3e64a687a3
2 changed files with 180 additions and 0 deletions

View file

@ -250,6 +250,12 @@ struct codeview_custom_type
codeview_integer length;
char *name;
} lf_structure;
struct
{
uint32_t element_type;
uint32_t index_type;
codeview_integer length_in_bytes;
} lf_array;
};
};
@ -1520,6 +1526,53 @@ write_lf_union (codeview_custom_type *t)
asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
}
/* Write an LF_ARRAY type. */
static void
write_lf_array (codeview_custom_type *t)
{
size_t leaf_len;
/* This is lf_array in binutils and lfArray in Microsoft's cvinfo.h:
struct lf_array
{
uint16_t size;
uint16_t kind;
uint32_t element_type;
uint32_t index_type;
uint16_t length_in_bytes;
char name[];
} 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_array.element_type);
putc ('\n', asm_out_file);
fputs (integer_asm_op (4, false), asm_out_file);
fprint_whex (asm_out_file, t->lf_array.index_type);
putc ('\n', asm_out_file);
leaf_len = 13 + write_cv_integer (&t->lf_array.length_in_bytes);
ASM_OUTPUT_ASCII (asm_out_file, "", 1);
write_cv_padding (4 - (leaf_len % 4));
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. */
@ -1562,6 +1615,10 @@ write_custom_types (void)
case LF_UNION:
write_lf_union (custom_types);
break;
case LF_ARRAY:
write_lf_array (custom_types);
break;
}
free (custom_types);
@ -2346,6 +2403,124 @@ get_type_num_struct (dw_die_ref type, bool in_struct, bool *is_fwd_ref)
return ct->num;
}
/* Process a DW_TAG_array_type DIE, adding an LF_ARRAY type and returning its
number. */
static uint32_t
get_type_num_array_type (dw_die_ref type, bool in_struct)
{
dw_die_ref base_type, t, first_child, c, *dimension_arr;
uint64_t size = 0;
unsigned int dimensions, i;
uint32_t element_type;
base_type = get_AT_ref (type, DW_AT_type);
if (!base_type)
return 0;
/* We need to know the size of our base type. Loop through until we find
it. */
t = base_type;
while (t && size == 0)
{
switch (dw_get_die_tag (t))
{
case DW_TAG_const_type:
case DW_TAG_volatile_type:
case DW_TAG_typedef:
case DW_TAG_enumeration_type:
t = get_AT_ref (t, DW_AT_type);
break;
case DW_TAG_base_type:
case DW_TAG_structure_type:
case DW_TAG_class_type:
case DW_TAG_union_type:
case DW_TAG_pointer_type:
size = get_AT_unsigned (t, DW_AT_byte_size);
break;
default:
return 0;
}
}
if (size == 0)
return 0;
first_child = dw_get_die_child (type);
if (!first_child)
return 0;
element_type = get_type_num (base_type, in_struct, false);
if (element_type == 0)
return 0;
/* Create an array of our DW_TAG_subrange_type children, in reverse order.
We have to do this because unlike DWARF CodeView doesn't have
multidimensional arrays, so instead we do arrays of arrays. */
dimensions = 0;
c = first_child;
do
{
c = dw_get_die_sib (c);
if (dw_get_die_tag (c) != DW_TAG_subrange_type)
continue;
dimensions++;
}
while (c != first_child);
if (dimensions == 0)
return 0;
dimension_arr = (dw_die_ref *) xmalloc (sizeof (dw_die_ref) * dimensions);
c = first_child;
i = 0;
do
{
c = dw_get_die_sib (c);
if (dw_get_die_tag (c) != DW_TAG_subrange_type)
continue;
dimension_arr[dimensions - i - 1] = c;
i++;
}
while (c != first_child);
/* Record an LF_ARRAY entry for each array dimension. If this leads to
duplicate types, ld will take care of it for us. */
for (i = 0; i < dimensions; i++)
{
codeview_custom_type *ct;
dw_die_ref index;
ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
size *= get_AT_unsigned (dimension_arr[i], DW_AT_upper_bound) + 1;
index = get_AT_ref (dimension_arr[i], DW_AT_type);
ct->next = NULL;
ct->kind = LF_ARRAY;
ct->lf_array.element_type = element_type;
ct->lf_array.index_type = get_type_num (index, in_struct, false);
ct->lf_array.length_in_bytes.neg = false;
ct->lf_array.length_in_bytes.num = size;
add_custom_type (ct);
element_type = ct->num;
}
free (dimension_arr);
return element_type;
}
/* 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
@ -2407,6 +2582,10 @@ get_type_num (dw_die_ref type, bool in_struct, bool no_fwd_ref)
num = get_type_num_struct (type, in_struct, &is_fwd_ref);
break;
case DW_TAG_array_type:
num = get_type_num_array_type (type, in_struct);
break;
default:
num = 0;
break;

View file

@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. If not see
#define LF_FIELDLIST 0x1203
#define LF_INDEX 0x1404
#define LF_ENUMERATE 0x1502
#define LF_ARRAY 0x1503
#define LF_CLASS 0x1504
#define LF_STRUCTURE 0x1505
#define LF_UNION 0x1506