public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/2] ld: Add section header stream to PDB files
@ 2022-10-27 19:00 Mark Harmstone
  2022-10-27 19:00 ` [PATCH 2/2] ld: Add publics " Mark Harmstone
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Harmstone @ 2022-10-27 19:00 UTC (permalink / raw)
  To: binutils; +Cc: Mark Harmstone

These patches add S_PUB32 records to PDB files, allowing Microsoft
debuggers to resolve mangled symbol names.

---
 ld/pdb.c                   |  69 ++++++++++++++++++++-
 ld/testsuite/ld-pe/pdb.exp | 123 +++++++++++++++++++++++++++++++++++++
 2 files changed, 189 insertions(+), 3 deletions(-)

diff --git a/ld/pdb.c b/ld/pdb.c
index 3452e2cbe5b..a82370701e8 100644
--- a/ld/pdb.c
+++ b/ld/pdb.c
@@ -385,7 +385,8 @@ get_arch_number (bfd *abfd)
 
 /* Stream 4 is the debug information (DBI) stream.  */
 static bool
-populate_dbi_stream (bfd *stream, bfd *abfd)
+populate_dbi_stream (bfd *stream, bfd *abfd,
+		     uint16_t section_header_stream_num)
 {
   struct pdb_dbi_stream_header h;
   struct optional_dbg_header opt;
@@ -419,7 +420,7 @@ populate_dbi_stream (bfd *stream, bfd *abfd)
   bfd_putl16 (0xffff, &opt.fixup_stream);
   bfd_putl16 (0xffff, &opt.omap_to_src_stream);
   bfd_putl16 (0xffff, &opt.omap_from_src_stream);
-  bfd_putl16 (0xffff, &opt.section_header_stream);
+  bfd_putl16 (section_header_stream_num, &opt.section_header_stream);
   bfd_putl16 (0xffff, &opt.token_map_stream);
   bfd_putl16 (0xffff, &opt.xdata_stream);
   bfd_putl16 (0xffff, &opt.pdata_stream);
@@ -432,6 +433,60 @@ populate_dbi_stream (bfd *stream, bfd *abfd)
   return true;
 }
 
+/* The section header stream contains a copy of the section headers
+   from the PE file, in the same format.  */
+static bool
+create_section_header_stream (bfd *pdb, bfd *abfd, uint16_t *num)
+{
+  bfd *stream;
+  unsigned int section_count;
+  file_ptr scn_base;
+  size_t len;
+  char *buf;
+
+  stream = add_stream (pdb, NULL, num);
+  if (!stream)
+    return false;
+
+  section_count = abfd->section_count;
+
+  /* Empty sections aren't output.  */
+  for (asection *sect = abfd->sections; sect; sect = sect->next)
+    {
+      if (sect->size == 0)
+	section_count--;
+    }
+
+  if (section_count == 0)
+    return true;
+
+  /* Copy section table from output - it's already been written at this
+     point.  */
+
+  scn_base = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
+
+  bfd_seek (abfd, scn_base, SEEK_SET);
+
+  len = section_count * sizeof (struct external_scnhdr);
+  buf = xmalloc (len);
+
+  if (bfd_bread (buf, len, abfd) != len)
+    {
+      free (buf);
+      return false;
+    }
+
+  if (bfd_bwrite (buf, len, stream) != len)
+    {
+      free (buf);
+      return false;
+    }
+
+  free (buf);
+
+  return true;
+}
+
 /* Create a PDB debugging file for the PE image file abfd with the build ID
    guid, stored at pdb_name.  */
 bool
@@ -440,6 +495,7 @@ create_pdb_file (bfd *abfd, const char *pdb_name, const unsigned char *guid)
   bfd *pdb;
   bool ret = false;
   bfd *info_stream, *dbi_stream, *names_stream;
+  uint16_t section_header_stream_num;
 
   pdb = bfd_openw (pdb_name, "pdb");
   if (!pdb)
@@ -499,7 +555,14 @@ create_pdb_file (bfd *abfd, const char *pdb_name, const unsigned char *guid)
       goto end;
     }
 
-  if (!populate_dbi_stream (dbi_stream, abfd))
+  if (!create_section_header_stream (pdb, abfd, &section_header_stream_num))
+    {
+      einfo (_("%P: warning: cannot create section header stream "
+	       "in PDB file: %s\n"), bfd_errmsg (bfd_get_error ()));
+      goto end;
+    }
+
+  if (!populate_dbi_stream (dbi_stream, abfd, section_header_stream_num))
     {
       einfo (_("%P: warning: cannot populate DBI stream "
 	       "in PDB file: %s\n"), bfd_errmsg (bfd_get_error ()));
diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp
index b62ce6da6f8..cee072187de 100644
--- a/ld/testsuite/ld-pe/pdb.exp
+++ b/ld/testsuite/ld-pe/pdb.exp
@@ -278,6 +278,123 @@ proc check_dbi_stream { pdb } {
     return 1
 }
 
+proc get_section_stream_index { pdb } {
+    global ar
+
+    set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0003"]
+
+    if ![string match "" $exec_output] {
+	return -1
+    }
+
+    set fi [open tmpdir/0003]
+    fconfigure $fi -translation binary
+
+    # skip fields
+    seek $fi 24
+
+    # read substream sizes
+
+    set data [read $fi 4]
+    binary scan $data i mod_info_size
+
+    set data [read $fi 4]
+    binary scan $data i section_contribution_size
+
+    set data [read $fi 4]
+    binary scan $data i section_map_size
+
+    set data [read $fi 4]
+    binary scan $data i source_info_size
+
+    set data [read $fi 4]
+    binary scan $data i type_server_map_size
+
+    # skip type server index
+    seek $fi 4 current
+
+    set data [read $fi 4]
+    binary scan $data i optional_dbg_header_size
+
+    if { $optional_dbg_header_size < 12 } {
+	close $fi
+	return -1
+    }
+
+    # skip data
+    seek $fi [expr 12 + $mod_info_size + $section_contribution_size + $section_map_size + $source_info_size + $type_server_map_size + 10] current
+
+    set data [read $fi 2]
+    binary scan $data s section_stream_index
+
+    close $fi
+
+    return $section_stream_index
+}
+
+proc check_section_stream { img pdb } {
+    global ar
+
+    # read sections stream
+
+    set index [get_section_stream_index $pdb]
+
+    if { $index == -1 } {
+	return 0
+    }
+
+    set index_str [format "%04x" $index]
+
+    set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb $index_str"]
+
+    if ![string match "" $exec_output] {
+	return 0
+    }
+
+    set stream_length [file size tmpdir/$index_str]
+
+    set fi [open tmpdir/$index_str]
+    fconfigure $fi -translation binary
+
+    set stream_data [read $fi $stream_length]
+
+    close $fi
+
+    # read sections from PE file
+
+    set fi [open $img]
+    fconfigure $fi -translation binary
+
+    # read PE offset
+    read $fi 0x3c
+    set data [read $fi 4]
+    binary scan $data i pe_offset
+
+    # read number of sections
+    seek $fi [expr $pe_offset + 6]
+    set data [read $fi 2]
+    binary scan $data s num_sections
+
+    # read size of optional header
+    seek $fi 12 current
+    set data [read $fi 2]
+    binary scan $data s opt_header_size
+
+    # read section headers
+    seek $fi [expr $opt_header_size + 2] current
+    set section_data [read $fi [expr $num_sections * 40]]
+
+    close $fi
+
+    # compare
+
+    if { $stream_data ne $section_data} {
+	return 0
+    }
+
+    return 1
+}
+
 if ![ld_assemble $as $srcdir/$subdir/pdb1.s tmpdir/pdb1.o] {
     unsupported "Build pdb1.o"
     return
@@ -318,3 +435,9 @@ if [check_dbi_stream tmpdir/pdb1.pdb] {
 } else {
     fail "Invalid DBI stream"
 }
+
+if [check_section_stream tmpdir/pdb1.exe tmpdir/pdb1.pdb] {
+    pass "Valid section stream"
+} else {
+    fail "Invalid section stream"
+}
-- 
2.37.4


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-10-28  1:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-27 19:00 [PATCH 1/2] ld: Add section header stream to PDB files Mark Harmstone
2022-10-27 19:00 ` [PATCH 2/2] ld: Add publics " Mark Harmstone
2022-10-28  1:26   ` Alan Modra

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).