From 5c9e42e0e9a8f881f8e1ac6b1133de148b26bb30 Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Mon, 26 Dec 2022 20:47:50 +0000 Subject: [PATCH] ld: Handle LF_VFTABLE types in PDBs --- ld/pdb.c | 20 +++++++++++++++ ld/pdb.h | 13 ++++++++++ ld/testsuite/ld-pe/pdb-types1-hashlist.d | 2 +- ld/testsuite/ld-pe/pdb-types1-typelist.d | 8 +++++- ld/testsuite/ld-pe/pdb-types1b.s | 32 +++++++++++++++++++++++- ld/testsuite/ld-pe/pdb.exp | 2 +- 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/ld/pdb.c b/ld/pdb.c index 60e9980407c..3934a920e84 100644 --- a/ld/pdb.c +++ b/ld/pdb.c @@ -3297,6 +3297,26 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num, /* Does not reference any types, nothing to be done. */ break; + case LF_VFTABLE: + { + struct lf_vftable *vft = (struct lf_vftable *) data; + + if (size < offsetof (struct lf_vftable, names)) + { + einfo (_("%P: warning: truncated CodeView type record" + " LF_VFTABLE\n")); + return false; + } + + if (!remap_type (&vft->type, map, type_num, num_types)) + return false; + + if (!remap_type (&vft->base_vftable, map, type_num, num_types)) + return false; + + break; + } + case LF_STRING_ID: { struct lf_string_id *str = (struct lf_string_id *) data; diff --git a/ld/pdb.h b/ld/pdb.h index ddf731b99c9..2efaa466efb 100644 --- a/ld/pdb.h +++ b/ld/pdb.h @@ -54,6 +54,7 @@ #define LF_METHOD 0x150f #define LF_NESTTYPE 0x1510 #define LF_ONEMETHOD 0x1511 +#define LF_VFTABLE 0x151d #define LF_FUNC_ID 0x1601 #define LF_MFUNC_ID 0x1602 #define LF_BUILDINFO 0x1603 @@ -578,6 +579,18 @@ struct lf_udt_mod_src_line uint16_t module_no; } ATTRIBUTE_PACKED; +/* lfVftable in cvinfo.h */ +struct lf_vftable +{ + uint16_t size; + uint16_t kind; + uint32_t type; + uint32_t base_vftable; + uint32_t offset; + uint32_t names_len; + char names[]; +} ATTRIBUTE_PACKED; + /* DATASYM32 in cvinfo.h */ struct datasym { diff --git a/ld/testsuite/ld-pe/pdb-types1-hashlist.d b/ld/testsuite/ld-pe/pdb-types1-hashlist.d index aa00aaf7593..7d314edb670 100644 --- a/ld/testsuite/ld-pe/pdb-types1-hashlist.d +++ b/ld/testsuite/ld-pe/pdb-types1-hashlist.d @@ -12,4 +12,4 @@ Contents of section .data: 0070 4d5e0200 8a940200 4b710300 6aa90300 * 0080 0a2c0300 67e10300 4a3d0300 fa460300 * 0090 db020200 ec4e0100 131e0300 fb120300 * - 00a0 aece0200 1db70100 * \ No newline at end of file + 00a0 aece0200 1db70100 99a30000 a8010100 * \ No newline at end of file diff --git a/ld/testsuite/ld-pe/pdb-types1-typelist.d b/ld/testsuite/ld-pe/pdb-types1-typelist.d index df862c3f837..248dda50d2d 100644 --- a/ld/testsuite/ld-pe/pdb-types1-typelist.d +++ b/ld/testsuite/ld-pe/pdb-types1-typelist.d @@ -71,4 +71,10 @@ Contents of section .data: 0420 25100000 0480c0d4 0100f2f1 0d150300 %............... 0430 23100000 00006400 26000312 01140000 #.....d.&....... 0440 25100000 00000000 028060ea 0480c0d4 %.........`..... - 0450 0100f2f1 0d150300 23100000 00006400 ........#.....d. \ No newline at end of file + 0450 0100f2f1 0d150300 23100000 00006400 ........#.....d. + 0460 1e000515 00008000 00000000 00000000 ................ + 0470 00000000 00004955 6e6b6e6f 776e00f1 ......IUnknown.. + 0480 3a001d15 2a100000 00000000 00000000 :...*........... + 0490 27000000 49556e6b 6e6f776e 00517565 '...IUnknown.Que + 04a0 7279496e 74657266 61636500 41646452 ryInterface.AddR + 04b0 65660052 656c6561 736500f1 ef.Release.. \ No newline at end of file diff --git a/ld/testsuite/ld-pe/pdb-types1b.s b/ld/testsuite/ld-pe/pdb-types1b.s index 544b338c251..bd227b12ebc 100644 --- a/ld/testsuite/ld-pe/pdb-types1b.s +++ b/ld/testsuite/ld-pe/pdb-types1b.s @@ -30,6 +30,7 @@ .equ LF_METHOD, 0x150f .equ LF_NESTTYPE, 0x1510 .equ LF_ONEMETHOD, 0x1511 +.equ LF_VFTABLE, 0x151d .equ LF_USHORT, 0x8002 .equ LF_LONG, 0x8003 @@ -559,7 +560,7 @@ # Type 1028, field list with virtual base class longstruct .fieldlist11: -.short .types_end - .fieldlist11 - 2 +.short .struct6 - .fieldlist11 - 2 .short LF_FIELDLIST .short LF_VBCLASS .short 0 # attributes @@ -577,4 +578,33 @@ .short 0 # offset .asciz "d" +# Type 1029, forward declaration of struct IUnknown +.struct6: +.short .vftable1 - .struct6 - 2 +.short LF_STRUCTURE +.short 0 # no. members +.short 0x80 # property (forward declaration) +.long 0 # field list +.long 0 # type derived from +.long 0 # type of vshape table +.short 0 # size +.asciz "IUnknown" # name +.byte 0xf1 # padding + +# Type 102a, virtual function table +.vftable1: +.short .types_end - .vftable1 - 2 +.short LF_VFTABLE +.long 0x1029 # type +.long 0 # base vftable +.long 0 # offset +.long .vftable1_names_end - .vftable1_names # length of names array +.vftable1_names: +.asciz "IUnknown" +.asciz "QueryInterface" +.asciz "AddRef" +.asciz "Release" +.vftable1_names_end: +.byte 0xf1 # padding + .types_end: diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp index fbc0cf949f1..b2016313e96 100644 --- a/ld/testsuite/ld-pe/pdb.exp +++ b/ld/testsuite/ld-pe/pdb.exp @@ -1029,7 +1029,7 @@ proc test5 { } { binary scan $data i end_type # end_type is one greater than the last type in the stream - if { $end_type != 0x102a } { + if { $end_type != 0x102c } { fail "Incorrect end type value in TPI stream." } else { pass "Correct end type value in TPI stream." -- 2.30.2