mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
BFD linker: Allow target backends to provide alternate entry names.
PR 30144
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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},...
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
34
ld/ldlang.c
34
ld/ldlang.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user