diff options
-rw-r--r-- | bfd/ChangeLog | 32 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 29 | ||||
-rw-r--r-- | bfd/elf32-i370.c | 83 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 384 | ||||
-rw-r--r-- | bfd/elfcode.h | 2 | ||||
-rw-r--r-- | bfd/elflink.c | 173 | ||||
-rw-r--r-- | bfd/elflink.h | 258 |
7 files changed, 397 insertions, 564 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6d520ca..8aedf99 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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, diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 5e4c180..1b9ec8a 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -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)); diff --git a/bfd/elf32-i370.c b/bfd/elf32-i370.c index 2eacb81..4a06ac0 100644 --- a/bfd/elf32-i370.c +++ b/bfd/elf32-i370.c @@ -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). */ diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 2e1353f..f2b987c 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -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 diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 6686ab9..6afaefa 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -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) diff --git a/bfd/elflink.c b/bfd/elflink.c index d6f6d70..b448367 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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, diff --git a/bfd/elflink.h b/bfd/elflink.h index f4a65bf..f679ab7 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -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 |