X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf.c;h=8b207ad872a3992381e93bdfa0a75ef444651613;hb=3f9034c204cf1845d2f2d94f906a8573183831ba;hp=7a06fb4a746ae3da5819c173ab4da2d25faa034b;hpb=5299c1c488017d034cd4f36821d35f8d04300c7c;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index 7a06fb4a74..8b207ad872 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-2014 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 * @@ -545,9 +554,9 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) shnum = elf_numsections (abfd); num_group = 0; -#define IS_VALID_GROUP_SECTION_HEADER(shdr) \ +#define IS_VALID_GROUP_SECTION_HEADER(shdr, minsize) \ ( (shdr)->sh_type == SHT_GROUP \ - && (shdr)->sh_size >= (2 * GRP_ENTRY_SIZE) \ + && (shdr)->sh_size >= minsize \ && (shdr)->sh_entsize == GRP_ENTRY_SIZE \ && ((shdr)->sh_size % GRP_ENTRY_SIZE) == 0) @@ -555,7 +564,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) { Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i]; - if (IS_VALID_GROUP_SECTION_HEADER (shdr)) + if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE)) num_group += 1; } @@ -581,7 +590,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) { Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i]; - if (IS_VALID_GROUP_SECTION_HEADER (shdr)) + if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE)) { unsigned char *src; Elf_Internal_Group *dest; @@ -599,9 +608,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 +619,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, @@ -642,6 +661,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 +741,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 +915,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; } } @@ -1025,7 +1040,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, else { /* Normal section. Check if we should compress. */ - if ((abfd->flags & BFD_COMPRESS)) + if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0) action = compress; } @@ -1038,7 +1053,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, if (!bfd_init_section_compress_status (abfd, newsect)) { (*_bfd_error_handler) - (_("%B: unable to initialize commpress status for section %s"), + (_("%B: unable to initialize compress status for section %s"), abfd, name); return FALSE; } @@ -1058,7 +1073,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, if (!bfd_init_section_decompress_status (abfd, newsect)) { (*_bfd_error_handler) - (_("%B: unable to initialize decommpress status for section %s"), + (_("%B: unable to initialize decompress status for section %s"), abfd, name); return FALSE; } @@ -1128,13 +1143,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); @@ -1454,9 +1473,9 @@ 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)) + if (elf_dynversym (abfd) != 0 + && (elf_dynverdef (abfd) != 0 + || elf_dynverref (abfd) != 0)) { unsigned int vernum; const char *version_string; @@ -1559,38 +1578,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, 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 +1659,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 +1692,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 +1728,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 +1754,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 +1785,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 +1825,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 +1845,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 +1855,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 +1871,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 +1879,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 +1922,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 +1937,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) @@ -1889,7 +1960,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) 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,34 +1976,40 @@ 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)) - return FALSE; + if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE)) + 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; @@ -1958,7 +2035,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) } } } - break; + goto success; default: /* Possibly an attributes section. */ @@ -1966,14 +2043,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 +2062,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 +2088,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 +2100,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 +2174,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 +2625,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, @@ -2989,9 +3085,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,21 +3095,28 @@ 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); } + if (section_number >= SHN_LORESERVE) + { + _bfd_error_handler (_("%B: too many sections: %u"), + abfd, section_number); + return FALSE; + } + _bfd_elf_strtab_finalize (elf_shstrtab (abfd)); t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); @@ -3037,17 +3140,17 @@ 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) @@ -3070,13 +3173,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. */ @@ -3163,7 +3268,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) name += 5; s = bfd_get_section_by_name (abfd, name); 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: @@ -3230,7 +3338,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); } } @@ -3257,13 +3365,21 @@ sym_is_global (bfd *abfd, asymbol *sym) } /* Don't output section symbols for sections that are not going to be - output, or that are duplicates. */ + output, that are duplicates or there is no BFD section. */ static bfd_boolean ignore_section_sym (bfd *abfd, asymbol *sym) { - return ((sym->flags & BSF_SECTION_SYM) != 0 - && !(sym->section->owner == abfd + elf_symbol_type *type_ptr; + + if ((sym->flags & BSF_SECTION_SYM) == 0) + return FALSE; + + type_ptr = elf_symbol_from (abfd, sym); + return ((type_ptr != NULL + && type_ptr->internal_elf_sym.st_shndx != 0 + && bfd_is_abs_section (sym->section)) + || !(sym->section->owner == abfd || (sym->section->output_section->owner == abfd && sym->section->output_offset == 0) || bfd_is_abs_section (sym->section))); @@ -3273,7 +3389,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); @@ -3389,8 +3505,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; } @@ -3447,8 +3562,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; @@ -3501,7 +3615,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); @@ -3513,7 +3627,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. */ @@ -3564,13 +3678,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; @@ -3632,8 +3746,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++) { @@ -3717,7 +3830,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; @@ -3761,7 +3874,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; @@ -3872,10 +3985,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 @@ -4103,11 +4217,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; @@ -4116,7 +4250,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) { @@ -4133,7 +4267,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); @@ -4141,8 +4275,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; @@ -4152,18 +4293,21 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) { for (m = mfirst; m != NULL; m = m->next) { - if (m->p_type == PT_LOAD) + if (m->p_type == PT_LOAD + && m->count != 0 + && m->sections[0]->vma >= info->relro_start + && m->sections[0]->vma < info->relro_end) { - asection *last = m->sections[m->count - 1]; - bfd_vma vaddr = m->sections[0]->vma; - bfd_vma filesz = last->vma - vaddr + last->size; + i = m->count; + while (--i != (unsigned) -1) + if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) + == (SEC_LOAD | SEC_HAS_CONTENTS)) + break; - if (vaddr < info->relro_end - && vaddr >= info->relro_start - && (vaddr + filesz) >= info->relro_end) + if (i != (unsigned) -1) break; } - } + } /* Make a PT_GNU_RELRO segment only when it isn't empty. */ if (m != NULL) @@ -4183,15 +4327,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; @@ -4285,6 +4429,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); } @@ -4355,7 +4502,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) @@ -4376,32 +4523,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) @@ -4419,7 +4566,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++) { @@ -4568,8 +4715,6 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_memsz = bed->s->sizeof_ehdr; if (m->count > 0) { - BFD_ASSERT (p->p_type == PT_LOAD); - if (p->p_vaddr < (bfd_vma) off) { (*_bfd_error_handler) @@ -4596,7 +4741,6 @@ assign_file_positions_for_load_sections (bfd *abfd, if (m->count > 0) { - BFD_ASSERT (p->p_type == PT_LOAD); p->p_vaddr -= off - p->p_offset; if (!m->p_paddr_valid) p->p_paddr -= off - p->p_offset; @@ -4764,6 +4908,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. @@ -4803,7 +4948,7 @@ assign_file_positions_for_load_sections (bfd *abfd, } } - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; return TRUE; } @@ -4819,6 +4964,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; struct elf_segment_map *m; + struct elf_segment_map *hdrs_segment; bfd_vma filehdr_vaddr, filehdr_paddr; bfd_vma phdrs_vaddr, phdrs_paddr; file_ptr off; @@ -4828,10 +4974,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; @@ -4861,9 +5006,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); @@ -4876,10 +5021,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd, filehdr_paddr = 0; phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr; 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) @@ -4896,34 +5040,82 @@ assign_file_positions_for_non_load_sections (bfd *abfd, phdrs_paddr = p->p_paddr; if (m->includes_filehdr) { + hdrs_segment = m; phdrs_vaddr += bed->s->sizeof_ehdr; phdrs_paddr += bed->s->sizeof_ehdr; } } } - for (m = elf_tdata (abfd)->segment_map, p = phdrs; - m != NULL; - m = m->next, p++) + if (hdrs_segment != NULL && link_info != NULL) + { + /* There is a segment that contains both the file headers and the + program headers, so provide a symbol __ehdr_start pointing there. + A program can use this to examine itself robustly. */ + + struct elf_link_hash_entry *hash + = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start", + FALSE, FALSE, TRUE); + /* If the symbol was referenced and not defined, define it. */ + if (hash != NULL + && (hash->root.type == bfd_link_hash_new + || hash->root.type == bfd_link_hash_undefined + || hash->root.type == bfd_link_hash_undefweak + || hash->root.type == bfd_link_hash_common)) + { + asection *s = NULL; + if (hdrs_segment->count != 0) + /* The segment contains sections, so use the first one. */ + s = hdrs_segment->sections[0]; + else + /* Use the first (i.e. lowest-addressed) section in any segment. */ + for (m = elf_seg_map (abfd); m != NULL; m = m->next) + if (m->count != 0) + { + s = m->sections[0]; + break; + } + + if (s != NULL) + { + hash->root.u.def.value = filehdr_vaddr - s->vma; + hash->root.u.def.section = s; + } + else + { + hash->root.u.def.value = filehdr_vaddr; + hash->root.u.def.section = bfd_abs_section_ptr; + } + + hash->root.type = bfd_link_hash_defined; + hash->def_regular = 1; + hash->non_elf = 0; + } + } + + for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++) { if (p->p_type == PT_GNU_RELRO) { const Elf_Internal_Phdr *lp; - - BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs); + struct elf_segment_map *lm; if (link_info != NULL) { /* During linking the range of the RELRO segment is passed in link_info. */ - for (lp = phdrs; lp < phdrs + count; ++lp) + 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_start && 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; } + + BFD_ASSERT (lm != NULL); } else { @@ -4949,14 +5141,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd, else abort (); p->p_memsz = p->p_filesz; - /* Preserve the alignment and flags if they are valid. The gold - linker generates RW/4 for the PT_GNU_RELRO section. It is better - for objcopy/strip to honor these attributes otherwise gdb will - choke when using separate debug files. */ - if (!m->p_align_valid) - p->p_align = 1; - if (!m->p_flags_valid) - p->p_flags = (lp->p_flags & ~PF_W); + /* Preserve the alignment and flags if they are valid. The + gold linker generates RW/4 for the PT_GNU_RELRO section. + It is better for objcopy/strip to honor these attributes + otherwise gdb will choke when using separate debug files. + */ + if (!m->p_align_valid) + p->p_align = 1; + if (!m->p_flags_valid) + p->p_flags = (lp->p_flags & ~PF_W); } else { @@ -4964,6 +5157,11 @@ 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 @@ -5001,7 +5199,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; } @@ -5026,7 +5224,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 @@ -5036,6 +5233,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; @@ -5050,15 +5248,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 { @@ -5079,22 +5279,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; } @@ -5179,7 +5391,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; @@ -5187,16 +5399,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++) @@ -5209,7 +5423,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 @@ -5219,6 +5439,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)) @@ -5250,21 +5471,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; } @@ -5973,7 +6194,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); @@ -5998,7 +6219,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 @@ -6108,12 +6329,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; } @@ -6136,7 +6360,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; @@ -6149,12 +6373,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 @@ -6189,7 +6415,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; } @@ -6283,6 +6509,26 @@ 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) + 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); } @@ -6460,7 +6706,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; @@ -6508,11 +6754,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; } @@ -6537,10 +6783,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. */ @@ -6554,7 +6801,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; @@ -6688,15 +6935,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; } } @@ -7021,8 +7269,12 @@ _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 *) + if (hdr->sh_info) + elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed)); + else + elf_tdata (abfd)->verref = NULL; + if (elf_tdata (abfd)->verref == NULL) goto error_return; @@ -7182,8 +7434,12 @@ error_return_verref: else freeidx = ++maxidx; } - elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) + if (maxidx) + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef)); + else + elf_tdata (abfd)->verdef = NULL; + if (elf_tdata (abfd)->verdef == NULL) goto error_return; @@ -7289,7 +7545,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; @@ -7324,16 +7580,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 @@ -7401,74 +7653,100 @@ _bfd_elf_set_arch_mach (bfd *abfd, static bfd_boolean elf_find_function (bfd *abfd, - asection *section, asymbol **symbols, + asection *section, bfd_vma offset, const char **filename_ptr, const char **functionname_ptr) { - const char *filename; - asymbol *func, *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); + struct elf_find_function_cache + { + asection *last_section; + asymbol *func; + const char *filename; + bfd_size_type func_size; + } *cache; if (symbols == NULL) return FALSE; - filename = NULL; - func = NULL; - file = NULL; - low_func = 0; - state = nothing_seen; - - for (p = symbols; *p != NULL; p++) + cache = elf_tdata (abfd)->elf_find_function_cache; + if (cache == NULL) { - asymbol *sym = *p; - asection *code_sec; - bfd_vma code_off; - - if ((sym->flags & BSF_FILE) != 0) - { - file = sym; - if (state == symbol_seen) - state = file_after_symbol_seen; - continue; - } + cache = bfd_zalloc (abfd, sizeof (*cache)); + elf_tdata (abfd)->elf_find_function_cache = cache; + if (cache == NULL) + return FALSE; + } + if (cache->last_section != section + || cache->func == NULL + || offset < cache->func->value + || offset >= cache->func->value + cache->func_size) + { + asymbol *file; + bfd_vma low_func; + asymbol **p; + /* ??? Given multiple file symbols, it is impossible to reliably + choose the right file name for global symbols. File symbols are + local symbols, and thus all file symbols must sort before any + global symbols. The ELF spec may be interpreted to say that a + file symbol must sort before other local symbols, but currently + ld -r doesn't do this. So, for ld -r output, it is possible to + make a better choice of file name for local symbols by ignoring + file symbols appearing after a given local symbol. */ + enum { nothing_seen, symbol_seen, file_after_symbol_seen } state; + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + + file = NULL; + low_func = 0; + state = nothing_seen; + cache->filename = NULL; + cache->func = NULL; + cache->func_size = 0; + cache->last_section = section; + + for (p = symbols; *p != NULL; p++) + { + asymbol *sym = *p; + bfd_vma code_off; + bfd_size_type size; + + if ((sym->flags & BSF_FILE) != 0) + { + file = sym; + if (state == symbol_seen) + state = file_after_symbol_seen; + continue; + } - if (bed->maybe_function_sym (sym, &code_sec, &code_off) - && code_sec == section - && code_off >= low_func - && code_off <= offset) - { - func = sym; - low_func = code_off; - filename = NULL; - if (file != NULL - && ((sym->flags & BSF_LOCAL) != 0 - || state != file_after_symbol_seen)) - filename = bfd_asymbol_name (file); + size = bed->maybe_function_sym (sym, section, &code_off); + if (size != 0 + && code_off <= offset + && (code_off > low_func + || (code_off == low_func + && size > cache->func_size))) + { + cache->func = sym; + cache->func_size = size; + cache->filename = NULL; + low_func = code_off; + if (file != NULL + && ((sym->flags & BSF_LOCAL) != 0 + || state != file_after_symbol_seen)) + cache->filename = bfd_asymbol_name (file); + } + if (state == nothing_seen) + state = symbol_seen; } - if (state == nothing_seen) - state = symbol_seen; } - if (func == NULL) + if (cache->func == NULL) return FALSE; if (filename_ptr) - *filename_ptr = filename; + *filename_ptr = cache->filename; if (functionname_ptr) - *functionname_ptr = bfd_asymbol_name (func); + *functionname_ptr = bfd_asymbol_name (cache->func); return TRUE; } @@ -7478,35 +7756,35 @@ elf_find_function (bfd *abfd, 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) + unsigned int *line_ptr, + unsigned int *discriminator_ptr) { bfd_boolean found; - if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, + if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, filename_ptr, functionname_ptr, - line_ptr)) + line_ptr, discriminator_ptr, + dwarf_debug_sections, 0, + &elf_tdata (abfd)->dwarf2_find_line_info)) { if (!*functionname_ptr) - elf_find_function (abfd, section, symbols, offset, + elf_find_function (abfd, symbols, section, offset, *filename_ptr ? NULL : filename_ptr, functionname_ptr); return TRUE; } - if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, - section, symbols, offset, - filename_ptr, functionname_ptr, - line_ptr, 0, - &elf_tdata (abfd)->dwarf2_find_line_info)) + if (_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, + elf_find_function (abfd, symbols, section, offset, *filename_ptr ? NULL : filename_ptr, functionname_ptr); @@ -7524,7 +7802,7 @@ _bfd_elf_find_nearest_line (bfd *abfd, if (symbols == NULL) return FALSE; - if (! elf_find_function (abfd, section, symbols, offset, + if (! elf_find_function (abfd, symbols, section, offset, filename_ptr, functionname_ptr)) return FALSE; @@ -7538,9 +7816,10 @@ bfd_boolean _bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol, const char **filename_ptr, unsigned int *line_ptr) { - return _bfd_dwarf2_find_line (abfd, symbols, symbol, - filename_ptr, line_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 @@ -7570,21 +7849,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; } @@ -7599,7 +7878,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)) @@ -7724,7 +8003,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); } @@ -7766,9 +8045,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; } @@ -7858,10 +8137,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+ @@ -7870,9 +8149,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) @@ -7887,10 +8166,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+ @@ -7899,9 +8178,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 */ @@ -8018,12 +8297,36 @@ 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_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 */ @@ -8075,13 +8378,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)); } @@ -8094,13 +8397,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)); } @@ -8118,7 +8421,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] == ' ') @@ -8143,7 +8446,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)) @@ -8153,7 +8456,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" @@ -8183,11 +8486,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. */ @@ -8270,11 +8573,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 */: @@ -8457,6 +8760,13 @@ 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_ARM_VFP: if (note->namesz == 6 && strcmp (note->namedata, "LINUX") == 0) @@ -8464,6 +8774,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) @@ -8488,18 +8819,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; - memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz); + t = elf_tdata (abfd); + t->build_id = bfd_alloc (abfd, sizeof (*t->build_id) - 1 + note->descsz); + if (t->build_id == NULL) + return FALSE; + + t->build_id->size = note->descsz; + memcpy (t->build_id->data, note->descdata, note->descsz); return TRUE; } @@ -8564,15 +8909,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", @@ -8585,7 +8930,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) { @@ -8648,15 +8993,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; @@ -8719,7 +9064,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); @@ -8730,15 +9075,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); @@ -8786,7 +9131,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; @@ -8972,6 +9317,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, @@ -9039,7 +9412,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, @@ -9247,6 +9620,18 @@ 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_arm_vfp (bfd *abfd, char *buf, @@ -9259,6 +9644,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, @@ -9293,8 +9714,16 @@ 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-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; } @@ -9453,7 +9882,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; } @@ -9555,11 +9986,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 *, size_t)) + 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 @@ -9685,8 +10117,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. */ @@ -9714,18 +10146,26 @@ _bfd_elf_is_function_type (unsigned int type) || type == STT_GNU_IFUNC); } -/* Return TRUE iff the ELF symbol SYM might be a function. Set *CODE_SEC - and *CODE_OFF to the function's entry point. */ +/* If the ELF symbol SYM might be a function in SEC, return the + function size and set *CODE_OFF to the function's entry point, + otherwise return zero. */ -bfd_boolean -_bfd_elf_maybe_function_sym (const asymbol *sym, - asection **code_sec, bfd_vma *code_off) +bfd_size_type +_bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec, + bfd_vma *code_off) { + bfd_size_type size; + if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT - | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0) - return FALSE; + | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0 + || sym->section != sec) + return 0; - *code_sec = sym->section; *code_off = sym->value; - return TRUE; + size = 0; + if (!(sym->flags & BSF_SYNTHETIC)) + size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; + if (size == 0) + size = 1; + return size; }