[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:
parent
0a5f559fb3
commit
3e64a687a3
2 changed files with 180 additions and 0 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue