From 6fa7408d72b3805536e3579ba46b48f07f2e780a Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 4 Mar 2021 16:55:01 +0100 Subject: [PATCH] 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. --- ld/ChangeLog | 8 ++++++++ ld/ldexp.c | 22 ++++++++++++++++++++++ ld/ldexp.h | 1 + ld/pe-dll.c | 12 +++++++++--- ld/testsuite/ld-pe/pe.exp | 2 ++ ld/testsuite/ld-pe/reloc.d | 14 ++++++++++++++ ld/testsuite/ld-pe/reloc.s | 13 +++++++++++++ 7 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 ld/testsuite/ld-pe/reloc.d create mode 100644 ld/testsuite/ld-pe/reloc.s diff --git a/ld/ChangeLog b/ld/ChangeLog index 0f1da7fafab..95bb3f6c1a8 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2021-03-04 Jan Beulich + + * 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 PR 27500 diff --git a/ld/ldexp.c b/ld/ldexp.c index 016784505b2..7a95e561a03 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -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) { diff --git a/ld/ldexp.h b/ld/ldexp.h index d6096175c05..1055053e28d 100644 --- a/ld/ldexp.h +++ b/ld/ldexp.h @@ -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 diff --git a/ld/pe-dll.c b/ld/pe-dll.c index 3c82f8d60d9..afcf6fea93e 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -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; diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp index de9e104f0f6..b1a200180be 100644 --- a/ld/testsuite/ld-pe/pe.exp +++ b/ld/testsuite/ld-pe/pe.exp @@ -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" diff --git a/ld/testsuite/ld-pe/reloc.d b/ld/testsuite/ld-pe/reloc.d new file mode 100644 index 00000000000..55888c3bdf1 --- /dev/null +++ b/ld/testsuite/ld-pe/reloc.d @@ -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 diff --git a/ld/testsuite/ld-pe/reloc.s b/ld/testsuite/ld-pe/reloc.s new file mode 100644 index 00000000000..3ed2e02e70d --- /dev/null +++ b/ld/testsuite/ld-pe/reloc.s @@ -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: -- 2.30.2