BFD linker: Allow target backends to provide alternate entry names.

PR 30144
This commit is contained in:
Pali Roh?r
2025-04-25 12:31:48 +01:00
committed by Nick Clifton
parent 6fa80ccbc4
commit a965df05e4
6 changed files with 88 additions and 19 deletions

View File

@@ -36,6 +36,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
${LDEMUL_EMIT_CTF_EARLY-NULL},
${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL},
${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL},
${LDEMUL_PRINT_SYMBOL-NULL}
${LDEMUL_PRINT_SYMBOL-NULL},
${LDEMUL_FIND_START_SYMBOL-NULL}
};
EOF

View File

@@ -2448,6 +2448,55 @@ gld${EMULATION_NAME}_find_potential_libraries
{
return ldfile_open_file_search (name, entry, "", ".lib");
}
static struct bfd_link_hash_entry *
gld${EMULATION_NAME}_find_alt_start_symbol
(struct bfd_sym_chain *entry)
{
#if defined (TARGET_IS_i386pe)
bool entry_has_stdcall_suffix;
#endif
struct bfd_link_hash_entry *h;
size_t entry_name_len;
char *symbol_name;
const char *prefix;
const char *suffix;
entry_name_len = strlen (entry->name);
if (is_underscoring ())
prefix = "_";
else
prefix = "";
#if defined (TARGET_IS_i386pe)
if ((entry_name_len > 2 && entry->name[entry_name_len-2] == '@' && ISDIGIT (entry->name[entry_name_len-1]))
|| (entry_name_len > 3 && entry->name[entry_name_len-3] == '@' && ISDIGIT (entry->name[entry_name_len-2]) && ISDIGIT (entry->name[entry_name_len-1]))
|| (entry_name_len > 4 && entry->name[entry_name_len-4] == '@' && ISDIGIT (entry->name[entry_name_len-3]) && ISDIGIT (entry->name[entry_name_len-2]) && ISDIGIT (entry->name[entry_name_len-1])))
entry_has_stdcall_suffix = true;
else
entry_has_stdcall_suffix = false;
if (!entry_has_stdcall_suffix && (bfd_link_dll (&link_info) || dll))
suffix = "@12";
else if (!entry_has_stdcall_suffix && pe_subsystem == 1 /* NT kernel driver */)
suffix = "@8";
else
#endif
suffix = "";
if (*prefix == '\0' && *suffix == '\0')
return NULL;
symbol_name = xmalloc (entry_name_len + 5);
strcpy (symbol_name, prefix);
strcat (symbol_name, entry->name);
strcat (symbol_name, suffix);
h = bfd_link_hash_lookup (link_info.hash, symbol_name, false, false, true);
free (symbol_name);
return h;
}
static char *
gld${EMULATION_NAME}_get_script (int *isfile)
@@ -2526,5 +2575,6 @@ LDEMUL_UNRECOGNIZED_FILE=gld${EMULATION_NAME}_unrecognized_file
LDEMUL_LIST_OPTIONS=gld${EMULATION_NAME}_list_options
LDEMUL_RECOGNIZED_FILE=gld${EMULATION_NAME}_recognized_file
LDEMUL_FIND_POTENTIAL_LIBRARIES=gld${EMULATION_NAME}_find_potential_libraries
LDEMUL_FIND_START_SYMBOL=gld${EMULATION_NAME}_find_alt_start_symbol
source_em ${srcdir}/emultempl/emulation.em

View File

@@ -531,7 +531,9 @@ named @var{entry}, the linker will try to parse @var{entry} as a number,
and use that as the entry address (the number will be interpreted in
base 10; you may use a leading @samp{0x} for base 16, or a leading
@samp{0} for base 8). @xref{Entry Point}, for a discussion of defaults
and other ways of specifying the entry point.
and other ways of specifying the entry point. For i386 PE, @var{entry}
can be also the original function name (without the leading underscore
and/or the trailing stdcall @samp{@@number} when applicable).
@kindex --exclude-libs
@item --exclude-libs @var{lib},@var{lib},...

View File

@@ -35,6 +35,14 @@
static ld_emulation_xfer_type *ld_emulation;
struct bfd_link_hash_entry *
ldemul_find_alt_start_symbol (struct bfd_sym_chain *entry)
{
if (ld_emulation->find_alt_start_symbol)
return ld_emulation->find_alt_start_symbol (entry);
return NULL;
}
void
ldemul_hll (char *name)
{

View File

@@ -115,9 +115,10 @@ extern void ldemul_acquire_strings_for_ctf
(struct ctf_dict *, struct elf_strtab_hash *);
extern void ldemul_new_dynsym_for_ctf
(struct ctf_dict *, int symidx, struct elf_internal_sym *);
extern bool ldemul_print_symbol
(struct bfd_link_hash_entry *hash_entry, void *ptr);
extern struct bfd_link_hash_entry * ldemul_find_alt_start_symbol
(struct bfd_sym_chain *);
typedef struct ld_emulation_xfer_struct {
/* Run before parsing the command line and script file.
@@ -259,6 +260,11 @@ typedef struct ld_emulation_xfer_struct {
bool (*print_symbol)
(struct bfd_link_hash_entry *hash_entry, void *ptr);
/* Called when ENTRY->name cannot be found by a direct lookup in INFO->hash.
Allows emulations to try variations of the name. */
struct bfd_link_hash_entry * (*find_alt_start_symbol)
(struct bfd_sym_chain *entry);
} ld_emulation_xfer_type;
typedef enum {

View File

@@ -2485,12 +2485,19 @@ lang_map (void)
config.map_file);
}
static bool
is_defined (struct bfd_link_hash_entry *h)
{
return h != NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak);
}
static bool
sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
void *info ATTRIBUTE_UNUSED)
{
if ((hash_entry->type == bfd_link_hash_defined
|| hash_entry->type == bfd_link_hash_defweak)
if (is_defined (hash_entry)
&& hash_entry->u.def.section->owner != link_info.output_bfd
&& hash_entry->u.def.section->owner != NULL)
{
@@ -4184,9 +4191,7 @@ ldlang_check_require_defined_symbols (void)
h = bfd_link_hash_lookup (link_info.hash, ptr->name,
false, false, true);
if (h == NULL
|| (h->type != bfd_link_hash_defined
&& h->type != bfd_link_hash_defweak))
if (! is_defined (h))
einfo(_("%X%P: required symbol `%s' not defined\n"), ptr->name);
}
}
@@ -4892,9 +4897,7 @@ print_assignment (lang_assignment_statement_type *assignment,
h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
false, false, true);
if (h != NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak))
if (is_defined (h))
{
value = h->u.def.value;
value += h->u.def.section->output_section->vma;
@@ -4939,8 +4942,7 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
{
asection *sec = (asection *) ptr;
if ((hash_entry->type == bfd_link_hash_defined
|| hash_entry->type == bfd_link_hash_defweak)
if (is_defined (hash_entry)
&& sec == hash_entry->u.def.section)
{
print_spaces (SECTION_NAME_MAP_LENGTH);
@@ -7234,9 +7236,7 @@ lang_end (void)
{
h = bfd_link_hash_lookup (link_info.hash, sym->name,
false, false, false);
if (h != NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
if (is_defined (h)
&& !bfd_is_const_section (h->u.def.section))
break;
}
@@ -7255,9 +7255,11 @@ lang_end (void)
h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
false, false, true);
if (h != NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
if (! is_defined (h) || h->u.def.section->output_section == NULL)
h = ldemul_find_alt_start_symbol (&entry_symbol);
if (is_defined (h)
&& h->u.def.section->output_section != NULL)
{
bfd_vma val;