* elf-bfd.h (_bfd_elf_create_linker_section) Don't declare.

(_bfd_elf_find_pointer_linker_section): Likewise.
	(bfd_elf32_create_pointer_linker_section): Likewise.
	(bfd_elf32_finish_pointer_linker_section): Likewise.
	(bfd_elf64_create_pointer_linker_section): Likewise.
	(bfd_elf64_finish_pointer_linker_section): Likewise.
	(_bfd_elf_make_linker_section_rela): Likewise.
	* elfcode.h (elf_create_pointer_linker_section): Don't define.
	(elf_finish_pointer_linker_section): Likewise.
	* elflink.c (_bfd_elf_make_linker_section_rela): Delete.
	(_bfd_elf_create_linker_section): Move this function..
	(_bfd_elf_find_pointer_linker_section): ..and this..
	* elflink.h (elf_create_pointer_linker_section): ..and this..
	(elf_finish_pointer_linker_section): ..and this..
	* elf32-ppc.c: ..to here, renaming to the following, and adjusting
	calls.
	(elf_create_linker_section): Convert to C90, tidy.
	(elf_find_pointer_linker_section): Likewise.
	(elf_create_pointer_linker_section): Likewise.
	(elf_finish_pointer_linker_section): Likewise.
	* elf32-i370.c: Delete #if 0 code.
This commit is contained in:
Alan Modra 2003-07-04 01:50:12 +00:00
parent 100f2e98f8
commit 3dab13f62b
7 changed files with 397 additions and 564 deletions

View File

@ -1,3 +1,27 @@
2003-07-03 Alan Modra <amodra@bigpond.net.au>
* elf-bfd.h (_bfd_elf_create_linker_section) Don't declare.
(_bfd_elf_find_pointer_linker_section): Likewise.
(bfd_elf32_create_pointer_linker_section): Likewise.
(bfd_elf32_finish_pointer_linker_section): Likewise.
(bfd_elf64_create_pointer_linker_section): Likewise.
(bfd_elf64_finish_pointer_linker_section): Likewise.
(_bfd_elf_make_linker_section_rela): Likewise.
* elfcode.h (elf_create_pointer_linker_section): Don't define.
(elf_finish_pointer_linker_section): Likewise.
* elflink.c (_bfd_elf_make_linker_section_rela): Delete.
(_bfd_elf_create_linker_section): Move this function..
(_bfd_elf_find_pointer_linker_section): ..and this..
* elflink.h (elf_create_pointer_linker_section): ..and this..
(elf_finish_pointer_linker_section): ..and this..
* elf32-ppc.c: ..to here, renaming to the following, and adjusting
calls.
(elf_create_linker_section): Convert to C90, tidy.
(elf_find_pointer_linker_section): Likewise.
(elf_create_pointer_linker_section): Likewise.
(elf_finish_pointer_linker_section): Likewise.
* elf32-i370.c: Delete #if 0 code.
2003-07-02 Alan Modra <amodra@bigpond.net.au>
* elf64-ppc.c (ppc64_elf_func_desc_adjust): Don't allow _savef* and
@ -3565,8 +3589,8 @@
(aout_link_write_symbols): Cast enums in comparisons, int values to
boolean, enums in assignments to int.
(aout_link_input_section_std): Cast rel->r_index to unsigned int.
(aout_link_input_section_ext): Likewise. Cast enums used in comparisons
with unsigned ints.
(aout_link_input_section_ext): Likewise. Cast enums used in
comparisons with unsigned ints.
(aout_link_reloc_link_order): Cast enum to int in assignment.
* archive.c (_bfd_generic_read_ar_hdr_mag): Cast result of memchr
calls to char *.
@ -3597,8 +3621,8 @@
(merge_strings): Add casts to const unsigned char *.
* reloc.c (bfd_get_reloc_code_name): Cast enums in comparison to int.
(bfd_generic_get_relocated_section_content): Cast enum to unsigned int.
* section.c (bfd_section_hash_newfunc): Cast bfd_hash_allocate result to
struct bfd_hash_entry *.
* section.c (bfd_section_hash_newfunc): Cast bfd_hash_allocate result
to struct bfd_hash_entry *.
(bfd_set_section_content): Add cast to PTR in comparison.
* simple.c (simple_dummy_warning, simple_dummy_undefined_symbol,
simple_dummy_reloc_overflow, simple_dummy_reloc_dangerous,

View File

@ -1554,35 +1554,6 @@ extern bfd_boolean _bfd_elfcore_make_pseudosection
extern char *_bfd_elfcore_strndup
PARAMS ((bfd *, char *, size_t));
extern elf_linker_section_t *_bfd_elf_create_linker_section
PARAMS ((bfd *, struct bfd_link_info *, enum elf_linker_section_enum,
elf_linker_section_t *));
extern elf_linker_section_pointers_t *_bfd_elf_find_pointer_linker_section
PARAMS ((elf_linker_section_pointers_t *, bfd_vma,
elf_linker_section_enum_t));
extern bfd_boolean bfd_elf32_create_pointer_linker_section
PARAMS ((bfd *, struct bfd_link_info *, elf_linker_section_t *,
struct elf_link_hash_entry *, const Elf_Internal_Rela *));
extern bfd_vma bfd_elf32_finish_pointer_linker_section
PARAMS ((bfd *, bfd *, struct bfd_link_info *, elf_linker_section_t *,
struct elf_link_hash_entry *, bfd_vma,
const Elf_Internal_Rela *, int));
extern bfd_boolean bfd_elf64_create_pointer_linker_section
PARAMS ((bfd *, struct bfd_link_info *, elf_linker_section_t *,
struct elf_link_hash_entry *, const Elf_Internal_Rela *));
extern bfd_vma bfd_elf64_finish_pointer_linker_section
PARAMS ((bfd *, bfd *, struct bfd_link_info *, elf_linker_section_t *,
struct elf_link_hash_entry *, bfd_vma,
const Elf_Internal_Rela *, int));
extern bfd_boolean _bfd_elf_make_linker_section_rela
PARAMS ((bfd *, elf_linker_section_t *, int));
extern Elf_Internal_Rela *_bfd_elf_link_read_relocs
PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, bfd_boolean));

