* elf-bfd.h (enum elf_reloc_type_class): New.

(struct elf_backend_data): Add elf_backend_reloc_type_class.
	(_bfd_elf_reloc_type_class): New.
	* elfxx-target.h (elf_backend_reloc_type_class): Define.
	(elfNN_bed): Add elf_backend_reloc_type_class.
	* elf.c (_bfd_elf_reloc_type_class): New.
	* elf32-i386.c (elf_i386_check_relocs): Set DF_TEXTREL if the reloc
	is against read-only section.
	(elf_i386_size_dynamic_sections): Use DF_TEXTREL flag instead of
	looking up section names for DT_TEXTREL.
	(elf_i386_reloc_type_class): New.
	(elf_backend_reloc_type_class): Define.
	* elf32-sparc.c (elf32_sparc_check_relocs): Set DF_TEXTREL if the
	reloc is against read-only section.
	(elf32_sparc_size_dynamic_sections): Use DF_TEXTREL flag instead of
	looking up section names for DT_TEXTREL.
	(elf32_sparc_reloc_type_class): New.
	(elf_backend_reloc_type_class): Define.
	* elf64-sparc.c (sparc64_elf_check_relocs): Set DF_TEXTREL if the
	reloc is against read-only section.
	(sparc64_elf_size_dynamic_sections): Use DF_TEXTREL flag instead of
	looking up section names for DT_TEXTREL.
	(sparc64_elf_reloc_type_class): New.
	(elf_backend_reloc_type_class): Define.
	* elfxx-ia64.c (struct elfNN_ia64_link_hash_table): Add reltext field.
	(elfNN_ia64_hash_table_create): Clear ia64_info.
	(get_reloc_section): Set DF_TEXTREL if the reloc is against read-only
	section.
	(elfNN_ia64_size_dynamic_sections): Use ia64_info->reltext flag
	instead of looking up section names for DT_TEXTREL.
	(elfNN_ia64_reloc_type_class): New.
	(elf_backend_reloc_type_class): Define.
	* elflink.h (size_dynamic_sections): Add spare DT_NULL tags.
	(struct elf_link_sort_rela): New.
	(elf_link_sort_cmp1, elf_link_sort_cmp2, elf_link_sort_relocs): New.
	(elf_bfd_final_link): Call elf_link_sort_relocs.
	Convert one spare DT_NULL into DT_RELCOUNT resp. DT_RELACOUNT if
	necessary.

	* bfdlink.h (struct bfd_link_info): Add combreloc and
	spare_dynamic_tags fields.

	* emultempl/elf32.em (place_orphan): Place orphan .rel* sections
	into .rel.dyn resp. .rela.dyn if combreloc.
	(get_script): If .x linker script is equal to .xn, only put it
	once into the binary.
	Add .xc and .xsc scripts.
	(parse_args): Handle -z combreloc and -z nocombreloc.
	* scripttempl/elf.sc (.rela.sbss): Fix a typo.
	For .xc and .xsc scripts put all .rel* or .rela* input sections
	but .rel*.plt and PLT-like sections into .rel.dyn resp. .rela.dyn.
	* genscripts.sh (GENERATE_COMBRELOC_SCRIPT): Set if SCRIPT_NAME
	is elf.
	Strip trailing whitespace from script.
	Generate .xc and .xsc scripts if requested.
	* ldmain.c (main): Initialize link_info.combreloc and
	link_info.spare_dynamic_tags.
	* lexsup.c (OPTION_SPARE_DYNAMIC_TAGS): Define.
	(ld_options): Add --spare-dynamic-tags option.
	(parse_args): Likewise.
	* ld.texinfo: Document -z combreloc and -z nocombreloc.
	* ldint.texinfo: Document .xc and .xsc linker scripts.
	* NEWS: Add notes about -z combreloc and SHF_MERGE.
This commit is contained in:
Jakub Jelinek 2001-08-23 15:14:18 +00:00
parent da4d4077bc
commit db6751f2e7
20 changed files with 571 additions and 98 deletions

View File

@ -1,3 +1,44 @@
2001-08-23 Jakub Jelinek <jakub@redhat.com>
* elf-bfd.h (enum elf_reloc_type_class): New.
(struct elf_backend_data): Add elf_backend_reloc_type_class.
(_bfd_elf_reloc_type_class): New.
* elfxx-target.h (elf_backend_reloc_type_class): Define.
(elfNN_bed): Add elf_backend_reloc_type_class.
* elf.c (_bfd_elf_reloc_type_class): New.
* elf32-i386.c (elf_i386_check_relocs): Set DF_TEXTREL if the reloc
is against read-only section.
(elf_i386_size_dynamic_sections): Use DF_TEXTREL flag instead of
looking up section names for DT_TEXTREL.
(elf_i386_reloc_type_class): New.
(elf_backend_reloc_type_class): Define.
* elf32-sparc.c (elf32_sparc_check_relocs): Set DF_TEXTREL if the
reloc is against read-only section.
(elf32_sparc_size_dynamic_sections): Use DF_TEXTREL flag instead of
looking up section names for DT_TEXTREL.
(elf32_sparc_reloc_type_class): New.
(elf_backend_reloc_type_class): Define.
* elf64-sparc.c (sparc64_elf_check_relocs): Set DF_TEXTREL if the
reloc is against read-only section.
(sparc64_elf_size_dynamic_sections): Use DF_TEXTREL flag instead of
looking up section names for DT_TEXTREL.
(sparc64_elf_reloc_type_class): New.
(elf_backend_reloc_type_class): Define.
* elfxx-ia64.c (struct elfNN_ia64_link_hash_table): Add reltext field.
(elfNN_ia64_hash_table_create): Clear ia64_info.
(get_reloc_section): Set DF_TEXTREL if the reloc is against read-only
section.
(elfNN_ia64_size_dynamic_sections): Use ia64_info->reltext flag
instead of looking up section names for DT_TEXTREL.
(elfNN_ia64_reloc_type_class): New.
(elf_backend_reloc_type_class): Define.
* elflink.h (size_dynamic_sections): Add spare DT_NULL tags.
(struct elf_link_sort_rela): New.
(elf_link_sort_cmp1, elf_link_sort_cmp2, elf_link_sort_relocs): New.
(elf_bfd_final_link): Call elf_link_sort_relocs.
Convert one spare DT_NULL into DT_RELCOUNT resp. DT_RELACOUNT if
necessary.
2001-08-23 Nick Clifton <nickc@cambridge.redhat.com>
* configure.in (x86-bsdi): No corefile support.

