diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-03-13 19:40:18 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-03-14 06:07:56 -0700 |
commit | c6ebff7349b602bdd670e9c170cb4aa111a293a7 (patch) | |
tree | b9ad30bcb99fb97257c235c673ce7bf1d81e7bfe | |
parent | 2159c3f1e6c191b1f80b8160caa92bccae2eb8f0 (diff) | |
download | binutils-gdb-users/hjl/pr19807.tar.gz |
Add -z upper-address=ADDRESS option to x86-64 ldusers/hjl/pr19807
Add -z upper-address=ADDRESS command-line option to the x86-64 ELF
linker to limit the upper load address to ADDRESS. This can be used
to avoid relocation overflow in PIE if PIE will only be loaded below
ADDRESS at run-time.
bfd/
PR ld/19807
* elf64-x86-64.c (elf_x86_64_relocate_section): Check
upper_address for R_X86_64_32/R_X86_64_32S relocation overflow.
include/
PR ld/19807
* bfdlink.h (bfd_link_info): Add upper_address.
ld/
PR ld/19807
* Makefile.am (ELF_X86_DEPS): Add
$(srcdir)/emulparams/upper_address.sh.
* Makefile.in: Regenerated.
* NEWS: Mention -z upper-address=ADDRESS.
* ld.texinfo: Document -z upper-address=ADDRESS.
* ldmain.c (main): Initialize link_info.upper_address to -1.
* emulparams/elf32_x86_64.sh: Source
${srcdir}/emulparams/upper_address.sh.
* emulparams/elf_x86_64.sh: Likewise.
* emulparams/upper_address.sh: New file.
* testsuite/ld-x86-64/pr19807-1a.d: New file.
* testsuite/ld-x86-64/pr19807-1a.s: Likewise.
* testsuite/ld-x86-64/pr19807-1b.d: Likewise.
* testsuite/ld-x86-64/pr19807-1b.s: Likewise.
* testsuite/ld-x86-64/pr19807-1b.d: Likewise.
* testsuite/ld-x86-64/pr19807-1c.d: Likewise.
* testsuite/ld-x86-64/pr19807-1d.d: Likewise.
* testsuite/ld-x86-64/pr19807-1e.d: Likewise.
* testsuite/ld-x86-64/pr19807-1f.d: Likewise.
* testsuite/ld-x86-64/pr19807-1g.d: Likewise.
* testsuite/ld-x86-64/pr19807-1h.d: Likewise.
* testsuite/ld-x86-64/pr19807-2.s: Likewise.
* testsuite/ld-x86-64/pr19807-2a.d: Likewise.
* testsuite/ld-x86-64/pr19807-2b.d: Likewise.
* testsuite/ld-x86-64/pr19807-2c.d: Likewise.
* testsuite/ld-x86-64/pr19807-2d.d: Likewise.
* testsuite/ld-x86-64/pr19807-3.s: Likewise.
* testsuite/ld-x86-64/pr19807-3a.d: Likewise.
* testsuite/ld-x86-64/pr19807-3b.d: Likewise.
* testsuite/ld-x86-64/pr19807-3c.d: Likewise.
* testsuite/ld-x86-64/pr19807-3d.d: Likewise.
* testsuite/ld-x86-64/pr19807-3e.d: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run PR ld/19807 tests.
32 files changed, 228 insertions, 3 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 35198713710..3d2453fc432 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -4745,8 +4745,11 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (resolved_to_zero_or_abs) break; - if ((ABI_64_P (output_bfd) - || r_type == R_X86_64_32S) + if (((r_type == R_X86_64_32 + && info->upper_address > 0xffffffff + && ABI_64_P (output_bfd)) + || (r_type == R_X86_64_32S + && info->upper_address > 0x7fffffff)) && (input_section->flags & SEC_ALLOC) != 0 && (input_section->flags & SEC_READONLY) != 0 && bfd_link_pic (info)) @@ -4901,7 +4904,8 @@ direct: else { /* This symbol is local, or marked to become local. */ - if (r_type == htab->pointer_r_type) + if (info->upper_address <= 0xffffffff + || r_type == htab->pointer_r_type) { relocate = TRUE; outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); diff --git a/include/bfdlink.h b/include/bfdlink.h index eeea6ef7a97..17810d84b57 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -463,6 +463,9 @@ struct bfd_link_info /* Compress DWARF debug sections. */ enum compressed_debug_section_type compress_debug; + /* Default upper load address. Default is unlimited. */ + bfd_vma upper_address; + /* Default stack size. Zero means default (often zero itself), -1 means explicitly zero-sized. */ bfd_signed_vma stacksize; diff --git a/ld/Makefile.am b/ld/Makefile.am index 4a8c0b6e875..34db8fa29f0 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -672,6 +672,7 @@ ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \ $(srcdir)/emulparams/extern_protected_data.sh \ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ + $(srcdir)/emulparams/upper_address.sh \ $(srcdir)/emulparams/call_nop.sh @TDIRS@ diff --git a/ld/Makefile.in b/ld/Makefile.in index 45388d7bacf..4ceab2b740d 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -888,6 +888,7 @@ ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \ $(srcdir)/emulparams/extern_protected_data.sh \ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ + $(srcdir)/emulparams/upper_address.sh \ $(srcdir)/emulparams/call_nop.sh @@ -1,5 +1,8 @@ -*- text -*- +* Support for -z upper-address=ADDRESS in the x86-64 ELF linker, which + limits the upper load address to ADDRESS. + * Add -z common/-z nocommon options for ELF targets to control whether to convert common symbols to the STT_COMMON type during a relocatable link. diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh index 1b285c559a1..cae27f377e0 100644 --- a/ld/emulparams/elf32_x86_64.sh +++ b/ld/emulparams/elf32_x86_64.sh @@ -1,6 +1,7 @@ . ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/dynamic_undefined_weak.sh +. ${srcdir}/emulparams/upper_address.sh . ${srcdir}/emulparams/call_nop.sh SCRIPT_NAME=elf ELFSIZE=32 diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh index 0159a6ca44c..a4919e3a09d 100644 --- a/ld/emulparams/elf_x86_64.sh +++ b/ld/emulparams/elf_x86_64.sh @@ -1,6 +1,7 @@ . ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/dynamic_undefined_weak.sh +. ${srcdir}/emulparams/upper_address.sh . ${srcdir}/emulparams/call_nop.sh SCRIPT_NAME=elf ELFSIZE=64 diff --git a/ld/emulparams/upper_address.sh b/ld/emulparams/upper_address.sh new file mode 100644 index 00000000000..9121666805d --- /dev/null +++ b/ld/emulparams/upper_address.sh @@ -0,0 +1,17 @@ +PARSE_AND_LIST_OPTIONS_UPPER_ADDRESS=' + fprintf (file, _("\ + -z upper-address=ADDRESS Limit upper load address to ADDRESS\n")); +' +PARSE_AND_LIST_ARGS_CASE_Z_UPPER_ADDRESS=' + else if (strncmp (optarg, "upper-address=", 14) == 0) + { + const char *end; + link_info.upper_address = bfd_scan_vma (optarg + 14, &end, 16); + if (*end) + einfo (_("%P%F: invalid hex number for -z upper-address=: %s\n"), + optarg + 14); + } +' + +PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_UPPER_ADDRESS" +PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_UPPER_ADDRESS" diff --git a/ld/ld.texinfo b/ld/ld.texinfo index b2b99ab6605..ce77cf642b3 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1213,6 +1213,11 @@ This option overrides linker backend default. It can be used to avoid dynamic relocations against undefined weak symbols in executable. Supported for i386 and x86-64. +@item upper-address=@var{address} +Limit the upper load address to @var{address}. This can be used to +avoid relocation overflow in PIE if PIE will only be loaded below +@var{address} at run-time. Supported for x86_64. + @item call-nop=prefix-addr @itemx call-nop=prefix-nop @itemx call-nop=suffix-nop diff --git a/ld/ldmain.c b/ld/ldmain.c index 21133ab7209..916479a2ed0 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -285,6 +285,7 @@ main (int argc, char **argv) #ifdef DEFAULT_FLAG_COMPRESS_DEBUG link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB; #endif + link_info.upper_address = (bfd_vma) -1; ldfile_add_arch (""); emulation = get_emulation (argc, argv); diff --git a/ld/testsuite/ld-x86-64/pr19807-1a.d b/ld/testsuite/ld-x86-64/pr19807-1a.d new file mode 100644 index 00000000000..fc8d342c446 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1a.d @@ -0,0 +1,6 @@ +#source: pr19807-1a.s +#as: --64 +#ld: -pie -melf_x86_64 --defsym foo=0x7fffffff +#readelf: -r --wide + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/pr19807-1a.s b/ld/testsuite/ld-x86-64/pr19807-1a.s new file mode 100644 index 00000000000..b8aa0a2dbdc --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1a.s @@ -0,0 +1,5 @@ + .globl _start + .type _start, @function +_start: + movq $foo, %rax + .size _start, .-_start diff --git a/ld/testsuite/ld-x86-64/pr19807-1b.d b/ld/testsuite/ld-x86-64/pr19807-1b.d new file mode 100644 index 00000000000..24f0a5acee7 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1b.d @@ -0,0 +1,13 @@ +#source: pr19807-1a.s +#as: --64 +#ld: -pie -melf_x86_64 --defsym foo=0x7fffffff +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 48 c7 c0 ff ff ff 7f mov \$0x7fffffff,%rax +#pass diff --git a/ld/testsuite/ld-x86-64/pr19807-1b.s b/ld/testsuite/ld-x86-64/pr19807-1b.s new file mode 100644 index 00000000000..10790b72ec0 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1b.s @@ -0,0 +1,5 @@ + .globl foo + .type foo, @object + .data +foo: + .quad 0 diff --git a/ld/testsuite/ld-x86-64/pr19807-1c.d b/ld/testsuite/ld-x86-64/pr19807-1c.d new file mode 100644 index 00000000000..f0fbee902aa --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1c.d @@ -0,0 +1,6 @@ +#source: pr19807-1a.s +#as: --x32 +#ld: -pie -melf32_x86_64 --defsym foo=0x7fffffff +#readelf: -r --wide + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/pr19807-1d.d b/ld/testsuite/ld-x86-64/pr19807-1d.d new file mode 100644 index 00000000000..245c759b712 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1d.d @@ -0,0 +1,13 @@ +#source: pr19807-1a.s +#as: --x32 +#ld: -pie -melf32_x86_64 --defsym foo=0x7fffffff +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 48 c7 c0 ff ff ff 7f mov \$0x7fffffff,%rax +#pass diff --git a/ld/testsuite/ld-x86-64/pr19807-1e.d b/ld/testsuite/ld-x86-64/pr19807-1e.d new file mode 100644 index 00000000000..4354ae30c66 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1e.d @@ -0,0 +1,4 @@ +#source: pr19807-1a.s +#as: --64 +#ld: -pie -melf_x86_64 --defsym foo=0x80000000 +#error: .*relocation truncated to fit: R_X86_64_32S .* diff --git a/ld/testsuite/ld-x86-64/pr19807-1f.d b/ld/testsuite/ld-x86-64/pr19807-1f.d new file mode 100644 index 00000000000..b3756b3deb7 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1f.d @@ -0,0 +1,5 @@ +#source: pr19807-1a.s +#source: pr19807-1b.s +#as: --64 +#ld: -pie -melf_x86_64 +#error: .*relocation R_X86_64_32S against symbol `foo' can not be used when making a shared object; recompile with -fPIC diff --git a/ld/testsuite/ld-x86-64/pr19807-1g.d b/ld/testsuite/ld-x86-64/pr19807-1g.d new file mode 100644 index 00000000000..10f66f0dc87 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1g.d @@ -0,0 +1,5 @@ +#source: pr19807-1a.s +#source: pr19807-1b.s +#as: --x32 +#ld: -pie -melf32_x86_64 +#error: .*relocation R_X86_64_32S against symbol `foo' can not be used when making a shared object; recompile with -fPIC diff --git a/ld/testsuite/ld-x86-64/pr19807-1h.d b/ld/testsuite/ld-x86-64/pr19807-1h.d new file mode 100644 index 00000000000..10f66f0dc87 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-1h.d @@ -0,0 +1,5 @@ +#source: pr19807-1a.s +#source: pr19807-1b.s +#as: --x32 +#ld: -pie -melf32_x86_64 +#error: .*relocation R_X86_64_32S against symbol `foo' can not be used when making a shared object; recompile with -fPIC diff --git a/ld/testsuite/ld-x86-64/pr19807-2.s b/ld/testsuite/ld-x86-64/pr19807-2.s new file mode 100644 index 00000000000..0870f6ade06 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-2.s @@ -0,0 +1,8 @@ + .globl _start + .type _start, @function +_start: + movq $foo, %rax + .size _start, .-_start + .data +foo: + .quad 0 diff --git a/ld/testsuite/ld-x86-64/pr19807-2a.d b/ld/testsuite/ld-x86-64/pr19807-2a.d new file mode 100644 index 00000000000..c8e96c8a97b --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-2a.d @@ -0,0 +1,8 @@ +#source: pr19807-2.s +#as: --64 +#ld: -pie -melf_x86_64 -z upper-address=0x7fffffff +#readelf: -r --wide + +Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries: + Offset Info Type Symbol's Value Symbol's Name \+ Addend +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+ diff --git a/ld/testsuite/ld-x86-64/pr19807-2b.d b/ld/testsuite/ld-x86-64/pr19807-2b.d new file mode 100644 index 00000000000..a2074f4229b --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-2b.d @@ -0,0 +1,13 @@ +#source: pr19807-2.s +#as: --64 +#ld: -pie -melf_x86_64 -z upper-address=0x7fffffff +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 48 c7 c0 ([0-9a-f]{2} ){4} mov \$0x[a-f0-9]+,%rax +#pass diff --git a/ld/testsuite/ld-x86-64/pr19807-2c.d b/ld/testsuite/ld-x86-64/pr19807-2c.d new file mode 100644 index 00000000000..010fde1858d --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-2c.d @@ -0,0 +1,8 @@ +#source: pr19807-2.s +#as: --x32 +#ld: -pie -melf32_x86_64 -z upper-address=0x7fffffff +#readelf: -r --wide + +Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries: + Offset Info Type Sym. Value Symbol's Name \+ Addend +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+ diff --git a/ld/testsuite/ld-x86-64/pr19807-2d.d b/ld/testsuite/ld-x86-64/pr19807-2d.d new file mode 100644 index 00000000000..7c7601d8625 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-2d.d @@ -0,0 +1,13 @@ +#source: pr19807-2.s +#as: --x32 +#ld: -pie -melf32_x86_64 -z upper-address=0x7fffffff +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: 48 c7 c0 ([0-9a-f]{2} ){4} mov \$0x[a-f0-9]+,%rax +#pass diff --git a/ld/testsuite/ld-x86-64/pr19807-3.s b/ld/testsuite/ld-x86-64/pr19807-3.s new file mode 100644 index 00000000000..2b309f24110 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-3.s @@ -0,0 +1,8 @@ + .globl _start + .type _start, @function +_start: + movl $foo, %eax + .size _start, .-_start + .data +foo: + .quad 0 diff --git a/ld/testsuite/ld-x86-64/pr19807-3a.d b/ld/testsuite/ld-x86-64/pr19807-3a.d new file mode 100644 index 00000000000..b6f61d71dbd --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-3a.d @@ -0,0 +1,4 @@ +#source: pr19807-3.s +#as: --64 +#ld: -pie -melf_x86_64 +#error: .*relocation R_X86_64_32 against symbol `.data' can not be used when making a shared object; recompile with -fPIC diff --git a/ld/testsuite/ld-x86-64/pr19807-3b.d b/ld/testsuite/ld-x86-64/pr19807-3b.d new file mode 100644 index 00000000000..43e2b02017e --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-3b.d @@ -0,0 +1,8 @@ +#source: pr19807-3.s +#as: --x32 +#ld: -pie -melf32_x86_64 +#readelf: -r --wide + +Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries: + Offset Info Type Sym. Value Symbol's Name \+ Addend +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+ diff --git a/ld/testsuite/ld-x86-64/pr19807-3c.d b/ld/testsuite/ld-x86-64/pr19807-3c.d new file mode 100644 index 00000000000..e6f9237f6fe --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-3c.d @@ -0,0 +1,13 @@ +#source: pr19807-3.s +#as: --x32 +#ld: -pie -melf32_x86_64 +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: b8 ([0-9a-f]{2} ){4} mov \$0x[a-f0-9]+,%eax +#pass diff --git a/ld/testsuite/ld-x86-64/pr19807-3d.d b/ld/testsuite/ld-x86-64/pr19807-3d.d new file mode 100644 index 00000000000..1466c0003c5 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-3d.d @@ -0,0 +1,8 @@ +#source: pr19807-3.s +#as: --64 +#ld: -pie -melf_x86_64 -z upper-address=0xffffffff +#readelf: -r --wide + +Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries: + Offset Info Type Symbol's Value Symbol's Name \+ Addend +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+ diff --git a/ld/testsuite/ld-x86-64/pr19807-3e.d b/ld/testsuite/ld-x86-64/pr19807-3e.d new file mode 100644 index 00000000000..40ffd297052 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr19807-3e.d @@ -0,0 +1,13 @@ +#source: pr19807-3.s +#as: --64 +#ld: -pie -melf_x86_64 -z upper-address=0xffffffff +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: +[ ]*[a-f0-9]+: b8 ([0-9a-f]{2} ){4} mov \$0x[a-f0-9]+,%eax +#pass diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 39385978f77..d524b2818d3 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -284,6 +284,23 @@ run_dump_test "pr19818-4a" run_dump_test "pr19818-4b" run_dump_test "pr19818-5a" run_dump_test "pr19818-5b" +run_dump_test "pr19807-1a" +run_dump_test "pr19807-1b" +run_dump_test "pr19807-1c" +run_dump_test "pr19807-1d" +run_dump_test "pr19807-1e" +run_dump_test "pr19807-1f" +run_dump_test "pr19807-1g" +run_dump_test "pr19807-1h" +run_dump_test "pr19807-2a" +run_dump_test "pr19807-2b" +run_dump_test "pr19807-2c" +run_dump_test "pr19807-2d" +run_dump_test "pr19807-3a" +run_dump_test "pr19807-3b" +run_dump_test "pr19807-3c" +run_dump_test "pr19807-3d" +run_dump_test "pr19807-3e" if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} { return |