aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2022-12-09 01:52:39 +0000
committerAlan Modra <amodra@gmail.com>2022-12-23 21:02:21 +1030
commit5d9c033689ad1ef19ed2d2fd7f30bfd0bc473d9d (patch)
treebf3884504f3d9ee575321ffa232a1adc45f5ad47
parent81814b6f5bd7be2ef719181286b375dcdd8a0f00 (diff)
downloadgdb-5d9c033689ad1ef19ed2d2fd7f30bfd0bc473d9d.zip
gdb-5d9c033689ad1ef19ed2d2fd7f30bfd0bc473d9d.tar.gz
gdb-5d9c033689ad1ef19ed2d2fd7f30bfd0bc473d9d.tar.bz2
ld: Copy other symbols into PDB file
-rw-r--r--ld/pdb.c362
-rw-r--r--ld/pdb.h179
-rw-r--r--ld/testsuite/ld-pe/pdb-syms2-symbols1.d38
-rw-r--r--ld/testsuite/ld-pe/pdb-syms2.s430
-rw-r--r--ld/testsuite/ld-pe/pdb.exp67
5 files changed, 1076 insertions, 0 deletions
diff --git a/ld/pdb.c b/ld/pdb.c
index 375ff35..5bcf056 100644
--- a/ld/pdb.c
+++ b/ld/pdb.c
@@ -908,11 +908,15 @@ find_end_of_scope (uint8_t *data, uint32_t size)
{
case S_GPROC32:
case S_LPROC32:
+ case S_BLOCK32:
+ case S_INLINESITE:
+ case S_THUNK32:
scope_level++;
break;
case S_END:
case S_PROC_ID_END:
+ case S_INLINESITE_END:
scope_level--;
if (scope_level == 0)
@@ -961,6 +965,7 @@ parse_symbols (uint8_t *data, uint32_t size, uint8_t **buf,
{
uint8_t *orig_buf = *buf;
unsigned int scope_level = 0;
+ uint8_t *scope = NULL;
while (size >= sizeof (uint16_t))
{
@@ -1206,6 +1211,8 @@ parse_symbols (uint8_t *data, uint32_t size, uint8_t **buf,
free (ref);
+ scope = *buf;
+
memcpy (*buf, proc, len);
*buf += len;
@@ -1321,16 +1328,343 @@ parse_symbols (uint8_t *data, uint32_t size, uint8_t **buf,
}
case S_END:
+ case S_INLINESITE_END:
case S_PROC_ID_END:
memcpy (*buf, data, len);
if (type == S_PROC_ID_END) /* transform to S_END */
bfd_putl16 (S_END, *buf + sizeof (uint16_t));
+ /* Reset scope variable back to the address of the previous
+ scope start. */
+ if (scope)
+ {
+ uint32_t parent;
+ uint16_t scope_start_type =
+ bfd_getl16 (scope + sizeof (uint16_t));
+
+ switch (scope_start_type)
+ {
+ case S_GPROC32:
+ case S_LPROC32:
+ parent = bfd_getl32 (scope + offsetof (struct procsym,
+ parent));
+ break;
+
+ case S_BLOCK32:
+ parent = bfd_getl32 (scope + offsetof (struct blocksym,
+ parent));
+ break;
+
+ case S_INLINESITE:
+ parent = bfd_getl32 (scope + offsetof (struct inline_site,
+ parent));
+ break;
+
+ case S_THUNK32:
+ parent = bfd_getl32 (scope + offsetof (struct thunk,
+ parent));
+ break;
+
+ default:
+ einfo (_("%P: warning: unexpected CodeView scope start"
+ " record %v\n"), scope_start_type);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (parent == 0)
+ scope = NULL;
+ else
+ scope = orig_buf + parent - sizeof (uint32_t);
+ }
+
*buf += len;
scope_level--;
break;
+ case S_BUILDINFO:
+ {
+ struct buildinfosym *bi = (struct buildinfosym *) data;
+
+ if (len < sizeof (struct buildinfosym))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_BUILDINFO\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (!remap_symbol_type (&bi->type, map, num_types))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ break;
+ }
+
+ case S_BLOCK32:
+ {
+ struct blocksym *bl = (struct blocksym *) data;
+ uint8_t *endptr;
+ uint32_t end;
+
+ if (len < offsetof (struct blocksym, name))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_BLOCK32\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ bfd_putl32 (scope - orig_buf + sizeof (uint32_t), &bl->parent);
+
+ endptr = find_end_of_scope (data, size);
+
+ if (!endptr)
+ {
+ einfo (_("%P: warning: could not find end of"
+ " S_BLOCK32 record\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ end = *buf - orig_buf + sizeof (uint32_t) + endptr - data;
+ bfd_putl32 (end, &bl->end);
+
+ scope = *buf;
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ scope_level++;
+
+ break;
+ }
+
+ case S_BPREL32:
+ {
+ struct bprelsym *bp = (struct bprelsym *) data;
+
+ if (len < offsetof (struct bprelsym, name))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_BPREL32\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (!remap_symbol_type (&bp->type, map, num_types))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ break;
+ }
+
+ case S_REGISTER:
+ {
+ struct regsym *reg = (struct regsym *) data;
+
+ if (len < offsetof (struct regsym, name))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_REGISTER\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (!remap_symbol_type (&reg->type, map, num_types))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ break;
+ }
+
+ case S_REGREL32:
+ {
+ struct regrel *rr = (struct regrel *) data;
+
+ if (len < offsetof (struct regrel, name))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_REGREL32\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (!remap_symbol_type (&rr->type, map, num_types))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ break;
+ }
+
+ case S_LOCAL:
+ {
+ struct localsym *l = (struct localsym *) data;
+
+ if (len < offsetof (struct localsym, name))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_LOCAL\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (!remap_symbol_type (&l->type, map, num_types))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ break;
+ }
+
+ case S_INLINESITE:
+ {
+ struct inline_site *is = (struct inline_site *) data;
+ uint8_t *endptr;
+ uint32_t end;
+
+ if (len < offsetof (struct inline_site, binary_annotations))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_INLINESITE\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ bfd_putl32 (scope - orig_buf + sizeof (uint32_t), &is->parent);
+
+ endptr = find_end_of_scope (data, size);
+
+ if (!endptr)
+ {
+ einfo (_("%P: warning: could not find end of"
+ " S_INLINESITE record\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ end = *buf - orig_buf + sizeof (uint32_t) + endptr - data;
+ bfd_putl32 (end, &is->end);
+
+ if (!remap_symbol_type (&is->inlinee, map, num_types))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ scope = *buf;
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ scope_level++;
+
+ break;
+ }
+
+ case S_THUNK32:
+ {
+ struct thunk *th = (struct thunk *) data;
+ uint8_t *endptr;
+ uint32_t end;
+
+ if (len < offsetof (struct thunk, name))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_THUNK32\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ bfd_putl32 (scope - orig_buf + sizeof (uint32_t), &th->parent);
+
+ endptr = find_end_of_scope (data, size);
+
+ if (!endptr)
+ {
+ einfo (_("%P: warning: could not find end of"
+ " S_THUNK32 record\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ end = *buf - orig_buf + sizeof (uint32_t) + endptr - data;
+ bfd_putl32 (end, &th->end);
+
+ scope = *buf;
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ scope_level++;
+
+ break;
+ }
+
+ case S_HEAPALLOCSITE:
+ {
+ struct heap_alloc_site *has = (struct heap_alloc_site *) data;
+
+ if (len < sizeof (struct heap_alloc_site))
+ {
+ einfo (_("%P: warning: truncated CodeView record"
+ " S_HEAPALLOCSITE\n"));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (!remap_symbol_type (&has->type, map, num_types))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ memcpy (*buf, data, len);
+ *buf += len;
+
+ break;
+ }
+
+ case S_OBJNAME: /* just copy */
+ case S_COMPILE3:
+ case S_UNAMESPACE:
+ case S_FRAMEPROC:
+ case S_FRAMECOOKIE:
+ case S_LABEL32:
+ case S_DEFRANGE_REGISTER_REL:
+ case S_DEFRANGE_FRAMEPOINTER_REL:
+ case S_DEFRANGE_SUBFIELD_REGISTER:
+ case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
+ case S_DEFRANGE_REGISTER:
+ memcpy (*buf, data, len);
+ *buf += len;
+ break;
+
default:
einfo (_("%P: warning: unrecognized CodeView record %v\n"), type);
bfd_set_error (bfd_error_bad_value);
@@ -1441,12 +1775,40 @@ calculate_symbols_size (uint8_t *data, uint32_t size, uint32_t *sym_size)
*sym_size += len;
break;
+ case S_BLOCK32: /* always copied */
+ case S_INLINESITE:
+ case S_THUNK32:
+ *sym_size += len;
+ scope_level++;
+ break;
+
case S_END: /* always copied */
case S_PROC_ID_END:
+ case S_INLINESITE_END:
*sym_size += len;
scope_level--;
break;
+ case S_OBJNAME: /* always copied */
+ case S_COMPILE3:
+ case S_UNAMESPACE:
+ case S_FRAMEPROC:
+ case S_FRAMECOOKIE:
+ case S_LABEL32:
+ case S_BUILDINFO:
+ case S_BPREL32:
+ case S_REGISTER:
+ case S_REGREL32:
+ case S_LOCAL:
+ case S_DEFRANGE_REGISTER_REL:
+ case S_DEFRANGE_FRAMEPOINTER_REL:
+ case S_DEFRANGE_SUBFIELD_REGISTER:
+ case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
+ case S_DEFRANGE_REGISTER:
+ case S_HEAPALLOCSITE:
+ *sym_size += len;
+ break;
+
default:
einfo (_("%P: warning: unrecognized CodeView record %v\n"), type);
return false;
diff --git a/ld/pdb.h b/ld/pdb.h
index 9048b5f..ddb9b86 100644
--- a/ld/pdb.h
+++ b/ld/pdb.h
@@ -71,20 +71,41 @@
#define LF_UQUADWORD 0x800a
#define S_END 0x0006
+#define S_FRAMEPROC 0x1012
+#define S_OBJNAME 0x1101
+#define S_THUNK32 0x1102
+#define S_BLOCK32 0x1103
+#define S_LABEL32 0x1105
+#define S_REGISTER 0x1106
#define S_CONSTANT 0x1107
#define S_UDT 0x1108
+#define S_BPREL32 0x110b
#define S_LDATA32 0x110c
#define S_GDATA32 0x110d
#define S_PUB32 0x110e
#define S_LPROC32 0x110f
#define S_GPROC32 0x1110
+#define S_REGREL32 0x1111
#define S_LTHREAD32 0x1112
#define S_GTHREAD32 0x1113
+#define S_UNAMESPACE 0x1124
#define S_PROCREF 0x1125
#define S_LPROCREF 0x1127
+#define S_FRAMECOOKIE 0x113a
+#define S_COMPILE3 0x113c
+#define S_LOCAL 0x113e
+#define S_DEFRANGE_REGISTER 0x1141
+#define S_DEFRANGE_FRAMEPOINTER_REL 0x1142
+#define S_DEFRANGE_SUBFIELD_REGISTER 0x1143
+#define S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE 0x1144
+#define S_DEFRANGE_REGISTER_REL 0x1145
#define S_LPROC32_ID 0x1146
#define S_GPROC32_ID 0x1147
+#define S_BUILDINFO 0x114c
+#define S_INLINESITE 0x114d
+#define S_INLINESITE_END 0x114e
#define S_PROC_ID_END 0x114f
+#define S_HEAPALLOCSITE 0x115e
/* PDBStream70 in pdb1.h */
struct pdb_stream_70
@@ -617,6 +638,164 @@ struct constsym
char name[];
} ATTRIBUTE_PACKED;
+/* BUILDINFOSYM in cvinfo.h */
+struct buildinfosym
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t type;
+} ATTRIBUTE_PACKED;
+
+/* BLOCKSYM32 in cvinfo.h */
+struct blocksym
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t parent;
+ uint32_t end;
+ uint32_t len;
+ uint32_t offset;
+ uint16_t section;
+ char name[];
+} ATTRIBUTE_PACKED;
+
+/* BPRELSYM32 in cvinfo.h */
+struct bprelsym
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t bp_offset;
+ uint32_t type;
+ char name[];
+} ATTRIBUTE_PACKED;
+
+/* REGSYM in cvinfo.h */
+struct regsym
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t type;
+ uint16_t reg;
+ char name[];
+} ATTRIBUTE_PACKED;
+
+/* REGREL32 in cvinfo.h */
+struct regrel
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t offset;
+ uint32_t type;
+ uint16_t reg;
+ char name[];
+} ATTRIBUTE_PACKED;
+
+/* LOCALSYM in cvinfo.h */
+struct localsym
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t type;
+ uint16_t flags;
+ char name[];
+} ATTRIBUTE_PACKED;
+
+/* CV_LVAR_ADDR_RANGE in cvinfo.h */
+struct lvar_addr_range
+{
+ uint32_t offset;
+ uint16_t section;
+ uint16_t length;
+} ATTRIBUTE_PACKED;
+
+/* CV_LVAR_ADDR_GAP in cvinfo.h */
+struct lvar_addr_gap {
+ uint16_t offset;
+ uint16_t length;
+} ATTRIBUTE_PACKED;
+
+/* DEFRANGESYMREGISTERREL in cvinfo.h */
+struct defrange_register_rel
+{
+ uint16_t size;
+ uint16_t kind;
+ uint16_t reg;
+ uint16_t offset_parent;
+ uint32_t offset_register;
+ struct lvar_addr_range range;
+ struct lvar_addr_gap gaps[];
+} ATTRIBUTE_PACKED;
+
+/* DEFRANGESYMFRAMEPOINTERREL in cvinfo.h */
+struct defrange_framepointer_rel
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t offset;
+ struct lvar_addr_range range;
+ struct lvar_addr_gap gaps[];
+} ATTRIBUTE_PACKED;
+
+/* DEFRANGESYMSUBFIELDREGISTER in cvinfo.h */
+struct defrange_subfield_register
+{
+ uint16_t size;
+ uint16_t kind;
+ uint16_t reg;
+ uint16_t attributes;
+ uint32_t offset_parent;
+ struct lvar_addr_range range;
+ struct lvar_addr_gap gaps[];
+} ATTRIBUTE_PACKED;
+
+/* DEFRANGESYMREGISTER in cvinfo.h */
+struct defrange_register
+{
+ uint16_t size;
+ uint16_t kind;
+ uint16_t reg;
+ uint16_t attributes;
+ struct lvar_addr_range range;
+ struct lvar_addr_gap gaps[];
+} ATTRIBUTE_PACKED;
+
+/* INLINESITESYM in cvinfo.h */
+struct inline_site
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t parent;
+ uint32_t end;
+ uint32_t inlinee;
+ uint8_t binary_annotations[];
+} ATTRIBUTE_PACKED;
+
+/* THUNKSYM32 in cvinfo.h */
+struct thunk
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t parent;
+ uint32_t end;
+ uint32_t next;
+ uint32_t offset;
+ uint16_t section;
+ uint16_t length;
+ uint8_t thunk_type;
+ char name[];
+} ATTRIBUTE_PACKED;
+
+/* HEAPALLOCSITE in cvinfo.h */
+struct heap_alloc_site
+{
+ uint16_t size;
+ uint16_t kind;
+ uint32_t offset;
+ uint16_t section;
+ uint16_t length;
+ uint32_t type;
+} ATTRIBUTE_PACKED;
+
extern bool create_pdb_file (bfd *, const char *, const unsigned char *);
#endif
diff --git a/ld/testsuite/ld-pe/pdb-syms2-symbols1.d b/ld/testsuite/ld-pe/pdb-syms2-symbols1.d
new file mode 100644
index 0000000..34132d1
--- /dev/null
+++ b/ld/testsuite/ld-pe/pdb-syms2-symbols1.d
@@ -0,0 +1,38 @@
+
+*: file format binary
+
+Contents of section .data:
+ 0000 04000000 0e000111 00000000 73796d73 ............syms
+ 0010 332e6f00 22003c11 00000000 d0000000 3.o.".<.........
+ 0020 00000000 00000000 00000000 0000474e ..............GN
+ 0030 55204153 00f3f2f1 06002411 73746400 U AS......$.std.
+ 0040 06004c11 05100000 2e001011 00000000 ..L.............
+ 0050 18020000 00000000 06000000 00000000 ................
+ 0060 00000000 01100000 00000000 01000070 ...............p
+ 0070 726f6331 00f3f2f1 1e001210 00000000 roc1............
+ 0080 00000000 00000000 00000000 00000000 ................
+ 0090 00000000 0000f2f1 0e003a11 08000000 ..........:.....
+ 00a0 48010000 000000f1 0e000b11 04000000 H...............
+ 00b0 02100000 666f6f00 0e000611 02100000 ....foo.........
+ 00c0 48016261 7200f2f1 12001111 04000000 H.bar...........
+ 00d0 02100000 48016261 7a00f2f1 12003e11 ....H.baz.....>.
+ 00e0 02100000 00006c6f 63616c31 00f3f2f1 ......local1....
+ 00f0 16004511 48010000 00000000 01000000 ..E.H...........
+ 0100 01000400 02000100 12003e11 02100000 ..........>.....
+ 0110 00006c6f 63616c32 00f3f2f1 12004211 ..local2......B.
+ 0120 04000000 01000000 01000400 02000100 ................
+ 0130 12003e11 02100000 00006c6f 63616c33 ..>.......local3
+ 0140 00f3f2f1 16004311 48010000 04000000 ......C.H.......
+ 0150 01000000 01000400 02000100 12003e11 ..............>.
+ 0160 02100000 00006c6f 63616c34 00f3f2f1 ......local4....
+ 0170 06004411 04000000 12003e11 02100000 ..D.......>.....
+ 0180 00006c6f 63616c35 00f3f2f1 12004111 ..local5......A.
+ 0190 48010000 01000000 01000400 02000100 H...............
+ 01a0 0e004d11 48000000 b0010000 06100000 ..M.H...........
+ 01b0 02004e11 16000311 48000000 e0010000 ..N.....H.......
+ 01c0 04000000 01000000 010000f1 12000511 ................
+ 01d0 02000000 0100006c 6162656c 00f3f2f1 .......label....
+ 01e0 02000600 1e000211 48000000 04020000 ........H.......
+ 01f0 00000000 06000000 01000100 00746875 .............thu
+ 0200 6e6b00f1 02000600 0e005e11 04000000 nk........^.....
+ 0210 01000100 02100000 02000600 00000000 ................ \ No newline at end of file
diff --git a/ld/testsuite/ld-pe/pdb-syms2.s b/ld/testsuite/ld-pe/pdb-syms2.s
new file mode 100644
index 0000000..ec677ea
--- /dev/null
+++ b/ld/testsuite/ld-pe/pdb-syms2.s
@@ -0,0 +1,430 @@
+.equ CV_SIGNATURE_C13, 4
+.equ DEBUG_S_SYMBOLS, 0xf1
+
+.equ T_VOID, 0x0003
+.equ T_UINT4, 0x0075
+
+.equ LF_MODIFIER, 0x1001
+.equ LF_PROCEDURE, 0x1008
+.equ LF_ARGLIST, 0x1201
+.equ LF_FUNC_ID, 0x1601
+.equ LF_BUILDINFO, 0x1603
+.equ LF_STRING_ID, 0x1605
+
+.equ S_END, 0x0006
+.equ S_FRAMEPROC, 0x1012
+.equ S_OBJNAME, 0x1101
+.equ S_THUNK32, 0x1102
+.equ S_BLOCK32, 0x1103
+.equ S_LABEL32, 0x1105
+.equ S_REGISTER, 0x1106
+.equ S_BPREL32, 0x110b
+.equ S_GPROC32, 0x1110
+.equ S_REGREL32, 0x1111
+.equ S_UNAMESPACE, 0x1124
+.equ S_FRAMECOOKIE, 0x113a
+.equ S_COMPILE3, 0x113c
+.equ S_LOCAL, 0x113e
+.equ S_DEFRANGE_REGISTER, 0x1141
+.equ S_DEFRANGE_FRAMEPOINTER_REL, 0x1142
+.equ S_DEFRANGE_SUBFIELD_REGISTER, 0x1143
+.equ S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE, 0x1144
+.equ S_DEFRANGE_REGISTER_REL, 0x1145
+.equ S_BUILDINFO, 0x114c
+.equ S_INLINESITE, 0x114d
+.equ S_INLINESITE_END, 0x114e
+.equ S_HEAPALLOCSITE, 0x115e
+
+.equ CV_AMD64_RAX, 328
+.equ CV_CFL_AMD64, 0xd0
+
+.section ".debug$S", "rn"
+
+.long CV_SIGNATURE_C13
+
+.long DEBUG_S_SYMBOLS
+.long .syms_end - .syms_start
+
+.syms_start:
+
+.objname1:
+.short .compile1 - .objname1 - 2
+.short S_OBJNAME
+.long 0 # signature
+.asciz "syms3.o"
+
+.compile1:
+.short .unamespace1 - .compile1 - 2
+.short S_COMPILE3
+.long 0 # flags
+.short CV_CFL_AMD64 # target processor
+.short 0 # frontend major
+.short 0 # frontend minor
+.short 0 # frontend build
+.short 0 # frontend qfe
+.short 0 # backend major
+.short 0 # backend minor
+.short 0 # backend build
+.short 0 # backend qfe
+.asciz "GNU AS"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.unamespace1:
+.short .sbuildinfo1 - .unamespace1 - 2
+.short S_UNAMESPACE
+.asciz "std"
+
+.sbuildinfo1:
+.short .gproc1 - .sbuildinfo1 - 2
+.short S_BUILDINFO
+.long 0x1007 # type
+
+.gproc1:
+.short .frameproc1 - .gproc1 - 2
+.short S_GPROC32
+.long 0 # parent
+.long 0 # end
+.long 0 # next symbol
+.long .proc1_end - proc1 # length
+.long 0 # debug start offset
+.long 0 # debug end offset
+.long 0x1001 # type
+.secrel32 proc1
+.secidx proc1
+.byte 0 # flags
+.asciz "proc1"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.frameproc1:
+.short .framecookie1 - .frameproc1 - 2
+.short S_FRAMEPROC
+.long 0 # frame size
+.long 0 # frame padding
+.long 0 # padding offset
+.long 0 # size of callee-save registers
+.long 0 # offset of exception handler
+.short 0 # section of exception handler
+.long 0 # flags
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.framecookie1:
+.short .bprel1 - .framecookie1 - 2
+.short S_FRAMECOOKIE
+.long 8 # frame-relative offset
+.short CV_AMD64_RAX # register
+.long 0 # cookie type (CV_COOKIETYPE_COPY)
+.byte 0 # flags
+.byte 0xf1 # padding
+
+.bprel1:
+.short .reg1 - .bprel1 - 2
+.short S_BPREL32
+.long 4 # BP-relative offset
+.long 0x1008 # type
+.asciz "foo"
+
+.reg1:
+.short .regrel1 - .reg1 - 2
+.short S_REGISTER
+.long 0x1008 # type
+.short CV_AMD64_RAX
+.asciz "bar"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.regrel1:
+.short .local1 - .regrel1 - 2
+.short S_REGREL32
+.long 4 # offset
+.long 0x1008 # type
+.short CV_AMD64_RAX
+.asciz "baz"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.local1:
+.short .defrange1 - .local1 - 2
+.short S_LOCAL
+.long 0x1008 # type
+.short 0 # flags
+.asciz "local1"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.defrange1:
+.short .local2 - .defrange1 - 2
+.short S_DEFRANGE_REGISTER_REL
+.short CV_AMD64_RAX
+.short 0 # offset parent
+.long 0 # offset register
+.secrel32 .block1 # offset
+.secidx .block1 # section
+.short .block1_end - .block1 # length
+.short .gap1 - .block1 # gap 1 offset
+.short .gap1_end - .gap1 # gap 1 length
+
+.local2:
+.short .defrange2 - .local2 - 2
+.short S_LOCAL
+.long 0x1008 # type
+.short 0 # flags
+.asciz "local2"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.defrange2:
+.short .local3 - .defrange2 - 2
+.short S_DEFRANGE_FRAMEPOINTER_REL
+.long 4 # frame pointer offset
+.secrel32 .block1 # offset
+.secidx .block1 # section
+.short .block1_end - .block1 # length
+.short .gap1 - .block1 # gap 1 offset
+.short .gap1_end - .gap1 # gap 1 length
+
+.local3:
+.short .defrange3 - .local3 - 2
+.short S_LOCAL
+.long 0x1008 # type
+.short 0 # flags
+.asciz "local3"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.defrange3:
+.short .local4 - .defrange3 - 2
+.short S_DEFRANGE_SUBFIELD_REGISTER
+.short CV_AMD64_RAX
+.short 0 # attributes
+.long 4 # offset in parent variable
+.secrel32 .block1 # offset
+.secidx .block1 # section
+.short .block1_end - .block1 # length
+.short .gap1 - .block1 # gap 1 offset
+.short .gap1_end - .gap1 # gap 1 length
+
+.local4:
+.short .defrange4 - .local4 - 2
+.short S_LOCAL
+.long 0x1008 # type
+.short 0 # flags
+.asciz "local4"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.defrange4:
+.short .local5 - .defrange4 - 2
+.short S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
+.long 4 # frame pointer offset
+
+.local5:
+.short .defrange5 - .local5 - 2
+.short S_LOCAL
+.long 0x1008 # type
+.short 0 # flags
+.asciz "local5"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.defrange5:
+.short .inlinesite1 - .defrange5 - 2
+.short S_DEFRANGE_REGISTER
+.short CV_AMD64_RAX
+.short 0 # attributes
+.secrel32 .block1 # offset
+.secidx .block1 # section
+.short .block1_end - .block1 # length
+.short .gap1 - .block1 # gap 1 offset
+.short .gap1_end - .gap1 # gap 1 length
+
+.inlinesite1:
+.short .inlinesite1end - .inlinesite1 - 2
+.short S_INLINESITE
+.long 0 # parent
+.long 0 # end
+.long 0x1009 # inlinee (inline_func)
+
+.inlinesite1end:
+.short .sblock1 - .inlinesite1end - 2
+.short S_INLINESITE_END
+
+.sblock1:
+.short .label1 - .sblock1 - 2
+.short S_BLOCK32
+.long 0 # parent (filled in by linker)
+.long 0 # end (filled in by linker)
+.long .block1_end - .block1 # length
+.secrel32 .block1
+.secidx .block1
+.byte 0 # name
+.byte 0xf1 # padding
+
+.label1:
+.short .sblock1_end - .label1 - 2
+.short S_LABEL32
+.secrel32 label
+.secidx label
+.byte 0 # flags
+.asciz "label"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+.sblock1_end:
+.short .thunk1 - .sblock1_end - 2
+.short S_END
+
+.thunk1:
+.short .thunk1_end - .thunk1 - 2
+.short S_THUNK32
+.long 0 # parent
+.long 0 # end
+.long 0 # next
+.secrel32 thunk
+.secidx thunk
+.short .thunk_end - thunk
+.byte 0 # THUNK_ORDINAL value
+.asciz "thunk"
+.byte 0xf1 # padding
+
+.thunk1_end:
+.short .heapallocsite1 - .thunk1_end - 2
+.short S_END
+
+.heapallocsite1:
+.short .gproc1_end - .heapallocsite1 - 2
+.short S_HEAPALLOCSITE
+.secrel32 .gap1_end
+.secidx .gap1_end
+.short .block1_end - .gap1_end
+.long 0x1008 # type
+
+.gproc1_end:
+.short .syms_end - .gproc1_end - 2
+.short S_END
+
+.syms_end:
+
+.section ".debug$T", "rn"
+
+.long CV_SIGNATURE_C13
+
+# Type 1000, arglist (uint32_t)
+.arglist1:
+.short .proctype1 - .arglist1 - 2
+.short LF_ARGLIST
+.long 1 # no. entries
+.long T_UINT4
+
+# Type 1001, procedure (return type T_VOID, arglist 1000)
+.proctype1:
+.short .string1 - .proctype1 - 2
+.short LF_PROCEDURE
+.long T_VOID
+.byte 0 # calling convention
+.byte 0 # attributes
+.short 1 # no. parameters
+.long 0x1000
+
+# Type 1002, string "/tmp" (build directory)
+.string1:
+.short .string2 - .string1 - 2
+.short LF_STRING_ID
+.long 0 # sub-string
+.asciz "/tmp"
+.byte 0xf3 # padding
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+# Type 1003, string "gcc" (compiler)
+.string2:
+.short .string3 - .string2 - 2
+.short LF_STRING_ID
+.long 0 # sub-string
+.asciz "gcc"
+
+# Type 1004, string "tmp.c" (source file)
+.string3:
+.short .string4 - .string3 - 2
+.short LF_STRING_ID
+.long 0 # sub-string
+.asciz "tmp.c"
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+# Type 1005, string "tmp.pdb" (PDB file)
+.string4:
+.short .string5 - .string4 - 2
+.short LF_STRING_ID
+.long 0 # sub-string
+.asciz "tmp.pdb"
+
+# Type 1006, string "-gcodeview" (command arguments)
+.string5:
+.short .buildinfo1 - .string5 - 2
+.short LF_STRING_ID
+.long 0 # sub-string
+.asciz "-gcodeview"
+.byte 0xf1 # padding
+
+# Type 1007, build info
+.buildinfo1:
+.short .mod1 - .buildinfo1 - 2
+.short LF_BUILDINFO
+.short 5 # count
+.long 0x1002 # build directory
+.long 0x1003 # compiler
+.long 0x1004 # source file
+.long 0x1005 # PDB file
+.long 0x1006 # command arguments
+.byte 0xf2 # padding
+.byte 0xf1 # padding
+
+# Type 1008, const uint32_t
+.mod1:
+.short .funcid1 - .mod1 - 2
+.short LF_MODIFIER
+.long T_UINT4
+.short 1 # const
+.p2align 2
+
+# Type 1009, func ID for inline_func
+.funcid1:
+.short .types_end - .funcid1 - 2
+.short LF_FUNC_ID
+.long 0 # parent scope
+.long 0x1001 # type
+.asciz "inline_func"
+
+.types_end:
+
+.text
+
+.global proc1
+proc1:
+ nop
+.block1:
+ nop
+label:
+ nop
+.gap1:
+ nop
+.gap1_end:
+ nop
+.block1_end:
+ nop
+.proc1_end:
+
+thunk:
+ nop
+.thunk_end:
diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp
index 34eafc1..5df1583 100644
--- a/ld/testsuite/ld-pe/pdb.exp
+++ b/ld/testsuite/ld-pe/pdb.exp
@@ -1614,6 +1614,72 @@ proc test8 { } {
}
}
+proc test9 { } {
+ global as
+ global ar
+ global ld
+ global objdump
+ global srcdir
+ global subdir
+
+ if ![ld_assemble $as $srcdir/$subdir/pdb-syms2.s tmpdir/pdb-syms2.o] {
+ unsupported "Build pdb-syms2.o"
+ return
+ }
+
+ if ![ld_link $ld "tmpdir/pdb-syms2.exe" "--pdb=tmpdir/pdb-syms2.pdb tmpdir/pdb-syms2.o"] {
+ unsupported "Create PE image with PDB file"
+ return
+ }
+
+ # get index of module stream
+
+ set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms2.pdb 0003"]
+
+ if ![string match "" $exec_output] {
+ fail "Could not extract DBI stream"
+ return
+ } else {
+ pass "Extracted DBI stream"
+ }
+
+ set fi [open tmpdir/0003]
+ fconfigure $fi -translation binary
+
+ seek $fi 24
+ set data [read $fi 4]
+ binary scan $data i mod_info_size
+
+ seek $fi 36 current
+ set mod_info [read $fi $mod_info_size]
+
+ close $fi
+
+ binary scan [string range $mod_info 34 35] s module_index
+
+ # check module records
+
+ set index_str [format "%04x" $module_index]
+
+ set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms2.pdb $index_str"]
+
+ if ![string match "" $exec_output] {
+ fail "Could not extract module symbols"
+ return
+ } else {
+ pass "Extracted module symbols"
+ }
+
+ set exp [file_contents "$srcdir/$subdir/pdb-syms2-symbols1.d"]
+ set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
+
+ if [string match $exp $got] {
+ pass "Correct symbols in module stream"
+ } else {
+ fail "Incorrect symbols in module stream"
+ }
+}
+
test1
test2
test3
@@ -1622,3 +1688,4 @@ test5
test6
test7
test8
+test9