X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf.c;h=f3364eeddf2a5db3b8e209e82c76278af574c83b;hb=6f6fd151cbf226bbaa66e44977f57b7c6dc33d89;hp=1926ecc80375bc31ec7a5943d2f19fd44f668a23;hpb=015ec493d8603095d212df443e7b75017b572455;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index 1926ecc803..f3364eeddf 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -857,11 +857,10 @@ _bfd_elf_setup_sections (bfd *abfd) if (elfsec == 0) { 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 */ - (_("%pB: warning: sh_link not set for section `%pA'"), - abfd, s); + bed->link_order_error_handler + /* xgettext:c-format */ + (_("%pB: warning: sh_link not set for section `%pA'"), + abfd, s); } else { @@ -1424,9 +1423,8 @@ copy_special_section_fields (const bfd *ibfd, } /* 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)) + if (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 @@ -1610,8 +1608,8 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) { /* Final attempt. Call the backend copy function with a NULL input section. */ - if (bed->elf_backend_copy_special_section_fields != NULL) - (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader); + (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd, + NULL, oheader); } } @@ -1885,10 +1883,12 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg) return FALSE; } -/* Get version string. */ +/* Get version name. If BASE_P is TRUE, return "Base" for VER_FLG_BASE + and return symbol version for symbol version itself. */ const char * _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol, + bfd_boolean base_p, bfd_boolean *hidden) { const char *version_string = NULL; @@ -1906,10 +1906,18 @@ _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol, && (vernum > elf_tdata (abfd)->cverdefs || (elf_tdata (abfd)->verdef[0].vd_flags == VER_FLG_BASE))) - version_string = "Base"; + version_string = base_p ? "Base" : ""; else if (vernum <= elf_tdata (abfd)->cverdefs) - version_string = - elf_tdata (abfd)->verdef[vernum - 1].vd_nodename; + { + const char *nodename + = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename; + version_string = ""; + if (base_p + || nodename == NULL + || symbol->name == NULL + || strcmp (symbol->name, nodename) != 0) + version_string = nodename; + } else { Elf_Internal_Verneed *t; @@ -1990,6 +1998,7 @@ bfd_elf_print_symbol (bfd *abfd, /* If we have version information, print it. */ version_string = _bfd_elf_get_symbol_version_string (abfd, symbol, + TRUE, &hidden); if (version_string) { @@ -2462,12 +2471,12 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) sections. */ if (*p_hdr != NULL) { - if (bed->init_secondary_reloc_section == NULL - || ! bed->init_secondary_reloc_section (abfd, hdr, name, shindex)) + if (!bed->init_secondary_reloc_section (abfd, hdr, name, shindex)) { _bfd_error_handler /* xgettext:c-format */ - (_("%pB: warning: secondary relocation section '%s' for section %pA found - ignoring"), + (_("%pB: warning: secondary relocation section '%s' " + "for section %pA found - ignoring"), abfd, name, target_sect); } goto success; @@ -3533,8 +3542,13 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) if (symindx == 0) { /* If called from the assembler, swap_out_syms will have set up - elf_section_syms. */ - BFD_ASSERT (elf_section_syms (abfd) != NULL); + elf_section_syms. + PR 25699: A corrupt input file could contain bogus group info. */ + if (elf_section_syms (abfd) == NULL) + { + *failedptr = TRUE; + return; + } symindx = elf_section_syms (abfd)[sec->index]->udata.i; } elf_section_data (sec)->this_hdr.sh_info = symindx; @@ -3935,11 +3949,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) where s is NULL. */ 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 */ - (_("%pB: warning: sh_link not set for section `%pA'"), - abfd, sec); + bed->link_order_error_handler + /* xgettext:c-format */ + (_("%pB: warning: sh_link not set for section `%pA'"), + abfd, sec); } } @@ -3989,9 +4002,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) elf_section_data (s)->this_hdr.sh_link = d->this_idx; /* This is a .stab section. */ - if (elf_section_data (s)->this_hdr.sh_entsize == 0) - elf_section_data (s)->this_hdr.sh_entsize - = 4 + 2 * bfd_get_arch_size (abfd) / 8; + elf_section_data (s)->this_hdr.sh_entsize = 12; } } break; @@ -5196,9 +5207,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) { i = m->count; while (--i != (unsigned) -1) - if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) - == (SEC_LOAD | SEC_HAS_CONTENTS)) - break; + { + if (m->sections[i]->size > 0 + && (m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) + == (SEC_LOAD | SEC_HAS_CONTENTS)) + break; + } if (i != (unsigned) -1) break; @@ -5312,19 +5326,25 @@ elf_sort_segments (const void *arg1, const void *arg2) return m1->no_sort_lma ? -1 : 1; if (m1->p_type == PT_LOAD && !m1->no_sort_lma) { - unsigned int opb = bfd_octets_per_byte (m1->sections[0]->owner, - m1->sections[0]); - bfd_vma lma1, lma2; /* Bytes. */ + bfd_vma lma1, lma2; /* Octets. */ lma1 = 0; if (m1->p_paddr_valid) - lma1 = m1->p_paddr / opb; + lma1 = m1->p_paddr; else if (m1->count != 0) - lma1 = m1->sections[0]->lma + m1->p_vaddr_offset; + { + unsigned int opb = bfd_octets_per_byte (m1->sections[0]->owner, + m1->sections[0]); + lma1 = (m1->sections[0]->lma + m1->p_vaddr_offset) * opb; + } lma2 = 0; if (m2->p_paddr_valid) - lma2 = m2->p_paddr / opb; + lma2 = m2->p_paddr; else if (m2->count != 0) - lma2 = m2->sections[0]->lma + m2->p_vaddr_offset; + { + unsigned int opb = bfd_octets_per_byte (m2->sections[0]->owner, + m2->sections[0]); + lma2 = (m2->sections[0]->lma + m2->p_vaddr_offset) * opb; + } if (lma1 != lma2) return lma1 < lma2 ? -1 : 1; } @@ -5815,10 +5835,11 @@ assign_file_positions_for_load_sections (bfd *abfd, } p->p_memsz += adjust; - if (this_hdr->sh_type != SHT_NOBITS) + if (p->p_type == PT_LOAD) { - if (p->p_type == PT_LOAD) + if (this_hdr->sh_type != SHT_NOBITS) { + off_adjust = 0; if (p->p_filesz + adjust < p->p_memsz) { /* We have a PROGBITS section following NOBITS ones. @@ -5828,10 +5849,25 @@ assign_file_positions_for_load_sections (bfd *abfd, if (!write_zeros (abfd, off, adjust)) return FALSE; } + } + /* We only adjust sh_offset in SHT_NOBITS sections + as would seem proper for their address when the + section is first in the segment. sh_offset + doesn't really have any significance for + SHT_NOBITS anyway, apart from a notional position + relative to other sections. Historically we + didn't bother with adjusting sh_offset and some + programs depend on it not being adjusted. See + pr12921 and pr25662. */ + if (this_hdr->sh_type != SHT_NOBITS || i == 0) + { off += adjust; + if (this_hdr->sh_type == SHT_NOBITS) + off_adjust += adjust; } - p->p_filesz += adjust; } + if (this_hdr->sh_type != SHT_NOBITS) + p->p_filesz += adjust; } if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core) @@ -7895,19 +7931,34 @@ _bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded) elf_section_flags (s->output_section) &= ~SHF_GROUP; elf_group_name (s->output_section) = NULL; } - /* Conversely, if the member section is not being output - but the SHT_GROUP section is, then adjust its size. */ - else if (s->output_section == discarded - && isec->output_section != discarded) + else { struct bfd_elf_section_data *elf_sec = elf_section_data (s); - removed += 4; - if (elf_sec->rel.hdr != NULL - && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0) - removed += 4; - if (elf_sec->rela.hdr != NULL - && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0) - removed += 4; + if (s->output_section == discarded + && isec->output_section != discarded) + { + /* Conversely, if the member section is not being + output but the SHT_GROUP section is, then adjust + its size. */ + removed += 4; + if (elf_sec->rel.hdr != NULL + && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0) + removed += 4; + if (elf_sec->rela.hdr != NULL + && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0) + removed += 4; + } + else + { + /* Also adjust for zero-sized relocation member + section. */ + if (elf_sec->rel.hdr != NULL + && elf_sec->rel.hdr->sh_size == 0) + removed += 4; + if (elf_sec->rela.hdr != NULL + && elf_sec->rela.hdr->sh_size == 0) + removed += 4; + } } s = elf_next_in_group (s); if (s == first) @@ -10749,12 +10800,18 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note) case NT_NETBSDCORE_AUXV: /* NetBSD-specific Elf Auxiliary Vector data. */ return elfcore_make_auxv_note_section (abfd, note, 4); +#endif +#ifdef NT_NETBSDCORE_LWPSTATUS + case NT_NETBSDCORE_LWPSTATUS: + return elfcore_make_note_pseudosection (abfd, + ".note.netbsdcore.lwpstatus", + note); #endif default: break; } - /* As of March 2017 there are no other machine-independent notes + /* As of March 2020 there are no other machine-independent notes defined for NetBSD core files. If the note type is less than the start of the machine-dependent note types, we don't understand it. */ @@ -12442,6 +12499,7 @@ _bfd_elf_slurp_secondary_reloc_section (bfd * abfd, reloc_count = NUM_SHDR_ENTRIES (hdr); if (_bfd_mul_overflow (reloc_count, sizeof (arelent), & amt)) { + free (native_relocs); bfd_set_error (bfd_error_file_too_big); result = FALSE; continue; @@ -12460,7 +12518,8 @@ _bfd_elf_slurp_secondary_reloc_section (bfd * abfd, != hdr->sh_size)) { free (native_relocs); - free (internal_relocs); + /* The internal_relocs will be freed when + the memory for the bfd is released. */ result = FALSE; continue; } @@ -12578,13 +12637,31 @@ _bfd_elf_copy_special_section_fields (const bfd * ibfd ATTRIBUTE_UNUSED, } /* Find the output section that corresponds to the isection's sh_info link. */ - BFD_ASSERT (isection->sh_info > 0 - && isection->sh_info < elf_numsections (ibfd)); + if (isection->sh_info == 0 + || isection->sh_info >= elf_numsections (ibfd)) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): info section index is invalid"), + obfd, osec); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + isection = elf_elfsections (ibfd)[isection->sh_info]; - BFD_ASSERT (isection != NULL); - BFD_ASSERT (isection->bfd_section != NULL); - BFD_ASSERT (isection->bfd_section->output_section != NULL); + if (isection == NULL + || isection->bfd_section == NULL + || isection->bfd_section->output_section == NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): info section index cannot be set because the section is not in the output"), + obfd, osec); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + osection->sh_info = elf_section_data (isection->bfd_section->output_section)->this_idx; @@ -12605,6 +12682,10 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) bfd_vma addr_offset; asection * relsec; bfd_vma (*r_info) (bfd_vma, bfd_vma); + bfd_boolean result = TRUE; + + if (sec == NULL) + return FALSE; #if BFD_DEFAULT_TARGET_SIZE > 32 if (bfd_arch_bits_per_address (abfd) != 32) @@ -12613,9 +12694,6 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) #endif r_info = elf32_r_info; - if (sec == NULL) - return FALSE; - /* The address of an ELF reloc is section relative for an object file, and absolute for an executable file or shared library. The address of a BFD reloc is always section relative. */ @@ -12640,10 +12718,28 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) arelent * src_irel; bfd_byte * dst_rela; - BFD_ASSERT (hdr->contents == NULL); + if (hdr->contents != NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc section processed twice"), + abfd, relsec); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + continue; + } reloc_count = hdr->sh_size / hdr->sh_entsize; - BFD_ASSERT (reloc_count > 0); + if (reloc_count <= 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc section is empty!"), + abfd, relsec); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + continue; + } hdr->contents = bfd_alloc (abfd, hdr->sh_size); if (hdr->contents == NULL) @@ -12657,7 +12753,16 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) last_sym_idx = 0; dst_rela = hdr->contents; src_irel = (arelent *) esd->sec_info; - BFD_ASSERT (src_irel != NULL); + if (src_irel == NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: internal relocs missing for secondary reloc section"), + abfd, relsec); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + continue; + } for (idx = 0; idx < reloc_count; idx++, dst_rela += hdr->sh_entsize) { @@ -12667,55 +12772,78 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) int n; ptr = src_irel + idx; - sym = *ptr->sym_ptr_ptr; + if (ptr == NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: reloc table entry %u is empty"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + break; + } - if (sym == last_sym) - n = last_sym_idx; + if (ptr->sym_ptr_ptr == NULL) + { + /* FIXME: Is this an error ? */ + n = 0; + } else { - last_sym = sym; - n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym); - if (n < 0) + sym = *ptr->sym_ptr_ptr; + + if (sym == last_sym) + n = last_sym_idx; + else { -#if DEBUG_SECONDARY_RELOCS - fprintf (stderr, "failed to find symbol %s whilst rewriting relocs\n", - sym->name); -#endif - /* FIXME: Signal failure somehow. */ - n = 0; + n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym); + if (n < 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc %u references a missing symbol"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + n = 0; + } + + last_sym = sym; + last_sym_idx = n; } - last_sym_idx = n; - } - if ((*ptr->sym_ptr_ptr)->the_bfd != NULL - && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec - && ! _bfd_elf_validate_reloc (abfd, ptr)) - { -#if DEBUG_SECONDARY_RELOCS - fprintf (stderr, "symbol %s is not in the output bfd\n", - sym->name); -#endif - /* FIXME: Signal failure somehow. */ - n = 0; + if (sym->the_bfd != NULL + && sym->the_bfd->xvec != abfd->xvec + && ! _bfd_elf_validate_reloc (abfd, ptr)) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc %u references a deleted symbol"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + n = 0; + } } + src_rela.r_offset = ptr->address + addr_offset; if (ptr->howto == NULL) { -#if DEBUG_SECONDARY_RELOCS - fprintf (stderr, "reloc for symbol %s does not have a howto associated with it\n", - sym->name); -#endif - /* FIXME: Signal failure somehow. */ - n = 0; + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc %u is of an unknown type"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + src_rela.r_info = r_info (0, 0); } - - src_rela.r_offset = ptr->address + addr_offset; - src_rela.r_info = r_info (n, ptr->howto->type); + else + src_rela.r_info = r_info (n, ptr->howto->type); src_rela.r_addend = ptr->addend; ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela); } } } - return TRUE; + return result; }