Decorated symbols in import libs (BUG 30421)
authorLuca Bacci <luca.bacci@outlook.com>
Wed, 17 May 2023 12:38:14 +0000 (13:38 +0100)
committerNick Clifton <nickc@redhat.com>
Wed, 17 May 2023 12:38:14 +0000 (13:38 +0100)
  PR 30421
  * cofflink.c (_decoration_hash_newfunc): New function. (_bfd_coff_link_hash_table_init): Call it.
  * libcoff-in.h (struct coff_link_hash_table): Add decoration_hash field. (struct decoration_hash_entry): Declare. (_decoration_hash_newfunc): Prototype.
  * libcoff.h: Regenerate.

  * emultempl/pe.em (set_decoration): New function. (pe_fixup_stdcalls): Call the new function.
  * emultempl/pep.em (set_decoration): New function. (pep_fixup_stdcalls): Call the new function.
  * pe-dll.c (make_one): Check for decoated symbols.

bfd/ChangeLog
bfd/cofflink.c
bfd/libcoff-in.h
bfd/libcoff.h
ld/ChangeLog
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/pe-dll.c

index dc4620663b2c0253a48d21c6e13276f5f30c7201..76d8a954ae39f2bca4831b48a1b78331e2bb506a 100644 (file)
@@ -1,3 +1,14 @@
+2023-05-17  Luca Bacci  <luca.bacci@outlook.com>
+
+       PR 30421
+       * cofflink.c (_decoration_hash_newfunc): New function.
+       (_bfd_coff_link_hash_table_init): Call it.
+       * libcoff-in.h (struct coff_link_hash_table): Add decoration_hash
+       field.
+       (struct decoration_hash_entry): Declare.
+       (_decoration_hash_newfunc): Prototype.
+       * libcoff.h: Regenerate.
+
 2023-05-16  Oleg Tolmatcev  <oleg.tolmatcev@gmail.com>
 
        * libcoff-in.h (struct coff_tdata): Add section_by_index and
index 9baec2fc712382a5267760dc3f18ad07c60762e0..24c4a2b0ad7601496550816e171c8135ebff75c4 100644 (file)
@@ -89,6 +89,34 @@ _bfd_coff_link_hash_newfunc (struct bfd_hash_entry *entry,
   return (struct bfd_hash_entry *) ret;
 }
 
+struct bfd_hash_entry *
+_decoration_hash_newfunc (struct bfd_hash_entry *entry,
+                         struct bfd_hash_table *table,
+                         const char *string)
+{
+  struct decoration_hash_entry *ret = (struct decoration_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == NULL)
+    {
+      ret = (struct decoration_hash_entry *)
+           bfd_hash_allocate (table, sizeof (struct decoration_hash_entry));
+      if (ret == NULL)
+       return NULL;
+    }
+
+  /* Call the allocation method of the superclass.  */
+  ret = (struct decoration_hash_entry *)
+       _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string);
+  if (ret != NULL)
+    {
+      ret->decorated_link = NULL;
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
 /* Initialize a COFF linker hash table.  */
 
 bool
@@ -100,7 +128,11 @@ _bfd_coff_link_hash_table_init (struct coff_link_hash_table *table,
                                unsigned int entsize)
 {
   memset (&table->stab_info, 0, sizeof (table->stab_info));
-  return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
+
+  return bfd_hash_table_init (&table->decoration_hash,
+                             _decoration_hash_newfunc,
+                             sizeof (struct decoration_hash_entry))
+        &&_bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
 }
 
 /* Create a COFF linker hash table.  */
index 9c5780bfcc03cc3563041cd023c06f0f38bb584b..24a950dedd41e96d99325a216a92145edc1c04b2 100644 (file)
@@ -290,6 +290,9 @@ struct coff_link_hash_table
   struct bfd_link_hash_table root;
   /* A pointer to information used to link stabs in sections.  */
   struct stab_info stab_info;
+  /* Hash table that maps undecorated names to their respective
+   * decorated coff_link_hash_entry as found in fixup_stdcalls  */
+  struct bfd_hash_table decoration_hash;
 };
 
 struct coff_reloc_cookie
@@ -321,6 +324,12 @@ struct coff_reloc_cookie
 
 #define coff_hash_table(p) ((struct coff_link_hash_table *) ((p)->hash))
 
