ld: Write DEBUG_S_LINES entries in PDB file
authorMark Harmstone <mark@harmstone.com>
Fri, 9 Dec 2022 01:52:34 +0000 (01:52 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 23 Dec 2022 09:27:56 +0000 (19:57 +1030)
ld/pdb.c
ld/pdb.h
ld/testsuite/ld-pe/pdb.exp
ld/testsuite/ld-pe/pdb3-c13-info1.d
ld/testsuite/ld-pe/pdb3a.s

index 45c933e080a379fac1e6d83fdb18818d49c080ef..1a8a126e8ad5be463d8155d65566e1c5cc40bb36 100644 (file)
--- a/ld/pdb.c
+++ b/ld/pdb.c
@@ -624,7 +624,8 @@ parse_string_table (bfd_byte *data, size_t size,
 static bool
 handle_debugs_section (asection *s, bfd *mod, struct string_table *strings,
                       uint8_t **dataptr, uint32_t *sizeptr,
-                      struct mod_source_files *mod_source)
+                      struct mod_source_files *mod_source,
+                      bfd *abfd)
 {
   bfd_byte *data = NULL;
   size_t off;
@@ -638,6 +639,59 @@ handle_debugs_section (asection *s, bfd *mod, struct string_table *strings,
   if (!data)
     return false;
 
+  /* Resolve relocations.  Addresses are stored within the .debug$S section as
+     a .secidx, .secrel32 pair.  */
+
+  if (s->flags & SEC_RELOC)
+    {
+      struct internal_reloc *relocs;
+      struct internal_syment *symbols;
+      asection **sectlist;
+      unsigned int syment_count;
+      int sect_num;
+      struct external_syment *ext;
+
+      syment_count = obj_raw_syment_count (mod);
+
+      relocs =
+       _bfd_coff_read_internal_relocs (mod, s, false, NULL, true, NULL);
+
+      symbols = xmalloc (sizeof (struct internal_syment) * syment_count);
+      sectlist = xmalloc (sizeof (asection *) * syment_count);
+
+      ext = (struct external_syment *) (coff_data (mod)->external_syms);
+
+      for (unsigned int i = 0; i < syment_count; i++)
+       {
+         bfd_coff_swap_sym_in (mod, &ext[i], &symbols[i]);
+       }
+
+      sect_num = 1;
+
+      for (asection *sect = mod->sections; sect; sect = sect->next)
+       {
+         for (unsigned int i = 0; i < syment_count; i++)
+           {
+             if (symbols[i].n_scnum == sect_num)
+               sectlist[i] = sect;
+           }
+
+         sect_num++;
+       }
+
+      if (!bfd_coff_relocate_section (abfd, coff_data (abfd)->link_info, mod,
+                                     s, data, relocs, symbols, sectlist))
+       {
+         free (sectlist);
+         free (symbols);
+         free (data);
+         return false;
+       }
+
+      free (sectlist);
+      free (symbols);
+    }
+
   if (bfd_getl32 (data) != CV_SIGNATURE_C13)
     {
       free (data);
@@ -690,6 +744,32 @@ handle_debugs_section (asection *s, bfd *mod, struct string_table *strings,
          string_table = (char *) data + off;
 
          break;
+
+       case DEBUG_S_LINES:
+         {
+           uint16_t sect;
+
+           if (size < sizeof (uint32_t) + sizeof (uint16_t))
+             {
+               free (data);
+               bfd_set_error (bfd_error_bad_value);
+               return false;
+             }
+
+           sect = bfd_getl16 (data + off + sizeof (uint32_t));
+
+           /* Skip GC'd symbols.  */
+           if (sect != 0)
+             {
+               c13_size += sizeof (uint32_t) + sizeof (uint32_t) + size;
+
+               if (c13_size % sizeof (uint32_t))
+                 c13_size +=
+                   sizeof (uint32_t) - (c13_size % sizeof (uint32_t));
+             }
+
+           break;
+         }
        }
 
       off += size;
@@ -734,6 +814,28 @@ handle_debugs_section (asection *s, bfd *mod, struct string_table *strings,
          bufptr += sizeof (uint32_t) + sizeof (uint32_t) + size;
 
          break;
+
+       case DEBUG_S_LINES:
+         {
+           uint16_t sect;
+
+           sect = bfd_getl16 (data + off + sizeof (uint32_t));
+
+           /* Skip if GC'd.  */
+           if (sect != 0)
+             {
+               bfd_putl32 (type, bufptr);
+               bufptr += sizeof (uint32_t);
+
+               bfd_putl32 (size, bufptr);
+               bufptr += sizeof (uint32_t);
+
+               memcpy (bufptr, data + off, size);
+               bufptr += size;
+             }
+
+           break;
+         }
        }
 
       off += size;
@@ -770,7 +872,8 @@ static bool
 populate_module_stream (bfd *stream, bfd *mod, uint32_t *sym_byte_size,
                        struct string_table *strings,
                        uint32_t *c13_info_size,
-                       struct mod_source_files *mod_source)
+                       struct mod_source_files *mod_source,
+                       bfd *abfd)
 {
   uint8_t int_buf[sizeof (uint32_t)];
   uint8_t *c13_info = NULL;
@@ -785,7 +888,7 @@ populate_module_stream (bfd *stream, bfd *mod, uint32_t *sym_byte_size,
       if (!strcmp (s->name, ".debug$S") && s->size >= sizeof (uint32_t))
        {
          if (!handle_debugs_section (s, mod, strings, &c13_info,
-                                     c13_info_size, mod_source))
+                                     c13_info_size, mod_source, abfd))
            {
              free (c13_info);
              free (mod_source->files);
@@ -917,7 +1020,7 @@ create_module_info_substream (bfd *abfd, bfd *pdb, void **data,
 
       if (!populate_module_stream (stream, in, &sym_byte_size,
                                   strings, &c13_info_size,
-                                  &source->mods[mod_num]))
+                                  &source->mods[mod_num], abfd))
        {
          for (unsigned int i = 0; i < source->mod_count; i++)
            {
index e8f673c24a0020783a417d3d68322e611b0e3c72..bbb106043c4f0020db8b35c09f7f84685dae3f90 100644 (file)
--- a/ld/pdb.h
+++ b/ld/pdb.h
@@ -155,6 +155,7 @@ struct optional_dbg_header
 
 #define CV_SIGNATURE_C13               4
 
+#define DEBUG_S_LINES                  0xf2
 #define DEBUG_S_STRINGTABLE            0xf3
 #define DEBUG_S_FILECHKSMS             0xf4
 
index 9dab41110ac3a510f883fb8f221e22c8958989c2..2e5f83477aa43b097647c5a6ccba0e9d294d4e9a 100644 (file)
@@ -870,7 +870,7 @@ proc test4 { } {
        return
     }
 
-    if ![ld_link $ld "tmpdir/pdb3.exe" "--pdb=tmpdir/pdb3.pdb tmpdir/pdb3a.o tmpdir/pdb3b.o"] {
+    if ![ld_link $ld "tmpdir/pdb3.exe" "--pdb=tmpdir/pdb3.pdb --gc-sections -e main tmpdir/pdb3a.o tmpdir/pdb3b.o"] {
        unsupported "Create PE image with PDB file"
        return
     }
index f92062ba4e55b82c512b87561371ea4d235b223c..5a4f94861c78662daa57d46b53de838945aa9e1e 100644 (file)
@@ -5,4 +5,10 @@ Contents of section .data:
  0000 f4000000 30000000 02000000 10016745  ....0.........gE
  0010 2301efcd ab8998ba dcfe1023 45670000  #..........#Eg..
  0020 06000000 100198ba dcfe1023 45676745  ...........#EggE
- 0030 2301efcd ab890000                    #.......        
\ No newline at end of file
+ 0030 2301efcd ab890000 f2000000 58000000  #...........X...
+ 0040 00000000 01000000 14000000 00000000  ................
+ 0050 02000000 1c000000 00000000 01000080  ................
+ 0060 04000000 02000080 18000000 02000000  ................
+ 0070 1c000000 08000000 03000080 0c000000  ................
+ 0080 04000080 00000000 01000000 14000000  ................
+ 0090 10000000 05000080                    ........        
\ No newline at end of file
index 71795b53a66aaf7e36fb0e273c9fbe503d3eab48..1df84a344f64c1e255ecdeaca1dda20922ef8611 100644 (file)
@@ -1,4 +1,5 @@
 .equ CV_SIGNATURE_C13, 4
+.equ DEBUG_S_LINES, 0xf2
 .equ DEBUG_S_STRINGTABLE, 0xf3
 .equ DEBUG_S_FILECHKSMS, 0xf4
 .equ CHKSUM_TYPE_MD5, 1
 .chksms_end:
 
 .balign 4
+
+.long DEBUG_S_LINES
+.long .lines_end - .lines_start
+
+.lines_start:
+
+.secrel32 main
+.secidx main
+.short 0 # flags
+.long .main_end - main # length of region
+
+.lines_block1:
+
+.long 0 # file ID 0 (foo)
+.long 2 # no. lines
+.long .lines_block2 - .lines_block1 # length
+
+.long .line1 - main
+.long 0x80000001 # line 1
+.long .line2 - main
+.long 0x80000002 # line 2
+
+.lines_block2:
+
+.long 0x18 # file ID 18 (bar)
+.long 2 # no. lines
+.long .lines_block3 - .lines_block2 # length
+
+.long .line3 - main
+.long 0x80000003 # line 3
+.long .line4 - main
+.long 0x80000004 # line 4
+
+.lines_block3:
+
+.long 0 # file ID 0 (foo)
+.long 1 # no. lines
+.long .lines_end - .lines_block3 # length
+
+.long .line5 - main
+.long 0x80000005 # line 5
+
+.lines_end:
+
+.long DEBUG_S_LINES
+.long .lines_end2 - .lines_start2
+
+.lines_start2:
+
+.secrel32 gcfunc
+.secidx gcfunc
+.short 0 # flags
+.long .gcfunc_end - gcfunc # length of region
+
+.lines_block4:
+
+.long 0 # file ID 0 (foo)
+.long 1 # no. lines
+.long .lines_end2 - .lines_block4 # length
+
+.long .line6 - gcfunc
+.long 0x80000006 # line 6
+
+.lines_end2:
+
+.text
+
+.global main
+main:
+.line1:
+       .long 0x12345678
+.line2:
+       .long 0x12345678
+.line3:
+       .long 0x12345678
+.line4:
+       .long 0x12345678
+.line5:
+       .long 0x12345678
+.main_end:
+
+.section "gcsect"
+
+gcfunc:
+.line6:
+       .long 0x12345678
+.gcfunc_end: