* 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:
parent
da4d4077bc
commit
db6751f2e7
@ -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.
|
||||
|
@ -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 *,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
238
bfd/elflink.h
238
bfd/elflink.h
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
24
ld/ChangeLog
24
ld/ChangeLog
@ -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.
|
||||
|
6
ld/NEWS
6
ld/NEWS
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ("");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user