View File

@ -331,6 +331,13 @@ struct elf_size_info {
? (elf_symbol_type *) (S) \
: 0)
enum elf_reloc_type_class {
reloc_class_normal,
reloc_class_relative,
reloc_class_plt,
reloc_class_copy
};
struct elf_backend_data
{
/* The architecture for this backend. */
@ -636,10 +643,13 @@ struct elf_backend_data
note is found in a core file. */
boolean (*elf_backend_grok_psinfo) PARAMS ((bfd *, Elf_Internal_Note *));
/* Functions to print VMAs. Special code to handle 64 bit ELF files. */
/* Functions to print VMAs. Special code to handle 64 bit ELF files. */
void (* elf_backend_sprintf_vma) PARAMS ((bfd *, char *, bfd_vma));
void (* elf_backend_fprintf_vma) PARAMS ((bfd *, PTR, bfd_vma));
/* This function returns class of a reloc type. */
enum elf_reloc_type_class (* elf_backend_reloc_type_class) PARAMS ((int));
/* The swapping table to use when dealing with ECOFF information.
Used for the MIPS ELF .mdebug section. */
const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
@ -1008,6 +1018,8 @@ extern void bfd_elf_print_symbol PARAMS ((bfd *, PTR, asymbol *,
extern void _bfd_elf_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
extern void _bfd_elf_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
extern enum elf_reloc_type_class _bfd_elf_reloc_type_class PARAMS ((int));
extern unsigned long bfd_elf_hash PARAMS ((const char *));
extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *,

View File

@ -6053,3 +6053,10 @@ _bfd_elf_fprintf_vma (abfd, stream, value)
fprintf_vma ((FILE *) stream, value);
#endif
}
enum elf_reloc_type_class
_bfd_elf_reloc_type_class (type)
int type;
{
return reloc_class_normal;
}

View File

@ -63,6 +63,7 @@ static boolean elf_i386_finish_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf_i386_fake_sections
PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
static enum elf_reloc_type_class elf_i386_reloc_type_class PARAMS ((int));
#define USE_REL 1 /* 386 uses REL relocations instead of RELA */
@ -767,6 +768,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
return false;
}
if (sec->flags & SEC_READONLY)
info->flags |= DF_TEXTREL;
}
sreloc->_raw_size += sizeof (Elf32_External_Rel);
@ -1243,14 +1246,13 @@ allocate_plt_and_got_and_discard_relocs (h, inf)
static boolean
elf_i386_size_dynamic_sections (output_bfd, info)
bfd *output_bfd;
bfd *output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
struct elf_i386_link_hash_table *htab;
bfd *dynobj;
asection *s;
boolean relocs;
boolean reltext;
bfd *i;
htab = elf_i386_hash_table (info);
@ -1315,7 +1317,6 @@ elf_i386_size_dynamic_sections (output_bfd, info)
/* We now have determined the sizes of the various dynamic sections.
Allocate memory for them. */
relocs = false;
reltext = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LINKER_CREATED) == 0)
@ -1344,29 +1345,8 @@ elf_i386_size_dynamic_sections (output_bfd, info)
}
else
{
asection *target;
/* Remember whether there are any reloc sections other
than .rel.plt. */
if (s != htab->srelplt)
{
const char *outname;
relocs = true;
/* If this relocation section applies to a read only
section, then we probably need a DT_TEXTREL
entry. The entries in the .rel.plt section
really apply to the .got section, which we
created ourselves and so know is not readonly. */
outname = bfd_get_section_name (output_bfd,
s->output_section);
target = bfd_get_section_by_name (output_bfd, outname + 4);
if (target != NULL
&& (target->flags & SEC_READONLY) != 0
&& (target->flags & SEC_ALLOC) != 0)
reltext = true;
}
relocs = true;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
@ -1426,11 +1406,10 @@ elf_i386_size_dynamic_sections (output_bfd, info)
return false;
}
if (reltext)
if ((info->flags & DF_TEXTREL) != 0)
{
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
info->flags |= DF_TEXTREL;
}
}
@ -2215,6 +2194,22 @@ elf_i386_fake_sections (abfd, hdr, sec)
return true;
}
static enum elf_reloc_type_class
elf_i386_reloc_type_class (type)
int type;
{
switch (type)
{
case R_386_RELATIVE:
return reloc_class_relative;
case R_386_JUMP_SLOT:
return reloc_class_plt;
case R_386_COPY:
return reloc_class_copy;
default:
return reloc_class_normal;
}
}
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
#define TARGET_LITTLE_NAME "elf32-i386"
@ -2246,5 +2241,6 @@ elf_i386_fake_sections (abfd, hdr, sec)
#define elf_backend_relocate_section elf_i386_relocate_section
#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
#define elf_backend_fake_sections elf_i386_fake_sections
#define elf_backend_reloc_type_class elf_i386_reloc_type_class
#include "elf32-target.h"

