diff options
author | Alan Modra <amodra@gmail.com> | 2019-10-16 21:23:29 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-10-16 23:07:27 +1030 |
commit | 22216541c1796e9e1331d6f4e16b03a6f02e7381 (patch) | |
tree | 4591c034f7c483dc18ff09eb257d19d99e916f30 /bfd | |
parent | 12234dfd5f70086fde87e1f6d56cf2aa2ce5ec4c (diff) | |
download | fsf-binutils-gdb-22216541c1796e9e1331d6f4e16b03a6f02e7381.zip fsf-binutils-gdb-22216541c1796e9e1331d6f4e16b03a6f02e7381.tar.gz fsf-binutils-gdb-22216541c1796e9e1331d6f4e16b03a6f02e7381.tar.bz2 |
PR13616, linker should pad executable sections with nops, not zeros
This implements padding of orphan executable sections for PowerPC.
Of course, the simple implementation of bfd_arch_ppc_nop_fill and
removing the NOP definition didn't work, with powerpc64 hitting a
testsuite failure linking to S-records. That's because the srec
target is BFD_ENDIAN_UNKNOWN so the test of bfd_big_endian (abfd) in
default_data_link_order therefore returned false, resulting in a
little-endian nop pattern. The rest of the patch fixes that problem
by adding a new field to bfd_link_info that can be used to determine
actual endianness on targets like srec.
PR 13616
include/
* bfdlink.h (struct bfd_link_info <big_endian>): New field.
bfd/
* cpu-powerpc.c (bfd_arch_ppc_nop_fill): New function, use it
for all ppc arch info.
* linker.c (default_data_link_order): Pass info->big_endian to
arch_info->fill function.
ld/
* emulparams/elf64lppc.sh (NOP): Don't define.
* emulparams/elf64ppc.sh (NOP): Don't define.
* ldwrite.c (build_link_order): Use link_info.big_endian. Move
code determining endian to use for data_statement to..
* ldemul.c (after_open_default): ..here. Set link_info.big_endian.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/cpu-powerpc.c | 39 | ||||
-rw-r--r-- | bfd/linker.c | 4 |
3 files changed, 48 insertions, 3 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5a9bfd7..74cdda4 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2019-10-16 Alan Modra <amodra@gmail.com> + + PR 13616 + * cpu-powerpc.c (bfd_arch_ppc_nop_fill): New function, use it + for all ppc arch info. + * linker.c (default_data_link_order): Pass info->big_endian to + arch_info->fill function. + 2019-10-15 Alan Modra <amodra@gmail.com> * elf32-m68hc1x.c (reloc_warning): Add printf attribute. diff --git a/bfd/cpu-powerpc.c b/bfd/cpu-powerpc.c index 4959467..6c54388 100644 --- a/bfd/cpu-powerpc.c +++ b/bfd/cpu-powerpc.c @@ -48,6 +48,43 @@ powerpc_compatible (const bfd_arch_info_type *a, /*NOTREACHED*/ } +/* Return a COUNT sized buffer filled with nops (if CODE is TRUE) or + zeros (if CODE is FALSE). This is the fill used between input + sections for alignment. It won't normally be executed. */ + +static void * +bfd_arch_ppc_nop_fill (bfd_size_type count, + bfd_boolean is_bigendian, + bfd_boolean code) +{ + bfd_byte *fill; + + if (count == 0) + return NULL; + fill = bfd_malloc (count); + if (fill == NULL) + return fill; + + if (code && (count & 3) == 0) + { + static const char nop_be[4] = {0x60, 0, 0, 0}; + static const char nop_le[4] = {0, 0, 0, 0x60}; + const char *nop = is_bigendian ? nop_be : nop_le; + bfd_byte *p = fill; + + while (count != 0) + { + memcpy (p, nop, 4); + p += 4; + count -= 4; + } + } + else + memset (fill, 0, count); + + return fill; +} + #define N(BITS, NUMBER, PRINT, DEFAULT, NEXT) \ { \ BITS, /* Bits in a word. */ \ @@ -61,7 +98,7 @@ powerpc_compatible (const bfd_arch_info_type *a, DEFAULT, \ powerpc_compatible, \ bfd_default_scan, \ - bfd_arch_default_fill, \ + bfd_arch_ppc_nop_fill, \ NEXT, \ 0 /* Maximum offset of a reloc from the start of an insn. */ \ } diff --git a/bfd/linker.c b/bfd/linker.c index 143b8eb..382b69d 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -2469,7 +2469,7 @@ _bfd_default_link_order (bfd *abfd, static bfd_boolean default_data_link_order (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_info *info, asection *sec, struct bfd_link_order *link_order) { @@ -2489,7 +2489,7 @@ default_data_link_order (bfd *abfd, fill_size = link_order->u.data.size; if (fill_size == 0) { - fill = abfd->arch_info->fill (size, bfd_big_endian (abfd), + fill = abfd->arch_info->fill (size, info->big_endian, (sec->flags & SEC_CODE) != 0); if (fill == NULL) return FALSE; |