public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Mark Harmstone <mark@harmstone.com>
To: binutils@sourceware.org
Cc: Mark Harmstone <mark@harmstone.com>
Subject: [PATCH] ld: Copy other symbols into PDB file
Date: Mon,  5 Dec 2022 01:53:46 +0000	[thread overview]
Message-ID: <20221205015347.25781-2-mark@harmstone.com> (raw)
In-Reply-To: <20221205015347.25781-1-mark@harmstone.com>

Copies the remaining symbols in the DEBUG_S_SYMBOLS subsection, the
local variables etc. that don't make up the globals stream.

I think that this is all, or nearly all, of the records that Clang emits
for C or C++.

---
 ld/pdb.c                                | 362 ++++++++++++++++++++
 ld/pdb.h                                | 179 ++++++++++
 ld/testsuite/ld-pe/pdb-syms2-symbols1.d |  38 +++
 ld/testsuite/ld-pe/pdb-syms2.s          | 430 ++++++++++++++++++++++++
 ld/testsuite/ld-pe/pdb.exp              |  67 ++++
 5 files changed, 1076 insertions(+)
 create mode 100644 ld/testsuite/ld-pe/pdb-syms2-symbols1.d
 create mode 100644 ld/testsuite/ld-pe/pdb-syms2.s

diff --git a/ld/pdb.c b/ld/pdb.c
index 268e2521b03..e16e45c23b1 100644
--- a/ld/pdb.c
+++ b/ld/pdb.c
@@ -907,11 +907,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)
@@ -960,6 +964,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))
     {
@@ -1205,6 +1210,8 @@ parse_symbols (uint8_t *data, uint32_t size, uint8_t **buf,
 
 	    free (ref);
 
+	    scope = *buf;
+
 	    memcpy (*buf, proc, len);
 	    *buf += len;
 
@@ -1320,16 +1327,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);
@@ -1440,12 +1774,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 3f516f8a5f8..2ac4701645e 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 00000000000..34132d1264e
--- /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 00000000000..ec677eaee43
--- /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 34eafc142a7..5df1583c247 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
-- 
2.37.4


  reply	other threads:[~2022-12-05  1:53 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-25  2:53 [PATCH v2] ld: Generate PDB string table Mark Harmstone
2022-11-25  2:54 ` [PATCH] ld: Write DEBUG_S_FILECHKSMS entries in PDBs Mark Harmstone
2022-11-27  2:38   ` [PATCH] ld: Fix segfault in populate_publics_stream Mark Harmstone
2022-11-27  2:38     ` [PATCH] ld: Write DEBUG_S_LINES entries in PDB file Mark Harmstone
2022-11-29  0:10       ` [PATCH] ld: Write types into TPI stream of PDB Mark Harmstone
2022-11-29  0:10         ` [PATCH] ld: Write types into IPI " Mark Harmstone
2022-11-29  0:10         ` [PATCH] ld: Parse LF_UDT_SRC_LINE records when creating PDB file Mark Harmstone
2022-12-05  1:53           ` [PATCH] ld: Write globals stream in PDB Mark Harmstone
2022-12-05  1:53             ` Mark Harmstone [this message]
2022-12-05  1:53             ` [PATCH] ld: Write linker symbols " Mark Harmstone
2022-12-06 17:07             ` [PATCH] ld: Write globals stream " Nick Clifton
2022-12-06 17:52               ` Mark Harmstone
2022-12-08 11:00                 ` Nick Clifton
2022-12-09  1:11               ` Mark Harmstone
2022-11-28 14:54     ` [PATCH] ld: Fix segfault in populate_publics_stream Jan Beulich
2022-11-28 17:53       ` Mark Harmstone
2022-11-29  9:00         ` Jan Beulich
2022-11-29 17:47           ` Mark Harmstone
2022-11-30  7:00             ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221205015347.25781-2-mark@harmstone.com \
    --to=mark@harmstone.com \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).