diff options
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index 55173ff..ce1dff7 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12269,3 +12269,128 @@ _bfd_elf_default_got_elt_size (bfd *abfd, const struct elf_backend_data *bed = get_elf_backend_data (abfd); return bed->s->arch_size / 8; } + +/* Routines to support the creation of dynamic relocs. */ + +/* Return true if NAME is a name of a relocation + section associated with section S. */ + +static bfd_boolean +is_reloc_section (bfd_boolean rela, const char * name, asection * s) +{ + if (rela) + return CONST_STRNEQ (name, ".rela") + && strcmp (bfd_get_section_name (NULL, s), name + 5) == 0; + + return CONST_STRNEQ (name, ".rel") + && strcmp (bfd_get_section_name (NULL, s), name + 4) == 0; +} + +/* Returns the name of the dynamic reloc section associated with SEC. */ + +static const char * +get_dynamic_reloc_section_name (bfd * abfd, + asection * sec, + bfd_boolean is_rela) +{ + const char * name; + unsigned int strndx = elf_elfheader (abfd)->e_shstrndx; + unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name; + + name = bfd_elf_string_from_elf_section (abfd, strndx, shnam); + if (name == NULL) + return NULL; + + if (! is_reloc_section (is_rela, name, sec)) + { + static bfd_boolean complained = FALSE; + + if (! complained) + { + (*_bfd_error_handler) + (_("%B: bad relocation section name `%s\'"), abfd, name); + complained = TRUE; + } + name = NULL; + } + + return name; +} + +/* Returns the dynamic reloc section associated with SEC. + If necessary compute the name of the dynamic reloc section based + on SEC's name (looked up in ABFD's string table) and the setting + of IS_RELA. */ + +asection * +_bfd_elf_get_dynamic_reloc_section (bfd * abfd, + asection * sec, + bfd_boolean is_rela) +{ + asection * reloc_sec = elf_section_data (sec)->sreloc; + + if (reloc_sec == NULL) + { + const char * name = get_dynamic_reloc_section_name (abfd, sec, is_rela); + + if (name != NULL) + { + reloc_sec = bfd_get_section_by_name (abfd, name); + + if (reloc_sec != NULL) + elf_section_data (sec)->sreloc = reloc_sec; + } + } + + return reloc_sec; +} + +/* Returns the dynamic reloc section associated with SEC. If the + section does not exist it is created and attached to the DYNOBJ + bfd and stored in the SRELOC field of SEC's elf_section_data + structure. + + ALIGNMENT is the alignment for the newly created section and + IS_RELA defines whether the name should be .rela.<SEC's name> + or .rel.<SEC's name>. The section name is looked up in the + string table associated with ABFD. */ + +asection * +_bfd_elf_make_dynamic_reloc_section (asection * sec, + bfd * dynobj, + unsigned int alignment, + bfd * abfd, + bfd_boolean is_rela) +{ + asection * reloc_sec = elf_section_data (sec)->sreloc; + + if (reloc_sec == NULL) + { + const char * name = get_dynamic_reloc_section_name (abfd, sec, is_rela); + + if (name == NULL) + return NULL; + + reloc_sec = bfd_get_section_by_name (dynobj, name); + + if (reloc_sec == NULL) + { + flagword flags; + + flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED); + if ((sec->flags & SEC_ALLOC) != 0) + flags |= SEC_ALLOC | SEC_LOAD; + + reloc_sec = bfd_make_section_with_flags (dynobj, name, flags); + if (reloc_sec != NULL) + { + if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment)) + reloc_sec = NULL; + } + } + + elf_section_data (sec)->sreloc = reloc_sec; + } + + return reloc_sec; +} |