Skip to content

Commit a965df0

Browse files
palinickclifton
authored andcommitted
BFD linker: Allow target backends to provide alternate entry names.
PR 30144
1 parent 6fa80cc commit a965df0

File tree

6 files changed

+88
-19
lines changed

6 files changed

+88
-19
lines changed

ld/emultempl/emulation.em

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
3636
${LDEMUL_EMIT_CTF_EARLY-NULL},
3737
${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL},
3838
${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL},
39-
${LDEMUL_PRINT_SYMBOL-NULL}
39+
${LDEMUL_PRINT_SYMBOL-NULL},
40+
${LDEMUL_FIND_START_SYMBOL-NULL}
4041
};
4142
EOF

ld/emultempl/pe.em

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,6 +2448,55 @@ gld${EMULATION_NAME}_find_potential_libraries
24482448
{
24492449
return ldfile_open_file_search (name, entry, "", ".lib");
24502450
}
2451+
2452+
static struct bfd_link_hash_entry *
2453+
gld${EMULATION_NAME}_find_alt_start_symbol
2454+
(struct bfd_sym_chain *entry)
2455+
{
2456+
#if defined (TARGET_IS_i386pe)
2457+
bool entry_has_stdcall_suffix;
2458+
#endif
2459+
struct bfd_link_hash_entry *h;
2460+
size_t entry_name_len;
2461+
char *symbol_name;
2462+
const char *prefix;
2463+
const char *suffix;
2464+
2465+
entry_name_len = strlen (entry->name);
2466+
2467+
if (is_underscoring ())
2468+
prefix = "_";
2469+
else
2470+
prefix = "";
2471+
2472+
#if defined (TARGET_IS_i386pe)
2473+
if ((entry_name_len > 2 && entry->name[entry_name_len-2] == '@' && ISDIGIT (entry->name[entry_name_len-1]))
2474+
|| (entry_name_len > 3 && entry->name[entry_name_len-3] == '@' && ISDIGIT (entry->name[entry_name_len-2]) && ISDIGIT (entry->name[entry_name_len-1]))
2475+
|| (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])))
2476+
entry_has_stdcall_suffix = true;
2477+
else
2478+
entry_has_stdcall_suffix = false;
2479+
2480+
if (!entry_has_stdcall_suffix && (bfd_link_dll (&link_info) || dll))
2481+
suffix = "@12";
2482+
else if (!entry_has_stdcall_suffix && pe_subsystem == 1 /* NT kernel driver */)
2483+
suffix = "@8";
2484+
else
2485+
#endif
2486+
suffix = "";
2487+
2488+
if (*prefix == '\0' && *suffix == '\0')
2489+
return NULL;
2490+
2491+
symbol_name = xmalloc (entry_name_len + 5);
2492+
strcpy (symbol_name, prefix);
2493+
strcat (symbol_name, entry->name);
2494+
strcat (symbol_name, suffix);
2495+
2496+
h = bfd_link_hash_lookup (link_info.hash, symbol_name, false, false, true);
2497+
free (symbol_name);
2498+
return h;
2499+
}
24512500

24522501
static char *
24532502
gld${EMULATION_NAME}_get_script (int *isfile)
@@ -2526,5 +2575,6 @@ LDEMUL_UNRECOGNIZED_FILE=gld${EMULATION_NAME}_unrecognized_file
25262575
LDEMUL_LIST_OPTIONS=gld${EMULATION_NAME}_list_options
25272576
LDEMUL_RECOGNIZED_FILE=gld${EMULATION_NAME}_recognized_file
25282577
LDEMUL_FIND_POTENTIAL_LIBRARIES=gld${EMULATION_NAME}_find_potential_libraries
2578+
LDEMUL_FIND_START_SYMBOL=gld${EMULATION_NAME}_find_alt_start_symbol
25292579

25302580
source_em ${srcdir}/emultempl/emulation.em

ld/ld.texi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,9 @@ named @var{entry}, the linker will try to parse @var{entry} as a number,
531531
and use that as the entry address (the number will be interpreted in
532532
base 10; you may use a leading @samp{0x} for base 16, or a leading
533533
@samp{0} for base 8). @xref{Entry Point}, for a discussion of defaults
534-
and other ways of specifying the entry point.
534+
and other ways of specifying the entry point. For i386 PE, @var{entry}
535+
can be also the original function name (without the leading underscore
536+
and/or the trailing stdcall @samp{@@number} when applicable).
535537

536538
@kindex --exclude-libs
537539
@item --exclude-libs @var{lib},@var{lib},...

ld/ldemul.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@
3535

3636
static ld_emulation_xfer_type *ld_emulation;
3737

