Skip to content

Commit

Permalink
Write LF_POINTER CodeView types for pointers to member functions or data
Browse files Browse the repository at this point in the history
Translate DW_TAG_ptr_to_member_type DIEs into special extended
LF_POINTER CodeView types.

gcc/
	* dwarf2codeview.cc (struct codeview_custom_type): Add new fields to
	lf_pointer struct in union.
	(write_lf_pointer): Write containing_class and ptr_to_mem_type if
	applicable.
	(get_type_num_subroutine_type): Write correct containing_class_type if
	this is a pointer to a member function.
	(get_type_num_ptr_to_member_type): New function.
	(get_type_num): Call get_type_num_ptr_to_member_type.
	* dwarf2codeview.h (CV_PTR_MODE_MASK, CV_PTR_MODE_PMEM): Define.
	(CV_PTR_MODE_PMFUNC, CV_PMTYPE_D_Single, CV_PMTYPE_F_Single): Likewise.
  • Loading branch information
maharmstone committed Nov 5, 2024
1 parent 7ac2407 commit b0f4f55
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
103 changes: 103 additions & 0 deletions gcc/dwarf2codeview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,8 @@ struct codeview_custom_type
{
uint32_t base_type;
uint32_t attributes;
uint32_t containing_class;
uint16_t ptr_to_mem_type;
} lf_pointer;
struct
{
Expand Down Expand Up @@ -3393,6 +3395,10 @@ write_lf_pointer (codeview_custom_type *t)
uint16_t kind;
uint32_t base_type;
uint32_t attributes;
(following only if CV_PTR_MODE_PMEM or CV_PTR_MODE_PMFUNC in attributes)
uint32_t containing_class;
uint16_t ptr_to_mem_type;
uint16_t padding;
} ATTRIBUTE_PACKED;
*/

Expand All @@ -3414,6 +3420,20 @@ write_lf_pointer (codeview_custom_type *t)
fprint_whex (asm_out_file, t->lf_pointer.attributes);
putc ('\n', asm_out_file);

if ((t->lf_pointer.attributes & CV_PTR_MODE_MASK) == CV_PTR_MODE_PMEM
|| (t->lf_pointer.attributes & CV_PTR_MODE_MASK) == CV_PTR_MODE_PMFUNC)
{
fputs (integer_asm_op (4, false), asm_out_file);
fprint_whex (asm_out_file, t->lf_pointer.containing_class);
putc ('\n', asm_out_file);

fputs (integer_asm_op (2, false), asm_out_file);
fprint_whex (asm_out_file, t->lf_pointer.ptr_to_mem_type);
putc ('\n', asm_out_file);

write_cv_padding (2);
}

asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
}

Expand Down Expand Up @@ -5886,6 +5906,30 @@ get_type_num_subroutine_type (dw_die_ref type, bool in_struct,
return_type = T_VOID;
}

/* Handle pointer to member function. */
if (containing_class_type == 0)
{
dw_die_ref obj_ptr = get_AT_ref (type, DW_AT_object_pointer);

if (obj_ptr)
{
dw_die_ref obj_ptr_type = get_AT_ref (obj_ptr, DW_AT_type);

if (obj_ptr_type
&& dw_get_die_tag (obj_ptr_type) == DW_TAG_pointer_type)
{
dw_die_ref cont_class = get_AT_ref (obj_ptr_type, DW_AT_type);

if (dw_get_die_tag (cont_class) == DW_TAG_const_type)
cont_class = get_AT_ref (cont_class, DW_AT_type);

containing_class_type = get_type_num (cont_class, in_struct,
false);
this_type = get_type_num (obj_ptr_type, in_struct, false);
}
}
}

/* Count the arguments. */

first_child = dw_get_die_child (type);
Expand Down Expand Up @@ -6121,6 +6165,61 @@ get_type_num_array_type (dw_die_ref type, bool in_struct)
return element_type;
}

/* Translate a DW_TAG_ptr_to_member_type DIE, that is a pointer to member
function or field, into an LF_POINTER record. */

static uint32_t
get_type_num_ptr_to_member_type (dw_die_ref type, bool in_struct)
{
uint32_t base_type_num;
uint32_t containing_class;
dw_die_ref base_type;
codeview_custom_type *ct;

base_type = get_AT_ref (type, DW_AT_type);

base_type_num = get_type_num (base_type, in_struct, false);
if (base_type_num == 0)
return 0;

containing_class = get_type_num (get_AT_ref (type, DW_AT_containing_type),
in_struct, false);

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 (TARGET_64BIT)
{
ct->lf_pointer.attributes = CV_PTR_64;
ct->lf_pointer.attributes |= 8 << 13;
}
else
{
ct->lf_pointer.attributes = CV_PTR_NEAR32;
ct->lf_pointer.attributes |= 4 << 13;
}

ct->lf_pointer.containing_class = containing_class;

if (base_type && dw_get_die_tag (base_type) == DW_TAG_subroutine_type)
{
ct->lf_pointer.attributes |= CV_PTR_MODE_PMFUNC;
ct->lf_pointer.ptr_to_mem_type = CV_PMTYPE_F_Single;
}
else
{
ct->lf_pointer.attributes |= CV_PTR_MODE_PMEM;
ct->lf_pointer.ptr_to_mem_type = CV_PMTYPE_D_Single;
}

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
Expand Down Expand Up @@ -6198,6 +6297,10 @@ get_type_num (dw_die_ref type, bool in_struct, bool no_fwd_ref)
num = get_type_num_subroutine_type (type, in_struct, 0, 0, 0);
break;

case DW_TAG_ptr_to_member_type:
num = get_type_num_ptr_to_member_type (type, in_struct);
break;

default:
num = 0;
break;
Expand Down
9 changes: 9 additions & 0 deletions gcc/dwarf2codeview.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,18 @@ along with GCC; see the file COPYING3. If not see
/* LF_POINTER attributes. */
#define CV_PTR_NEAR32 0x0a
#define CV_PTR_64 0x0c

/* enum CV_ptrmode_e in cvinfo.h, shifted by 5 for the lfPointerAttr bitfield */
#define CV_PTR_MODE_MASK 0xe0
#define CV_PTR_MODE_LVREF 0x20
#define CV_PTR_MODE_PMEM 0x40
#define CV_PTR_MODE_PMFUNC 0x60
#define CV_PTR_MODE_RVREF 0x80

/* enum CV_pmtype_e in in cvinfo.h */
#define CV_PMTYPE_D_Single 0x01
#define CV_PMTYPE_F_Single 0x05

/* LF_MODIFIER values. */
#define MOD_const 0x1
#define MOD_volatile 0x2
Expand Down

0 comments on commit b0f4f55

Please sign in to comment.