View File

@ -290,11 +290,6 @@ static bfd_boolean i370_elf_section_from_shdr
PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
static bfd_boolean i370_elf_fake_sections
PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
#if 0
static elf_linker_section_t *i370_elf_create_linker_section
PARAMS ((bfd *abfd, struct bfd_link_info *info,
enum elf_linker_section_enum));
#endif
static bfd_boolean i370_elf_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
@ -434,84 +429,6 @@ i370_elf_fake_sections (abfd, shdr, asect)
return TRUE;
}
#if 0
/* Create a special linker section */
/* XXX hack alert bogus This routine is mostly all junk and almost
* certainly does the wrong thing. Its here simply because it does
* just enough to allow glibc-2.1 ld.so to compile & link.
*/
static elf_linker_section_t *
i370_elf_create_linker_section (abfd, info, which)
bfd *abfd;
struct bfd_link_info *info;
enum elf_linker_section_enum which;
{
bfd *dynobj = elf_hash_table (info)->dynobj;
elf_linker_section_t *lsect;
/* Record the first bfd section that needs the special section */
if (!dynobj)
dynobj = elf_hash_table (info)->dynobj = abfd;
/* If this is the first time, create the section */
lsect = elf_linker_section (dynobj, which);
if (!lsect)
{
elf_linker_section_t defaults;
static elf_linker_section_t zero_section;
defaults = zero_section;
defaults.which = which;
defaults.hole_written_p = FALSE;
defaults.alignment = 2;
/* Both of these sections are (technically) created by the user
putting data in them, so they shouldn't be marked
SEC_LINKER_CREATED.
The linker creates them so it has somewhere to attach their
respective symbols. In fact, if they were empty it would
be OK to leave the symbol set to 0 (or any random number), because
the appropriate register should never be used. */
defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
| SEC_IN_MEMORY);
switch (which)
{
default:
(*_bfd_error_handler) ("%s: Unknown special linker type %d",
bfd_archive_filename (abfd),
(int) which);
bfd_set_error (bfd_error_bad_value);
return (elf_linker_section_t *)0;
case LINKER_SECTION_SDATA: /* .sdata/.sbss section */
defaults.name = ".sdata";
defaults.rel_name = ".rela.sdata";
defaults.bss_name = ".sbss";
defaults.sym_name = "_SDA_BASE_";
defaults.sym_offset = 32768;
break;
case LINKER_SECTION_SDATA2: /* .sdata2/.sbss2 section */
defaults.name = ".sdata2";
defaults.rel_name = ".rela.sdata2";
defaults.bss_name = ".sbss2";
defaults.sym_name = "_SDA2_BASE_";
defaults.sym_offset = 32768;
defaults.flags |= SEC_READONLY;
break;
}
lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults);
}
return lsect;
}
#endif
/* We have to create .dynsbss and .rela.sbss here so that they get mapped
to output sections (just like _bfd_elf_create_dynamic_sections has
to create .dynbss and .rela.bss). */