View File

@ -52,6 +52,8 @@ static boolean elf32_sparc_object_p
PARAMS ((bfd *));
static void elf32_sparc_final_write_processing
PARAMS ((bfd *, boolean));
static enum elf_reloc_type_class elf32_sparc_reloc_type_class
PARAMS ((int));
/* The relocation "howto" table. */
@ -592,6 +594,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs)
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
return false;
}
if (sec->flags & SEC_READONLY)
info->flags |= DF_TEXTREL;
}
sreloc->_raw_size += sizeof (Elf32_External_Rela);
@ -909,12 +913,11 @@ elf32_sparc_adjust_dynamic_symbol (info, h)
static boolean
elf32_sparc_size_dynamic_sections (output_bfd, info)
bfd *output_bfd;
bfd *output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
bfd *dynobj;
asection *s;
boolean reltext;
boolean relplt;
dynobj = elf_hash_table (info)->dynobj;
@ -952,7 +955,6 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
reltext = false;
relplt = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
@ -985,19 +987,6 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
}
else
{
const char *outname;
asection *target;
/* If this relocation section applies to a read only
section, then we probably need a DT_TEXTREL entry. */
outname = bfd_get_section_name (output_bfd,
s->output_section);
target = bfd_get_section_by_name (output_bfd, outname + 5);
if (target != NULL
&& (target->flags & SEC_READONLY) != 0
&& (target->flags & SEC_ALLOC) != 0)
reltext = true;
if (strcmp (name, ".rela.plt") == 0)
relplt = true;
@ -1058,11 +1047,10 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
sizeof (Elf32_External_Rela)))
return false;
if (reltext)
if (info->flags & DF_TEXTREL)
{
if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
info->flags |= DF_TEXTREL;
}
}
@ -2081,6 +2069,23 @@ elf32_sparc_final_write_processing (abfd, linker)
break;
}
}
static enum elf_reloc_type_class
elf32_sparc_reloc_type_class (type)
int type;
{
switch (type)
{
case R_SPARC_RELATIVE:
return reloc_class_relative;
case R_SPARC_JMP_SLOT:
return reloc_class_plt;
case R_SPARC_COPY:
return reloc_class_copy;
default:
return reloc_class_normal;
}
}
#define TARGET_BIG_SYM bfd_elf32_sparc_vec
#define TARGET_BIG_NAME "elf32-sparc"
@ -2111,6 +2116,7 @@ elf32_sparc_final_write_processing (abfd, linker)
elf32_sparc_final_write_processing
#define elf_backend_gc_mark_hook elf32_sparc_gc_mark_hook
#define elf_backend_gc_sweep_hook elf32_sparc_gc_sweep_hook
#define elf_backend_reloc_type_class elf32_sparc_reloc_type_class
#define elf_backend_can_gc_sections 1
#define elf_backend_want_got_plt 0

View File

@ -96,6 +96,7 @@ static boolean sparc64_elf_slurp_reloc_table
static long sparc64_elf_canonicalize_dynamic_reloc
PARAMS ((bfd *, arelent **, asymbol **));
static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR));
static enum elf_reloc_type_class sparc64_elf_reloc_type_class PARAMS ((int));
/* The relocation "howto" table. */
@ -1248,6 +1249,8 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
|| ! bfd_set_section_alignment (dynobj, sreloc, 3))
return false;
}
if (sec->flags & SEC_READONLY)
info->flags |= DF_TEXTREL;
}
sreloc->_raw_size += sizeof (Elf64_External_Rela);
@ -1666,7 +1669,6 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
{
bfd *dynobj;
asection *s;
boolean reltext;
boolean relplt;
dynobj = elf_hash_table (info)->dynobj;
@ -1698,7 +1700,6 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
reltext = false;
relplt = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
@ -1731,18 +1732,6 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
}
else
{
const char *outname;
asection *target;
/* If this relocation section applies to a read only
section, then we probably need a DT_TEXTREL entry. */
outname = bfd_get_section_name (output_bfd,
s->output_section);
target = bfd_get_section_by_name (output_bfd, outname + 5);
if (target != NULL
&& (target->flags & SEC_READONLY) != 0)
reltext = true;
if (strcmp (name, ".rela.plt") == 0)
relplt = true;
@ -1805,11 +1794,10 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
sizeof (Elf64_External_Rela)))
return false;
if (reltext)
if (info->flags & DF_TEXTREL)
{
if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
info->flags |= DF_TEXTREL;
}
/* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER
@ -2909,6 +2897,23 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
return true;
}
static enum elf_reloc_type_class
sparc64_elf_reloc_type_class (type)
int type;
{
switch (type)
{
case R_SPARC_RELATIVE:
return reloc_class_relative;
case R_SPARC_JMP_SLOT:
return reloc_class_plt;
case R_SPARC_COPY:
return reloc_class_copy;
default:
return reloc_class_normal;
}
}
/* Functions for dealing with the e_flags field. */
@ -3160,6 +3165,8 @@ const struct elf_size_info sparc64_elf_size_info =
sparc64_elf_size_info
#define elf_backend_object_p \
sparc64_elf_object_p
#define elf_backend_reloc_type_class \
sparc64_elf_reloc_type_class
#define elf_backend_want_got_plt 0
#define elf_backend_plt_readonly 0

