X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf.c;h=9c56e2e7b1f7c4f0bacad9f32c715a526d70f574;hb=8d06853ec69b274b573df0ac2f5c00e2aa8d0daa;hp=7f74236302c4c6457e872ca4267c48dce7d8a5f0;hpb=83b89087cf717b455598eee2fb5ddb4d5465a6a0;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index 7f74236302..9c56e2e7b1 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1,7 +1,7 @@ /* ELF executable support for BFD. Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -45,6 +45,10 @@ SECTION #include "libiberty.h" #include "safe-ctype.h" +#ifdef CORE_HEADER +#include CORE_HEADER +#endif + static int elf_sort_sections (const void *, const void *); static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *); static bfd_boolean prep_headers (bfd *); @@ -232,7 +236,7 @@ bfd_elf_gnu_hash (const char *namearg) bfd_boolean bfd_elf_allocate_object (bfd *abfd, size_t object_size, - enum elf_object_id object_id) + enum elf_target_id object_id) { BFD_ASSERT (object_size >= sizeof (struct elf_obj_tdata)); abfd->tdata.any = bfd_zalloc (abfd, object_size); @@ -249,7 +253,7 @@ bfd_boolean bfd_elf_make_generic_object (bfd *abfd) { return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata), - GENERIC_ELF_TDATA); + GENERIC_ELF_DATA); } bfd_boolean @@ -283,7 +287,7 @@ 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_alloc (abfd, shstrtabsize + 1)) == NULL + || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL || bfd_seek (abfd, offset, SEEK_SET) != 0) shstrtab = NULL; else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize) @@ -331,7 +335,7 @@ bfd_elf_string_from_elf_section (bfd *abfd, (shindex == shstrndx && strindex == hdr->sh_name ? ".shstrtab" : bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name))); - return ""; + return NULL; } return ((char *) hdr->contents) + strindex; @@ -407,8 +411,8 @@ bfd_elf_get_elf_syms (bfd *ibfd, pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx); if (extshndx_buf == NULL) { - alloc_extshndx = bfd_malloc2 (symcount, - sizeof (Elf_External_Sym_Shndx)); + alloc_extshndx = (Elf_External_Sym_Shndx *) + bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx)); extshndx_buf = alloc_extshndx; } if (extshndx_buf == NULL @@ -422,7 +426,8 @@ bfd_elf_get_elf_syms (bfd *ibfd, if (intsym_buf == NULL) { - alloc_intsym = bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym)); + alloc_intsym = (Elf_Internal_Sym *) + bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym)); intsym_buf = alloc_intsym; if (intsym_buf == NULL) goto out; @@ -430,7 +435,8 @@ bfd_elf_get_elf_syms (bfd *ibfd, /* Convert the symbols to internal form. */ isymend = intsym_buf + symcount; - for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf; + for (esym = (const bfd_byte *) extsym_buf, isym = intsym_buf, + shndx = extshndx_buf; isym < isymend; esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL) if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym)) @@ -564,8 +570,8 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) bfd_size_type amt; elf_tdata (abfd)->num_group = num_group; - elf_tdata (abfd)->group_sect_ptr - = bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *)); + elf_tdata (abfd)->group_sect_ptr = (Elf_Internal_Shdr **) + bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *)); if (elf_tdata (abfd)->group_sect_ptr == NULL) return FALSE; @@ -586,8 +592,8 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) /* Read the raw contents. */ BFD_ASSERT (sizeof (*dest) >= 4); amt = shdr->sh_size * sizeof (*dest) / 4; - shdr->contents = bfd_alloc2 (abfd, shdr->sh_size, - sizeof (*dest) / 4); + shdr->contents = (unsigned char *) + bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4); /* PR binutils/4110: Handle corrupt group headers. */ if (shdr->contents == NULL) { @@ -732,18 +738,18 @@ _bfd_elf_setup_sections (bfd *abfd) } else { - asection *link = NULL; + asection *linksec = NULL; if (elfsec < elf_numsections (abfd)) { this_hdr = elf_elfsections (abfd)[elfsec]; - link = this_hdr->bfd_section; + linksec = this_hdr->bfd_section; } /* PR 1991, 2008: Some strip/objcopy may leave an incorrect value in sh_link. We don't want to proceed. */ - if (link == NULL) + if (linksec == NULL) { (*_bfd_error_handler) (_("%B: sh_link [%d] in section `%A' is incorrect"), @@ -751,7 +757,7 @@ _bfd_elf_setup_sections (bfd *abfd) result = FALSE; } - elf_linked_to_section (s) = link; + elf_linked_to_section (s) = linksec; } } } @@ -870,6 +876,8 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, return FALSE; if ((hdr->sh_flags & SHF_TLS) != 0) flags |= SEC_THREAD_LOCAL; + if ((hdr->sh_flags & SHF_EXCLUDE) != 0) + flags |= SEC_EXCLUDE; if ((flags & SEC_ALLOC) == 0) { @@ -971,25 +979,8 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, phdr = elf_tdata (abfd)->phdr; for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++) { - /* This section is part of this segment if its file - offset plus size lies within the segment's memory - span and, if the section is loaded, the extent of the - loaded data lies within the extent of the segment. - - Note - we used to check the p_paddr field as well, and - refuse to set the LMA if it was 0. This is wrong - though, as a perfectly valid initialised segment can - have a p_paddr of zero. Some architectures, eg ARM, - place special significance on the address 0 and - executables need to be able to have a segment which - covers this address. */ if (phdr->p_type == PT_LOAD - && (bfd_vma) hdr->sh_offset >= phdr->p_offset - && (hdr->sh_offset + hdr->sh_size - <= phdr->p_offset + phdr->p_memsz) - && ((flags & SEC_LOAD) == 0 - || (hdr->sh_offset + hdr->sh_size - <= phdr->p_offset + phdr->p_filesz))) + && ELF_SECTION_IN_SEGMENT (hdr, phdr)) { if ((flags & SEC_LOAD) == 0) newsect->lma = (phdr->p_paddr @@ -1077,7 +1068,6 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) /* Copy object attributes. */ _bfd_elf_copy_obj_attributes (ibfd, obfd); - return TRUE; } @@ -1108,7 +1098,7 @@ get_segment_type (unsigned int p_type) bfd_boolean _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg) { - FILE *f = farg; + FILE *f = (FILE *) farg; Elf_Internal_Phdr *p; asection *s; bfd_byte *dynbuf = NULL; @@ -1351,7 +1341,7 @@ bfd_elf_print_symbol (bfd *abfd, asymbol *symbol, bfd_print_symbol_type how) { - FILE *file = filep; + FILE *file = (FILE *) filep; switch (how) { case bfd_print_symbol_name: @@ -1531,10 +1521,25 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) case SHT_DYNAMIC: /* Dynamic linking information. */ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) return FALSE; - if (hdr->sh_link > elf_numsections (abfd) - || elf_elfsections (abfd)[hdr->sh_link] == NULL) + if (hdr->sh_link > elf_numsections (abfd)) + { + /* PR 10478: Accept Solaris binaries with a sh_link + field set to SHN_BEFORE or SHN_AFTER. */ + switch (bfd_get_arch (abfd)) + { + case bfd_arch_i386: + case bfd_arch_sparc: + if (hdr->sh_link == (SHN_LORESERVE & 0xffff) /* SHN_BEFORE */ + || hdr->sh_link == ((SHN_LORESERVE + 1) & 0xffff) /* SHN_AFTER */) + break; + /* Otherwise fall through. */ + default: + return FALSE; + } + } + else if (elf_elfsections (abfd)[hdr->sh_link] == NULL) return FALSE; - if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB) + else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB) { Elf_Internal_Shdr *dynsymhdr; @@ -1792,7 +1797,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) bfd_size_type amt; BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL); amt = sizeof (*hdr2); - hdr2 = bfd_alloc (abfd, amt); + hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); if (hdr2 == NULL) return FALSE; elf_section_data (target_sect)->rel_hdr2 = hdr2; @@ -1961,11 +1966,11 @@ bfd_sym_from_r_symndx (struct sym_cache *cache, section. */ asection * -bfd_section_from_elf_index (bfd *abfd, unsigned int index) +bfd_section_from_elf_index (bfd *abfd, unsigned int sec_index) { - if (index >= elf_numsections (abfd)) + if (sec_index >= elf_numsections (abfd)) return NULL; - return elf_elfsections (abfd)[index]->bfd_section; + return elf_elfsections (abfd)[sec_index]->bfd_section; } static const struct bfd_elf_special_section special_sections_b[] = @@ -2210,7 +2215,8 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec) sdata = (struct bfd_elf_section_data *) sec->used_by_bfd; if (sdata == NULL) { - sdata = bfd_zalloc (abfd, sizeof (*sdata)); + sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, + sizeof (*sdata)); if (sdata == NULL) return FALSE; sec->used_by_bfd = sdata; @@ -2265,8 +2271,8 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec) bfd_boolean _bfd_elf_make_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, - int index, - const char *typename) + int hdr_index, + const char *type_name) { asection *newsect; char *name; @@ -2280,9 +2286,9 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, if (hdr->p_filesz > 0) { - sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : ""); + sprintf (namebuf, "%s%d%s", type_name, hdr_index, split ? "a" : ""); len = strlen (namebuf) + 1; - name = bfd_alloc (abfd, len); + name = (char *) bfd_alloc (abfd, len); if (!name) return FALSE; memcpy (name, namebuf, len); @@ -2316,9 +2322,9 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, { bfd_vma align; - sprintf (namebuf, "%s%d%s", typename, index, split ? "b" : ""); + sprintf (namebuf, "%s%d%s", type_name, hdr_index, split ? "b" : ""); len = strlen (namebuf) + 1; - name = bfd_alloc (abfd, len); + name = (char *) bfd_alloc (abfd, len); if (!name) return FALSE; memcpy (name, namebuf, len); @@ -2355,51 +2361,51 @@ _bfd_elf_make_section_from_phdr (bfd *abfd, } bfd_boolean -bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index) +bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index) { const struct elf_backend_data *bed; switch (hdr->p_type) { case PT_NULL: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "null"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "null"); case PT_LOAD: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "load"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "load"); case PT_DYNAMIC: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "dynamic"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "dynamic"); case PT_INTERP: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "interp"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "interp"); case PT_NOTE: - if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note")) + if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "note")) return FALSE; if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz)) return FALSE; return TRUE; case PT_SHLIB: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "shlib"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "shlib"); case PT_PHDR: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "phdr"); case PT_GNU_EH_FRAME: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "eh_frame_hdr"); case PT_GNU_STACK: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "stack"); case PT_GNU_RELRO: - return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro"); + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "relro"); default: /* Check for any processor-specific program segment types. */ bed = get_elf_backend_data (abfd); - return bed->elf_backend_section_from_phdr (abfd, hdr, index, "proc"); + return bed->elf_backend_section_from_phdr (abfd, hdr, hdr_index, "proc"); } } @@ -2417,7 +2423,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd, const struct elf_backend_data *bed = get_elf_backend_data (abfd); bfd_size_type amt = sizeof ".rela" + strlen (asect->name); - name = bfd_alloc (abfd, amt); + name = (char *) bfd_alloc (abfd, amt); if (name == NULL) return FALSE; sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name); @@ -2439,13 +2445,25 @@ _bfd_elf_init_reloc_shdr (bfd *abfd, return TRUE; } +/* Return the default section type based on the passed in section flags. */ + +int +bfd_elf_get_default_section_type (flagword flags) +{ + if ((flags & SEC_ALLOC) != 0 + && ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0 + || (flags & SEC_NEVER_LOAD) != 0)) + return SHT_NOBITS; + return SHT_PROGBITS; +} + /* Set up an ELF internal section header for a section. */ static void elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); - bfd_boolean *failedptr = failedptrarg; + bfd_boolean *failedptr = (bfd_boolean *) failedptrarg; Elf_Internal_Shdr *this_hdr; unsigned int sh_type; @@ -2488,12 +2506,8 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) asect->flags. */ if ((asect->flags & SEC_GROUP) != 0) sh_type = SHT_GROUP; - else if ((asect->flags & SEC_ALLOC) != 0 - && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) - || (asect->flags & SEC_NEVER_LOAD) != 0)) - sh_type = SHT_NOBITS; else - sh_type = SHT_PROGBITS; + sh_type = bfd_elf_get_default_section_type (asect->flags); if (this_hdr->sh_type == SHT_NULL) this_hdr->sh_type = sh_type; @@ -2615,6 +2629,8 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) } } } + if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE) + this_hdr->sh_flags |= SHF_EXCLUDE; /* Check for processor-specific section types. */ sh_type = this_hdr->sh_type; @@ -2649,7 +2665,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) void bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) { - bfd_boolean *failedptr = failedptrarg; + bfd_boolean *failedptr = (bfd_boolean *) failedptrarg; asection *elt, *first; unsigned char *loc; bfd_boolean gas; @@ -2709,7 +2725,7 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) if (sec->contents == NULL) { gas = FALSE; - sec->contents = bfd_alloc (abfd, sec->size); + sec->contents = (unsigned char *) bfd_alloc (abfd, sec->size); /* Arrange for the section to be written out. */ elf_section_data (sec)->this_hdr.contents = sec->contents; @@ -2734,17 +2750,16 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) while (elt != NULL) { asection *s; - unsigned int idx; s = elt; - if (! elf_discarded_section (s)) + if (!gas) + s = s->output_section; + if (s != NULL + && !bfd_is_abs_section (s)) { + unsigned int idx = elf_section_data (s)->this_idx; + loc -= 4; - if (!gas) - s = s->output_section; - idx = 0; - if (s != NULL) - idx = elf_section_data (s)->this_idx; H_PUT_32 (abfd, idx, loc); } elt = elf_next_in_group (elt); @@ -2855,11 +2870,13 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) /* Set up the list of section header pointers, in agreement with the indices. */ - i_shdrp = bfd_zalloc2 (abfd, section_number, sizeof (Elf_Internal_Shdr *)); + i_shdrp = (Elf_Internal_Shdr **) bfd_zalloc2 (abfd, section_number, + sizeof (Elf_Internal_Shdr *)); if (i_shdrp == NULL) return FALSE; - i_shdrp[0] = bfd_zalloc (abfd, sizeof (Elf_Internal_Shdr)); + i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd, + sizeof (Elf_Internal_Shdr)); if (i_shdrp[0] == NULL) { bfd_release (abfd, i_shdrp); @@ -2883,10 +2900,11 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) for (sec = abfd->sections; sec; sec = sec->next) { - struct bfd_elf_section_data *d = elf_section_data (sec); asection *s; const char *name; + d = elf_section_data (sec); + i_shdrp[d->this_idx] = &d->this_hdr; if (d->rel_idx != 0) i_shdrp[d->rel_idx] = &d->rel_hdr; @@ -3008,7 +3026,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) char *alc; len = strlen (sec->name); - alc = bfd_malloc (len - 2); + alc = (char *) bfd_malloc (len - 2); if (alc == NULL) return FALSE; memcpy (alc, sec->name, len - 3); @@ -3084,7 +3102,7 @@ sym_is_global (bfd *abfd, asymbol *sym) if (bed->elf_backend_sym_is_global) return (*bed->elf_backend_sym_is_global) (abfd, sym); - return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 + return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0 || bfd_is_und_section (bfd_get_section (sym)) || bfd_is_com_section (bfd_get_section (sym))); } @@ -3128,7 +3146,7 @@ elf_map_symbols (bfd *abfd) } max_index++; - sect_syms = bfd_zalloc2 (abfd, max_index, sizeof (asymbol *)); + sect_syms = (asymbol **) bfd_zalloc2 (abfd, max_index, sizeof (asymbol *)); if (sect_syms == NULL) return FALSE; elf_section_syms (abfd) = sect_syms; @@ -3180,7 +3198,8 @@ elf_map_symbols (bfd *abfd) } /* Now sort the symbols so the local symbols are first. */ - new_syms = bfd_alloc2 (abfd, num_locals + num_globals, sizeof (asymbol *)); + new_syms = (asymbol **) bfd_alloc2 (abfd, num_locals + num_globals, + sizeof (asymbol *)); if (new_syms == NULL) return FALSE; @@ -3489,7 +3508,7 @@ make_mapping (bfd *abfd, amt = sizeof (struct elf_segment_map); amt += (to - from - 1) * sizeof (asection *); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) return NULL; m->next = NULL; @@ -3516,7 +3535,8 @@ _bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec) { struct elf_segment_map *m; - m = bfd_zalloc (abfd, sizeof (struct elf_segment_map)); + m = (struct elf_segment_map *) bfd_zalloc (abfd, + sizeof (struct elf_segment_map)); if (m == NULL) return NULL; m->next = NULL; @@ -3604,13 +3624,21 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) asection *first_tls = NULL; asection *dynsec, *eh_frame_hdr; bfd_size_type amt; + bfd_vma addr_mask, wrap_to = 0; /* Select the allocated sections, and sort them. */ - sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *)); + sections = (asection **) bfd_malloc2 (bfd_count_sections (abfd), + sizeof (asection *)); if (sections == NULL) goto error_return; + /* Calculate top address, avoiding undefined behaviour of shift + left operator when shift count is equal to size of type + being shifted. */ + addr_mask = ((bfd_vma) 1 << (bfd_arch_bits_per_address (abfd) - 1)) - 1; + addr_mask = (addr_mask << 1) + 1; + i = 0; for (s = abfd->sections; s != NULL; s = s->next) { @@ -3618,6 +3646,9 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) { sections[i] = s; ++i; + /* A wrapping section potentially clashes with header. */ + if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask)) + wrap_to = (s->lma + s->size) & addr_mask; } } BFD_ASSERT (i <= bfd_count_sections (abfd)); @@ -3637,7 +3668,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (s != NULL && (s->flags & SEC_LOAD) != 0) { amt = sizeof (struct elf_segment_map); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -3651,7 +3682,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) pm = &m->next; amt = sizeof (struct elf_segment_map); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -3687,8 +3718,10 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (phdr_size == (bfd_size_type) -1) phdr_size = get_program_header_size (abfd, info); if ((abfd->flags & D_PAGED) == 0 - || sections[0]->lma < phdr_size - || sections[0]->lma % maxpagesize < phdr_size % maxpagesize) + || (sections[0]->lma & addr_mask) < phdr_size + || ((sections[0]->lma & addr_mask) % maxpagesize + < phdr_size % maxpagesize) + || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to) phdr_in_segment = FALSE; } @@ -3715,6 +3748,13 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) segment. */ new_segment = TRUE; } + else if (hdr->lma < last_hdr->lma + last_size + || last_hdr->lma + last_size < last_hdr->lma) + { + /* If this section has a load address that makes it overlap + the previous section, then we need a new segment. */ + new_segment = TRUE; + } /* In the next test we have to be careful when last_hdr->lma is close to the end of the address space. If the aligned address wraps around to the start of the address space, then there are no more @@ -3746,9 +3786,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) } else if (! writable && (hdr->flags & SEC_READONLY) == 0 - && (((last_hdr->lma + last_size - 1) - & ~(maxpagesize - 1)) - != (hdr->lma & ~(maxpagesize - 1)))) + && (((last_hdr->lma + last_size - 1) & -maxpagesize) + != (hdr->lma & -maxpagesize))) { /* We don't want to put a writable section in a read only segment, unless they are on the same page in memory @@ -3846,7 +3885,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) && CONST_STRNEQ (s->name, ".note")) { asection *s2; - unsigned count = 1; + + count = 1; amt = sizeof (struct elf_segment_map); if (s->alignment_power == 2) for (s2 = s; s2->next != NULL; s2 = s2->next) @@ -3854,14 +3894,14 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (s2->next->alignment_power == 2 && (s2->next->flags & SEC_LOAD) != 0 && CONST_STRNEQ (s2->next->name, ".note") - && align_power (s2->vma + s2->size, 2) - == s2->next->vma) + && align_power (s2->lma + s2->size, 2) + == s2->next->lma) count++; else break; } amt += (count - 1) * sizeof (asection *); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -3889,11 +3929,9 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) /* If there are any SHF_TLS output sections, add PT_TLS segment. */ if (tls_count > 0) { - int i; - amt = sizeof (struct elf_segment_map); amt += (tls_count - 1) * sizeof (asection *); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -3902,7 +3940,7 @@ _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; - for (i = 0; i < tls_count; ++i) + for (i = 0; i < (unsigned int) tls_count; ++i) { BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL); m->sections[i] = first_tls; @@ -3920,7 +3958,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0) { amt = sizeof (struct elf_segment_map); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -3935,7 +3973,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (elf_tdata (abfd)->stack_flags) { amt = sizeof (struct elf_segment_map); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -3968,7 +4006,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) if (m != NULL) { amt = sizeof (struct elf_segment_map); - m = bfd_zalloc (abfd, amt); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -4113,6 +4151,22 @@ print_segment_map (const struct elf_segment_map *m) putc ('\n',stderr); } +static bfd_boolean +write_zeros (bfd *abfd, file_ptr pos, bfd_size_type len) +{ + void *buf; + bfd_boolean ret; + + if (bfd_seek (abfd, pos, SEEK_SET) != 0) + return FALSE; + buf = bfd_zmalloc (len); + if (buf == NULL) + return FALSE; + ret = bfd_bwrite (buf, len, abfd) == len; + free (buf); + return ret; +} + /* Assign file positions to the sections based on the mapping from sections to segments. This function also sets up some fields in the file header. */ @@ -4170,10 +4224,10 @@ assign_file_positions_for_load_sections (bfd *abfd, last iterations for the testcase ld-elf/header. */ BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr == 0); - phdrs = bfd_zalloc2 (abfd, - (elf_tdata (abfd)->program_header_size - / bed->s->sizeof_phdr), - sizeof (Elf_Internal_Phdr)); + phdrs = (Elf_Internal_Phdr *) + bfd_zalloc2 (abfd, + (elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr), + sizeof (Elf_Internal_Phdr)); elf_tdata (abfd)->phdr = phdrs; if (phdrs == NULL) return FALSE; @@ -4294,7 +4348,7 @@ assign_file_positions_for_load_sections (bfd *abfd, break; } - off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align); + off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align); off += off_adjust; if (no_contents) { @@ -4421,19 +4475,33 @@ assign_file_positions_for_load_sections (bfd *abfd, && ((this_hdr->sh_flags & SHF_TLS) == 0 || p->p_type == PT_TLS)))) { - bfd_signed_vma adjust = sec->vma - (p->p_vaddr + p->p_memsz); + bfd_vma p_start = p->p_paddr; + bfd_vma p_end = p_start + p->p_memsz; + bfd_vma s_start = sec->lma; + bfd_vma adjust = s_start - p_end; - if (adjust < 0) + if (s_start < p_end + || p_end < p_start) { (*_bfd_error_handler) - (_("%B: section %A vma 0x%lx overlaps previous sections"), - abfd, sec, (unsigned long) sec->vma); + (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec, + (unsigned long) s_start, (unsigned long) p_end); adjust = 0; + sec->lma = p_end; } p->p_memsz += adjust; if (this_hdr->sh_type != SHT_NOBITS) { + if (p->p_filesz + adjust < p->p_memsz) + { + /* We have a PROGBITS section following NOBITS ones. + Allocate file space for the NOBITS section(s) and + zero it. */ + adjust = p->p_memsz - p->p_filesz; + if (!write_zeros (abfd, off, adjust)) + return FALSE; + } off += adjust; p->p_filesz += adjust; } @@ -4510,24 +4578,37 @@ assign_file_positions_for_load_sections (bfd *abfd, /* Check that all sections are in a PT_LOAD segment. Don't check funky gdb generated core files. */ if (p->p_type == PT_LOAD && bfd_get_format (abfd) != bfd_core) - for (i = 0, secpp = m->sections; i < m->count; i++, secpp++) - { - Elf_Internal_Shdr *this_hdr; - asection *sec; - - sec = *secpp; - this_hdr = &(elf_section_data(sec)->this_hdr); - if (this_hdr->sh_size != 0 - && !ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, p)) + { + bfd_boolean check_vma = TRUE; + + for (i = 1; i < m->count; i++) + if (m->sections[i]->vma == m->sections[i - 1]->vma + && ELF_SECTION_SIZE (&(elf_section_data (m->sections[i]) + ->this_hdr), p) != 0 + && ELF_SECTION_SIZE (&(elf_section_data (m->sections[i - 1]) + ->this_hdr), p) != 0) { - (*_bfd_error_handler) - (_("%B: section `%A' can't be allocated in segment %d"), - abfd, sec, j); - print_segment_map (m); - bfd_set_error (bfd_error_bad_value); - return FALSE; + /* Looks like we have overlays packed into the segment. */ + check_vma = FALSE; + break; } - } + + for (i = 0; i < m->count; i++) + { + Elf_Internal_Shdr *this_hdr; + asection *sec; + + sec = m->sections[i]; + this_hdr = &(elf_section_data(sec)->this_hdr); + if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)) + { + (*_bfd_error_handler) + (_("%B: section `%A' can't be allocated in segment %d"), + abfd, sec, j); + print_segment_map (m); + } + } + } } elf_tdata (abfd)->next_file_pos = off; @@ -4569,13 +4650,12 @@ assign_file_positions_for_non_load_sections (bfd *abfd, BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos); else if ((hdr->sh_flags & SHF_ALLOC) != 0) { - if (hdr->sh_size != 0) - ((*_bfd_error_handler) - (_("%B: warning: allocated section `%s' not in segment"), - abfd, - (hdr->bfd_section == NULL - ? "*unknown*" - : hdr->bfd_section->name))); + (*_bfd_error_handler) + (_("%B: warning: allocated section `%s' not in segment"), + abfd, + (hdr->bfd_section == NULL + ? "*unknown*" + : hdr->bfd_section->name)); /* We don't need to page align empty sections. */ if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0) off += vma_page_aligned_bias (hdr->sh_addr, off, @@ -4818,8 +4898,7 @@ assign_file_positions_except_relocs (bfd *abfd, static bfd_boolean prep_headers (bfd *abfd) { - Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ - Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form. */ struct elf_strtab_hash *shstrtab; const struct elf_backend_data *bed = get_elf_backend_data (abfd); @@ -4887,7 +4966,6 @@ prep_headers (bfd *abfd) else { i_ehdrp->e_phentsize = 0; - i_phdrp = 0; i_ehdrp->e_phoff = 0; } @@ -4935,7 +5013,6 @@ bfd_boolean _bfd_elf_write_object_contents (bfd *abfd) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); - Elf_Internal_Ehdr *i_ehdrp; Elf_Internal_Shdr **i_shdrp; bfd_boolean failed; unsigned int count, num_sec; @@ -4945,7 +5022,6 @@ _bfd_elf_write_object_contents (bfd *abfd) return FALSE; i_shdrp = elf_elfsections (abfd); - i_ehdrp = elf_elfheader (abfd); failed = FALSE; bfd_map_over_sections (abfd, bed->s->write_relocs, &failed); @@ -5003,34 +5079,34 @@ unsigned int _bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect) { const struct elf_backend_data *bed; - unsigned int index; + unsigned int sec_index; if (elf_section_data (asect) != NULL && elf_section_data (asect)->this_idx != 0) return elf_section_data (asect)->this_idx; if (bfd_is_abs_section (asect)) - index = SHN_ABS; + sec_index = SHN_ABS; else if (bfd_is_com_section (asect)) - index = SHN_COMMON; + sec_index = SHN_COMMON; else if (bfd_is_und_section (asect)) - index = SHN_UNDEF; + sec_index = SHN_UNDEF; else - index = SHN_BAD; + sec_index = SHN_BAD; bed = get_elf_backend_data (abfd); if (bed->elf_backend_section_from_bfd_section) { - int retval = index; + int retval = sec_index; if ((*bed->elf_backend_section_from_bfd_section) (abfd, asect, &retval)) return retval; } - if (index == SHN_BAD) + if (sec_index == SHN_BAD) bfd_set_error (bfd_error_nonrepresentable_section); - return index; + return sec_index; } /* Given a BFD symbol, return the index in the ELF symbol table, or -1 @@ -5365,7 +5441,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) all of the sections we have selected. */ amt = sizeof (struct elf_segment_map); amt += ((bfd_size_type) section_count - 1) * sizeof (asection *); - map = bfd_zalloc (obfd, amt); + map = (struct elf_segment_map *) bfd_zalloc (obfd, amt); if (map == NULL) return FALSE; @@ -5449,7 +5525,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) pointers that we are interested in. As these sections get assigned to a segment, they are removed from this array. */ - sections = bfd_malloc2 (section_count, sizeof (asection *)); + sections = (asection **) bfd_malloc2 (section_count, sizeof (asection *)); if (sections == NULL) return FALSE; @@ -5695,7 +5771,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 = bfd_alloc (obfd, amt); + map = (struct elf_segment_map *) bfd_alloc (obfd, amt); if (map == NULL) { free (sections); @@ -5801,7 +5877,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) section = section->next) { this_hdr = &(elf_section_data(section)->this_hdr); - if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment)) + if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { if (!first_section) first_section = lowest_section = section; @@ -5816,7 +5892,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) amt = sizeof (struct elf_segment_map); if (section_count != 0) amt += ((bfd_size_type) section_count - 1) * sizeof (asection *); - map = bfd_zalloc (obfd, amt); + map = (struct elf_segment_map *) bfd_zalloc (obfd, amt); if (map == NULL) return FALSE; @@ -5880,7 +5956,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) section = section->next) { this_hdr = &(elf_section_data(section)->this_hdr); - if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment)) + if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { map->sections[isec++] = section->output_section; if (isec == section_count) @@ -5957,7 +6033,7 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd) /* Check if this section is covered by the segment. */ this_hdr = &(elf_section_data(section)->this_hdr); - if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment)) + if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { /* FIXME: Check if its output section is changed or removed. What else do we need to check? */ @@ -6002,18 +6078,21 @@ _bfd_elf_init_private_section_data (bfd *ibfd, { Elf_Internal_Shdr *ihdr, *ohdr; - bfd_boolean need_group = link_info == NULL || link_info->relocatable; + bfd_boolean final_link = link_info != NULL && !link_info->relocatable; if (ibfd->xvec->flavour != bfd_target_elf_flavour || obfd->xvec->flavour != bfd_target_elf_flavour) return TRUE; - /* Don't copy the output ELF section type from input if the - output BFD section flags have been set to something different. - elf_fake_sections will set ELF section type based on BFD - section flags. */ + /* For objcopy and relocatable link, don't copy the output ELF + section type from input if the output BFD section flags have been + set to something different. For a final link allow some flags + that the linker clears to differ. */ if (elf_section_type (osec) == SHT_NULL - && (osec->flags == isec->flags || !osec->flags)) + && (osec->flags == isec->flags + || (final_link + && ((osec->flags ^ isec->flags) + & ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES)) == 0))) elf_section_type (osec) = elf_section_type (isec); /* FIXME: Is this correct for all OS/PROC specific flags? */ @@ -6024,7 +6103,7 @@ _bfd_elf_init_private_section_data (bfd *ibfd, SHT_GROUP section will have its elf_next_in_group pointing back to the input group members. Ignore linker created group section. See elfNN_ia64_object_p in elfxx-ia64.c. */ - if (need_group) + if (!final_link) { if (elf_sec_group (isec) == NULL || (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0) @@ -6083,52 +6162,92 @@ _bfd_elf_copy_private_section_data (bfd *ibfd, NULL); } -/* Copy private header information. */ +/* Look at all the SHT_GROUP sections in IBFD, making any adjustments + necessary if we are removing either the SHT_GROUP section or any of + the group member sections. DISCARDED is the value that a section's + output_section has if the section will be discarded, NULL when this + function is called from objcopy, bfd_abs_section_ptr when called + from the linker. */ bfd_boolean -_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd) +_bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded) { asection *isec; - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return TRUE; - - /* Copy over private BFD data if it has not already been copied. - This must be done here, rather than in the copy_private_bfd_data - 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 (! copy_private_bfd_data (ibfd, obfd)) - return FALSE; - } - - /* _bfd_elf_copy_private_section_data copied over the SHF_GROUP flag - but this might be wrong if we deleted the group section. */ for (isec = ibfd->sections; isec != NULL; isec = isec->next) - if (elf_section_type (isec) == SHT_GROUP - && isec->output_section == NULL) + if (elf_section_type (isec) == SHT_GROUP) { asection *first = elf_next_in_group (isec); asection *s = first; + bfd_size_type removed = 0; + while (s != NULL) { - if (s->output_section != NULL) + /* If this member section is being output but the + SHT_GROUP section is not, then clear the group info + set up by _bfd_elf_copy_private_section_data. */ + if (s->output_section != discarded + && isec->output_section == discarded) { elf_section_flags (s->output_section) &= ~SHF_GROUP; elf_group_name (s->output_section) = NULL; } + /* Conversely, if the member section is not being output + but the SHT_GROUP section is, then adjust its size. */ + else if (s->output_section == discarded + && isec->output_section != discarded) + removed += 4; s = elf_next_in_group (s); if (s == first) break; } + if (removed != 0) + { + if (discarded != NULL) + { + /* If we've been called for ld -r, then we need to + adjust the input section size. This function may + be called multiple times, so save the original + size. */ + if (isec->rawsize == 0) + isec->rawsize = isec->size; + isec->size = isec->rawsize - removed; + } + else + { + /* Adjust the output section size when called from + objcopy. */ + isec->output_section->size -= removed; + } + } } return TRUE; } +/* Copy private header information. */ + +bfd_boolean +_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd) +{ + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return TRUE; + + /* Copy over private BFD data if it has not already been copied. + This must be done here, rather than in the copy_private_bfd_data + 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 (! copy_private_bfd_data (ibfd, obfd)) + return FALSE; + } + + return _bfd_elf_fixup_group_sections (ibfd, NULL); +} + /* Copy private symbol information. If this symbol is in a section which we did not map into a BFD section, try to map the section index correctly. We use special macro definitions for the mapped @@ -6220,7 +6339,8 @@ swap_out_syms (bfd *abfd, symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; symstrtab_hdr->sh_type = SHT_STRTAB; - outbound_syms = bfd_alloc2 (abfd, 1 + symcount, bed->s->sizeof_sym); + outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount, + bed->s->sizeof_sym); if (outbound_syms == NULL) { _bfd_stringtab_free (stt); @@ -6233,8 +6353,8 @@ swap_out_syms (bfd *abfd, if (symtab_shndx_hdr->sh_name != 0) { amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx); - outbound_shndx = bfd_zalloc2 (abfd, 1 + symcount, - sizeof (Elf_External_Sym_Shndx)); + outbound_shndx = (bfd_byte *) + bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx)); if (outbound_shndx == NULL) { _bfd_stringtab_free (stt); @@ -6446,6 +6566,8 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"), if (flags & BSF_LOCAL) bind = STB_LOCAL; + else if (flags & BSF_GNU_UNIQUE) + bind = STB_GNU_UNIQUE; else if (flags & BSF_WEAK) bind = STB_WEAK; else if (flags & BSF_GLOBAL) @@ -6670,14 +6792,14 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver) hdr = &elf_tdata (abfd)->dynverref_hdr; - elf_tdata (abfd)->verref = bfd_zalloc2 (abfd, hdr->sh_info, - sizeof (Elf_Internal_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; elf_tdata (abfd)->cverrefs = hdr->sh_info; - contents = bfd_malloc (hdr->sh_size); + contents = (bfd_byte *) bfd_malloc (hdr->sh_size); if (contents == NULL) { error_return_verref: @@ -6717,8 +6839,9 @@ error_return_verref: iverneed->vn_auxptr = NULL; else { - iverneed->vn_auxptr = bfd_alloc2 (abfd, iverneed->vn_cnt, - sizeof (Elf_Internal_Vernaux)); + iverneed->vn_auxptr = (struct elf_internal_vernaux *) + bfd_alloc2 (abfd, iverneed->vn_cnt, + sizeof (Elf_Internal_Vernaux)); if (iverneed->vn_auxptr == NULL) goto error_return_verref; } @@ -6786,7 +6909,7 @@ error_return_verref: hdr = &elf_tdata (abfd)->dynverdef_hdr; - contents = bfd_malloc (hdr->sh_size); + contents = (bfd_byte *) bfd_malloc (hdr->sh_size); if (contents == NULL) goto error_return; if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 @@ -6830,8 +6953,8 @@ error_return_verref: else freeidx = ++maxidx; } - elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, maxidx, - sizeof (Elf_Internal_Verdef)); + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) + bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef)); if (elf_tdata (abfd)->verdef == NULL) goto error_return; @@ -6864,8 +6987,9 @@ error_return_verdef: iverdef->vd_auxptr = NULL; else { - iverdef->vd_auxptr = bfd_alloc2 (abfd, iverdef->vd_cnt, - sizeof (Elf_Internal_Verdaux)); + iverdef->vd_auxptr = (struct elf_internal_verdaux *) + bfd_alloc2 (abfd, iverdef->vd_cnt, + sizeof (Elf_Internal_Verdaux)); if (iverdef->vd_auxptr == NULL) goto error_return_verdef; } @@ -6922,8 +7046,8 @@ error_return_verdef: else freeidx++; - elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, freeidx, - sizeof (Elf_Internal_Verdef)); + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) + bfd_zalloc2 (abfd, freeidx, sizeof (Elf_Internal_Verdef)); if (elf_tdata (abfd)->verdef == NULL) goto error_return; @@ -6949,7 +7073,8 @@ error_return_verdef: if (iverdef->vd_nodename == NULL) goto error_return_verdef; iverdef->vd_nextdef = NULL; - iverdef->vd_auxptr = bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux)); + iverdef->vd_auxptr = (struct elf_internal_verdaux *) + bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux)); if (iverdef->vd_auxptr == NULL) goto error_return_verdef; @@ -6972,7 +7097,7 @@ _bfd_elf_make_empty_symbol (bfd *abfd) elf_symbol_type *newsym; bfd_size_type amt = sizeof (elf_symbol_type); - newsym = bfd_zalloc (abfd, amt); + newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt); if (!newsym) return NULL; else @@ -7400,16 +7525,24 @@ _bfd_elf_rel_vtable_reloc_fn out details about the corefile. */ #ifdef HAVE_SYS_PROCFS_H +/* Needed for new procfs interface on sparc-solaris. */ +# define _STRUCTURED_PROC 1 # include #endif -/* FIXME: this is kinda wrong, but it's what gdb wants. */ +/* Return a PID that identifies a "thread" for threaded cores, or the + PID of the main process for non-threaded cores. */ static int elfcore_make_pid (bfd *abfd) { - return ((elf_tdata (abfd)->core_lwpid << 16) - + (elf_tdata (abfd)->core_pid)); + int pid; + + pid = elf_tdata (abfd)->core_lwpid; + if (pid == 0) + pid = elf_tdata (abfd)->core_pid; + + return pid; } /* If there isn't a section called NAME, make one, using @@ -7457,7 +7590,7 @@ _bfd_elfcore_make_pseudosection (bfd *abfd, sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd)); len = strlen (buf) + 1; - threaded_name = bfd_alloc (abfd, len); + threaded_name = (char *) bfd_alloc (abfd, len); if (threaded_name == NULL) return FALSE; memcpy (threaded_name, buf, len); @@ -7499,7 +7632,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) has already been set by another thread. */ if (elf_tdata (abfd)->core_signal == 0) elf_tdata (abfd)->core_signal = prstat.pr_cursig; - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core_pid == 0) + elf_tdata (abfd)->core_pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -7509,6 +7643,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) */ #if defined (HAVE_PRSTATUS_T_PR_WHO) elf_tdata (abfd)->core_lwpid = prstat.pr_who; +#else + elf_tdata (abfd)->core_lwpid = prstat.pr_pid; #endif } #if defined (HAVE_PRSTATUS32_T) @@ -7525,7 +7661,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) has already been set by another thread. */ if (elf_tdata (abfd)->core_signal == 0) elf_tdata (abfd)->core_signal = prstat.pr_cursig; - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core_pid == 0) + elf_tdata (abfd)->core_pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -7535,6 +7672,8 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) */ #if defined (HAVE_PRSTATUS32_T_PR_WHO) elf_tdata (abfd)->core_lwpid = prstat.pr_who; +#else + elf_tdata (abfd)->core_lwpid = prstat.pr_pid; #endif } #endif /* HAVE_PRSTATUS32_T */ @@ -7581,6 +7720,16 @@ elfcore_grok_prxfpreg (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note); } +/* Linux dumps the Intel XSAVE extended state in a note named "LINUX" + with a note type of NT_X86_XSTATE. Just include the whole note's + contents literally. */ + +static bfd_boolean +elfcore_grok_xstatereg (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-xstate", note); +} + static bfd_boolean elfcore_grok_ppc_vmx (bfd *abfd, Elf_Internal_Note *note) { @@ -7593,6 +7742,42 @@ elfcore_grok_ppc_vsx (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vsx", note); } +static bfd_boolean +elfcore_grok_s390_high_gprs (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-high-gprs", note); +} + +static bfd_boolean +elfcore_grok_s390_timer (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-timer", note); +} + +static bfd_boolean +elfcore_grok_s390_todcmp (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-todcmp", note); +} + +static bfd_boolean +elfcore_grok_s390_todpreg (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-todpreg", note); +} + +static bfd_boolean +elfcore_grok_s390_ctrs (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-ctrs", note); +} + +static bfd_boolean +elfcore_grok_s390_prefix (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note); +} + #if defined (HAVE_PRPSINFO_T) typedef prpsinfo_t elfcore_psinfo_t; #if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */ @@ -7615,7 +7800,7 @@ char * _bfd_elfcore_strndup (bfd *abfd, char *start, size_t max) { char *dups; - char *end = memchr (start, '\0', max); + char *end = (char *) memchr (start, '\0', max); size_t len; if (end == NULL) @@ -7623,7 +7808,7 @@ _bfd_elfcore_strndup (bfd *abfd, char *start, size_t max) else len = end - start; - dups = bfd_alloc (abfd, len + 1); + dups = (char *) bfd_alloc (abfd, len + 1); if (dups == NULL) return NULL; @@ -7747,7 +7932,10 @@ 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_signal = lwpstat.pr_cursig; + /* 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; /* Make a ".reg/999" section. */ @@ -7843,7 +8031,7 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note) sprintf (buf, ".reg/%ld", (long) bfd_get_32 (abfd, note->descdata + 8)); len = strlen (buf) + 1; - name = bfd_alloc (abfd, len); + name = (char *) bfd_alloc (abfd, len); if (name == NULL) return FALSE; @@ -7874,7 +8062,7 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note) sprintf (buf, ".module/%08lx", (unsigned long) base_addr); len = strlen (buf) + 1; - name = bfd_alloc (abfd, len); + name = (char *) bfd_alloc (abfd, len); if (name == NULL) return FALSE; @@ -7940,6 +8128,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_X86_XSTATE: /* Linux XSAVE extension */ + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_xstatereg (abfd, note); + else + return TRUE; + case NT_PPC_VMX: if (note->namesz == 6 && strcmp (note->namedata, "LINUX") == 0) @@ -7954,6 +8149,48 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_S390_HIGH_GPRS: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_high_gprs (abfd, note); + else + return TRUE; + + case NT_S390_TIMER: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_timer (abfd, note); + else + return TRUE; + + case NT_S390_TODCMP: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_todcmp (abfd, note); + else + return TRUE; + + case NT_S390_TODPREG: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_todpreg (abfd, note); + else + return TRUE; + + case NT_S390_CTRS: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_ctrs (abfd, note); + else + return TRUE; + + case NT_S390_PREFIX: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_prefix (abfd, note); + else + return TRUE; + case NT_PRPSINFO: case NT_PSINFO: if (bed->elf_backend_grok_psinfo) @@ -7985,7 +8222,7 @@ 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_alloc (abfd, note->descsz); + elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz); if (elf_tdata (abfd)->build_id == NULL) return FALSE; @@ -8204,7 +8441,7 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid) /* Make a ".qnx_core_status/%d" section. */ sprintf (buf, ".qnx_core_status/%ld", *tid); - name = bfd_alloc (abfd, strlen (buf) + 1); + name = (char *) bfd_alloc (abfd, strlen (buf) + 1); if (name == NULL) return FALSE; strcpy (name, buf); @@ -8233,7 +8470,7 @@ elfcore_grok_nto_regs (bfd *abfd, /* Make a "(base)/%d" section. */ sprintf (buf, "%s/%ld", base, tid); - name = bfd_alloc (abfd, strlen (buf) + 1); + name = (char *) bfd_alloc (abfd, strlen (buf) + 1); if (name == NULL) return FALSE; strcpy (name, buf); @@ -8290,7 +8527,7 @@ elfcore_grok_spu_note (bfd *abfd, Elf_Internal_Note *note) /* Use note name as section name. */ len = note->namesz; - name = bfd_alloc (abfd, len); + name = (char *) bfd_alloc (abfd, len); if (name == NULL) return FALSE; memcpy (name, note->namedata, len); @@ -8344,7 +8581,7 @@ elfcore_write_note (bfd *abfd, newspace = 12 + ((namesz + 3) & -4) + ((size + 3) & -4); - buf = realloc (buf, *bufsiz + newspace); + buf = (char *) realloc (buf, *bufsiz + newspace); if (buf == NULL) return buf; dest = buf + *bufsiz; @@ -8572,6 +8809,15 @@ elfcore_write_prxfpreg (bfd *abfd, note_name, NT_PRXFPREG, xfpregs, size); } +char * +elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz, + const void *xfpregs, int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_X86_XSTATE, xfpregs, size); +} + char * elfcore_write_ppc_vmx (bfd *abfd, char *buf, @@ -8596,6 +8842,79 @@ elfcore_write_ppc_vsx (bfd *abfd, note_name, NT_PPC_VSX, ppc_vsx, size); } +static char * +elfcore_write_s390_high_gprs (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_high_gprs, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_HIGH_GPRS, + s390_high_gprs, size); +} + +char * +elfcore_write_s390_timer (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_timer, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_TIMER, s390_timer, size); +} + +char * +elfcore_write_s390_todcmp (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_todcmp, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_TODCMP, s390_todcmp, size); +} + +char * +elfcore_write_s390_todpreg (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_todpreg, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_TODPREG, s390_todpreg, size); +} + +char * +elfcore_write_s390_ctrs (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_ctrs, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_CTRS, s390_ctrs, size); +} + +char * +elfcore_write_s390_prefix (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_prefix, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_PREFIX, s390_prefix, size); +} + char * elfcore_write_register_note (bfd *abfd, char *buf, @@ -8608,10 +8927,24 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_prfpreg (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-xfp") == 0) return elfcore_write_prxfpreg (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-xstate") == 0) + return elfcore_write_xstatereg (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-ppc-vmx") == 0) return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-ppc-vsx") == 0) return elfcore_write_ppc_vsx (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-high-gprs") == 0) + return elfcore_write_s390_high_gprs (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-timer") == 0) + return elfcore_write_s390_timer (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-todcmp") == 0) + return elfcore_write_s390_todcmp (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-todpreg") == 0) + return elfcore_write_s390_todpreg (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-ctrs") == 0) + return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-prefix") == 0) + return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size); return NULL; } @@ -8704,7 +9037,7 @@ elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size) if (bfd_seek (abfd, offset, SEEK_SET) != 0) return FALSE; - buf = bfd_malloc (size); + buf = (char *) bfd_malloc (size); if (buf == NULL) return FALSE; @@ -8922,9 +9255,19 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd, size = count * sizeof (asymbol); p = relplt->relocation; for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel) - size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt"); + { + size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt"); + if (p->addend != 0) + { +#ifdef BFD64 + size += sizeof ("+0x") - 1 + 8 + 8 * (bed->s->elfclass == ELFCLASS64); +#else + size += sizeof ("+0x") - 1 + 8; +#endif + } + } - s = *ret = bfd_malloc (size); + s = *ret = (asymbol *) bfd_malloc (size); if (s == NULL) return -1; @@ -8953,6 +9296,19 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd, len = strlen ((*p->sym_ptr_ptr)->name); memcpy (names, (*p->sym_ptr_ptr)->name, len); names += len; + if (p->addend != 0) + { + char buf[30], *a; + + memcpy (names, "+0x", sizeof ("+0x") - 1); + names += sizeof ("+0x") - 1; + bfd_sprintf_vma (abfd, buf, p->addend); + for (a = buf; *a == '0'; ++a) + ; + len = strlen (a); + memcpy (names, a, len); + names += len; + } memcpy (names, "@plt", sizeof ("@plt")); names += sizeof ("@plt"); ++s, ++n;