38+
struct bfd_link_hash_entry *
39+
ldemul_find_alt_start_symbol (struct bfd_sym_chain *entry)
40+
{
41+
if (ld_emulation->find_alt_start_symbol)
42+
return ld_emulation->find_alt_start_symbol (entry);
43+
return NULL;
44+
}
45+
3846
void
3947
ldemul_hll (char *name)
4048
{

ld/ldemul.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,10 @@ extern void ldemul_acquire_strings_for_ctf
115115
(struct ctf_dict *, struct elf_strtab_hash *);
116116
extern void ldemul_new_dynsym_for_ctf
117117
(struct ctf_dict *, int symidx, struct elf_internal_sym *);
118-
119118
extern bool ldemul_print_symbol
120119
(struct bfd_link_hash_entry *hash_entry, void *ptr);
120+
extern struct bfd_link_hash_entry * ldemul_find_alt_start_symbol
121+
(struct bfd_sym_chain *);
121122

122123
typedef struct ld_emulation_xfer_struct {
123124
/* Run before parsing the command line and script file.
@@ -259,6 +260,11 @@ typedef struct ld_emulation_xfer_struct {
259260
bool (*print_symbol)
260261
(struct bfd_link_hash_entry *hash_entry, void *ptr);
261262

263+
/* Called when ENTRY->name cannot be found by a direct lookup in INFO->hash.
264+
Allows emulations to try variations of the name. */
265+
struct bfd_link_hash_entry * (*find_alt_start_symbol)
266+
(struct bfd_sym_chain *entry);
267+
262268
} ld_emulation_xfer_type;
263269

264270
typedef enum {

ld/ldlang.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,12 +2485,19 @@ lang_map (void)
24852485
config.map_file);
24862486
}
24872487

2488+
static bool
2489+
is_defined (struct bfd_link_hash_entry *h)
2490+
{
2491+
return h != NULL
2492+
&& (h->type == bfd_link_hash_defined
2493+
|| h->type == bfd_link_hash_defweak);
2494+
}
2495+
24882496
static bool
24892497
sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
24902498
void *info ATTRIBUTE_UNUSED)
24912499
{
2492-
if ((hash_entry->type == bfd_link_hash_defined
2493-
|| hash_entry->type == bfd_link_hash_defweak)
2500+
if (is_defined (hash_entry)
24942501
&& hash_entry->u.def.section->owner != link_info.output_bfd
24952502
&& hash_entry->u.def.section->owner != NULL)
24962503
{
@@ -4184,9 +4191,7 @@ ldlang_check_require_defined_symbols (void)
41844191

41854192
h = bfd_link_hash_lookup (link_info.hash, ptr->name,
41864193
false, false, true);
4187-
if (h == NULL
4188-
|| (h->type != bfd_link_hash_defined
4189-
&& h->type != bfd_link_hash_defweak))
4194+
if (! is_defined (h))
41904195
einfo(_("%X%P: required symbol `%s' not defined\n"), ptr->name);
41914196
}
41924197
}
@@ -4892,9 +4897,7 @@ print_assignment (lang_assignment_statement_type *assignment,
48924897

48934898
h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
48944899
false, false, true);
4895-
if (h != NULL
4896-
&& (h->type == bfd_link_hash_defined
4897-
|| h->type == bfd_link_hash_defweak))
4900+
if (is_defined (h))
48984901
{
48994902
value = h->u.def.value;
49004903
value += h->u.def.section->output_section->vma;
@@ -4939,8 +4942,7 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
49394942
{
49404943
asection *sec = (asection *) ptr;
49414944

4942-
if ((hash_entry->type == bfd_link_hash_defined
4943-
|| hash_entry->type == bfd_link_hash_defweak)
4945+
if (is_defined (hash_entry)
49444946
&& sec == hash_entry->u.def.section)
49454947
{
49464948
print_spaces (SECTION_NAME_MAP_LENGTH);
@@ -7234,9 +7236,7 @@ lang_end (void)
72347236
{
72357237
h = bfd_link_hash_lookup (link_info.hash, sym->name,
72367238
false, false, false);
7237-
if (h != NULL
7238-
&& (h->type == bfd_link_hash_defined
7239-
|| h->type == bfd_link_hash_defweak)
7239+
if (is_defined (h)
72407240
&& !bfd_is_const_section (h->u.def.section))
72417241
break;
72427242
}
@@ -7255,9 +7255,11 @@ lang_end (void)
72557255

72567256
h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
72577257
false, false, true);
7258-
if (h != NULL
7259-
&& (h->type == bfd_link_hash_defined
7260-
|| h->type == bfd_link_hash_defweak)
7258+
7259+
if (! is_defined (h) || h->u.def.section->output_section == NULL)
7260+
h = ldemul_find_alt_start_symbol (&entry_symbol);
7261+
7262+
if (is_defined (h)
72617263
&& h->u.def.section->output_section != NULL)
72627264
{
72637265
bfd_vma val;

0 commit comments

Comments
 (0)