This patch adds support for ARM PLT entries that support a full 32-bit offset range.

Enabled via the use of a new linker command line option: --long-plt.

	* bfd-in.h: Add export of bfd_elf32_arm_use_long_plt.
	* bfd-in2.h: Regenerate.
	* elf32-arm.c (elf32_arm_plt_entry_long): New array.
	(elf32_arm_link_hash_table_create): Set plt_entry_size to 16 if
	using long PLT entries.
	(bfd_elf32_arm_use_long_plt): New function.
	(elf32_arm_populate_plt_entry): Add support for long PLT entries.

	* emultempl/armelf.em (OPTION_LONG_PLT): Define.
	(PARSE_AND_LIST_LONGOPTS): Add long-plt.
	(PARSE_AND_LIST_OPTIONS): Likewise.
	(PARSE_AND_LIST_ARGS_CASES): Handle long-plt.
	* ld.texinfo: Document --long-plt.

	* ld-arm/long-plt-format.s: New test case.
	* ld-arm/long-plt-format.d: Expected disassembly.
	* ld-arm/arm-elf.exp: Run the new test.
This commit is contained in:
Yuri Gribov 2014-02-27 14:35:37 +00:00 committed by Nick Clifton
parent fa96cb382c
commit 1db37fe627
11 changed files with 164 additions and 48 deletions

View File

@ -1,3 +1,13 @@
2014-02-27 Yuri Gribov <y.gribov@samsung.com>
* bfd-in.h: Add export of bfd_elf32_arm_use_long_plt.
* bfd-in2.h: Regenerate.
* elf32-arm.c (elf32_arm_plt_entry_long): New array.
(elf32_arm_link_hash_table_create): Set plt_entry_size to 16 if
using long PLT entries.
(bfd_elf32_arm_use_long_plt): New function.
(elf32_arm_populate_plt_entry): Add support for long PLT entries.
2014-02-27 Alan Modra <amodra@gmail.com>
* elf32-ppc.c (ppc_elf_link_hash_table_create): Provide default

View File

@ -1,6 +1,6 @@
/* Main header file for the bfd library -- portable access to object files.
Copyright 1990-2013 Free Software Foundation, Inc.
Copyright 1990-2014 Free Software Foundation, Inc.
Contributed by Cygnus Support.
@ -877,15 +877,19 @@ extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd
(bfd *, struct bfd_link_info *);
/* ELF ARM mapping symbol support */
/* ELF ARM mapping symbol support. */
#define BFD_ARM_SPECIAL_SYM_TYPE_MAP (1 << 0)
#define BFD_ARM_SPECIAL_SYM_TYPE_TAG (1 << 1)
#define BFD_ARM_SPECIAL_SYM_TYPE_OTHER (1 << 2)
#define BFD_ARM_SPECIAL_SYM_TYPE_ANY (~0)
extern bfd_boolean bfd_is_arm_special_symbol_name
(const char * name, int type);
extern void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *, int);
extern bfd_boolean bfd_is_arm_special_symbol_name
(const char *, int);
extern void bfd_elf32_arm_set_byteswap_code
(struct bfd_link_info *, int);
extern void bfd_elf32_arm_use_long_plt (void);
/* ARM Note section processing. */
extern bfd_boolean bfd_arm_merge_machines

View File

@ -7,7 +7,7 @@
/* Main header file for the bfd library -- portable access to object files.
Copyright 1990-2013 Free Software Foundation, Inc.
Copyright 1990-2014 Free Software Foundation, Inc.
Contributed by Cygnus Support.
@ -884,15 +884,19 @@ extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd
(bfd *, struct bfd_link_info *);
/* ELF ARM mapping symbol support */
/* ELF ARM mapping symbol support. */
#define BFD_ARM_SPECIAL_SYM_TYPE_MAP (1 << 0)
#define BFD_ARM_SPECIAL_SYM_TYPE_TAG (1 << 1)
#define BFD_ARM_SPECIAL_SYM_TYPE_OTHER (1 << 2)
#define BFD_ARM_SPECIAL_SYM_TYPE_ANY (~0)
extern bfd_boolean bfd_is_arm_special_symbol_name
(const char * name, int type);
extern void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *, int);
extern bfd_boolean bfd_is_arm_special_symbol_name
(const char *, int);
extern void bfd_elf32_arm_set_byteswap_code
(struct bfd_link_info *, int);
extern void bfd_elf32_arm_use_long_plt (void);
/* ARM Note section processing. */
extern bfd_boolean bfd_arm_merge_machines

