Compare commits

...

6 Commits

Author SHA1 Message Date
Marcin Kościelnicki
0757c0695b gold/s390: Support partial got relro. 2016-07-04 11:04:48 +02:00
Marcin Kościelnicki
6257e07319 bfd/elf64-s390: Support partial got relro. 2016-07-04 11:04:10 +02:00
Marcin Kościelnicki
6f074b23dc bfd/elf32-s390: Support partial got relro. 2016-07-04 11:04:10 +02:00
Marcin Kościelnicki
137afa28a3 bfd/elf32-s390: Prepare for _GLOBAL_OFFSET_TABLE_ != DT_PLTGOT
This will be used for got relro support.
2016-06-22 13:06:44 +02:00
Marcin Kościelnicki
2dacf3e9c8 bfd/elf64-s390: Prepare for _GLOBAL_OFFSET_TABLE_ != DT_PLTGOT
This will be used for got relro support.
2016-06-22 13:06:44 +02:00
Marcin Kościelnicki
cbbdd10114 ld: Enable using separate linker script for -z relro
This will be used for s390 relro got support.

ld/ChangeLog:

	* emultempl/elf32.em: Use .xo, .xso, .xdo scripts if
	GENERATE_RELRO_SCRIPT is set.
	* genscripts.sh: Create .xo, .xso, .xdo scripts if
	GENERATE_RELRO_SCRIPT is set.
2016-06-22 13:06:44 +02:00
7 changed files with 462 additions and 77 deletions

View File

