diff options
-rw-r--r-- | bfd/ChangeLog | 13 | ||||
-rw-r--r-- | bfd/elf32-s390.c | 231 | ||||
-rw-r--r-- | bfd/elf64-s390.c | 72 |
3 files changed, 167 insertions, 149 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d1fa9b0..31f21d7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,18 @@ 2012-03-30 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + * elf64-s390.c (elf_s390x_plt_entry, elf_s390x_first_plt_entry): + New definitions. + (PLT_PIC_ENTRY_WORD*, PLT_PIC12_ENTRY_WORD*): Remove. + (elf_s390_finish_dynamic_symbol): Use memcpy instead of bfd_put_32. + (elf_s390_finish_dynamic_sections): Likewise. + * elf32-s390.c (elf_s390_plt_entry, elf_s390_plt_pic_entry) + (elf_s390_plt_pic12_entry, elf_s390_plt_pic16_entry) + (elf_s390_plt_first_entry, elf_s390_plt_pic_first_entry): New definitions. + (PLT_PIC16_ENTRY_WORD*, PLT_ENTRY_WORD*) + (PLT_PIC_FIRST_ENTRY_WORD*, PLT_FIRST_ENTRY_WORD*): Remove. + +2012-03-30 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + * elf32-s390.c (struct elf_s390_dyn_relocs): Remove. Rename all occurrences in the file to elf_dyn_relocs. * elf64-s390.c: Likewise. diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index 9dc68e7..58048be 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -569,29 +569,65 @@ RET1: BASR 1,0 # 2 bytes Return from GOT 1st time .long ? # 4 bytes address of GOT entry .long ? # 4 bytes offset into symbol table */ -#define PLT_PIC_ENTRY_WORD0 0x0d105810 -#define PLT_PIC_ENTRY_WORD1 0x10165811 -#define PLT_PIC_ENTRY_WORD2 0xc00007f1 -#define PLT_PIC_ENTRY_WORD3 0x0d105810 -#define PLT_PIC_ENTRY_WORD4 0x100ea7f4 - -#define PLT_PIC12_ENTRY_WORD0 0x5810c000 -#define PLT_PIC12_ENTRY_WORD1 0x07f10000 -#define PLT_PIC12_ENTRY_WORD2 0x00000000 -#define PLT_PIC12_ENTRY_WORD3 0x0d105810 -#define PLT_PIC12_ENTRY_WORD4 0x100ea7f4 - -#define PLT_PIC16_ENTRY_WORD0 0xa7180000 -#define PLT_PIC16_ENTRY_WORD1 0x5811c000 -#define PLT_PIC16_ENTRY_WORD2 0x07f10000 -#define PLT_PIC16_ENTRY_WORD3 0x0d105810 -#define PLT_PIC16_ENTRY_WORD4 0x100ea7f4 - -#define PLT_ENTRY_WORD0 0x0d105810 -#define PLT_ENTRY_WORD1 0x10165810 -#define PLT_ENTRY_WORD2 0x100007f1 -#define PLT_ENTRY_WORD3 0x0d105810 -#define PLT_ENTRY_WORD4 0x100ea7f4 +static const bfd_byte elf_s390_plt_entry[PLT_ENTRY_SIZE] = + { + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x58, 0x10, 0x10, 0x16, /* l %r1,22(%r1) */ + 0x58, 0x10, 0x10, 0x00, /* l %r1,0(%r1) */ + 0x07, 0xf1, /* br %r1 */ + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x58, 0x10, 0x10, 0x0e, /* l %r1,14(%r1) */ + 0xa7, 0xf4, 0x00, 0x00, /* j first plt */ + 0x00, 0x00, /* padding */ + 0x00, 0x00, 0x00, 0x00, /* GOT offset */ + 0x00, 0x00, 0x00, 0x00 /* rela.plt offset */ + }; + +/* Generic PLT pic entry. */ +static const bfd_byte elf_s390_plt_pic_entry[PLT_ENTRY_SIZE] = + { + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x58, 0x10, 0x10, 0x16, /* l %r1,22(%r1) */ + 0x58, 0x11, 0xc0, 0x00, /* l %r1,0(%r1,%r12) */ + 0x07, 0xf1, /* br %r1 */ + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x58, 0x10, 0x10, 0x0e, /* l %r1,14(%r1) */ + 0xa7, 0xf4, 0x00, 0x00, /* j first plt */ + 0x00, 0x00, /* padding */ + 0x00, 0x00, 0x00, 0x00, /* GOT offset */ + 0x00, 0x00, 0x00, 0x00 /* rela.plt offset */ + }; + +/* Optimized PLT pic entry for GOT offset < 4k. xx will be replaced + when generating the PLT slot with the GOT offset. */ +static const bfd_byte elf_s390_plt_pic12_entry[PLT_ENTRY_SIZE] = + { + 0x58, 0x10, 0xc0, 0x00, /* l %r1,xx(%r12) */ + 0x07, 0xf1, /* br %r1 */ + 0x00, 0x00, 0x00, 0x00, /* padding */ + 0x00, 0x00, + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x58, 0x10, 0x10, 0x0e, /* l %r1,14(%r1) */ + 0xa7, 0xf4, 0x00, 0x00, /* j first plt */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + +/* Optimized PLT pic entry for GOT offset < 32k. xx will be replaced + when generating the PLT slot with the GOT offset. */ +static const bfd_byte elf_s390_plt_pic16_entry[PLT_ENTRY_SIZE] = + { + 0xa7, 0x18, 0x00, 0x00, /* lhi %r1,xx */ + 0x58, 0x11, 0xc0, 0x00, /* l %r1,0(%r1,%r12) */ + 0x07, 0xf1, /* br %r1 */ + 0x00, 0x00, + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x58, 0x10, 0x10, 0x0e, /* l %r1,14(%r1) */ + 0xa7, 0xf4, 0x00, 0x00, /* j first plt */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; /* The first PLT entry pushes the offset into the symbol table from R1 onto the stack at 8(15) and the loader object info @@ -618,18 +654,31 @@ PLT0: .word 0 # filler .long got # address of GOT */ -#define PLT_PIC_FIRST_ENTRY_WORD0 0x5010f01c -#define PLT_PIC_FIRST_ENTRY_WORD1 0x5810c004 -#define PLT_PIC_FIRST_ENTRY_WORD2 0x5010f018 -#define PLT_PIC_FIRST_ENTRY_WORD3 0x5810c008 -#define PLT_PIC_FIRST_ENTRY_WORD4 0x07f10000 - -#define PLT_FIRST_ENTRY_WORD0 0x5010f01c -#define PLT_FIRST_ENTRY_WORD1 0x0d105810 -#define PLT_FIRST_ENTRY_WORD2 0x1012D203 -#define PLT_FIRST_ENTRY_WORD3 0xf0181004 -#define PLT_FIRST_ENTRY_WORD4 0x58101008 -#define PLT_FIRST_ENTRY_WORD5 0x07f10000 +static const bfd_byte elf_s390_plt_first_entry[PLT_FIRST_ENTRY_SIZE] = + { + 0x50, 0x10, 0xf0, 0x1c, /* st %r1,28(%r15) */ + 0x0d, 0x10, /* basr %r1,%r0 */ + 0x58, 0x10, 0x10, 0x12, /* l %r1,18(%r1) */ + 0xd2, 0x03, 0xf0, 0x18, 0x10, 0x04, /* mvc 24(4,%r15),4(%r1) */ + 0x58, 0x10, 0x10, 0x08, /* l %r1,8(%r1) */ + 0x07, 0xf1, /* br %r1 */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + +static const bfd_byte elf_s390_plt_pic_first_entry[PLT_FIRST_ENTRY_SIZE] = + { + 0x50, 0x10, 0xf0, 0x1c, /* st %r1,28(%r15) */ + 0x58, 0x10, 0xc0, 0x04, /* l %r1,4(%r12) */ + 0x50, 0x10, 0xf0, 0x18, /* st %r1,24(%r15) */ + 0x58, 0x10, 0xc0, 0x08, /* l %r1,8(%r12) */ + 0x07, 0xf1, /* br %r1 */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; /* s390 ELF linker hash entry. */ @@ -3107,18 +3156,14 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) /* Fill in the entry in the procedure linkage table. */ if (!info->shared) { - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0, - htab->splt->contents + h->plt.offset); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD1, - htab->splt->contents + h->plt.offset + 4); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD2, - htab->splt->contents + h->plt.offset + 8); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD3, - htab->splt->contents + h->plt.offset + 12); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD4, - htab->splt->contents + h->plt.offset + 16); + memcpy (htab->splt->contents + h->plt.offset, elf_s390_plt_entry, + PLT_ENTRY_SIZE); + + /* Adjust jump to the first plt entry. */ bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16), htab->splt->contents + h->plt.offset + 20); + + /* Push the GOT offset field. */ bfd_put_32 (output_bfd, (htab->sgotplt->output_section->vma + htab->sgotplt->output_offset @@ -3127,52 +3172,50 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) } else if (got_offset < 4096) { - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD0 + got_offset, - htab->splt->contents + h->plt.offset); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD1, - htab->splt->contents + h->plt.offset + 4); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD2, - htab->splt->contents + h->plt.offset + 8); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD3, - htab->splt->contents + h->plt.offset + 12); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD4, - htab->splt->contents + h->plt.offset + 16); + /* The GOT offset is small enough to be used directly as + displacement. */ + memcpy (htab->splt->contents + h->plt.offset, + elf_s390_plt_pic12_entry, + PLT_ENTRY_SIZE); + + /* Put in the GOT offset as displacement value. The 0xc000 + value comes from the first word of the plt entry. Look + at the elf_s390_plt_pic16_entry content. */ + bfd_put_16 (output_bfd, (bfd_vma)0xc000 | got_offset, + htab->splt->contents + h->plt.offset + 2); + + /* Adjust the jump to the first plt entry. */ bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16), htab->splt->contents + h->plt.offset + 20); - bfd_put_32 (output_bfd, (bfd_vma) 0, - htab->splt->contents + h->plt.offset + 24); } else if (got_offset < 32768) { - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD0 + got_offset, - htab->splt->contents + h->plt.offset); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD1, - htab->splt->contents + h->plt.offset + 4); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD2, - htab->splt->contents + h->plt.offset + 8); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD3, - htab->splt->contents + h->plt.offset + 12); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD4, - htab->splt->contents + h->plt.offset + 16); + /* The GOT offset is too big for a displacement but small + enough to be a signed 16 bit immediate value as it can be + used in an lhi instruction. */ + memcpy (htab->splt->contents + h->plt.offset, + elf_s390_plt_pic16_entry, + PLT_ENTRY_SIZE); + + /* Put in the GOT offset for the lhi instruction. */ + bfd_put_16 (output_bfd, (bfd_vma)got_offset, + htab->splt->contents + h->plt.offset + 2); + + /* Adjust the jump to the first plt entry. */ bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16), htab->splt->contents + h->plt.offset + 20); - bfd_put_32 (output_bfd, (bfd_vma) 0, - htab->splt->contents + h->plt.offset + 24); } else { - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD0, - htab->splt->contents + h->plt.offset); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD1, - htab->splt->contents + h->plt.offset + 4); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD2, - htab->splt->contents + h->plt.offset + 8); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD3, - htab->splt->contents + h->plt.offset + 12); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD4, - htab->splt->contents + h->plt.offset + 16); + memcpy (htab->splt->contents + h->plt.offset, + elf_s390_plt_pic_entry, + PLT_ENTRY_SIZE); + + /* Adjust the jump to the first plt entry. */ bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16), htab->splt->contents + h->plt.offset + 20); + + /* Push the GOT offset field. */ bfd_put_32 (output_bfd, got_offset, htab->splt->contents + h->plt.offset + 24); } @@ -3367,31 +3410,13 @@ elf_s390_finish_dynamic_sections (output_bfd, info) memset (htab->splt->contents, 0, PLT_FIRST_ENTRY_SIZE); if (info->shared) { - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD0, - htab->splt->contents ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD1, - htab->splt->contents +4 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD2, - htab->splt->contents +8 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD3, - htab->splt->contents +12 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD4, - htab->splt->contents +16 ); - } + memcpy (htab->splt->contents, elf_s390_plt_pic_first_entry, + PLT_FIRST_ENTRY_SIZE); + } else - { - bfd_put_32 (output_bfd, (bfd_vma)PLT_FIRST_ENTRY_WORD0, - htab->splt->contents ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1, - htab->splt->contents +4 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD2, - htab->splt->contents +8 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3, - htab->splt->contents +12 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4, - htab->splt->contents +16 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5, - htab->splt->contents +20 ); + { + memcpy (htab->splt->contents, elf_s390_plt_first_entry, + PLT_FIRST_ENTRY_SIZE); bfd_put_32 (output_bfd, htab->sgotplt->output_section->vma + htab->sgotplt->output_offset, diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index fc9b7a6..118b052 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -553,14 +553,16 @@ elf_s390_is_local_label_name (abfd, name) the program that manages to have a symbol table of more than 2 GB with a total size of at max 4 GB. */ -#define PLT_ENTRY_WORD0 (bfd_vma) 0xc0100000 -#define PLT_ENTRY_WORD1 (bfd_vma) 0x0000e310 -#define PLT_ENTRY_WORD2 (bfd_vma) 0x10000004 -#define PLT_ENTRY_WORD3 (bfd_vma) 0x07f10d10 -#define PLT_ENTRY_WORD4 (bfd_vma) 0xe310100c -#define PLT_ENTRY_WORD5 (bfd_vma) 0x0014c0f4 -#define PLT_ENTRY_WORD6 (bfd_vma) 0x00000000 -#define PLT_ENTRY_WORD7 (bfd_vma) 0x00000000 +static const bfd_byte elf_s390x_plt_entry[PLT_ENTRY_SIZE] = + { + 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, /* larl %r1,. */ + 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, /* lg %r1,0(%r1) */ + 0x07, 0xf1, /* br %r1 */ + 0x0d, 0x10, /* basr %r1,%r0 */ + 0xe3, 0x10, 0x10, 0x0c, 0x00, 0x14, /* lgf %r1,12(%r1) */ + 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg first plt */ + 0x00, 0x00, 0x00, 0x00 /* .long 0x00000000 */ + }; /* The first PLT entry pushes the offset into the symbol table from R1 onto the stack at 8(15) and the loader object info @@ -577,14 +579,17 @@ elf_s390_is_local_label_name (abfd, name) Fixup at offset 8: relative address to start of GOT. */ -#define PLT_FIRST_ENTRY_WORD0 (bfd_vma) 0xe310f038 -#define PLT_FIRST_ENTRY_WORD1 (bfd_vma) 0x0024c010 -#define PLT_FIRST_ENTRY_WORD2 (bfd_vma) 0x00000000 -#define PLT_FIRST_ENTRY_WORD3 (bfd_vma) 0xd207f030 -#define PLT_FIRST_ENTRY_WORD4 (bfd_vma) 0x1008e310 -#define PLT_FIRST_ENTRY_WORD5 (bfd_vma) 0x10100004 -#define PLT_FIRST_ENTRY_WORD6 (bfd_vma) 0x07f10700 -#define PLT_FIRST_ENTRY_WORD7 (bfd_vma) 0x07000700 +static const bfd_byte elf_s390x_first_plt_entry[PLT_FIRST_ENTRY_SIZE] = + { + 0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24, /* stg %r1,56(%r15) */ + 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, /* larl %r1,. */ + 0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, /* mvc 48(8,%r15),8(%r1) */ + 0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, /* lg %r1,16(%r1) */ + 0x07, 0xf1, /* br %r1 */ + 0x07, 0x00, /* nopr %r0 */ + 0x07, 0x00, /* nopr %r0 */ + 0x07, 0x00 /* nopr %r0 */ + }; /* s390 ELF linker hash entry. */ @@ -3052,22 +3057,9 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd, got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; /* Fill in the blueprint of a PLT. */ - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0, - htab->splt->contents + h->plt.offset); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD1, - htab->splt->contents + h->plt.offset + 4); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD2, - htab->splt->contents + h->plt.offset + 8); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD3, - htab->splt->contents + h->plt.offset + 12); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD4, - htab->splt->contents + h->plt.offset + 16); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD5, - htab->splt->contents + h->plt.offset + 20); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD6, - htab->splt->contents + h->plt.offset + 24); - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD7, - htab->splt->contents + h->plt.offset + 28); + memcpy (htab->splt->contents + h->plt.offset, elf_s390x_plt_entry, + PLT_ENTRY_SIZE); + /* Fixup the relative address to the GOT entry */ bfd_put_32 (output_bfd, (htab->sgotplt->output_section->vma + @@ -3280,20 +3272,8 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd, if (htab->splt && htab->splt->size > 0) { /* fill in blueprint for plt 0 entry */ - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD0, - htab->splt->contents ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1, - htab->splt->contents +4 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3, - htab->splt->contents +12 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4, - htab->splt->contents +16 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5, - htab->splt->contents +20 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD6, - htab->splt->contents + 24); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD7, - htab->splt->contents + 28 ); + memcpy (htab->splt->contents, elf_s390x_first_plt_entry, + PLT_FIRST_ENTRY_SIZE); /* Fixup relative address to start of GOT */ bfd_put_32 (output_bfd, (htab->sgotplt->output_section->vma + |