View File

@ -67,6 +67,12 @@ static boolean elf_link_size_reloc_section
static void elf_link_adjust_relocs
PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned int,
struct elf_link_hash_entry **));
static int elf_link_sort_cmp1
PARAMS ((const void *, const void *));
static int elf_link_sort_cmp2
PARAMS ((const void *, const void *));
static size_t elf_link_sort_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection **));
/* Given an ELF BFD, add symbols to the global hash table as
appropriate. */
@ -3065,6 +3071,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
asection *s;
size_t bucketcount = 0;
size_t hash_entry_size;
unsigned int dtagcount;
/* Set up the version definition section. */
s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
@ -3439,8 +3446,9 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
BFD_ASSERT (s != NULL);
s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
if (! elf_add_dynamic_entry (info, DT_NULL, 0))
return false;
for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount)
if (! elf_add_dynamic_entry (info, DT_NULL, 0))
return false;
}
return true;
@ -4270,6 +4278,210 @@ elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash)
free (irela);
}
struct elf_link_sort_rela {
bfd_vma offset;
enum elf_reloc_type_class type;
union {
Elf_Internal_Rel rel;
Elf_Internal_Rela rela;
} u;
};
static int
elf_link_sort_cmp1 (A, B)
const PTR A;
const PTR B;
{
struct elf_link_sort_rela *a = (struct elf_link_sort_rela *)A;
struct elf_link_sort_rela *b = (struct elf_link_sort_rela *)B;
int relativea, relativeb;
relativea = a->type == reloc_class_relative;
relativeb = b->type == reloc_class_relative;
if (relativea < relativeb)
return -1;
if (relativea > relativeb)
return 1;
if (ELF_R_SYM (a->u.rel.r_info) < ELF_R_SYM (b->u.rel.r_info))
return -1;
if (ELF_R_SYM (a->u.rel.r_info) > ELF_R_SYM (b->u.rel.r_info))
return 1;
if (a->u.rel.r_offset < b->u.rel.r_offset)
return -1;
if (a->u.rel.r_offset > b->u.rel.r_offset)
return 1;
return 0;
}
static int
elf_link_sort_cmp2 (A, B)
const PTR A;
const PTR B;
{
struct elf_link_sort_rela *a = (struct elf_link_sort_rela *)A;
struct elf_link_sort_rela *b = (struct elf_link_sort_rela *)B;
int copya, copyb;
if (a->offset < b->offset)
return -1;
if (a->offset > b->offset)
return 1;
copya = a->type == reloc_class_copy;
copyb = b->type == reloc_class_copy;
if (copya < copyb)
return -1;
if (copya > copyb)
return 1;
if (a->u.rel.r_offset < b->u.rel.r_offset)
return -1;
if (a->u.rel.r_offset > b->u.rel.r_offset)
return 1;
return 0;
}
static size_t
elf_link_sort_relocs (abfd, info, psec)
bfd *abfd;
struct bfd_link_info *info;
asection **psec;
{
bfd *dynobj = elf_hash_table (info)->dynobj;
asection *reldyn, *o;
boolean rel = false;
size_t count, size, i, j, ret;
struct elf_link_sort_rela *rela;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
if (reldyn == NULL || reldyn->_raw_size == 0)
{
reldyn = bfd_get_section_by_name (abfd, ".rel.dyn");
if (reldyn == NULL || reldyn->_raw_size == 0)
return 0;
rel = true;
count = reldyn->_raw_size / sizeof (Elf_External_Rel);
}
else
count = reldyn->_raw_size / sizeof (Elf_External_Rela);
size = 0;
for (o = dynobj->sections; o != NULL; o = o->next)
if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
&& o->output_section == reldyn)
size += o->_raw_size;
if (size != reldyn->_raw_size)
return 0;
rela = (struct elf_link_sort_rela *) calloc (sizeof (*rela), count);
if (rela == NULL)
{
(*info->callbacks->warning)
(info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
return 0;
}
for (o = dynobj->sections; o != NULL; o = o->next)
if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
&& o->output_section == reldyn)
{
if (rel)
{
Elf_External_Rel *erel, *erelend;
struct elf_link_sort_rela *s;
erel = (Elf_External_Rel *) o->contents;
erelend = (Elf_External_Rel *) ((PTR) o->contents + o->_raw_size);
s = rela + o->output_offset / sizeof (Elf_External_Rel);
for (; erel < erelend; erel++, s++)
{
if (bed->s->swap_reloc_in)
(*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &s->u.rel);
else
elf_swap_reloc_in (abfd, erel, &s->u.rel);
s->type = (*bed->elf_backend_reloc_type_class)
(ELF_R_TYPE (s->u.rel.r_info));
}
}
else
{
Elf_External_Rela *erela, *erelaend;
struct elf_link_sort_rela *s;
erela = (Elf_External_Rela *) o->contents;
erelaend = (Elf_External_Rela *) ((PTR) o->contents + o->_raw_size);
s = rela + o->output_offset / sizeof (Elf_External_Rela);
for (; erela < erelaend; erela++, s++)
{
if (bed->s->swap_reloca_in)
(*bed->s->swap_reloca_in) (dynobj, (bfd_byte *) erela, &s->u.rela);
else
elf_swap_reloca_in (dynobj, erela, &s->u.rela);
s->type = (*bed->elf_backend_reloc_type_class)
(ELF_R_TYPE (s->u.rel.r_info));
}
}
}
qsort (rela, count, sizeof (*rela), elf_link_sort_cmp1);
for (i = 0, j = 0; i < count && rela[i].type != reloc_class_relative; i++)
{
if (ELF_R_SYM (rela[i].u.rel.r_info) != ELF_R_SYM (rela[j].u.rel.r_info))
j = i;
rela[i].offset = rela[j].u.rel.r_offset;
}
ret = count - i;
qsort (rela, i, sizeof (*rela), elf_link_sort_cmp2);
for (o = dynobj->sections; o != NULL; o = o->next)
if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
== (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
&& o->output_section == reldyn)
{
if (rel)
{
Elf_External_Rel *erel, *erelend;
struct elf_link_sort_rela *s;
erel = (Elf_External_Rel *) o->contents;
erelend = (Elf_External_Rel *) ((PTR) o->contents + o->_raw_size);
s = rela + o->output_offset / sizeof (Elf_External_Rel);
for (; erel < erelend; erel++, s++)
{
if (bed->s->swap_reloc_out)
(*bed->s->swap_reloc_out) (abfd, &s->u.rel, (bfd_byte *) erel);
else
elf_swap_reloc_out (abfd, &s->u.rel, erel);
}
}
else
{
Elf_External_Rela *erela, *erelaend;
struct elf_link_sort_rela *s;
erela = (Elf_External_Rela *) o->contents;
erelaend = (Elf_External_Rela *) ((PTR) o->contents + o->_raw_size);
s = rela + o->output_offset / sizeof (Elf_External_Rela);
for (; erela < erelaend; erela++, s++)
{
if (bed->s->swap_reloca_out)
(*bed->s->swap_reloca_out) (dynobj, &s->u.rela, (bfd_byte *) erela);
else
elf_swap_reloca_out (dynobj, &s->u.rela, erela);
}
}
}
free (rela);
*psec = reldyn;
return ret;
}
/* Do the final step of an ELF link. */
boolean
@ -4296,6 +4508,8 @@ elf_bfd_final_link (abfd, info)
struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_outext_info eoinfo;
boolean merged;
size_t relativecount = 0;
asection *reldyn = 0;
if (info->shared)
abfd->flags |= DYNAMIC;
@ -4866,6 +5080,9 @@ elf_bfd_final_link (abfd, info)
o->reloc_count = 0;
}
if (dynamic && info->combreloc && dynobj != NULL)
relativecount = elf_link_sort_relocs (abfd, info, &reldyn);
/* If we are linking against a dynamic object, or generating a
shared library, finish up the dynamic linking information. */
if (dynamic)
@ -4890,6 +5107,23 @@ elf_bfd_final_link (abfd, info)
{
default:
break;
case DT_NULL:
if (relativecount > 0 && dyncon + 1 < dynconend)
{
switch (elf_section_data (reldyn)->this_hdr.sh_type)
{
case SHT_REL: dyn.d_tag = DT_RELCOUNT; break;
case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break;
default: break;
}
if (dyn.d_tag != DT_NULL)
{
dyn.d_un.d_val = relativecount;
elf_swap_dyn_out (dynobj, &dyn, dyncon);
relativecount = 0;
}
}
break;
case DT_INIT:
name = info->init_function;
goto get_sym;

View File

@ -138,6 +138,7 @@ struct elfNN_ia64_link_hash_table
asection *rel_pltoff_sec; /* dynamic relocation section for same */
bfd_size_type minplt_entries; /* number of minplt entries */
unsigned reltext : 1; /* are there relocs against readonly sections? */
struct elfNN_ia64_local_hash_table loc_hash_table;
};
@ -299,6 +300,8 @@ static boolean elfNN_ia64_merge_private_bfd_data
PARAMS ((bfd *ibfd, bfd *obfd));
static boolean elfNN_ia64_print_private_bfd_data
PARAMS ((bfd *abfd, PTR ptr));
static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
PARAMS ((int));
/* ia64-specific relocation */
@ -1571,7 +1574,7 @@ elfNN_ia64_hash_table_create (abfd)
{
struct elfNN_ia64_link_hash_table *ret;
ret = bfd_alloc (abfd, sizeof (*ret));
ret = bfd_zalloc (abfd, sizeof (*ret));
if (!ret)
return 0;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
@ -1916,6 +1919,9 @@ get_reloc_section (abfd, ia64_info, sec, create)
return NULL;
}
if (sec->flags & SEC_READONLY)
ia64_info->reltext = 1;
return srel;
}
@ -2535,7 +2541,6 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
struct elfNN_ia64_link_hash_table *ia64_info;
asection *sec;
bfd *dynobj;
boolean reltext = false;
boolean relplt = false;
dynobj = elf_hash_table(info)->dynobj;
@ -2692,24 +2697,6 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
{
if (!strip)
{
const char *outname;
asection *target;
/* If this relocation section applies to a read only
section, then we probably need a DT_TEXTREL entry. */
outname = bfd_get_section_name (output_bfd,
sec->output_section);
if (outname[4] == 'a')
outname += 5;
else
outname += 4;
target = bfd_get_section_by_name (output_bfd, outname);
if (target != NULL
&& (target->flags & SEC_READONLY) != 0
&& (target->flags & SEC_ALLOC) != 0)
reltext = true;
/* We use the reloc_count field as a counter if we need to
copy relocs into the output file. */
sec->reloc_count = 0;
@ -2763,7 +2750,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
sizeof (ElfNN_External_Rela)))
return false;
if (reltext)
if (ia64_info->reltext)
{
if (! bfd_elfNN_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
@ -4324,6 +4311,27 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr)
_bfd_elf_print_private_bfd_data (abfd, ptr);
return true;
}
static enum elf_reloc_type_class
elfNN_ia64_reloc_type_class (type)
int type;
{
switch (type)
{
case R_IA64_REL32MSB:
case R_IA64_REL32LSB:
case R_IA64_REL64MSB:
case R_IA64_REL64LSB:
return reloc_class_relative;
case R_IA64_IPLTMSB:
case R_IA64_IPLTLSB:
return reloc_class_plt;
case R_IA64_COPY:
return reloc_class_copy;
default:
return reloc_class_normal;
}
}
#define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
#define TARGET_LITTLE_NAME "elfNN-ia64-little"
@ -4400,6 +4408,7 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr)
#define elf_backend_want_dynbss 0
#define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect
#define elf_backend_hide_symbol elfNN_ia64_hash_hide_symbol
#define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class
#include "elfNN-target.h"

