Linker generated relative relocations don't have symbol info:
[hjl@gnu-cfl-2 tmpdir]$ readelf -rW dump
Relocation section '.rela.dyn' at offset 0x180 contains 2 entries:
Offset Info Type Sym. Value Symbol's Name + Addend
00002f70 00000008 R_X86_64_RELATIVE 1000
00002f68 00000025 R_X86_64_IRELATIVE 1007
[hjl@gnu-cfl-2 tmpdir]$
Add -z report-relative-reloc to x86 ELF linker to report dynamic relative
relocations:
[hjl@gnu-cfl-2 tmpdir]$ ../ld-new -pie -melf32_x86_64 -z report-relative-reloc -o dump report-reloc-1.o
dump: R_X86_64_IRELATIVE (offset: 0x00002f68, info: 0x00000025, addend: 0x00001007) against 'ifunc' for section '.data.rel.ro.local' in report-reloc-1.o
dump: R_X86_64_RELATIVE (offset: 0x00002f70, info: 0x00000008, addend: 0x00001000) against '_start' for section '.data.rel.ro.local' in report-reloc-1.o
[hjl@gnu-cfl-2 tmpdir]$
It can be used to map relative relocations to corresponding symbols.
bfd/
* elf-linker-x86.h (elf_linker_x86_params): Add
report_relative_reloc.
* elf32-i386.c (elf_i386_relocate_section): Call
_bfd_x86_elf_link_report_relative_reloc to report relative
relocations for -z report-relative-reloc.
(elf_i386_finish_dynamic_symbol): Likewse.
* elf64-x86-64.c (elf_x86_64_relocate_section): Likewse.
(elf_x86_64_finish_dynamic_symbol): Likewse.
* elfxx-x86.c (_bfd_x86_elf_link_report_relative_reloc): New
function.
* elfxx-x86.h (_bfd_x86_elf_link_report_relative_reloc): New
prototype.
ld/
* NEWS: Mention -z report-relative-reloc.
* ld.texi: Document -z report-relative-reloc.
* emulparams/elf32_x86_64.sh: Source x86-report-relative.sh.
* emulparams/elf_i386.sh: Likewse.
* emulparams/elf_x86_64.sh: Likewse.
* emulparams/x86-report-relative.sh: New file.
* testsuite/ld-i386/report-reloc-1.d: Likewse.
* testsuite/ld-i386/report-reloc-1.l: Likewse.
* testsuite/ld-i386/report-reloc-1.s: Likewse.
* testsuite/ld-x86-64/report-reloc-1-x32.d: Likewse.
* testsuite/ld-x86-64/report-reloc-1.d: Likewse.
* testsuite/ld-x86-64/report-reloc-1.l: Likewse.
* testsuite/ld-x86-64/report-reloc-1.s: Likewse.
* testsuite/ld-i386/i386.exp: Run report-reloc-1.
* testsuite/ld-x86-64/x86-64.exp: Run report-reloc-1 and
report-reloc-1-x32.
+2021-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf-linker-x86.h (elf_linker_x86_params): Add
+ report_relative_reloc.
+ * elf32-i386.c (elf_i386_relocate_section): Call
+ _bfd_x86_elf_link_report_relative_reloc to report relative
+ relocations for -z report-relative-reloc.
+ (elf_i386_finish_dynamic_symbol): Likewse.
+ * elf64-x86-64.c (elf_x86_64_relocate_section): Likewse.
+ (elf_x86_64_finish_dynamic_symbol): Likewse.
+ * elfxx-x86.c (_bfd_x86_elf_link_report_relative_reloc): New
+ function.
+ * elfxx-x86.h (_bfd_x86_elf_link_report_relative_reloc): New
+ prototype.
+
2021-01-16 Alan Modra <amodra@gmail.com>
* compress.c (decompress_contents): Tidy inflateEnd result test.
/* TRUE if --dynamic-linker is passed at command-line. */
unsigned int has_dynamic_linker : 1;
+ /* Report relative relocations. */
+ unsigned int report_relative_reloc : 1;
+
/* X86-64 ISA level needed. */
unsigned int isa_level;
/* This symbol is resolved locally. */
outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, input_section, h, sym,
+ "R_386_IRELATIVE", &outrel);
+
bfd_put_32 (output_bfd,
(h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ htab->elf.sgot->output_offset
+ off);
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, input_section, h, sym, "R_386_RELATIVE",
+ &outrel);
+
elf_append_rel (output_bfd, s, &outrel);
}
/* This symbol is local, or marked to become local. */
relocate = TRUE;
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, input_section, h, sym, "R_386_RELATIVE",
+ &outrel);
}
sreloc = elf_section_data (input_section)->sreloc;
+ input_section->output_section->vma
+ input_section->output_offset;
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, input_section, h, sym, "R_386_RELATIVE",
+ &outrel);
+
sreloc = elf_section_data (input_section)->sreloc;
if (sreloc == NULL)
abort ();
+ h->root.u.def.section->output_offset),
gotplt->contents + got_offset);
rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, relplt, h, sym, "R_386_IRELATIVE", &rel);
+
/* R_386_IRELATIVE comes last. */
plt_index = htab->next_irelative_index--;
}
{
Elf_Internal_Rela rel;
asection *relgot = htab->elf.srelgot;
+ const char *relative_reloc_name = NULL;
/* This symbol has an entry in the global offset table. Set it
up. */
+ h->root.u.def.section->output_offset),
htab->elf.sgot->contents + h->got.offset);
rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+ relative_reloc_name = "R_386_IRELATIVE";
}
else
goto do_glob_dat;
{
BFD_ASSERT((h->got.offset & 1) != 0);
rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ relative_reloc_name = "R_386_RELATIVE";
}
else
{
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
}
+ if (relative_reloc_name != NULL
+ && htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, relgot, h, sym, relative_reloc_name, &rel);
+
elf_append_rel (output_bfd, relgot, &rel);
}
outrel.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, input_section, h, sym,
+ "R_X86_64_IRELATIVE", &outrel);
}
else
{
+ off);
outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE);
outrel.r_addend = relocation;
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, input_section, h, sym, "R_X86_64_RELATIVE",
+ &outrel);
+
elf_append_rela (output_bfd, s, &outrel);
}
Elf_Internal_Rela outrel;
bfd_boolean skip, relocate;
asection *sreloc;
+ const char *relative_reloc_name = NULL;
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
relocate = TRUE;
outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE);
outrel.r_addend = relocation + rel->r_addend;
+ relative_reloc_name = "R_X86_64_RELATIVE";
}
else if (r_type == R_X86_64_64
&& !ABI_64_P (output_bfd))
outrel.r_info = htab->r_info (0,
R_X86_64_RELATIVE64);
outrel.r_addend = relocation + rel->r_addend;
+ relative_reloc_name = "R_X86_64_RELATIVE64";
/* Check addend overflow. */
if ((outrel.r_addend & 0x80000000)
!= (rel->r_addend & 0x80000000))
goto check_relocation_error;
}
+ if (relative_reloc_name
+ && htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, input_section, h, sym, relative_reloc_name,
+ &outrel);
+
elf_append_rela (output_bfd, sreloc, &outrel);
/* If this reloc is against an external symbol, we do
rela.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+
+ if (htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, relplt, h, sym, "R_X86_64_IRELATIVE", &rela);
+
/* R_X86_64_IRELATIVE comes last. */
plt_index = htab->next_irelative_index--;
}
{
Elf_Internal_Rela rela;
asection *relgot = htab->elf.srelgot;
+ const char *relative_reloc_name = NULL;
/* This symbol has an entry in the global offset table. Set it
up. */
rela.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+ relative_reloc_name = "R_X86_64_IRELATIVE";
}
else
goto do_glob_dat;
rela.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+ relative_reloc_name = "R_X86_64_RELATIVE";
}
else
{
rela.r_addend = 0;
}
+ if (relative_reloc_name != NULL
+ && htab->params->report_relative_reloc)
+ _bfd_x86_elf_link_report_relative_reloc
+ (info, relgot, h, sym, relative_reloc_name, &rela);
+
elf_append_rela (output_bfd, relgot, &rela);
}
}
}
+/* Report relative relocation. */
+
+void
+_bfd_x86_elf_link_report_relative_reloc
+ (struct bfd_link_info *info, asection *asect,
+ struct elf_link_hash_entry *h, Elf_Internal_Sym *sym,
+ const char *reloc_name, const void *reloc)
+{
+ const char *name;
+ bfd *abfd;
+ const Elf_Internal_Rela *rel = (const Elf_Internal_Rela *) reloc;
+ char r_offset[30], r_info[30];
+
+ /* Use the output BFD for linker created sections. */
+ if ((asect->flags & SEC_LINKER_CREATED) != 0)
+ abfd = info->output_bfd;
+ else
+ abfd = asect->owner;
+
+ if (h != NULL && h->root.root.string != NULL)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (abfd, &elf_symtab_hdr (abfd), sym, NULL);
+
+ bfd_sprintf_vma (abfd, r_offset, rel->r_offset);
+ bfd_sprintf_vma (abfd, r_info, rel->r_info);
+
+ if (asect->use_rela_p)
+ {
+ char r_addend[30];
+
+ bfd_sprintf_vma (abfd, r_addend, rel->r_addend);
+
+ info->callbacks->einfo
+ (_("%pB: %s (offset: 0x%s, info: 0x%s, addend: 0x%s) against "
+ "'%s' " "for section '%pA' in %pB\n"),
+ info->output_bfd, reloc_name, r_offset, r_info, r_addend,
+ name, asect, abfd);
+ }
+ else
+ info->callbacks->einfo
+ (_("%pB: %s (offset: 0x%s, info: 0x%s) against '%s' for section "
+ "'%pA' in %pB\n"),
+ info->output_bfd, reloc_name, r_offset, r_info, name,
+ asect, abfd);
+}
+
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
bfd_boolean
(struct bfd_link_info *, struct elf_x86_link_hash_table *,
struct elf_link_hash_entry *, Elf_Internal_Sym *sym);
+extern void _bfd_x86_elf_link_report_relative_reloc
+ (struct bfd_link_info *, asection *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *, const char *, const void *);
+
#define bfd_elf64_mkobject \
_bfd_x86_elf_mkobject
#define bfd_elf32_mkobject \
+2021-01-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * NEWS: Mention -z report-relative-reloc.
+ * ld.texi: Document -z report-relative-reloc.
+ * emulparams/elf32_x86_64.sh: Source x86-report-relative.sh.
+ * emulparams/elf_i386.sh: Likewse.
+ * emulparams/elf_x86_64.sh: Likewse.
+ * emulparams/x86-report-relative.sh: New file.
+ * testsuite/ld-i386/report-reloc-1.d: Likewse.
+ * testsuite/ld-i386/report-reloc-1.l: Likewse.
+ * testsuite/ld-i386/report-reloc-1.s: Likewse.
+ * testsuite/ld-x86-64/report-reloc-1-x32.d: Likewse.
+ * testsuite/ld-x86-64/report-reloc-1.d: Likewse.
+ * testsuite/ld-x86-64/report-reloc-1.l: Likewse.
+ * testsuite/ld-x86-64/report-reloc-1.s: Likewse.
+ * testsuite/ld-i386/i386.exp: Run report-reloc-1.
+ * testsuite/ld-x86-64/x86-64.exp: Run report-reloc-1 and
+ report-reloc-1-x32.
+
2021-01-16 Alan Modra <amodra@gmail.com>
PR 26002
-*- text -*-
+* Add -z report-relative-reloc to x86 ELF linker to report dynamic
+ relative relocations.
+
Changes in 2.36:
* Add libdep plugin, for linking dependencies of static libraries that
source_sh ${srcdir}/emulparams/reloc_overflow.sh
source_sh ${srcdir}/emulparams/call_nop.sh
source_sh ${srcdir}/emulparams/cet.sh
+source_sh ${srcdir}/emulparams/x86-report-relative.sh
source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/static.sh
SCRIPT_NAME=elf
source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
source_sh ${srcdir}/emulparams/call_nop.sh
source_sh ${srcdir}/emulparams/cet.sh
+source_sh ${srcdir}/emulparams/x86-report-relative.sh
source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/static.sh
SCRIPT_NAME=elf
source_sh ${srcdir}/emulparams/reloc_overflow.sh
source_sh ${srcdir}/emulparams/call_nop.sh
source_sh ${srcdir}/emulparams/cet.sh
+source_sh ${srcdir}/emulparams/x86-report-relative.sh
source_sh ${srcdir}/emulparams/x86-64-level.sh
source_sh ${srcdir}/emulparams/x86-64-lam.sh
source_sh ${srcdir}/emulparams/static.sh
--- /dev/null
+PARSE_AND_LIST_OPTIONS_X86_REPORT_RELATIVE='
+ fprintf (file, _("\
+ -z report-relative-reloc Report relative relocations\n"));
+'
+PARSE_AND_LIST_ARGS_CASE_Z_X86_REPORT_RELATIVE='
+ else if (strcmp (optarg, "report-relative-reloc") == 0)
+ params.report_relative_reloc = 1;
+'
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_X86_REPORT_RELATIVE"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_X86_REPORT_RELATIVE"
than the system page size will render this protection ineffective.
Don't create an ELF @code{PT_GNU_RELRO} segment if @samp{norelro}.
+@item report-relative-reloc
+Report dynamic relative relocations generated by linker. Supported for
+Linux/i386 and Linux/x86_64.
+
@item separate-code
@itemx noseparate-code
Create separate code @code{PT_LOAD} segment header in the object. This
run_dump_test "pr19939a"
run_dump_test "pr19939b"
run_dump_test "tlsdesc2"
+run_dump_test "report-reloc-1"
proc undefined_weak {cflags ldflags} {
set testname "Undefined weak symbol"
--- /dev/null
+#source: report-reloc-1.s
+#as: --32
+#ld: -pie -melf_i386 -z report-relative-reloc
+#warning_output: report-reloc-1.l
+#readelf: -r --wide
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name
+[0-9a-f]+ +[0-9a-f]+ +R_386_RELATIVE +
+[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE +
--- /dev/null
+tmpdir/dump: R_386_IRELATIVE \(offset: 0x0+2000, info: 0x0+2a\) against 'ifunc' for section '.data.rel.ro.local' in tmpdir/report-reloc-1.o
+tmpdir/dump: R_386_RELATIVE \(offset: 0x0+2004, info: 0x0+8\) against '_start' for section '.data.rel.ro.local' in tmpdir/report-reloc-1.o
--- /dev/null
+ .text
+ .globl _start
+ .type ifunc, @gnu_indirect_function
+_start:
+ lea .Ljmp@GOTOFF(%ebx), %eax
+ifunc:
+ jmp *(%eax)
+ .section .data.rel.ro.local,"aw",@progbits
+ .align 4
+.Ljmp:
+ .long ifunc
+ .long _start
--- /dev/null
+#source: report-reloc-1.s
+#as: --x32
+#ld: -pie -melf32_x86_64 -z report-relative-reloc
+#warning_output: report-reloc-1.l
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
--- /dev/null
+#source: report-reloc-1.s
+#as: --64
+#ld: -pie -melf_x86_64 -z report-relative-reloc
+#warning_output: report-reloc-1.l
+#readelf: -r --wide
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ +Offset +Info +Type +Sym.* Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+
+[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+
--- /dev/null
+tmpdir/dump: R_X86_64_IRELATIVE \(offset: 0x0+2000, info: 0x0+25, addend: 0x0+1007\) against 'ifunc' for section '.data.rel.ro.local' in tmpdir/report-reloc-1.o
+tmpdir/dump: R_X86_64_RELATIVE \(offset: 0x0+2008, info: 0x0+8, addend: 0x0+1000\) against '_start' for section '.data.rel.ro.local' in tmpdir/report-reloc-1.o
--- /dev/null
+ .text
+ .globl _start
+ .type ifunc, @gnu_indirect_function
+_start:
+ lea .Ljmp(%rip), %rax
+ifunc:
+ jmp *(%rax)
+ .section .data.rel.ro.local,"aw",@progbits
+ .align 8
+.Ljmp:
+ .quad ifunc
+ .quad _start
run_dump_test "pr26939-x32"
run_dump_test "pr27016a"
run_dump_test "pr27016b"
+run_dump_test "report-reloc-1"
+run_dump_test "report-reloc-1-x32"
proc undefined_weak {cflags ldflags} {
set testname "Undefined weak symbol"