diff options
author | Mark Harmstone <mark@harmstone.com> | 2024-06-23 21:30:08 -0600 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro.com> | 2024-06-23 21:30:08 -0600 |
commit | 35cca2ccd908960d789533ddb93bb1bea5e71305 (patch) | |
tree | 2e27c0d6cd5962c21335604205d4b84fe3f5be4b /gcc/dwarf2codeview.cc | |
parent | de2ade6908c6f18b821d6d25b4f4833c850fa19c (diff) | |
download | gcc-35cca2ccd908960d789533ddb93bb1bea5e71305.zip gcc-35cca2ccd908960d789533ddb93bb1bea5e71305.tar.gz gcc-35cca2ccd908960d789533ddb93bb1bea5e71305.tar.bz2 |
[PATCH 04/11] Handle pointers for CodeView
Translates DW_TAG_pointer_type DIEs into LF_POINTER symbols, which get
output into the .debug$T section.
gcc/
* dwarf2codeview.cc (FIRST_TYPE): Define.
(struct codeview_custom_type): New structure.
(custom_types, last_custom_type): New variables.
(get_type_num): Prototype.
(write_lf_pointer, write_custom_types): New functions.
(codeview_debug_finish): Call write_custom_types.
(add_custom_type, get_type_num_pointer_type): New functions.
(get_type_num): Handle DW_TAG_pointer_type DIEs.
* dwarf2codeview.h (T_VOID): Define.
(CV_POINTER_32, CV_POINTER_64): Likewise.
(T_32PVOID, T_64PVOID): Likewise.
(CV_PTR_NEAR32, CV_PTR64, LF_POINTER): Likewise.
Diffstat (limited to 'gcc/dwarf2codeview.cc')
-rw-r--r-- | gcc/dwarf2codeview.cc | 179 |
1 files changed, 175 insertions, 4 deletions
diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 5006a17..51401f2 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see #define CV_CFL_C 0x00 #define CV_CFL_CXX 0x01 +#define FIRST_TYPE 0x1000 + #define LINE_LABEL "Lcvline" #define END_FUNC_LABEL "Lcvendfunc" #define SYMBOL_START_LABEL "Lcvsymstart" @@ -168,6 +170,22 @@ struct die_hasher : free_ptr_hash <codeview_type> } }; +struct codeview_custom_type +{ + struct codeview_custom_type *next; + uint32_t num; + uint16_t kind; + + union + { + struct + { + uint32_t base_type; + uint32_t attributes; + } lf_pointer; + }; +}; + static unsigned int line_label_num; static unsigned int func_label_num; static unsigned int sym_label_num; @@ -181,6 +199,9 @@ static const char* last_filename; static uint32_t last_file_id; static codeview_symbol *sym, *last_sym; static hash_table<die_hasher> *types_htab; +static codeview_custom_type *custom_types, *last_custom_type; + +static uint32_t get_type_num (dw_die_ref type); /* Record new line number against the current function. */ @@ -845,6 +866,71 @@ write_codeview_symbols (void) asm_fprintf (asm_out_file, "%LLcv_syms_end:\n"); } +/* Write an LF_POINTER type. */ + +static void +write_lf_pointer (codeview_custom_type *t) +{ + /* This is lf_pointer in binutils and lfPointer in Microsoft's cvinfo.h: + + struct lf_pointer + { + uint16_t size; + uint16_t kind; + uint32_t base_type; + uint32_t attributes; + } 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_pointer.base_type); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_pointer.attributes); + putc ('\n', asm_out_file); + + 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. */ + +static void +write_custom_types (void) +{ + targetm.asm_out.named_section (".debug$T", SECTION_DEBUG, NULL); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, CV_SIGNATURE_C13); + putc ('\n', asm_out_file); + + while (custom_types) + { + codeview_custom_type *n = custom_types->next; + + switch (custom_types->kind) + { + case LF_POINTER: + write_lf_pointer (custom_types); + break; + } + + free (custom_types); + custom_types = n; + } +} + /* Finish CodeView debug info emission. */ void @@ -861,6 +947,9 @@ codeview_debug_finish (void) write_line_numbers (); write_codeview_symbols (); + if (custom_types) + write_custom_types (); + if (types_htab) delete types_htab; } @@ -993,10 +1082,88 @@ get_type_num_base_type (dw_die_ref type) } } -/* Process a DIE representing a type definition 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 times - though if we do it's not - disastrous, as ld will deduplicate everything for us. */ +/* Add a new codeview_custom_type to our singly-linked custom_types list. */ + +static void +add_custom_type (codeview_custom_type *ct) +{ + uint32_t num; + + if (last_custom_type) + { + num = last_custom_type->num + 1; + last_custom_type->next = ct; + } + else + { + num = FIRST_TYPE; + custom_types = ct; + } + + last_custom_type = ct; + + ct->num = num; +} + +/* Process a DW_TAG_pointer_type DIE. If this is a pointer to a builtin + type, return the predefined constant for this. Otherwise, add a new + LF_POINTER type and return its number. */ + +static uint32_t +get_type_num_pointer_type (dw_die_ref type) +{ + uint32_t base_type_num, byte_size; + dw_die_ref base_type; + codeview_custom_type *ct; + + byte_size = get_AT_unsigned (type, DW_AT_byte_size); + if (byte_size != 4 && byte_size != 8) + return 0; + + base_type = get_AT_ref (type, DW_AT_type); + + /* If DW_AT_type is not set, this must be a void pointer. */ + if (!base_type) + return byte_size == 4 ? T_32PVOID : T_64PVOID; + + base_type_num = get_type_num (base_type); + if (base_type_num == 0) + return 0; + + /* Pointers to builtin types have predefined type numbers, with the top byte + determining the pointer size - 0x0400 for a 32-bit pointer and 0x0600 + for 64-bit. */ + if (base_type_num < FIRST_TYPE && !(base_type_num & 0xff00)) + { + if (byte_size == 4) + return CV_POINTER_32 | base_type_num; + else + return CV_POINTER_64 | base_type_num; + } + + ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type)); + + ct->next = NULL; + ct->kind = LF_POINTER; + ct->lf_pointer.base_type = base_type_num; + + if (byte_size == 4) + ct->lf_pointer.attributes = CV_PTR_NEAR32; + else + ct->lf_pointer.attributes = CV_PTR_64; + + ct->lf_pointer.attributes |= byte_size << 13; + + 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 + times - though if we do it's not disastrous, as ld will deduplicate + everything for us. */ static uint32_t get_type_num (dw_die_ref type) @@ -1030,6 +1197,10 @@ get_type_num (dw_die_ref type) t->num = get_type_num (get_AT_ref (type, DW_AT_type)); break; + case DW_TAG_pointer_type: + t->num = get_type_num_pointer_type (type); + break; + default: t->num = 0; break; |