View File

@ -339,6 +339,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef elf_backend_fprintf_vma
#define elf_backend_fprintf_vma _bfd_elf_fprintf_vma
#endif
#ifndef elf_backend_reloc_type_class
#define elf_backend_reloc_type_class _bfd_elf_reloc_type_class
#endif
/* Previously, backends could only use SHT_REL or SHT_RELA relocation
sections, but not both. They defined USE_REL to indicate SHT_REL
@ -426,6 +429,7 @@ static CONST struct elf_backend_data elfNN_bed =
elf_backend_grok_psinfo,
elf_backend_sprintf_vma,
elf_backend_fprintf_vma,
elf_backend_reloc_type_class,
elf_backend_ecoff_debug_swap,
ELF_MACHINE_ALT1,
ELF_MACHINE_ALT2,

View File

@ -1,3 +1,8 @@
2001-08-23 Jakub Jelinek <jakub@redhat.com>
* bfdlink.h (struct bfd_link_info): Add combreloc and
spare_dynamic_tags fields.
2001-08-23 Lars Brinkhoff <lars@nocrew.org>
* dyn-string.h, fibheap.h, partition.h, sort.h, splay-tree.h:

View File

@ -275,9 +275,16 @@ struct bfd_link_info
/* May be used to set DT_FLAGS_1 for ELF. */
bfd_vma flags_1;
/* true if auto-import thunks for DATA items in pei386 DLLs
/* True if auto-import thunks for DATA items in pei386 DLLs
should be generated/linked against. */
boolean pei386_auto_import;
/* True if non-PLT relocs should be merged into one reloc section
and sorted so that relocs against the same symbol come together. */
boolean combreloc;
/* How many spare .dynamic DT_NULL entries should be added? */
int spare_dynamic_tags;
};
/* This structures holds a set of callback functions. These are

View File

@ -1,3 +1,27 @@
2001-08-23 Jakub Jelinek <jakub@redhat.com>
* emultempl/elf32.em (place_orphan): Place orphan .rel* sections
into .rel.dyn resp. .rela.dyn if combreloc.
(get_script): If .x linker script is equal to .xn, only put it
once into the binary.
Add .xc and .xsc scripts.
(parse_args): Handle -z combreloc and -z nocombreloc.
* scripttempl/elf.sc (.rela.sbss): Fix a typo.
For .xc and .xsc scripts put all .rel* or .rela* input sections
but .rel*.plt and PLT-like sections into .rel.dyn resp. .rela.dyn.
* genscripts.sh (GENERATE_COMBRELOC_SCRIPT): Set if SCRIPT_NAME
is elf.
Strip trailing whitespace from script.
Generate .xc and .xsc scripts if requested.
* ldmain.c (main): Initialize link_info.combreloc and
link_info.spare_dynamic_tags.
* lexsup.c (OPTION_SPARE_DYNAMIC_TAGS): Define.
(ld_options): Add --spare-dynamic-tags option.
(parse_args): Likewise.
* ld.texinfo: Document -z combreloc and -z nocombreloc.
* ldint.texinfo: Document .xc and .xsc linker scripts.
* NEWS: Add notes about -z combreloc and SHF_MERGE.
2001-08-22 H.J. Lu <hjl@gnu.org>
* emulparams/elf32fr30.sh: Add a newline.

View File

@ -1,5 +1,11 @@
-*- text -*-
* Support for -z combreloc in the ELF linker, which puts dynamic
relocations against the same symbol together, so that dynamic linker
can use an one-entry symbol lookup cache.
* Support for ELF SHF_MERGE section merging, by Jakub Jelinek.
* Support for AMD x86-64 architecture, by Jan Hubicka, SuSE Labs.
* Support added for eliminating duplicate DWARF2 debug information by

View File

@ -1135,7 +1135,25 @@ gld${EMULATION_NAME}_place_orphan (file, s)
else if (strncmp (secname, ".rel", 4) == 0
&& (hold_rel.os != NULL
|| (hold_rel.os = output_rel_find ()) != NULL))
place = &hold_rel;
{
if (! link_info.relocateable && link_info.combreloc)
{
if (strncmp (secname, ".rela", 5) == 0)
os = lang_output_section_find (".rela.dyn");
else
os = lang_output_section_find (".rel.dyn");
if (os != NULL
&& os->bfd_section != NULL
&& ((s->flags ^ os->bfd_section->flags)
& (SEC_LOAD | SEC_ALLOC)) == 0)
{
lang_add_section (&os->children, s, os, file);
return true;
}
}
place = &hold_rel;
}
else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY
&& HAVE_SECTION (hold_rodata, ".rodata"))
place = &hold_rodata;
@ -1332,14 +1350,18 @@ echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}
sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
if ! cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then
echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
fi
if test -n "$GENERATE_SHLIB_SCRIPT" ; then
echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c
echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
fi
echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c
echo ' ; else return' >> e${EMULATION_NAME}.c
sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
echo '; }' >> e${EMULATION_NAME}.c
@ -1492,6 +1514,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
}
else if (strcmp (optarg, "defs") == 0)
link_info.no_undefined = true;
else if (strcmp (optarg, "combreloc") == 0)
link_info.combreloc = true;
else if (strcmp (optarg, "nocombreloc") == 0)
link_info.combreloc = false;
/* What about the other Solaris -z options? FIXME. */
break;
EOF