+struct decoration_hash_entry
+{
+  struct bfd_hash_entry root;
+  struct bfd_link_hash_entry *decorated_link;
+};
+
 /* Functions in coffgen.c.  */
 extern bfd_cleanup coff_object_p
   (bfd *);
@@ -568,6 +577,8 @@ struct coff_section_alignment_entry
   unsigned int alignment_power;
 };
 
+extern struct bfd_hash_entry *_decoration_hash_newfunc
+  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
 extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc
   (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
 extern bool _bfd_coff_link_hash_table_init
index 1a8d930773491b2f73096dc4c538c5d720a9fd87..c5d15a13f7bcf528534970a31660e1b91f8d24bc 100644 (file)
@@ -294,6 +294,9 @@ struct coff_link_hash_table
   struct bfd_link_hash_table root;
   /* A pointer to information used to link stabs in sections.  */
   struct stab_info stab_info;
+  /* Hash table that maps undecorated names to their respective
+   * decorated coff_link_hash_entry as found in fixup_stdcalls  */
+  struct bfd_hash_table decoration_hash;
 };
 
 struct coff_reloc_cookie
@@ -325,6 +328,12 @@ struct coff_reloc_cookie
 
 #define coff_hash_table(p) ((struct coff_link_hash_table *) ((p)->hash))
 
+struct decoration_hash_entry
+{
+  struct bfd_hash_entry root;
+  struct bfd_link_hash_entry *decorated_link;
+};
+
 /* Functions in coffgen.c.  */
 extern bfd_cleanup coff_object_p
   (bfd *);
@@ -572,6 +581,8 @@ struct coff_section_alignment_entry
   unsigned int alignment_power;
 };
 
+extern struct bfd_hash_entry *_decoration_hash_newfunc
+  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
 extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc
   (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
 extern bool _bfd_coff_link_hash_table_init
index ae1b34af0c05f756f8ecb811fd26f1d80b762432..1acef2afc97ea44af67284f3fad5c8bbcea96263 100644 (file)
@@ -1,3 +1,12 @@
+2023-05-17  Luca Bacci  <luca.bacci@outlook.com>
+
+       PR 30421
+       * emultempl/pe.em (set_decoration): New function.
+       (pe_fixup_stdcalls): Call the new function.
+       * emultempl/pep.em (set_decoration): New function.
+       (pep_fixup_stdcalls): Call the new function.
+       * pe-dll.c (make_one): Check for decoated symbols.
+
 2023-05-16  Nick Clifton  <nickc@redhat.com>
 
        PR 30359
index 38cb61138bd96e7bbaabb3141ec4c4dc1fd9f49e..7d956bf555ceb165b1b5bdaed159ca745533065c 100644 (file)
@@ -1188,6 +1188,30 @@ change_undef (struct bfd_link_hash_entry * undef,
   lang_add_gc_name (sym->root.string);
 }
 
+static void
+set_decoration (const char *undecorated_name,
+               struct bfd_link_hash_entry * decoration)
+{
+  static bool  gave_warning_message = false;
+  struct decoration_hash_entry *entry;
+
+  if (is_underscoring () && undecorated_name[0] == '_')
+    undecorated_name++;
+
+  entry = (struct decoration_hash_entry *)
+         bfd_hash_lookup (&(coff_hash_table (&link_info)->decoration_hash),
+                          undecorated_name, true /* create */, false /* copy */);
+
+  if (entry->decorated_link != NULL && !gave_warning_message)
+    {
+      einfo (_("%P: warning: overwriting decorated name %s with %s\n"),
+            entry->decorated_link->root.string, undecorated_name);
+      gave_warning_message = true;
+    }
+
+  entry->decorated_link = decoration;
+}
+
 static void
 pe_fixup_stdcalls (void)
 {
@@ -1231,7 +1255,10 @@ pe_fixup_stdcalls (void)
            bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match,
                                    (char *) name);
            if (pe_undef_found_sym)
-             change_undef (undef, pe_undef_found_sym);
+             {
+               change_undef (undef, pe_undef_found_sym);
+               set_decoration (undef->root.string, pe_undef_found_sym);
+             }
          }
       }
 }
