(_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-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
(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 *.
(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,
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));
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 *));
return TRUE;
}
\f
-#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
-\f
/* 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). */
return TRUE;
}
\f
+/* 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;
+}
+\f
+/* 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;
+}
+\f
+/* 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;
+}
+\f
+#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;
+}
+\f
/* Create a special linker section */
static elf_linker_section_t *
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;
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))
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
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;
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;
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
#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)
return TRUE;
}
\f
-/* 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;
-}
-\f
-/* 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;
-}
-\f
-/* 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;
-}
-\f
/* 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,
return TRUE;
}
\f
-/* 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;
-}
-\f
-#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;
-}
-\f
/* Garbage collect unused sections. */
static bfd_boolean elf_gc_mark