View File

@ -84,6 +84,17 @@ LIB_SEARCH_DIRS=`echo ${LIB_PATH} | tr ':' ' ' | sed -e 's/\([^ ][^ ]*\)/SEARCH_
# A .xs script is for generating a shared library with the --shared
# flag; it is only generated if $GENERATE_SHLIB_SCRIPT is set by the
# emulation parameters.
# A .xc script is for linking with -z combreloc; it is only generated if
# $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or
# $SCRIPT_NAME is "elf".
# A .xsc script is for linking with --shared -z combreloc; it is generated
# if $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or
# $SCRIPT_NAME is "elf" and $GENERATE_SHLIB_SCRIPT is set by the emulation
# parameters too.
if [ "x$SCRIPT_NAME" = "xelf" ]; then
GENERATE_COMBRELOC_SCRIPT=yes
fi
SEGMENT_SIZE=${SEGMENT_SIZE-${TARGET_PAGE_SIZE}}
@ -101,34 +112,45 @@ DATA_ALIGNMENT=${DATA_ALIGNMENT_r}
DEFAULT_DATA_ALIGNMENT="ALIGN(${SEGMENT_SIZE})"
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xr
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xr
LD_FLAG=u
DATA_ALIGNMENT=${DATA_ALIGNMENT_u}
CONSTRUCTING=" "
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xu
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xu
LD_FLAG=
DATA_ALIGNMENT=${DATA_ALIGNMENT_}
RELOCATING=" "
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.x
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.x
LD_FLAG=n
DATA_ALIGNMENT=${DATA_ALIGNMENT_n}
TEXT_START_ADDR=${NONPAGED_TEXT_START_ADDR-${TEXT_START_ADDR}}
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xn
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xn
LD_FLAG=N
DATA_ALIGNMENT=${DATA_ALIGNMENT_N}
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xbn
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xbn
if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
DATA_ALIGNMENT=${DATA_ALIGNMENT_c-${DATA_ALIGNMENT_}}
LD_FLAG=c
COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xc
rm -f ${COMBRELOC}
COMBRELOC=
fi
if test -n "$GENERATE_SHLIB_SCRIPT"; then
LD_FLAG=shared
@ -137,7 +159,17 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then
# Note that TEXT_START_ADDR is set to NONPAGED_TEXT_START_ADDR.
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xs
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xs
if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
LD_FLAG=cshared
DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp
( . ${srcdir}/emulparams/${EMULATION_NAME}.sh
. ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xsc
rm -f ${COMBRELOC}
COMBRELOC=
fi
fi
for i in $EMULATION_LIBPATH ; do

View File

@ -840,7 +840,8 @@ for Solaris compatibility.
@item -z @var{keyword}
The recognized keywords are @code{initfirst}, @code{interpose},
@code{loadfltr}, @code{nodefaultlib}, @code{nodelete}, @code{nodlopen},
@code{nodump}, @code{now} and @code{origin}. The other keywords are
@code{nodump}, @code{now}, @code{origin}, @code{combreloc} and
@code{nocombreloc}. The other keywords are
ignored for Solaris compatibility. @code{initfirst} marks the object
to be initialized first at runtime before any other objects.
@code{interpose} marks the object that its symbol table interposes
@ -854,6 +855,9 @@ of this object will ignore any default library search paths.
@code{now} marks the object with the non-lazy runtime binding.
@code{origin} marks the object may contain $ORIGIN.
@code{defs} disallows undefined symbols.
@code{combreloc} combines multiple reloc sections and sorts them
to make dynamic symbol lookup caching possible.
@code{nocombreloc} disables multiple reloc sections combining.
@kindex -(
@cindex groups of archives

View File

@ -239,7 +239,7 @@ If @code{SCRIPT_NAME} is set to @var{script}, @code{genscripts.sh} will
invoke @file{scripttempl/@var{script}.sc}.
The @file{genscripts.sh} script will invoke the @file{scripttempl}
script 5 or 6 times. Each time it will set the shell variable
script 5 to 8 times. Each time it will set the shell variable
@code{LD_FLAG} to a different value. When the linker is run, the
options used will direct it to select a particular script. (Script
selection is controlled by the @code{get_script} emulation entry point;
@ -278,6 +278,22 @@ this value if @code{GENERATE_SHLIB_SCRIPT} is defined in the
this script at the appropriate time, normally when the linker is invoked
with the @code{-shared} option. The output has an extension of
@file{.xs}.
@item c
The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to
this value if @code{GENERATE_COMBRELOC_SCRIPT} is defined in the
@file{emulparams} file or if @code{SCRIPT_NAME} is @code{elf}. The
@file{emultempl} script must arrange to use this script at the appropriate
time, normally when the linker is invoked with the @code{-z combreloc}
option. The output has an extension of
@file{.xc}.
@item cshared
The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to
this value if @code{GENERATE_COMBRELOC_SCRIPT} is defined in the
@file{emulparams} file or if @code{SCRIPT_NAME} is @code{elf} and
@code{GENERATE_SHLIB_SCRIPT} is defined in the @file{emulparms} file.
The @file{emultempl} script must arrange to use this script at the
appropriate time, normally when the linker is invoked with the @code{-shared
-z combreloc} option. The output has an extension of @file{.xsc}.
@end table
Besides the shell variables set by the @file{emulparams} script, and the
@ -301,6 +317,10 @@ page aligned, or to @samp{.} when generating the @code{-N} script.
@item CREATE_SHLIB
This will be set to a non-empty string when generating a @code{-shared}
script.
@item COMBRELOC
This will be set to a non-empty string when generating @code{-z combreloc}
scripts to a temporary file name which can be used during script generation.
@end table
The conventional way to write a @file{scripttempl} script is to first

View File

@ -244,6 +244,8 @@ main (argc, argv)
link_info.flags = (bfd_vma) 0;
link_info.flags_1 = (bfd_vma) 0;
link_info.pei386_auto_import = false;
link_info.combreloc = false;
link_info.spare_dynamic_tags = 5;
ldfile_add_arch ("");

View File

@ -131,6 +131,7 @@ int parsing_defsym = 0;
#define OPTION_TARGET_HELP (OPTION_UNIQUE + 1)
#define OPTION_ALLOW_SHLIB_UNDEFINED (OPTION_TARGET_HELP + 1)
#define OPTION_DISCARD_NONE (OPTION_ALLOW_SHLIB_UNDEFINED + 1)
#define OPTION_SPARE_DYNAMIC_TAGS (OPTION_DISCARD_NONE + 1)
/* The long options. This structure is used for both the option
parsing and the help text. */
@ -347,6 +348,8 @@ static const struct ld_option ld_options[] =
'\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
{ {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
'\0', NULL, NULL, NO_HELP },
{ {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
'\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"), TWO_DASHES },
{ {"split-by-file", optional_argument, NULL, OPTION_SPLIT_BY_FILE},
'\0', N_("[=SIZE]"), N_("Split output sections every SIZE octets"), TWO_DASHES },
{ {"split-by-reloc", optional_argument, NULL, OPTION_SPLIT_BY_RELOC},
@ -1073,6 +1076,9 @@ the GNU General Public License. This program has absolutely no warranty.\n"));
case 'y':
add_ysym (optarg);
break;
case OPTION_SPARE_DYNAMIC_TAGS:
link_info.spare_dynamic_tags = strtoul (optarg, NULL, 0);
break;
case OPTION_SPLIT_BY_RELOC:
if (optarg != NULL)
config.split_by_reloc = strtoul (optarg, NULL, 0);

View File

@ -145,6 +145,13 @@ SECTIONS
.gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
.gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
EOF
if [ "x$COMBRELOC" = x ]; then
COMBRELOCCAT=cat
else
COMBRELOCCAT="cat > $COMBRELOC"
fi
eval $COMBRELOCCAT <<EOF
.rel.init ${RELOCATING-0} : { *(.rel.init) }
.rela.init ${RELOCATING-0} : { *(.rela.init) }
.rel.text ${RELOCATING-0} :
@ -215,7 +222,7 @@ SECTIONS
{
*(.rela.sbss)
${RELOCATING+*(.rela.sbss.*)}
${RELOCATING+*(.rel.gnu.linkonce.sb.*)}
${RELOCATING+*(.rela.gnu.linkonce.sb.*)}
}
.rel.sdata2 ${RELOCATING-0} :
{
@ -253,6 +260,24 @@ SECTIONS
${RELOCATING+*(.rela.bss.*)}
${RELOCATING+*(.rela.gnu.linkonce.b.*)}
}
EOF
if [ -n "$COMBRELOC" ]; then
cat <<EOF
.rel.dyn :
{
EOF
sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rela\./d;s/^.*: { *\(.*\)}$/ \1/' $COMBRELOC
cat <<EOF
}
.rela.dyn :
{
EOF
sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rel\./d;s/^.*: { *\(.*\)}/ \1/' $COMBRELOC
cat <<EOF
}
EOF
fi
cat <<EOF
.rel.plt ${RELOCATING-0} : { *(.rel.plt) }
.rela.plt ${RELOCATING-0} : { *(.rela.plt) }
${OTHER_PLT_RELOC_SECTIONS}