@@ -629,6 +629,19 @@ static const bfd_byte elf_s390_plt_first_entry[PLT_FIRST_ENTRY_SIZE] =
}; };
static const bfd_byte elf_s390_plt_pic_first_entry[PLT_FIRST_ENTRY_SIZE] = static const bfd_byte elf_s390_plt_pic_first_entry[PLT_FIRST_ENTRY_SIZE] =
{
0x50, 0x10, 0xf0, 0x1c, /* st %r1,28(%r15) */
0x0d, 0x10, /* basr %r1,%r0 */
0x5a, 0x10, 0x10, 0x12, /* a %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_pic12_first_entry[PLT_FIRST_ENTRY_SIZE] =
{ {
0x50, 0x10, 0xf0, 0x1c, /* st %r1,28(%r15) */ 0x50, 0x10, 0xf0, 0x1c, /* st %r1,28(%r15) */
0x58, 0x10, 0xc0, 0x04, /* l %r1,4(%r12) */ 0x58, 0x10, 0xc0, 0x04, /* l %r1,4(%r12) */
@@ -740,6 +753,8 @@ struct elf_s390_link_hash_table
asection *srelbss; asection *srelbss;
asection *irelifunc; asection *irelifunc;
bfd_boolean split_got;
union union
{ {
bfd_signed_vma refcount; bfd_signed_vma refcount;
@@ -823,6 +838,8 @@ static bfd_boolean
create_got_section (bfd *dynobj, struct bfd_link_info *info) create_got_section (bfd *dynobj, struct bfd_link_info *info)
{ {
struct elf_s390_link_hash_table *htab; struct elf_s390_link_hash_table *htab;
struct elf_link_hash_entry *h;
asection *got_section;
if (! _bfd_elf_create_got_section (dynobj, info)) if (! _bfd_elf_create_got_section (dynobj, info))
return FALSE; return FALSE;
@@ -834,6 +851,27 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot) if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot)
abort (); abort ();
/* The condition here has to match linker script selection. */
if (info->combreloc && info->relro && !(info->flags & DF_BIND_NOW))
{
htab->elf.sgot->size += GOT_ENTRY_SIZE;
got_section = htab->elf.sgot;
htab->split_got = TRUE;
}
else
{
got_section = htab->elf.sgotplt;
htab->split_got = FALSE;
}
/* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
or .got.plt section. */
h = _bfd_elf_define_linkage_sym (dynobj, info, got_section,
"_GLOBAL_OFFSET_TABLE_");
elf_hash_table (info)->hgot = h;
if (h == NULL)
return FALSE;
return TRUE; return TRUE;
} }
@@ -2508,9 +2546,10 @@ elf_s390_relocate_section (bfd *output_bfd,
{ {
plt_index = h->plt.offset / PLT_ENTRY_SIZE; plt_index = h->plt.offset / PLT_ENTRY_SIZE;
relocation = (plt_index * GOT_ENTRY_SIZE + relocation = (plt_index * GOT_ENTRY_SIZE +
htab->elf.igotplt->output_offset); htab->elf.igotplt->output_offset +
if (r_type == R_390_GOTPLTENT) htab->elf.igotplt->output_section->vma);
relocation += htab->elf.igotplt->output_section->vma; if (r_type != R_390_GOTPLTENT)
relocation -= htab->elf.sgot->output_section->vma;
} }
else else
{ {
@@ -2521,9 +2560,11 @@ elf_s390_relocate_section (bfd *output_bfd,
/* Offset in GOT is PLT index plus GOT headers(3) /* Offset in GOT is PLT index plus GOT headers(3)
times 4, addr & GOT addr. */ times 4, addr & GOT addr. */
relocation = (plt_index + 3) * GOT_ENTRY_SIZE; relocation = (plt_index + 3) * GOT_ENTRY_SIZE +
if (r_type == R_390_GOTPLTENT) htab->elf.sgotplt->output_offset +
relocation += htab->elf.sgot->output_section->vma; htab->elf.sgotplt->output_section->vma;
if (r_type != R_390_GOTPLTENT)
relocation -= htab->elf.sgot->output_section->vma;
} }
unresolved_reloc = FALSE; unresolved_reloc = FALSE;
@@ -2671,15 +2712,16 @@ elf_s390_relocate_section (bfd *output_bfd,
if (off >= (bfd_vma) -2) if (off >= (bfd_vma) -2)
abort (); abort ();
relocation = base_got->output_offset + off; relocation = base_got->output_offset + off +
base_got->output_section->vma;
/* For @GOTENT the relocation is against the offset between /* For @GOTENT the relocation is against the offset between
the instruction and the symbols entry in the GOT and not the instruction and the symbols entry in the GOT and not
between the start of the GOT and the symbols entry. We between the start of the GOT and the symbols entry. We
add the vma of the GOT to get the correct value. */ add the vma of the GOT to get the correct value. */
if ( r_type == R_390_GOTENT if ( r_type != R_390_GOTENT
|| r_type == R_390_GOTPLTENT) && r_type != R_390_GOTPLTENT)
relocation += base_got->output_section->vma; relocation -= base_got->output_section->vma;
break; break;
@@ -3492,7 +3534,9 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
/* Offset into the igot.plt section. */ /* Offset into the igot.plt section. */
igotiplt_offset = iplt_index * GOT_ENTRY_SIZE; igotiplt_offset = iplt_index * GOT_ENTRY_SIZE;
/* Offset into the got section. */ /* Offset into the got section. */
got_offset = igotiplt_offset + gotplt->output_offset; got_offset = igotiplt_offset + gotplt->output_offset +
gotplt->output_section->vma -
htab->elf.sgot->output_section->vma;
/* S390 uses halfwords for relative branch calc! */ /* S390 uses halfwords for relative branch calc! */
relative_offset = - (plt->output_offset + relative_offset = - (plt->output_offset +
@@ -3515,7 +3559,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
/* Push the GOT offset field. */ /* Push the GOT offset field. */
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
(gotplt->output_section->vma (htab->elf.sgot->output_section->vma
+ got_offset), + got_offset),
plt->contents + iplt_offset + 24); plt->contents + iplt_offset + 24);
} }
@@ -3583,7 +3627,7 @@ elf_s390_finish_ifunc_symbol (bfd *output_bfd,
gotplt->contents + igotiplt_offset); gotplt->contents + igotiplt_offset);
/* Fill in the entry in the .rela.plt section. */ /* Fill in the entry in the .rela.plt section. */
rela.r_offset = gotplt->output_section->vma + got_offset; rela.r_offset = htab->elf.sgot->output_section->vma + got_offset;
if (!h if (!h
|| h->dynindx == -1 || h->dynindx == -1
@@ -3623,6 +3667,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
{ {
bfd_vma plt_index; bfd_vma plt_index;
bfd_vma got_offset; bfd_vma got_offset;
bfd_vma got_plt_offset;
Elf_Internal_Rela rela; Elf_Internal_Rela rela;
bfd_byte *loc; bfd_byte *loc;
bfd_vma relative_offset; bfd_vma relative_offset;
@@ -3653,7 +3698,10 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
/* Offset in GOT is PLT index plus GOT headers(3) times 4, /* Offset in GOT is PLT index plus GOT headers(3) times 4,
addr & GOT addr. */ addr & GOT addr. */
got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; got_plt_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
got_offset = got_plt_offset + htab->elf.sgotplt->output_offset +
htab->elf.sgotplt->output_section->vma -
htab->elf.sgot->output_section->vma;
/* S390 uses halfwords for relative branch calc! */ /* S390 uses halfwords for relative branch calc! */
relative_offset = - ((PLT_FIRST_ENTRY_SIZE + relative_offset = - ((PLT_FIRST_ENTRY_SIZE +
@@ -3676,8 +3724,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
/* Push the GOT offset field. */ /* Push the GOT offset field. */
bfd_put_32 (output_bfd, bfd_put_32 (output_bfd,
(htab->elf.sgotplt->output_section->vma (htab->elf.sgot->output_section->vma
+ htab->elf.sgotplt->output_offset
+ got_offset), + got_offset),
htab->elf.splt->contents + h->plt.offset + 24); htab->elf.splt->contents + h->plt.offset + 24);
} }
@@ -3741,11 +3788,10 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+ htab->elf.splt->output_offset + htab->elf.splt->output_offset
+ h->plt.offset + h->plt.offset
+ 12), + 12),
htab->elf.sgotplt->contents + got_offset); htab->elf.sgotplt->contents + got_plt_offset);
/* Fill in the entry in the .rela.plt section. */ /* Fill in the entry in the .rela.plt section. */
rela.r_offset = (htab->elf.sgotplt->output_section->vma rela.r_offset = (htab->elf.sgot->output_section->vma
+ htab->elf.sgotplt->output_offset
+ got_offset); + got_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_390_JMP_SLOT); rela.r_info = ELF32_R_INFO (h->dynindx, R_390_JMP_SLOT);
rela.r_addend = 0; rela.r_addend = 0;
@@ -3921,6 +3967,7 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
asection *sdyn; asection *sdyn;
bfd *ibfd; bfd *ibfd;
unsigned int i; unsigned int i;
bfd_vma got_plt_offset;
htab = elf_s390_hash_table (info); htab = elf_s390_hash_table (info);
dynobj = htab->elf.dynobj; dynobj = htab->elf.dynobj;
@@ -3971,8 +4018,33 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
memset (htab->elf.splt->contents, 0, PLT_FIRST_ENTRY_SIZE); memset (htab->elf.splt->contents, 0, PLT_FIRST_ENTRY_SIZE);
if (bfd_link_pic (info)) if (bfd_link_pic (info))
{ {
memcpy (htab->elf.splt->contents, elf_s390_plt_pic_first_entry, got_plt_offset = htab->elf.sgotplt->output_offset +
PLT_FIRST_ENTRY_SIZE); htab->elf.sgotplt->output_section->vma -
htab->elf.sgot->output_section->vma;
if (got_plt_offset < 0xff8)
{
memcpy (htab->elf.splt->contents,
elf_s390_plt_pic12_first_entry,
PLT_FIRST_ENTRY_SIZE);
/* Put in the GOT offset as displacement values. The 0xc000
value comes from the first word of the plt entry. Look
at the elf_s390_plt_pic12_first_entry content. */
bfd_put_16 (output_bfd, (bfd_vma)0xc000 | (got_plt_offset + 4),
htab->elf.splt->contents + 6);
bfd_put_16 (output_bfd, (bfd_vma)0xc000 | (got_plt_offset + 8),
htab->elf.splt->contents + 14);
}
else
{
memcpy (htab->elf.splt->contents,
elf_s390_plt_pic_first_entry,
PLT_FIRST_ENTRY_SIZE);
bfd_put_32 (output_bfd,
htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset
- htab->elf.splt->output_section->vma - 6,
htab->elf.splt->contents + 24);
}
} }
else else
{ {
@@ -4007,6 +4079,15 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
elf_section_data (htab->elf.sgotplt->output_section) elf_section_data (htab->elf.sgotplt->output_section)
->this_hdr.sh_entsize = 4; ->this_hdr.sh_entsize = 4;
} }
if (htab->elf.sgot && htab->split_got)
{
bfd_put_32 (output_bfd,
(sdyn == NULL ? (bfd_vma) 0
: sdyn->output_section->vma + sdyn->output_offset),
htab->elf.sgot->contents);
}
/* Finish dynamic symbol for local IFUNC symbols. */ /* Finish dynamic symbol for local IFUNC symbols. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{ {
@@ -4109,6 +4190,8 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
#define elf_backend_want_got_plt 1 #define elf_backend_want_got_plt 1
#define elf_backend_plt_readonly 1 #define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0 #define elf_backend_want_plt_sym 0
/* We create got symbol ourselves, since it may not be in .got.plt */
#define elf_backend_want_got_sym 0
#define elf_backend_got_header_size 12 #define elf_backend_got_header_size 12
#define elf_backend_rela_normal 1 #define elf_backend_rela_normal 1

View File

@@ -653,6 +653,8 @@ struct elf_s390_link_hash_table
asection *srelbss; asection *srelbss;
asection *irelifunc; asection *irelifunc;
bfd_boolean split_got;
union { union {
bfd_signed_vma refcount; bfd_signed_vma refcount;
bfd_vma offset; bfd_vma offset;
@@ -736,6 +738,8 @@ create_got_section (bfd *dynobj,
struct bfd_link_info *info) struct bfd_link_info *info)
{ {
struct elf_s390_link_hash_table *htab; struct elf_s390_link_hash_table *htab;
struct elf_link_hash_entry *h;
asection *got_section;
if (! _bfd_elf_create_got_section (dynobj, info)) if (! _bfd_elf_create_got_section (dynobj, info))
return FALSE; return FALSE;
@@ -749,6 +753,28 @@ create_got_section (bfd *dynobj,
htab->elf.srelgot = bfd_get_linker_section (dynobj, ".rela.got"); htab->elf.srelgot = bfd_get_linker_section (dynobj, ".rela.got");
if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot) if (!htab->elf.sgot || !htab->elf.sgotplt || !htab->elf.srelgot)
abort (); abort ();
/* The condition here has to match linker script selection. */
if (info->combreloc && info->relro && !(info->flags & DF_BIND_NOW))
{
htab->elf.sgot->size += GOT_ENTRY_SIZE;
got_section = htab->elf.sgot;
htab->split_got = TRUE;
}
else
{
got_section = htab->elf.sgotplt;
htab->split_got = FALSE;
}
/* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
or .got.plt section. */
h = _bfd_elf_define_linkage_sym (dynobj, info, got_section,
"_GLOBAL_OFFSET_TABLE_");
elf_hash_table (info)->hgot = h;
if (h == NULL)
return FALSE;
return TRUE; return TRUE;
} }
@@ -2467,9 +2493,10 @@ elf_s390_relocate_section (bfd *output_bfd,
{ {
plt_index = h->plt.offset / PLT_ENTRY_SIZE; plt_index = h->plt.offset / PLT_ENTRY_SIZE;
relocation = (plt_index * GOT_ENTRY_SIZE + relocation = (plt_index * GOT_ENTRY_SIZE +
htab->elf.igotplt->output_offset); htab->elf.igotplt->output_offset +
if (r_type == R_390_GOTPLTENT) htab->elf.igotplt->output_section->vma);
relocation += htab->elf.igotplt->output_section->vma; if (r_type != R_390_GOTPLTENT)
relocation -= htab->elf.sgot->output_section->vma;
} }
else else
{ {
@@ -2480,9 +2507,11 @@ elf_s390_relocate_section (bfd *output_bfd,
/* Offset in GOT is PLT index plus GOT headers(3) /* Offset in GOT is PLT index plus GOT headers(3)
times 8, addr & GOT addr. */ times 8, addr & GOT addr. */
relocation = (plt_index + 3) * GOT_ENTRY_SIZE; relocation = (plt_index + 3) * GOT_ENTRY_SIZE +
if (r_type == R_390_GOTPLTENT) htab->elf.sgotplt->output_offset +
relocation += htab->elf.sgot->output_section->vma; htab->elf.sgotplt->output_section->vma;
if (r_type != R_390_GOTPLTENT)
relocation -= htab->elf.sgot->output_section->vma;
} }
unresolved_reloc = FALSE; unresolved_reloc = FALSE;
break; break;
@@ -2631,15 +2660,16 @@ elf_s390_relocate_section (bfd *output_bfd,
if (off >= (bfd_vma) -2) if (off >= (bfd_vma) -2)
abort (); abort ();
relocation = base_got->output_offset + off; relocation = base_got->output_offset + off +
base_got->output_section->vma;
/* For @GOTENT the relocation is against the offset between /* For @GOTENT the relocation is against the offset between
the instruction and the symbols entry in the GOT and not the instruction and the symbols entry in the GOT and not
between the start of the GOT and the symbols entry. We between the start of the GOT and the symbols entry. We
add the vma of the GOT to get the correct value. */ add the vma of the GOT to get the correct value. */
if ( r_type == R_390_GOTENT if ( r_type != R_390_GOTENT
|| r_type == R_390_GOTPLTENT) && r_type != R_390_GOTPLTENT)
relocation += base_got->output_section->vma; relocation -= htab->elf.sgot->output_section->vma;
break; break;
@@ -3810,6 +3840,14 @@ elf_s390_finish_dynamic_sections (bfd *output_bfd,
->this_hdr.sh_entsize = 8; ->this_hdr.sh_entsize = 8;
} }
if (htab->elf.sgot && htab->split_got)
{
bfd_put_64 (output_bfd,
(sdyn == NULL ? (bfd_vma) 0
: sdyn->output_section->vma + sdyn->output_offset),
htab->elf.sgot->contents);
}
/* Finish dynamic symbol for local IFUNC symbols. */ /* Finish dynamic symbol for local IFUNC symbols. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{ {
@@ -3919,6 +3957,8 @@ const struct elf_size_info s390_elf64_size_info =
#define elf_backend_want_got_plt 1 #define elf_backend_want_got_plt 1
#define elf_backend_plt_readonly 1 #define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0 #define elf_backend_want_plt_sym 0
/* We create got symbol ourselves, since it may not be in .got.plt */
#define elf_backend_want_got_sym 0
#define elf_backend_got_header_size 24 #define elf_backend_got_header_size 24
#define elf_backend_rela_normal 1 #define elf_backend_rela_normal 1

View File

@@ -78,6 +78,38 @@ class Output_data_got_plt_s390 : public Output_section_data_build
Layout* layout_; Layout* layout_;
}; };
// A class to handle the first entry of .got when partial relro is in use.
template<int size>
class Output_data_got_dynamic_s390 : public Output_section_data_build
{
public:
Output_data_got_dynamic_s390(Layout* layout)
: Output_section_data_build(size/8),
layout_(layout)
{ }
Output_data_got_dynamic_s390(Layout* layout, off_t data_size)
: Output_section_data_build(data_size, size/8),
layout_(layout)
{ }
protected:
// Write out the PLT data.
void
do_write(Output_file*);
// Write to a map file.
void
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, "** GOT DYNAMIC"); }
private:
// A pointer to the Layout class, so that we can find the .dynamic
// section when we write out the GOT section.
Layout* layout_;
};
// A class to handle the PLT data. // A class to handle the PLT data.
template<int size> template<int size>
@@ -90,10 +122,11 @@ class Output_data_plt_s390 : public Output_section_data
Output_data_plt_s390(Layout* layout, Output_data_plt_s390(Layout* layout,
Output_data_got<size, true>* got, Output_data_got<size, true>* got,
Output_data_got_plt_s390<size>* got_plt, Output_data_got_plt_s390<size>* got_plt,
Output_data_space* got_irelative) Output_data_space* got_irelative,
Output_section_data_build* got_dynamic)
: Output_section_data(4), layout_(layout), : Output_section_data(4), layout_(layout),
irelative_rel_(NULL), got_(got), got_plt_(got_plt), irelative_rel_(NULL), got_(got), got_plt_(got_plt),
got_irelative_(got_irelative), count_(0), got_irelative_(got_irelative), got_dynamic_(got_dynamic), count_(0),
irelative_count_(0), free_list_() irelative_count_(0), free_list_()
{ this->init(layout); } { this->init(layout); }
@@ -101,11 +134,13 @@ class Output_data_plt_s390 : public Output_section_data
Output_data_got<size, true>* got, Output_data_got<size, true>* got,
Output_data_got_plt_s390<size>* got_plt, Output_data_got_plt_s390<size>* got_plt,
Output_data_space* got_irelative, Output_data_space* got_irelative,
Output_section_data_build* got_dynamic,
unsigned int plt_count) unsigned int plt_count)
: Output_section_data((plt_count + 1) * plt_entry_size, : Output_section_data((plt_count + 1) * plt_entry_size,
4, false), 4, false),
layout_(layout), irelative_rel_(NULL), got_(got), layout_(layout), irelative_rel_(NULL), got_(got),
got_plt_(got_plt), got_irelative_(got_irelative), count_(plt_count), got_plt_(got_plt), got_irelative_(got_irelative),
got_dynamic_(got_dynamic), count_(plt_count),
irelative_count_(0), free_list_() irelative_count_(0), free_list_()
{ {
this->init(layout); this->init(layout);
@@ -195,7 +230,8 @@ class Output_data_plt_s390 : public Output_section_data
void void
fill_first_plt_entry(unsigned char* pov, fill_first_plt_entry(unsigned char* pov,
typename elfcpp::Elf_types<size>::Elf_Addr got_address, typename elfcpp::Elf_types<size>::Elf_Addr got_address,
typename elfcpp::Elf_types<size>::Elf_Addr plt_address); typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
unsigned int got_plt_offset);
// Fill in a normal PLT entry. Returns the offset into the entry that // Fill in a normal PLT entry. Returns the offset into the entry that
// should be the initial GOT slot value. // should be the initial GOT slot value.
@@ -238,6 +274,8 @@ class Output_data_plt_s390 : public Output_section_data
Output_data_got_plt_s390<size>* got_plt_; Output_data_got_plt_s390<size>* got_plt_;
// The part of the .got.plt section used for IRELATIVE relocs. // The part of the .got.plt section used for IRELATIVE relocs.
Output_data_space* got_irelative_; Output_data_space* got_irelative_;
// The header of .got section.
Output_section_data_build* got_dynamic_;
// The number of PLT entries. // The number of PLT entries.
unsigned int count_; unsigned int count_;
// Number of PLT entries with R_TILEGX_IRELATIVE relocs. These // Number of PLT entries with R_TILEGX_IRELATIVE relocs. These
@@ -251,6 +289,7 @@ class Output_data_plt_s390 : public Output_section_data
static const int plt_entry_size = 0x20; static const int plt_entry_size = 0x20;
// The first entry in the PLT. // The first entry in the PLT.
static const unsigned char first_plt_entry_32_abs[plt_entry_size]; static const unsigned char first_plt_entry_32_abs[plt_entry_size];
static const unsigned char first_plt_entry_32_pic12[plt_entry_size];
static const unsigned char first_plt_entry_32_pic[plt_entry_size]; static const unsigned char first_plt_entry_32_pic[plt_entry_size];
static const unsigned char first_plt_entry_64[plt_entry_size]; static const unsigned char first_plt_entry_64[plt_entry_size];
// Other entries in the PLT for an executable. // Other entries in the PLT for an executable.
@@ -646,7 +685,7 @@ class Target_s390 : public Sized_target<size, true>
got_address() const got_address() const
{ {
gold_assert(this->got_ != NULL); gold_assert(this->got_ != NULL);
return this->got_plt_->address(); return this->got_dynamic_->address();
} }
typename elfcpp::Elf_types<size>::Elf_Addr typename elfcpp::Elf_types<size>::Elf_Addr
@@ -741,6 +780,10 @@ class Target_s390 : public Sized_target<size, true>
Output_data_got_plt_s390<size>* got_plt_; Output_data_got_plt_s390<size>* got_plt_;
// The GOT section for IRELATIVE relocations. // The GOT section for IRELATIVE relocations.
Output_data_space* got_irelative_; Output_data_space* got_irelative_;
// The section containing the first GOT entry (_DYNAMIC) - this is
// Output_data_got_dynamic_s390 if partial relro is in use, same
// as got_plt_ otherwise.
Output_section_data_build* got_dynamic_;
// The _GLOBAL_OFFSET_TABLE_ symbol. // The _GLOBAL_OFFSET_TABLE_ symbol.
Symbol* global_offset_table_; Symbol* global_offset_table_;
// The dynamic reloc section. // The dynamic reloc section.
@@ -1247,18 +1290,18 @@ Output_data_plt_s390<size>::first_plt_entry_32_abs[plt_entry_size] =
0x58, 0x10, 0x10, 0x08, // l %r1, 8(%r1) 0x58, 0x10, 0x10, 0x08, // l %r1, 8(%r1)
0x07, 0xf1, // br %r1 0x07, 0xf1, // br %r1
0x00, 0x00, // padding 0x00, 0x00, // padding
0x00, 0x00, 0x00, 0x00, // _GLOBAL_OFFSET_TABLE_ (to fill) 0x00, 0x00, 0x00, 0x00, // DT_GOTPLT (to fill)
0x00, 0x00, 0x00, 0x00, // padding 0x00, 0x00, 0x00, 0x00, // padding
}; };
template<int size> template<int size>
const unsigned char const unsigned char
Output_data_plt_s390<size>::first_plt_entry_32_pic[plt_entry_size] = Output_data_plt_s390<size>::first_plt_entry_32_pic12[plt_entry_size] =
{ {
0x50, 0x10, 0xf0, 0x1c, // st %r1, 28(%r15) 0x50, 0x10, 0xf0, 0x1c, // st %r1, 28(%r15)
0x58, 0x10, 0xc0, 0x04, // l %r1, 4(%r12) 0x58, 0x10, 0xc0, 0x00, // l %r1, DT_GOTPLT@got+4(%r12) (to fill)
0x50, 0x10, 0xf0, 0x18, // st %r1, 24(%r15) 0x50, 0x10, 0xf0, 0x18, // st %r1, 24(%r15)
0x58, 0x10, 0xc0, 0x08, // l %r1, 8(%r12) 0x58, 0x10, 0xc0, 0x00, // l %r1, DT_GOTPLT@got+8(%r12) (to fill)
0x07, 0xf1, // br %r1 0x07, 0xf1, // br %r1
0x00, 0x00, // padding 0x00, 0x00, // padding
0x00, 0x00, 0x00, 0x00, // padding 0x00, 0x00, 0x00, 0x00, // padding
@@ -1266,12 +1309,27 @@ Output_data_plt_s390<size>::first_plt_entry_32_pic[plt_entry_size] =
0x00, 0x00, 0x00, 0x00, // padding 0x00, 0x00, 0x00, 0x00, // padding
}; };
template<int size>
const unsigned char
Output_data_plt_s390<size>::first_plt_entry_32_pic[plt_entry_size] =
{
0x50, 0x10, 0xf0, 0x1c, // st %r1, 28(%r15)
0x0d, 0x10, // basr %r1, %r0
0x5a, 0x10, 0x10, 0x12, // a %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, // padding
0x00, 0x00, 0x00, 0x00, // DT_GOTPLT - . + 18 (to fill)
0x00, 0x00, 0x00, 0x00, // padding
};
template<int size> template<int size>
const unsigned char const unsigned char
Output_data_plt_s390<size>::first_plt_entry_64[plt_entry_size] = Output_data_plt_s390<size>::first_plt_entry_64[plt_entry_size] =
{ {
0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24, // stg %r1, 56(%r15) 0xe3, 0x10, 0xf0, 0x38, 0x00, 0x24, // stg %r1, 56(%r15)
0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1, _GLOBAL_OFFSET_TABLE_ (to fill) 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, // larl %r1, DT_GOTPLT (to fill)
0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, // mvc 48(8,%r15), 8(%r1) 0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, // mvc 48(8,%r15), 8(%r1)
0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, // lg %r1, 16(%r1) 0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, // lg %r1, 16(%r1)
0x07, 0xf1, // br %r1 0x07, 0xf1, // br %r1
@@ -1284,22 +1342,33 @@ template<int size>
void void
Output_data_plt_s390<size>::fill_first_plt_entry( Output_data_plt_s390<size>::fill_first_plt_entry(
unsigned char* pov, unsigned char* pov,
typename elfcpp::Elf_types<size>::Elf_Addr got_address, typename elfcpp::Elf_types<size>::Elf_Addr got_plt_address,
typename elfcpp::Elf_types<size>::Elf_Addr plt_address) typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
unsigned int got_plt_offset)
{ {
if (size == 64) if (size == 64)
{ {
memcpy(pov, first_plt_entry_64, plt_entry_size); memcpy(pov, first_plt_entry_64, plt_entry_size);
S390_relocate_functions<size>::pcrela32dbl(pov + 8, got_address, (plt_address + 6)); S390_relocate_functions<size>::pcrela32dbl(pov + 8, got_plt_address, (plt_address + 6));
} }
else if (!parameters->options().output_is_position_independent()) else if (!parameters->options().output_is_position_independent())
{ {
memcpy(pov, first_plt_entry_32_abs, plt_entry_size); memcpy(pov, first_plt_entry_32_abs, plt_entry_size);
elfcpp::Swap<32, true>::writeval(pov + 24, got_address); elfcpp::Swap<32, true>::writeval(pov + 24, got_plt_address);
} }
else else
{ {
memcpy(pov, first_plt_entry_32_pic, plt_entry_size); if (got_plt_offset < 0xff8)
{
memcpy(pov, first_plt_entry_32_pic12, plt_entry_size);
S390_relocate_functions<size>::rela12(pov + 6, got_plt_offset + 4);
S390_relocate_functions<size>::rela12(pov + 14, got_plt_offset + 8);
}
else
{
memcpy(pov, first_plt_entry_32_pic, plt_entry_size);
elfcpp::Swap<32, true>::writeval(pov + 24, got_plt_address - (plt_address + 6));
}
} }
} }
@@ -1536,9 +1605,12 @@ Output_data_plt_s390<size>::do_write(Output_file* of)
// which is where the GOT pointer will point, and where the // which is where the GOT pointer will point, and where the
// three reserved GOT entries are located. // three reserved GOT entries are located.
typename elfcpp::Elf_types<size>::Elf_Addr got_address typename elfcpp::Elf_types<size>::Elf_Addr got_address
= this->got_plt_->address(); = this->got_dynamic_->address();
this->fill_first_plt_entry(pov, got_address, plt_address); unsigned int got_plt_offset = this->got_plt_->address() - got_address;
this->fill_first_plt_entry(pov, this->got_plt_->address(), plt_address,
got_plt_offset);
pov += this->get_plt_entry_size(); pov += this->get_plt_entry_size();
unsigned char* got_pov = got_view; unsigned char* got_pov = got_view;
@@ -1547,7 +1619,7 @@ Output_data_plt_s390<size>::do_write(Output_file* of)
unsigned int plt_offset = this->get_plt_entry_size(); unsigned int plt_offset = this->get_plt_entry_size();
unsigned int plt_rel_offset = 0; unsigned int plt_rel_offset = 0;
unsigned int got_offset = 3 * size / 8; unsigned int got_offset = 3 * size / 8 + got_plt_offset;
const unsigned int count = this->count_ + this->irelative_count_; const unsigned int count = this->count_ + this->irelative_count_;
// The first three entries in the GOT are reserved, and are written // The first three entries in the GOT are reserved, and are written
// by Output_data_got_plt_s390::do_write. // by Output_data_got_plt_s390::do_write.
@@ -1590,22 +1662,43 @@ Target_s390<size>::got_section(Symbol_table* symtab, Layout* layout)
{ {
gold_assert(symtab != NULL && layout != NULL); gold_assert(symtab != NULL && layout != NULL);
// When using -z now, we can treat .got as a relro section. bool is_got_relro, is_got_plt_relro;
// Without -z now, it is modified after program startup by lazy Output_section_order got_order, got_plt_order;
// PLT relocations. const char *got_plt_name;
bool is_got_relro = parameters->options().now(); if (parameters->options().relro())
Output_section_order got_order = (is_got_relro {
? ORDER_RELRO_LAST // Partial GOT relro.
: ORDER_DATA); is_got_relro = true;
is_got_plt_relro = false;
got_order = ORDER_RELRO_LAST;
got_plt_order = ORDER_NON_RELRO_FIRST;
got_plt_name = ".got.plt";
}
else if (parameters->options().now())
{
// When using -z now, we can treat the whole .got as a relro section.
is_got_plt_relro = is_got_relro = true;
got_order = got_plt_order = ORDER_RELRO_LAST;
got_plt_name = ".got";
}
else
{
// Without -z now, it is modified after program startup by lazy
// PLT relocations.
is_got_plt_relro = is_got_relro = false;
got_order = got_plt_order = ORDER_DATA;
got_plt_name = ".got";
}
// The old GNU linker creates a .got.plt section. We just // The old GNU linker creates a .got.plt section. We just
// create another set of data in the .got section. Note that we // create another set of data in the .got section. Note that we
// always create a PLT if we create a GOT, although the PLT // always create a PLT if we create a GOT, although the PLT
// might be empty. // might be empty.
this->got_plt_ = new Output_data_got_plt_s390<size>(layout); this->got_plt_ = new Output_data_got_plt_s390<size>(layout);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
this->got_plt_, got_order, is_got_relro); this->got_plt_, got_plt_order,
is_got_plt_relro);
// The first three entries are reserved. // The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * size / 8); this->got_plt_->set_current_data_size(3 * size / 8);
@@ -1613,10 +1706,23 @@ Target_s390<size>::got_section(Symbol_table* symtab, Layout* layout)
// If there are any IRELATIVE relocations, they get GOT entries // If there are any IRELATIVE relocations, they get GOT entries
// in .got.plt after the jump slot entries. // in .got.plt after the jump slot entries.
this->got_irelative_ = new Output_data_space(size / 8, "** GOT IRELATIVE PLT"); this->got_irelative_ = new Output_data_space(size / 8, "** GOT IRELATIVE PLT");
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
this->got_irelative_, this->got_irelative_,
got_order, is_got_relro); got_plt_order, is_got_plt_relro);
if (parameters->options().relro())
{
// For partial relro, we need a _DYNAMIC pointer at
// _GLOBAL_OFFSET_TABLE_, not at DT_GOTPLT.
this->got_dynamic_ = new Output_data_got_dynamic_s390<size>(layout);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
this->got_dynamic_, got_order, true);
this->got_dynamic_->set_current_data_size(size / 8);
}
else
this->got_dynamic_ = this->got_plt_;
// Unlike some targets (.e.g x86), S/390 does not use separate .got and // Unlike some targets (.e.g x86), S/390 does not use separate .got and
// .got.plt sections in output. The output .got section contains both // .got.plt sections in output. The output .got section contains both
@@ -1629,9 +1735,9 @@ Target_s390<size>::got_section(Symbol_table* symtab, Layout* layout)
// Define _GLOBAL_OFFSET_TABLE_ at the start of the GOT. // Define _GLOBAL_OFFSET_TABLE_ at the start of the GOT.
this->global_offset_table_ = this->global_offset_table_ =
symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
Symbol_table::PREDEFINED, Symbol_table::PREDEFINED,
this->got_plt_, this->got_dynamic_,
0, 0, elfcpp::STT_OBJECT, 0, 0, elfcpp::STT_OBJECT,
elfcpp::STB_LOCAL, elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0, elfcpp::STV_HIDDEN, 0,
@@ -1693,7 +1799,7 @@ Output_data_got_plt_s390<size>::do_write(Output_file* of)
// The first entry in the GOT is the address of the .dynamic section // The first entry in the GOT is the address of the .dynamic section
// aka the PT_DYNAMIC segment. The next two entries are reserved. // aka the PT_DYNAMIC segment. The next two entries are reserved.
// We saved space for them when we created the section in // We saved space for them when we created the section in
// Target_x86_64::got_section. // Target_s390::got_section.
const off_t got_file_offset = this->offset(); const off_t got_file_offset = this->offset();
gold_assert(this->data_size() >= 3 * size / 8); gold_assert(this->data_size() >= 3 * size / 8);
unsigned char* const got_view = unsigned char* const got_view =
@@ -1705,6 +1811,26 @@ Output_data_got_plt_s390<size>::do_write(Output_file* of)
of->write_output_view(got_file_offset, 3 * size / 8, got_view); of->write_output_view(got_file_offset, 3 * size / 8, got_view);
} }
// Write the first reserved word of the .got section.
template<int size>
void
Output_data_got_dynamic_s390<size>::do_write(Output_file* of)
{
// The first entry in the GOT is the address of the .dynamic section
// aka the PT_DYNAMIC segment. The next two entries are reserved.
// We saved space for them when we created the section in
// Target_s390::got_section.
const off_t got_file_offset = this->offset();
gold_assert(this->data_size() == size / 8);
unsigned char* const got_view =
of->get_output_view(got_file_offset, size / 8);
Output_section* dynamic = this->layout_->dynamic_section();
uint64_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
elfcpp::Swap<size, true>::writeval(got_view, dynamic_addr);
of->write_output_view(got_file_offset, size / 8, got_view);
}
// Create the PLT section. // Create the PLT section.
template<int size> template<int size>
@@ -1722,7 +1848,8 @@ Target_s390<size>::make_plt_section(Symbol_table* symtab, Layout* layout)
this->rela_dyn_section(layout); this->rela_dyn_section(layout);
this->plt_ = new Output_data_plt_s390<size>(layout, this->plt_ = new Output_data_plt_s390<size>(layout,
this->got_, this->got_plt_, this->got_irelative_); this->got_, this->got_plt_, this->got_irelative_,
this->got_dynamic_);
// Add unwind information if requested. // Add unwind information if requested.
if (parameters->options().ld_generated_unwind_info()) if (parameters->options().ld_generated_unwind_info())
@@ -1814,34 +1941,72 @@ Target_s390<size>::init_got_plt_for_update(Symbol_table* symtab,
{ {
gold_assert(this->got_ == NULL); gold_assert(this->got_ == NULL);
bool is_got_relro, is_got_plt_relro;
Output_section_order got_order, got_plt_order;
const char *got_plt_name;
if (parameters->options().relro())
{
// Partial GOT relro.
is_got_relro = true;
is_got_plt_relro = false;
got_order = ORDER_RELRO_LAST;
got_plt_order = ORDER_NON_RELRO_FIRST;
got_plt_name = ".got.plt";
}
else if (parameters->options().now())
{
// When using -z now, we can treat the whole .got as a relro section.
is_got_plt_relro = is_got_relro = true;
got_order = got_plt_order = ORDER_RELRO_LAST;
got_plt_name = ".got";
}
else
{
// Without -z now, it is modified after program startup by lazy
// PLT relocations.
is_got_plt_relro = is_got_relro = false;
got_order = got_plt_order = ORDER_DATA;
got_plt_name = ".got";
}
// Add the three reserved entries. // Add the three reserved entries.
this->got_plt_ = new Output_data_got_plt_s390<size>(layout, (plt_count + 3) * size / 8); this->got_plt_ = new Output_data_got_plt_s390<size>(layout, (plt_count + 3) * size / 8);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
| elfcpp::SHF_WRITE), this->got_plt_, got_plt_order,
this->got_plt_, ORDER_NON_RELRO_FIRST, is_got_plt_relro);
false);
// If there are any IRELATIVE relocations, they get GOT entries in // If there are any IRELATIVE relocations, they get GOT entries in
// .got.plt after the jump slot entries. // .got.plt after the jump slot entries.
this->got_irelative_ = new Output_data_space(0, size / 8, "** GOT IRELATIVE PLT"); this->got_irelative_ = new Output_data_space(0, size / 8, "** GOT IRELATIVE PLT");
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, layout->add_output_section_data(got_plt_name, elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
this->got_irelative_, this->got_irelative_,
ORDER_NON_RELRO_FIRST, false); got_plt_order, is_got_plt_relro);
if (parameters->options().relro())
{
// For partial relro, we need a _DYNAMIC pointer at
// _GLOBAL_OFFSET_TABLE_, not at DT_GOTPLT.
this->got_dynamic_ = new Output_data_got_dynamic_s390<size>(layout);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
this->got_dynamic_, got_order, true);
this->got_dynamic_->set_current_data_size(size / 8);
}
else
this->got_dynamic_ = this->got_plt_;
this->got_ = new Output_data_got<size, true>(got_count * size / 8); this->got_ = new Output_data_got<size, true>(got_count * size / 8);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
| elfcpp::SHF_WRITE), this->got_, got_order, is_got_relro);
this->got_, ORDER_RELRO_LAST,
true);
// Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
this->global_offset_table_ = this->global_offset_table_ =
symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
Symbol_table::PREDEFINED, Symbol_table::PREDEFINED,
this->got_plt_, this->got_dynamic_,
0, 0, elfcpp::STT_OBJECT, 0, 0, elfcpp::STT_OBJECT,
elfcpp::STB_LOCAL, elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0, elfcpp::STV_HIDDEN, 0,
@@ -1849,7 +2014,8 @@ Target_s390<size>::init_got_plt_for_update(Symbol_table* symtab,
// Create the PLT section. // Create the PLT section.
this->plt_ = new Output_data_plt_s390<size>(layout, this->plt_ = new Output_data_plt_s390<size>(layout,
this->got_, this->got_plt_, this->got_irelative_, plt_count); this->got_, this->got_plt_, this->got_irelative_,
this->got_dynamic_, plt_count);
// Add unwind information if requested. // Add unwind information if requested.
if (parameters->options().ld_generated_unwind_info()) if (parameters->options().ld_generated_unwind_info())
@@ -4051,6 +4217,10 @@ Target_s390<size>::do_finalize_sections(
if (sym != NULL) if (sym != NULL)
{ {
uint64_t data_size = this->got_->current_data_size(); uint64_t data_size = this->got_->current_data_size();
data_size += this->got_plt_->current_data_size();
data_size += this->got_irelative_->current_data_size();
if (this->got_plt_ != this->got_dynamic_)
data_size += this->got_dynamic_->current_data_size();
symtab->get_sized_symbol<size>(sym)->set_symsize(data_size); symtab->get_sized_symbol<size>(sym)->set_symsize(data_size);
} }

View File

@@ -11,8 +11,11 @@ NOP=0x07070707
TEMPLATE_NAME=elf32 TEMPLATE_NAME=elf32
GENERATE_SHLIB_SCRIPT=yes GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes GENERATE_PIE_SCRIPT=yes
GENERATE_RELRO_SCRIPT=yes
NO_SMALL_DATA=yes NO_SMALL_DATA=yes
IREL_IN_PLT= IREL_IN_PLT=
SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 24 ? 24 : 0"
test -z "$RELRO" && unset SEPARATE_GOTPLT
# Treat a host that matches the target with the possible exception of "x" # Treat a host that matches the target with the possible exception of "x"
# in the name as if it were native. # in the name as if it were native.

View File

@@ -10,5 +10,8 @@ NOP=0x07070707
TEMPLATE_NAME=elf32 TEMPLATE_NAME=elf32
GENERATE_SHLIB_SCRIPT=yes GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes GENERATE_PIE_SCRIPT=yes
GENERATE_RELRO_SCRIPT=yes
NO_SMALL_DATA=yes NO_SMALL_DATA=yes
IREL_IN_PLT= IREL_IN_PLT=
SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 12 ? 12 : 0"
test -z "$RELRO" && unset SEPARATE_GOTPLT

View File

@@ -2074,6 +2074,12 @@ echo ' && link_info.combreloc' >> e${EMULATION_NAME}.c
echo ' && link_info.relro' >> e${EMULATION_NAME}.c echo ' && link_info.relro' >> e${EMULATION_NAME}.c
echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xdw >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xdw >> e${EMULATION_NAME}.c
if test -n "$GENERATE_RELRO_SCRIPT" ; then
echo ' ; else if (bfd_link_pie (&link_info)' >> e${EMULATION_NAME}.c
echo ' && link_info.combreloc' >> e${EMULATION_NAME}.c
echo ' && link_info.relro) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xdo >> e${EMULATION_NAME}.c
fi
echo ' ; else if (bfd_link_pie (&link_info)' >> e${EMULATION_NAME}.c echo ' ; else if (bfd_link_pie (&link_info)' >> e${EMULATION_NAME}.c
echo ' && link_info.combreloc) return' >> e${EMULATION_NAME}.c echo ' && link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c
@@ -2087,6 +2093,12 @@ echo ' ; else if (bfd_link_dll (&link_info) && link_info.combreloc' >> e${EMULA
echo ' && link_info.relro' >> e${EMULATION_NAME}.c echo ' && link_info.relro' >> e${EMULATION_NAME}.c
echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xsw >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xsw >> e${EMULATION_NAME}.c
if test -n "$GENERATE_RELRO_SCRIPT" ; then
echo ' ; else if (bfd_link_dll (&link_info)' >> e${EMULATION_NAME}.c
echo ' && link_info.combreloc' >> e${EMULATION_NAME}.c
echo ' && link_info.relro) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xso >> e${EMULATION_NAME}.c
fi
echo ' ; else if (bfd_link_dll (&link_info) && link_info.combreloc) return' >> e${EMULATION_NAME}.c echo ' ; else if (bfd_link_dll (&link_info) && link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c
fi fi
@@ -2097,6 +2109,11 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
echo ' ; else if (link_info.combreloc && link_info.relro' >> e${EMULATION_NAME}.c echo ' ; else if (link_info.combreloc && link_info.relro' >> e${EMULATION_NAME}.c
echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xw >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xw >> e${EMULATION_NAME}.c
if test -n "$GENERATE_RELRO_SCRIPT" ; then
echo ' ; else if (link_info.combreloc' >> e${EMULATION_NAME}.c
echo ' && link_info.relro) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xo >> e${EMULATION_NAME}.c
fi
echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c
fi fi
@@ -2133,6 +2150,16 @@ fragment <<EOF
&& link_info.relro && link_info.relro
&& (link_info.flags & DF_BIND_NOW)) && (link_info.flags & DF_BIND_NOW))
return "ldscripts/${EMULATION_NAME}.xdw"; return "ldscripts/${EMULATION_NAME}.xdw";
EOF
if test -n "$GENERATE_RELRO_SCRIPT" ; then
fragment <<EOF
else if (bfd_link_pie (&link_info)
&& link_info.combreloc
&& link_info.relro)
return "ldscripts/${EMULATION_NAME}.xdo";
EOF
fi
fragment <<EOF
else if (bfd_link_pie (&link_info) else if (bfd_link_pie (&link_info)
&& link_info.combreloc) && link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xdc"; return "ldscripts/${EMULATION_NAME}.xdc";
@@ -2149,6 +2176,15 @@ fragment <<EOF
else if (bfd_link_dll (&link_info) && link_info.combreloc else if (bfd_link_dll (&link_info) && link_info.combreloc
&& link_info.relro && (link_info.flags & DF_BIND_NOW)) && link_info.relro && (link_info.flags & DF_BIND_NOW))
return "ldscripts/${EMULATION_NAME}.xsw"; return "ldscripts/${EMULATION_NAME}.xsw";
EOF
if test -n "$GENERATE_RELRO_SCRIPT" ; then
fragment <<EOF
else if (bfd_link_dll (&link_info) && link_info.combreloc
&& link_info.relro)
return "ldscripts/${EMULATION_NAME}.xso";
EOF
fi
fragment <<EOF
else if (bfd_link_dll (&link_info) && link_info.combreloc) else if (bfd_link_dll (&link_info) && link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xsc"; return "ldscripts/${EMULATION_NAME}.xsc";
EOF EOF
@@ -2163,6 +2199,14 @@ fragment <<EOF
else if (link_info.combreloc && link_info.relro else if (link_info.combreloc && link_info.relro
&& (link_info.flags & DF_BIND_NOW)) && (link_info.flags & DF_BIND_NOW))
return "ldscripts/${EMULATION_NAME}.xw"; return "ldscripts/${EMULATION_NAME}.xw";
EOF
if test -n "$GENERATE_RELRO_SCRIPT" ; then
fragment <<EOF
else if (link_info.combreloc && link_info.relro)
return "ldscripts/${EMULATION_NAME}.xo";
EOF
fi
fragment <<EOF
else if (link_info.combreloc) else if (link_info.combreloc)
return "ldscripts/${EMULATION_NAME}.xc"; return "ldscripts/${EMULATION_NAME}.xc";
EOF EOF

View File

@@ -321,6 +321,20 @@ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xc ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xc
rm -f ${COMBRELOC} rm -f ${COMBRELOC}
if test -n "$GENERATE_RELRO_SCRIPT"; then
LD_FLAG=o
RELRO=" "
COMBRELOC=ldscripts/${EMULATION_NAME}.xo.tmp
( echo "/* Script for -z combreloc -z relro: combine and sort reloc sections */"
. ${CUSTOMIZER_SCRIPT}
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xo
rm -f ${COMBRELOC}
COMBRELOC=
unset RELRO
fi
LD_FLAG=w LD_FLAG=w
RELRO_NOW=" " RELRO_NOW=" "
COMBRELOC=ldscripts/${EMULATION_NAME}.xw.tmp COMBRELOC=ldscripts/${EMULATION_NAME}.xw.tmp
@@ -351,6 +365,20 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xsc ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xsc
rm -f ${COMBRELOC} rm -f ${COMBRELOC}
if test -n "$GENERATE_RELRO_SCRIPT"; then
LD_FLAG=oshared
RELRO=" "
COMBRELOC=ldscripts/${EMULATION_NAME}.xso.tmp
( echo "/* Script for --shared -z combreloc -z relro: shared library, combine & sort relocs */"
. ${CUSTOMIZER_SCRIPT}
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xso
rm -f ${COMBRELOC}
COMBRELOC=
unset RELRO
fi
LD_FLAG=wshared LD_FLAG=wshared
RELRO_NOW=" " RELRO_NOW=" "
COMBRELOC=ldscripts/${EMULATION_NAME}.xsw.tmp COMBRELOC=ldscripts/${EMULATION_NAME}.xsw.tmp
@@ -383,6 +411,20 @@ if test -n "$GENERATE_PIE_SCRIPT"; then
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xdc ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xdc
rm -f ${COMBRELOC} rm -f ${COMBRELOC}
if test -n "$GENERATE_RELRO_SCRIPT"; then
LD_FLAG=opie
RELRO=" "
COMBRELOC=ldscripts/${EMULATION_NAME}.xdo.tmp
( echo "/* Script for -pie -z combreloc -z relro: position independent executable, combine & sort relocs */"
. ${CUSTOMIZER_SCRIPT}
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xdo
rm -f ${COMBRELOC}
COMBRELOC=
unset RELRO
fi
LD_FLAG=wpie LD_FLAG=wpie
RELRO_NOW=" " RELRO_NOW=" "
COMBRELOC=ldscripts/${EMULATION_NAME}.xdw.tmp COMBRELOC=ldscripts/${EMULATION_NAME}.xdw.tmp