summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Bacci <luca.bacci@outlook.com>2023-05-17 13:38:14 +0100
committerNick Clifton <nickc@redhat.com>2023-05-17 13:38:14 +0100
commit80d4e113d7b9af8a5a36e5ea4399bca86050784f (patch)
treea471fa8b0176805e795dd73a3a97b5af94630482
parent80b6c32f233ed28607643c4e4e4e2ee3399fdfd7 (diff)
downloadbinutils-gdb-80d4e113d7b9af8a5a36e5ea4399bca86050784f.tar.gz
Decorated symbols in import libs (BUG 30421)
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.
-rw-r--r--bfd/ChangeLog11
-rw-r--r--bfd/cofflink.c34
-rw-r--r--bfd/libcoff-in.h11
-rw-r--r--bfd/libcoff.h11
-rw-r--r--ld/ChangeLog9
-rw-r--r--ld/emultempl/pe.em29
-rw-r--r--ld/emultempl/pep.em25
-rw-r--r--ld/pe-dll.c39
8 files changed, 160 insertions, 9 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index dc4620663b2..76d8a954ae3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 9baec2fc712..24c4a2b0ad7 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -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. */
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 9c5780bfcc0..24a950dedd4 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -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
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 1a8d9307734..c5d15a13f7b 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -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
diff --git a/ld/ChangeLog b/ld/ChangeLog
index ae1b34af0c0..1acef2afc97 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 38cb61138bd..7d956bf555c 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -1189,6 +1189,30 @@ change_undef (struct bfd_link_hash_entry * undef,
}
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)
{
struct bfd_link_hash_entry *undef, *sym;
@@ -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);
+ }
}
}
}
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 32883b27706..99e71951b8a 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -1120,6 +1120,30 @@ pep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
}
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)
{
static int gave_warning_message = 0;
@@ -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)
{
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index 8d74dba6af0..e45ae104265 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -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)