mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 09:58:19 +08:00
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.
This commit is contained in:
@ -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>
|
2019-10-15 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* elf32-m68hc1x.c (reloc_warning): Add printf attribute.
|
* elf32-m68hc1x.c (reloc_warning): Add printf attribute.
|
||||||
|
@ -48,6 +48,43 @@ powerpc_compatible (const bfd_arch_info_type *a,
|
|||||||
/*NOTREACHED*/
|
/*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) \
|
#define N(BITS, NUMBER, PRINT, DEFAULT, NEXT) \
|
||||||
{ \
|
{ \
|
||||||
BITS, /* Bits in a word. */ \
|
BITS, /* Bits in a word. */ \
|
||||||
@ -61,7 +98,7 @@ powerpc_compatible (const bfd_arch_info_type *a,
|
|||||||
DEFAULT, \
|
DEFAULT, \
|
||||||
powerpc_compatible, \
|
powerpc_compatible, \
|
||||||
bfd_default_scan, \
|
bfd_default_scan, \
|
||||||
bfd_arch_default_fill, \
|
bfd_arch_ppc_nop_fill, \
|
||||||
NEXT, \
|
NEXT, \
|
||||||
0 /* Maximum offset of a reloc from the start of an insn. */ \
|
0 /* Maximum offset of a reloc from the start of an insn. */ \
|
||||||
}
|
}
|
||||||
|
@ -2469,7 +2469,7 @@ _bfd_default_link_order (bfd *abfd,
|
|||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
default_data_link_order (bfd *abfd,
|
default_data_link_order (bfd *abfd,
|
||||||
struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
struct bfd_link_info *info,
|
||||||
asection *sec,
|
asection *sec,
|
||||||
struct bfd_link_order *link_order)
|
struct bfd_link_order *link_order)
|
||||||
{
|
{
|
||||||
@ -2489,7 +2489,7 @@ default_data_link_order (bfd *abfd,
|
|||||||
fill_size = link_order->u.data.size;
|
fill_size = link_order->u.data.size;
|
||||||
if (fill_size == 0)
|
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);
|
(sec->flags & SEC_CODE) != 0);
|
||||||
if (fill == NULL)
|
if (fill == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2019-10-16 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
PR 13616
|
||||||
|
* bfdlink.h (struct bfd_link_info <big_endian>): New field.
|
||||||
|
|
||||||
2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
|
2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
|
||||||
|
|
||||||
* elf/msp430.h: Add enums for MSPABI and GNU object attribute tag
|
* elf/msp430.h: Add enums for MSPABI and GNU object attribute tag
|
||||||
|
@ -359,6 +359,10 @@ struct bfd_link_info
|
|||||||
/* TRUE if section groups should be resolved. */
|
/* TRUE if section groups should be resolved. */
|
||||||
unsigned int resolve_section_groups: 1;
|
unsigned int resolve_section_groups: 1;
|
||||||
|
|
||||||
|
/* Set if output file is big-endian, or if that is unknown, from
|
||||||
|
the command line or first input file endianness. */
|
||||||
|
unsigned int big_endian : 1;
|
||||||
|
|
||||||
/* Which symbols to strip. */
|
/* Which symbols to strip. */
|
||||||
ENUM_BITFIELD (bfd_link_strip) strip : 2;
|
ENUM_BITFIELD (bfd_link_strip) strip : 2;
|
||||||
|
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
2019-10-16 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
PR 13616
|
||||||
|
* 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.
|
||||||
|
|
||||||
2019-10-16 Alan Modra <amodra@gmail.com>
|
2019-10-16 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* genscripts.sh: Correct comments. Remove outdated comment block
|
* genscripts.sh: Correct comments. Remove outdated comment block
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
source_sh ${srcdir}/emulparams/elf64ppc.sh
|
source_sh ${srcdir}/emulparams/elf64ppc.sh
|
||||||
OUTPUT_FORMAT="elf64-powerpcle"
|
OUTPUT_FORMAT="elf64-powerpcle"
|
||||||
NOP=0x00000060
|
|
||||||
|
@ -6,7 +6,6 @@ OUTPUT_FORMAT="elf64-powerpc"
|
|||||||
TEXT_START_ADDR=0x10000000
|
TEXT_START_ADDR=0x10000000
|
||||||
#SEGMENT_SIZE=0x10000000
|
#SEGMENT_SIZE=0x10000000
|
||||||
ARCH=powerpc:common64
|
ARCH=powerpc:common64
|
||||||
NOP=0x60000000
|
|
||||||
unset EXECUTABLE_SYMBOLS
|
unset EXECUTABLE_SYMBOLS
|
||||||
unset SDATA_START_SYMBOLS
|
unset SDATA_START_SYMBOLS
|
||||||
unset SDATA2_START_SYMBOLS
|
unset SDATA2_START_SYMBOLS
|
||||||
|
23
ld/ldemul.c
23
ld/ldemul.c
@ -236,6 +236,29 @@ after_parse_default (void)
|
|||||||
void
|
void
|
||||||
after_open_default (void)
|
after_open_default (void)
|
||||||
{
|
{
|
||||||
|
link_info.big_endian = TRUE;
|
||||||
|
|
||||||
|
if (bfd_big_endian (link_info.output_bfd))
|
||||||
|
;
|
||||||
|
else if (bfd_little_endian (link_info.output_bfd))
|
||||||
|
link_info.big_endian = FALSE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (command_line.endian == ENDIAN_BIG)
|
||||||
|
;
|
||||||
|
else if (command_line.endian == ENDIAN_LITTLE)
|
||||||
|
link_info.big_endian = FALSE;
|
||||||
|
else if (command_line.endian == ENDIAN_UNSET)
|
||||||
|
{
|
||||||
|
LANG_FOR_EACH_INPUT_STATEMENT (s)
|
||||||
|
if (s->the_bfd != NULL)
|
||||||
|
{
|
||||||
|
if (bfd_little_endian (s->the_bfd))
|
||||||
|
link_info.big_endian = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
93
ld/ldwrite.c
93
ld/ldwrite.c
@ -46,7 +46,6 @@ build_link_order (lang_statement_union_type *statement)
|
|||||||
asection *output_section;
|
asection *output_section;
|
||||||
struct bfd_link_order *link_order;
|
struct bfd_link_order *link_order;
|
||||||
bfd_vma value;
|
bfd_vma value;
|
||||||
bfd_boolean big_endian = FALSE;
|
|
||||||
|
|
||||||
output_section = statement->data_statement.output_section;
|
output_section = statement->data_statement.output_section;
|
||||||
ASSERT (output_section->owner == link_info.output_bfd);
|
ASSERT (output_section->owner == link_info.output_bfd);
|
||||||
@ -66,74 +65,38 @@ build_link_order (lang_statement_union_type *statement)
|
|||||||
|
|
||||||
value = statement->data_statement.value;
|
value = statement->data_statement.value;
|
||||||
|
|
||||||
/* If the endianness of the output BFD is not known, then we
|
/* By convention, the bfd_put routines for an unknown
|
||||||
base the endianness of the data on the first input file.
|
|
||||||
By convention, the bfd_put routines for an unknown
|
|
||||||
endianness are big endian, so we must swap here if the
|
endianness are big endian, so we must swap here if the
|
||||||
input file is little endian. */
|
input is little endian. */
|
||||||
if (bfd_big_endian (link_info.output_bfd))
|
if (!bfd_big_endian (link_info.output_bfd)
|
||||||
big_endian = TRUE;
|
&& !bfd_little_endian (link_info.output_bfd)
|
||||||
else if (bfd_little_endian (link_info.output_bfd))
|
&& !link_info.big_endian)
|
||||||
big_endian = FALSE;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
bfd_boolean swap;
|
bfd_byte buffer[8];
|
||||||
|
|
||||||
swap = FALSE;
|
switch (statement->data_statement.type)
|
||||||
if (command_line.endian == ENDIAN_BIG)
|
|
||||||
big_endian = TRUE;
|
|
||||||
else if (command_line.endian == ENDIAN_LITTLE)
|
|
||||||
{
|
{
|
||||||
big_endian = FALSE;
|
case QUAD:
|
||||||
swap = TRUE;
|
case SQUAD:
|
||||||
}
|
if (sizeof (bfd_vma) >= QUAD_SIZE)
|
||||||
else if (command_line.endian == ENDIAN_UNSET)
|
|
||||||
{
|
|
||||||
big_endian = TRUE;
|
|
||||||
{
|
|
||||||
LANG_FOR_EACH_INPUT_STATEMENT (s)
|
|
||||||
{
|
{
|
||||||
if (s->the_bfd != NULL)
|
bfd_putl64 (value, buffer);
|
||||||
{
|
value = bfd_getb64 (buffer);
|
||||||
if (bfd_little_endian (s->the_bfd))
|
break;
|
||||||
{
|
|
||||||
big_endian = FALSE;
|
|
||||||
swap = TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (swap)
|
|
||||||
{
|
|
||||||
bfd_byte buffer[8];
|
|
||||||
|
|
||||||
switch (statement->data_statement.type)
|
|
||||||
{
|
|
||||||
case QUAD:
|
|
||||||
case SQUAD:
|
|
||||||
if (sizeof (bfd_vma) >= QUAD_SIZE)
|
|
||||||
{
|
|
||||||
bfd_putl64 (value, buffer);
|
|
||||||
value = bfd_getb64 (buffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Fall through. */
|
|
||||||
case LONG:
|
|
||||||
bfd_putl32 (value, buffer);
|
|
||||||
value = bfd_getb32 (buffer);
|
|
||||||
break;
|
|
||||||
case SHORT:
|
|
||||||
bfd_putl16 (value, buffer);
|
|
||||||
value = bfd_getb16 (buffer);
|
|
||||||
break;
|
|
||||||
case BYTE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort ();
|
|
||||||
}
|
}
|
||||||
|
/* Fall through. */
|
||||||
|
case LONG:
|
||||||
|
bfd_putl32 (value, buffer);
|
||||||
|
value = bfd_getb32 (buffer);
|
||||||
|
break;
|
||||||
|
case SHORT:
|
||||||
|
bfd_putl16 (value, buffer);
|
||||||
|
value = bfd_getb16 (buffer);
|
||||||
|
break;
|
||||||
|
case BYTE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,10 +120,10 @@ build_link_order (lang_statement_union_type *statement)
|
|||||||
high = (bfd_vma) -1;
|
high = (bfd_vma) -1;
|
||||||
bfd_put_32 (link_info.output_bfd, high,
|
bfd_put_32 (link_info.output_bfd, high,
|
||||||
(link_order->u.data.contents
|
(link_order->u.data.contents
|
||||||
+ (big_endian ? 0 : 4)));
|
+ (link_info.big_endian ? 0 : 4)));
|
||||||
bfd_put_32 (link_info.output_bfd, value,
|
bfd_put_32 (link_info.output_bfd, value,
|
||||||
(link_order->u.data.contents
|
(link_order->u.data.contents
|
||||||
+ (big_endian ? 4 : 0)));
|
+ (link_info.big_endian ? 4 : 0)));
|
||||||
}
|
}
|
||||||
link_order->size = QUAD_SIZE;
|
link_order->size = QUAD_SIZE;
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user