From 80d4e113d7b9af8a5a36e5ea4399bca86050784f Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Wed, 17 May 2023 13:38:14 +0100 Subject: [PATCH] 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. --- bfd/ChangeLog | 11 +++++++++++ bfd/cofflink.c | 34 +++++++++++++++++++++++++++++++++- bfd/libcoff-in.h | 11 +++++++++++ bfd/libcoff.h | 11 +++++++++++ ld/ChangeLog | 9 +++++++++ ld/emultempl/pe.em | 29 ++++++++++++++++++++++++++++- ld/emultempl/pep.em | 25 +++++++++++++++++++++++++ ld/pe-dll.c | 39 ++++++++++++++++++++++++++++++++------- 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 + + 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 * 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 + + 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 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 @@ -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); + } } } } 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 @@ -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) { 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 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) -- 2.30.2