View File

@ -1,5 +1,5 @@
/* 32-bit ELF support for ARM
Copyright 1998-2013 Free Software Foundation, Inc.
Copyright 1998-2014 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -2140,15 +2140,27 @@ static const bfd_vma elf32_arm_plt0_entry [] =
0x00000000, /* &GOT[0] - . */
};
/* Subsequent entries in a procedure linkage table look like
this. */
static const bfd_vma elf32_arm_plt_entry [] =
/* By default subsequent entries in a procedure linkage table look like
this. Offsets that don't fit into 28 bits will cause link error. */
static const bfd_vma elf32_arm_plt_entry_short [] =
{
0xe28fc600, /* add ip, pc, #0xNN00000 */
0xe28cca00, /* add ip, ip, #0xNN000 */
0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */
};
/* When explicitly asked, we'll use this "long" entry format
which can cope with arbitrary displacements. */
static const bfd_vma elf32_arm_plt_entry_long [] =
{
0xe28fc200, /* add ip, pc, #0xN0000000 */
0xe28cc600, /* add ip, ip, #0xNN00000 */
0xe28cca00, /* add ip, ip, #0xNN000 */
0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */
};
static bfd_boolean elf32_arm_use_long_plt_entry = FALSE;
#endif
/* The format of the first entry in the procedure linkage table
@ -3464,7 +3476,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
ret->plt_entry_size = 16;
#else
ret->plt_header_size = 20;
ret->plt_entry_size = 12;
ret->plt_entry_size = elf32_arm_use_long_plt_entry ? 16 : 12;
#endif
ret->use_rel = 1;
ret->obfd = abfd;
@ -6027,6 +6039,15 @@ arm_make_glue_section (bfd * abfd, const char * name)
return TRUE;
}
/* Set size of .plt entries. This function is called from the
linker scripts in ld/emultempl/{armelf}.em. */
void
bfd_elf32_arm_use_long_plt (void)
{
elf32_arm_use_long_plt_entry = TRUE;
}
/* Add the glue sections to ABFD. This function is called from the
linker scripts in ld/emultempl/{armelf}.em. */
@ -7705,8 +7726,6 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
of the PLT stub. */
got_displacement = got_address - (plt_address + 8);
BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt))
{
put_thumb_insn (htab, output_bfd,
@ -7715,21 +7734,45 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
elf32_arm_plt_thumb_stub[1], ptr - 2);
}
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry[0]
| ((got_displacement & 0x0ff00000) >> 20),
ptr + 0);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry[1]
| ((got_displacement & 0x000ff000) >> 12),
ptr+ 4);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry[2]
| (got_displacement & 0x00000fff),
ptr + 8);
if (!elf32_arm_use_long_plt_entry)
{
BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry_short[0]
| ((got_displacement & 0x0ff00000) >> 20),
ptr + 0);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry_short[1]
| ((got_displacement & 0x000ff000) >> 12),
ptr+ 4);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry_short[2]
| (got_displacement & 0x00000fff),
ptr + 8);
#ifdef FOUR_WORD_PLT
bfd_put_32 (output_bfd, elf32_arm_plt_entry[3], ptr + 12);
bfd_put_32 (output_bfd, elf32_arm_plt_entry_short[3], ptr + 12);
#endif
}
else
{
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry_long[0]
| ((got_displacement & 0xf0000000) >> 28),
ptr + 0);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry_long[1]
| ((got_displacement & 0x0ff00000) >> 20),
ptr + 4);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry_long[2]
| ((got_displacement & 0x000ff000) >> 12),
ptr+ 8);
put_arm_insn (htab, output_bfd,
elf32_arm_plt_entry_long[3]
| (got_displacement & 0x00000fff),
ptr + 12);
}
}
/* Fill in the entry in the .rel(a).(i)plt section. */

