X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felf.c;h=3d1a28aa7eef24abcbe04040e309158a6db5f851;hb=50455f1ab2935f7321215dfa681745c9b1cb5b19;hp=9e46f7c7caaf90c1b7ac36e54146ba148d335d94;hpb=f0a5d95aae21532529061054fa13816d7adf81d8;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index 9e46f7c7ca..3d1a28aa7e 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1,6 +1,6 @@ /* ELF executable support for BFD. - Copyright (C) 1993-2014 Free Software Foundation, Inc. + Copyright (C) 1993-2016 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -42,7 +42,7 @@ SECTION #include "elf-bfd.h" #include "libiberty.h" #include "safe-ctype.h" -#include "elf-linux-psinfo.h" +#include "elf-linux-core.h" #ifdef CORE_HEADER #include CORE_HEADER @@ -51,7 +51,7 @@ SECTION static int elf_sort_sections (const void *, const void *); static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *); static bfd_boolean prep_headers (bfd *); -static bfd_boolean swap_out_syms (bfd *, struct bfd_strtab_hash **, int) ; +static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ; static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ; static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset); @@ -297,13 +297,14 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex) /* Allocate and clear an extra byte at the end, to prevent crashes in case the string table is not terminated. */ if (shstrtabsize + 1 <= 1 - || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL - || bfd_seek (abfd, offset, SEEK_SET) != 0) + || bfd_seek (abfd, offset, SEEK_SET) != 0 + || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL) shstrtab = NULL; else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_file_truncated); + bfd_release (abfd, shstrtab); shstrtab = NULL; /* Once we've failed to read it, make sure we don't keep trying. Otherwise, we'll keep allocating space for @@ -332,14 +333,26 @@ bfd_elf_string_from_elf_section (bfd *abfd, hdr = elf_elfsections (abfd)[shindex]; - if (hdr->contents == NULL - && bfd_elf_get_str_section (abfd, shindex) == NULL) - return NULL; + if (hdr->contents == NULL) + { + if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS) + { + /* PR 17512: file: f057ec89. */ + /* xgettext:c-format */ + _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"), + abfd, shindex); + return NULL; + } + + if (bfd_elf_get_str_section (abfd, shindex) == NULL) + return NULL; + } if (strindex >= hdr->sh_size) { unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx; - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: invalid string offset %u >= %lu for section `%s'"), abfd, strindex, (unsigned long) hdr->sh_size, (shindex == shstrndx && strindex == hdr->sh_name @@ -389,8 +402,34 @@ bfd_elf_get_elf_syms (bfd *ibfd, /* Normal syms might have section extension entries. */ shndx_hdr = NULL; - if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr) - shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr; + if (elf_symtab_shndx_list (ibfd) != NULL) + { + elf_section_list * entry; + Elf_Internal_Shdr **sections = elf_elfsections (ibfd); + + /* Find an index section that is linked to this symtab section. */ + for (entry = elf_symtab_shndx_list (ibfd); entry != NULL; entry = entry->next) + { + /* PR 20063. */ + if (entry->hdr.sh_link >= elf_numsections (ibfd)) + continue; + + if (sections[entry->hdr.sh_link] == symtab_hdr) + { + shndx_hdr = & entry->hdr; + break; + }; + } + + if (shndx_hdr == NULL) + { + if (symtab_hdr == & elf_symtab_hdr (ibfd)) + /* Not really accurate, but this was how the old code used to work. */ + shndx_hdr = & elf_symtab_shndx_list (ibfd)->hdr; + /* Otherwise we do nothing. The assumption is that + the index table will not be needed. */ + } + } /* Read the symbols. */ alloc_ext = NULL; @@ -398,7 +437,7 @@ bfd_elf_get_elf_syms (bfd *ibfd, alloc_intsym = NULL; bed = get_elf_backend_data (ibfd); extsym_size = bed->s->sizeof_sym; - amt = symcount * extsym_size; + amt = (bfd_size_type) symcount * extsym_size; pos = symtab_hdr->sh_offset + symoffset * extsym_size; if (extsym_buf == NULL) { @@ -417,7 +456,7 @@ bfd_elf_get_elf_syms (bfd *ibfd, extshndx_buf = NULL; else { - amt = symcount * sizeof (Elf_External_Sym_Shndx); + amt = (bfd_size_type) symcount * sizeof (Elf_External_Sym_Shndx); pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx); if (extshndx_buf == NULL) { @@ -452,9 +491,10 @@ bfd_elf_get_elf_syms (bfd *ibfd, if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym)) { symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size; - (*_bfd_error_handler) (_("%B symbol number %lu references " - "nonexistent SHT_SYMTAB_SHNDX section"), - ibfd, (unsigned long) symoffset); + /* xgettext:c-format */ + _bfd_error_handler (_("%B symbol number %lu references " + "nonexistent SHT_SYMTAB_SHNDX section"), + ibfd, (unsigned long) symoffset); if (alloc_intsym != NULL) free (alloc_intsym); intsym_buf = NULL; @@ -608,9 +648,11 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) if (shdr->contents == NULL) { _bfd_error_handler - (_("%B: Corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size); + /* xgettext:c-format */ + (_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size); bfd_set_error (bfd_error_bad_value); - return FALSE; + -- num_group; + continue; } memset (shdr->contents, 0, amt); @@ -618,7 +660,17 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0 || (bfd_bread (shdr->contents, shdr->sh_size, abfd) != shdr->sh_size)) - return FALSE; + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size); + bfd_set_error (bfd_error_bad_value); + -- num_group; + /* PR 17510: If the group contents are even partially + corrupt, do not allow any of the contents to be used. */ + memset (shdr->contents, 0, amt); + continue; + } /* Translate raw contents, a flag word followed by an array of elf section indices all in target byte order, @@ -626,6 +678,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) pointers. */ src = shdr->contents + shdr->sh_size; dest = (Elf_Internal_Group *) (shdr->contents + amt); + while (1) { unsigned int idx; @@ -643,14 +696,30 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) } if (idx >= shnum) { - ((*_bfd_error_handler) - (_("%B: invalid SHT_GROUP entry"), abfd)); + _bfd_error_handler + (_("%B: invalid SHT_GROUP entry"), abfd); idx = 0; } dest->shdr = elf_elfsections (abfd)[idx]; } } } + + /* PR 17510: Corrupt binaries might contain invalid groups. */ + if (num_group != (unsigned) elf_tdata (abfd)->num_group) + { + elf_tdata (abfd)->num_group = num_group; + + /* If all groups are invalid then fail. */ + if (num_group == 0) + { + elf_tdata (abfd)->group_sect_ptr = NULL; + elf_tdata (abfd)->num_group = num_group = -1; + _bfd_error_handler + (_("%B: no valid group sections found"), abfd); + bfd_set_error (bfd_error_bad_value); + } + } } } @@ -714,8 +783,10 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) if (elf_group_name (newsect) == NULL) { - (*_bfd_error_handler) (_("%B: no group info for section %A"), - abfd, newsect); + /* xgettext:c-format */ + _bfd_error_handler (_("%B: no group info for section %A"), + abfd, newsect); + return FALSE; } return TRUE; } @@ -743,6 +814,7 @@ _bfd_elf_setup_sections (bfd *abfd) const struct elf_backend_data *bed = get_elf_backend_data (abfd); if (bed->link_order_error_handler) bed->link_order_error_handler + /* xgettext:c-format */ (_("%B: warning: sh_link not set for section `%A'"), abfd, s); } @@ -761,7 +833,8 @@ _bfd_elf_setup_sections (bfd *abfd) sh_link. We don't want to proceed. */ if (linksec == NULL) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: sh_link [%d] in section `%A' is incorrect"), s->owner, s, elfsec); result = FALSE; @@ -770,6 +843,15 @@ _bfd_elf_setup_sections (bfd *abfd) elf_linked_to_section (s) = linksec; } } + else if (this_hdr->sh_type == SHT_GROUP + && elf_next_in_group (s) == NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: SHT_GROUP section [index %d] has no SHF_GROUP sections"), + abfd, elf_section_data (s)->this_idx); + result = FALSE; + } } /* Process section groups. */ @@ -779,8 +861,22 @@ _bfd_elf_setup_sections (bfd *abfd) for (i = 0; i < num_group; i++) { Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i]; - Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents; - unsigned int n_elt = shdr->sh_size / 4; + Elf_Internal_Group *idx; + unsigned int n_elt; + + /* PR binutils/18758: Beware of corrupt binaries with invalid group data. */ + if (shdr == NULL || shdr->bfd_section == NULL || shdr->contents == NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: section group entry number %u is corrupt"), + abfd, i); + result = FALSE; + continue; + } + + idx = (Elf_Internal_Group *) shdr->contents; + n_elt = shdr->sh_size / 4; while (--n_elt != 0) if ((++idx)->shdr->bfd_section) @@ -796,7 +892,8 @@ _bfd_elf_setup_sections (bfd *abfd) else { /* There are some unknown sections in the group. */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: unknown [%d] section `%s' in group [%s]"), abfd, (unsigned int) idx->shdr->sh_type, @@ -817,6 +914,31 @@ bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec) return elf_next_in_group (sec) != NULL; } +static char * +convert_debug_to_zdebug (bfd *abfd, const char *name) +{ + unsigned int len = strlen (name); + char *new_name = bfd_alloc (abfd, len + 2); + if (new_name == NULL) + return NULL; + new_name[0] = '.'; + new_name[1] = 'z'; + memcpy (new_name + 2, name + 1, len); + return new_name; +} + +static char * +convert_zdebug_to_debug (bfd *abfd, const char *name) +{ + unsigned int len = strlen (name); + char *new_name = bfd_alloc (abfd, len); + if (new_name == NULL) + return NULL; + new_name[0] = '.'; + memcpy (new_name + 1, name + 2, len - 1); + return new_name; +} + /* Make a BFD section from an ELF section. We store a pointer to the BFD section in the bfd_section field of the header. */ @@ -874,9 +996,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, { flags |= SEC_MERGE; newsect->entsize = hdr->sh_entsize; - if ((hdr->sh_flags & SHF_STRINGS) != 0) - flags |= SEC_STRINGS; } + if ((hdr->sh_flags & SHF_STRINGS) != 0) + flags |= SEC_STRINGS; if (hdr->sh_flags & SHF_GROUP) if (!setup_group (abfd, hdr, newsect)) return FALSE; @@ -1003,74 +1125,86 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, || (name[1] == 'z' && name[7] == '_'))) { enum { nothing, compress, decompress } action = nothing; - char *new_name; + int compression_header_size; + bfd_size_type uncompressed_size; + bfd_boolean compressed + = bfd_is_section_compressed_with_header (abfd, newsect, + &compression_header_size, + &uncompressed_size); - if (bfd_is_section_compressed (abfd, newsect)) + if (compressed) { /* Compressed section. Check if we should decompress. */ if ((abfd->flags & BFD_DECOMPRESS)) action = decompress; } - else + + /* Compress the uncompressed section or convert from/to .zdebug* + section. Check if we should compress. */ + if (action == nothing) { - /* Normal section. Check if we should compress. */ - if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0) + if (newsect->size != 0 + && (abfd->flags & BFD_COMPRESS) + && compression_header_size >= 0 + && uncompressed_size > 0 + && (!compressed + || ((compression_header_size > 0) + != ((abfd->flags & BFD_COMPRESS_GABI) != 0)))) action = compress; + else + return TRUE; } - new_name = NULL; - switch (action) + if (action == compress) { - case nothing: - break; - case compress: if (!bfd_init_section_compress_status (abfd, newsect)) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: unable to initialize compress status for section %s"), abfd, name); return FALSE; } - if (name[1] != 'z') - { - unsigned int len = strlen (name); - - new_name = bfd_alloc (abfd, len + 2); - if (new_name == NULL) - return FALSE; - new_name[0] = '.'; - new_name[1] = 'z'; - memcpy (new_name + 2, name + 1, len); - } - break; - case decompress: + } + else + { if (!bfd_init_section_decompress_status (abfd, newsect)) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: unable to initialize decompress status for section %s"), abfd, name); return FALSE; } - if (name[1] == 'z') - { - unsigned int len = strlen (name); + } - new_name = bfd_alloc (abfd, len); + if (abfd->is_linker_input) + { + if (name[1] == 'z' + && (action == decompress + || (action == compress + && (abfd->flags & BFD_COMPRESS_GABI) != 0))) + { + /* Convert section name from .zdebug_* to .debug_* so + that linker will consider this section as a debug + section. */ + char *new_name = convert_zdebug_to_debug (abfd, name); if (new_name == NULL) return FALSE; - new_name[0] = '.'; - memcpy (new_name + 1, name + 2, len - 1); + bfd_rename_section (abfd, newsect, new_name); } - break; } - if (new_name != NULL) - bfd_rename_section (abfd, newsect, new_name); + else + /* For objdump, don't rename the section. For objcopy, delay + section rename to elf_fake_sections. */ + newsect->flags |= SEC_ELF_RENAME; } return TRUE; } -const char *const bfd_elf_section_type_names[] = { +const char *const bfd_elf_section_type_names[] = +{ "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB", "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE", "SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM", @@ -1107,14 +1241,162 @@ bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, return bfd_reloc_continue; } +/* Returns TRUE if section A matches section B. + Names, addresses and links may be different, but everything else + should be the same. */ + +static bfd_boolean +section_match (const Elf_Internal_Shdr * a, + const Elf_Internal_Shdr * b) +{ + return + a->sh_type == b->sh_type + && (a->sh_flags & ~ SHF_INFO_LINK) + == (b->sh_flags & ~ SHF_INFO_LINK) + && a->sh_addralign == b->sh_addralign + && a->sh_size == b->sh_size + && a->sh_entsize == b->sh_entsize + /* FIXME: Check sh_addr ? */ + ; +} + +/* Find a section in OBFD that has the same characteristics + as IHEADER. Return the index of this section or SHN_UNDEF if + none can be found. Check's section HINT first, as this is likely + to be the correct section. */ + +static unsigned int +find_link (const bfd * obfd, const Elf_Internal_Shdr * iheader, const unsigned int hint) +{ + Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd); + unsigned int i; + + if (section_match (oheaders[hint], iheader)) + return hint; + + for (i = 1; i < elf_numsections (obfd); i++) + { + Elf_Internal_Shdr * oheader = oheaders[i]; + + if (section_match (oheader, iheader)) + /* FIXME: Do we care if there is a potential for + multiple matches ? */ + return i; + } + + return SHN_UNDEF; +} + +/* PR 19938: Attempt to set the ELF section header fields of an OS or + Processor specific section, based upon a matching input section. + Returns TRUE upon success, FALSE otherwise. */ + +static bfd_boolean +copy_special_section_fields (const bfd *ibfd, + bfd *obfd, + const Elf_Internal_Shdr *iheader, + Elf_Internal_Shdr *oheader, + const unsigned int secnum) +{ + const struct elf_backend_data *bed = get_elf_backend_data (obfd); + const Elf_Internal_Shdr **iheaders = (const Elf_Internal_Shdr **) elf_elfsections (ibfd); + bfd_boolean changed = FALSE; + unsigned int sh_link; + + if (oheader->sh_type == SHT_NOBITS) + { + /* This is a feature for objcopy --only-keep-debug: + When a section's type is changed to NOBITS, we preserve + the sh_link and sh_info fields so that they can be + matched up with the original. + + Note: Strictly speaking these assignments are wrong. + The sh_link and sh_info fields should point to the + relevent sections in the output BFD, which may not be in + the same location as they were in the input BFD. But + the whole point of this action is to preserve the + original values of the sh_link and sh_info fields, so + that they can be matched up with the section headers in + the original file. So strictly speaking we may be + creating an invalid ELF file, but it is only for a file + that just contains debug info and only for sections + without any contents. */ + if (oheader->sh_link == 0) + oheader->sh_link = iheader->sh_link; + if (oheader->sh_info == 0) + oheader->sh_info = iheader->sh_info; + return TRUE; + } + + /* Allow the target a chance to decide how these fields should be set. */ + if (bed->elf_backend_copy_special_section_fields != NULL + && bed->elf_backend_copy_special_section_fields + (ibfd, obfd, iheader, oheader)) + return TRUE; + + /* We have an iheader which might match oheader, and which has non-zero + sh_info and/or sh_link fields. Attempt to follow those links and find + the section in the output bfd which corresponds to the linked section + in the input bfd. */ + if (iheader->sh_link != SHN_UNDEF) + { + sh_link = find_link (obfd, iheaders[iheader->sh_link], iheader->sh_link); + if (sh_link != SHN_UNDEF) + { + oheader->sh_link = sh_link; + changed = TRUE; + } + else + /* FIXME: Should we install iheader->sh_link + if we could not find a match ? */ + (* _bfd_error_handler) + /* xgettext:c-format */ + (_("%B: Failed to find link section for section %d"), obfd, secnum); + } + + if (iheader->sh_info) + { + /* The sh_info field can hold arbitrary information, but if the + SHF_LINK_INFO flag is set then it should be interpreted as a + section index. */ + if (iheader->sh_flags & SHF_INFO_LINK) + { + sh_link = find_link (obfd, iheaders[iheader->sh_info], + iheader->sh_info); + if (sh_link != SHN_UNDEF) + oheader->sh_flags |= SHF_INFO_LINK; + } + else + /* No idea what it means - just copy it. */ + sh_link = iheader->sh_info; + + if (sh_link != SHN_UNDEF) + { + oheader->sh_info = sh_link; + changed = TRUE; + } + else + (* _bfd_error_handler) + /* xgettext:c-format */ + (_("%B: Failed to find info section for section %d"), obfd, secnum); + } + + return changed; +} + /* Copy the program header and other data from one object module to another. */ bfd_boolean _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) { + const Elf_Internal_Shdr **iheaders = (const Elf_Internal_Shdr **) elf_elfsections (ibfd); + Elf_Internal_Shdr **oheaders = elf_elfsections (obfd); + const struct elf_backend_data *bed; + unsigned int i; + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; if (!elf_flags_init (obfd)) @@ -1129,8 +1411,105 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) elf_elfheader (obfd)->e_ident[EI_OSABI] = elf_elfheader (ibfd)->e_ident[EI_OSABI]; + /* If set, copy the EI_ABIVERSION field. */ + if (elf_elfheader (ibfd)->e_ident[EI_ABIVERSION]) + elf_elfheader (obfd)->e_ident[EI_ABIVERSION] + = elf_elfheader (ibfd)->e_ident[EI_ABIVERSION]; + /* Copy object attributes. */ _bfd_elf_copy_obj_attributes (ibfd, obfd); + + if (iheaders == NULL || oheaders == NULL) + return TRUE; + + bed = get_elf_backend_data (obfd); + + /* Possibly copy other fields in the section header. */ + for (i = 1; i < elf_numsections (obfd); i++) + { + unsigned int j; + Elf_Internal_Shdr * oheader = oheaders[i]; + + /* Ignore ordinary sections. SHT_NOBITS sections are considered however + because of a special case need for generating separate debug info + files. See below for more details. */ + if (oheader == NULL + || (oheader->sh_type != SHT_NOBITS + && oheader->sh_type < SHT_LOOS)) + continue; + + /* Ignore empty sections, and sections whose + fields have already been initialised. */ + if (oheader->sh_size == 0 + || (oheader->sh_info != 0 && oheader->sh_link != 0)) + continue; + + /* Scan for the matching section in the input bfd. + First we try for a direct mapping between the input and output sections. */ + for (j = 1; j < elf_numsections (ibfd); j++) + { + const Elf_Internal_Shdr * iheader = iheaders[j]; + + if (iheader == NULL) + continue; + + if (oheader->bfd_section != NULL + && iheader->bfd_section != NULL + && iheader->bfd_section->output_section != NULL + && iheader->bfd_section->output_section == oheader->bfd_section) + { + /* We have found a connection from the input section to the + output section. Attempt to copy the header fields. If + this fails then do not try any further sections - there + should only be a one-to-one mapping between input and output. */ + if (! copy_special_section_fields (ibfd, obfd, iheader, oheader, i)) + j = elf_numsections (ibfd); + break; + } + } + + if (j < elf_numsections (ibfd)) + continue; + + /* That failed. So try to deduce the corresponding input section. + Unfortunately we cannot compare names as the output string table + is empty, so instead we check size, address and type. */ + for (j = 1; j < elf_numsections (ibfd); j++) + { + const Elf_Internal_Shdr * iheader = iheaders[j]; + + if (iheader == NULL) + continue; + + /* Try matching fields in the input section's header. + Since --only-keep-debug turns all non-debug sections into + SHT_NOBITS sections, the output SHT_NOBITS type matches any + input type. */ + if ((oheader->sh_type == SHT_NOBITS + || iheader->sh_type == oheader->sh_type) + && (iheader->sh_flags & ~ SHF_INFO_LINK) + == (oheader->sh_flags & ~ SHF_INFO_LINK) + && iheader->sh_addralign == oheader->sh_addralign + && iheader->sh_entsize == oheader->sh_entsize + && iheader->sh_size == oheader->sh_size + && iheader->sh_addr == oheader->sh_addr + && (iheader->sh_info != oheader->sh_info + || iheader->sh_link != oheader->sh_link)) + { + if (copy_special_section_fields (ibfd, obfd, iheader, oheader, i)) + break; + } + } + + if (j == elf_numsections (ibfd) && oheader->sh_type >= SHT_LOOS) + { + /* Final attempt. Call the backend copy function + with a NULL input section. */ + if (bed->elf_backend_copy_special_section_fields != NULL) + bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader); + } + } + return TRUE; } @@ -1227,8 +1606,13 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg) swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in; extdyn = dynbuf; + /* PR 17512: file: 6f427532. */ + if (s->size < extdynsize) + goto error_return; extdynend = extdyn + s->size; - for (; extdyn < extdynend; extdyn += extdynsize) + /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664. + Fix range check. */ + for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize) { Elf_Internal_Dyn dyn; const char *name = ""; @@ -1396,6 +1780,53 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg) return FALSE; } +/* Get version string. */ + +const char * +_bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol, + bfd_boolean *hidden) +{ + const char *version_string = NULL; + if (elf_dynversym (abfd) != 0 + && (elf_dynverdef (abfd) != 0 || elf_dynverref (abfd) != 0)) + { + unsigned int vernum = ((elf_symbol_type *) symbol)->version; + + *hidden = (vernum & VERSYM_HIDDEN) != 0; + vernum &= VERSYM_VERSION; + + if (vernum == 0) + version_string = ""; + else if (vernum == 1) + version_string = "Base"; + else if (vernum <= elf_tdata (abfd)->cverdefs) + version_string = + elf_tdata (abfd)->verdef[vernum - 1].vd_nodename; + else + { + Elf_Internal_Verneed *t; + + version_string = ""; + for (t = elf_tdata (abfd)->verref; + t != NULL; + t = t->vn_nextref) + { + Elf_Internal_Vernaux *a; + + for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) + { + if (a->vna_other == vernum) + { + version_string = a->vna_nodename; + break; + } + } + } + } + } + return version_string; +} + /* Display ELF-specific fields of a symbol. */ void @@ -1422,6 +1853,8 @@ bfd_elf_print_symbol (bfd *abfd, const struct elf_backend_data *bed; unsigned char st_other; bfd_vma val; + const char *version_string; + bfd_boolean hidden; section_name = symbol->section ? symbol->section->name : "(*none*)"; @@ -1447,45 +1880,12 @@ bfd_elf_print_symbol (bfd *abfd, bfd_fprintf_vma (abfd, file, val); /* If we have version information, print it. */ - if (elf_dynversym (abfd) != 0 - && (elf_dynverdef (abfd) != 0 - || elf_dynverref (abfd) != 0)) + version_string = _bfd_elf_get_symbol_version_string (abfd, + symbol, + &hidden); + if (version_string) { - unsigned int vernum; - const char *version_string; - - vernum = ((elf_symbol_type *) symbol)->version & VERSYM_VERSION; - - if (vernum == 0) - version_string = ""; - else if (vernum == 1) - version_string = "Base"; - else if (vernum <= elf_tdata (abfd)->cverdefs) - version_string = - elf_tdata (abfd)->verdef[vernum - 1].vd_nodename; - else - { - Elf_Internal_Verneed *t; - - version_string = ""; - for (t = elf_tdata (abfd)->verref; - t != NULL; - t = t->vn_nextref) - { - Elf_Internal_Vernaux *a; - - for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) - { - if (a->vna_other == vernum) - { - version_string = a->vna_nodename; - break; - } - } - } - } - - if ((((elf_symbol_type *) symbol)->version & VERSYM_HIDDEN) == 0) + if (!hidden) fprintf (file, " %-11s", version_string); else { @@ -1517,29 +1917,6 @@ bfd_elf_print_symbol (bfd *abfd, break; } } - -/* Allocate an ELF string table--force the first byte to be zero. */ - -struct bfd_strtab_hash * -_bfd_elf_stringtab_init (void) -{ - struct bfd_strtab_hash *ret; - - ret = _bfd_stringtab_init (); - if (ret != NULL) - { - bfd_size_type loc; - - loc = _bfd_stringtab_add (ret, "", TRUE, FALSE); - BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1); - if (loc == (bfd_size_type) -1) - { - _bfd_stringtab_free (ret); - ret = NULL; - } - } - return ret; -} /* ELF .o/exec file reading */ @@ -1552,38 +1929,74 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) Elf_Internal_Ehdr *ehdr; const struct elf_backend_data *bed; const char *name; + bfd_boolean ret = TRUE; + static bfd_boolean * sections_being_created = NULL; + static bfd * sections_being_created_abfd = NULL; + static unsigned int nesting = 0; if (shindex >= elf_numsections (abfd)) return FALSE; + if (++ nesting > 3) + { + /* PR17512: A corrupt ELF binary might contain a recursive group of + sections, with each the string indicies pointing to the next in the + loop. Detect this here, by refusing to load a section that we are + already in the process of loading. We only trigger this test if + we have nested at least three sections deep as normal ELF binaries + can expect to recurse at least once. + + FIXME: It would be better if this array was attached to the bfd, + rather than being held in a static pointer. */ + + if (sections_being_created_abfd != abfd) + sections_being_created = NULL; + if (sections_being_created == NULL) + { + /* FIXME: It would be more efficient to attach this array to the bfd somehow. */ + sections_being_created = (bfd_boolean *) + bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean)); + sections_being_created_abfd = abfd; + } + if (sections_being_created [shindex]) + { + _bfd_error_handler + (_("%B: warning: loop in section dependencies detected"), abfd); + return FALSE; + } + sections_being_created [shindex] = TRUE; + } + hdr = elf_elfsections (abfd)[shindex]; ehdr = elf_elfheader (abfd); name = bfd_elf_string_from_elf_section (abfd, ehdr->e_shstrndx, hdr->sh_name); if (name == NULL) - return FALSE; + goto fail; bed = get_elf_backend_data (abfd); switch (hdr->sh_type) { case SHT_NULL: /* Inactive section. Throw it away. */ - return TRUE; + goto success; - case SHT_PROGBITS: /* Normal section with contents. */ - case SHT_NOBITS: /* .bss section. */ - case SHT_HASH: /* .hash section. */ - case SHT_NOTE: /* .note section. */ + case SHT_PROGBITS: /* Normal section with contents. */ + case SHT_NOBITS: /* .bss section. */ + case SHT_HASH: /* .hash section. */ + case SHT_NOTE: /* .note section. */ case SHT_INIT_ARRAY: /* .init_array section. */ case SHT_FINI_ARRAY: /* .fini_array section. */ case SHT_PREINIT_ARRAY: /* .preinit_array section. */ case SHT_GNU_LIBLIST: /* .gnu.liblist section. */ case SHT_GNU_HASH: /* .gnu.hash section. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_DYNAMIC: /* Dynamic linking information. */ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; + if (hdr->sh_link > elf_numsections (abfd)) { /* PR 10478: Accept Solaris binaries with a sh_link @@ -1597,11 +2010,11 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) break; /* Otherwise fall through. */ default: - return FALSE; + goto fail; } } else if (elf_elfsections (abfd)[hdr->sh_link] == NULL) - return FALSE; + goto fail; else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB) { Elf_Internal_Shdr *dynsymhdr; @@ -1630,28 +2043,39 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) } } } - break; + goto success; - case SHT_SYMTAB: /* A symbol table */ + case SHT_SYMTAB: /* A symbol table. */ if (elf_onesymtab (abfd) == shindex) - return TRUE; + goto success; if (hdr->sh_entsize != bed->s->sizeof_sym) - return FALSE; + goto fail; + if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size) { if (hdr->sh_size != 0) - return FALSE; + goto fail; /* Some assemblers erroneously set sh_info to one with a zero sh_size. ld sees this as a global symbol count of (unsigned) -1. Fix it here. */ hdr->sh_info = 0; - return TRUE; + goto success; + } + + /* PR 18854: A binary might contain more than one symbol table. + Unusual, but possible. Warn, but continue. */ + if (elf_onesymtab (abfd) != 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: warning: multiple symbol tables detected - ignoring the table in section %u"), + abfd, shindex); + goto success; } - BFD_ASSERT (elf_onesymtab (abfd) == 0); elf_onesymtab (abfd) = shindex; - elf_tdata (abfd)->symtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr; + elf_symtab_hdr (abfd) = *hdr; + elf_elfsections (abfd)[shindex] = hdr = & elf_symtab_hdr (abfd); abfd->flags |= HAS_SYMS; /* Sometimes a shared object will map in the symbol table. If @@ -1664,53 +2088,74 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) && (abfd->flags & DYNAMIC) != 0 && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we can't read symbols without that section loaded as well. It is most likely specified by the next section header. */ - if (elf_elfsections (abfd)[elf_symtab_shndx (abfd)]->sh_link != shindex) - { - unsigned int i, num_sec; + { + elf_section_list * entry; + unsigned int i, num_sec; - num_sec = elf_numsections (abfd); - for (i = shindex + 1; i < num_sec; i++) + for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next) + if (entry->hdr.sh_link == shindex) + goto success; + + num_sec = elf_numsections (abfd); + for (i = shindex + 1; i < num_sec; i++) + { + Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; + + if (hdr2->sh_type == SHT_SYMTAB_SHNDX + && hdr2->sh_link == shindex) + break; + } + + if (i == num_sec) + for (i = 1; i < shindex; i++) { Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; + if (hdr2->sh_type == SHT_SYMTAB_SHNDX && hdr2->sh_link == shindex) break; } - if (i == num_sec) - for (i = 1; i < shindex; i++) - { - Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; - if (hdr2->sh_type == SHT_SYMTAB_SHNDX - && hdr2->sh_link == shindex) - break; - } - if (i != shindex) - return bfd_section_from_shdr (abfd, i); - } - return TRUE; - case SHT_DYNSYM: /* A dynamic symbol table */ + if (i != shindex) + ret = bfd_section_from_shdr (abfd, i); + /* else FIXME: we have failed to find the symbol table - should we issue an error ? */ + goto success; + } + + case SHT_DYNSYM: /* A dynamic symbol table. */ if (elf_dynsymtab (abfd) == shindex) - return TRUE; + goto success; if (hdr->sh_entsize != bed->s->sizeof_sym) - return FALSE; + goto fail; + if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size) { if (hdr->sh_size != 0) - return FALSE; + goto fail; + /* Some linkers erroneously set sh_info to one with a zero sh_size. ld sees this as a global symbol count of (unsigned) -1. Fix it here. */ hdr->sh_info = 0; - return TRUE; + goto success; + } + + /* PR 18854: A binary might contain more than one dynamic symbol table. + Unusual, but possible. Warn, but continue. */ + if (elf_dynsymtab (abfd) != 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: warning: multiple dynamic symbol tables detected - ignoring the table in section %u"), + abfd, shindex); + goto success; } - BFD_ASSERT (elf_dynsymtab (abfd) == 0); elf_dynsymtab (abfd) = shindex; elf_tdata (abfd)->dynsymtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynsymtab_hdr; @@ -1718,34 +2163,47 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) /* Besides being a symbol table, we also treat this as a regular section, so that objcopy can handle it. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); - - case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections */ - if (elf_symtab_shndx (abfd) == shindex) - return TRUE; + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; - BFD_ASSERT (elf_symtab_shndx (abfd) == 0); - elf_symtab_shndx (abfd) = shindex; - elf_tdata (abfd)->symtab_shndx_hdr = *hdr; - elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr; - return TRUE; + case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections. */ + { + elf_section_list * entry; + + for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next) + if (entry->ndx == shindex) + goto success; + + entry = bfd_alloc (abfd, sizeof * entry); + if (entry == NULL) + goto fail; + entry->ndx = shindex; + entry->hdr = * hdr; + entry->next = elf_symtab_shndx_list (abfd); + elf_symtab_shndx_list (abfd) = entry; + elf_elfsections (abfd)[shindex] = & entry->hdr; + goto success; + } - case SHT_STRTAB: /* A string table */ + case SHT_STRTAB: /* A string table. */ if (hdr->bfd_section != NULL) - return TRUE; + goto success; + if (ehdr->e_shstrndx == shindex) { elf_tdata (abfd)->shstrtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr; - return TRUE; + goto success; } + if (elf_elfsections (abfd)[elf_onesymtab (abfd)]->sh_link == shindex) { symtab_strtab: elf_tdata (abfd)->strtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr; - return TRUE; + goto success; } + if (elf_elfsections (abfd)[elf_dynsymtab (abfd)]->sh_link == shindex) { dynsymtab_strtab: @@ -1754,8 +2212,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) elf_elfsections (abfd)[shindex] = hdr; /* We also treat this as a regular section, so that objcopy can handle it. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; } /* If the string table isn't one of the above, then treat it as a @@ -1773,9 +2232,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) { /* Prevent endless recursion on broken objects. */ if (i == shindex) - return FALSE; + goto fail; if (! bfd_section_from_shdr (abfd, i)) - return FALSE; + goto fail; if (elf_onesymtab (abfd) == i) goto symtab_strtab; if (elf_dynsymtab (abfd) == i) @@ -1783,7 +2242,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) } } } - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_REL: case SHT_RELA: @@ -1793,21 +2253,22 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) Elf_Internal_Shdr *hdr2, **p_hdr; unsigned int num_sec = elf_numsections (abfd); struct bfd_elf_section_data *esdt; - bfd_size_type amt; if (hdr->sh_entsize != (bfd_size_type) (hdr->sh_type == SHT_REL ? bed->s->sizeof_rel : bed->s->sizeof_rela)) - return FALSE; + goto fail; /* Check for a bogus link to avoid crashing. */ if (hdr->sh_link >= num_sec) { - ((*_bfd_error_handler) - (_("%B: invalid link %lu for reloc section %s (index %u)"), - abfd, hdr->sh_link, name, shindex)); - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: invalid link %lu for reloc section %s (index %u)"), + abfd, hdr->sh_link, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; } /* For some incomprehensible reason Oracle distributes @@ -1848,7 +2309,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) if ((elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB || elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_DYNSYM) && ! bfd_section_from_shdr (abfd, hdr->sh_link)) - return FALSE; + goto fail; /* If this reloc section does not use the main symbol table we don't treat it as a reloc section. BFD can't adequately @@ -1863,14 +2324,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) || hdr->sh_info >= num_sec || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA) - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + { + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; + } if (! bfd_section_from_shdr (abfd, hdr->sh_info)) - return FALSE; + goto fail; + target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info); if (target_sect == NULL) - return FALSE; + goto fail; esdt = elf_section_data (target_sect); if (hdr->sh_type == SHT_RELA) @@ -1878,11 +2343,12 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) else p_hdr = &esdt->rel.hdr; - BFD_ASSERT (*p_hdr == NULL); - amt = sizeof (*hdr2); - hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); + /* PR 17512: file: 0b4f81b7. */ + if (*p_hdr != NULL) + goto fail; + hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2)); if (hdr2 == NULL) - return FALSE; + goto fail; *hdr2 = *hdr; *p_hdr = hdr2; elf_elfsections (abfd)[shindex] = hdr2; @@ -1898,46 +2364,55 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) target_sect->use_rela_p = 1; } abfd->flags |= HAS_RELOC; - return TRUE; + goto success; } case SHT_GNU_verdef: elf_dynverdef (abfd) = shindex; elf_tdata (abfd)->dynverdef_hdr = *hdr; - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_GNU_versym: if (hdr->sh_entsize != sizeof (Elf_External_Versym)) - return FALSE; + goto fail; + elf_dynversym (abfd) = shindex; elf_tdata (abfd)->dynversym_hdr = *hdr; - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_GNU_verneed: elf_dynverref (abfd) = shindex; elf_tdata (abfd)->dynverref_hdr = *hdr; - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_SHLIB: - return TRUE; + goto success; case SHT_GROUP: if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE)) - return FALSE; + goto fail; + if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; + if (hdr->contents != NULL) { Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents; - unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE; + unsigned int n_elt = hdr->sh_size / sizeof (* idx); asection *s; + if (n_elt == 0) + goto fail; if (idx->flags & GRP_COMDAT) hdr->bfd_section->flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD; /* We try to keep the same section order as it comes in. */ idx += n_elt; + while (--n_elt != 0) { --idx; @@ -1951,7 +2426,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) } } } - break; + goto success; default: /* Possibly an attributes section. */ @@ -1959,33 +2434,38 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) || hdr->sh_type == bed->obj_attrs_section_type) { if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; _bfd_elf_parse_attributes (abfd, hdr); - return TRUE; + goto success; } /* Check for any processor-specific section types. */ if (bed->elf_backend_section_from_shdr (abfd, hdr, name, shindex)) - return TRUE; + goto success; if (hdr->sh_type >= SHT_LOUSER && hdr->sh_type <= SHT_HIUSER) { if ((hdr->sh_flags & SHF_ALLOC) != 0) /* FIXME: How to properly handle allocated section reserved for applications? */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: don't know how to handle allocated, application " "specific section `%s' [0x%8x]"), abfd, name, hdr->sh_type); else - /* Allow sections reserved for applications. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + { + /* Allow sections reserved for applications. */ + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; + } } else if (hdr->sh_type >= SHT_LOPROC && hdr->sh_type <= SHT_HIPROC) /* FIXME: We should handle this section. */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: don't know how to handle processor specific section " "`%s' [0x%8x]"), abfd, name, hdr->sh_type); @@ -1996,24 +2476,39 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) /* SHF_OS_NONCONFORMING indicates that special knowledge is required to correctly process the section and the file should be rejected with an error message. */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: don't know how to handle OS specific section " "`%s' [0x%8x]"), abfd, name, hdr->sh_type); else - /* Otherwise it should be processed. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + { + /* Otherwise it should be processed. */ + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; + } } else /* FIXME: We should handle this section. */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: don't know how to handle section `%s' [0x%8x]"), abfd, name, hdr->sh_type); - return FALSE; + goto fail; } - return TRUE; + fail: + ret = FALSE; + success: + if (sections_being_created && sections_being_created_abfd == abfd) + sections_being_created [shindex] = FALSE; + if (-- nesting == 0) + { + sections_being_created = NULL; + sections_being_created_abfd = abfd; + } + return ret; } /* Return the local symbol specified by ABFD, R_SYMNDX. */ @@ -2520,6 +3015,27 @@ _bfd_elf_single_rel_hdr (asection *sec) return elf_section_data (sec)->rela.hdr; } +static bfd_boolean +_bfd_elf_set_reloc_sh_name (bfd *abfd, + Elf_Internal_Shdr *rel_hdr, + const char *sec_name, + bfd_boolean use_rela_p) +{ + char *name = (char *) bfd_alloc (abfd, + sizeof ".rela" + strlen (sec_name)); + if (name == NULL) + return FALSE; + + sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", sec_name); + rel_hdr->sh_name = + (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name, + FALSE); + if (rel_hdr->sh_name == (unsigned int) -1) + return FALSE; + + return TRUE; +} + /* Allocate and initialize a section-header for a new reloc section, containing relocations against ASECT. It is stored in RELDATA. If USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL @@ -2528,28 +3044,21 @@ _bfd_elf_single_rel_hdr (asection *sec) static bfd_boolean _bfd_elf_init_reloc_shdr (bfd *abfd, struct bfd_elf_section_reloc_data *reldata, - asection *asect, - bfd_boolean use_rela_p) + const char *sec_name, + bfd_boolean use_rela_p, + bfd_boolean delay_st_name_p) { Elf_Internal_Shdr *rel_hdr; - char *name; const struct elf_backend_data *bed = get_elf_backend_data (abfd); - bfd_size_type amt; - amt = sizeof (Elf_Internal_Shdr); BFD_ASSERT (reldata->hdr == NULL); - rel_hdr = bfd_zalloc (abfd, amt); + rel_hdr = bfd_zalloc (abfd, sizeof (*rel_hdr)); reldata->hdr = rel_hdr; - amt = sizeof ".rela" + strlen (asect->name); - name = (char *) bfd_alloc (abfd, amt); - if (name == NULL) - return FALSE; - sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name); - rel_hdr->sh_name = - (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name, - FALSE); - if (rel_hdr->sh_name == (unsigned int) -1) + if (delay_st_name_p) + rel_hdr->sh_name = (unsigned int) -1; + else if (!_bfd_elf_set_reloc_sh_name (abfd, rel_hdr, sec_name, + use_rela_p)) return FALSE; rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL; rel_hdr->sh_entsize = (use_rela_p @@ -2591,6 +3100,8 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) struct bfd_elf_section_data *esd = elf_section_data (asect); Elf_Internal_Shdr *this_hdr; unsigned int sh_type; + const char *name = asect->name; + bfd_boolean delay_st_name_p = FALSE; if (arg->failed) { @@ -2601,12 +3112,72 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) this_hdr = &esd->this_hdr; - this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), - asect->name, FALSE); - if (this_hdr->sh_name == (unsigned int) -1) + if (arg->link_info) { - arg->failed = TRUE; - return; + /* ld: compress DWARF debug sections with names: .debug_*. */ + if ((arg->link_info->compress_debug & COMPRESS_DEBUG) + && (asect->flags & SEC_DEBUGGING) + && name[1] == 'd' + && name[6] == '_') + { + /* Set SEC_ELF_COMPRESS to indicate this section should be + compressed. */ + asect->flags |= SEC_ELF_COMPRESS; + + /* If this section will be compressed, delay adding section + name to section name section after it is compressed in + _bfd_elf_assign_file_positions_for_non_load. */ + delay_st_name_p = TRUE; + } + } + else if ((asect->flags & SEC_ELF_RENAME)) + { + /* objcopy: rename output DWARF debug section. */ + if ((abfd->flags & (BFD_DECOMPRESS | BFD_COMPRESS_GABI))) + { + /* When we decompress or compress with SHF_COMPRESSED, + convert section name from .zdebug_* to .debug_* if + needed. */ + if (name[1] == 'z') + { + char *new_name = convert_zdebug_to_debug (abfd, name); + if (new_name == NULL) + { + arg->failed = TRUE; + return; + } + name = new_name; + } + } + else if (asect->compress_status == COMPRESS_SECTION_DONE) + { + /* PR binutils/18087: Compression does not always make a + section smaller. So only rename the section when + compression has actually taken place. If input section + name is .zdebug_*, we should never compress it again. */ + char *new_name = convert_debug_to_zdebug (abfd, name); + if (new_name == NULL) + { + arg->failed = TRUE; + return; + } + BFD_ASSERT (name[1] != 'z'); + name = new_name; + } + } + + if (delay_st_name_p) + this_hdr->sh_name = (unsigned int) -1; + else + { + this_hdr->sh_name + = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), + name, FALSE); + if (this_hdr->sh_name == (unsigned int) -1) + { + arg->failed = TRUE; + return; + } } /* Don't clear sh_flags. Assembler may set additional bits. */ @@ -2620,6 +3191,16 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) this_hdr->sh_offset = 0; this_hdr->sh_size = asect->size; this_hdr->sh_link = 0; + /* PR 17512: file: 0eb809fe, 8b0535ee. */ + if (asect->alignment_power >= (sizeof (bfd_vma) * 8) - 1) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%B: error: Alignment power %d of section `%A' is too big"), + abfd, asect, asect->alignment_power); + arg->failed = TRUE; + return; + } this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power; /* The sh_entsize and sh_info fields may have been set already by copy_private_section_data. */ @@ -2644,7 +3225,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) allow the link to proceed. This can happen when users link non-bss input sections to bss output sections, or emit data to a bss output section via a linker script. */ - (*_bfd_error_handler) + _bfd_error_handler (_("warning: section `%A' type changed to PROGBITS"), asect); this_hdr->sh_type = sh_type; } @@ -2655,14 +3236,17 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) break; case SHT_STRTAB: - case SHT_INIT_ARRAY: - case SHT_FINI_ARRAY: - case SHT_PREINIT_ARRAY: case SHT_NOTE: case SHT_NOBITS: case SHT_PROGBITS: break; + case SHT_INIT_ARRAY: + case SHT_FINI_ARRAY: + case SHT_PREINIT_ARRAY: + this_hdr->sh_entsize = bed->s->arch_size / 8; + break; + case SHT_HASH: this_hdr->sh_entsize = bed->s->sizeof_hash_entry; break; @@ -2732,9 +3316,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) { this_hdr->sh_flags |= SHF_MERGE; this_hdr->sh_entsize = asect->entsize; - if ((asect->flags & SEC_STRINGS) != 0) - this_hdr->sh_flags |= SHF_STRINGS; } + if ((asect->flags & SEC_STRINGS) != 0) + this_hdr->sh_flags |= SHF_STRINGS; if ((asect->flags & SEC_GROUP) == 0 && elf_group_name (asect) != NULL) this_hdr->sh_flags |= SHF_GROUP; if ((asect->flags & SEC_THREAD_LOCAL) != 0) @@ -2768,16 +3352,19 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) if (arg->link_info /* Do the normal setup if we wouldn't create any sections here. */ && esd->rel.count + esd->rela.count > 0 - && (arg->link_info->relocatable || arg->link_info->emitrelocations)) + && (bfd_link_relocatable (arg->link_info) + || arg->link_info->emitrelocations)) { if (esd->rel.count && esd->rel.hdr == NULL - && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, asect, FALSE)) + && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, name, FALSE, + delay_st_name_p)) { arg->failed = TRUE; return; } if (esd->rela.count && esd->rela.hdr == NULL - && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, asect, TRUE)) + && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, name, TRUE, + delay_st_name_p)) { arg->failed = TRUE; return; @@ -2786,8 +3373,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) else if (!_bfd_elf_init_reloc_shdr (abfd, (asect->use_rela_p ? &esd->rela : &esd->rel), - asect, - asect->use_rela_p)) + name, + asect->use_rela_p, + delay_st_name_p)) arg->failed = TRUE; } @@ -2847,12 +3435,19 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) /* The ELF backend linker sets sh_info to -2 when the group signature symbol is global, and thus the index can't be set until all local symbols are output. */ - asection *igroup = elf_sec_group (elf_next_in_group (sec)); - struct bfd_elf_section_data *sec_data = elf_section_data (igroup); - unsigned long symndx = sec_data->this_hdr.sh_info; - unsigned long extsymoff = 0; + asection *igroup; + struct bfd_elf_section_data *sec_data; + unsigned long symndx; + unsigned long extsymoff; struct elf_link_hash_entry *h; + /* The point of this little dance to the first SHF_GROUP section + then back to the SHT_GROUP section is that this gets us to + the SHT_GROUP in the input object. */ + igroup = elf_sec_group (elf_next_in_group (sec)); + sec_data = elf_section_data (igroup); + symndx = sec_data->this_hdr.sh_info; + extsymoff = 0; if (!elf_bad_symtab (igroup->owner)) { Elf_Internal_Shdr *symtab_hdr; @@ -2921,6 +3516,48 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc); } +/* Return the section which RELOC_SEC applies to. */ + +asection * +_bfd_elf_get_reloc_section (asection *reloc_sec) +{ + const char *name; + unsigned int type; + bfd *abfd; + + if (reloc_sec == NULL) + return NULL; + + type = elf_section_data (reloc_sec)->this_hdr.sh_type; + if (type != SHT_REL && type != SHT_RELA) + return NULL; + + /* We look up the section the relocs apply to by name. */ + name = reloc_sec->name; + if (type == SHT_REL) + name += 4; + else + name += 5; + + /* If a target needs .got.plt section, relocations in rela.plt/rel.plt + section apply to .got.plt section. */ + abfd = reloc_sec->owner; + if (get_elf_backend_data (abfd)->want_got_plt + && strcmp (name, ".plt") == 0) + { + /* .got.plt is a linker created input section. It may be mapped + to some other output section. Try two likely sections. */ + name = ".got.plt"; + reloc_sec = bfd_get_section_by_name (abfd, name); + if (reloc_sec != NULL) + return reloc_sec; + name = ".got"; + } + + reloc_sec = bfd_get_section_by_name (abfd, name); + return reloc_sec; +} + /* Assign all ELF section numbers. The dummy first section is handled here too. The link/info pointers for the standard section types are filled in here too, while we're at it. */ @@ -2930,7 +3567,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) { struct elf_obj_tdata *t = elf_tdata (abfd); asection *sec; - unsigned int section_number, secn; + unsigned int section_number; Elf_Internal_Shdr **i_shdrp; struct bfd_elf_section_data *d; bfd_boolean need_symtab; @@ -2940,8 +3577,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) _bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd)); /* SHT_GROUP sections are in relocatable files only. */ - if (link_info == NULL || link_info->relocatable) + if (link_info == NULL || bfd_link_relocatable (link_info)) { + size_t reloc_count = 0; + /* Put SHT_GROUP sections first. */ for (sec = abfd->sections; sec != NULL; sec = sec->next) { @@ -2958,7 +3597,14 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) else d->this_idx = section_number++; } + + /* Count relocations. */ + reloc_count += sec->reloc_count; } + + /* Clear HAS_RELOC if there are no relocations. */ + if (reloc_count == 0) + abfd->flags &= ~HAS_RELOC; } for (sec = abfd->sections; sec; sec = sec->next) @@ -2967,11 +3613,13 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) if (d->this_hdr.sh_type != SHT_GROUP) d->this_idx = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name); + if (d->this_hdr.sh_name != (unsigned int) -1) + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name); if (d->rel.hdr) { d->rel.idx = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name); + if (d->rel.hdr->sh_name != (unsigned int) -1) + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name); } else d->rel.idx = 0; @@ -2979,16 +3627,13 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) if (d->rela.hdr) { d->rela.idx = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name); + if (d->rela.hdr->sh_name != (unsigned int) -1) + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name); } else d->rela.idx = 0; } - elf_shstrtab_sec (abfd) = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name); - elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd); - need_symtab = (bfd_get_symcount (abfd) > 0 || (link_info == NULL && ((abfd->flags & (EXEC_P | DYNAMIC | HAS_RELOC)) @@ -2999,27 +3644,35 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name); if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF)) { - elf_symtab_shndx (abfd) = section_number++; - t->symtab_shndx_hdr.sh_name + elf_section_list * entry; + + BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL); + + entry = bfd_zalloc (abfd, sizeof * entry); + entry->ndx = section_number++; + elf_symtab_shndx_list (abfd) = entry; + entry->hdr.sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), ".symtab_shndx", FALSE); - if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1) + if (entry->hdr.sh_name == (unsigned int) -1) return FALSE; } elf_strtab_sec (abfd) = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name); } + elf_shstrtab_sec (abfd) = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name); + elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd); + if (section_number >= SHN_LORESERVE) { + /* xgettext:c-format */ _bfd_error_handler (_("%B: too many sections: %u"), abfd, section_number); return FALSE; } - _bfd_elf_strtab_finalize (elf_shstrtab (abfd)); - t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); - elf_numsections (abfd) = section_number; elf_elfheader (abfd)->e_shnum = section_number; @@ -3046,8 +3699,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr; if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF)) { - i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr; - t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd); + elf_section_list * entry = elf_symtab_shndx_list (abfd); + BFD_ASSERT (entry != NULL); + i_shdrp[entry->ndx] = & entry->hdr; + entry->hdr.sh_link = elf_onesymtab (abfd); } i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr; t->symtab_hdr.sh_link = elf_strtab_sec (abfd); @@ -3056,7 +3711,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) for (sec = abfd->sections; sec; sec = sec->next) { asection *s; - const char *name; d = elf_section_data (sec); @@ -3097,7 +3751,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) if (discarded_section (s)) { asection *kept; - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"), abfd, d->this_hdr.bfd_section, s, s->owner); @@ -3120,7 +3775,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) /* Handle objcopy. */ if (s->output_section == NULL) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: sh_link of section `%A' points to removed section `%A' of `%B'"), abfd, d->this_hdr.bfd_section, s, s->owner); bfd_set_error (bfd_error_bad_value); @@ -3141,6 +3797,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) = get_elf_backend_data (abfd); if (bed->link_order_error_handler) bed->link_order_error_handler + /* xgettext:c-format */ (_("%B: warning: sh_link not set for section `%A'"), abfd, sec); } @@ -3160,13 +3817,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) if (s != NULL) d->this_hdr.sh_link = elf_section_data (s)->this_idx; - /* We look up the section the relocs apply to by name. */ - name = sec->name; - if (d->this_hdr.sh_type == SHT_REL) - name += 4; - else - name += 5; - s = bfd_get_section_by_name (abfd, name); + s = get_elf_backend_data (abfd)->get_reloc_section (sec); if (s != NULL) { d->this_hdr.sh_info = elf_section_data (s)->this_idx; @@ -3242,12 +3893,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) } } - for (secn = 1; secn < section_number; ++secn) - if (i_shdrp[secn] == NULL) - i_shdrp[secn] = i_shdrp[0]; - else - i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd), - i_shdrp[secn]->sh_name); + /* Delay setting sh_name to _bfd_elf_write_object_contents so that + _bfd_elf_assign_file_positions_for_non_load can convert DWARF + debug section name from .debug_* to .zdebug_* if needed. */ + return TRUE; } @@ -3264,6 +3913,44 @@ sym_is_global (bfd *abfd, asymbol *sym) || bfd_is_com_section (bfd_get_section (sym))); } +/* Filter global symbols of ABFD to include in the import library. All + SYMCOUNT symbols of ABFD can be examined from their pointers in + SYMS. Pointers of symbols to keep should be stored contiguously at + the beginning of that array. + + Returns the number of symbols to keep. */ + +unsigned int +_bfd_elf_filter_global_symbols (bfd *abfd, struct bfd_link_info *info, + asymbol **syms, long symcount) +{ + long src_count, dst_count = 0; + + for (src_count = 0; src_count < symcount; src_count++) + { + asymbol *sym = syms[src_count]; + char *name = (char *) bfd_asymbol_name (sym); + struct bfd_link_hash_entry *h; + + if (!sym_is_global (abfd, sym)) + continue; + + h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE); + if (h == NULL) + continue; + if (h->type != bfd_link_hash_defined && h->type != bfd_link_hash_defweak) + continue; + if (h->linker_def || h->ldscript_def) + continue; + + syms[dst_count++] = sym; + } + + syms[dst_count] = NULL; + + return dst_count; +} + /* Don't output section symbols for sections that are not going to be output, that are duplicates or there is no BFD section. */ @@ -3298,7 +3985,7 @@ elf_map_symbols (bfd *abfd, unsigned int *pnum_locals) unsigned int num_globals = 0; unsigned int num_locals2 = 0; unsigned int num_globals2 = 0; - int max_index = 0; + unsigned int max_index = 0; unsigned int idx; asection *asect; asymbol **new_syms; @@ -3447,7 +4134,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, const struct elf_backend_data *bed = get_elf_backend_data (abfd); struct fake_section_arg fsargs; bfd_boolean failed; - struct bfd_strtab_hash *strtab = NULL; + struct elf_strtab_hash *strtab = NULL; Elf_Internal_Shdr *shstrtab_hdr; bfd_boolean need_symtab; @@ -3498,13 +4185,13 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr; /* sh_name was set in prep_headers. */ shstrtab_hdr->sh_type = SHT_STRTAB; - shstrtab_hdr->sh_flags = 0; + shstrtab_hdr->sh_flags = bed->elf_strtab_flags; shstrtab_hdr->sh_addr = 0; - shstrtab_hdr->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); + /* sh_size is set in _bfd_elf_assign_file_positions_for_non_load. */ shstrtab_hdr->sh_entsize = 0; shstrtab_hdr->sh_link = 0; shstrtab_hdr->sh_info = 0; - /* sh_offset is set in assign_file_positions_except_relocs. */ + /* sh_offset is set in _bfd_elf_assign_file_positions_for_non_load. */ shstrtab_hdr->sh_addralign = 1; if (!assign_file_positions_except_relocs (abfd, link_info)) @@ -3517,12 +4204,16 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, off = elf_next_file_pos (abfd); - hdr = &elf_tdata (abfd)->symtab_hdr; + hdr = & elf_symtab_hdr (abfd); off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); - hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (hdr->sh_size != 0) - off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); + if (elf_symtab_shndx_list (abfd) != NULL) + { + hdr = & elf_symtab_shndx_list (abfd)->hdr; + if (hdr->sh_size != 0) + off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); + /* FIXME: What about other symtab_shndx sections in the list ? */ + } hdr = &elf_tdata (abfd)->strtab_hdr; off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); @@ -3532,9 +4223,9 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, /* Now that we know where the .strtab section goes, write it out. */ if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 - || ! _bfd_stringtab_emit (abfd, strtab)) + || ! _bfd_elf_strtab_emit (abfd, strtab)) return FALSE; - _bfd_stringtab_free (strtab); + _bfd_elf_strtab_free (strtab); } abfd->output_has_begun = TRUE; @@ -3747,7 +4438,10 @@ elf_modify_segment_map (bfd *abfd, } (*m)->count = new_count; - if (remove_empty_load && (*m)->p_type == PT_LOAD && (*m)->count == 0) + if (remove_empty_load + && (*m)->p_type == PT_LOAD + && (*m)->count == 0 + && !(*m)->includes_phdrs) *m = (*m)->next; else m = &(*m)->next; @@ -3797,6 +4491,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) asection *dynsec, *eh_frame_hdr; bfd_size_type amt; bfd_vma addr_mask, wrap_to = 0; + bfd_boolean linker_created_pt_phdr_segment = FALSE; /* Select the allocated sections, and sort them. */ @@ -3849,7 +4544,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) m->p_flags = PF_R | PF_X; m->p_flags_valid = 1; m->includes_phdrs = 1; - + linker_created_pt_phdr_segment = TRUE; *pm = m; pm = &m->next; @@ -3873,6 +4568,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) last_size = 0; phdr_index = 0; maxpagesize = bed->maxpagesize; + /* PR 17512: file: c8455299. + Avoid divide-by-zero errors later on. + FIXME: Should we abort if the maxpagesize is zero ? */ + if (maxpagesize == 0) + maxpagesize = 1; writable = FALSE; dynsec = bfd_get_section_by_name (abfd, ".dynamic"); if (dynsec != NULL @@ -3895,7 +4595,19 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) || ((sections[0]->lma & addr_mask) % maxpagesize < phdr_size % maxpagesize) || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to) - phdr_in_segment = FALSE; + { + /* PR 20815: The ELF standard says that a PT_PHDR segment, if + present, must be included as part of the memory image of the + program. Ie it must be part of a PT_LOAD segment as well. + If we have had to create our own PT_PHDR segment, but it is + not going to be covered by the first PT_LOAD segment, then + force the inclusion if we can... */ + if ((abfd->flags & D_PAGED) != 0 + && linker_created_pt_phdr_segment) + phdr_in_segment = TRUE; + else + phdr_in_segment = FALSE; + } } for (i = 0, hdrpp = sections; i < count; i++, hdrpp++) @@ -3943,11 +4655,18 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) new_segment = TRUE; } else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0 - && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0) + && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0 + && ((abfd->flags & D_PAGED) == 0 + || (((last_hdr->lma + last_size - 1) & -maxpagesize) + != (hdr->lma & -maxpagesize)))) { - /* We don't want to put a loadable section after a - nonloadable section in the same segment. - Consider .tbss sections as loadable for this purpose. */ + /* We don't want to put a loaded section after a + nonloaded (ie. bss style) section in the same segment + as that will force the non-loaded section to be loaded. + Consider .tbss sections as loaded for this purpose. + However, like the writable/non-writable case below, + if they are on the same page then they must be put + in the same segment. */ new_segment = TRUE; } else if ((abfd->flags & D_PAGED) == 0) @@ -4218,9 +4937,6 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) goto error_return; m->next = NULL; m->p_type = PT_GNU_RELRO; - m->p_flags = PF_R; - m->p_flags_valid = 1; - *pm = m; pm = &m->next; } @@ -4615,9 +5331,11 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_memsz = bed->s->sizeof_ehdr; if (m->count > 0) { - if (p->p_vaddr < (bfd_vma) off) + if (p->p_vaddr < (bfd_vma) off + || (!m->p_paddr_valid + && p->p_paddr < (bfd_vma) off)) { - (*_bfd_error_handler) + _bfd_error_handler (_("%B: Not enough room for program headers, try linking with -N"), abfd); bfd_set_error (bfd_error_bad_value); @@ -4703,7 +5421,8 @@ assign_file_positions_for_load_sections (bfd *abfd, && (s_start < p_end || p_end < p_start)) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec, (unsigned long) s_start, (unsigned long) p_end); adjust = 0; @@ -4839,7 +5558,8 @@ assign_file_positions_for_load_sections (bfd *abfd, if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0) && !ELF_TBSS_SPECIAL (this_hdr, p)) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: section `%A' can't be allocated in segment %d"), abfd, sec, j); print_segment_map (m); @@ -4860,7 +5580,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, { const struct elf_backend_data *bed = get_elf_backend_data (abfd); Elf_Internal_Shdr **i_shdrpp; - Elf_Internal_Shdr **hdrpp; + Elf_Internal_Shdr **hdrpp, **end_hdrpp; Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; struct elf_segment_map *m; @@ -4868,14 +5588,12 @@ assign_file_positions_for_non_load_sections (bfd *abfd, bfd_vma filehdr_vaddr, filehdr_paddr; bfd_vma phdrs_vaddr, phdrs_paddr; file_ptr off; - unsigned int num_sec; - unsigned int i; unsigned int count; i_shdrpp = elf_elfsections (abfd); - num_sec = elf_numsections (abfd); + end_hdrpp = i_shdrpp + elf_numsections (abfd); off = elf_next_file_pos (abfd); - for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++) + for (hdrpp = i_shdrpp + 1; hdrpp < end_hdrpp; hdrpp++) { Elf_Internal_Shdr *hdr; @@ -4888,7 +5606,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd, else if ((hdr->sh_flags & SHF_ALLOC) != 0) { if (hdr->sh_size != 0) - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: warning: allocated section `%s' not in segment"), abfd, (hdr->bfd_section == NULL @@ -4906,9 +5625,14 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) + || (hdr->bfd_section != NULL + && (hdr->bfd_section->flags & SEC_ELF_COMPRESS)) + /* Compress DWARF debug sections. */ || hdr == i_shdrpp[elf_onesymtab (abfd)] - || hdr == i_shdrpp[elf_symtab_shndx (abfd)] - || hdr == i_shdrpp[elf_strtab_sec (abfd)]) + || (elf_symtab_shndx_list (abfd) != NULL + && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx]) + || hdr == i_shdrpp[elf_strtab_sec (abfd)] + || hdr == i_shdrpp[elf_shstrtab_sec (abfd)]) hdr->sh_offset = -1; else off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); @@ -5049,7 +5773,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, if (!m->p_align_valid) p->p_align = 1; if (!m->p_flags_valid) - p->p_flags = (lp->p_flags & ~PF_W); + p->p_flags = PF_R; } else { @@ -5064,11 +5788,28 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } else if (m->count != 0) { + unsigned int i; + if (p->p_type != PT_LOAD && (p->p_type != PT_NOTE || bfd_get_format (abfd) != bfd_core)) { - BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs); + /* A user specified segment layout may include a PHDR + segment that overlaps with a LOAD segment... */ + if (p->p_type == PT_PHDR) + { + m->count = 0; + continue; + } + + if (m->includes_filehdr || m->includes_phdrs) + { + /* PR 17512: file: 2195325e. */ + _bfd_error_handler + (_("%B: error: non-load segment %d includes file header and/or program header"), + abfd, (int)(p - phdrs)); + return FALSE; + } p->p_filesz = 0; p->p_offset = m->sections[0]->filepos; @@ -5104,6 +5845,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd, return TRUE; } +static elf_section_list * +find_section_in_list (unsigned int i, elf_section_list * list) +{ + for (;list != NULL; list = list->next) + if (list->ndx == i) + break; + return list; +} + /* Work out the file positions of all the sections. This is called by _bfd_elf_compute_section_file_positions. All the section sizes and VMAs must be known before this is called. @@ -5124,7 +5874,6 @@ assign_file_positions_except_relocs (bfd *abfd, { struct elf_obj_tdata *tdata = elf_tdata (abfd); Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); - file_ptr off; const struct elf_backend_data *bed = get_elf_backend_data (abfd); if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 @@ -5134,6 +5883,7 @@ assign_file_positions_except_relocs (bfd *abfd, unsigned int num_sec = elf_numsections (abfd); Elf_Internal_Shdr **hdrpp; unsigned int i; + file_ptr off; /* Start after the ELF header. */ off = i_ehdrp->e_ehsize; @@ -5148,15 +5898,22 @@ assign_file_positions_except_relocs (bfd *abfd, hdr = *hdrpp; if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) + || (hdr->bfd_section != NULL + && (hdr->bfd_section->flags & SEC_ELF_COMPRESS)) + /* Compress DWARF debug sections. */ || i == elf_onesymtab (abfd) - || i == elf_symtab_shndx (abfd) - || i == elf_strtab_sec (abfd)) + || (elf_symtab_shndx_list (abfd) != NULL + && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx]) + || i == elf_strtab_sec (abfd) + || i == elf_shstrtab_sec (abfd)) { hdr->sh_offset = -1; } else off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); } + + elf_next_file_pos (abfd) = off; } else { @@ -5178,9 +5935,7 @@ assign_file_positions_except_relocs (bfd *abfd, } /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. */ - if (link_info != NULL - && link_info->executable - && link_info->shared) + if (link_info != NULL && bfd_link_pie (link_info)) { unsigned int num_segments = elf_elfheader (abfd)->e_phnum; Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr; @@ -5200,20 +5955,44 @@ assign_file_positions_except_relocs (bfd *abfd, /* Write out the program headers. */ alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr; + + /* Sort the program headers into the ordering required by the ELF standard. */ + if (alloc == 0) + return TRUE; + + /* PR ld/20815 - Check that the program header segment, if present, will + be loaded into memory. FIXME: The check below is not sufficient as + really all PT_LOAD segments should be checked before issuing an error + message. Plus the PHDR segment does not have to be the first segment + in the program header table. But this version of the check should + catch all real world use cases. + + FIXME: We used to have code here to sort the PT_LOAD segments into + ascending order, as per the ELF spec. But this breaks some programs, + including the Linux kernel. But really either the spec should be + changed or the programs updated. */ + if (alloc > 1 + && tdata->phdr[0].p_type == PT_PHDR + && ! bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, alloc) + && tdata->phdr[1].p_type == PT_LOAD + && (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr + || (tdata->phdr[1].p_vaddr + tdata->phdr[1].p_memsz) + < (tdata->phdr[0].p_vaddr + tdata->phdr[0].p_memsz))) + { + /* The fix for this error is usually to edit the linker script being + used and set up the program headers manually. Either that or + leave room for the headers at the start of the SECTIONS. */ + _bfd_error_handler (_("\ +%B: error: PHDR segment not covered by LOAD segment"), + abfd); + return FALSE; + } + if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0 || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0) return FALSE; - - off = elf_next_file_pos (abfd); } - /* Place the section headers. */ - off = align_file_position (off, 1 << bed->s->log_file_align); - i_ehdrp->e_shoff = off; - off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize; - - elf_next_file_pos (abfd) = off; - return TRUE; } @@ -5298,7 +6077,7 @@ prep_headers (bfd *abfd) elf_tdata (abfd)->shstrtab_hdr.sh_name = (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", FALSE); if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1 - || elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1 + || elf_tdata (abfd)->strtab_hdr.sh_name == (unsigned int) -1 || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1) return FALSE; @@ -5306,29 +6085,101 @@ prep_headers (bfd *abfd) } /* Assign file positions for all the reloc sections which are not part - of the loadable file image. */ + of the loadable file image, and the file position of section headers. */ -void -_bfd_elf_assign_file_positions_for_relocs (bfd *abfd) +static bfd_boolean +_bfd_elf_assign_file_positions_for_non_load (bfd *abfd) { file_ptr off; - unsigned int i, num_sec; - Elf_Internal_Shdr **shdrpp; + Elf_Internal_Shdr **shdrpp, **end_shdrpp; + Elf_Internal_Shdr *shdrp; + Elf_Internal_Ehdr *i_ehdrp; + const struct elf_backend_data *bed; off = elf_next_file_pos (abfd); - num_sec = elf_numsections (abfd); - for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++) + shdrpp = elf_elfsections (abfd); + end_shdrpp = shdrpp + elf_numsections (abfd); + for (shdrpp++; shdrpp < end_shdrpp; shdrpp++) { - Elf_Internal_Shdr *shdrp; - shdrp = *shdrpp; - if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA) - && shdrp->sh_offset == -1) - off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE); + if (shdrp->sh_offset == -1) + { + asection *sec = shdrp->bfd_section; + bfd_boolean is_rel = (shdrp->sh_type == SHT_REL + || shdrp->sh_type == SHT_RELA); + if (is_rel + || (sec != NULL && (sec->flags & SEC_ELF_COMPRESS))) + { + if (!is_rel) + { + const char *name = sec->name; + struct bfd_elf_section_data *d; + + /* Compress DWARF debug sections. */ + if (!bfd_compress_section (abfd, sec, + shdrp->contents)) + return FALSE; + + if (sec->compress_status == COMPRESS_SECTION_DONE + && (abfd->flags & BFD_COMPRESS_GABI) == 0) + { + /* If section is compressed with zlib-gnu, convert + section name from .debug_* to .zdebug_*. */ + char *new_name + = convert_debug_to_zdebug (abfd, name); + if (new_name == NULL) + return FALSE; + name = new_name; + } + /* Add section name to section name section. */ + if (shdrp->sh_name != (unsigned int) -1) + abort (); + shdrp->sh_name + = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), + name, FALSE); + d = elf_section_data (sec); + + /* Add reloc section name to section name section. */ + if (d->rel.hdr + && !_bfd_elf_set_reloc_sh_name (abfd, + d->rel.hdr, + name, FALSE)) + return FALSE; + if (d->rela.hdr + && !_bfd_elf_set_reloc_sh_name (abfd, + d->rela.hdr, + name, TRUE)) + return FALSE; + + /* Update section size and contents. */ + shdrp->sh_size = sec->size; + shdrp->contents = sec->contents; + shdrp->bfd_section->contents = NULL; + } + off = _bfd_elf_assign_file_position_for_section (shdrp, + off, + TRUE); + } + } } + /* Place section name section after DWARF debug sections have been + compressed. */ + _bfd_elf_strtab_finalize (elf_shstrtab (abfd)); + shdrp = &elf_tdata (abfd)->shstrtab_hdr; + shdrp->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); + off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE); + + /* Place the section headers. */ + i_ehdrp = elf_elfheader (abfd); + bed = get_elf_backend_data (abfd); + off = align_file_position (off, 1 << bed->s->log_file_align); + i_ehdrp->e_shoff = off; + off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize; elf_next_file_pos (abfd) = off; + + return TRUE; } bfd_boolean @@ -5351,12 +6202,16 @@ _bfd_elf_write_object_contents (bfd *abfd) if (failed) return FALSE; - _bfd_elf_assign_file_positions_for_relocs (abfd); + if (!_bfd_elf_assign_file_positions_for_non_load (abfd)) + return FALSE; /* After writing the headers, we need to write the sections too... */ num_sec = elf_numsections (abfd); for (count = 1; count < num_sec; count++) { + i_shdrp[count]->sh_name + = _bfd_elf_strtab_offset (elf_shstrtab (abfd), + i_shdrp[count]->sh_name); if (bed->elf_backend_section_processing) (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]); if (i_shdrp[count]->contents) @@ -5469,7 +6324,8 @@ _bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr) { /* This case can occur when using --strip-symbol on a symbol which is used in a relocation entry. */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: symbol `%s' required but not present"), abfd, bfd_asymbol_name (asym_ptr)); bfd_set_error (bfd_error_no_symbols); @@ -5808,9 +6664,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) something. They are allowed by the ELF spec however, so only a warning is produced. */ if (segment->p_type == PT_LOAD) - (*_bfd_error_handler) (_("%B: warning: Empty loadable segment" - " detected, is this intentional ?\n"), - ibfd); + _bfd_error_handler (_("\ +%B: warning: Empty loadable segment detected, is this intentional ?"), + ibfd); map->count = 0; *pointer_to_map = map; @@ -5863,13 +6719,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) first_matching_lma = TRUE; first_suggested_lma = TRUE; - for (section = ibfd->sections; + for (section = first_section, j = 0; section != NULL; section = section->next) - if (section == first_section) - break; - - for (j = 0; section != NULL; section = section->next) { if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed)) { @@ -6422,7 +7274,16 @@ rewrite: i++, segment++) if (segment->p_type == PT_LOAD && maxpagesize < segment->p_align) - maxpagesize = segment->p_align; + { + /* PR 17512: file: f17299af. */ + if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2)) + /* xgettext:c-format */ + _bfd_error_handler (_("\ +%B: warning: segment alignment of 0x%llx is too large"), + ibfd, (long long) segment->p_align); + else + maxpagesize = segment->p_align; + } if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize) bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize); @@ -6442,7 +7303,8 @@ _bfd_elf_init_private_section_data (bfd *ibfd, { Elf_Internal_Shdr *ihdr, *ohdr; - bfd_boolean final_link = link_info != NULL && !link_info->relocatable; + bfd_boolean final_link = (link_info != NULL + && !bfd_link_relocatable (link_info)); if (ibfd->xvec->flavour != bfd_target_elf_flavour || obfd->xvec->flavour != bfd_target_elf_flavour) @@ -6479,6 +7341,11 @@ _bfd_elf_init_private_section_data (bfd *ibfd, elf_next_in_group (osec) = elf_next_in_group (isec); elf_section_data (osec)->group = elf_section_data (isec)->group; } + + /* If not decompress, preserve SHF_COMPRESSED. */ + if ((ibfd->flags & BFD_DECOMPRESS) == 0) + elf_section_flags (osec) |= (elf_section_flags (isec) + & SHF_COMPRESSED); } ihdr = &elf_section_data (isec)->this_hdr; @@ -6657,7 +7524,7 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd, shndx = MAP_STRTAB; else if (shndx == elf_shstrtab_sec (ibfd)) shndx = MAP_SHSTRTAB; - else if (shndx == elf_symtab_shndx (ibfd)) + else if (find_section_in_list (shndx, elf_symtab_shndx_list (ibfd))) shndx = MAP_SYM_SHNDX; osym->internal_elf_sym.st_shndx = shndx; } @@ -6669,18 +7536,21 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd, static bfd_boolean swap_out_syms (bfd *abfd, - struct bfd_strtab_hash **sttp, + struct elf_strtab_hash **sttp, int relocatable_p) { const struct elf_backend_data *bed; int symcount; asymbol **syms; - struct bfd_strtab_hash *stt; + struct elf_strtab_hash *stt; Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_shndx_hdr; Elf_Internal_Shdr *symstrtab_hdr; + struct elf_sym_strtab *symstrtab; bfd_byte *outbound_syms; bfd_byte *outbound_shndx; + unsigned long outbound_syms_index; + unsigned long outbound_shndx_index; int idx; unsigned int num_locals; bfd_size_type amt; @@ -6690,7 +7560,7 @@ swap_out_syms (bfd *abfd, return FALSE; /* Dump out the symtabs. */ - stt = _bfd_elf_stringtab_init (); + stt = _bfd_elf_strtab_init (); if (stt == NULL) return FALSE; @@ -6706,33 +7576,48 @@ swap_out_syms (bfd *abfd, symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; symstrtab_hdr->sh_type = SHT_STRTAB; + /* Allocate buffer to swap out the .strtab section. */ + symstrtab = (struct elf_sym_strtab *) bfd_malloc ((symcount + 1) + * sizeof (*symstrtab)); + if (symstrtab == NULL) + { + _bfd_elf_strtab_free (stt); + return FALSE; + } + outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount, bed->s->sizeof_sym); if (outbound_syms == NULL) { - _bfd_stringtab_free (stt); +error_return: + _bfd_elf_strtab_free (stt); + free (symstrtab); return FALSE; } symtab_hdr->contents = outbound_syms; + outbound_syms_index = 0; outbound_shndx = NULL; - symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (symtab_shndx_hdr->sh_name != 0) + outbound_shndx_index = 0; + + if (elf_symtab_shndx_list (abfd)) { - amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx); - outbound_shndx = (bfd_byte *) - bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx)); - if (outbound_shndx == NULL) + symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr; + if (symtab_shndx_hdr->sh_name != 0) { - _bfd_stringtab_free (stt); - return FALSE; - } + amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx); + outbound_shndx = (bfd_byte *) + bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx)); + if (outbound_shndx == NULL) + goto error_return; - symtab_shndx_hdr->contents = outbound_shndx; - symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX; - symtab_shndx_hdr->sh_size = amt; - symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx); - symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx); + symtab_shndx_hdr->contents = outbound_shndx; + symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX; + symtab_shndx_hdr->sh_size = amt; + symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx); + symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx); + } + /* FIXME: What about any other headers in the list ? */ } /* Now generate the data (for "contents"). */ @@ -6746,10 +7631,12 @@ swap_out_syms (bfd *abfd, sym.st_other = 0; sym.st_shndx = SHN_UNDEF; sym.st_target_internal = 0; - bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx); - outbound_syms += bed->s->sizeof_sym; + symstrtab[0].sym = sym; + symstrtab[0].dest_index = outbound_syms_index; + symstrtab[0].destshndx_index = outbound_shndx_index; + outbound_syms_index++; if (outbound_shndx != NULL) - outbound_shndx += sizeof (Elf_External_Sym_Shndx); + outbound_shndx_index++; } name_local_sections @@ -6757,7 +7644,7 @@ swap_out_syms (bfd *abfd, && bed->elf_backend_name_local_section_symbols (abfd)); syms = bfd_get_outsymbols (abfd); - for (idx = 0; idx < symcount; idx++) + for (idx = 0; idx < symcount;) { Elf_Internal_Sym sym; bfd_vma value = syms[idx]->value; @@ -6769,18 +7656,17 @@ swap_out_syms (bfd *abfd, && (flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM) { /* Local section symbols have no name. */ - sym.st_name = 0; + sym.st_name = (unsigned long) -1; } else { - sym.st_name = (unsigned long) _bfd_stringtab_add (stt, - syms[idx]->name, - TRUE, FALSE); + /* Call _bfd_elf_strtab_offset after _bfd_elf_strtab_finalize + to get the final offset for st_name. */ + sym.st_name + = (unsigned long) _bfd_elf_strtab_add (stt, syms[idx]->name, + FALSE); if (sym.st_name == (unsigned long) -1) - { - _bfd_stringtab_free (stt); - return FALSE; - } + goto error_return; } type_ptr = elf_symbol_from (abfd, syms[idx]); @@ -6840,7 +7726,8 @@ swap_out_syms (bfd *abfd, shndx = elf_shstrtab_sec (abfd); break; case MAP_SYM_SHNDX: - shndx = elf_symtab_shndx (abfd); + if (elf_symtab_shndx_list (abfd)) + shndx = elf_symtab_shndx_list (abfd)->ndx; break; default: shndx = SHN_ABS; @@ -6863,19 +7750,18 @@ swap_out_syms (bfd *abfd, section of a symbol to be a section that is actually in the output file. */ sec2 = bfd_get_section_by_name (abfd, sec->name); - if (sec2 == NULL) + if (sec2 != NULL) + shndx = _bfd_elf_section_from_bfd_section (abfd, sec2); + if (shndx == SHN_BAD) { + /* xgettext:c-format */ _bfd_error_handler (_("\ Unable to find equivalent output section for symbol '%s' from section '%s'"), syms[idx]->name ? syms[idx]->name : "", sec->name); bfd_set_error (bfd_error_invalid_operation); - _bfd_stringtab_free (stt); - return FALSE; + goto error_return; } - - shndx = _bfd_elf_section_from_bfd_section (abfd, sec2); - BFD_ASSERT (shndx != SHN_BAD); } } @@ -6915,12 +7801,16 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"), } else if (bfd_is_com_section (syms[idx]->section)) { -#ifdef USE_STT_COMMON - if (type == STT_OBJECT) - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_COMMON); - else -#endif - sym.st_info = ELF_ST_INFO (STB_GLOBAL, type); + if (type != STT_TLS) + { + if ((abfd->flags & BFD_CONVERT_ELF_COMMON)) + type = ((abfd->flags & BFD_USE_ELF_STT_COMMON) + ? STT_COMMON : STT_OBJECT); + else + type = ((flags & BSF_ELF_COMMON) != 0 + ? STT_COMMON : STT_OBJECT); + } + sym.st_info = ELF_ST_INFO (STB_GLOBAL, type); } else if (bfd_is_und_section (syms[idx]->section)) sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK) @@ -6957,17 +7847,42 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"), sym.st_target_internal = 0; } - bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx); - outbound_syms += bed->s->sizeof_sym; + idx++; + symstrtab[idx].sym = sym; + symstrtab[idx].dest_index = outbound_syms_index; + symstrtab[idx].destshndx_index = outbound_shndx_index; + + outbound_syms_index++; if (outbound_shndx != NULL) - outbound_shndx += sizeof (Elf_External_Sym_Shndx); + outbound_shndx_index++; } + /* Finalize the .strtab section. */ + _bfd_elf_strtab_finalize (stt); + + /* Swap out the .strtab section. */ + for (idx = 0; idx <= symcount; idx++) + { + struct elf_sym_strtab *elfsym = &symstrtab[idx]; + if (elfsym->sym.st_name == (unsigned long) -1) + elfsym->sym.st_name = 0; + else + elfsym->sym.st_name = _bfd_elf_strtab_offset (stt, + elfsym->sym.st_name); + bed->s->swap_symbol_out (abfd, &elfsym->sym, + (outbound_syms + + (elfsym->dest_index + * bed->s->sizeof_sym)), + (outbound_shndx + + (elfsym->destshndx_index + * sizeof (Elf_External_Sym_Shndx)))); + } + free (symstrtab); + *sttp = stt; - symstrtab_hdr->sh_size = _bfd_stringtab_size (stt); + symstrtab_hdr->sh_size = _bfd_elf_strtab_size (stt); symstrtab_hdr->sh_type = SHT_STRTAB; - - symstrtab_hdr->sh_flags = 0; + symstrtab_hdr->sh_flags = bed->elf_strtab_flags; symstrtab_hdr->sh_addr = 0; symstrtab_hdr->sh_entsize = 0; symstrtab_hdr->sh_link = 0; @@ -7168,26 +8083,30 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver) hdr = &elf_tdata (abfd)->dynverref_hdr; - elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) - bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed)); - if (elf_tdata (abfd)->verref == NULL) - goto error_return; - - elf_tdata (abfd)->cverrefs = hdr->sh_info; - - contents = (bfd_byte *) bfd_malloc (hdr->sh_size); - if (contents == NULL) + if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verneed)) { +error_return_bad_verref: + _bfd_error_handler + (_("%B: .gnu.version_r invalid entry"), abfd); + bfd_set_error (bfd_error_bad_value); error_return_verref: elf_tdata (abfd)->verref = NULL; elf_tdata (abfd)->cverrefs = 0; goto error_return; } + + contents = (bfd_byte *) bfd_malloc (hdr->sh_size); + if (contents == NULL) + goto error_return_verref; + if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size) goto error_return_verref; - if (hdr->sh_info && hdr->sh_size < sizeof (Elf_External_Verneed)) + elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) + bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed)); + + if (elf_tdata (abfd)->verref == NULL) goto error_return_verref; BFD_ASSERT (sizeof (Elf_External_Verneed) @@ -7209,7 +8128,7 @@ error_return_verref: bfd_elf_string_from_elf_section (abfd, hdr->sh_link, iverneed->vn_file); if (iverneed->vn_filename == NULL) - goto error_return_verref; + goto error_return_bad_verref; if (iverneed->vn_cnt == 0) iverneed->vn_auxptr = NULL; @@ -7224,7 +8143,7 @@ error_return_verref: if (iverneed->vn_aux > (size_t) (contents_end - (bfd_byte *) everneed)) - goto error_return_verref; + goto error_return_bad_verref; evernaux = ((Elf_External_Vernaux *) ((bfd_byte *) everneed + iverneed->vn_aux)); @@ -7237,36 +8156,42 @@ error_return_verref: bfd_elf_string_from_elf_section (abfd, hdr->sh_link, ivernaux->vna_name); if (ivernaux->vna_nodename == NULL) - goto error_return_verref; + goto error_return_bad_verref; + + if (ivernaux->vna_other > freeidx) + freeidx = ivernaux->vna_other; + ivernaux->vna_nextptr = NULL; + if (ivernaux->vna_next == 0) + { + iverneed->vn_cnt = j + 1; + break; + } if (j + 1 < iverneed->vn_cnt) ivernaux->vna_nextptr = ivernaux + 1; - else - ivernaux->vna_nextptr = NULL; if (ivernaux->vna_next > (size_t) (contents_end - (bfd_byte *) evernaux)) - goto error_return_verref; + goto error_return_bad_verref; evernaux = ((Elf_External_Vernaux *) ((bfd_byte *) evernaux + ivernaux->vna_next)); - - if (ivernaux->vna_other > freeidx) - freeidx = ivernaux->vna_other; } + iverneed->vn_nextref = NULL; + if (iverneed->vn_next == 0) + break; if (i + 1 < hdr->sh_info) iverneed->vn_nextref = iverneed + 1; - else - iverneed->vn_nextref = NULL; if (iverneed->vn_next > (size_t) (contents_end - (bfd_byte *) everneed)) - goto error_return_verref; + goto error_return_bad_verref; everneed = ((Elf_External_Verneed *) ((bfd_byte *) everneed + iverneed->vn_next)); } + elf_tdata (abfd)->cverrefs = i; free (contents); contents = NULL; @@ -7285,15 +8210,24 @@ error_return_verref: hdr = &elf_tdata (abfd)->dynverdef_hdr; + if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verdef)) + { + error_return_bad_verdef: + _bfd_error_handler + (_("%B: .gnu.version_d invalid entry"), abfd); + bfd_set_error (bfd_error_bad_value); + error_return_verdef: + elf_tdata (abfd)->verdef = NULL; + elf_tdata (abfd)->cverdefs = 0; + goto error_return; + } + contents = (bfd_byte *) bfd_malloc (hdr->sh_size); if (contents == NULL) - goto error_return; + goto error_return_verdef; if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size) - goto error_return; - - if (hdr->sh_info && hdr->sh_size < sizeof (Elf_External_Verdef)) - goto error_return; + goto error_return_verdef; BFD_ASSERT (sizeof (Elf_External_Verdef) >= sizeof (Elf_External_Verdaux)); @@ -7311,12 +8245,17 @@ error_return_verref: { _bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem); + if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) == 0) + goto error_return_bad_verdef; if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx) maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION); + if (iverdefmem.vd_next == 0) + break; + if (iverdefmem.vd_next > (size_t) (contents_end_def - (bfd_byte *) everdef)) - goto error_return; + goto error_return_bad_verdef; everdef = ((Elf_External_Verdef *) ((bfd_byte *) everdef + iverdefmem.vd_next)); @@ -7329,10 +8268,11 @@ error_return_verref: else freeidx = ++maxidx; } + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) - bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef)); + bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef)); if (elf_tdata (abfd)->verdef == NULL) - goto error_return; + goto error_return_verdef; elf_tdata (abfd)->cverdefs = maxidx; @@ -7347,15 +8287,10 @@ error_return_verref: _bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem); if ((iverdefmem.vd_ndx & VERSYM_VERSION) == 0) - { -error_return_verdef: - elf_tdata (abfd)->verdef = NULL; - elf_tdata (abfd)->cverdefs = 0; - goto error_return; - } + goto error_return_bad_verdef; iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1]; - memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef)); + memcpy (iverdef, &iverdefmem, offsetof (Elf_Internal_Verdef, vd_bfd)); iverdef->vd_bfd = abfd; @@ -7372,7 +8307,7 @@ error_return_verdef: if (iverdef->vd_aux > (size_t) (contents_end_aux - (bfd_byte *) everdef)) - goto error_return_verdef; + goto error_return_bad_verdef; everdaux = ((Elf_External_Verdaux *) ((bfd_byte *) everdef + iverdef->vd_aux)); @@ -7385,28 +8320,34 @@ error_return_verdef: bfd_elf_string_from_elf_section (abfd, hdr->sh_link, iverdaux->vda_name); if (iverdaux->vda_nodename == NULL) - goto error_return_verdef; + goto error_return_bad_verdef; + iverdaux->vda_nextptr = NULL; + if (iverdaux->vda_next == 0) + { + iverdef->vd_cnt = j + 1; + break; + } if (j + 1 < iverdef->vd_cnt) iverdaux->vda_nextptr = iverdaux + 1; - else - iverdaux->vda_nextptr = NULL; if (iverdaux->vda_next > (size_t) (contents_end_aux - (bfd_byte *) everdaux)) - goto error_return_verdef; + goto error_return_bad_verdef; everdaux = ((Elf_External_Verdaux *) ((bfd_byte *) everdaux + iverdaux->vda_next)); } + iverdef->vd_nodename = NULL; if (iverdef->vd_cnt) iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename; + iverdef->vd_nextdef = NULL; + if (iverdef->vd_next == 0) + break; if ((size_t) (iverdef - iverdefarr) + 1 < maxidx) iverdef->vd_nextdef = iverdef + 1; - else - iverdef->vd_nextdef = NULL; everdef = ((Elf_External_Verdef *) ((bfd_byte *) everdef + iverdef->vd_next)); @@ -7449,14 +8390,13 @@ error_return_verdef: if (iverdef->vd_nodename == NULL) goto error_return_verdef; iverdef->vd_nextdef = NULL; - iverdef->vd_auxptr = (struct elf_internal_verdaux *) - bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux)); + iverdef->vd_auxptr = ((struct elf_internal_verdaux *) + bfd_zalloc (abfd, sizeof (Elf_Internal_Verdaux))); if (iverdef->vd_auxptr == NULL) goto error_return_verdef; iverdaux = iverdef->vd_auxptr; iverdaux->vda_nodename = iverdef->vd_nodename; - iverdaux->vda_nextptr = NULL; } return TRUE; @@ -7471,16 +8411,12 @@ asymbol * _bfd_elf_make_empty_symbol (bfd *abfd) { elf_symbol_type *newsym; - bfd_size_type amt = sizeof (elf_symbol_type); - newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt); + newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym); if (!newsym) return NULL; - else - { - newsym->symbol.the_bfd = abfd; - return &newsym->symbol; - } + newsym->symbol.the_bfd = abfd; + return &newsym->symbol; } void @@ -7517,6 +8453,47 @@ _bfd_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_') return TRUE; + /* Treat assembler generated fake symbols, dollar local labels and + forward-backward labels (aka local labels) as locals. + These labels have the form: + + L0^A.* (fake symbols) + + [.]?L[0123456789]+{^A|^B}[0123456789]* (local labels) + + Versions which start with .L will have already been matched above, + so we only need to match the rest. */ + if (name[0] == 'L' && ISDIGIT (name[1])) + { + bfd_boolean ret = FALSE; + const char * p; + char c; + + for (p = name + 2; (c = *p); p++) + { + if (c == 1 || c == 2) + { + if (c == 1 && p == name + 2) + /* A fake symbol. */ + return TRUE; + + /* FIXME: We are being paranoid here and treating symbols like + L0^Bfoo as if there were non-local, on the grounds that the + assembler will never generate them. But can any symbol + containing an ASCII value in the range 1-31 ever be anything + other than some kind of local ? */ + ret = TRUE; + } + + if (! ISDIGIT (c)) + { + ret = FALSE; + break; + } + } + return ret; + } + return FALSE; } @@ -7543,163 +8520,34 @@ _bfd_elf_set_arch_mach (bfd *abfd, return bfd_default_set_arch_mach (abfd, arch, machine); } -/* Find the function to a particular section and offset, - for error reporting. */ - -static bfd_boolean -elf_find_function (bfd *abfd, - asection *section, - asymbol **symbols, - bfd_vma offset, - const char **filename_ptr, - const char **functionname_ptr) -{ - struct elf_find_function_cache - { - asection *last_section; - asymbol *func; - const char *filename; - bfd_size_type func_size; - } *cache; - - if (symbols == NULL) - return FALSE; - - cache = elf_tdata (abfd)->elf_find_function_cache; - if (cache == NULL) - { - cache = bfd_zalloc (abfd, sizeof (*cache)); - elf_tdata (abfd)->elf_find_function_cache = cache; - if (cache == NULL) - return FALSE; - } - if (cache->last_section != section - || cache->func == NULL - || offset < cache->func->value - || offset >= cache->func->value + cache->func_size) - { - asymbol *file; - bfd_vma low_func; - asymbol **p; - /* ??? Given multiple file symbols, it is impossible to reliably - choose the right file name for global symbols. File symbols are - local symbols, and thus all file symbols must sort before any - global symbols. The ELF spec may be interpreted to say that a - file symbol must sort before other local symbols, but currently - ld -r doesn't do this. So, for ld -r output, it is possible to - make a better choice of file name for local symbols by ignoring - file symbols appearing after a given local symbol. */ - enum { nothing_seen, symbol_seen, file_after_symbol_seen } state; - const struct elf_backend_data *bed = get_elf_backend_data (abfd); - - file = NULL; - low_func = 0; - state = nothing_seen; - cache->filename = NULL; - cache->func = NULL; - cache->func_size = 0; - cache->last_section = section; - - for (p = symbols; *p != NULL; p++) - { - asymbol *sym = *p; - bfd_vma code_off; - bfd_size_type size; - - if ((sym->flags & BSF_FILE) != 0) - { - file = sym; - if (state == symbol_seen) - state = file_after_symbol_seen; - continue; - } - - size = bed->maybe_function_sym (sym, section, &code_off); - if (size != 0 - && code_off <= offset - && (code_off > low_func - || (code_off == low_func - && size > cache->func_size))) - { - cache->func = sym; - cache->func_size = size; - cache->filename = NULL; - low_func = code_off; - if (file != NULL - && ((sym->flags & BSF_LOCAL) != 0 - || state != file_after_symbol_seen)) - cache->filename = bfd_asymbol_name (file); - } - if (state == nothing_seen) - state = symbol_seen; - } - } - - if (cache->func == NULL) - return FALSE; - - if (filename_ptr) - *filename_ptr = cache->filename; - if (functionname_ptr) - *functionname_ptr = bfd_asymbol_name (cache->func); - - return TRUE; -} - /* Find the nearest line to a particular section and offset, for error reporting. */ bfd_boolean _bfd_elf_find_nearest_line (bfd *abfd, - asection *section, asymbol **symbols, + asection *section, bfd_vma offset, const char **filename_ptr, const char **functionname_ptr, - unsigned int *line_ptr) -{ - return _bfd_elf_find_nearest_line_discriminator (abfd, section, symbols, - offset, filename_ptr, - functionname_ptr, - line_ptr, - NULL); -} - -bfd_boolean -_bfd_elf_find_nearest_line_discriminator (bfd *abfd, - asection *section, - asymbol **symbols, - bfd_vma offset, - const char **filename_ptr, - const char **functionname_ptr, - unsigned int *line_ptr, - unsigned int *discriminator_ptr) + unsigned int *line_ptr, + unsigned int *discriminator_ptr) { bfd_boolean found; - if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, - filename_ptr, functionname_ptr, - line_ptr)) - { - if (!*functionname_ptr) - elf_find_function (abfd, section, symbols, offset, - *filename_ptr ? NULL : filename_ptr, - functionname_ptr); - - return TRUE; - } - - if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, - section, symbols, offset, + if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, filename_ptr, functionname_ptr, - line_ptr, discriminator_ptr, 0, - &elf_tdata (abfd)->dwarf2_find_line_info)) + line_ptr, discriminator_ptr, + dwarf_debug_sections, 0, + &elf_tdata (abfd)->dwarf2_find_line_info) + || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset, + filename_ptr, functionname_ptr, + line_ptr)) { if (!*functionname_ptr) - elf_find_function (abfd, section, symbols, offset, - *filename_ptr ? NULL : filename_ptr, - functionname_ptr); - + _bfd_elf_find_function (abfd, symbols, section, offset, + *filename_ptr ? NULL : filename_ptr, + functionname_ptr); return TRUE; } @@ -7714,8 +8562,8 @@ _bfd_elf_find_nearest_line_discriminator (bfd *abfd, if (symbols == NULL) return FALSE; - if (! elf_find_function (abfd, section, symbols, offset, - filename_ptr, functionname_ptr)) + if (! _bfd_elf_find_function (abfd, symbols, section, offset, + filename_ptr, functionname_ptr)) return FALSE; *line_ptr = 0; @@ -7728,20 +8576,10 @@ bfd_boolean _bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol, const char **filename_ptr, unsigned int *line_ptr) { - return _bfd_elf_find_line_discriminator (abfd, symbols, symbol, - filename_ptr, line_ptr, - NULL); -} - -bfd_boolean -_bfd_elf_find_line_discriminator (bfd *abfd, asymbol **symbols, asymbol *symbol, - const char **filename_ptr, - unsigned int *line_ptr, - unsigned int *discriminator_ptr) -{ - return _bfd_dwarf2_find_line (abfd, symbols, symbol, - filename_ptr, line_ptr, discriminator_ptr, 0, - &elf_tdata (abfd)->dwarf2_find_line_info); + return _bfd_dwarf2_find_nearest_line (abfd, symbols, symbol, NULL, 0, + filename_ptr, NULL, line_ptr, NULL, + dwarf_debug_sections, 0, + &elf_tdata (abfd)->dwarf2_find_line_info); } /* After a call to bfd_find_nearest_line, successive calls to @@ -7769,7 +8607,7 @@ _bfd_elf_sizeof_headers (bfd *abfd, struct bfd_link_info *info) const struct elf_backend_data *bed = get_elf_backend_data (abfd); int ret = bed->s->sizeof_ehdr; - if (!info->relocatable) + if (!bfd_link_relocatable (info)) { bfd_size_type phdr_size = elf_program_header_size (abfd); @@ -7800,13 +8638,27 @@ _bfd_elf_set_section_contents (bfd *abfd, bfd_size_type count) { Elf_Internal_Shdr *hdr; - bfd_signed_vma pos; + file_ptr pos; if (! abfd->output_has_begun && ! _bfd_elf_compute_section_file_positions (abfd, NULL)) return FALSE; + if (!count) + return TRUE; + hdr = &elf_section_data (section)->this_hdr; + if (hdr->sh_offset == (file_ptr) -1) + { + /* We must compress this section. Write output to the buffer. */ + unsigned char *contents = hdr->contents; + if ((offset + count) > hdr->sh_size + || (section->flags & SEC_ELF_COMPRESS) == 0 + || contents == NULL) + abort (); + memcpy (contents + offset, location, count); + return TRUE; + } pos = hdr->sh_offset + offset; if (bfd_seek (abfd, pos, SEEK_SET) != 0 || bfd_bwrite (location, count, abfd) != count) @@ -7912,7 +8764,8 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc) return TRUE; fail: - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: unsupported relocation type %s"), abfd, areloc->howto->name); bfd_set_error (bfd_error_bad_value); @@ -8225,6 +9078,18 @@ elfcore_grok_s390_tdb (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-s390-tdb", note); } +static bfd_boolean +elfcore_grok_s390_vxrs_low (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-vxrs-low", note); +} + +static bfd_boolean +elfcore_grok_s390_vxrs_high (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-vxrs-high", note); +} + static bfd_boolean elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note) { @@ -8689,6 +9554,20 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_S390_VXRS_LOW: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_vxrs_low (abfd, note); + else + return TRUE; + + case NT_S390_VXRS_HIGH: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_vxrs_high (abfd, note); + else + return TRUE; + case NT_ARM_VFP: if (note->namesz == 6 && strcmp (note->namedata, "LINUX") == 0) @@ -8749,24 +9628,25 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) case NT_SIGINFO: return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo", note); + } } static bfd_boolean elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note) { - struct elf_obj_tdata *t; + struct bfd_build_id* build_id; if (note->descsz == 0) return FALSE; - t = elf_tdata (abfd); - t->build_id = bfd_alloc (abfd, sizeof (*t->build_id) - 1 + note->descsz); - if (t->build_id == NULL) + build_id = bfd_alloc (abfd, sizeof (struct bfd_build_id) - 1 + note->descsz); + if (build_id == NULL) return FALSE; - t->build_id->size = note->descsz; - memcpy (t->build_id->data, note->descdata, note->descsz); + build_id->size = note->descsz; + memcpy (build_id->data, note->descdata, note->descsz); + abfd->build_id = build_id; return TRUE; } @@ -8813,6 +9693,168 @@ elfobj_grok_stapsdt_note (bfd *abfd, Elf_Internal_Note *note) } } +static bfd_boolean +elfcore_grok_freebsd_psinfo (bfd *abfd, Elf_Internal_Note *note) +{ + size_t offset; + + switch (abfd->arch_info->bits_per_word) + { + case 32: + if (note->descsz < 108) + return FALSE; + break; + + case 64: + if (note->descsz < 120) + return FALSE; + break; + + default: + return FALSE; + } + + /* Check for version 1 in pr_version. */ + if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1) + return FALSE; + offset = 4; + + /* Skip over pr_psinfosz. */ + if (abfd->arch_info->bits_per_word == 32) + offset += 4; + else + { + offset += 4; /* Padding before pr_psinfosz. */ + offset += 8; + } + + /* pr_fname is PRFNAMESZ (16) + 1 bytes in size. */ + elf_tdata (abfd)->core->program + = _bfd_elfcore_strndup (abfd, note->descdata + offset, 17); + offset += 17; + + /* pr_psargs is PRARGSZ (80) + 1 bytes in size. */ + elf_tdata (abfd)->core->command + = _bfd_elfcore_strndup (abfd, note->descdata + offset, 81); + offset += 81; + + /* Padding before pr_pid. */ + offset += 2; + + /* The pr_pid field was added in version "1a". */ + if (note->descsz < offset + 4) + return TRUE; + + elf_tdata (abfd)->core->pid + = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset); + + return TRUE; +} + +static bfd_boolean +elfcore_grok_freebsd_prstatus (bfd *abfd, Elf_Internal_Note *note) +{ + size_t offset; + size_t size; + + /* Check for version 1 in pr_version. */ + if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1) + return FALSE; + offset = 4; + + /* Skip over pr_statussz. */ + switch (abfd->arch_info->bits_per_word) + { + case 32: + offset += 4; + break; + + case 64: + offset += 4; /* Padding before pr_statussz. */ + offset += 8; + break; + + default: + return FALSE; + } + + /* Extract size of pr_reg from pr_gregsetsz. */ + if (abfd->arch_info->bits_per_word == 32) + size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset); + else + size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset); + + /* Skip over pr_gregsetsz and pr_fpregsetsz. */ + offset += (abfd->arch_info->bits_per_word / 8) * 2; + + /* Skip over pr_osreldate. */ + offset += 4; + + /* Read signal from pr_cursig. */ + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal + = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset); + offset += 4; + + /* Read TID from pr_pid. */ + elf_tdata (abfd)->core->lwpid + = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset); + offset += 4; + + /* Padding before pr_reg. */ + if (abfd->arch_info->bits_per_word == 64) + offset += 4; + + /* Make a ".reg/999" section and a ".reg" section. */ + return _bfd_elfcore_make_pseudosection (abfd, ".reg", + size, note->descpos + offset); +} + +static bfd_boolean +elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note) +{ + switch (note->type) + { + case NT_PRSTATUS: + return elfcore_grok_freebsd_prstatus (abfd, note); + + case NT_FPREGSET: + return elfcore_grok_prfpreg (abfd, note); + + case NT_PRPSINFO: + return elfcore_grok_freebsd_psinfo (abfd, note); + + case NT_FREEBSD_THRMISC: + if (note->namesz == 8) + return elfcore_make_note_pseudosection (abfd, ".thrmisc", note); + else + return TRUE; + + case NT_FREEBSD_PROCSTAT_AUXV: + { + asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv", + SEC_HAS_CONTENTS); + + if (sect == NULL) + return FALSE; + sect->size = note->descsz - 4; + sect->filepos = note->descpos + 4; + sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32; + + return TRUE; + } + + case NT_X86_XSTATE: + if (note->namesz == 8) + return elfcore_grok_xstatereg (abfd, note); + else + return TRUE; + + default: + return TRUE; + } +} + static bfd_boolean elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp) { @@ -9246,9 +10288,7 @@ elfcore_write_linux_prpsinfo32 { struct elf_external_linux_prpsinfo32 data; - memset (&data, 0, sizeof (data)); - LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data); - + swap_linux_prpsinfo32_out (abfd, prpsinfo, &data); return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO, &data, sizeof (data)); } @@ -9260,9 +10300,7 @@ elfcore_write_linux_prpsinfo64 { struct elf_external_linux_prpsinfo64 data; - memset (&data, 0, sizeof (data)); - LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data); - + swap_linux_prpsinfo64_out (abfd, prpsinfo, &data); return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO, &data, sizeof (data)); } @@ -9334,7 +10372,7 @@ elfcore_write_lwpstatus (bfd *abfd, lwpstat.pr_lwpid = pid >> 16; lwpstat.pr_cursig = cursig; #if defined (HAVE_LWPSTATUS_T_PR_REG) - memcpy (lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg)); + memcpy (&lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg)); #elif defined (HAVE_LWPSTATUS_T_PR_CONTEXT) #if !defined(gregs) memcpy (lwpstat.pr_context.uc_mcontext.gregs, @@ -9414,7 +10452,11 @@ char * elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz, const void *xfpregs, int size) { - char *note_name = "LINUX"; + char *note_name; + if (get_elf_backend_data (abfd)->elf_osabi == ELFOSABI_FREEBSD) + note_name = "FreeBSD"; + else + note_name = "LINUX"; return elfcore_write_note (abfd, buf, bufsiz, note_name, NT_X86_XSTATE, xfpregs, size); } @@ -9554,6 +10596,31 @@ elfcore_write_s390_tdb (bfd *abfd, note_name, NT_S390_TDB, s390_tdb, size); } +char * +elfcore_write_s390_vxrs_low (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_vxrs_low, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_VXRS_LOW, s390_vxrs_low, size); +} + +char * +elfcore_write_s390_vxrs_high (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_vxrs_high, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_VXRS_HIGH, + s390_vxrs_high, size); +} + char * elfcore_write_arm_vfp (bfd *abfd, char *buf, @@ -9638,6 +10705,10 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-s390-tdb") == 0) return elfcore_write_s390_tdb (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-vxrs-low") == 0) + return elfcore_write_s390_vxrs_low (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-vxrs-high") == 0) + return elfcore_write_s390_vxrs_high (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-arm-vfp") == 0) return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-aarch-tls") == 0) @@ -9685,32 +10756,39 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset) return TRUE; case bfd_core: - if (CONST_STRNEQ (in.namedata, "NetBSD-CORE")) - { - if (! elfcore_grok_netbsd_note (abfd, &in)) - return FALSE; - } - else if (CONST_STRNEQ (in.namedata, "OpenBSD")) - { - if (! elfcore_grok_openbsd_note (abfd, &in)) - return FALSE; - } - else if (CONST_STRNEQ (in.namedata, "QNX")) - { - if (! elfcore_grok_nto_note (abfd, &in)) - return FALSE; - } - else if (CONST_STRNEQ (in.namedata, "SPU/")) + { +#define GROKER_ELEMENT(S,F) {S, sizeof (S) - 1, F} + struct { - if (! elfcore_grok_spu_note (abfd, &in)) - return FALSE; + const char * string; + size_t len; + bfd_boolean (* func)(bfd *, Elf_Internal_Note *); } - else + grokers[] = { - if (! elfcore_grok_note (abfd, &in)) - return FALSE; - } - break; + GROKER_ELEMENT ("", elfcore_grok_note), + GROKER_ELEMENT ("FreeBSD", elfcore_grok_freebsd_note), + GROKER_ELEMENT ("NetBSD-CORE", elfcore_grok_netbsd_note), + GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note), + GROKER_ELEMENT ("QNX", elfcore_grok_nto_note), + GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note) + }; +#undef GROKER_ELEMENT + int i; + + for (i = ARRAY_SIZE (grokers); i--;) + { + if (in.namesz >= grokers[i].len + && strncmp (in.namedata, grokers[i].string, + grokers[i].len) == 0) + { + if (! grokers[i].func (abfd, & in)) + return FALSE; + break; + } + } + break; + } case bfd_object: if (in.namesz == sizeof "GNU" && strcmp (in.namedata, "GNU") == 0) @@ -9744,10 +10822,14 @@ elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size) if (bfd_seek (abfd, offset, SEEK_SET) != 0) return FALSE; - buf = (char *) bfd_malloc (size); + buf = (char *) bfd_malloc (size + 1); if (buf == NULL) return FALSE; + /* PR 17512: file: ec08f814 + 0-termintate the buffer so that string searches will not overflow. */ + buf[size] = 0; + if (bfd_bread (buf, size, abfd) != size || !elf_parse_notes (abfd, buf, size, offset)) { @@ -9867,6 +10949,12 @@ _bfd_elf_rel_local_sym (bfd *abfd, sym->st_value + addend); } +/* Adjust an address within a section. Given OFFSET within SEC, return + the new offset within the section, based upon changes made to the + section. Returns -1 if the offset is now invalid. + The offset (in abnd out) is in target sized bytes, however big a + byte may be. */ + bfd_vma _bfd_elf_section_offset (bfd *abfd, struct bfd_link_info *info, @@ -9880,12 +10968,17 @@ _bfd_elf_section_offset (bfd *abfd, offset); case SEC_INFO_TYPE_EH_FRAME: return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset); + default: if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0) { + /* Reverse the offset. */ const struct elf_backend_data *bed = get_elf_backend_data (abfd); bfd_size_type address_size = bed->s->arch_size / 8; - offset = sec->size - offset - address_size; + + /* address_size and sec->size are in octets. Convert + to bytes before subtracting the original offset. */ + offset = (sec->size - address_size) / bfd_octets_per_byte (abfd) - offset; } return offset; } @@ -10033,10 +11126,12 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd, return n; } -/* It is only used by x86-64 so far. */ +/* It is only used by x86-64 so far. + ??? This repeats *COM* id of zero. sec->id is supposed to be unique, + but current usage would allow all of _bfd_std_section to be zero. t*/ asection _bfd_elf_large_com_section - = BFD_FAKE_SECTION (_bfd_elf_large_com_section, - SEC_IS_COMMON, NULL, "LARGE_COMMON", 0); + = BFD_FAKE_SECTION (_bfd_elf_large_com_section, NULL, + "LARGE_COMMON", 0, SEC_IS_COMMON); void _bfd_elf_post_process_headers (bfd * abfd,