aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2024-08-26 13:58:56 +0100
committerMark Harmstone <mark@harmstone.com>2024-08-26 16:12:52 +0100
commit91555eddd48726592478fc3fbe4a4dbce31384bf (patch)
tree6ba3974eae808ed8e174c00bbd21ef4058508261
parenta733b2c90463231d9fb8b143e168403d96efe54f (diff)
downloadgdb-91555eddd48726592478fc3fbe4a4dbce31384bf.zip
gdb-91555eddd48726592478fc3fbe4a4dbce31384bf.tar.gz
gdb-91555eddd48726592478fc3fbe4a4dbce31384bf.tar.bz2
ld/PDB: handle pointers to members
If the CV_PTR_MODE_PMEM or CV_PTR_MODE_PMFUNC flags were set in an LF_POINTER entry's attributes, there's a few extra bytes on the end that we weren't accounting for. Change handle_type so that we remap the containing_class field if it's present, and add a test for this.
-rw-r--r--ld/pdb.c17
-rw-r--r--ld/pdb.h9
-rw-r--r--ld/testsuite/ld-pe/pdb-types1-typelist.d4
-rw-r--r--ld/testsuite/ld-pe/pdb-types1b.s30
-rw-r--r--ld/testsuite/ld-pe/pdb.exp2
5 files changed, 59 insertions, 3 deletions
diff --git a/ld/pdb.c b/ld/pdb.c
index fcbe325..a15da9d 100644
--- a/ld/pdb.c
+++ b/ld/pdb.c
@@ -2375,6 +2375,7 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
case LF_POINTER:
{
struct lf_pointer *ptr = (struct lf_pointer *) data;
+ uint32_t attributes;
if (size < offsetof (struct lf_pointer, attributes))
{
@@ -2386,6 +2387,22 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
if (!remap_type (&ptr->base_type, map, type_num, num_types))
return false;
+ attributes = bfd_getl32 (&ptr->attributes);
+
+ if ((attributes & CV_PTR_MODE_MASK) == CV_PTR_MODE_PMEM
+ || (attributes & CV_PTR_MODE_MASK) == CV_PTR_MODE_PMFUNC)
+ {
+ if (size < offsetof (struct lf_pointer, ptr_to_mem_type))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_POINTER\n"));
+ return false;
+ }
+
+ if (!remap_type (&ptr->containing_class, map, type_num, num_types))
+ return false;
+ }
+
break;
}
diff --git a/ld/pdb.h b/ld/pdb.h
index b98d386..a9b518a 100644
--- a/ld/pdb.h
+++ b/ld/pdb.h
@@ -303,6 +303,11 @@ struct lf_modifier
uint16_t padding;
} ATTRIBUTE_PACKED;
+/* enum CV_ptrmode_e in cvinfo.h, shifted by 5 for the lfPointerAttr bitfield */
+#define CV_PTR_MODE_MASK 0xe0
+#define CV_PTR_MODE_PMEM 0x40
+#define CV_PTR_MODE_PMFUNC 0x60
+
/* lfPointer in cvinfo.h */
struct lf_pointer
{
@@ -310,6 +315,10 @@ struct lf_pointer
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;
/* lfArgList in cvinfo.h (used for both LF_ARGLIST and LF_SUBSTR_LIST) */
diff --git a/ld/testsuite/ld-pe/pdb-types1-typelist.d b/ld/testsuite/ld-pe/pdb-types1-typelist.d
index 1caa074..e97c4f7 100644
--- a/ld/testsuite/ld-pe/pdb-types1-typelist.d
+++ b/ld/testsuite/ld-pe/pdb-types1-typelist.d
@@ -80,4 +80,6 @@ Contents of section .data:
04b0 65660052 656c6561 736500f1 02000312 ef.Release......
04c0 22000515 00000000 2c100000 00000000 ".......,.......
04d0 00000000 0100656d 7074795f 73747275 ......empty_stru
- 04e0 637400f1 ct..
+ 04e0 637400f1 12000210 11100000 6c000100 ct..........l...
+ 04f0 0d100000 0500f2f1 12000210 75000000 ............u...
+ 0500 4c000100 0d100000 0100f2f1 L...........
diff --git a/ld/testsuite/ld-pe/pdb-types1b.s b/ld/testsuite/ld-pe/pdb-types1b.s
index 8bfc973..0cb301c 100644
--- a/ld/testsuite/ld-pe/pdb-types1b.s
+++ b/ld/testsuite/ld-pe/pdb-types1b.s
@@ -40,6 +40,12 @@
.equ CV_PTR_NEAR32, 0xa
.equ CV_PTR_64, 0xc
+.equ CV_PTR_MODE_PMEM, 0x40
+.equ CV_PTR_MODE_PMFUNC, 0x60
+
+.equ CV_PMTYPE_D_Single, 0x01
+.equ CV_PMTYPE_F_Single, 0x05
+
.section ".debug$T", "rn"
.long CV_SIGNATURE_C13
@@ -614,7 +620,7 @@
/* Type 102c, empty struct */
.struct7:
-.short .types_end - .struct7 - 2
+.short .ptr5 - .struct7 - 2
.short LF_STRUCTURE
.short 0 /* no. members */
.short 0 /* property */
@@ -625,4 +631,26 @@
.asciz "empty_struct" /* name */
.byte 0xf1 /* padding */
+/* Type 102d, pointer to member function method2 in struct foo */
+.ptr5:
+.short .ptr6 - .ptr5 - 2
+.short LF_POINTER
+.long 0x1010 /* base type */
+.long (8 << 13) | CV_PTR_MODE_PMFUNC | CV_PTR_64 /* attributes */
+.long 0x100c /* containing class */
+.short CV_PMTYPE_F_Single /* member function, single inheritance */
+.byte 0xf2 /* padding */
+.byte 0xf1 /* padding */
+
+/* Type 102e, pointer to member num in struct foo */
+.ptr6:
+.short .types_end - .ptr6 - 2
+.short LF_POINTER
+.long T_UINT4 /* base type */
+.long (8 << 13) | CV_PTR_MODE_PMEM | CV_PTR_64 /* attributes */
+.long 0x100c /* containing class */
+.short CV_PMTYPE_D_Single /* member data, single inheritance */
+.byte 0xf2 /* padding */
+.byte 0xf1 /* padding */
+
.types_end:
diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp
index b583e87..7ca0fb6 100644
--- a/ld/testsuite/ld-pe/pdb.exp
+++ b/ld/testsuite/ld-pe/pdb.exp
@@ -1036,7 +1036,7 @@ proc test5 { } {
binary scan $data i end_type
# end_type is one greater than the last type in the stream
- if { $end_type != 0x102e } {
+ if { $end_type != 0x1030 } {
fail "Incorrect end type value in TPI stream."
} else {
pass "Correct end type value in TPI stream."