public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Tristan Gingold <tgingold@free.fr>
To: binutils <binutils@sourceware.org>
Subject: [PATCH] pe/coff - add support for base64 encoded long section names
Date: Thu, 11 May 2023 07:28:58 +0200	[thread overview]
Message-ID: <243D0799-E3D0-4938-A438-DD8725593F67@free.fr> (raw)

Hello,

to overcome the 8 characters limit of COFF section names, PE has introduced a convention to put long section names in the strtab and use special section names '/nnnnnnn' when this convention is used.

LLVM has added another convention for very large strtab, using '//xxxxxx' names and base64 encoding of the index in the strtab.

For the LLVM implementation, see:
https://github.com/llvm/llvm-project/blob/6311ab21474a0f3e0340515185cd1d6e33a9892a/llvm/lib/BinaryFormat/COFF.cpp#L20

The object files generated by LLVM using this convention cannot be handled by binutils and this can result in weird errors like:

objdump: ../../unisim_retarget_VCOMP.o: warning: COMDAT symbol '.rdata$.refptr.ieee__numeric_std__ELABORATED' does not match section name '//AA1GKj'
objdump: ../../unisim_retarget_VCOMP.o: warning: COMDAT symbol '.rdata$.refptr.ieee__std_logic_1164__ELABORATED' does not match section name '//AA1GLQ'

This patch adds support in bfd to correctly decode those names.
There is no real need to support encoding as the section names are usually put first in the strtab (issues could happen only if there are a huge number of sections with very long names).

Mostly manually checked, no regressions with 'make check' (when configured for x86_64-linux + mingw64 target enabled).

It has been a while since I haven't submitted a patch, I hope I am correctly following the procedure!

Tristan.

bfd/
	* coffgen.c (extract_long_section_name): New function extracted
	from ...
	(make_a_section_from_file): ... here.  Add support for base64
	long section names.


diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index ac936def566..c7ccfae59ed 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -43,6 +43,29 @@
#include "coff/internal.h"
#include "libcoff.h"

+/* Extract a long section name at STRINDEX and copy it to the bfd objstack.
+   Return NULL in case of error.  */
+
+static char *
+extract_long_section_name(bfd *abfd, unsigned long strindex)
+{
+  const char *strings;
+  char *name;
+
+  strings = _bfd_coff_read_string_table (abfd);
+  if (strings == NULL)
+    return NULL;
+  if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd))
+    return NULL;
+  strings += strindex;
+  name = (char *) bfd_alloc (abfd, (bfd_size_type) strlen (strings) + 1 + 1);
+  if (name == NULL)
+    return NULL;
+  strcpy (name, strings);
+
+  return name;
+}
+
/* Take a section header read from a coff file (in HOST byte order),
   and make a BFD "section" out of it.  This is used by ECOFF.  */

@@ -67,32 +90,62 @@ make_a_section_from_file (bfd *abfd,
  if (bfd_coff_set_long_section_names (abfd, bfd_coff_long_section_names (abfd))
      && hdr->s_name[0] == '/')
    {
-      char buf[SCNNMLEN];
-      long strindex;
-      char *p;
-      const char *strings;
-
      /* Flag that this BFD uses long names, even though the format might
	 expect them to be off by default.  This won't directly affect the
	 format of any output BFD created from this one, but the information
	 can be used to decide what to do.  */
      bfd_coff_set_long_section_names (abfd, true);
-      memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1);
-      buf[SCNNMLEN - 1] = '\0';
-      strindex = strtol (buf, &p, 10);
-      if (*p == '\0' && strindex >= 0)
+
+      if (hdr->s_name[1] == '/')
	{
-	  strings = _bfd_coff_read_string_table (abfd);
-	  if (strings == NULL)
-	    return false;
-	  if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd))
-	    return false;
-	  strings += strindex;
-	  name = (char *) bfd_alloc (abfd,
-				     (bfd_size_type) strlen (strings) + 1 + 1);
+	  /* LLVM extension: the '/' is followed by another '/' and then by
+	     the index in the strtab encoded in base64 without NUL at the
+	     end.  */
+	  unsigned strindex;
+	  unsigned i;
+
+	  strindex = 0;
+	  for (i = 2; i < SCNNMLEN; i++)
+	    {
+	      char c = hdr->s_name[i];
+	      unsigned d;
+
+	      if (c >= 'A' && c <= 'Z')
+		d = c - 'A';
+	      else if (c >= 'a' && c <= 'z')
+		d = c - 'a' + 26;
+	      else if (c >= '0' && c <= '9')
+		d = c - '0' + 52;
+	      else if (c == '+')
+		d = 62;
+	      else if (c == '/')
+		d = 63;
+	      else
+		return false;
+	      strindex = (strindex << 6) + d;
+	    }
+
+	  name = extract_long_section_name (abfd, strindex);
	  if (name == NULL)
	    return false;
-	  strcpy (name, strings);
+	}
+      else
+	{
+	  /* PE classic long section name.  The '/' is followed by the index
+	     in the strtab.  The index is formatted as a decimal string.  */
+	  char buf[SCNNMLEN];
+	  long strindex;
+	  char *p;
+
+	  memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1);
+	  buf[SCNNMLEN - 1] = '\0';
+	  strindex = strtol (buf, &p, 10);
+	  if (*p == '\0' && strindex >= 0)
+	    {
+	      name = extract_long_section_name (abfd, strindex);
+	      if (name == NULL)
+		return false;
+	    }
	}
    }

             reply	other threads:[~2023-05-11  5:29 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-11  5:28 Tristan Gingold [this message]
2023-05-17 13:30 ` Nick Clifton
2023-05-17 14:14   ` Jose E. Marchesi
2023-05-21 15:50     ` Tristan Gingold
2023-05-21 15:40   ` Tristan Gingold
2023-05-22  6:36     ` Jan Beulich
2023-05-22  8:53       ` Martin Storsjö
2023-05-22 19:40       ` Tristan Gingold
2023-05-23  6:31         ` 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=243D0799-E3D0-4938-A438-DD8725593F67@free.fr \
    --to=tgingold@free.fr \
    --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).