index 32883b27706ea92249f3c34c14889cecd124534c..99e71951b8a0b7ea5446be1d6800c487ef0cf9db 100644 (file)
@@ -1119,6 +1119,30 @@ pep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
   return true;
 }
 
+static void
+set_decoration (const char *undecorated_name,
+               struct bfd_link_hash_entry * decoration)
+{
+  static bool  gave_warning_message = false;
+  struct decoration_hash_entry *entry;
+
+  if (is_underscoring () && undecorated_name[0] == '_')
+    undecorated_name++;
+
+  entry = (struct decoration_hash_entry *)
+         bfd_hash_lookup (&(coff_hash_table (&link_info)->decoration_hash),
+                          undecorated_name, true /* create */, false /* copy */);
+
+  if (entry->decorated_link != NULL && !gave_warning_message)
+    {
+      einfo (_("%P: warning: overwriting decorated name %s with %s\n"),
+            entry->decorated_link->root.string, undecorated_name);
+      gave_warning_message = true;
+    }
+
+  entry->decorated_link = decoration;
+}
+
 static void
 pep_fixup_stdcalls (void)
 {
@@ -1180,6 +1204,7 @@ pep_fixup_stdcalls (void)
                undef->type = bfd_link_hash_defined;
                undef->u.def.value = sym->u.def.value;
                undef->u.def.section = sym->u.def.section;
+               set_decoration (undef->root.string, sym);
 
                if (pep_enable_stdcall_fixup == -1)
                  {
index 8d74dba6af0273971cd559a69129c9f5baac8a55..e45ae1042654bb57f3282731b22dfb46e7766a56 100644 (file)
@@ -2321,6 +2321,31 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub)
   bfd *abfd;
   const unsigned char *jmp_bytes = NULL;
   int jmp_byte_count = 0;
+  const char *internal_name = exp->internal_name;
+
+  if (!exp->flag_noname)
+    {
+      /* Check for a decorated symbol name */
+      struct decoration_hash_entry *entry;
+
+      entry = (struct decoration_hash_entry *)
+             bfd_hash_lookup (&(coff_hash_table (&link_info)->decoration_hash),
+                              internal_name, false, false);
+      if (entry)
+       {
+         if (entry->decorated_link)
+           {
+             internal_name = entry->decorated_link->root.string;
+
+             if (pe_details->underscored && internal_name[0] == '_')
+               internal_name++;
+           }
+         else
+           {
+             einfo (_("%P: error: NULL decorated name for %s\n"), internal_name);
+           }
+       }
+    }
 
   /* Include the jump stub section only if it is needed. A jump
      stub is needed if the symbol being imported <sym> is a function
@@ -2382,13 +2407,13 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub)
   id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
   id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
 
-  if  (*exp->internal_name == '@')
+  if  (*internal_name == '@')
     {
       quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
                    BSF_GLOBAL, 0);
       if (include_jmp_stub)
-       quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
-      quick_symbol (abfd, "__imp_", exp->internal_name, "", id5,
+       quick_symbol (abfd, "", internal_name, "", tx, BSF_GLOBAL, 0);
+      quick_symbol (abfd, "__imp_", internal_name, "", id5,
                    BSF_GLOBAL, 0);
       /* Fastcall applies only to functions,
         so no need for auto-import symbol.  */
@@ -2398,18 +2423,18 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub)
       quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
                    BSF_GLOBAL, 0);
       if (include_jmp_stub)
-       quick_symbol (abfd, U (""), exp->internal_name, "", tx,
+       quick_symbol (abfd, U (""), internal_name, "", tx,
                      BSF_GLOBAL, 0);
-      quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5,
+      quick_symbol (abfd, "__imp_", U (""), internal_name, id5,
                    BSF_GLOBAL, 0);
       /* Symbol to reference ord/name of imported
         data symbol, used to implement auto-import.  */
       if (exp->flag_data)
-       quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6,
+       quick_symbol (abfd, "__nm_", U (""), internal_name, id6,
                      BSF_GLOBAL,0);
     }
   if (pe_dll_compat_implib)
-    quick_symbol (abfd, "___imp_", exp->internal_name, "", id5,
+    quick_symbol (abfd, "___imp_", internal_name, "", id5,
                  BSF_GLOBAL, 0);
 
   if (include_jmp_stub)