ld: don't generate base relocations in PE output for absolute symbols

It is the very nature of absolute symbols that they don't change even
if the loader decides to put the image at other than its link-time base
address. Of the linker-defined (and PE-specific) symbols __image_base__
(and its alias) needs special casing, as it'll still appear to be
absolute at this point.

A new inquiry function in ldexp.c is needed because PE base relocations
get generated before ldexp_finalize_syms() runs, yet whether a
relocation is needed depends on the ultimate property of a symbol.
This commit is contained in:
Jan Beulich 2021-03-04 16:55:01 +01:00
parent 1178743e4c
commit 6fa7408d72
7 changed files with 69 additions and 3 deletions

View file

@ -1,3 +1,11 @@
2021-03-04 Jan Beulich <jbeulich@suse.com>
* ldexp.c (ldexp_is_final_sym_absolute): New.
* ldexp.h (ldexp_is_final_sym_absolute): Declare.
* pe-dll.c (generate_reloc): Skip absolute symbols.
* testsuite/ld-pe/reloc.s, testsuite/ld-pe/reloc.d: New.
* testsuite/ld-pe/pe.exp: Run new test.
2021-03-03 Alan Modra <amodra@gmail.com>
PR 27500

View file

@ -1699,6 +1699,28 @@ ldexp_finalize_syms (void)
bfd_hash_traverse (&definedness_table, set_sym_sections, NULL);
}
/* Determine whether a symbol is going to remain absolute even after
ldexp_finalize_syms() has run. */
bfd_boolean
ldexp_is_final_sym_absolute (const struct bfd_link_hash_entry *h)
{
if (h->type == bfd_link_hash_defined
&& h->u.def.section == bfd_abs_section_ptr)
{
const struct definedness_hash_entry *def;
if (!h->ldscript_def)
return TRUE;
def = symbol_defined (h->root.string);
if (def != NULL)
return def->final_sec == bfd_abs_section_ptr;
}
return FALSE;
}
void
ldexp_finish (void)
{

View file

@ -239,6 +239,7 @@ bfd_vma exp_get_abs_int
(etree_type *, int, char *);
void ldexp_init (void);
void ldexp_finalize_syms (void);
bfd_boolean ldexp_is_final_sym_absolute (const struct bfd_link_hash_entry *);
void ldexp_finish (void);
#endif

View file

@ -1579,13 +1579,13 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
&& relocs[i]->howto->type != pe_details->imagebase_reloc)
{
struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
const struct bfd_link_hash_entry *blhe
= bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
FALSE, FALSE, FALSE);
/* Don't create relocs for undefined weak symbols. */
if (sym->flags == BSF_WEAK)
{
struct bfd_link_hash_entry *blhe
= bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
FALSE, FALSE, FALSE);
if (blhe && blhe->type == bfd_link_hash_undefweak)
{
/* Check aux sym and see if it is defined or not. */
@ -1617,6 +1617,12 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
if (!strcmp (s->name, ".eh_frame"))
continue;
}
/* Nor for absolute symbols. */
else if (blhe && ldexp_is_final_sym_absolute (blhe)
&& (!blhe->linker_def
|| (strcmp (sym->name, "__image_base__")
&& strcmp (sym->name, U ("__ImageBase")))))
continue;
reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
reloc_data[total_relocs].idx = total_relocs;

View file

@ -76,6 +76,8 @@ run_dump_test "longsecn-5"
run_dump_test "orphan"
run_dump_test "orphan_nu"
run_dump_test "reloc"
run_dump_test "weakdef-1"
run_dump_test "pr19803"

View file

@ -0,0 +1,14 @@
#name: PE base relocations
#ld: --enable-reloc-section
#objdump: -p
.*: file format .*
#...
PE File Base Relocations.*
Virtual Address: .* Number of fixups 4
[ ]*reloc 0 offset 0 .* (LOW|HIGHLOW|DIR64)
[ ]*reloc 1 offset [248] .* (LOW|HIGHLOW|DIR64)
[ ]*reloc 2 offset [124]0 .* (LOW|HIGHLOW|DIR64)
[ ]*reloc 3 offset 0 .* ABSOLUTE
#pass

View file

@ -0,0 +1,13 @@
.data
.p2align 4
start:
.dc.a __image_base__
.dc.a start
.dc.a __section_alignment__
.dc.a __file_alignment__
.dc.a __major_os_version__
.dc.a __minor_os_version__
.dc.a __major_subsystem_version__
.dc.a __minor_subsystem_version__
.dc.a end
end: