]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld/PDB: handle pointers to members
authorMark Harmstone <mark@harmstone.com>
Mon, 26 Aug 2024 12:58:56 +0000 (13:58 +0100)
committerMark Harmstone <mark@harmstone.com>
Mon, 26 Aug 2024 15:12:52 +0000 (16:12 +0100)
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.

ld/pdb.c
ld/pdb.h
ld/testsuite/ld-pe/pdb-types1-typelist.d
ld/testsuite/ld-pe/pdb-types1b.s
ld/testsuite/ld-pe/pdb.exp

index fcbe325603c9c2d0a7211c1e13f6284bed525d3b..a15da9db73d5f3151c8faff758d035b09fa95f2e 100644 (file)
--- 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;
       }
 
index b98d3868354d32c95d092650ddc44f033b751c14..a9b518a9f991c152630ceff2501f038993468767 100644 (file)
--- 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) */
index 1caa074ac56be1d9343b2b3fc5c1b89751b8a04f..e97c4f7aa581aa2061633421b72515b3fd3067ff 100644 (file)
@@ -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...........    
index 8bfc973c1c80a2cfc29c5b5b6043f83f0dd0736e..0cb301ce60b9b432984655fdff1dabb707ab9631 100644 (file)
 .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
 
 /* Type 102c, empty struct */
 .struct7:
-.short .types_end - .struct7 - 2
+.short .ptr5 - .struct7 - 2
 .short LF_STRUCTURE
 .short 0 /* no. members */
 .short 0 /* property */
 .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:
index b583e877f0176f445b8d3352d583ad99296b5981..7ca0fb66246fe481d5133b235e1a4cc4cbeee0bf 100644 (file)
@@ -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."