View File

@ -1,3 +1,11 @@
2014-02-27 Yuri Gribov <y.gribov@samsung.com>
* emultempl/armelf.em (OPTION_LONG_PLT): Define.
(PARSE_AND_LIST_LONGOPTS): Add long-plt.
(PARSE_AND_LIST_OPTIONS): Likewise.
(PARSE_AND_LIST_ARGS_CASES): Handle long-plt.
* ld.texinfo: Document --long-plt.
2014-02-27 Alan Modra <amodra@gmail.com>
* emulparams/elf32ppcvxworks.sh: Source plt_unwind.sh and

View File

@ -1,5 +1,5 @@
# This shell script emits a C file. -*- C -*-
# Copyright 1991-2013 Free Software Foundation, Inc.
# Copyright 1991-2014 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
@ -28,10 +28,10 @@ fragment <<EOF
#include "ldctor.h"
#include "elf/arm.h"
static char *thumb_entry_symbol = NULL;
static char * thumb_entry_symbol = NULL;
static int byteswap_code = 0;
static int target1_is_rel = 0${TARGET1_IS_REL};
static char *target2_type = "${TARGET2_TYPE}";
static char * target2_type = "${TARGET2_TYPE}";
static int fix_v4bx = 0;
static int use_blx = 0;
static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT;
@ -531,6 +531,7 @@ PARSE_AND_LIST_PROLOGUE='
#define OPTION_NO_MERGE_EXIDX_ENTRIES 316
#define OPTION_FIX_ARM1176 317
#define OPTION_NO_FIX_ARM1176 318
#define OPTION_LONG_PLT 319
'
PARSE_AND_LIST_SHORTOPTS=p
@ -555,6 +556,7 @@ PARSE_AND_LIST_LONGOPTS='
{ "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES },
{ "fix-arm1176", no_argument, NULL, OPTION_FIX_ARM1176 },
{ "no-fix-arm1176", no_argument, NULL, OPTION_NO_FIX_ARM1176 },
{ "long-plt", no_argument, NULL, OPTION_LONG_PLT },
'
PARSE_AND_LIST_OPTIONS='
@ -572,6 +574,8 @@ PARSE_AND_LIST_OPTIONS='
fprintf (file, _(" --no-wchar-size-warning Don'\''t warn about objects with incompatible\n"
" wchar_t sizes\n"));
fprintf (file, _(" --pic-veneer Always generate PIC interworking veneers\n"));
fprintf (file, _(" --long-plt Generate long .plt entries\n"
" to handle large .plt/.got displacements\n"));
fprintf (file, _("\
--stub-group-size=N Maximum size of a group of input sections that\n\
can be handled by one stub section. A negative\n\
@ -675,6 +679,10 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_NO_FIX_ARM1176:
fix_arm1176 = 0;
break;
case OPTION_LONG_PLT:
bfd_elf32_arm_use_long_plt ();
break;
'
# We have our own before_allocation etc. functions, but they call

View File

@ -1,6 +1,6 @@
\input texinfo
@setfilename ld.info
@c Copyright 1991-2013 Free Software Foundation, Inc.
@c Copyright 1991-2014 Free Software Foundation, Inc.
@syncodeindex ky cp
@c man begin INCLUDE
@include configdoc.texi
@ -55,7 +55,7 @@ This file documents the @sc{gnu} linker LD
@end ifset
version @value{VERSION}.
Copyright @copyright{} 1991-2013 Free Software Foundation, Inc.
Copyright @copyright{} 1991-2014 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
@ -92,7 +92,7 @@ section entitled ``GNU Free Documentation License''.
@vskip 0pt plus 1filll
@c man begin COPYRIGHT
Copyright @copyright{} 1991-2013 Free Software Foundation, Inc.
Copyright @copyright{} 1991-2014 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
@ -6257,17 +6257,6 @@ instructions into @code{bal} instructions when it determines that the
target subroutine is a leaf routine (that is, the target subroutine does
not itself call any subroutines).
@cindex Cortex-A8 erratum workaround
@kindex --fix-cortex-a8
@kindex --no-fix-cortex-a8
The @samp{--fix-cortex-a8} switch enables a link-time workaround for an erratum in certain Cortex-A8 processors. The workaround is enabled by default if you are targeting the ARM v7-A architecture profile. It can be enabled otherwise by specifying @samp{--fix-cortex-a8}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a8}.
The erratum only affects Thumb-2 code. Please contact ARM for further details.
@kindex --merge-exidx-entries
@kindex --no-merge-exidx-entries
The @samp{--no-merge-exidx-entries} switch disables the merging of adjacent exidx entries in debuginfo.
@ifclear GENERIC
@lowersections
@end ifclear
@ -6526,6 +6515,24 @@ Farcalls stubs insertion is fully supported for the ARM-EABI target
only, because it relies on object files properties not present
otherwise.
@cindex Cortex-A8 erratum workaround
@kindex --fix-cortex-a8
@kindex --no-fix-cortex-a8
The @samp{--fix-cortex-a8} switch enables a link-time workaround for an erratum in certain Cortex-A8 processors. The workaround is enabled by default if you are targeting the ARM v7-A architecture profile. It can be enabled otherwise by specifying @samp{--fix-cortex-a8}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a8}.
The erratum only affects Thumb-2 code. Please contact ARM for further details.
@kindex --merge-exidx-entries
@kindex --no-merge-exidx-entries
@cindex Merging exidx entries
The @samp{--no-merge-exidx-entries} switch disables the merging of adjacent exidx entries in debuginfo.
@kindex --long-plt
@cindex 32-bit PLT entries
The @samp{--long-plt} option enables the use of 16 byte PLT entries
which support up to 4Gb of code. The default is to use 12 byte PLT
entries which only support 512Mb of code.
@ifclear GENERIC
@lowersections
@end ifclear

View File

@ -1,3 +1,9 @@
2014-02-27 Yuri Gribov <y.gribov@samsung.com>
* ld-arm/long-plt-format.s: New test case.
* ld-arm/long-plt-format.d: Expected disassembly.
* ld-arm/arm-elf.exp: Run the new test.
2014-02-27 Nick Clifton <nickc@redhat.com>
* ld-pe/longsecn-1.d: Allow for extra sections.

View File

@ -1,5 +1,5 @@
# Expect script for various ARM ELF tests.
# Copyright 2002-2013 Free Software Foundation, Inc.
# Copyright 2002-2014 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
@ -188,6 +188,10 @@ set armelftests_common {
"" {exec-got-1b.s}
{{readelf --relocs exec-got-1.d}}
"exec-got-1"}
{"Long PLT entries in executables" "--long-plt -shared --section-start=.plt=0x200 --section-start=.got=0xf0000300" ""
"" {long-plt-format.s}
{{objdump "-d -j .plt" long-plt-format.d}}
"long-plt-format"}
{"abs call" "-T arm.ld" "" "" {abs-call-1.s}
{{objdump -d abs-call-1.d}}
"abs-call-1"}

View File

@ -0,0 +1,15 @@
.*: file format elf32-.*
Disassembly of section .plt:
00000200 <.plt>:
200: .*
204: .*
208: .*
20c: .*
210: .* .word .*
214: .* add ip, pc, #-268435456 ; 0xf0000000
218: .* add ip, ip, #0, 12
21c: .* add ip, ip, #0, 20
220: .* ldr pc, [ip, #[0-9]*]! ; 0x.*

View File

@ -0,0 +1,7 @@
.globl _start
.type _start,%function
.globl foo
_start:
bl foo(PLT)
.size _start,.-_start