View File

@ -2169,6 +2169,360 @@ ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
return TRUE;
}
/* Create a special linker section, or return a pointer to a linker
section already created */
static elf_linker_section_t *
elf_create_linker_section (bfd *abfd,
struct bfd_link_info *info,
enum elf_linker_section_enum which,
elf_linker_section_t *defaults)
{
bfd *dynobj = elf_hash_table (info)->dynobj;
elf_linker_section_t *lsect;
/* Record the first bfd section that needs the special section */
if (!dynobj)
dynobj = elf_hash_table (info)->dynobj = abfd;
/* If this is the first time, create the section */
lsect = elf_linker_section (dynobj, which);
if (!lsect)
{
asection *s;
bfd_size_type amt = sizeof (elf_linker_section_t);
lsect = bfd_alloc (dynobj, amt);
*lsect = *defaults;
elf_linker_section (dynobj, which) = lsect;
lsect->which = which;
lsect->hole_written_p = FALSE;
/* See if the sections already exist */
lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
if (!s || (s->flags & defaults->flags) != defaults->flags)
{
lsect->section = s = bfd_make_section_anyway (dynobj, lsect->name);
if (s == NULL)
return NULL;
bfd_set_section_flags (dynobj, s, defaults->flags);
bfd_set_section_alignment (dynobj, s, lsect->alignment);
}
else if (bfd_get_section_alignment (dynobj, s) < lsect->alignment)
bfd_set_section_alignment (dynobj, s, lsect->alignment);
s->_raw_size = align_power (s->_raw_size, lsect->alignment);
/* Is there a hole we have to provide? If so check whether the
segment is too big already */
if (lsect->hole_size)
{
lsect->hole_offset = s->_raw_size;
s->_raw_size += lsect->hole_size;
if (lsect->hole_offset > lsect->max_hole_offset)
{
(*_bfd_error_handler)
(_("%s: Section %s is too large to add hole of %ld bytes"),
bfd_get_filename (abfd),
lsect->name,
(long) lsect->hole_size);
bfd_set_error (bfd_error_bad_value);
return NULL;
}
}
#ifdef DEBUG
fprintf (stderr, "Creating section %s, current size = %ld\n",
lsect->name, (long) s->_raw_size);
#endif
if (lsect->sym_name)
{
struct elf_link_hash_entry *h;
struct bfd_link_hash_entry *bh;
#ifdef DEBUG
fprintf (stderr, "Adding %s to section %s\n",
lsect->sym_name,
lsect->name);
#endif
bh = bfd_link_hash_lookup (info->hash, lsect->sym_name,
FALSE, FALSE, FALSE);
if ((bh == NULL || bh->type == bfd_link_hash_undefined)
&& !(_bfd_generic_link_add_one_symbol
(info, abfd, lsect->sym_name, BSF_GLOBAL, s,
(lsect->hole_size
? s->_raw_size - lsect->hole_size + lsect->sym_offset
: lsect->sym_offset),
NULL, FALSE,
get_elf_backend_data (abfd)->collect, &bh)))
return NULL;
h = (struct elf_link_hash_entry *) bh;
if ((defaults->which != LINKER_SECTION_SDATA)
&& (defaults->which != LINKER_SECTION_SDATA2))
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
h->type = STT_OBJECT;
lsect->sym_hash = h;
if (info->shared
&& ! _bfd_elf_link_record_dynamic_symbol (info, h))
return NULL;
}
}
return lsect;
}
/* Find a linker generated pointer with a given addend and type. */
static elf_linker_section_pointers_t *
elf_find_pointer_linker_section
(elf_linker_section_pointers_t *linker_pointers,
bfd_vma addend,
elf_linker_section_enum_t which)
{
for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next)
if (which == linker_pointers->which && addend == linker_pointers->addend)
return linker_pointers;
return NULL;
}
/* Allocate a pointer to live in a linker created section. */
static bfd_boolean
elf_create_pointer_linker_section (bfd *abfd,
struct bfd_link_info *info,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
const Elf_Internal_Rela *rel)
{
elf_linker_section_pointers_t **ptr_linker_section_ptr = NULL;
elf_linker_section_pointers_t *linker_section_ptr;
unsigned long r_symndx = ELF32_R_SYM (rel->r_info);
bfd_size_type amt;
BFD_ASSERT (lsect != NULL);
/* Is this a global symbol? */
if (h != NULL)
{
/* Has this symbol already been allocated? If so, our work is done. */
if (elf_find_pointer_linker_section (h->linker_section_pointer,
rel->r_addend,
lsect->which))
return TRUE;
ptr_linker_section_ptr = &h->linker_section_pointer;
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
if (! _bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (lsect->rel_section)
lsect->rel_section->_raw_size += sizeof (Elf32_External_Rela);
}
else
{
/* Allocation of a pointer to a local symbol. */
elf_linker_section_pointers_t **ptr = elf_local_ptr_offsets (abfd);
/* Allocate a table to hold the local symbols if first time. */
if (!ptr)
{
unsigned int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
register unsigned int i;
amt = num_symbols;
amt *= sizeof (elf_linker_section_pointers_t *);
ptr = bfd_alloc (abfd, amt);
if (!ptr)
return FALSE;
elf_local_ptr_offsets (abfd) = ptr;
for (i = 0; i < num_symbols; i++)
ptr[i] = NULL;
}
/* Has this symbol already been allocated? If so, our work is done. */
if (elf_find_pointer_linker_section (ptr[r_symndx],
rel->r_addend,
lsect->which))
return TRUE;
ptr_linker_section_ptr = &ptr[r_symndx];
if (info->shared)
{
/* If we are generating a shared object, we need to
output a R_<xxx>_RELATIVE reloc so that the
dynamic linker can adjust this GOT entry. */
BFD_ASSERT (lsect->rel_section != NULL);
lsect->rel_section->_raw_size += sizeof (Elf32_External_Rela);
}
}
/* Allocate space for a pointer in the linker section, and allocate
a new pointer record from internal memory. */
BFD_ASSERT (ptr_linker_section_ptr != NULL);
amt = sizeof (elf_linker_section_pointers_t);
linker_section_ptr = bfd_alloc (abfd, amt);
if (!linker_section_ptr)
return FALSE;
linker_section_ptr->next = *ptr_linker_section_ptr;
linker_section_ptr->addend = rel->r_addend;
linker_section_ptr->which = lsect->which;
linker_section_ptr->written_address_p = FALSE;
*ptr_linker_section_ptr = linker_section_ptr;
linker_section_ptr->offset = lsect->section->_raw_size;
lsect->section->_raw_size += 4;
#ifdef DEBUG
fprintf (stderr,
"Create pointer in linker section %s, offset = %ld, section size = %ld\n",
lsect->name, (long) linker_section_ptr->offset,
(long) lsect->section->_raw_size);
#endif
return TRUE;
}
#define bfd_put_ptr(BFD, VAL, ADDR) bfd_put_32 (BFD, VAL, ADDR)
/* Fill in the address for a pointer generated in a linker section. */
static bfd_vma
elf_finish_pointer_linker_section (bfd *output_bfd,
bfd *input_bfd,
struct bfd_link_info *info,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
bfd_vma relocation,
const Elf_Internal_Rela *rel,
int relative_reloc)
{
elf_linker_section_pointers_t *linker_section_ptr;
BFD_ASSERT (lsect != NULL);
if (h != NULL)
{
/* Handle global symbol. */
linker_section_ptr
= elf_find_pointer_linker_section (h->linker_section_pointer,
rel->r_addend,
lsect->which);
BFD_ASSERT (linker_section_ptr != NULL);
if (! elf_hash_table (info)->dynamic_sections_created
|| (info->shared
&& info->symbolic
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
locally. We must initialize this entry in the
global section.
When doing a dynamic link, we create a .rela.<xxx>
relocation entry to initialize the value. This
is done in the finish_dynamic_symbol routine. */
if (!linker_section_ptr->written_address_p)
{
linker_section_ptr->written_address_p = TRUE;
bfd_put_ptr (output_bfd,
relocation + linker_section_ptr->addend,
(lsect->section->contents
+ linker_section_ptr->offset));
}
}
}
else
{
/* Handle local symbol. */
unsigned long r_symndx = ELF32_R_SYM (rel->r_info);
BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL);
BFD_ASSERT (elf_local_ptr_offsets (input_bfd)[r_symndx] != NULL);
linker_section_ptr = (elf_find_pointer_linker_section
(elf_local_ptr_offsets (input_bfd)[r_symndx],
rel->r_addend,
lsect->which));
BFD_ASSERT (linker_section_ptr != NULL);
/* Write out pointer if it hasn't been rewritten out before. */
if (!linker_section_ptr->written_address_p)
{
linker_section_ptr->written_address_p = TRUE;
bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend,
lsect->section->contents + linker_section_ptr->offset);
if (info->shared)
{
asection *srel = lsect->rel_section;
Elf_Internal_Rela outrel[MAX_INT_RELS_PER_EXT_REL];
bfd_byte *erel;
struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
unsigned int i;
/* We need to generate a relative reloc for the dynamic
linker. */
if (!srel)
{
srel = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
lsect->rel_name);
lsect->rel_section = srel;
}
BFD_ASSERT (srel != NULL);
for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
{
outrel[i].r_offset = (lsect->section->output_section->vma
+ lsect->section->output_offset
+ linker_section_ptr->offset);
outrel[i].r_info = 0;
outrel[i].r_addend = 0;
}
outrel[0].r_info = ELF32_R_INFO (0, relative_reloc);
erel = lsect->section->contents;
erel += (elf_section_data (lsect->section)->rel_count++
* sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (output_bfd, outrel, erel);
}
}
}
relocation = (lsect->section->output_offset
+ linker_section_ptr->offset
- lsect->hole_offset
- lsect->sym_offset);
#ifdef DEBUG
fprintf (stderr,
"Finish pointer in linker section %s, offset = %ld (0x%lx)\n",
lsect->name, (long) relocation, (long) relocation);
#endif
/* Subtract out the addend, because it will get added back in by the normal
processing. */
return relocation - linker_section_ptr->addend;
}
/* Create a special linker section */
static elf_linker_section_t *
ppc_elf_create_linker_section (bfd *abfd,
@ -2233,7 +2587,7 @@ ppc_elf_create_linker_section (bfd *abfd,
break;
}
lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults);
lsect = elf_create_linker_section (abfd, info, which, &defaults);
}
return lsect;
@ -2318,7 +2672,10 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
asection *s;
flagword flags;
if (!ppc_elf_create_got (abfd, info))
htab = ppc_elf_hash_table (info);
if (htab->got == NULL
&& !ppc_elf_create_got (abfd, info))
return FALSE;
if (!_bfd_elf_create_dynamic_sections (abfd, info))
@ -2327,7 +2684,6 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
htab = ppc_elf_hash_table (info);
htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss");
htab->dynsbss = s = bfd_make_section (abfd, ".dynsbss");
if (s == NULL
@ -3220,8 +3576,8 @@ ppc_elf_check_relocs (bfd *abfd,
bad_shared_reloc (abfd, r_type);
return FALSE;
}
if (!bfd_elf32_create_pointer_linker_section (abfd, info,
htab->sdata, h, rel))
if (!elf_create_pointer_linker_section (abfd, info,
htab->sdata, h, rel))
return FALSE;
break;
@ -3232,8 +3588,8 @@ ppc_elf_check_relocs (bfd *abfd,
bad_shared_reloc (abfd, r_type);
return FALSE;
}
if (!bfd_elf32_create_pointer_linker_section (abfd, info,
htab->sdata2, h, rel))
if (!elf_create_pointer_linker_section (abfd, info,
htab->sdata2, h, rel))
return FALSE;
break;
@ -5008,20 +5364,18 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_EMB_SDAI16:
BFD_ASSERT (htab->sdata != NULL);
relocation
= bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd,
info, htab->sdata, h,
relocation, rel,
R_PPC_RELATIVE);
= elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
htab->sdata, h, relocation,
rel, R_PPC_RELATIVE);
break;
/* Indirect .sdata2 relocation. */
case R_PPC_EMB_SDA2I16:
BFD_ASSERT (htab->sdata2 != NULL);
relocation
= bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd,
info, htab->sdata2, h,
relocation, rel,
R_PPC_RELATIVE);
= elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
htab->sdata2, h, relocation,
rel, R_PPC_RELATIVE);
break;
/* Handle the TOC16 reloc. We want to use the offset within the .got

View File

@ -125,8 +125,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define elf_reloc_symbol_deleted_p NAME(_bfd_elf,reloc_symbol_deleted_p)
#define elf_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
#define elf_bfd_final_link NAME(bfd_elf,bfd_final_link)
#define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section)
#define elf_finish_pointer_linker_section NAME(bfd_elf,finish_pointer_linker_section)
#define elf_gc_sections NAME(_bfd_elf,gc_sections)
#define elf_gc_common_finalize_got_offsets \
NAME(_bfd_elf,gc_common_finalize_got_offsets)

View File

@ -1896,179 +1896,6 @@ _bfd_elf_link_assign_sym_version (h, data)
return TRUE;
}
/* Create a special linker section, or return a pointer to a linker
section already created */
elf_linker_section_t *
_bfd_elf_create_linker_section (abfd, info, which, defaults)
bfd *abfd;
struct bfd_link_info *info;
enum elf_linker_section_enum which;
elf_linker_section_t *defaults;
{
bfd *dynobj = elf_hash_table (info)->dynobj;
elf_linker_section_t *lsect;
/* Record the first bfd section that needs the special section */
if (!dynobj)
dynobj = elf_hash_table (info)->dynobj = abfd;
/* If this is the first time, create the section */
lsect = elf_linker_section (dynobj, which);
if (!lsect)
{
asection *s;
bfd_size_type amt = sizeof (elf_linker_section_t);
lsect = (elf_linker_section_t *) bfd_alloc (dynobj, amt);
*lsect = *defaults;
elf_linker_section (dynobj, which) = lsect;
lsect->which = which;
lsect->hole_written_p = FALSE;
/* See if the sections already exist */
lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
if (!s || (s->flags & defaults->flags) != defaults->flags)
{
lsect->section = s = bfd_make_section_anyway (dynobj, lsect->name);
if (s == NULL)
return (elf_linker_section_t *)0;
bfd_set_section_flags (dynobj, s, defaults->flags);
bfd_set_section_alignment (dynobj, s, lsect->alignment);
}
else if (bfd_get_section_alignment (dynobj, s) < lsect->alignment)
bfd_set_section_alignment (dynobj, s, lsect->alignment);
s->_raw_size = align_power (s->_raw_size, lsect->alignment);
/* Is there a hole we have to provide? If so check whether the
segment is too big already */
if (lsect->hole_size)
{
lsect->hole_offset = s->_raw_size;
s->_raw_size += lsect->hole_size;
if (lsect->hole_offset > lsect->max_hole_offset)
{
(*_bfd_error_handler)
(_("%s: Section %s is too large to add hole of %ld bytes"),
bfd_get_filename (abfd),
lsect->name,
(long) lsect->hole_size);
bfd_set_error (bfd_error_bad_value);
return (elf_linker_section_t *)0;
}
}
#ifdef DEBUG
fprintf (stderr, "Creating section %s, current size = %ld\n",
lsect->name, (long)s->_raw_size);
#endif
if (lsect->sym_name)
{
struct elf_link_hash_entry *h;
struct bfd_link_hash_entry *bh;
#ifdef DEBUG
fprintf (stderr, "Adding %s to section %s\n",
lsect->sym_name,
lsect->name);
#endif
bh = bfd_link_hash_lookup (info->hash, lsect->sym_name,
FALSE, FALSE, FALSE);
if ((bh == NULL || bh->type == bfd_link_hash_undefined)
&& !(_bfd_generic_link_add_one_symbol
(info, abfd, lsect->sym_name, BSF_GLOBAL, s,
(lsect->hole_size
? s->_raw_size - lsect->hole_size + lsect->sym_offset
: lsect->sym_offset),
(const char *) NULL, FALSE,
get_elf_backend_data (abfd)->collect, &bh)))
return (elf_linker_section_t *) 0;
h = (struct elf_link_hash_entry *) bh;
if ((defaults->which != LINKER_SECTION_SDATA)
&& (defaults->which != LINKER_SECTION_SDATA2))
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
h->type = STT_OBJECT;
lsect->sym_hash = h;
if (info->shared
&& ! _bfd_elf_link_record_dynamic_symbol (info, h))
return (elf_linker_section_t *) 0;
}
}
#if 0
/* This does not make sense. The sections which may exist in the
object file have nothing to do with the sections we want to
create. */
/* Find the related sections if they have been created */
if (lsect->bss_name && !lsect->bss_section)
lsect->bss_section = bfd_get_section_by_name (dynobj, lsect->bss_name);
if (lsect->rel_name && !lsect->rel_section)
lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
#endif
return lsect;
}
/* Find a linker generated pointer with a given addend and type. */
elf_linker_section_pointers_t *
_bfd_elf_find_pointer_linker_section (linker_pointers, addend, which)
elf_linker_section_pointers_t *linker_pointers;
bfd_vma addend;
elf_linker_section_enum_t which;
{
for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next)
{
if (which == linker_pointers->which && addend == linker_pointers->addend)
return linker_pointers;
}
return (elf_linker_section_pointers_t *)0;
}
/* Make the .rela section corresponding to the generated linker section. */
bfd_boolean
_bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
bfd *dynobj;
elf_linker_section_t *lsect;
int alignment;
{
if (lsect->rel_section)
return TRUE;
lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
if (lsect->rel_section == NULL)
{
lsect->rel_section = bfd_make_section (dynobj, lsect->rel_name);
if (lsect->rel_section == NULL
|| ! bfd_set_section_flags (dynobj,
lsect->rel_section,
(SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
| SEC_LINKER_CREATED
| SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, lsect->rel_section, alignment))
return FALSE;
}
return TRUE;
}
/* Read and swap the relocs from the section indicated by SHDR. This
may be either a REL or a RELA section. The relocations are
translated into RELA relocations and stored in INTERNAL_RELOCS,

View File

@ -5557,264 +5557,6 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
return TRUE;
}
/* Allocate a pointer to live in a linker created section. */
bfd_boolean
elf_create_pointer_linker_section (abfd, info, lsect, h, rel)
bfd *abfd;
struct bfd_link_info *info;
elf_linker_section_t *lsect;
struct elf_link_hash_entry *h;
const Elf_Internal_Rela *rel;
{
elf_linker_section_pointers_t **ptr_linker_section_ptr = NULL;
elf_linker_section_pointers_t *linker_section_ptr;
unsigned long r_symndx = ELF_R_SYM (rel->r_info);
bfd_size_type amt;
BFD_ASSERT (lsect != NULL);
/* Is this a global symbol? */
if (h != NULL)
{
/* Has this symbol already been allocated? If so, our work is done. */
if (_bfd_elf_find_pointer_linker_section (h->linker_section_pointer,
rel->r_addend,
lsect->which))
return TRUE;
ptr_linker_section_ptr = &h->linker_section_pointer;
/* Make sure this symbol is output as a dynamic symbol. */
if (h->dynindx == -1)
{
if (! elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (lsect->rel_section)
lsect->rel_section->_raw_size += sizeof (Elf_External_Rela);
}
else
{
/* Allocation of a pointer to a local symbol. */
elf_linker_section_pointers_t **ptr = elf_local_ptr_offsets (abfd);
/* Allocate a table to hold the local symbols if first time. */
if (!ptr)
{
unsigned int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
register unsigned int i;
amt = num_symbols;
amt *= sizeof (elf_linker_section_pointers_t *);
ptr = (elf_linker_section_pointers_t **) bfd_alloc (abfd, amt);
if (!ptr)
return FALSE;
elf_local_ptr_offsets (abfd) = ptr;
for (i = 0; i < num_symbols; i++)
ptr[i] = (elf_linker_section_pointers_t *) 0;
}
/* Has this symbol already been allocated? If so, our work is done. */
if (_bfd_elf_find_pointer_linker_section (ptr[r_symndx],
rel->r_addend,
lsect->which))
return TRUE;
ptr_linker_section_ptr = &ptr[r_symndx];
if (info->shared)
{
/* If we are generating a shared object, we need to
output a R_<xxx>_RELATIVE reloc so that the
dynamic linker can adjust this GOT entry. */
BFD_ASSERT (lsect->rel_section != NULL);
lsect->rel_section->_raw_size += sizeof (Elf_External_Rela);
}
}
/* Allocate space for a pointer in the linker section, and allocate
a new pointer record from internal memory. */
BFD_ASSERT (ptr_linker_section_ptr != NULL);
amt = sizeof (elf_linker_section_pointers_t);
linker_section_ptr = (elf_linker_section_pointers_t *) bfd_alloc (abfd, amt);
if (!linker_section_ptr)
return FALSE;
linker_section_ptr->next = *ptr_linker_section_ptr;
linker_section_ptr->addend = rel->r_addend;
linker_section_ptr->which = lsect->which;
linker_section_ptr->written_address_p = FALSE;
*ptr_linker_section_ptr = linker_section_ptr;
#if 0
if (lsect->hole_size && lsect->hole_offset < lsect->max_hole_offset)
{
linker_section_ptr->offset = (lsect->section->_raw_size
- lsect->hole_size + (ARCH_SIZE / 8));
lsect->hole_offset += ARCH_SIZE / 8;
lsect->sym_offset += ARCH_SIZE / 8;
if (lsect->sym_hash)
{
/* Bump up symbol value if needed. */
lsect->sym_hash->root.u.def.value += ARCH_SIZE / 8;
#ifdef DEBUG
fprintf (stderr, "Bump up %s by %ld, current value = %ld\n",
lsect->sym_hash->root.root.string,
(long) ARCH_SIZE / 8,
(long) lsect->sym_hash->root.u.def.value);
#endif
}
}
else
#endif
linker_section_ptr->offset = lsect->section->_raw_size;
lsect->section->_raw_size += ARCH_SIZE / 8;
#ifdef DEBUG
fprintf (stderr,
"Create pointer in linker section %s, offset = %ld, section size = %ld\n",
lsect->name, (long) linker_section_ptr->offset,
(long) lsect->section->_raw_size);
#endif
return TRUE;
}
#if ARCH_SIZE==64
#define bfd_put_ptr(BFD,VAL,ADDR) bfd_put_64 (BFD, VAL, ADDR)
#endif
#if ARCH_SIZE==32
#define bfd_put_ptr(BFD,VAL,ADDR) bfd_put_32 (BFD, VAL, ADDR)
#endif
/* Fill in the address for a pointer generated in a linker section. */
bfd_vma
elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h,
relocation, rel, relative_reloc)
bfd *output_bfd;
bfd *input_bfd;
struct bfd_link_info *info;
elf_linker_section_t *lsect;
struct elf_link_hash_entry *h;
bfd_vma relocation;
const Elf_Internal_Rela *rel;
int relative_reloc;
{
elf_linker_section_pointers_t *linker_section_ptr;
BFD_ASSERT (lsect != NULL);
if (h != NULL)
{
/* Handle global symbol. */
linker_section_ptr = (_bfd_elf_find_pointer_linker_section
(h->linker_section_pointer,
rel->r_addend,
lsect->which));
BFD_ASSERT (linker_section_ptr != NULL);
if (! elf_hash_table (info)->dynamic_sections_created
|| (info->shared
&& info->symbolic
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
{
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
locally. We must initialize this entry in the
global section.
When doing a dynamic link, we create a .rela.<xxx>
relocation entry to initialize the value. This
is done in the finish_dynamic_symbol routine. */
if (!linker_section_ptr->written_address_p)
{
linker_section_ptr->written_address_p = TRUE;
bfd_put_ptr (output_bfd,
relocation + linker_section_ptr->addend,
(lsect->section->contents
+ linker_section_ptr->offset));
}
}
}
else
{
/* Handle local symbol. */
unsigned long r_symndx = ELF_R_SYM (rel->r_info);
BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL);
BFD_ASSERT (elf_local_ptr_offsets (input_bfd)[r_symndx] != NULL);
linker_section_ptr = (_bfd_elf_find_pointer_linker_section
(elf_local_ptr_offsets (input_bfd)[r_symndx],
rel->r_addend,
lsect->which));
BFD_ASSERT (linker_section_ptr != NULL);
/* Write out pointer if it hasn't been rewritten out before. */
if (!linker_section_ptr->written_address_p)
{
linker_section_ptr->written_address_p = TRUE;
bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend,
lsect->section->contents + linker_section_ptr->offset);
if (info->shared)
{
asection *srel = lsect->rel_section;
Elf_Internal_Rela outrel[MAX_INT_RELS_PER_EXT_REL];
bfd_byte *erel;
struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
unsigned int i;
/* We need to generate a relative reloc for the dynamic
linker. */
if (!srel)
{
srel = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
lsect->rel_name);
lsect->rel_section = srel;
}
BFD_ASSERT (srel != NULL);
for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
{
outrel[i].r_offset = (lsect->section->output_section->vma
+ lsect->section->output_offset
+ linker_section_ptr->offset);
outrel[i].r_info = 0;
outrel[i].r_addend = 0;
}
outrel[0].r_info = ELF_R_INFO (0, relative_reloc);
erel = lsect->section->contents;
erel += (elf_section_data (lsect->section)->rel_count++
* sizeof (Elf_External_Rela));
elf_swap_reloca_out (output_bfd, outrel, erel);
}
}
}
relocation = (lsect->section->output_offset
+ linker_section_ptr->offset
- lsect->hole_offset
- lsect->sym_offset);
#ifdef DEBUG
fprintf (stderr,
"Finish pointer in linker section %s, offset = %ld (0x%lx)\n",
lsect->name, (long) relocation, (long) relocation);
#endif
/* Subtract out the addend, because it will get added back in by the normal
processing. */
return relocation - linker_section_ptr->addend;
}
/* Garbage collect unused sections. */
static bfd_boolean elf_gc_mark