X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf.c;h=a3a83e4b32e5e89f10520bf479a984f024f83177;hb=dbb410c3e20602a6d4be32a6833a9b7f5b0f1ae9;hp=5dac0a35a85e6c450b26f8e61ef23ecbb6617362;hpb=f572a39d1559be095b66dc346f00d205492b02bb;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index 5dac0a35a8..a3a83e4b32 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1,5 +1,6 @@ /* ELF executable support for BFD. - Copyright 1993, 94, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -49,13 +50,25 @@ static boolean assign_file_positions_except_relocs PARAMS ((bfd *)); static boolean prep_headers PARAMS ((bfd *)); static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **, int)); static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *)); -static char *elf_read PARAMS ((bfd *, long, unsigned int)); +static char *elf_read PARAMS ((bfd *, file_ptr, bfd_size_type)); +static boolean setup_group PARAMS ((bfd *, Elf_Internal_Shdr *, asection *)); static void elf_fake_sections PARAMS ((bfd *, asection *, PTR)); +static void set_group_contents PARAMS ((bfd *, asection *, PTR)); static boolean assign_section_numbers PARAMS ((bfd *)); static INLINE int sym_is_global PARAMS ((bfd *, asymbol *)); static boolean elf_map_symbols PARAMS ((bfd *)); static bfd_size_type get_program_header_size PARAMS ((bfd *)); -static boolean elfcore_read_notes PARAMS ((bfd *, bfd_vma, bfd_vma)); +static boolean elfcore_read_notes PARAMS ((bfd *, file_ptr, bfd_size_type)); +static boolean elf_find_function PARAMS ((bfd *, asection *, asymbol **, + bfd_vma, const char **, + const char **)); +static int elfcore_make_pid PARAMS ((bfd *)); +static boolean elfcore_maybe_make_sect PARAMS ((bfd *, char *, asection *)); +static boolean elfcore_make_note_pseudosection PARAMS ((bfd *, char *, + Elf_Internal_Note *)); +static boolean elfcore_grok_prfpreg PARAMS ((bfd *, Elf_Internal_Note *)); +static boolean elfcore_grok_prxfpreg PARAMS ((bfd *, Elf_Internal_Note *)); +static boolean elfcore_grok_note PARAMS ((bfd *, Elf_Internal_Note *)); /* Swap version information in and out. The version information is currently size independent. If that ever changes, this code will @@ -69,13 +82,13 @@ _bfd_elf_swap_verdef_in (abfd, src, dst) const Elf_External_Verdef *src; Elf_Internal_Verdef *dst; { - dst->vd_version = bfd_h_get_16 (abfd, src->vd_version); - dst->vd_flags = bfd_h_get_16 (abfd, src->vd_flags); - dst->vd_ndx = bfd_h_get_16 (abfd, src->vd_ndx); - dst->vd_cnt = bfd_h_get_16 (abfd, src->vd_cnt); - dst->vd_hash = bfd_h_get_32 (abfd, src->vd_hash); - dst->vd_aux = bfd_h_get_32 (abfd, src->vd_aux); - dst->vd_next = bfd_h_get_32 (abfd, src->vd_next); + dst->vd_version = H_GET_16 (abfd, src->vd_version); + dst->vd_flags = H_GET_16 (abfd, src->vd_flags); + dst->vd_ndx = H_GET_16 (abfd, src->vd_ndx); + dst->vd_cnt = H_GET_16 (abfd, src->vd_cnt); + dst->vd_hash = H_GET_32 (abfd, src->vd_hash); + dst->vd_aux = H_GET_32 (abfd, src->vd_aux); + dst->vd_next = H_GET_32 (abfd, src->vd_next); } /* Swap out a Verdef structure. */ @@ -86,13 +99,13 @@ _bfd_elf_swap_verdef_out (abfd, src, dst) const Elf_Internal_Verdef *src; Elf_External_Verdef *dst; { - bfd_h_put_16 (abfd, src->vd_version, dst->vd_version); - bfd_h_put_16 (abfd, src->vd_flags, dst->vd_flags); - bfd_h_put_16 (abfd, src->vd_ndx, dst->vd_ndx); - bfd_h_put_16 (abfd, src->vd_cnt, dst->vd_cnt); - bfd_h_put_32 (abfd, src->vd_hash, dst->vd_hash); - bfd_h_put_32 (abfd, src->vd_aux, dst->vd_aux); - bfd_h_put_32 (abfd, src->vd_next, dst->vd_next); + H_PUT_16 (abfd, src->vd_version, dst->vd_version); + H_PUT_16 (abfd, src->vd_flags, dst->vd_flags); + H_PUT_16 (abfd, src->vd_ndx, dst->vd_ndx); + H_PUT_16 (abfd, src->vd_cnt, dst->vd_cnt); + H_PUT_32 (abfd, src->vd_hash, dst->vd_hash); + H_PUT_32 (abfd, src->vd_aux, dst->vd_aux); + H_PUT_32 (abfd, src->vd_next, dst->vd_next); } /* Swap in a Verdaux structure. */ @@ -103,8 +116,8 @@ _bfd_elf_swap_verdaux_in (abfd, src, dst) const Elf_External_Verdaux *src; Elf_Internal_Verdaux *dst; { - dst->vda_name = bfd_h_get_32 (abfd, src->vda_name); - dst->vda_next = bfd_h_get_32 (abfd, src->vda_next); + dst->vda_name = H_GET_32 (abfd, src->vda_name); + dst->vda_next = H_GET_32 (abfd, src->vda_next); } /* Swap out a Verdaux structure. */ @@ -115,8 +128,8 @@ _bfd_elf_swap_verdaux_out (abfd, src, dst) const Elf_Internal_Verdaux *src; Elf_External_Verdaux *dst; { - bfd_h_put_32 (abfd, src->vda_name, dst->vda_name); - bfd_h_put_32 (abfd, src->vda_next, dst->vda_next); + H_PUT_32 (abfd, src->vda_name, dst->vda_name); + H_PUT_32 (abfd, src->vda_next, dst->vda_next); } /* Swap in a Verneed structure. */ @@ -127,11 +140,11 @@ _bfd_elf_swap_verneed_in (abfd, src, dst) const Elf_External_Verneed *src; Elf_Internal_Verneed *dst; { - dst->vn_version = bfd_h_get_16 (abfd, src->vn_version); - dst->vn_cnt = bfd_h_get_16 (abfd, src->vn_cnt); - dst->vn_file = bfd_h_get_32 (abfd, src->vn_file); - dst->vn_aux = bfd_h_get_32 (abfd, src->vn_aux); - dst->vn_next = bfd_h_get_32 (abfd, src->vn_next); + dst->vn_version = H_GET_16 (abfd, src->vn_version); + dst->vn_cnt = H_GET_16 (abfd, src->vn_cnt); + dst->vn_file = H_GET_32 (abfd, src->vn_file); + dst->vn_aux = H_GET_32 (abfd, src->vn_aux); + dst->vn_next = H_GET_32 (abfd, src->vn_next); } /* Swap out a Verneed structure. */ @@ -142,11 +155,11 @@ _bfd_elf_swap_verneed_out (abfd, src, dst) const Elf_Internal_Verneed *src; Elf_External_Verneed *dst; { - bfd_h_put_16 (abfd, src->vn_version, dst->vn_version); - bfd_h_put_16 (abfd, src->vn_cnt, dst->vn_cnt); - bfd_h_put_32 (abfd, src->vn_file, dst->vn_file); - bfd_h_put_32 (abfd, src->vn_aux, dst->vn_aux); - bfd_h_put_32 (abfd, src->vn_next, dst->vn_next); + H_PUT_16 (abfd, src->vn_version, dst->vn_version); + H_PUT_16 (abfd, src->vn_cnt, dst->vn_cnt); + H_PUT_32 (abfd, src->vn_file, dst->vn_file); + H_PUT_32 (abfd, src->vn_aux, dst->vn_aux); + H_PUT_32 (abfd, src->vn_next, dst->vn_next); } /* Swap in a Vernaux structure. */ @@ -157,11 +170,11 @@ _bfd_elf_swap_vernaux_in (abfd, src, dst) const Elf_External_Vernaux *src; Elf_Internal_Vernaux *dst; { - dst->vna_hash = bfd_h_get_32 (abfd, src->vna_hash); - dst->vna_flags = bfd_h_get_16 (abfd, src->vna_flags); - dst->vna_other = bfd_h_get_16 (abfd, src->vna_other); - dst->vna_name = bfd_h_get_32 (abfd, src->vna_name); - dst->vna_next = bfd_h_get_32 (abfd, src->vna_next); + dst->vna_hash = H_GET_32 (abfd, src->vna_hash); + dst->vna_flags = H_GET_16 (abfd, src->vna_flags); + dst->vna_other = H_GET_16 (abfd, src->vna_other); + dst->vna_name = H_GET_32 (abfd, src->vna_name); + dst->vna_next = H_GET_32 (abfd, src->vna_next); } /* Swap out a Vernaux structure. */ @@ -172,11 +185,11 @@ _bfd_elf_swap_vernaux_out (abfd, src, dst) const Elf_Internal_Vernaux *src; Elf_External_Vernaux *dst; { - bfd_h_put_32 (abfd, src->vna_hash, dst->vna_hash); - bfd_h_put_16 (abfd, src->vna_flags, dst->vna_flags); - bfd_h_put_16 (abfd, src->vna_other, dst->vna_other); - bfd_h_put_32 (abfd, src->vna_name, dst->vna_name); - bfd_h_put_32 (abfd, src->vna_next, dst->vna_next); + H_PUT_32 (abfd, src->vna_hash, dst->vna_hash); + H_PUT_16 (abfd, src->vna_flags, dst->vna_flags); + H_PUT_16 (abfd, src->vna_other, dst->vna_other); + H_PUT_32 (abfd, src->vna_name, dst->vna_name); + H_PUT_32 (abfd, src->vna_next, dst->vna_next); } /* Swap in a Versym structure. */ @@ -187,7 +200,7 @@ _bfd_elf_swap_versym_in (abfd, src, dst) const Elf_External_Versym *src; Elf_Internal_Versym *dst; { - dst->vs_vers = bfd_h_get_16 (abfd, src->vs_vers); + dst->vs_vers = H_GET_16 (abfd, src->vs_vers); } /* Swap out a Versym structure. */ @@ -198,7 +211,7 @@ _bfd_elf_swap_versym_out (abfd, src, dst) const Elf_Internal_Versym *src; Elf_External_Versym *dst; { - bfd_h_put_16 (abfd, src->vs_vers, dst->vs_vers); + H_PUT_16 (abfd, src->vs_vers, dst->vs_vers); } /* Standard ELF hash function. Do not change this function; you will @@ -234,16 +247,16 @@ bfd_elf_hash (namearg) static char * elf_read (abfd, offset, size) bfd *abfd; - long offset; - unsigned int size; + file_ptr offset; + bfd_size_type size; { char *buf; if ((buf = bfd_alloc (abfd, size)) == NULL) return NULL; - if (bfd_seek (abfd, offset, SEEK_SET) == -1) + if (bfd_seek (abfd, offset, SEEK_SET) != 0) return NULL; - if (bfd_read ((PTR) buf, size, 1, abfd) != size) + if (bfd_bread ((PTR) buf, size, abfd) != size) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_file_truncated); @@ -258,8 +271,8 @@ bfd_elf_mkobject (abfd) { /* This just does initialization. */ /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */ - elf_tdata (abfd) = (struct elf_obj_tdata *) - bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); + bfd_size_type amt = sizeof (struct elf_obj_tdata); + elf_tdata (abfd) = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt); if (elf_tdata (abfd) == 0) return false; /* Since everything is done at close time, do we need any @@ -283,8 +296,8 @@ bfd_elf_get_str_section (abfd, shindex) { Elf_Internal_Shdr **i_shdrp; char *shstrtab = NULL; - unsigned int offset; - unsigned int shstrtabsize; + file_ptr offset; + bfd_size_type shstrtabsize; i_shdrp = elf_elfsections (abfd); if (i_shdrp == 0 || i_shdrp[shindex] == 0) @@ -323,7 +336,7 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex) { (*_bfd_error_handler) (_("%s: invalid string offset %u >= %lu for section `%s'"), - bfd_get_filename (abfd), strindex, (unsigned long) hdr->sh_size, + bfd_archive_filename (abfd), strindex, (unsigned long) hdr->sh_size, ((shindex == elf_elfheader(abfd)->e_shstrndx && strindex == hdr->sh_name) ? ".shstrtab" @@ -334,6 +347,191 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex) return ((char *) hdr->contents) + strindex; } +/* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP + sections. The first element is the flags, the rest are section + pointers. */ + +typedef union elf_internal_group { + Elf_Internal_Shdr *shdr; + unsigned int flags; +} Elf_Internal_Group; + +/* Set next_in_group list pointer, and group name for NEWSECT. */ + +static boolean +setup_group (abfd, hdr, newsect) + bfd *abfd; + Elf_Internal_Shdr *hdr; + asection *newsect; +{ + unsigned int num_group = elf_tdata (abfd)->num_group; + + /* If num_group is zero, read in all SHT_GROUP sections. The count + is set to -1 if there are no SHT_GROUP sections. */ + if (num_group == 0) + { + unsigned int i, shnum; + + /* First count the number of groups. If we have a SHT_GROUP + section with just a flag word (ie. sh_size is 4), ignore it. */ + shnum = elf_elfheader (abfd)->e_shnum; + num_group = 0; + for (i = 0; i < shnum; i++) + { + Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i]; + if (shdr->sh_type == SHT_GROUP && shdr->sh_size >= 8) + num_group += 1; + } + + if (num_group == 0) + num_group = -1; + elf_tdata (abfd)->num_group = num_group; + + if (num_group > 0) + { + /* We keep a list of elf section headers for group sections, + so we can find them quickly. */ + bfd_size_type amt = num_group * sizeof (Elf_Internal_Shdr *); + elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt); + if (elf_tdata (abfd)->group_sect_ptr == NULL) + return false; + + num_group = 0; + for (i = 0; i < shnum; i++) + { + Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i]; + if (shdr->sh_type == SHT_GROUP && shdr->sh_size >= 8) + { + char *src; + Elf_Internal_Group *dest; + + /* Add to list of sections. */ + elf_tdata (abfd)->group_sect_ptr[num_group] = shdr; + num_group += 1; + + /* Read the raw contents. */ + BFD_ASSERT (sizeof (*dest) >= 4); + amt = shdr->sh_size * sizeof (*dest) / 4; + shdr->contents = bfd_alloc (abfd, amt); + if (shdr->contents == NULL + || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0 + || (bfd_bread (shdr->contents, shdr->sh_size, abfd) + != shdr->sh_size)) + return false; + + /* Translate raw contents, a flag word followed by an + array of elf section indices all in target byte order, + to the flag word followed by an array of elf section + pointers. */ + src = shdr->contents + shdr->sh_size; + dest = (Elf_Internal_Group *) (shdr->contents + amt); + while (1) + { + unsigned int idx; + + src -= 4; + --dest; + idx = H_GET_32 (abfd, src); + if (src == shdr->contents) + { + dest->flags = idx; + break; + } + if (idx >= shnum) + { + ((*_bfd_error_handler) + (_("%s: invalid SHT_GROUP entry"), + bfd_archive_filename (abfd))); + idx = 0; + } + dest->shdr = elf_elfsections (abfd)[idx]; + } + } + } + } + } + + if (num_group != (unsigned) -1) + { + unsigned int i; + + for (i = 0; i < num_group; i++) + { + Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i]; + Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents; + unsigned int n_elt = shdr->sh_size / 4; + + /* Look through this group's sections to see if current + section is a member. */ + while (--n_elt != 0) + if ((++idx)->shdr == hdr) + { + asection *s; + + /* We are a member of this group. Go looking through + other members to see if any others are linked via + next_in_group. */ + idx = (Elf_Internal_Group *) shdr->contents; + n_elt = shdr->sh_size / 4; + while (--n_elt != 0) + if ((s = (++idx)->shdr->bfd_section) != NULL + && elf_section_data (s)->next_in_group != NULL) + break; + if (n_elt != 0) + { + const char *gname; + asection *next; + + /* Snarf the group name from other member, and + insert current section in circular list. */ + gname = elf_section_data (s)->group; + elf_section_data (newsect)->group = gname; + next = elf_section_data (s)->next_in_group; + elf_section_data (newsect)->next_in_group = next; + elf_section_data (s)->next_in_group = newsect; + } + else + { + struct elf_backend_data *bed; + file_ptr pos; + unsigned char ename[4]; + unsigned long iname; + const char *gname; + + /* Humbug. Get the name from the group signature + symbol. Why isn't the signature just a string? + Fortunately, the name index is at the same + place in the external symbol for both 32 and 64 + bit ELF. */ + bed = get_elf_backend_data (abfd); + pos = elf_tdata (abfd)->symtab_hdr.sh_offset; + pos += shdr->sh_info * bed->s->sizeof_sym; + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bread (ename, 4, abfd) != 4) + return false; + iname = H_GET_32 (abfd, ename); + gname = elf_string_from_elf_strtab (abfd, iname); + elf_section_data (newsect)->group = gname; + + /* Start a circular list with one element. */ + elf_section_data (newsect)->next_in_group = newsect; + } + if (shdr->bfd_section != NULL) + shdr->bfd_section->lineno = (alent *) newsect; + i = num_group - 1; + break; + } + } + } + + if (elf_section_data (newsect)->group == NULL) + { + (*_bfd_error_handler) (_("%s: no group info for section %s"), + bfd_archive_filename (abfd), newsect->name); + } + return true; +} + /* Make a BFD section from an ELF section. We store a pointer to the BFD section in the bfd_section field of the header. */ @@ -345,6 +543,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name) { asection *newsect; flagword flags; + struct elf_backend_data *bed; if (hdr->bfd_section != NULL) { @@ -362,12 +561,14 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name) if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr) || ! bfd_set_section_size (abfd, newsect, hdr->sh_size) || ! bfd_set_section_alignment (abfd, newsect, - bfd_log2 (hdr->sh_addralign))) + bfd_log2 ((bfd_vma) hdr->sh_addralign))) return false; flags = SEC_NO_FLAGS; if (hdr->sh_type != SHT_NOBITS) flags |= SEC_HAS_CONTENTS; + if (hdr->sh_type == SHT_GROUP) + flags |= SEC_GROUP | SEC_EXCLUDE; if ((hdr->sh_flags & SHF_ALLOC) != 0) { flags |= SEC_ALLOC; @@ -380,6 +581,16 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name) flags |= SEC_CODE; else if ((flags & SEC_LOAD) != 0) flags |= SEC_DATA; + if ((hdr->sh_flags & SHF_MERGE) != 0) + { + flags |= SEC_MERGE; + newsect->entsize = hdr->sh_entsize; + if ((hdr->sh_flags & SHF_STRINGS) != 0) + flags |= SEC_STRINGS; + } + if (hdr->sh_flags & SHF_GROUP) + if (!setup_group (abfd, hdr, newsect)) + return false; /* The debugging sections appear to be recognized only by name, not any sort of flag. */ @@ -410,6 +621,11 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name) if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0) flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD; + bed = get_elf_backend_data (abfd); + if (bed->elf_backend_section_flags) + if (! bed->elf_backend_section_flags (&flags, hdr)) + return false; + if (! bfd_set_section_flags (abfd, newsect, flags)) return false; @@ -540,6 +756,20 @@ bfd_elf_generic_reloc (abfd, return bfd_reloc_continue; } +/* Finish SHF_MERGE section merging. */ + +boolean +_bfd_elf_merge_sections (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + if (!is_elf_hash_table (info)) + return false; + if (elf_hash_table (info)->merge_info) + _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info); + return true; +} + /* Print out the program headers. */ boolean @@ -561,37 +791,37 @@ _bfd_elf_print_private_bfd_data (abfd, farg) c = elf_elfheader (abfd)->e_phnum; for (i = 0; i < c; i++, p++) { - const char *s; + const char *pt; char buf[20]; switch (p->p_type) { - case PT_NULL: s = "NULL"; break; - case PT_LOAD: s = "LOAD"; break; - case PT_DYNAMIC: s = "DYNAMIC"; break; - case PT_INTERP: s = "INTERP"; break; - case PT_NOTE: s = "NOTE"; break; - case PT_SHLIB: s = "SHLIB"; break; - case PT_PHDR: s = "PHDR"; break; - default: sprintf (buf, "0x%lx", p->p_type); s = buf; break; + case PT_NULL: pt = "NULL"; break; + case PT_LOAD: pt = "LOAD"; break; + case PT_DYNAMIC: pt = "DYNAMIC"; break; + case PT_INTERP: pt = "INTERP"; break; + case PT_NOTE: pt = "NOTE"; break; + case PT_SHLIB: pt = "SHLIB"; break; + case PT_PHDR: pt = "PHDR"; break; + default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break; } - fprintf (f, "%8s off 0x", s); - fprintf_vma (f, p->p_offset); + fprintf (f, "%8s off 0x", pt); + bfd_fprintf_vma (abfd, f, p->p_offset); fprintf (f, " vaddr 0x"); - fprintf_vma (f, p->p_vaddr); + bfd_fprintf_vma (abfd, f, p->p_vaddr); fprintf (f, " paddr 0x"); - fprintf_vma (f, p->p_paddr); + bfd_fprintf_vma (abfd, f, p->p_paddr); fprintf (f, " align 2**%u\n", bfd_log2 (p->p_align)); fprintf (f, " filesz 0x"); - fprintf_vma (f, p->p_filesz); + bfd_fprintf_vma (abfd, f, p->p_filesz); fprintf (f, " memsz 0x"); - fprintf_vma (f, p->p_memsz); + bfd_fprintf_vma (abfd, f, p->p_memsz); fprintf (f, " flags %c%c%c", (p->p_flags & PF_R) != 0 ? 'r' : '-', (p->p_flags & PF_W) != 0 ? 'w' : '-', (p->p_flags & PF_X) != 0 ? 'x' : '-'); - if ((p->p_flags &~ (PF_R | PF_W | PF_X)) != 0) - fprintf (f, " %lx", p->p_flags &~ (PF_R | PF_W | PF_X)); + if ((p->p_flags &~ (unsigned) (PF_R | PF_W | PF_X)) != 0) + fprintf (f, " %lx", p->p_flags &~ (unsigned) (PF_R | PF_W | PF_X)); fprintf (f, "\n"); } } @@ -600,7 +830,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg) if (s != NULL) { int elfsec; - unsigned long link; + unsigned long shlink; bfd_byte *extdyn, *extdynend; size_t extdynsize; void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *)); @@ -617,7 +847,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg) elfsec = _bfd_elf_section_from_bfd_section (abfd, s); if (elfsec == -1) goto error_return; - link = elf_elfsections (abfd)[elfsec]->sh_link; + shlink = elf_elfsections (abfd)[elfsec]->sh_link; extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn; swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in; @@ -709,9 +939,9 @@ _bfd_elf_print_private_bfd_data (abfd, farg) else { const char *string; + unsigned int tagv = dyn.d_un.d_val; - string = bfd_elf_string_from_elf_section (abfd, link, - dyn.d_un.d_val); + string = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (string == NULL) goto error_return; fprintf (f, "%s", string); @@ -794,15 +1024,16 @@ bfd_elf_print_symbol (abfd, filep, symbol, how) break; case bfd_print_symbol_more: fprintf (file, "elf "); - fprintf_vma (file, symbol->value); + bfd_fprintf_vma (abfd, file, symbol->value); fprintf (file, " %lx", (long) symbol->flags); break; case bfd_print_symbol_all: { - CONST char *section_name; - CONST char *name = NULL; + const char *section_name; + const char *name = NULL; struct elf_backend_data *bed; unsigned char st_other; + bfd_vma val; section_name = symbol->section ? symbol->section->name : "(*none*)"; @@ -813,7 +1044,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how) if (name == NULL) { name = symbol->name; - bfd_print_symbol_vandf ((PTR) file, symbol); + bfd_print_symbol_vandf (abfd, (PTR) file, symbol); } fprintf (file, " %s\t", section_name); @@ -821,10 +1052,11 @@ bfd_elf_print_symbol (abfd, filep, symbol, how) we've already printed the size; now print the alignment. For other symbols, we have no specified alignment, and we've printed the address; now print the size. */ - fprintf_vma (file, - (bfd_is_com_section (symbol->section) - ? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value - : ((elf_symbol_type *) symbol)->internal_elf_sym.st_size)); + if (bfd_is_com_section (symbol->section)) + val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value; + else + val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_size; + bfd_fprintf_vma (abfd, file, val); /* If we have version information, print it. */ if (elf_tdata (abfd)->dynversym_section != 0 @@ -906,31 +1138,31 @@ _bfd_elf_link_hash_newfunc (entry, table, string) struct bfd_hash_table *table; const char *string; { - struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; - /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct elf_link_hash_entry *) NULL) - ret = ((struct elf_link_hash_entry *) - bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry))); - if (ret == (struct elf_link_hash_entry *) NULL) - return (struct bfd_hash_entry *) ret; + if (entry == NULL) + { + entry = bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry)); + if (entry == NULL) + return entry; + } /* Call the allocation method of the superclass. */ - ret = ((struct elf_link_hash_entry *) - _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, - table, string)); - if (ret != (struct elf_link_hash_entry *) NULL) + entry = _bfd_link_hash_newfunc (entry, table, string); + if (entry != NULL) { + struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; + struct elf_link_hash_table *htab = (struct elf_link_hash_table *) table; + /* Set local fields. */ ret->indx = -1; ret->size = 0; ret->dynindx = -1; ret->dynstr_index = 0; ret->weakdef = NULL; - ret->got.offset = (bfd_vma) -1; - ret->plt.offset = (bfd_vma) -1; - ret->linker_section_pointer = (elf_linker_section_pointers_t *)0; + ret->got.refcount = htab->init_refcount; + ret->plt.refcount = htab->init_refcount; + ret->linker_section_pointer = NULL; ret->verinfo.verdef = NULL; ret->vtable_entries_used = NULL; ret->vtable_entries_size = 0; @@ -944,16 +1176,18 @@ _bfd_elf_link_hash_newfunc (entry, table, string) ret->elf_link_hash_flags = ELF_LINK_NON_ELF; } - return (struct bfd_hash_entry *) ret; + return entry; } /* Copy data from an indirect symbol to its direct symbol, hiding the - old indirect symbol. */ + old indirect symbol. Also used for copying flags to a weakdef. */ void _bfd_elf_link_hash_copy_indirect (dir, ind) struct elf_link_hash_entry *dir, *ind; { + bfd_signed_vma tmp; + /* Copy down any references that we may have already seen to the symbol which just became indirect. */ @@ -964,21 +1198,28 @@ _bfd_elf_link_hash_copy_indirect (dir, ind) | ELF_LINK_HASH_REF_REGULAR_NONWEAK | ELF_LINK_NON_GOT_REF)); - /* Copy over the global and procedure linkage table offset entries. + if (dir == ind->weakdef) + return; + + /* Copy over the global and procedure linkage table refcount entries. These may have been already set up by a check_relocs routine. */ - if (dir->got.offset == (bfd_vma) -1) + tmp = dir->got.refcount; + if (tmp <= 0) { - dir->got.offset = ind->got.offset; - ind->got.offset = (bfd_vma) -1; + dir->got.refcount = ind->got.refcount; + ind->got.refcount = tmp; } - BFD_ASSERT (ind->got.offset == (bfd_vma) -1); + else + BFD_ASSERT (ind->got.refcount <= 0); - if (dir->plt.offset == (bfd_vma) -1) + tmp = dir->plt.refcount; + if (tmp <= 0) { - dir->plt.offset = ind->plt.offset; - ind->plt.offset = (bfd_vma) -1; + dir->plt.refcount = ind->plt.refcount; + ind->plt.refcount = tmp; } - BFD_ASSERT (ind->plt.offset == (bfd_vma) -1); + else + BFD_ASSERT (ind->plt.refcount <= 0); if (dir->dynindx == -1) { @@ -987,7 +1228,8 @@ _bfd_elf_link_hash_copy_indirect (dir, ind) ind->dynindx = -1; ind->dynstr_index = 0; } - BFD_ASSERT (ind->dynindx == -1); + else + BFD_ASSERT (ind->dynindx == -1); } void @@ -996,8 +1238,9 @@ _bfd_elf_link_hash_hide_symbol (info, h) struct elf_link_hash_entry *h; { h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; - h->dynindx = -1; h->plt.offset = (bfd_vma) -1; + if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) + h->dynindx = -1; } /* Initialize an ELF linker hash table. */ @@ -1010,8 +1253,11 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc) struct bfd_hash_table *, const char *)); { + boolean ret; + table->dynamic_sections_created = false; table->dynobj = NULL; + table->init_refcount = get_elf_backend_data (abfd)->can_refcount - 1; /* The first dynamic symbol is a dummy. */ table->dynsymcount = 1; table->dynstr = NULL; @@ -1020,8 +1266,12 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc) table->runpath = NULL; table->hgot = NULL; table->stab_info = NULL; + table->merge_info = NULL; table->dynlocal = NULL; - return _bfd_link_hash_table_init (&table->root, abfd, newfunc); + ret = _bfd_link_hash_table_init (& table->root, abfd, newfunc); + table->root.type = bfd_link_elf_hash_table; + + return ret; } /* Create an ELF linker hash table. */ @@ -1031,9 +1281,9 @@ _bfd_elf_link_hash_table_create (abfd) bfd *abfd; { struct elf_link_hash_table *ret; + bfd_size_type amt = sizeof (struct elf_link_hash_table); - ret = ((struct elf_link_hash_table *) - bfd_alloc (abfd, sizeof (struct elf_link_hash_table))); + ret = (struct elf_link_hash_table *) bfd_alloc (abfd, amt); if (ret == (struct elf_link_hash_table *) NULL) return NULL; @@ -1122,7 +1372,7 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded) asection *s; bfd_byte *dynbuf = NULL; int elfsec; - unsigned long link; + unsigned long shlink; bfd_byte *extdyn, *extdynend; size_t extdynsize; void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *)); @@ -1149,7 +1399,7 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded) if (elfsec == -1) goto error_return; - link = elf_elfsections (abfd)[elfsec]->sh_link; + shlink = elf_elfsections (abfd)[elfsec]->sh_link; extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn; swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in; @@ -1169,13 +1419,15 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded) { const char *string; struct bfd_link_needed_list *l; + unsigned int tagv = dyn.d_un.d_val; + bfd_size_type amt; - string = bfd_elf_string_from_elf_section (abfd, link, - dyn.d_un.d_val); + string = bfd_elf_string_from_elf_section (abfd, shlink, tagv); if (string == NULL) goto error_return; - l = (struct bfd_link_needed_list *) bfd_alloc (abfd, sizeof *l); + amt = sizeof *l; + l = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt); if (l == NULL) goto error_return; @@ -1351,7 +1603,7 @@ bfd_section_from_shdr (abfd, shindex) { ((*_bfd_error_handler) (_("%s: invalid link %lu for reloc section %s (index %u)"), - bfd_get_filename (abfd), hdr->sh_link, name, shindex)); + bfd_archive_filename (abfd), hdr->sh_link, name, shindex)); return _bfd_elf_make_section_from_shdr (abfd, hdr, name); } @@ -1411,13 +1663,15 @@ bfd_section_from_shdr (abfd, shindex) hdr2 = &elf_section_data (target_sect)->rel_hdr; else { + bfd_size_type amt; BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL); - hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2)); + amt = sizeof (*hdr2); + hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); elf_section_data (target_sect)->rel_hdr2 = hdr2; } *hdr2 = *hdr; elf_elfsections (abfd)[shindex] = hdr2; - target_sect->reloc_count += hdr->sh_size / hdr->sh_entsize; + target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr); target_sect->flags |= SEC_RELOC; target_sect->relocation = NULL; target_sect->rel_filepos = hdr->sh_offset; @@ -1452,6 +1706,26 @@ bfd_section_from_shdr (abfd, shindex) case SHT_SHLIB: return true; + case SHT_GROUP: + /* Make a section for objcopy and relocatable links. */ + if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name)) + return false; + if (hdr->contents != NULL) + { + Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents; + unsigned int n_elt = hdr->sh_size / 4; + asection *s; + + while (--n_elt != 0) + if ((s = (++idx)->shdr->bfd_section) != NULL + && elf_section_data (s)->next_in_group != NULL) + { + hdr->bfd_section->lineno = (alent *) s; + break; + } + } + break; + default: /* Check for any processor-specific section types. */ { @@ -1484,8 +1758,9 @@ _bfd_elf_new_section_hook (abfd, sec) asection *sec; { struct bfd_elf_section_data *sdata; + bfd_size_type amt = sizeof (*sdata); - sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, sizeof (*sdata)); + sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, amt); if (!sdata) return false; sec->used_by_bfd = (PTR) sdata; @@ -1535,7 +1810,7 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename) && (hdr->p_filesz > 0) && (hdr->p_memsz > hdr->p_filesz)); sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : ""); - name = bfd_alloc (abfd, strlen (namebuf) + 1); + name = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1); if (!name) return false; strcpy (name, namebuf); @@ -1566,7 +1841,7 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename) if (split) { sprintf (namebuf, "%s%db", typename, index); - name = bfd_alloc (abfd, strlen (namebuf) + 1); + name = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1); if (!name) return false; strcpy (name, namebuf); @@ -1614,7 +1889,7 @@ bfd_section_from_phdr (abfd, hdr, index) case PT_NOTE: if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note")) return false; - if (! elfcore_read_notes (abfd, hdr->p_offset, hdr->p_filesz)) + if (! elfcore_read_notes (abfd, (file_ptr) hdr->p_offset, hdr->p_filesz)) return false; return true; @@ -1647,10 +1922,10 @@ _bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p) boolean use_rela_p; { char *name; - struct elf_backend_data *bed; + struct elf_backend_data *bed = get_elf_backend_data (abfd); + bfd_size_type amt = sizeof ".rela" + strlen (asect->name); - bed = get_elf_backend_data (abfd); - name = bfd_alloc (abfd, sizeof ".rela" + strlen (asect->name)); + name = bfd_alloc (abfd, amt); if (name == NULL) return false; sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name); @@ -1786,6 +2061,11 @@ elf_fake_sections (abfd, asect, failedptrarg) BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0 || this_hdr->sh_info == elf_tdata (abfd)->cverrefs); } + else if ((asect->flags & SEC_GROUP) != 0) + { + this_hdr->sh_type = SHT_GROUP; + this_hdr->sh_entsize = 4; + } else if ((asect->flags & SEC_ALLOC) != 0 && ((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)) this_hdr->sh_type = SHT_NOBITS; @@ -1798,6 +2078,15 @@ elf_fake_sections (abfd, asect, failedptrarg) this_hdr->sh_flags |= SHF_WRITE; if ((asect->flags & SEC_CODE) != 0) this_hdr->sh_flags |= SHF_EXECINSTR; + if ((asect->flags & SEC_MERGE) != 0) + { + this_hdr->sh_flags |= SHF_MERGE; + this_hdr->sh_entsize = asect->entsize; + if ((asect->flags & SEC_STRINGS) != 0) + this_hdr->sh_flags |= SHF_STRINGS; + } + if (elf_section_data (asect)->group != NULL) + this_hdr->sh_flags |= SHF_GROUP; /* Check for processor-specific section types. */ if (bed->elf_backend_fake_sections) @@ -1815,6 +2104,82 @@ elf_fake_sections (abfd, asect, failedptrarg) *failedptr = true; } +/* Fill in the contents of a SHT_GROUP section. */ + +static void +set_group_contents (abfd, sec, failedptrarg) + bfd *abfd; + asection *sec; + PTR failedptrarg ATTRIBUTE_UNUSED; +{ + boolean *failedptr = (boolean *) failedptrarg; + unsigned long symindx; + asection *elt; + unsigned char *loc; + struct bfd_link_order *l; + + if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP + || *failedptr) + return; + + /* If called from the assembler, swap_out_syms will have set up + udata.i; If called for "ld -r", the symbols won't yet be mapped, + so emulate elf_bfd_final_link. */ + symindx = sec->symbol->udata.i; + if (symindx == 0) + symindx = elf_section_data (sec)->this_idx; + elf_section_data (sec)->this_hdr.sh_info = symindx; + + /* Nor will the contents be allocated for "ld -r". */ + if (sec->contents == NULL) + { + sec->contents = bfd_alloc (abfd, sec->_raw_size); + if (sec->contents == NULL) + { + *failedptr = true; + return; + } + } + + loc = sec->contents + sec->_raw_size; + + /* Get the pointer to the first section in the group that we + squirreled away here. */ + elt = (asection *) sec->lineno; + + /* First element is a flag word. Rest of section is elf section + indices for all the sections of the group. Write them backwards + just to keep the group in the same order as given in .section + directives, not that it matters. */ + while (elt != NULL) + { + loc -= 4; + H_PUT_32 (abfd, elf_section_data (elt)->this_idx, loc); + elt = elf_section_data (elt)->next_in_group; + } + + /* If this is a relocatable link, then the above did nothing because + SEC is the output section. Look through the input sections + instead. */ + for (l = sec->link_order_head; l != NULL; l = l->next) + if (l->type == bfd_indirect_link_order + && (elt = (asection *) l->u.indirect.section->lineno) != NULL) + do + { + loc -= 4; + H_PUT_32 (abfd, + elf_section_data (elt->output_section)->this_idx, loc); + elt = elf_section_data (elt)->next_in_group; + /* During a relocatable link, the lists are circular. */ + } + while (elt != (asection *) l->u.indirect.section->lineno); + + loc -= 4; + H_PUT_32 (abfd, 0, loc); + + BFD_ASSERT (loc == sec->contents); +} + /* Assign all ELF section numbers. The dummy first section is handled here too. The link/info pointers for the standard section types are filled in here too, while we're at it. */ @@ -1827,6 +2192,7 @@ assign_section_numbers (abfd) asection *sec; unsigned int section_number; Elf_Internal_Shdr **i_shdrp; + bfd_size_type amt; section_number = 1; @@ -1860,13 +2226,13 @@ assign_section_numbers (abfd) /* Set up the list of section header pointers, in agreement with the indices. */ - i_shdrp = ((Elf_Internal_Shdr **) - bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *))); + amt = section_number * sizeof (Elf_Internal_Shdr *); + i_shdrp = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt); if (i_shdrp == NULL) return false; - i_shdrp[0] = ((Elf_Internal_Shdr *) - bfd_alloc (abfd, sizeof (Elf_Internal_Shdr))); + amt = sizeof (Elf_Internal_Shdr); + i_shdrp[0] = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); if (i_shdrp[0] == NULL) { bfd_release (abfd, i_shdrp); @@ -1948,7 +2314,7 @@ assign_section_numbers (abfd) char *alc; len = strlen (sec->name); - alc = (char *) bfd_malloc (len - 2); + alc = (char *) bfd_malloc ((bfd_size_type) len - 2); if (alc == NULL) return false; strncpy (alc, sec->name, len - 3); @@ -1986,6 +2352,9 @@ assign_section_numbers (abfd) if (s != NULL) d->this_hdr.sh_link = elf_section_data (s)->this_idx; break; + + case SHT_GROUP: + d->this_hdr.sh_link = t->symtab_section; } } @@ -2014,19 +2383,19 @@ static boolean elf_map_symbols (abfd) bfd *abfd; { - int symcount = bfd_get_symcount (abfd); + unsigned int symcount = bfd_get_symcount (abfd); asymbol **syms = bfd_get_outsymbols (abfd); asymbol **sect_syms; - int num_locals = 0; - int num_globals = 0; - int num_locals2 = 0; - int num_globals2 = 0; + unsigned int num_locals = 0; + unsigned int num_globals = 0; + unsigned int num_locals2 = 0; + unsigned int num_globals2 = 0; int max_index = 0; - int num_sections = 0; - int idx; + unsigned int num_sections = 0; + unsigned int idx; asection *asect; asymbol **new_syms; - asymbol *sym; + bfd_size_type amt; #ifdef DEBUG fprintf (stderr, "elf_map_symbols\n"); @@ -2042,14 +2411,16 @@ elf_map_symbols (abfd) } max_index++; - sect_syms = (asymbol **) bfd_zalloc (abfd, max_index * sizeof (asymbol *)); + amt = max_index * sizeof (asymbol *); + sect_syms = (asymbol **) bfd_zalloc (abfd, amt); if (sect_syms == NULL) return false; elf_section_syms (abfd) = sect_syms; + elf_num_section_syms (abfd) = max_index; for (idx = 0; idx < symcount; idx++) { - sym = syms[idx]; + asymbol *sym = syms[idx]; if ((sym->flags & BSF_SECTION_SYM) != 0 && sym->value == 0) @@ -2088,6 +2459,8 @@ elf_map_symbols (abfd) for (asect = abfd->sections; asect; asect = asect->next) { + asymbol *sym; + if (sect_syms[asect->index] != NULL) continue; @@ -2132,16 +2505,16 @@ elf_map_symbols (abfd) } /* Now sort the symbols so the local symbols are first. */ - new_syms = ((asymbol **) - bfd_alloc (abfd, - (num_locals + num_globals) * sizeof (asymbol *))); + amt = (num_locals + num_globals) * sizeof (asymbol *); + new_syms = (asymbol **) bfd_alloc (abfd, amt); + if (new_syms == NULL) return false; for (idx = 0; idx < symcount; idx++) { asymbol *sym = syms[idx]; - int i; + unsigned int i; if (!sym_is_global (abfd, sym)) i = num_locals2++; @@ -2156,7 +2529,7 @@ elf_map_symbols (abfd) && sect_syms[asect->index]->flags == 0) { asymbol *sym = sect_syms[asect->index]; - int i; + unsigned int i; sym->flags = BSF_SECTION_SYM; if (!sym_is_global (abfd, sym)) @@ -2258,6 +2631,13 @@ _bfd_elf_compute_section_file_positions (abfd, link_info) return false; } + if (link_info == NULL || link_info->relocateable) + { + bfd_map_over_sections (abfd, set_group_contents, &failed); + if (failed) + return false; + } + shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr; /* sh_name was set in prep_headers. */ shstrtab_hdr->sh_type = SHT_STRTAB; @@ -2314,11 +2694,11 @@ make_mapping (abfd, sections, from, to, phdr) struct elf_segment_map *m; unsigned int i; asection **hdrpp; + bfd_size_type amt; - m = ((struct elf_segment_map *) - bfd_zalloc (abfd, - (sizeof (struct elf_segment_map) - + (to - from - 1) * sizeof (asection *)))); + amt = sizeof (struct elf_segment_map); + amt += (to - from - 1) * sizeof (asection *); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) return NULL; m->next = NULL; @@ -2357,6 +2737,7 @@ map_sections_to_segments (abfd) boolean phdr_in_segment = true; boolean writable; asection *dynsec; + bfd_size_type amt; if (elf_tdata (abfd)->segment_map != NULL) return true; @@ -2366,8 +2747,8 @@ map_sections_to_segments (abfd) /* Select the allocated sections, and sort them. */ - sections = (asection **) bfd_malloc (bfd_count_sections (abfd) - * sizeof (asection *)); + amt = bfd_count_sections (abfd) * sizeof (asection *); + sections = (asection **) bfd_malloc (amt); if (sections == NULL) goto error_return; @@ -2396,8 +2777,8 @@ map_sections_to_segments (abfd) s = bfd_get_section_by_name (abfd, ".interp"); if (s != NULL && (s->flags & SEC_LOAD) != 0) { - m = ((struct elf_segment_map *) - bfd_zalloc (abfd, sizeof (struct elf_segment_map))); + amt = sizeof (struct elf_segment_map); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -2410,8 +2791,8 @@ map_sections_to_segments (abfd) *pm = m; pm = &m->next; - m = ((struct elf_segment_map *) - bfd_zalloc (abfd, sizeof (struct elf_segment_map))); + amt = sizeof (struct elf_segment_map); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -2558,8 +2939,8 @@ map_sections_to_segments (abfd) /* If there is a .dynamic section, throw in a PT_DYNAMIC segment. */ if (dynsec != NULL) { - m = ((struct elf_segment_map *) - bfd_zalloc (abfd, sizeof (struct elf_segment_map))); + amt = sizeof (struct elf_segment_map); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -2581,8 +2962,8 @@ map_sections_to_segments (abfd) if ((s->flags & SEC_LOAD) != 0 && strncmp (s->name, ".note", 5) == 0) { - m = ((struct elf_segment_map *) - bfd_zalloc (abfd, sizeof (struct elf_segment_map))); + amt = sizeof (struct elf_segment_map); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (m == NULL) goto error_return; m->next = NULL; @@ -2638,18 +3019,22 @@ elf_sort_sections (arg1, arg2) if (TOEND (sec1)) { if (TOEND (sec2)) - return sec1->target_index - sec2->target_index; + { + /* If the indicies are the same, do not return 0 + here, but continue to try the next comparison. */ + if (sec1->target_index - sec2->target_index != 0) + return sec1->target_index - sec2->target_index; + } else return 1; } - - if (TOEND (sec2)) + else if (TOEND (sec2)) return -1; #undef TOEND - /* Sort by size, to put zero sized sections before others at the - same address. */ + /* Sort by size, to put zero sized sections + before others at the same address. */ if (sec1->_raw_size < sec2->_raw_size) return -1; @@ -2676,6 +3061,7 @@ assign_file_positions_for_segments (abfd) bfd_vma filehdr_vaddr, filehdr_paddr; bfd_vma phdrs_vaddr, phdrs_paddr; Elf_Internal_Phdr *p; + bfd_size_type amt; if (elf_tdata (abfd)->segment_map == NULL) { @@ -2716,8 +3102,8 @@ assign_file_positions_for_segments (abfd) if (alloc == 0) alloc = count; - phdrs = ((Elf_Internal_Phdr *) - bfd_alloc (abfd, alloc * sizeof (Elf_Internal_Phdr))); + amt = alloc * sizeof (Elf_Internal_Phdr); + phdrs = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt); if (phdrs == NULL) return false; @@ -3045,7 +3431,7 @@ assign_file_positions_for_segments (abfd) elf_tdata (abfd)->next_file_pos = off; /* Write out the program headers. */ - if (bfd_seek (abfd, bed->s->sizeof_ehdr, SEEK_SET) != 0 + if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0 || bed->s->write_out_phdrs (abfd, phdrs, alloc) != 0) return false; @@ -3290,101 +3676,22 @@ prep_headers (abfd) case bfd_arch_unknown: i_ehdrp->e_machine = EM_NONE; break; - case bfd_arch_sparc: - if (bfd_get_arch_size (abfd) == 64) - i_ehdrp->e_machine = EM_SPARCV9; - else - i_ehdrp->e_machine = EM_SPARC; - break; - case bfd_arch_i370: - i_ehdrp->e_machine = EM_S370; - break; - case bfd_arch_i386: - i_ehdrp->e_machine = EM_386; - break; - case bfd_arch_ia64: - i_ehdrp->e_machine = EM_IA_64; - break; - case bfd_arch_m68hc11: - i_ehdrp->e_machine = EM_68HC11; - break; - case bfd_arch_m68hc12: - i_ehdrp->e_machine = EM_68HC12; - break; - case bfd_arch_m68k: - i_ehdrp->e_machine = EM_68K; - break; - case bfd_arch_m88k: - i_ehdrp->e_machine = EM_88K; - break; - case bfd_arch_i860: - i_ehdrp->e_machine = EM_860; - break; - case bfd_arch_i960: - i_ehdrp->e_machine = EM_960; - break; - case bfd_arch_mips: /* MIPS Rxxxx */ - i_ehdrp->e_machine = EM_MIPS; /* only MIPS R3000 */ - break; - case bfd_arch_hppa: - i_ehdrp->e_machine = EM_PARISC; - break; - case bfd_arch_powerpc: - i_ehdrp->e_machine = EM_PPC; - break; - case bfd_arch_alpha: - i_ehdrp->e_machine = EM_ALPHA; - break; - case bfd_arch_sh: - i_ehdrp->e_machine = EM_SH; - break; - case bfd_arch_d10v: - i_ehdrp->e_machine = EM_CYGNUS_D10V; - break; - case bfd_arch_d30v: - i_ehdrp->e_machine = EM_CYGNUS_D30V; - break; - case bfd_arch_fr30: - i_ehdrp->e_machine = EM_CYGNUS_FR30; - break; - case bfd_arch_mcore: - i_ehdrp->e_machine = EM_MCORE; - break; - case bfd_arch_avr: - i_ehdrp->e_machine = EM_AVR; - break; - case bfd_arch_v850: - switch (bfd_get_mach (abfd)) - { - default: - case 0: i_ehdrp->e_machine = EM_CYGNUS_V850; break; - } - break; - case bfd_arch_arc: - i_ehdrp->e_machine = EM_CYGNUS_ARC; - break; - case bfd_arch_arm: - i_ehdrp->e_machine = EM_ARM; - break; - case bfd_arch_m32r: - i_ehdrp->e_machine = EM_CYGNUS_M32R; - break; - case bfd_arch_mn10200: - i_ehdrp->e_machine = EM_CYGNUS_MN10200; - break; - case bfd_arch_mn10300: - i_ehdrp->e_machine = EM_CYGNUS_MN10300; - break; - case bfd_arch_pj: - i_ehdrp->e_machine = EM_PJ; - break; - case bfd_arch_cris: - i_ehdrp->e_machine = EM_CRIS; - break; - /* also note that EM_M32, AT&T WE32100 is unknown to bfd */ + + /* There used to be a long list of cases here, each one setting + e_machine to the same EM_* macro #defined as ELF_MACHINE_CODE + in the corresponding bfd definition. To avoid duplication, + the switch was removed. Machines that need special handling + can generally do it in elf_backend_final_write_processing(), + unless they need the information earlier than the final write. + Such need can generally be supplied by replacing the tests for + e_machine with the conditions used to determine it. */ default: - i_ehdrp->e_machine = EM_NONE; - } + if (get_elf_backend_data (abfd) != NULL) + i_ehdrp->e_machine = get_elf_backend_data (abfd)->elf_machine_code; + else + i_ehdrp->e_machine = EM_NONE; + } + i_ehdrp->e_version = bed->s->ev_current; i_ehdrp->e_ehsize = bed->s->sizeof_ehdr; @@ -3492,10 +3799,10 @@ _bfd_elf_write_object_contents (abfd) (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]); if (i_shdrp[count]->contents) { + bfd_size_type amt = i_shdrp[count]->sh_size; + if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0 - || (bfd_write (i_shdrp[count]->contents, i_shdrp[count]->sh_size, - 1, abfd) - != i_shdrp[count]->sh_size)) + || bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt) return false; } } @@ -3593,7 +3900,8 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr) indx = asym_ptr->section->output_section->index; else indx = asym_ptr->section->index; - if (elf_section_syms (abfd)[indx]) + if (indx < elf_num_section_syms (abfd) + && elf_section_syms (abfd)[indx] != NULL) asym_ptr->udata.i = elf_section_syms (abfd)[indx]->udata.i; } @@ -3605,7 +3913,7 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr) which is used in a relocation entry. */ (*_bfd_error_handler) (_("%s: symbol `%s' required but not present"), - bfd_get_filename (abfd), bfd_asymbol_name (asym_ptr)); + bfd_archive_filename (abfd), bfd_asymbol_name (asym_ptr)); bfd_set_error (bfd_error_no_symbols); return -1; } @@ -3800,6 +4108,7 @@ copy_private_bfd_data (ibfd, obfd) bfd_vma matching_lma; bfd_vma suggested_lma; unsigned int j; + bfd_size_type amt; if (segment->p_type == PT_NULL) continue; @@ -3812,10 +4121,9 @@ copy_private_bfd_data (ibfd, obfd) /* Allocate a segment map big enough to contain all of the sections we have selected. */ - map = ((struct elf_segment_map *) - bfd_alloc (obfd, - (sizeof (struct elf_segment_map) - + ((size_t) section_count - 1) * sizeof (asection *)))); + amt = sizeof (struct elf_segment_map); + amt += ((bfd_size_type) section_count - 1) * sizeof (asection *); + map = (struct elf_segment_map *) bfd_alloc (obfd, amt); if (map == NULL) return false; @@ -3855,7 +4163,7 @@ copy_private_bfd_data (ibfd, obfd) if (segment->p_type == PT_LOAD) _bfd_error_handler (_("%s: warning: Empty loadable segment detected\n"), - bfd_get_filename (ibfd)); + bfd_archive_filename (ibfd)); map->count = 0; *pointer_to_map = map; @@ -3892,8 +4200,8 @@ copy_private_bfd_data (ibfd, obfd) pointers that we are interested in. As these sections get assigned to a segment, they are removed from this array. */ - sections = (asection **) bfd_malloc - (sizeof (asection *) * section_count); + amt = (bfd_size_type) section_count * sizeof (asection *); + sections = (asection **) bfd_malloc (amt); if (sections == NULL) return false; @@ -4085,11 +4393,9 @@ copy_private_bfd_data (ibfd, obfd) /* We still have not allocated all of the sections to segments. Create a new segment here, initialise it and carry on looping. */ - map = ((struct elf_segment_map *) - bfd_alloc (obfd, - (sizeof (struct elf_segment_map) - + ((size_t) section_count - 1) - * sizeof (asection *)))); + amt = sizeof (struct elf_segment_map); + amt += ((bfd_size_type) section_count - 1) * sizeof (asection *); + map = (struct elf_segment_map *) bfd_alloc (obfd, amt); if (map == NULL) return false; @@ -4304,6 +4610,7 @@ swap_out_syms (abfd, sttp, relocatable_p) Elf_Internal_Shdr *symstrtab_hdr; char *outbound_syms; int idx; + bfd_size_type amt; stt = _bfd_elf_stringtab_init (); if (stt == NULL) @@ -4319,8 +4626,8 @@ swap_out_syms (abfd, sttp, relocatable_p) symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; symstrtab_hdr->sh_type = SHT_STRTAB; - outbound_syms = bfd_alloc (abfd, - (1 + symcount) * bed->s->sizeof_sym); + amt = (bfd_size_type) (1 + symcount) * bed->s->sizeof_sym; + outbound_syms = bfd_alloc (abfd, amt); if (outbound_syms == NULL) return false; symtab_hdr->contents = (PTR) outbound_syms; @@ -4346,9 +4653,11 @@ swap_out_syms (abfd, sttp, relocatable_p) flagword flags = syms[idx]->flags; int type; - if (flags & BSF_SECTION_SYM) - /* Section symbols have no names. */ - sym.st_name = 0; + if ((flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM) + { + /* Local section symbols have no name. */ + sym.st_name = 0; + } else { sym.st_name = (unsigned long) _bfd_stringtab_add (stt, @@ -4455,7 +4764,12 @@ swap_out_syms (abfd, sttp, relocatable_p) type = (*bed->elf_backend_get_symbol_type) (&type_ptr->internal_elf_sym, type); if (flags & BSF_SECTION_SYM) - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); + { + if (flags & BSF_GLOBAL) + sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION); + else + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); + } else if (bfd_is_com_section (syms[idx]->section)) sym.st_info = ELF_ST_INFO (STB_GLOBAL, type); else if (bfd_is_und_section (syms[idx]->section)) @@ -4562,11 +4876,9 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols) { arelent *tblptr; unsigned int i; + struct elf_backend_data *bed = get_elf_backend_data (abfd); - if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd, - section, - symbols, - false)) + if (! bed->s->slurp_reloc_table (abfd, section, symbols, false)) return -1; tblptr = section->relocation; @@ -4583,8 +4895,8 @@ _bfd_elf_get_symtab (abfd, alocation) bfd *abfd; asymbol **alocation; { - long symcount = get_elf_backend_data (abfd)->s->slurp_symbol_table - (abfd, alocation, false); + struct elf_backend_data *bed = get_elf_backend_data (abfd); + long symcount = bed->s->slurp_symbol_table (abfd, alocation, false); if (symcount >= 0) bfd_get_symcount (abfd) = symcount; @@ -4596,8 +4908,8 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation) bfd *abfd; asymbol **alocation; { - return get_elf_backend_data (abfd)->s->slurp_symbol_table - (abfd, alocation, true); + struct elf_backend_data *bed = get_elf_backend_data (abfd); + return bed->s->slurp_symbol_table (abfd, alocation, true); } /* Return the size required for the dynamic reloc entries. Any @@ -4687,6 +4999,7 @@ _bfd_elf_slurp_version_tables (abfd) bfd *abfd; { bfd_byte *contents = NULL; + bfd_size_type amt; if (elf_dynverdef (abfd) != 0) { @@ -4704,7 +5017,7 @@ _bfd_elf_slurp_version_tables (abfd) if (contents == NULL) goto error_return; if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 - || bfd_read ((PTR) contents, 1, hdr->sh_size, abfd) != hdr->sh_size) + || bfd_bread ((PTR) contents, hdr->sh_size, abfd) != hdr->sh_size) goto error_return; /* We know the number of entries in the section but not the maximum @@ -4716,16 +5029,15 @@ _bfd_elf_slurp_version_tables (abfd) { _bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem); - if ((iverdefmem.vd_ndx & VERSYM_VERSION) > maxidx) - maxidx = iverdefmem.vd_ndx & VERSYM_VERSION; + if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx) + maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION); everdef = ((Elf_External_Verdef *) ((bfd_byte *) everdef + iverdefmem.vd_next)); } - elf_tdata (abfd)->verdef = - ((Elf_Internal_Verdef *) - bfd_zalloc (abfd, maxidx * sizeof (Elf_Internal_Verdef))); + amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef); + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc (abfd, amt); if (elf_tdata (abfd)->verdef == NULL) goto error_return; @@ -4746,10 +5058,8 @@ _bfd_elf_slurp_version_tables (abfd) iverdef->vd_bfd = abfd; - iverdef->vd_auxptr = ((Elf_Internal_Verdaux *) - bfd_alloc (abfd, - (iverdef->vd_cnt - * sizeof (Elf_Internal_Verdaux)))); + amt = (bfd_size_type) iverdef->vd_cnt * sizeof (Elf_Internal_Verdaux); + iverdef->vd_auxptr = (Elf_Internal_Verdaux *) bfd_alloc (abfd, amt); if (iverdef->vd_auxptr == NULL) goto error_return; @@ -4799,9 +5109,9 @@ _bfd_elf_slurp_version_tables (abfd) hdr = &elf_tdata (abfd)->dynverref_hdr; + amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed); elf_tdata (abfd)->verref = - ((Elf_Internal_Verneed *) - bfd_zalloc (abfd, hdr->sh_info * sizeof (Elf_Internal_Verneed))); + (Elf_Internal_Verneed *) bfd_zalloc (abfd, amt); if (elf_tdata (abfd)->verref == NULL) goto error_return; @@ -4811,7 +5121,7 @@ _bfd_elf_slurp_version_tables (abfd) if (contents == NULL) goto error_return; if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0 - || bfd_read ((PTR) contents, 1, hdr->sh_size, abfd) != hdr->sh_size) + || bfd_bread ((PTR) contents, hdr->sh_size, abfd) != hdr->sh_size) goto error_return; everneed = (Elf_External_Verneed *) contents; @@ -4832,10 +5142,9 @@ _bfd_elf_slurp_version_tables (abfd) if (iverneed->vn_filename == NULL) goto error_return; - iverneed->vn_auxptr = - ((Elf_Internal_Vernaux *) - bfd_alloc (abfd, - iverneed->vn_cnt * sizeof (Elf_Internal_Vernaux))); + amt = iverneed->vn_cnt; + amt *= sizeof (Elf_Internal_Vernaux); + iverneed->vn_auxptr = (Elf_Internal_Vernaux *) bfd_alloc (abfd, amt); evernaux = ((Elf_External_Vernaux *) ((bfd_byte *) everneed + iverneed->vn_aux)); @@ -4885,8 +5194,9 @@ _bfd_elf_make_empty_symbol (abfd) bfd *abfd; { elf_symbol_type *newsym; + bfd_size_type amt = sizeof (elf_symbol_type); - newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (elf_symbol_type)); + newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt); if (!newsym) return NULL; else @@ -4960,52 +5270,24 @@ _bfd_elf_set_arch_mach (abfd, arch, machine) return bfd_default_set_arch_mach (abfd, arch, machine); } -/* Find the nearest line to a particular section and offset, for error - reporting. */ +/* Find the function to a particular section and offset, + for error reporting. */ -boolean -_bfd_elf_find_nearest_line (abfd, - section, - symbols, - offset, - filename_ptr, - functionname_ptr, - line_ptr) - bfd *abfd; +static boolean +elf_find_function (abfd, section, symbols, offset, + filename_ptr, functionname_ptr) + bfd *abfd ATTRIBUTE_UNUSED; asection *section; asymbol **symbols; bfd_vma offset; - CONST char **filename_ptr; - CONST char **functionname_ptr; - unsigned int *line_ptr; + const char **filename_ptr; + const char **functionname_ptr; { - boolean found; const char *filename; asymbol *func; bfd_vma low_func; asymbol **p; - if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, - filename_ptr, functionname_ptr, - line_ptr)) - return true; - - if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, - filename_ptr, functionname_ptr, - line_ptr, 0)) - return true; - - if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, - &found, filename_ptr, - functionname_ptr, line_ptr, - &elf_tdata (abfd)->line_info)) - return false; - if (found) - return true; - - if (symbols == NULL) - return false; - filename = NULL; func = NULL; low_func = 0; @@ -5042,8 +5324,70 @@ _bfd_elf_find_nearest_line (abfd, if (func == NULL) return false; - *filename_ptr = filename; - *functionname_ptr = bfd_asymbol_name (func); + if (filename_ptr) + *filename_ptr = filename; + if (functionname_ptr) + *functionname_ptr = bfd_asymbol_name (func); + + return true; +} + +/* Find the nearest line to a particular section and offset, + for error reporting. */ + +boolean +_bfd_elf_find_nearest_line (abfd, section, symbols, offset, + filename_ptr, functionname_ptr, line_ptr) + bfd *abfd; + asection *section; + asymbol **symbols; + bfd_vma offset; + const char **filename_ptr; + const char **functionname_ptr; + unsigned int *line_ptr; +{ + boolean found; + + if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset, + filename_ptr, functionname_ptr, + line_ptr)) + { + if (!*functionname_ptr) + elf_find_function (abfd, section, symbols, offset, + *filename_ptr ? NULL : filename_ptr, + functionname_ptr); + + return true; + } + + if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, + filename_ptr, functionname_ptr, + line_ptr, 0, + &elf_tdata (abfd)->dwarf2_find_line_info)) + { + if (!*functionname_ptr) + elf_find_function (abfd, section, symbols, offset, + *filename_ptr ? NULL : filename_ptr, + functionname_ptr); + + return true; + } + + if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, + &found, filename_ptr, + functionname_ptr, line_ptr, + &elf_tdata (abfd)->line_info)) + return false; + if (found) + return true; + + if (symbols == NULL) + return false; + + if (! elf_find_function (abfd, section, symbols, offset, + filename_ptr, functionname_ptr)) + return false; + *line_ptr = 0; return true; } @@ -5070,6 +5414,7 @@ _bfd_elf_set_section_contents (abfd, section, location, offset, count) bfd_size_type count; { Elf_Internal_Shdr *hdr; + bfd_signed_vma pos; if (! abfd->output_has_begun && ! _bfd_elf_compute_section_file_positions @@ -5077,10 +5422,9 @@ _bfd_elf_set_section_contents (abfd, section, location, offset, count) return false; hdr = &elf_section_data (section)->this_hdr; - - if (bfd_seek (abfd, hdr->sh_offset + offset, SEEK_SET) == -1) - return false; - if (bfd_write (location, 1, count, abfd) != count) + pos = hdr->sh_offset + offset; + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bwrite (location, count, abfd) != count) return false; return true; @@ -5199,7 +5543,7 @@ _bfd_elf_validate_reloc (abfd, areloc) fail: (*_bfd_error_handler) (_("%s: unsupported relocation type %s"), - bfd_get_filename (abfd), areloc->howto->name); + bfd_archive_filename (abfd), areloc->howto->name); bfd_set_error (bfd_error_bad_value); return false; } @@ -5244,12 +5588,6 @@ _bfd_elf_rel_vtable_reloc_fn (abfd, re, symbol, data, is, obfd, errmsg) # include #endif -/* Define offsetof for those systems which lack it. */ - -#ifndef offsetof -# define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) -#endif - /* FIXME: this is kinda wrong, but it's what gdb wants. */ static int @@ -5287,6 +5625,43 @@ elfcore_maybe_make_sect (abfd, name, sect) return true; } +/* Create a pseudosection containing SIZE bytes at FILEPOS. This + actually creates up to two pseudosections: + - For the single-threaded case, a section named NAME, unless + such a section already exists. + - For the multi-threaded case, a section named "NAME/PID", where + PID is elfcore_make_pid (abfd). + Both pseudosections have identical contents. */ +boolean +_bfd_elfcore_make_pseudosection (abfd, name, size, filepos) + bfd *abfd; + char *name; + size_t size; + ufile_ptr filepos; +{ + char buf[100]; + char *threaded_name; + asection *sect; + + /* Build the section name. */ + + sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd)); + threaded_name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1); + if (threaded_name == NULL) + return false; + strcpy (threaded_name, buf); + + sect = bfd_make_section (abfd, threaded_name); + if (sect == NULL) + return false; + sect->_raw_size = size; + sect->filepos = filepos; + sect->flags = SEC_HAS_CONTENTS; + sect->alignment_power = 2; + + return elfcore_maybe_make_sect (abfd, name, sect); +} + /* prstatus_t exists on: solaris 2.5+ linux 2.[01] + glibc @@ -5294,15 +5669,14 @@ elfcore_maybe_make_sect (abfd, name, sect) */ #if defined (HAVE_PRSTATUS_T) +static boolean elfcore_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *)); + static boolean elfcore_grok_prstatus (abfd, note) bfd *abfd; Elf_Internal_Note *note; { - char buf[100]; - char *name; - asection *sect; - int raw_size; + size_t raw_size; int offset; if (note->descsz == sizeof (prstatus_t)) @@ -5357,69 +5731,21 @@ elfcore_grok_prstatus (abfd, note) return true; } - /* Make a ".reg/999" section. */ - - sprintf (buf, ".reg/%d", elfcore_make_pid (abfd)); - name = bfd_alloc (abfd, strlen (buf) + 1); - if (name == NULL) - return false; - strcpy (name, buf); - - sect = bfd_make_section (abfd, name); - if (sect == NULL) - return false; - - sect->_raw_size = raw_size; - sect->filepos = note->descpos + offset; - - sect->flags = SEC_HAS_CONTENTS; - sect->alignment_power = 2; - - if (! elfcore_maybe_make_sect (abfd, ".reg", sect)) - return false; - - return true; + /* Make a ".reg/999" section and a ".reg" section. */ + return _bfd_elfcore_make_pseudosection (abfd, ".reg", + raw_size, note->descpos + offset); } #endif /* defined (HAVE_PRSTATUS_T) */ -/* Create a pseudosection containing the exact contents of NOTE. This - actually creates up to two pseudosections: - - For the single-threaded case, a section named NAME, unless - such a section already exists. - - For the multi-threaded case, a section named "NAME/PID", where - PID is elfcore_make_pid (abfd). - Both pseudosections have identical contents: the contents of NOTE. */ - +/* Create a pseudosection containing the exact contents of NOTE. */ static boolean elfcore_make_note_pseudosection (abfd, name, note) bfd *abfd; char *name; Elf_Internal_Note *note; { - char buf[100]; - char *threaded_name; - asection *sect; - - /* Build the section name. */ - - sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd)); - threaded_name = bfd_alloc (abfd, strlen (buf) + 1); - if (threaded_name == NULL) - return false; - strcpy (threaded_name, buf); - - sect = bfd_make_section (abfd, threaded_name); - if (sect == NULL) - return false; - sect->_raw_size = note->descsz; - sect->filepos = note->descpos; - sect->flags = SEC_HAS_CONTENTS; - sect->alignment_power = 2; - - if (! elfcore_maybe_make_sect (abfd, name, sect)) - return false; - - return true; + return _bfd_elfcore_make_pseudosection (abfd, name, + note->descsz, note->descpos); } /* There isn't a consistent prfpregset_t across platforms, @@ -5460,37 +5786,38 @@ typedef psinfo32_t elfcore_psinfo32_t; #endif #endif -#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) - /* return a malloc'ed copy of a string at START which is at most MAX bytes long, possibly without a terminating '\0'. the copy will always have a terminating '\0'. */ -static char* -elfcore_strndup (abfd, start, max) +char * +_bfd_elfcore_strndup (abfd, start, max) bfd *abfd; char *start; - int max; + size_t max; { - char *dup; + char *dups; char *end = memchr (start, '\0', max); - int len; + size_t len; if (end == NULL) len = max; else len = end - start; - dup = bfd_alloc (abfd, len + 1); - if (dup == NULL) + dups = bfd_alloc (abfd, (bfd_size_type) len + 1); + if (dups == NULL) return NULL; - memcpy (dup, start, len); - dup[len] = '\0'; + memcpy (dups, start, len); + dups[len] = '\0'; - return dup; + return dups; } +#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) +static boolean elfcore_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *)); + static boolean elfcore_grok_psinfo (abfd, note) bfd *abfd; @@ -5503,10 +5830,12 @@ elfcore_grok_psinfo (abfd, note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); elf_tdata (abfd)->core_program - = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); + = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, + sizeof (psinfo.pr_fname)); elf_tdata (abfd)->core_command - = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs)); + = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs, + sizeof (psinfo.pr_psargs)); } #if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T) else if (note->descsz == sizeof (elfcore_psinfo32_t)) @@ -5517,10 +5846,12 @@ elfcore_grok_psinfo (abfd, note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); elf_tdata (abfd)->core_program - = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); + = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, + sizeof (psinfo.pr_fname)); elf_tdata (abfd)->core_command - = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs)); + = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs, + sizeof (psinfo.pr_psargs)); } #endif @@ -5610,7 +5941,7 @@ elfcore_grok_lwpstatus (abfd, note) /* Make a ".reg/999" section. */ sprintf (buf, ".reg/%d", elfcore_make_pid (abfd)); - name = bfd_alloc (abfd, strlen (buf) + 1); + name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1); if (name == NULL) return false; strcpy (name, buf); @@ -5639,7 +5970,7 @@ elfcore_grok_lwpstatus (abfd, note) /* Make a ".reg2/999" section */ sprintf (buf, ".reg2/%d", elfcore_make_pid (abfd)); - name = bfd_alloc (abfd, strlen (buf) + 1); + name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1); if (name == NULL) return false; strcpy (name, buf); @@ -5662,10 +5993,7 @@ elfcore_grok_lwpstatus (abfd, note) sect->flags = SEC_HAS_CONTENTS; sect->alignment_power = 2; - if (!elfcore_maybe_make_sect (abfd, ".reg2", sect)) - return false; - - return true; + return elfcore_maybe_make_sect (abfd, ".reg2", sect); } #endif /* defined (HAVE_LWPSTATUS_T) */ @@ -5697,7 +6025,7 @@ elfcore_grok_win32pstatus (abfd, note) /* Make a ".reg/999" section. */ sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid); - name = bfd_alloc (abfd, strlen (buf) + 1); + name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1); if (name == NULL) return false; @@ -5722,7 +6050,7 @@ elfcore_grok_win32pstatus (abfd, note) /* Make a ".module/xxxxxxxx" section. */ sprintf (buf, ".module/%08x", pstatus.data.module_info.base_address); - name = bfd_alloc (abfd, strlen (buf) + 1); + name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1); if (name == NULL) return false; @@ -5752,14 +6080,21 @@ elfcore_grok_note (abfd, note) bfd *abfd; Elf_Internal_Note *note; { + struct elf_backend_data *bed = get_elf_backend_data (abfd); + switch (note->type) { default: return true; -#if defined (HAVE_PRSTATUS_T) case NT_PRSTATUS: + if (bed->elf_backend_grok_prstatus) + if ((*bed->elf_backend_grok_prstatus) (abfd, note)) + return true; +#if defined (HAVE_PRSTATUS_T) return elfcore_grok_prstatus (abfd, note); +#else + return true; #endif #if defined (HAVE_PSTATUS_T) @@ -5787,10 +6122,15 @@ elfcore_grok_note (abfd, note) else return true; -#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) case NT_PRPSINFO: case NT_PSINFO: + if (bed->elf_backend_grok_psinfo) + if ((*bed->elf_backend_grok_psinfo) (abfd, note)) + return true; +#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) return elfcore_grok_psinfo (abfd, note); +#else + return true; #endif } } @@ -5798,8 +6138,8 @@ elfcore_grok_note (abfd, note) static boolean elfcore_read_notes (abfd, offset, size) bfd *abfd; - bfd_vma offset; - bfd_vma size; + file_ptr offset; + bfd_size_type size; { char *buf; char *p; @@ -5807,14 +6147,14 @@ elfcore_read_notes (abfd, offset, size) if (size <= 0) return true; - if (bfd_seek (abfd, offset, SEEK_SET) == -1) + if (bfd_seek (abfd, offset, SEEK_SET) != 0) return false; - buf = bfd_malloc ((size_t) size); + buf = bfd_malloc (size); if (buf == NULL) return false; - if (bfd_read (buf, size, 1, abfd) != size) + if (bfd_bread (buf, size, abfd) != size) { error: free (buf); @@ -5828,12 +6168,12 @@ elfcore_read_notes (abfd, offset, size) Elf_External_Note *xnp = (Elf_External_Note *) p; Elf_Internal_Note in; - in.type = bfd_h_get_32 (abfd, (bfd_byte *) xnp->type); + in.type = H_GET_32 (abfd, xnp->type); - in.namesz = bfd_h_get_32 (abfd, (bfd_byte *) xnp->namesz); + in.namesz = H_GET_32 (abfd, xnp->namesz); in.namedata = xnp->name; - in.descsz = bfd_h_get_32 (abfd, (bfd_byte *) xnp->descsz); + in.descsz = H_GET_32 (abfd, xnp->descsz); in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4); in.descpos = offset + (in.descdata - buf); @@ -5846,21 +6186,6 @@ elfcore_read_notes (abfd, offset, size) free (buf); return true; } - -/* FIXME: This function is now unnecessary. Callers can just call - bfd_section_from_phdr directly. */ - -boolean -_bfd_elfcore_section_from_phdr (abfd, phdr, sec_num) - bfd *abfd; - Elf_Internal_Phdr* phdr; - int sec_num; -{ - if (! bfd_section_from_phdr (abfd, phdr, sec_num)) - return false; - - return true; -} /* Providing external access to the ELF program header table. */ @@ -5878,8 +6203,7 @@ bfd_get_elf_phdr_upper_bound (abfd) return -1; } - return (elf_elfheader (abfd)->e_phnum - * sizeof (Elf_Internal_Phdr)); + return elf_elfheader (abfd)->e_phnum * sizeof (Elf_Internal_Phdr); } /* Copy ABFD's program header table entries to *PHDRS. The entries @@ -5909,3 +6233,73 @@ bfd_get_elf_phdrs (abfd, phdrs) return num_phdrs; } + +void +_bfd_elf_sprintf_vma (abfd, buf, value) + bfd *abfd ATTRIBUTE_UNUSED; + char *buf; + bfd_vma value; +{ +#ifdef BFD64 + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + + i_ehdrp = elf_elfheader (abfd); + if (i_ehdrp == NULL) + sprintf_vma (buf, value); + else + { + if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64) + { +#if BFD_HOST_64BIT_LONG + sprintf (buf, "%016lx", value); +#else + sprintf (buf, "%08lx%08lx", _bfd_int64_high (value), + _bfd_int64_low (value)); +#endif + } + else + sprintf (buf, "%08lx", (unsigned long) (value & 0xffffffff)); + } +#else + sprintf_vma (buf, value); +#endif +} + +void +_bfd_elf_fprintf_vma (abfd, stream, value) + bfd *abfd ATTRIBUTE_UNUSED; + PTR stream; + bfd_vma value; +{ +#ifdef BFD64 + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + + i_ehdrp = elf_elfheader (abfd); + if (i_ehdrp == NULL) + fprintf_vma ((FILE *) stream, value); + else + { + if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64) + { +#if BFD_HOST_64BIT_LONG + fprintf ((FILE *) stream, "%016lx", value); +#else + fprintf ((FILE *) stream, "%08lx%08lx", + _bfd_int64_high (value), _bfd_int64_low (value)); +#endif + } + else + fprintf ((FILE *) stream, "%08lx", + (unsigned long) (value & 0xffffffff)); + } +#else + fprintf_vma ((FILE *) stream, value); +#endif +} + +enum elf_reloc_type_class +_bfd_elf_reloc_type_class (rela) + const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED; +{ + return reloc_class_normal; +}