X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf.c;h=cbc0c918f8809bd0d75ef53b771c2c70dbd96511;hb=68f5ff89edd041719c0d45e1f716a5251d7be768;hp=b4043b129281de336268546e209f5fe616f4c593;hpb=c6d8cab4ac5c906937dcd4f884e65fb4d1052381;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index b4043b1292..cbc0c918f8 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1,8 +1,6 @@ /* ELF executable support for BFD. - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + Copyright (C) 1993-2015 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -44,6 +42,7 @@ SECTION #include "elf-bfd.h" #include "libiberty.h" #include "safe-ctype.h" +#include "elf-linux-psinfo.h" #ifdef CORE_HEADER #include CORE_HEADER @@ -244,7 +243,14 @@ bfd_elf_allocate_object (bfd *abfd, return FALSE; elf_object_id (abfd) = object_id; - elf_program_header_size (abfd) = (bfd_size_type) -1; + if (abfd->direction != read_direction) + { + struct output_elf_obj_tdata *o = bfd_zalloc (abfd, sizeof *o); + if (o == NULL) + return FALSE; + elf_tdata (abfd)->o = o; + elf_program_header_size (abfd) = (bfd_size_type) -1; + } return TRUE; } @@ -261,7 +267,10 @@ bfd_boolean bfd_elf_mkcorefile (bfd *abfd) { /* I think this can be done just like an object file. */ - return abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd); + if (!abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd)) + return FALSE; + elf_tdata (abfd)->core = bfd_zalloc (abfd, sizeof (*elf_tdata (abfd)->core)); + return elf_tdata (abfd)->core != NULL; } static char * @@ -288,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 @@ -323,9 +333,19 @@ 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. */ + _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) { @@ -599,9 +619,10 @@ 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); + (_("%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); @@ -609,7 +630,16 @@ 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 + (_("%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, @@ -617,6 +647,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; @@ -642,6 +673,21 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) } } } + + /* 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); + } + } } } @@ -707,6 +753,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) { (*_bfd_error_handler) (_("%B: no group info for section %A"), abfd, newsect); + return FALSE; } return TRUE; } @@ -880,45 +927,25 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, { /* The debugging sections appear to be recognized only by name, not any sort of flag. Their SEC_ALLOC bits are cleared. */ - static const struct - { - const char *name; - int len; - } debug_sections [] = - { - { STRING_COMMA_LEN ("debug") }, /* 'd' */ - { NULL, 0 }, /* 'e' */ - { NULL, 0 }, /* 'f' */ - { STRING_COMMA_LEN ("gnu.linkonce.wi.") }, /* 'g' */ - { NULL, 0 }, /* 'h' */ - { NULL, 0 }, /* 'i' */ - { NULL, 0 }, /* 'j' */ - { NULL, 0 }, /* 'k' */ - { STRING_COMMA_LEN ("line") }, /* 'l' */ - { NULL, 0 }, /* 'm' */ - { NULL, 0 }, /* 'n' */ - { NULL, 0 }, /* 'o' */ - { NULL, 0 }, /* 'p' */ - { NULL, 0 }, /* 'q' */ - { NULL, 0 }, /* 'r' */ - { STRING_COMMA_LEN ("stab") }, /* 's' */ - { NULL, 0 }, /* 't' */ - { NULL, 0 }, /* 'u' */ - { NULL, 0 }, /* 'v' */ - { NULL, 0 }, /* 'w' */ - { NULL, 0 }, /* 'x' */ - { NULL, 0 }, /* 'y' */ - { STRING_COMMA_LEN ("zdebug") } /* 'z' */ - }; - if (name [0] == '.') { - int i = name [1] - 'd'; - if (i >= 0 - && i < (int) ARRAY_SIZE (debug_sections) - && debug_sections [i].name != NULL - && strncmp (&name [1], debug_sections [i].name, - debug_sections [i].len) == 0) + const char *p; + int n; + if (name[1] == 'd') + p = ".debug", n = 6; + else if (name[1] == 'g' && name[2] == 'n') + p = ".gnu.linkonce.wi.", n = 17; + else if (name[1] == 'g' && name[2] == 'd') + p = ".gdb_index", n = 11; /* yes we really do mean 11. */ + else if (name[1] == 'l') + p = ".line", n = 5; + else if (name[1] == 's') + p = ".stab", n = 5; + else if (name[1] == 'z') + p = ".zdebug", n = 7; + else + p = NULL, n = 0; + if (p != NULL && strncmp (name, p, n) == 0) flags |= SEC_DEBUGGING; } } @@ -1042,16 +1069,22 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, abfd, name); return FALSE; } - if (name[1] != 'z') + /* PR binutils/18087: Compression does not always make a section + smaller. So only rename the section when compression has + actually taken place. */ + if (newsect->compress_status == COMPRESS_SECTION_DONE) { - unsigned int len = strlen (name); + 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); + 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: @@ -1128,13 +1161,17 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; - BFD_ASSERT (!elf_flags_init (obfd) - || (elf_elfheader (obfd)->e_flags - == elf_elfheader (ibfd)->e_flags)); + if (!elf_flags_init (obfd)) + { + elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + elf_flags_init (obfd) = TRUE; + } elf_gp (obfd) = elf_gp (ibfd); - elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; - elf_flags_init (obfd) = TRUE; + + /* Also copy the EI_OSABI field. */ + elf_elfheader (obfd)->e_ident[EI_OSABI] = + elf_elfheader (ibfd)->e_ident[EI_OSABI]; /* Copy object attributes. */ _bfd_elf_copy_obj_attributes (ibfd, obfd); @@ -1234,8 +1271,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 = ""; @@ -1403,6 +1445,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 @@ -1429,6 +1518,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*)"; @@ -1454,45 +1545,12 @@ bfd_elf_print_symbol (bfd *abfd, bfd_fprintf_vma (abfd, file, val); /* If we have version information, print it. */ - if (elf_tdata (abfd)->dynversym_section != 0 - && (elf_tdata (abfd)->dynverdef_section != 0 - || elf_tdata (abfd)->dynverref_section != 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 { @@ -1559,38 +1617,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 @@ -1604,11 +1698,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; @@ -1637,24 +1731,26 @@ 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; } + BFD_ASSERT (elf_onesymtab (abfd) == 0); elf_onesymtab (abfd) = shindex; elf_tdata (abfd)->symtab_hdr = *hdr; @@ -1671,7 +1767,7 @@ 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 @@ -1697,26 +1793,29 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) break; } if (i != shindex) - return bfd_section_from_shdr (abfd, i); + ret = bfd_section_from_shdr (abfd, i); } - return TRUE; + goto success; - case SHT_DYNSYM: /* A dynamic symbol table */ + 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; } + BFD_ASSERT (elf_dynsymtab (abfd) == 0); elf_dynsymtab (abfd) = shindex; elf_tdata (abfd)->dynsymtab_hdr = *hdr; @@ -1725,34 +1824,38 @@ 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); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; - case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections */ + case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections. */ if (elf_symtab_shndx (abfd) == shindex) - return TRUE; + 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; + 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: @@ -1761,8 +1864,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 @@ -1780,9 +1884,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) @@ -1790,7 +1894,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: @@ -1805,7 +1910,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) 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) @@ -1813,8 +1918,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) ((*_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); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; } /* For some incomprehensible reason Oracle distributes @@ -1855,7 +1961,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 @@ -1870,14 +1976,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) @@ -1885,11 +1995,13 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) else p_hdr = &esdt->rel.hdr; - BFD_ASSERT (*p_hdr == NULL); + /* PR 17512: file: 0b4f81b7. */ + if (*p_hdr != NULL) + goto fail; amt = sizeof (*hdr2); hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); if (hdr2 == NULL) - return FALSE; + goto fail; *hdr2 = *hdr; *p_hdr = hdr2; elf_elfsections (abfd)[shindex] = hdr2; @@ -1905,46 +2017,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; @@ -1958,7 +2079,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) } } } - break; + goto success; default: /* Possibly an attributes section. */ @@ -1966,14 +2087,14 @@ 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) { @@ -1985,9 +2106,12 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) "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) @@ -2008,8 +2132,11 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) "`%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. */ @@ -2017,10 +2144,20 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) (_("%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. */ @@ -2081,6 +2218,9 @@ static const struct bfd_elf_special_section special_sections_d[] = { { STRING_COMMA_LEN (".data"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".data1"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, + /* There are more DWARF sections than these, but they needn't be added here + unless you have to cope with broken compilers that don't emit section + attributes or you want to help the user writing assembler. */ { STRING_COMMA_LEN (".debug"), 0, SHT_PROGBITS, 0 }, { STRING_COMMA_LEN (".debug_line"), 0, SHT_PROGBITS, 0 }, { STRING_COMMA_LEN (".debug_info"), 0, SHT_PROGBITS, 0 }, @@ -2529,7 +2669,7 @@ _bfd_elf_single_rel_hdr (asection *sec) USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL relocations. */ -bfd_boolean +static bfd_boolean _bfd_elf_init_reloc_shdr (bfd *abfd, struct bfd_elf_section_reloc_data *reldata, asection *asect, @@ -2624,6 +2764,15 @@ 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) + (_("%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. */ @@ -2925,6 +3074,40 @@ 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) + name = ".got.plt"; + + 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. */ @@ -2989,9 +3172,9 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) d->rela.idx = 0; } - t->shstrtab_section = section_number++; + elf_shstrtab_sec (abfd) = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name); - elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section; + elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd); need_symtab = (bfd_get_symcount (abfd) > 0 || (link_info == NULL @@ -2999,18 +3182,18 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) == HAS_RELOC))); if (need_symtab) { - t->symtab_section = section_number++; + elf_onesymtab (abfd) = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name); if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF)) { - t->symtab_shndx_section = section_number++; + elf_symtab_shndx (abfd) = section_number++; t->symtab_shndx_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) return FALSE; } - t->strtab_section = section_number++; + elf_strtab_sec (abfd) = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name); } @@ -3044,23 +3227,22 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) elf_elfsections (abfd) = i_shdrp; - i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr; + i_shdrp[elf_shstrtab_sec (abfd)] = &t->shstrtab_hdr; if (need_symtab) { - i_shdrp[t->symtab_section] = &t->symtab_hdr; + i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr; if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF)) { - i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr; - t->symtab_shndx_hdr.sh_link = t->symtab_section; + i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr; + t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd); } - i_shdrp[t->strtab_section] = &t->strtab_hdr; - t->symtab_hdr.sh_link = t->strtab_section; + i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr; + t->symtab_hdr.sh_link = elf_strtab_sec (abfd); } for (sec = abfd->sections; sec; sec = sec->next) { asection *s; - const char *name; d = elf_section_data (sec); @@ -3077,13 +3259,15 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) the relocation entries apply. */ if (d->rel.idx != 0) { - d->rel.hdr->sh_link = t->symtab_section; + d->rel.hdr->sh_link = elf_onesymtab (abfd); d->rel.hdr->sh_info = d->this_idx; + d->rel.hdr->sh_flags |= SHF_INFO_LINK; } if (d->rela.idx != 0) { - d->rela.hdr->sh_link = t->symtab_section; + d->rela.hdr->sh_link = elf_onesymtab (abfd); d->rela.hdr->sh_info = d->this_idx; + d->rela.hdr->sh_flags |= SHF_INFO_LINK; } /* We need to set up sh_link for SHF_LINK_ORDER. */ @@ -3162,15 +3346,12 @@ 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; + { + d->this_hdr.sh_info = elf_section_data (s)->this_idx; + d->this_hdr.sh_flags |= SHF_INFO_LINK; + } break; case SHT_STRTAB: @@ -3237,7 +3418,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) break; case SHT_GROUP: - d->this_hdr.sh_link = t->symtab_section; + d->this_hdr.sh_link = elf_onesymtab (abfd); } } @@ -3288,7 +3469,7 @@ ignore_section_sym (bfd *abfd, asymbol *sym) all local symbols to be at the head of the list. */ static bfd_boolean -elf_map_symbols (bfd *abfd) +elf_map_symbols (bfd *abfd, unsigned int *pnum_locals) { unsigned int symcount = bfd_get_symcount (abfd); asymbol **syms = bfd_get_outsymbols (abfd); @@ -3404,8 +3585,7 @@ elf_map_symbols (bfd *abfd) bfd_set_symtab (abfd, new_syms, num_locals + num_globals); - elf_num_locals (abfd) = num_locals; - elf_num_globals (abfd) = num_globals; + *pnum_locals = num_locals; return TRUE; } @@ -3462,8 +3642,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, return FALSE; /* Post process the headers if necessary. */ - if (bed->elf_backend_post_process_headers) - (*bed->elf_backend_post_process_headers) (abfd, link_info); + (*bed->elf_backend_post_process_headers) (abfd, link_info); fsargs.failed = FALSE; fsargs.link_info = link_info; @@ -3516,7 +3695,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, file_ptr off; Elf_Internal_Shdr *hdr; - off = elf_tdata (abfd)->next_file_pos; + off = elf_next_file_pos (abfd); hdr = &elf_tdata (abfd)->symtab_hdr; off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); @@ -3528,7 +3707,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, hdr = &elf_tdata (abfd)->strtab_hdr; off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; /* Now that we know where the .strtab section goes, write it out. */ @@ -3579,13 +3758,13 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info) ++segs; } - if (elf_tdata (abfd)->eh_frame_hdr) + if (elf_eh_frame_hdr (abfd)) { /* We need a PT_GNU_EH_FRAME segment. */ ++segs; } - if (elf_tdata (abfd)->stack_flags) + if (elf_stack_flags (abfd)) { /* We need a PT_GNU_STACK segment. */ ++segs; @@ -3647,8 +3826,7 @@ _bfd_elf_find_segment_containing_section (bfd * abfd, asection * section) struct elf_segment_map *m; Elf_Internal_Phdr *p; - for (m = elf_tdata (abfd)->segment_map, - p = elf_tdata (abfd)->phdr; + for (m = elf_seg_map (abfd), p = elf_tdata (abfd)->phdr; m != NULL; m = m->next, p++) { @@ -3732,7 +3910,7 @@ elf_modify_segment_map (bfd *abfd, sections from the segment map. We also remove excluded sections. Finally, any PT_LOAD segment without sections is removed. */ - m = &elf_tdata (abfd)->segment_map; + m = &elf_seg_map (abfd); while (*m) { unsigned int i, new_count; @@ -3776,7 +3954,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) const struct elf_backend_data *bed = get_elf_backend_data (abfd); bfd_boolean no_user_phdrs; - no_user_phdrs = elf_tdata (abfd)->segment_map == NULL; + no_user_phdrs = elf_seg_map (abfd) == NULL; if (info != NULL) info->user_phdrs = !no_user_phdrs; @@ -3875,6 +4053,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 @@ -3887,10 +4070,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) program headers we will need. */ if (count > 0) { - bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size; + bfd_size_type phdr_size = elf_program_header_size (abfd); if (phdr_size == (bfd_size_type) -1) phdr_size = get_program_header_size (abfd, info); + phdr_size += bed->s->sizeof_ehdr; if ((abfd->flags & D_PAGED) == 0 || (sections[0]->lma & addr_mask) < phdr_size || ((sections[0]->lma & addr_mask) % maxpagesize @@ -4118,11 +4302,31 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) /* Mandated PF_R. */ m->p_flags = PF_R; m->p_flags_valid = 1; + s = first_tls; for (i = 0; i < (unsigned int) tls_count; ++i) { - BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL); - m->sections[i] = first_tls; - first_tls = first_tls->next; + if ((s->flags & SEC_THREAD_LOCAL) == 0) + { + _bfd_error_handler + (_("%B: TLS sections are not adjacent:"), abfd); + s = first_tls; + i = 0; + while (i < (unsigned int) tls_count) + { + if ((s->flags & SEC_THREAD_LOCAL) != 0) + { + _bfd_error_handler (_(" TLS: %A"), s); + i++; + } + else + _bfd_error_handler (_(" non-TLS: %A"), s); + s = s->next; + } + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + m->sections[i] = s; + s = s->next; } *pm = m; @@ -4131,7 +4335,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME segment. */ - eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr; + eh_frame_hdr = elf_eh_frame_hdr (abfd); if (eh_frame_hdr != NULL && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0) { @@ -4148,7 +4352,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) pm = &m->next; } - if (elf_tdata (abfd)->stack_flags) + if (elf_stack_flags (abfd)) { amt = sizeof (struct elf_segment_map); m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); @@ -4156,8 +4360,15 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) goto error_return; m->next = NULL; m->p_type = PT_GNU_STACK; - m->p_flags = elf_tdata (abfd)->stack_flags; + m->p_flags = elf_stack_flags (abfd); + m->p_align = bed->stack_align; m->p_flags_valid = 1; + m->p_align_valid = m->p_align != 0; + if (info->stacksize > 0) + { + m->p_size = info->stacksize; + m->p_size_valid = 1; + } *pm = m; pm = &m->next; @@ -4178,11 +4389,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) == (SEC_LOAD | SEC_HAS_CONTENTS)) break; - if (i == (unsigned) -1) - continue; - - if (m->sections[i]->vma + m->sections[i]->size - >= info->relro_end) + if (i != (unsigned) -1) break; } } @@ -4205,15 +4412,15 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) } free (sections); - elf_tdata (abfd)->segment_map = mfirst; + elf_seg_map (abfd) = mfirst; } if (!elf_modify_segment_map (abfd, info, no_user_phdrs)) return FALSE; - for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (count = 0, m = elf_seg_map (abfd); m != NULL; m = m->next) ++count; - elf_tdata (abfd)->program_header_size = count * bed->s->sizeof_phdr; + elf_program_header_size (abfd) = count * bed->s->sizeof_phdr; return TRUE; @@ -4307,6 +4514,9 @@ elf_sort_sections (const void *arg1, const void *arg2) static file_ptr vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize) { + /* PR binutils/16199: Handle an alignment of zero. */ + if (maxpagesize == 0) + maxpagesize = 1; return ((vma - off) % maxpagesize); } @@ -4377,7 +4587,7 @@ assign_file_positions_for_load_sections (bfd *abfd, return FALSE; alloc = 0; - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (abfd); m != NULL; m = m->next) { ++alloc; if (m->header_size) @@ -4398,32 +4608,32 @@ assign_file_positions_for_load_sections (bfd *abfd, elf_elfheader (abfd)->e_phnum = alloc; - if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1) - elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr; + if (elf_program_header_size (abfd) == (bfd_size_type) -1) + elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr; else - BFD_ASSERT (elf_tdata (abfd)->program_header_size + BFD_ASSERT (elf_program_header_size (abfd) >= alloc * bed->s->sizeof_phdr); if (alloc == 0) { - elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr; + elf_next_file_pos (abfd) = bed->s->sizeof_ehdr; return TRUE; } - /* We're writing the size in elf_tdata (abfd)->program_header_size, + /* We're writing the size in elf_program_header_size (abfd), see assign_file_positions_except_relocs, so make sure we have that amount allocated, with trailing space cleared. - The variable alloc contains the computed need, while elf_tdata - (abfd)->program_header_size contains the size used for the + The variable alloc contains the computed need, while + elf_program_header_size (abfd) contains the size used for the layout. See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments where the layout is forced to according to a larger size in the last iterations for the testcase ld-elf/header. */ - BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr + BFD_ASSERT (elf_program_header_size (abfd) % bed->s->sizeof_phdr == 0); phdrs = (Elf_Internal_Phdr *) bfd_zalloc2 (abfd, - (elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr), + (elf_program_header_size (abfd) / bed->s->sizeof_phdr), sizeof (Elf_Internal_Phdr)); elf_tdata (abfd)->phdr = phdrs; if (phdrs == NULL) @@ -4441,7 +4651,7 @@ assign_file_positions_for_load_sections (bfd *abfd, header_pad -= off; off += header_pad; - for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0; + for (m = elf_seg_map (abfd), p = phdrs, j = 0; m != NULL; m = m->next, p++, j++) { @@ -4783,6 +4993,7 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_flags |= PF_W; } } + off -= off_adjust; /* Check that all sections are in a PT_LOAD segment. @@ -4822,7 +5033,7 @@ assign_file_positions_for_load_sections (bfd *abfd, } } - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; return TRUE; } @@ -4848,10 +5059,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd, i_shdrpp = elf_elfsections (abfd); num_sec = elf_numsections (abfd); - off = elf_tdata (abfd)->next_file_pos; + off = elf_next_file_pos (abfd); for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++) { - struct elf_obj_tdata *tdata = elf_tdata (abfd); Elf_Internal_Shdr *hdr; hdr = *hdrpp; @@ -4881,9 +5091,9 @@ 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 == i_shdrpp[tdata->symtab_section] - || hdr == i_shdrpp[tdata->symtab_shndx_section] - || hdr == i_shdrpp[tdata->strtab_section]) + || hdr == i_shdrpp[elf_onesymtab (abfd)] + || hdr == i_shdrpp[elf_symtab_shndx (abfd)] + || hdr == i_shdrpp[elf_strtab_sec (abfd)]) hdr->sh_offset = -1; else off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); @@ -4898,9 +5108,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, phdrs_paddr = 0; hdrs_segment = NULL; phdrs = elf_tdata (abfd)->phdr; - for (m = elf_tdata (abfd)->segment_map, p = phdrs; - m != NULL; - m = m->next, p++) + for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++) { ++count; if (p->p_type != PT_LOAD) @@ -4946,7 +5154,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, s = hdrs_segment->sections[0]; else /* Use the first (i.e. lowest-addressed) section in any segment. */ - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (abfd); m != NULL; m = m->next) if (m->count != 0) { s = m->sections[0]; @@ -4970,9 +5178,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } } - for (m = elf_tdata (abfd)->segment_map, p = phdrs; - m != NULL; - m = m->next, p++) + for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++) { if (p->p_type == PT_GNU_RELRO) { @@ -4983,20 +5189,17 @@ assign_file_positions_for_non_load_sections (bfd *abfd, { /* During linking the range of the RELRO segment is passed in link_info. */ - for (lm = elf_tdata (abfd)->segment_map, lp = phdrs; + for (lm = elf_seg_map (abfd), lp = phdrs; lm != NULL; lm = lm->next, lp++) { if (lp->p_type == PT_LOAD && lp->p_vaddr < link_info->relro_end - && lp->p_vaddr + lp->p_filesz >= link_info->relro_end && lm->count != 0 && lm->sections[0]->vma >= link_info->relro_start) break; } - /* PR ld/14207. If the RELRO segment doesn't fit in the - LOAD segment, it should be removed. */ BFD_ASSERT (lm != NULL); } else @@ -5039,13 +5242,25 @@ assign_file_positions_for_non_load_sections (bfd *abfd, p->p_type = PT_NULL; } } + else if (p->p_type == PT_GNU_STACK) + { + if (m->p_size_valid) + p->p_memsz = m->p_size; + } else if (m->count != 0) { 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); + if (m->includes_filehdr || m->includes_phdrs) + { + /* PR 17512: file: 2195325e. */ + (*_bfd_error_handler) + (_("%B: warning: non-load segment includes file header and/or program header"), + abfd); + return FALSE; + } p->p_filesz = 0; p->p_offset = m->sections[0]->filepos; @@ -5076,7 +5291,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } } - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; return TRUE; } @@ -5101,7 +5316,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 @@ -5111,6 +5325,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; @@ -5125,15 +5340,17 @@ assign_file_positions_except_relocs (bfd *abfd, hdr = *hdrpp; if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) - || i == tdata->symtab_section - || i == tdata->symtab_shndx_section - || i == tdata->strtab_section) + || i == elf_onesymtab (abfd) + || i == elf_symtab_shndx (abfd) + || i == elf_strtab_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 { @@ -5154,22 +5371,34 @@ assign_file_positions_except_relocs (bfd *abfd, return FALSE; } + /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. */ + if (link_info != NULL + && link_info->executable + && link_info->shared) + { + unsigned int num_segments = elf_elfheader (abfd)->e_phnum; + Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr; + Elf_Internal_Phdr *end_segment = &segment[num_segments]; + + /* Find the lowest p_vaddr in PT_LOAD segments. */ + bfd_vma p_vaddr = (bfd_vma) -1; + for (; segment < end_segment; segment++) + if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr) + p_vaddr = segment->p_vaddr; + + /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD + segments is non-zero. */ + if (p_vaddr) + i_ehdrp->e_type = ET_EXEC; + } + /* Write out the program headers. */ - alloc = tdata->program_header_size / bed->s->sizeof_phdr; + alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr; 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 = tdata->next_file_pos; } - /* 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; - - tdata->next_file_pos = off; - return TRUE; } @@ -5254,7 +5483,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; @@ -5262,16 +5491,18 @@ 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 +static void _bfd_elf_assign_file_positions_for_relocs (bfd *abfd) { file_ptr off; unsigned int i, num_sec; Elf_Internal_Shdr **shdrpp; + Elf_Internal_Ehdr *i_ehdrp; + const struct elf_backend_data *bed; - off = elf_tdata (abfd)->next_file_pos; + off = elf_next_file_pos (abfd); num_sec = elf_numsections (abfd); for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++) @@ -5284,7 +5515,13 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd) off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE); } - elf_tdata (abfd)->next_file_pos = off; +/* 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; } bfd_boolean @@ -5294,6 +5531,7 @@ _bfd_elf_write_object_contents (bfd *abfd) Elf_Internal_Shdr **i_shdrp; bfd_boolean failed; unsigned int count, num_sec; + struct elf_obj_tdata *t; if (! abfd->output_has_begun && ! _bfd_elf_compute_section_file_positions (abfd, NULL)) @@ -5325,21 +5563,21 @@ _bfd_elf_write_object_contents (bfd *abfd) } /* Write out the section header names. */ + t = elf_tdata (abfd); if (elf_shstrtab (abfd) != NULL - && (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0 + && (bfd_seek (abfd, t->shstrtab_hdr.sh_offset, SEEK_SET) != 0 || !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd)))) return FALSE; if (bed->elf_backend_final_write_processing) - (*bed->elf_backend_final_write_processing) (abfd, - elf_tdata (abfd)->linker); + (*bed->elf_backend_final_write_processing) (abfd, elf_linker (abfd)); if (!bed->s->write_shdrs_and_ehdr (abfd)) return FALSE; /* This is last since write_shdrs_and_ehdr can touch i_shdrp[0]. */ - if (elf_tdata (abfd)->after_write_object_contents) - return (*elf_tdata (abfd)->after_write_object_contents) (abfd); + if (t->o->build_id.after_write_object_contents != NULL) + return (*t->o->build_id.after_write_object_contents) (abfd); return TRUE; } @@ -5763,8 +6001,8 @@ 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"), + (*_bfd_error_handler) (_("\ +%B: warning: Empty loadable segment detected, is this intentional ?"), ibfd); map->count = 0; @@ -6048,7 +6286,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) and carry on looping. */ amt = sizeof (struct elf_segment_map); amt += ((bfd_size_type) section_count - 1) * sizeof (asection *); - map = (struct elf_segment_map *) bfd_alloc (obfd, amt); + map = (struct elf_segment_map *) bfd_zalloc (obfd, amt); if (map == NULL) { free (sections); @@ -6073,7 +6311,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) free (sections); } - elf_tdata (obfd)->segment_map = map_first; + elf_seg_map (obfd) = map_first; /* If we had to estimate the number of program headers that were going to be needed, then check our estimate now and adjust @@ -6183,12 +6421,15 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) map->p_align_valid = 1; map->p_vaddr_offset = 0; - if (map->p_type == PT_GNU_RELRO) + if (map->p_type == PT_GNU_RELRO + || map->p_type == PT_GNU_STACK) { /* The PT_GNU_RELRO segment may contain the first a few bytes in the .got.plt section even if the whole .got.plt section isn't in the PT_GNU_RELRO segment. We won't - change the size of the PT_GNU_RELRO segment. */ + change the size of the PT_GNU_RELRO segment. + Similarly, PT_GNU_STACK size is significant on uclinux + systems. */ map->p_size = segment->p_memsz; map->p_size_valid = 1; } @@ -6211,7 +6452,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) phdr_included = TRUE; } - lowest_section = first_section; + lowest_section = NULL; if (section_count != 0) { unsigned int isec = 0; @@ -6224,12 +6465,14 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { map->sections[isec++] = section->output_section; - if (section->lma < lowest_section->lma) - lowest_section = section; if ((section->flags & SEC_ALLOC) != 0) { bfd_vma seg_off; + if (lowest_section == NULL + || section->lma < lowest_section->lma) + lowest_section = section; + /* Section lmas are set up from PT_LOAD header p_paddr in _bfd_elf_make_section_from_shdr. If this header has a p_paddr that disagrees @@ -6264,7 +6507,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) pointer_to_map = &map->next; } - elf_tdata (obfd)->segment_map = map_first; + elf_seg_map (obfd) = map_first; return TRUE; } @@ -6358,6 +6601,34 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd) } rewrite: + if (ibfd->xvec == obfd->xvec) + { + /* When rewriting program header, set the output maxpagesize to + the maximum alignment of input PT_LOAD segments. */ + Elf_Internal_Phdr *segment; + unsigned int i; + unsigned int num_segments = elf_elfheader (ibfd)->e_phnum; + bfd_vma maxpagesize = 0; + + for (i = 0, segment = elf_tdata (ibfd)->phdr; + i < num_segments; + i++, segment++) + if (segment->p_type == PT_LOAD + && maxpagesize < segment->p_align) + { + /* PR 17512: file: f17299af. */ + if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2)) + (*_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); + } + return rewrite_elf_program_header (ibfd, obfd); } @@ -6409,6 +6680,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; @@ -6535,7 +6811,7 @@ _bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd) entry point, because the latter is called after the section contents have been set, which means that the program headers have already been worked out. */ - if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL) + if (elf_seg_map (obfd) == NULL && elf_tdata (ibfd)->phdr != NULL) { if (! copy_private_bfd_data (ibfd, obfd)) return FALSE; @@ -6583,11 +6859,11 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd, shndx = MAP_ONESYMTAB; else if (shndx == elf_dynsymtab (ibfd)) shndx = MAP_DYNSYMTAB; - else if (shndx == elf_tdata (ibfd)->strtab_section) + else if (shndx == elf_strtab_sec (ibfd)) shndx = MAP_STRTAB; - else if (shndx == elf_tdata (ibfd)->shstrtab_section) + else if (shndx == elf_shstrtab_sec (ibfd)) shndx = MAP_SHSTRTAB; - else if (shndx == elf_tdata (ibfd)->symtab_shndx_section) + else if (shndx == elf_symtab_shndx (ibfd)) shndx = MAP_SYM_SHNDX; osym->internal_elf_sym.st_shndx = shndx; } @@ -6612,10 +6888,11 @@ swap_out_syms (bfd *abfd, bfd_byte *outbound_syms; bfd_byte *outbound_shndx; int idx; + unsigned int num_locals; bfd_size_type amt; bfd_boolean name_local_sections; - if (!elf_map_symbols (abfd)) + if (!elf_map_symbols (abfd, &num_locals)) return FALSE; /* Dump out the symtabs. */ @@ -6629,7 +6906,7 @@ swap_out_syms (bfd *abfd, symtab_hdr->sh_type = SHT_SYMTAB; symtab_hdr->sh_entsize = bed->s->sizeof_sym; symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1); - symtab_hdr->sh_info = elf_num_locals (abfd) + 1; + symtab_hdr->sh_info = num_locals + 1; symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align; symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; @@ -6763,15 +7040,16 @@ swap_out_syms (bfd *abfd, shndx = elf_dynsymtab (abfd); break; case MAP_STRTAB: - shndx = elf_tdata (abfd)->strtab_section; + shndx = elf_strtab_sec (abfd); break; case MAP_SHSTRTAB: - shndx = elf_tdata (abfd)->shstrtab_section; + shndx = elf_shstrtab_sec (abfd); break; case MAP_SYM_SHNDX: - shndx = elf_tdata (abfd)->symtab_shndx_section; + shndx = elf_symtab_shndx (abfd); break; default: + shndx = SHN_ABS; break; } } @@ -7096,26 +7374,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) @@ -7137,7 +7419,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; @@ -7152,7 +7434,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)); @@ -7165,36 +7447,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; @@ -7213,15 +7501,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)); @@ -7239,12 +7536,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)); @@ -7257,10 +7559,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; @@ -7275,12 +7578,7 @@ 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)); @@ -7300,7 +7598,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)); @@ -7313,16 +7611,20 @@ 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)); @@ -7331,10 +7633,11 @@ error_return_verdef: 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)); @@ -7364,7 +7667,7 @@ error_return_verdef: Elf_Internal_Verdef *iverdef; Elf_Internal_Verdaux *iverdaux; - iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];; + iverdef = &elf_tdata (abfd)->verdef[freeidx - 1]; iverdef->vd_version = VER_DEF_CURRENT; iverdef->vd_flags = 0; @@ -7377,14 +7680,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; @@ -7399,16 +7701,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 @@ -7471,152 +7769,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) -{ - static asection *last_section; - static asymbol *func; - static const char *filename; - static bfd_size_type func_size; - - if (symbols == NULL) - return FALSE; - - if (last_section != section - || func == NULL - || offset < func->value - || offset >= func->value + 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); - - filename = NULL; - func = NULL; - file = NULL; - low_func = 0; - state = nothing_seen; - func_size = 0; - 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 > func_size))) - { - func = sym; - func_size = size; - low_func = code_off; - filename = NULL; - if (file != NULL - && ((sym->flags & BSF_LOCAL) != 0 - || state != file_after_symbol_seen)) - filename = bfd_asymbol_name (file); - } - if (state == nothing_seen) - state = symbol_seen; - } - } - - if (func == NULL) - return FALSE; - - if (filename_ptr) - *filename_ptr = filename; - if (functionname_ptr) - *functionname_ptr = bfd_asymbol_name (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; } @@ -7631,8 +7811,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; @@ -7645,20 +7825,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 @@ -7688,21 +7858,21 @@ _bfd_elf_sizeof_headers (bfd *abfd, struct bfd_link_info *info) if (!info->relocatable) { - bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size; + bfd_size_type phdr_size = elf_program_header_size (abfd); if (phdr_size == (bfd_size_type) -1) { struct elf_segment_map *m; phdr_size = 0; - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (abfd); m != NULL; m = m->next) phdr_size += bed->s->sizeof_phdr; if (phdr_size == 0) phdr_size = get_program_header_size (abfd, info); } - elf_tdata (abfd)->program_header_size = phdr_size; + elf_program_header_size (abfd) = phdr_size; ret += phdr_size; } @@ -7717,7 +7887,7 @@ _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)) @@ -7842,7 +8012,7 @@ _bfd_elf_close_and_cleanup (bfd *abfd) struct elf_obj_tdata *tdata = elf_tdata (abfd); if (bfd_get_format (abfd) == bfd_object && tdata != NULL) { - if (elf_shstrtab (abfd) != NULL) + if (elf_tdata (abfd)->o != NULL && elf_shstrtab (abfd) != NULL) _bfd_elf_strtab_free (elf_shstrtab (abfd)); _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info); } @@ -7884,9 +8054,9 @@ elfcore_make_pid (bfd *abfd) { int pid; - pid = elf_tdata (abfd)->core_lwpid; + pid = elf_tdata (abfd)->core->lwpid; if (pid == 0) - pid = elf_tdata (abfd)->core_pid; + pid = elf_tdata (abfd)->core->pid; return pid; } @@ -7976,10 +8146,10 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) /* Do not overwrite the core signal if it has already been set by another thread. */ - if (elf_tdata (abfd)->core_signal == 0) - elf_tdata (abfd)->core_signal = prstat.pr_cursig; - if (elf_tdata (abfd)->core_pid == 0) - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal = prstat.pr_cursig; + if (elf_tdata (abfd)->core->pid == 0) + elf_tdata (abfd)->core->pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -7988,9 +8158,9 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) linux 2.[01] */ #if defined (HAVE_PRSTATUS_T_PR_WHO) - elf_tdata (abfd)->core_lwpid = prstat.pr_who; + elf_tdata (abfd)->core->lwpid = prstat.pr_who; #else - elf_tdata (abfd)->core_lwpid = prstat.pr_pid; + elf_tdata (abfd)->core->lwpid = prstat.pr_pid; #endif } #if defined (HAVE_PRSTATUS32_T) @@ -8005,10 +8175,10 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) /* Do not overwrite the core signal if it has already been set by another thread. */ - if (elf_tdata (abfd)->core_signal == 0) - elf_tdata (abfd)->core_signal = prstat.pr_cursig; - if (elf_tdata (abfd)->core_pid == 0) - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal = prstat.pr_cursig; + if (elf_tdata (abfd)->core->pid == 0) + elf_tdata (abfd)->core->pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -8017,9 +8187,9 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) linux 2.[01] */ #if defined (HAVE_PRSTATUS32_T_PR_WHO) - elf_tdata (abfd)->core_lwpid = prstat.pr_who; + elf_tdata (abfd)->core->lwpid = prstat.pr_who; #else - elf_tdata (abfd)->core_lwpid = prstat.pr_pid; + elf_tdata (abfd)->core->lwpid = prstat.pr_pid; #endif } #endif /* HAVE_PRSTATUS32_T */ @@ -8136,12 +8306,48 @@ elfcore_grok_s390_system_call (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-s390-system-call", note); } +static bfd_boolean +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) { return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note); } +static bfd_boolean +elfcore_grok_aarch_tls (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-tls", note); +} + +static bfd_boolean +elfcore_grok_aarch_hw_break (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-break", note); +} + +static bfd_boolean +elfcore_grok_aarch_hw_watch (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", note); +} + #if defined (HAVE_PRPSINFO_T) typedef prpsinfo_t elfcore_psinfo_t; #if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */ @@ -8193,13 +8399,13 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); #if defined (HAVE_PSINFO_T_PR_PID) || defined (HAVE_PRPSINFO_T_PR_PID) - elf_tdata (abfd)->core_pid = psinfo.pr_pid; + elf_tdata (abfd)->core->pid = psinfo.pr_pid; #endif - elf_tdata (abfd)->core_program + elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs)); } @@ -8212,13 +8418,13 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); #if defined (HAVE_PSINFO32_T_PR_PID) || defined (HAVE_PRPSINFO32_T_PR_PID) - elf_tdata (abfd)->core_pid = psinfo.pr_pid; + elf_tdata (abfd)->core->pid = psinfo.pr_pid; #endif - elf_tdata (abfd)->core_program + elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs)); } @@ -8236,7 +8442,7 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) implementations, so strip it off if it exists. */ { - char *command = elf_tdata (abfd)->core_command; + char *command = elf_tdata (abfd)->core->command; int n = strlen (command); if (0 < n && command[n - 1] == ' ') @@ -8261,7 +8467,7 @@ elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note) memcpy (&pstat, note->descdata, sizeof (pstat)); - elf_tdata (abfd)->core_pid = pstat.pr_pid; + elf_tdata (abfd)->core->pid = pstat.pr_pid; } #if defined (HAVE_PSTATUS32_T) else if (note->descsz == sizeof (pstatus32_t)) @@ -8271,7 +8477,7 @@ elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note) memcpy (&pstat, note->descdata, sizeof (pstat)); - elf_tdata (abfd)->core_pid = pstat.pr_pid; + elf_tdata (abfd)->core->pid = pstat.pr_pid; } #endif /* Could grab some more details from the "representative" @@ -8301,11 +8507,11 @@ elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note) memcpy (&lwpstat, note->descdata, sizeof (lwpstat)); - elf_tdata (abfd)->core_lwpid = lwpstat.pr_lwpid; + elf_tdata (abfd)->core->lwpid = lwpstat.pr_lwpid; /* Do not overwrite the core signal if it has already been set by another thread. */ - if (elf_tdata (abfd)->core_signal == 0) - elf_tdata (abfd)->core_signal = lwpstat.pr_cursig; + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal = lwpstat.pr_cursig; /* Make a ".reg/999" section. */ @@ -8388,11 +8594,11 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note) switch (type) { case 1 /* NOTE_INFO_PROCESS */: - /* FIXME: need to add ->core_command. */ + /* FIXME: need to add ->core->command. */ /* process_info.pid */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 8); + elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 8); /* process_info.signal */ - elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 12); + elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 12); break; case 2 /* NOTE_INFO_THREAD */: @@ -8575,6 +8781,27 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_S390_TDB: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_tdb (abfd, 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) @@ -8582,6 +8809,27 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_ARM_TLS: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_tls (abfd, note); + else + return TRUE; + + case NT_ARM_HW_BREAK: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_hw_break (abfd, note); + else + return TRUE; + + case NT_ARM_HW_WATCH: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_hw_watch (abfd, note); + else + return TRUE; + case NT_PRPSINFO: case NT_PSINFO: if (bed->elf_backend_grok_psinfo) @@ -8606,18 +8854,32 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) return TRUE; } + + case NT_FILE: + return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.file", + 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) { - elf_tdata (abfd)->build_id_size = note->descsz; - elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz); - if (elf_tdata (abfd)->build_id == NULL) + struct elf_obj_tdata *t; + + 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) return FALSE; - memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz); + t->build_id->size = note->descsz; + memcpy (t->build_id->data, note->descdata, note->descsz); return TRUE; } @@ -8682,15 +8944,15 @@ static bfd_boolean elfcore_grok_netbsd_procinfo (bfd *abfd, Elf_Internal_Note *note) { /* Signal number at offset 0x08. */ - elf_tdata (abfd)->core_signal + elf_tdata (abfd)->core->signal = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08); /* Process ID at offset 0x50. */ - elf_tdata (abfd)->core_pid + elf_tdata (abfd)->core->pid = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x50); /* Command name at 0x7c (max 32 bytes, including nul). */ - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31); return elfcore_make_note_pseudosection (abfd, ".note.netbsdcore.procinfo", @@ -8703,7 +8965,7 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note) int lwp; if (elfcore_netbsd_get_lwpid (note, &lwp)) - elf_tdata (abfd)->core_lwpid = lwp; + elf_tdata (abfd)->core->lwpid = lwp; if (note->type == NT_NETBSDCORE_PROCINFO) { @@ -8766,15 +9028,15 @@ static bfd_boolean elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note) { /* Signal number at offset 0x08. */ - elf_tdata (abfd)->core_signal + elf_tdata (abfd)->core->signal = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08); /* Process ID at offset 0x20. */ - elf_tdata (abfd)->core_pid + elf_tdata (abfd)->core->pid = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x20); /* Command name at 0x48 (max 32 bytes, including nul). */ - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, note->descdata + 0x48, 31); return TRUE; @@ -8837,7 +9099,7 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid) unsigned flags; /* nto_procfs_status 'pid' field is at offset 0. */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata); + elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, (bfd_byte *) ddata); /* nto_procfs_status 'tid' field is at offset 4. Pass it back. */ *tid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4); @@ -8848,15 +9110,15 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid) /* nto_procfs_status 'what' field is at offset 14. */ if ((sig = bfd_get_16 (abfd, (bfd_byte *) ddata + 14)) > 0) { - elf_tdata (abfd)->core_signal = sig; - elf_tdata (abfd)->core_lwpid = *tid; + elf_tdata (abfd)->core->signal = sig; + elf_tdata (abfd)->core->lwpid = *tid; } /* _DEBUG_FLAG_CURTID (current thread) is 0x80. Some cores do not come from signals so we make sure we set the current thread just in case. */ if (flags & 0x00000080) - elf_tdata (abfd)->core_lwpid = *tid; + elf_tdata (abfd)->core->lwpid = *tid; /* Make a ".qnx_core_status/%d" section. */ sprintf (buf, ".qnx_core_status/%ld", *tid); @@ -8904,7 +9166,7 @@ elfcore_grok_nto_regs (bfd *abfd, sect->alignment_power = 2; /* This is the current thread. */ - if (elf_tdata (abfd)->core_lwpid == tid) + if (elf_tdata (abfd)->core->lwpid == tid) return elfcore_maybe_make_sect (abfd, base, sect); return TRUE; @@ -9090,6 +9352,34 @@ elfcore_write_prpsinfo (bfd *abfd, return NULL; } +char * +elfcore_write_linux_prpsinfo32 + (bfd *abfd, char *buf, int *bufsiz, + const struct elf_internal_linux_prpsinfo *prpsinfo) +{ + struct elf_external_linux_prpsinfo32 data; + + memset (&data, 0, sizeof (data)); + LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data); + + return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO, + &data, sizeof (data)); +} + +char * +elfcore_write_linux_prpsinfo64 + (bfd *abfd, char *buf, int *bufsiz, + const struct elf_internal_linux_prpsinfo *prpsinfo) +{ + struct elf_external_linux_prpsinfo64 data; + + memset (&data, 0, sizeof (data)); + LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data); + + return elfcore_write_note (abfd, buf, bufsiz, + "CORE", NT_PRPSINFO, &data, sizeof (data)); +} + char * elfcore_write_prstatus (bfd *abfd, char *buf, @@ -9157,7 +9447,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, @@ -9365,6 +9655,43 @@ elfcore_write_s390_system_call (bfd *abfd, s390_system_call, size); } +char * +elfcore_write_s390_tdb (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_tdb, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + 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, @@ -9377,6 +9704,42 @@ elfcore_write_arm_vfp (bfd *abfd, note_name, NT_ARM_VFP, arm_vfp, size); } +char * +elfcore_write_aarch_tls (bfd *abfd, + char *buf, + int *bufsiz, + const void *aarch_tls, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_TLS, aarch_tls, size); +} + +char * +elfcore_write_aarch_hw_break (bfd *abfd, + char *buf, + int *bufsiz, + const void *aarch_hw_break, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_HW_BREAK, aarch_hw_break, size); +} + +char * +elfcore_write_aarch_hw_watch (bfd *abfd, + char *buf, + int *bufsiz, + const void *aarch_hw_watch, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_HW_WATCH, aarch_hw_watch, size); +} + char * elfcore_write_register_note (bfd *abfd, char *buf, @@ -9411,8 +9774,20 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_s390_last_break (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-s390-system-call") == 0) 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) + return elfcore_write_aarch_tls (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-hw-break") == 0) + return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-hw-watch") == 0) + return elfcore_write_aarch_hw_watch (abfd, buf, bufsiz, data, size); return NULL; } @@ -9452,32 +9827,38 @@ 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 ("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) @@ -9511,10 +9892,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)) { @@ -9571,7 +9956,9 @@ bfd_get_elf_phdrs (bfd *abfd, void *phdrs) } enum elf_reloc_type_class -_bfd_elf_reloc_type_class (const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED) +_bfd_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED) { return reloc_class_normal; } @@ -9673,11 +10060,12 @@ bfd * bfd_elf_bfd_from_remote_memory (bfd *templ, bfd_vma ehdr_vma, + bfd_size_type size, bfd_vma *loadbasep, int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type)) { return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory) - (templ, ehdr_vma, loadbasep, target_read_memory); + (templ, ehdr_vma, size, loadbasep, target_read_memory); } long @@ -9803,8 +10191,8 @@ asection _bfd_elf_large_com_section SEC_IS_COMMON, NULL, "LARGE_COMMON", 0); void -_bfd_elf_set_osabi (bfd * abfd, - struct bfd_link_info * link_info ATTRIBUTE_UNUSED) +_bfd_elf_post_process_headers (bfd * abfd, + struct bfd_link_info * link_info ATTRIBUTE_UNUSED) { Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */