X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf.c;h=c0303fc21a6d57855d9afa9d4938f1ca8d733426;hb=493443a47f514251f12e08223b2c56f0fed69015;hp=7acf1422e5d0f47d92561f424046db98a6d6f2b8;hpb=eee3b786492c6a4564515f3a0ae4029645d73a01;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf.c b/bfd/elf.c index 7acf1422e5..c0303fc21a 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1,8 +1,6 @@ /* ELF executable support for BFD. - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + Copyright 1993-2014 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -44,6 +42,7 @@ SECTION #include "elf-bfd.h" #include "libiberty.h" #include "safe-ctype.h" +#include "elf-linux-psinfo.h" #ifdef CORE_HEADER #include CORE_HEADER @@ -244,7 +243,14 @@ bfd_elf_allocate_object (bfd *abfd, return FALSE; elf_object_id (abfd) = object_id; - elf_program_header_size (abfd) = (bfd_size_type) -1; + if (abfd->direction != read_direction) + { + struct output_elf_obj_tdata *o = bfd_zalloc (abfd, sizeof *o); + if (o == NULL) + return FALSE; + elf_tdata (abfd)->o = o; + elf_program_header_size (abfd) = (bfd_size_type) -1; + } return TRUE; } @@ -261,7 +267,10 @@ bfd_boolean bfd_elf_mkcorefile (bfd *abfd) { /* I think this can be done just like an object file. */ - return abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd); + if (!abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd)) + return FALSE; + elf_tdata (abfd)->core = bfd_zalloc (abfd, sizeof (*elf_tdata (abfd)->core)); + return elf_tdata (abfd)->core != NULL; } static char * @@ -545,9 +554,9 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) shnum = elf_numsections (abfd); num_group = 0; -#define IS_VALID_GROUP_SECTION_HEADER(shdr) \ +#define IS_VALID_GROUP_SECTION_HEADER(shdr, minsize) \ ( (shdr)->sh_type == SHT_GROUP \ - && (shdr)->sh_size >= (2 * GRP_ENTRY_SIZE) \ + && (shdr)->sh_size >= minsize \ && (shdr)->sh_entsize == GRP_ENTRY_SIZE \ && ((shdr)->sh_size % GRP_ENTRY_SIZE) == 0) @@ -555,7 +564,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) { Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i]; - if (IS_VALID_GROUP_SECTION_HEADER (shdr)) + if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE)) num_group += 1; } @@ -581,7 +590,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect) { Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i]; - if (IS_VALID_GROUP_SECTION_HEADER (shdr)) + if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE)) { unsigned char *src; Elf_Internal_Group *dest; @@ -880,45 +889,25 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, { /* The debugging sections appear to be recognized only by name, not any sort of flag. Their SEC_ALLOC bits are cleared. */ - static const struct - { - const char *name; - int len; - } debug_sections [] = - { - { STRING_COMMA_LEN ("debug") }, /* 'd' */ - { NULL, 0 }, /* 'e' */ - { NULL, 0 }, /* 'f' */ - { STRING_COMMA_LEN ("gnu.linkonce.wi.") }, /* 'g' */ - { NULL, 0 }, /* 'h' */ - { NULL, 0 }, /* 'i' */ - { NULL, 0 }, /* 'j' */ - { NULL, 0 }, /* 'k' */ - { STRING_COMMA_LEN ("line") }, /* 'l' */ - { NULL, 0 }, /* 'm' */ - { NULL, 0 }, /* 'n' */ - { NULL, 0 }, /* 'o' */ - { NULL, 0 }, /* 'p' */ - { NULL, 0 }, /* 'q' */ - { NULL, 0 }, /* 'r' */ - { STRING_COMMA_LEN ("stab") }, /* 's' */ - { NULL, 0 }, /* 't' */ - { NULL, 0 }, /* 'u' */ - { NULL, 0 }, /* 'v' */ - { NULL, 0 }, /* 'w' */ - { NULL, 0 }, /* 'x' */ - { NULL, 0 }, /* 'y' */ - { STRING_COMMA_LEN ("zdebug") } /* 'z' */ - }; - if (name [0] == '.') { - int i = name [1] - 'd'; - if (i >= 0 - && i < (int) ARRAY_SIZE (debug_sections) - && debug_sections [i].name != NULL - && strncmp (&name [1], debug_sections [i].name, - debug_sections [i].len) == 0) + const char *p; + int n; + if (name[1] == 'd') + p = ".debug", n = 6; + else if (name[1] == 'g' && name[2] == 'n') + p = ".gnu.linkonce.wi.", n = 17; + else if (name[1] == 'g' && name[2] == 'd') + p = ".gdb_index", n = 11; /* yes we really do mean 11. */ + else if (name[1] == 'l') + p = ".line", n = 5; + else if (name[1] == 's') + p = ".stab", n = 5; + else if (name[1] == 'z') + p = ".zdebug", n = 7; + else + p = NULL, n = 0; + if (p != NULL && strncmp (name, p, n) == 0) flags |= SEC_DEBUGGING; } } @@ -1025,7 +1014,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, else { /* Normal section. Check if we should compress. */ - if ((abfd->flags & BFD_COMPRESS)) + if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0) action = compress; } @@ -1038,7 +1027,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, if (!bfd_init_section_compress_status (abfd, newsect)) { (*_bfd_error_handler) - (_("%B: unable to initialize commpress status for section %s"), + (_("%B: unable to initialize compress status for section %s"), abfd, name); return FALSE; } @@ -1058,7 +1047,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, if (!bfd_init_section_decompress_status (abfd, newsect)) { (*_bfd_error_handler) - (_("%B: unable to initialize decommpress status for section %s"), + (_("%B: unable to initialize decompress status for section %s"), abfd, name); return FALSE; } @@ -1128,13 +1117,17 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; - BFD_ASSERT (!elf_flags_init (obfd) - || (elf_elfheader (obfd)->e_flags - == elf_elfheader (ibfd)->e_flags)); + if (!elf_flags_init (obfd)) + { + elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + elf_flags_init (obfd) = TRUE; + } elf_gp (obfd) = elf_gp (ibfd); - elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; - elf_flags_init (obfd) = TRUE; + + /* Also copy the EI_OSABI field. */ + elf_elfheader (obfd)->e_ident[EI_OSABI] = + elf_elfheader (ibfd)->e_ident[EI_OSABI]; /* Copy object attributes. */ _bfd_elf_copy_obj_attributes (ibfd, obfd); @@ -1454,9 +1447,9 @@ bfd_elf_print_symbol (bfd *abfd, bfd_fprintf_vma (abfd, file, val); /* If we have version information, print it. */ - if (elf_tdata (abfd)->dynversym_section != 0 - && (elf_tdata (abfd)->dynverdef_section != 0 - || elf_tdata (abfd)->dynverref_section != 0)) + if (elf_dynversym (abfd) != 0 + && (elf_dynverdef (abfd) != 0 + || elf_dynverref (abfd) != 0)) { unsigned int vernum; const char *version_string; @@ -1929,7 +1922,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) return TRUE; case SHT_GROUP: - if (! IS_VALID_GROUP_SECTION_HEADER (hdr)) + if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE)) return FALSE; if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) return FALSE; @@ -2081,6 +2074,9 @@ static const struct bfd_elf_special_section special_sections_d[] = { { STRING_COMMA_LEN (".data"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { STRING_COMMA_LEN (".data1"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, + /* There are more DWARF sections than these, but they needn't be added here + unless you have to cope with broken compilers that don't emit section + attributes or you want to help the user writing assembler. */ { STRING_COMMA_LEN (".debug"), 0, SHT_PROGBITS, 0 }, { STRING_COMMA_LEN (".debug_line"), 0, SHT_PROGBITS, 0 }, { STRING_COMMA_LEN (".debug_info"), 0, SHT_PROGBITS, 0 }, @@ -2529,7 +2525,7 @@ _bfd_elf_single_rel_hdr (asection *sec) USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL relocations. */ -bfd_boolean +static bfd_boolean _bfd_elf_init_reloc_shdr (bfd *abfd, struct bfd_elf_section_reloc_data *reldata, asection *asect, @@ -2989,9 +2985,9 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) d->rela.idx = 0; } - t->shstrtab_section = section_number++; + elf_shstrtab_sec (abfd) = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name); - elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section; + elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd); need_symtab = (bfd_get_symcount (abfd) > 0 || (link_info == NULL @@ -2999,21 +2995,28 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) == HAS_RELOC))); if (need_symtab) { - t->symtab_section = section_number++; + elf_onesymtab (abfd) = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name); if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF)) { - t->symtab_shndx_section = section_number++; + elf_symtab_shndx (abfd) = section_number++; t->symtab_shndx_hdr.sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), ".symtab_shndx", FALSE); if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1) return FALSE; } - t->strtab_section = section_number++; + elf_strtab_sec (abfd) = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name); } + if (section_number >= SHN_LORESERVE) + { + _bfd_error_handler (_("%B: too many sections: %u"), + abfd, section_number); + return FALSE; + } + _bfd_elf_strtab_finalize (elf_shstrtab (abfd)); t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); @@ -3037,17 +3040,17 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) elf_elfsections (abfd) = i_shdrp; - i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr; + i_shdrp[elf_shstrtab_sec (abfd)] = &t->shstrtab_hdr; if (need_symtab) { - i_shdrp[t->symtab_section] = &t->symtab_hdr; + i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr; if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF)) { - i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr; - t->symtab_shndx_hdr.sh_link = t->symtab_section; + i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr; + t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd); } - i_shdrp[t->strtab_section] = &t->strtab_hdr; - t->symtab_hdr.sh_link = t->strtab_section; + i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr; + t->symtab_hdr.sh_link = elf_strtab_sec (abfd); } for (sec = abfd->sections; sec; sec = sec->next) @@ -3070,13 +3073,15 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) the relocation entries apply. */ if (d->rel.idx != 0) { - d->rel.hdr->sh_link = t->symtab_section; + d->rel.hdr->sh_link = elf_onesymtab (abfd); d->rel.hdr->sh_info = d->this_idx; + d->rel.hdr->sh_flags |= SHF_INFO_LINK; } if (d->rela.idx != 0) { - d->rela.hdr->sh_link = t->symtab_section; + d->rela.hdr->sh_link = elf_onesymtab (abfd); d->rela.hdr->sh_info = d->this_idx; + d->rela.hdr->sh_flags |= SHF_INFO_LINK; } /* We need to set up sh_link for SHF_LINK_ORDER. */ @@ -3163,7 +3168,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) name += 5; s = bfd_get_section_by_name (abfd, name); if (s != NULL) - d->this_hdr.sh_info = elf_section_data (s)->this_idx; + { + d->this_hdr.sh_info = elf_section_data (s)->this_idx; + d->this_hdr.sh_flags |= SHF_INFO_LINK; + } break; case SHT_STRTAB: @@ -3230,7 +3238,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) break; case SHT_GROUP: - d->this_hdr.sh_link = t->symtab_section; + d->this_hdr.sh_link = elf_onesymtab (abfd); } } @@ -3243,9 +3251,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) return TRUE; } -/* Map symbol from it's internal number to the external number, moving - all local symbols to be at the head of the list. */ - static bfd_boolean sym_is_global (bfd *abfd, asymbol *sym) { @@ -3260,19 +3265,31 @@ sym_is_global (bfd *abfd, asymbol *sym) } /* Don't output section symbols for sections that are not going to be - output. */ + output, that are duplicates or there is no BFD section. */ static bfd_boolean ignore_section_sym (bfd *abfd, asymbol *sym) { - return ((sym->flags & BSF_SECTION_SYM) != 0 - && !(sym->section->owner == abfd + elf_symbol_type *type_ptr; + + if ((sym->flags & BSF_SECTION_SYM) == 0) + return FALSE; + + type_ptr = elf_symbol_from (abfd, sym); + return ((type_ptr != NULL + && type_ptr->internal_elf_sym.st_shndx != 0 + && bfd_is_abs_section (sym->section)) + || !(sym->section->owner == abfd || (sym->section->output_section->owner == abfd - && sym->section->output_offset == 0))); + && sym->section->output_offset == 0) + || bfd_is_abs_section (sym->section))); } +/* Map symbol from it's internal number to the external number, moving + all local symbols to be at the head of the list. */ + static bfd_boolean -elf_map_symbols (bfd *abfd) +elf_map_symbols (bfd *abfd, unsigned int *pnum_locals) { unsigned int symcount = bfd_get_symcount (abfd); asymbol **syms = bfd_get_outsymbols (abfd); @@ -3312,7 +3329,8 @@ elf_map_symbols (bfd *abfd) if ((sym->flags & BSF_SECTION_SYM) != 0 && sym->value == 0 - && !ignore_section_sym (abfd, sym)) + && !ignore_section_sym (abfd, sym) + && !bfd_is_abs_section (sym->section)) { asection *sec = sym->section; @@ -3326,12 +3344,10 @@ elf_map_symbols (bfd *abfd) /* Classify all of the symbols. */ for (idx = 0; idx < symcount; idx++) { - if (ignore_section_sym (abfd, syms[idx])) - continue; - if (!sym_is_global (abfd, syms[idx])) - num_locals++; - else + if (sym_is_global (abfd, syms[idx])) num_globals++; + else if (!ignore_section_sym (abfd, syms[idx])) + num_locals++; } /* We will be adding a section symbol for each normal BFD section. Most @@ -3361,12 +3377,12 @@ elf_map_symbols (bfd *abfd) asymbol *sym = syms[idx]; unsigned int i; - if (ignore_section_sym (abfd, sym)) - continue; - if (!sym_is_global (abfd, sym)) + if (sym_is_global (abfd, sym)) + i = num_locals + num_globals2++; + else if (!ignore_section_sym (abfd, sym)) i = num_locals2++; else - i = num_locals + num_globals2++; + continue; new_syms[i] = sym; sym->udata.i = i + 1; } @@ -3389,8 +3405,7 @@ elf_map_symbols (bfd *abfd) bfd_set_symtab (abfd, new_syms, num_locals + num_globals); - elf_num_locals (abfd) = num_locals; - elf_num_globals (abfd) = num_globals; + *pnum_locals = num_locals; return TRUE; } @@ -3447,8 +3462,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, return FALSE; /* Post process the headers if necessary. */ - if (bed->elf_backend_post_process_headers) - (*bed->elf_backend_post_process_headers) (abfd, link_info); + (*bed->elf_backend_post_process_headers) (abfd, link_info); fsargs.failed = FALSE; fsargs.link_info = link_info; @@ -3501,7 +3515,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, file_ptr off; Elf_Internal_Shdr *hdr; - off = elf_tdata (abfd)->next_file_pos; + off = elf_next_file_pos (abfd); hdr = &elf_tdata (abfd)->symtab_hdr; off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); @@ -3513,7 +3527,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, hdr = &elf_tdata (abfd)->strtab_hdr; off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; /* Now that we know where the .strtab section goes, write it out. */ @@ -3564,13 +3578,13 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info) ++segs; } - if (elf_tdata (abfd)->eh_frame_hdr) + if (elf_eh_frame_hdr (abfd)) { /* We need a PT_GNU_EH_FRAME segment. */ ++segs; } - if (elf_tdata (abfd)->stack_flags) + if (elf_stack_flags (abfd)) { /* We need a PT_GNU_STACK segment. */ ++segs; @@ -3632,8 +3646,7 @@ _bfd_elf_find_segment_containing_section (bfd * abfd, asection * section) struct elf_segment_map *m; Elf_Internal_Phdr *p; - for (m = elf_tdata (abfd)->segment_map, - p = elf_tdata (abfd)->phdr; + for (m = elf_seg_map (abfd), p = elf_tdata (abfd)->phdr; m != NULL; m = m->next, p++) { @@ -3717,7 +3730,7 @@ elf_modify_segment_map (bfd *abfd, sections from the segment map. We also remove excluded sections. Finally, any PT_LOAD segment without sections is removed. */ - m = &elf_tdata (abfd)->segment_map; + m = &elf_seg_map (abfd); while (*m) { unsigned int i, new_count; @@ -3761,7 +3774,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) const struct elf_backend_data *bed = get_elf_backend_data (abfd); bfd_boolean no_user_phdrs; - no_user_phdrs = elf_tdata (abfd)->segment_map == NULL; + no_user_phdrs = elf_seg_map (abfd) == NULL; if (info != NULL) info->user_phdrs = !no_user_phdrs; @@ -3872,10 +3885,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) program headers we will need. */ if (count > 0) { - bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size; + bfd_size_type phdr_size = elf_program_header_size (abfd); if (phdr_size == (bfd_size_type) -1) phdr_size = get_program_header_size (abfd, info); + phdr_size += bed->s->sizeof_ehdr; if ((abfd->flags & D_PAGED) == 0 || (sections[0]->lma & addr_mask) < phdr_size || ((sections[0]->lma & addr_mask) % maxpagesize @@ -4103,11 +4117,31 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) /* Mandated PF_R. */ m->p_flags = PF_R; m->p_flags_valid = 1; + s = first_tls; for (i = 0; i < (unsigned int) tls_count; ++i) { - BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL); - m->sections[i] = first_tls; - first_tls = first_tls->next; + if ((s->flags & SEC_THREAD_LOCAL) == 0) + { + _bfd_error_handler + (_("%B: TLS sections are not adjacent:"), abfd); + s = first_tls; + i = 0; + while (i < (unsigned int) tls_count) + { + if ((s->flags & SEC_THREAD_LOCAL) != 0) + { + _bfd_error_handler (_(" TLS: %A"), s); + i++; + } + else + _bfd_error_handler (_(" non-TLS: %A"), s); + s = s->next; + } + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + m->sections[i] = s; + s = s->next; } *pm = m; @@ -4116,7 +4150,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME segment. */ - eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr; + eh_frame_hdr = elf_eh_frame_hdr (abfd); if (eh_frame_hdr != NULL && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0) { @@ -4133,7 +4167,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) pm = &m->next; } - if (elf_tdata (abfd)->stack_flags) + if (elf_stack_flags (abfd)) { amt = sizeof (struct elf_segment_map); m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); @@ -4141,8 +4175,15 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) goto error_return; m->next = NULL; m->p_type = PT_GNU_STACK; - m->p_flags = elf_tdata (abfd)->stack_flags; + m->p_flags = elf_stack_flags (abfd); + m->p_align = bed->stack_align; m->p_flags_valid = 1; + m->p_align_valid = m->p_align != 0; + if (info->stacksize > 0) + { + m->p_size = info->stacksize; + m->p_size_valid = 1; + } *pm = m; pm = &m->next; @@ -4152,18 +4193,21 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) { for (m = mfirst; m != NULL; m = m->next) { - if (m->p_type == PT_LOAD) + if (m->p_type == PT_LOAD + && m->count != 0 + && m->sections[0]->vma >= info->relro_start + && m->sections[0]->vma < info->relro_end) { - asection *last = m->sections[m->count - 1]; - bfd_vma vaddr = m->sections[0]->vma; - bfd_vma filesz = last->vma - vaddr + last->size; + i = m->count; + while (--i != (unsigned) -1) + if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) + == (SEC_LOAD | SEC_HAS_CONTENTS)) + break; - if (vaddr < info->relro_end - && vaddr >= info->relro_start - && (vaddr + filesz) >= info->relro_end) + if (i != (unsigned) -1) break; } - } + } /* Make a PT_GNU_RELRO segment only when it isn't empty. */ if (m != NULL) @@ -4183,15 +4227,15 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) } free (sections); - elf_tdata (abfd)->segment_map = mfirst; + elf_seg_map (abfd) = mfirst; } if (!elf_modify_segment_map (abfd, info, no_user_phdrs)) return FALSE; - for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (count = 0, m = elf_seg_map (abfd); m != NULL; m = m->next) ++count; - elf_tdata (abfd)->program_header_size = count * bed->s->sizeof_phdr; + elf_program_header_size (abfd) = count * bed->s->sizeof_phdr; return TRUE; @@ -4285,6 +4329,9 @@ elf_sort_sections (const void *arg1, const void *arg2) static file_ptr vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize) { + /* PR binutils/16199: Handle an alignment of zero. */ + if (maxpagesize == 0) + maxpagesize = 1; return ((vma - off) % maxpagesize); } @@ -4355,7 +4402,7 @@ assign_file_positions_for_load_sections (bfd *abfd, return FALSE; alloc = 0; - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (abfd); m != NULL; m = m->next) { ++alloc; if (m->header_size) @@ -4376,32 +4423,32 @@ assign_file_positions_for_load_sections (bfd *abfd, elf_elfheader (abfd)->e_phnum = alloc; - if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1) - elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr; + if (elf_program_header_size (abfd) == (bfd_size_type) -1) + elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr; else - BFD_ASSERT (elf_tdata (abfd)->program_header_size + BFD_ASSERT (elf_program_header_size (abfd) >= alloc * bed->s->sizeof_phdr); if (alloc == 0) { - elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr; + elf_next_file_pos (abfd) = bed->s->sizeof_ehdr; return TRUE; } - /* We're writing the size in elf_tdata (abfd)->program_header_size, + /* We're writing the size in elf_program_header_size (abfd), see assign_file_positions_except_relocs, so make sure we have that amount allocated, with trailing space cleared. - The variable alloc contains the computed need, while elf_tdata - (abfd)->program_header_size contains the size used for the + The variable alloc contains the computed need, while + elf_program_header_size (abfd) contains the size used for the layout. See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments where the layout is forced to according to a larger size in the last iterations for the testcase ld-elf/header. */ - BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr + BFD_ASSERT (elf_program_header_size (abfd) % bed->s->sizeof_phdr == 0); phdrs = (Elf_Internal_Phdr *) bfd_zalloc2 (abfd, - (elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr), + (elf_program_header_size (abfd) / bed->s->sizeof_phdr), sizeof (Elf_Internal_Phdr)); elf_tdata (abfd)->phdr = phdrs; if (phdrs == NULL) @@ -4419,7 +4466,7 @@ assign_file_positions_for_load_sections (bfd *abfd, header_pad -= off; off += header_pad; - for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0; + for (m = elf_seg_map (abfd), p = phdrs, j = 0; m != NULL; m = m->next, p++, j++) { @@ -4568,8 +4615,6 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_memsz = bed->s->sizeof_ehdr; if (m->count > 0) { - BFD_ASSERT (p->p_type == PT_LOAD); - if (p->p_vaddr < (bfd_vma) off) { (*_bfd_error_handler) @@ -4596,7 +4641,6 @@ assign_file_positions_for_load_sections (bfd *abfd, if (m->count > 0) { - BFD_ASSERT (p->p_type == PT_LOAD); p->p_vaddr -= off - p->p_offset; if (!m->p_paddr_valid) p->p_paddr -= off - p->p_offset; @@ -4764,6 +4808,7 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_flags |= PF_W; } } + off -= off_adjust; /* Check that all sections are in a PT_LOAD segment. @@ -4803,7 +4848,7 @@ assign_file_positions_for_load_sections (bfd *abfd, } } - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; return TRUE; } @@ -4819,6 +4864,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, Elf_Internal_Phdr *phdrs; Elf_Internal_Phdr *p; struct elf_segment_map *m; + struct elf_segment_map *hdrs_segment; bfd_vma filehdr_vaddr, filehdr_paddr; bfd_vma phdrs_vaddr, phdrs_paddr; file_ptr off; @@ -4828,10 +4874,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd, i_shdrpp = elf_elfsections (abfd); num_sec = elf_numsections (abfd); - off = elf_tdata (abfd)->next_file_pos; + off = elf_next_file_pos (abfd); for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++) { - struct elf_obj_tdata *tdata = elf_tdata (abfd); Elf_Internal_Shdr *hdr; hdr = *hdrpp; @@ -4861,9 +4906,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) - || hdr == i_shdrpp[tdata->symtab_section] - || hdr == i_shdrpp[tdata->symtab_shndx_section] - || hdr == i_shdrpp[tdata->strtab_section]) + || hdr == i_shdrpp[elf_onesymtab (abfd)] + || hdr == i_shdrpp[elf_symtab_shndx (abfd)] + || hdr == i_shdrpp[elf_strtab_sec (abfd)]) hdr->sh_offset = -1; else off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); @@ -4876,10 +4921,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd, filehdr_paddr = 0; phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr; phdrs_paddr = 0; + hdrs_segment = NULL; phdrs = elf_tdata (abfd)->phdr; - for (m = elf_tdata (abfd)->segment_map, p = phdrs; - m != NULL; - m = m->next, p++) + for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++) { ++count; if (p->p_type != PT_LOAD) @@ -4896,34 +4940,82 @@ assign_file_positions_for_non_load_sections (bfd *abfd, phdrs_paddr = p->p_paddr; if (m->includes_filehdr) { + hdrs_segment = m; phdrs_vaddr += bed->s->sizeof_ehdr; phdrs_paddr += bed->s->sizeof_ehdr; } } } - for (m = elf_tdata (abfd)->segment_map, p = phdrs; - m != NULL; - m = m->next, p++) + if (hdrs_segment != NULL && link_info != NULL) + { + /* There is a segment that contains both the file headers and the + program headers, so provide a symbol __ehdr_start pointing there. + A program can use this to examine itself robustly. */ + + struct elf_link_hash_entry *hash + = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start", + FALSE, FALSE, TRUE); + /* If the symbol was referenced and not defined, define it. */ + if (hash != NULL + && (hash->root.type == bfd_link_hash_new + || hash->root.type == bfd_link_hash_undefined + || hash->root.type == bfd_link_hash_undefweak + || hash->root.type == bfd_link_hash_common)) + { + asection *s = NULL; + if (hdrs_segment->count != 0) + /* The segment contains sections, so use the first one. */ + s = hdrs_segment->sections[0]; + else + /* Use the first (i.e. lowest-addressed) section in any segment. */ + for (m = elf_seg_map (abfd); m != NULL; m = m->next) + if (m->count != 0) + { + s = m->sections[0]; + break; + } + + if (s != NULL) + { + hash->root.u.def.value = filehdr_vaddr - s->vma; + hash->root.u.def.section = s; + } + else + { + hash->root.u.def.value = filehdr_vaddr; + hash->root.u.def.section = bfd_abs_section_ptr; + } + + hash->root.type = bfd_link_hash_defined; + hash->def_regular = 1; + hash->non_elf = 0; + } + } + + for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++) { if (p->p_type == PT_GNU_RELRO) { const Elf_Internal_Phdr *lp; - - BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs); + struct elf_segment_map *lm; if (link_info != NULL) { /* During linking the range of the RELRO segment is passed in link_info. */ - for (lp = phdrs; lp < phdrs + count; ++lp) + for (lm = elf_seg_map (abfd), lp = phdrs; + lm != NULL; + lm = lm->next, lp++) { if (lp->p_type == PT_LOAD - && lp->p_vaddr >= link_info->relro_start && lp->p_vaddr < link_info->relro_end - && lp->p_vaddr + lp->p_filesz >= link_info->relro_end) + && lm->count != 0 + && lm->sections[0]->vma >= link_info->relro_start) break; } + + BFD_ASSERT (lm != NULL); } else { @@ -4949,14 +5041,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd, else abort (); p->p_memsz = p->p_filesz; - /* Preserve the alignment and flags if they are valid. The gold - linker generates RW/4 for the PT_GNU_RELRO section. It is better - for objcopy/strip to honor these attributes otherwise gdb will - choke when using separate debug files. */ - if (!m->p_align_valid) - p->p_align = 1; - if (!m->p_flags_valid) - p->p_flags = (lp->p_flags & ~PF_W); + /* Preserve the alignment and flags if they are valid. The + gold linker generates RW/4 for the PT_GNU_RELRO section. + It is better for objcopy/strip to honor these attributes + otherwise gdb will choke when using separate debug files. + */ + if (!m->p_align_valid) + p->p_align = 1; + if (!m->p_flags_valid) + p->p_flags = (lp->p_flags & ~PF_W); } else { @@ -4964,6 +5057,11 @@ assign_file_positions_for_non_load_sections (bfd *abfd, p->p_type = PT_NULL; } } + else if (p->p_type == PT_GNU_STACK) + { + if (m->p_size_valid) + p->p_memsz = m->p_size; + } else if (m->count != 0) { if (p->p_type != PT_LOAD @@ -5001,7 +5099,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } } - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; return TRUE; } @@ -5050,9 +5148,9 @@ assign_file_positions_except_relocs (bfd *abfd, hdr = *hdrpp; if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) - || i == tdata->symtab_section - || i == tdata->symtab_shndx_section - || i == tdata->strtab_section) + || i == elf_onesymtab (abfd) + || i == elf_symtab_shndx (abfd) + || i == elf_strtab_sec (abfd)) { hdr->sh_offset = -1; } @@ -5079,13 +5177,34 @@ assign_file_positions_except_relocs (bfd *abfd, return FALSE; } + /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. */ + if (link_info != NULL + && link_info->executable + && link_info->shared) + { + unsigned int num_segments = elf_elfheader (abfd)->e_phnum; + Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr; + Elf_Internal_Phdr *end_segment = &segment[num_segments]; + + /* Find the lowest p_vaddr in PT_LOAD segments. */ + bfd_vma p_vaddr = (bfd_vma) -1; + for (; segment < end_segment; segment++) + if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr) + p_vaddr = segment->p_vaddr; + + /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD + segments is non-zero. */ + if (p_vaddr) + i_ehdrp->e_type = ET_EXEC; + } + /* Write out the program headers. */ - alloc = tdata->program_header_size / bed->s->sizeof_phdr; + alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr; if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0 || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0) return FALSE; - off = tdata->next_file_pos; + off = elf_next_file_pos (abfd); } /* Place the section headers. */ @@ -5093,7 +5212,7 @@ assign_file_positions_except_relocs (bfd *abfd, i_ehdrp->e_shoff = off; off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize; - tdata->next_file_pos = off; + elf_next_file_pos (abfd) = off; return TRUE; } @@ -5196,7 +5315,7 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd) unsigned int i, num_sec; Elf_Internal_Shdr **shdrpp; - off = elf_tdata (abfd)->next_file_pos; + off = elf_next_file_pos (abfd); num_sec = elf_numsections (abfd); for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++) @@ -5209,7 +5328,7 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd) off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE); } - elf_tdata (abfd)->next_file_pos = off; + elf_next_file_pos (abfd) = off; } bfd_boolean @@ -5219,6 +5338,7 @@ _bfd_elf_write_object_contents (bfd *abfd) Elf_Internal_Shdr **i_shdrp; bfd_boolean failed; unsigned int count, num_sec; + struct elf_obj_tdata *t; if (! abfd->output_has_begun && ! _bfd_elf_compute_section_file_positions (abfd, NULL)) @@ -5250,21 +5370,21 @@ _bfd_elf_write_object_contents (bfd *abfd) } /* Write out the section header names. */ + t = elf_tdata (abfd); if (elf_shstrtab (abfd) != NULL - && (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0 + && (bfd_seek (abfd, t->shstrtab_hdr.sh_offset, SEEK_SET) != 0 || !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd)))) return FALSE; if (bed->elf_backend_final_write_processing) - (*bed->elf_backend_final_write_processing) (abfd, - elf_tdata (abfd)->linker); + (*bed->elf_backend_final_write_processing) (abfd, elf_linker (abfd)); if (!bed->s->write_shdrs_and_ehdr (abfd)) return FALSE; /* This is last since write_shdrs_and_ehdr can touch i_shdrp[0]. */ - if (elf_tdata (abfd)->after_write_object_contents) - return (*elf_tdata (abfd)->after_write_object_contents) (abfd); + if (t->o->build_id.after_write_object_contents != NULL) + return (*t->o->build_id.after_write_object_contents) (abfd); return TRUE; } @@ -5973,7 +6093,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) and carry on looping. */ amt = sizeof (struct elf_segment_map); amt += ((bfd_size_type) section_count - 1) * sizeof (asection *); - map = (struct elf_segment_map *) bfd_alloc (obfd, amt); + map = (struct elf_segment_map *) bfd_zalloc (obfd, amt); if (map == NULL) { free (sections); @@ -5998,7 +6118,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) free (sections); } - elf_tdata (obfd)->segment_map = map_first; + elf_seg_map (obfd) = map_first; /* If we had to estimate the number of program headers that were going to be needed, then check our estimate now and adjust @@ -6108,12 +6228,15 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) map->p_align_valid = 1; map->p_vaddr_offset = 0; - if (map->p_type == PT_GNU_RELRO) + if (map->p_type == PT_GNU_RELRO + || map->p_type == PT_GNU_STACK) { /* The PT_GNU_RELRO segment may contain the first a few bytes in the .got.plt section even if the whole .got.plt section isn't in the PT_GNU_RELRO segment. We won't - change the size of the PT_GNU_RELRO segment. */ + change the size of the PT_GNU_RELRO segment. + Similarly, PT_GNU_STACK size is significant on uclinux + systems. */ map->p_size = segment->p_memsz; map->p_size_valid = 1; } @@ -6149,12 +6272,13 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) if (ELF_SECTION_IN_SEGMENT (this_hdr, segment)) { map->sections[isec++] = section->output_section; - if (section->lma < lowest_section->lma) - lowest_section = section; if ((section->flags & SEC_ALLOC) != 0) { bfd_vma seg_off; + if (section->lma < lowest_section->lma) + lowest_section = section; + /* Section lmas are set up from PT_LOAD header p_paddr in _bfd_elf_make_section_from_shdr. If this header has a p_paddr that disagrees @@ -6189,7 +6313,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) pointer_to_map = &map->next; } - elf_tdata (obfd)->segment_map = map_first; + elf_seg_map (obfd) = map_first; return TRUE; } @@ -6283,6 +6407,26 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd) } rewrite: + if (ibfd->xvec == obfd->xvec) + { + /* When rewriting program header, set the output maxpagesize to + the maximum alignment of input PT_LOAD segments. */ + Elf_Internal_Phdr *segment; + unsigned int i; + unsigned int num_segments = elf_elfheader (ibfd)->e_phnum; + bfd_vma maxpagesize = 0; + + for (i = 0, segment = elf_tdata (ibfd)->phdr; + i < num_segments; + i++, segment++) + if (segment->p_type == PT_LOAD + && maxpagesize < segment->p_align) + maxpagesize = segment->p_align; + + if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize) + bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize); + } + return rewrite_elf_program_header (ibfd, obfd); } @@ -6460,7 +6604,7 @@ _bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd) entry point, because the latter is called after the section contents have been set, which means that the program headers have already been worked out. */ - if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL) + if (elf_seg_map (obfd) == NULL && elf_tdata (ibfd)->phdr != NULL) { if (! copy_private_bfd_data (ibfd, obfd)) return FALSE; @@ -6508,11 +6652,11 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd, shndx = MAP_ONESYMTAB; else if (shndx == elf_dynsymtab (ibfd)) shndx = MAP_DYNSYMTAB; - else if (shndx == elf_tdata (ibfd)->strtab_section) + else if (shndx == elf_strtab_sec (ibfd)) shndx = MAP_STRTAB; - else if (shndx == elf_tdata (ibfd)->shstrtab_section) + else if (shndx == elf_shstrtab_sec (ibfd)) shndx = MAP_SHSTRTAB; - else if (shndx == elf_tdata (ibfd)->symtab_shndx_section) + else if (shndx == elf_symtab_shndx (ibfd)) shndx = MAP_SYM_SHNDX; osym->internal_elf_sym.st_shndx = shndx; } @@ -6537,10 +6681,11 @@ swap_out_syms (bfd *abfd, bfd_byte *outbound_syms; bfd_byte *outbound_shndx; int idx; + unsigned int num_locals; bfd_size_type amt; bfd_boolean name_local_sections; - if (!elf_map_symbols (abfd)) + if (!elf_map_symbols (abfd, &num_locals)) return FALSE; /* Dump out the symtabs. */ @@ -6554,7 +6699,7 @@ swap_out_syms (bfd *abfd, symtab_hdr->sh_type = SHT_SYMTAB; symtab_hdr->sh_entsize = bed->s->sizeof_sym; symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1); - symtab_hdr->sh_info = elf_num_locals (abfd) + 1; + symtab_hdr->sh_info = num_locals + 1; symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align; symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; @@ -6688,15 +6833,16 @@ swap_out_syms (bfd *abfd, shndx = elf_dynsymtab (abfd); break; case MAP_STRTAB: - shndx = elf_tdata (abfd)->strtab_section; + shndx = elf_strtab_sec (abfd); break; case MAP_SHSTRTAB: - shndx = elf_tdata (abfd)->shstrtab_section; + shndx = elf_shstrtab_sec (abfd); break; case MAP_SYM_SHNDX: - shndx = elf_tdata (abfd)->symtab_shndx_section; + shndx = elf_symtab_shndx (abfd); break; default: + shndx = SHN_ABS; break; } } @@ -7289,7 +7435,7 @@ error_return_verdef: Elf_Internal_Verdef *iverdef; Elf_Internal_Verdaux *iverdaux; - iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];; + iverdef = &elf_tdata (abfd)->verdef[freeidx - 1]; iverdef->vd_version = VER_DEF_CURRENT; iverdef->vd_flags = 0; @@ -7407,68 +7553,94 @@ elf_find_function (bfd *abfd, const char **filename_ptr, const char **functionname_ptr) { - const char *filename; - asymbol *func, *file; - bfd_vma low_func; - asymbol **p; - /* ??? Given multiple file symbols, it is impossible to reliably - choose the right file name for global symbols. File symbols are - local symbols, and thus all file symbols must sort before any - global symbols. The ELF spec may be interpreted to say that a - file symbol must sort before other local symbols, but currently - ld -r doesn't do this. So, for ld -r output, it is possible to - make a better choice of file name for local symbols by ignoring - file symbols appearing after a given local symbol. */ - enum { nothing_seen, symbol_seen, file_after_symbol_seen } state; - const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct elf_find_function_cache + { + asection *last_section; + asymbol *func; + const char *filename; + bfd_size_type func_size; + } *cache; if (symbols == NULL) return FALSE; - filename = NULL; - func = NULL; - file = NULL; - low_func = 0; - state = nothing_seen; - - for (p = symbols; *p != NULL; p++) + cache = elf_tdata (abfd)->elf_find_function_cache; + if (cache == NULL) { - asymbol *sym = *p; - asection *code_sec; - bfd_vma code_off; - - if ((sym->flags & BSF_FILE) != 0) - { - file = sym; - if (state == symbol_seen) - state = file_after_symbol_seen; - continue; - } + cache = bfd_zalloc (abfd, sizeof (*cache)); + elf_tdata (abfd)->elf_find_function_cache = cache; + if (cache == NULL) + return FALSE; + } + if (cache->last_section != section + || cache->func == NULL + || offset < cache->func->value + || offset >= cache->func->value + cache->func_size) + { + asymbol *file; + bfd_vma low_func; + asymbol **p; + /* ??? Given multiple file symbols, it is impossible to reliably + choose the right file name for global symbols. File symbols are + local symbols, and thus all file symbols must sort before any + global symbols. The ELF spec may be interpreted to say that a + file symbol must sort before other local symbols, but currently + ld -r doesn't do this. So, for ld -r output, it is possible to + make a better choice of file name for local symbols by ignoring + file symbols appearing after a given local symbol. */ + enum { nothing_seen, symbol_seen, file_after_symbol_seen } state; + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + + file = NULL; + low_func = 0; + state = nothing_seen; + cache->filename = NULL; + cache->func = NULL; + cache->func_size = 0; + cache->last_section = section; + + for (p = symbols; *p != NULL; p++) + { + asymbol *sym = *p; + bfd_vma code_off; + bfd_size_type size; + + if ((sym->flags & BSF_FILE) != 0) + { + file = sym; + if (state == symbol_seen) + state = file_after_symbol_seen; + continue; + } - if (bed->maybe_function_sym (sym, &code_sec, &code_off) - && code_sec == section - && code_off >= low_func - && code_off <= offset) - { - func = sym; - low_func = code_off; - filename = NULL; - if (file != NULL - && ((sym->flags & BSF_LOCAL) != 0 - || state != file_after_symbol_seen)) - filename = bfd_asymbol_name (file); + size = bed->maybe_function_sym (sym, section, &code_off); + if (size != 0 + && code_off <= offset + && (code_off > low_func + || (code_off == low_func + && size > cache->func_size))) + { + cache->func = sym; + cache->func_size = size; + cache->filename = NULL; + low_func = code_off; + if (file != NULL + && ((sym->flags & BSF_LOCAL) != 0 + || state != file_after_symbol_seen)) + cache->filename = bfd_asymbol_name (file); + } + if (state == nothing_seen) + state = symbol_seen; } - if (state == nothing_seen) - state = symbol_seen; } - if (func == NULL) + if (cache->func == NULL) return FALSE; if (filename_ptr) - *filename_ptr = filename; + *filename_ptr = cache->filename; if (functionname_ptr) - *functionname_ptr = bfd_asymbol_name (func); + *functionname_ptr = bfd_asymbol_name (cache->func); return TRUE; } @@ -7484,6 +7656,23 @@ _bfd_elf_find_nearest_line (bfd *abfd, const char **filename_ptr, const char **functionname_ptr, unsigned int *line_ptr) +{ + return _bfd_elf_find_nearest_line_discriminator (abfd, section, symbols, + offset, filename_ptr, + functionname_ptr, + line_ptr, + NULL); +} + +bfd_boolean +_bfd_elf_find_nearest_line_discriminator (bfd *abfd, + asection *section, + asymbol **symbols, + bfd_vma offset, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *line_ptr, + unsigned int *discriminator_ptr) { bfd_boolean found; @@ -7502,7 +7691,7 @@ _bfd_elf_find_nearest_line (bfd *abfd, if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, section, symbols, offset, filename_ptr, functionname_ptr, - line_ptr, 0, + line_ptr, discriminator_ptr, 0, &elf_tdata (abfd)->dwarf2_find_line_info)) { if (!*functionname_ptr) @@ -7537,9 +7726,20 @@ _bfd_elf_find_nearest_line (bfd *abfd, bfd_boolean _bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol, const char **filename_ptr, unsigned int *line_ptr) +{ + return _bfd_elf_find_line_discriminator (abfd, symbols, symbol, + filename_ptr, line_ptr, + NULL); +} + +bfd_boolean +_bfd_elf_find_line_discriminator (bfd *abfd, asymbol **symbols, asymbol *symbol, + const char **filename_ptr, + unsigned int *line_ptr, + unsigned int *discriminator_ptr) { return _bfd_dwarf2_find_line (abfd, symbols, symbol, - filename_ptr, line_ptr, 0, + filename_ptr, line_ptr, discriminator_ptr, 0, &elf_tdata (abfd)->dwarf2_find_line_info); } @@ -7570,21 +7770,21 @@ _bfd_elf_sizeof_headers (bfd *abfd, struct bfd_link_info *info) if (!info->relocatable) { - bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size; + bfd_size_type phdr_size = elf_program_header_size (abfd); if (phdr_size == (bfd_size_type) -1) { struct elf_segment_map *m; phdr_size = 0; - for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) + for (m = elf_seg_map (abfd); m != NULL; m = m->next) phdr_size += bed->s->sizeof_phdr; if (phdr_size == 0) phdr_size = get_program_header_size (abfd, info); } - elf_tdata (abfd)->program_header_size = phdr_size; + elf_program_header_size (abfd) = phdr_size; ret += phdr_size; } @@ -7724,7 +7924,7 @@ _bfd_elf_close_and_cleanup (bfd *abfd) struct elf_obj_tdata *tdata = elf_tdata (abfd); if (bfd_get_format (abfd) == bfd_object && tdata != NULL) { - if (elf_shstrtab (abfd) != NULL) + if (elf_tdata (abfd)->o != NULL && elf_shstrtab (abfd) != NULL) _bfd_elf_strtab_free (elf_shstrtab (abfd)); _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info); } @@ -7766,9 +7966,9 @@ elfcore_make_pid (bfd *abfd) { int pid; - pid = elf_tdata (abfd)->core_lwpid; + pid = elf_tdata (abfd)->core->lwpid; if (pid == 0) - pid = elf_tdata (abfd)->core_pid; + pid = elf_tdata (abfd)->core->pid; return pid; } @@ -7858,10 +8058,10 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) /* Do not overwrite the core signal if it has already been set by another thread. */ - if (elf_tdata (abfd)->core_signal == 0) - elf_tdata (abfd)->core_signal = prstat.pr_cursig; - if (elf_tdata (abfd)->core_pid == 0) - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal = prstat.pr_cursig; + if (elf_tdata (abfd)->core->pid == 0) + elf_tdata (abfd)->core->pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -7870,9 +8070,9 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) linux 2.[01] */ #if defined (HAVE_PRSTATUS_T_PR_WHO) - elf_tdata (abfd)->core_lwpid = prstat.pr_who; + elf_tdata (abfd)->core->lwpid = prstat.pr_who; #else - elf_tdata (abfd)->core_lwpid = prstat.pr_pid; + elf_tdata (abfd)->core->lwpid = prstat.pr_pid; #endif } #if defined (HAVE_PRSTATUS32_T) @@ -7887,10 +8087,10 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) /* Do not overwrite the core signal if it has already been set by another thread. */ - if (elf_tdata (abfd)->core_signal == 0) - elf_tdata (abfd)->core_signal = prstat.pr_cursig; - if (elf_tdata (abfd)->core_pid == 0) - elf_tdata (abfd)->core_pid = prstat.pr_pid; + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal = prstat.pr_cursig; + if (elf_tdata (abfd)->core->pid == 0) + elf_tdata (abfd)->core->pid = prstat.pr_pid; /* pr_who exists on: solaris 2.5+ @@ -7899,9 +8099,9 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) linux 2.[01] */ #if defined (HAVE_PRSTATUS32_T_PR_WHO) - elf_tdata (abfd)->core_lwpid = prstat.pr_who; + elf_tdata (abfd)->core->lwpid = prstat.pr_who; #else - elf_tdata (abfd)->core_lwpid = prstat.pr_pid; + elf_tdata (abfd)->core->lwpid = prstat.pr_pid; #endif } #endif /* HAVE_PRSTATUS32_T */ @@ -8018,12 +8218,36 @@ elfcore_grok_s390_system_call (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-s390-system-call", note); } +static bfd_boolean +elfcore_grok_s390_tdb (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-tdb", note); +} + static bfd_boolean elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note) { return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note); } +static bfd_boolean +elfcore_grok_aarch_tls (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-tls", note); +} + +static bfd_boolean +elfcore_grok_aarch_hw_break (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-break", note); +} + +static bfd_boolean +elfcore_grok_aarch_hw_watch (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", note); +} + #if defined (HAVE_PRPSINFO_T) typedef prpsinfo_t elfcore_psinfo_t; #if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */ @@ -8075,13 +8299,13 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); #if defined (HAVE_PSINFO_T_PR_PID) || defined (HAVE_PRPSINFO_T_PR_PID) - elf_tdata (abfd)->core_pid = psinfo.pr_pid; + elf_tdata (abfd)->core->pid = psinfo.pr_pid; #endif - elf_tdata (abfd)->core_program + elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs)); } @@ -8094,13 +8318,13 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); #if defined (HAVE_PSINFO32_T_PR_PID) || defined (HAVE_PRPSINFO32_T_PR_PID) - elf_tdata (abfd)->core_pid = psinfo.pr_pid; + elf_tdata (abfd)->core->pid = psinfo.pr_pid; #endif - elf_tdata (abfd)->core_program + elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs)); } @@ -8118,7 +8342,7 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) implementations, so strip it off if it exists. */ { - char *command = elf_tdata (abfd)->core_command; + char *command = elf_tdata (abfd)->core->command; int n = strlen (command); if (0 < n && command[n - 1] == ' ') @@ -8143,7 +8367,7 @@ elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note) memcpy (&pstat, note->descdata, sizeof (pstat)); - elf_tdata (abfd)->core_pid = pstat.pr_pid; + elf_tdata (abfd)->core->pid = pstat.pr_pid; } #if defined (HAVE_PSTATUS32_T) else if (note->descsz == sizeof (pstatus32_t)) @@ -8153,7 +8377,7 @@ elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note) memcpy (&pstat, note->descdata, sizeof (pstat)); - elf_tdata (abfd)->core_pid = pstat.pr_pid; + elf_tdata (abfd)->core->pid = pstat.pr_pid; } #endif /* Could grab some more details from the "representative" @@ -8183,11 +8407,11 @@ elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note) memcpy (&lwpstat, note->descdata, sizeof (lwpstat)); - elf_tdata (abfd)->core_lwpid = lwpstat.pr_lwpid; + elf_tdata (abfd)->core->lwpid = lwpstat.pr_lwpid; /* Do not overwrite the core signal if it has already been set by another thread. */ - if (elf_tdata (abfd)->core_signal == 0) - elf_tdata (abfd)->core_signal = lwpstat.pr_cursig; + if (elf_tdata (abfd)->core->signal == 0) + elf_tdata (abfd)->core->signal = lwpstat.pr_cursig; /* Make a ".reg/999" section. */ @@ -8270,11 +8494,11 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note) switch (type) { case 1 /* NOTE_INFO_PROCESS */: - /* FIXME: need to add ->core_command. */ + /* FIXME: need to add ->core->command. */ /* process_info.pid */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 8); + elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 8); /* process_info.signal */ - elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 12); + elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 12); break; case 2 /* NOTE_INFO_THREAD */: @@ -8457,6 +8681,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_S390_TDB: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_tdb (abfd, note); + else + return TRUE; + case NT_ARM_VFP: if (note->namesz == 6 && strcmp (note->namedata, "LINUX") == 0) @@ -8464,6 +8695,27 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_ARM_TLS: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_tls (abfd, note); + else + return TRUE; + + case NT_ARM_HW_BREAK: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_hw_break (abfd, note); + else + return TRUE; + + case NT_ARM_HW_WATCH: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_aarch_hw_watch (abfd, note); + else + return TRUE; + case NT_PRPSINFO: case NT_PSINFO: if (bed->elf_backend_grok_psinfo) @@ -8488,18 +8740,32 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) return TRUE; } + + case NT_FILE: + return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.file", + note); + + case NT_SIGINFO: + return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo", + note); } } static bfd_boolean elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note) { - elf_tdata (abfd)->build_id_size = note->descsz; - elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz); - if (elf_tdata (abfd)->build_id == NULL) + struct elf_obj_tdata *t; + + if (note->descsz == 0) + return FALSE; + + t = elf_tdata (abfd); + t->build_id = bfd_alloc (abfd, sizeof (*t->build_id) - 1 + note->descsz); + if (t->build_id == NULL) return FALSE; - memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz); + t->build_id->size = note->descsz; + memcpy (t->build_id->data, note->descdata, note->descsz); return TRUE; } @@ -8564,15 +8830,15 @@ static bfd_boolean elfcore_grok_netbsd_procinfo (bfd *abfd, Elf_Internal_Note *note) { /* Signal number at offset 0x08. */ - elf_tdata (abfd)->core_signal + elf_tdata (abfd)->core->signal = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08); /* Process ID at offset 0x50. */ - elf_tdata (abfd)->core_pid + elf_tdata (abfd)->core->pid = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x50); /* Command name at 0x7c (max 32 bytes, including nul). */ - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31); return elfcore_make_note_pseudosection (abfd, ".note.netbsdcore.procinfo", @@ -8585,7 +8851,7 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note) int lwp; if (elfcore_netbsd_get_lwpid (note, &lwp)) - elf_tdata (abfd)->core_lwpid = lwp; + elf_tdata (abfd)->core->lwpid = lwp; if (note->type == NT_NETBSDCORE_PROCINFO) { @@ -8648,15 +8914,15 @@ static bfd_boolean elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note) { /* Signal number at offset 0x08. */ - elf_tdata (abfd)->core_signal + elf_tdata (abfd)->core->signal = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08); /* Process ID at offset 0x20. */ - elf_tdata (abfd)->core_pid + elf_tdata (abfd)->core->pid = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x20); /* Command name at 0x48 (max 32 bytes, including nul). */ - elf_tdata (abfd)->core_command + elf_tdata (abfd)->core->command = _bfd_elfcore_strndup (abfd, note->descdata + 0x48, 31); return TRUE; @@ -8719,7 +8985,7 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid) unsigned flags; /* nto_procfs_status 'pid' field is at offset 0. */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata); + elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, (bfd_byte *) ddata); /* nto_procfs_status 'tid' field is at offset 4. Pass it back. */ *tid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4); @@ -8730,15 +8996,15 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid) /* nto_procfs_status 'what' field is at offset 14. */ if ((sig = bfd_get_16 (abfd, (bfd_byte *) ddata + 14)) > 0) { - elf_tdata (abfd)->core_signal = sig; - elf_tdata (abfd)->core_lwpid = *tid; + elf_tdata (abfd)->core->signal = sig; + elf_tdata (abfd)->core->lwpid = *tid; } /* _DEBUG_FLAG_CURTID (current thread) is 0x80. Some cores do not come from signals so we make sure we set the current thread just in case. */ if (flags & 0x00000080) - elf_tdata (abfd)->core_lwpid = *tid; + elf_tdata (abfd)->core->lwpid = *tid; /* Make a ".qnx_core_status/%d" section. */ sprintf (buf, ".qnx_core_status/%ld", *tid); @@ -8786,7 +9052,7 @@ elfcore_grok_nto_regs (bfd *abfd, sect->alignment_power = 2; /* This is the current thread. */ - if (elf_tdata (abfd)->core_lwpid == tid) + if (elf_tdata (abfd)->core->lwpid == tid) return elfcore_maybe_make_sect (abfd, base, sect); return TRUE; @@ -8972,6 +9238,34 @@ elfcore_write_prpsinfo (bfd *abfd, return NULL; } +char * +elfcore_write_linux_prpsinfo32 + (bfd *abfd, char *buf, int *bufsiz, + const struct elf_internal_linux_prpsinfo *prpsinfo) +{ + struct elf_external_linux_prpsinfo32 data; + + memset (&data, 0, sizeof (data)); + LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data); + + return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO, + &data, sizeof (data)); +} + +char * +elfcore_write_linux_prpsinfo64 + (bfd *abfd, char *buf, int *bufsiz, + const struct elf_internal_linux_prpsinfo *prpsinfo) +{ + struct elf_external_linux_prpsinfo64 data; + + memset (&data, 0, sizeof (data)); + LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data); + + return elfcore_write_note (abfd, buf, bufsiz, + "CORE", NT_PRPSINFO, &data, sizeof (data)); +} + char * elfcore_write_prstatus (bfd *abfd, char *buf, @@ -9247,6 +9541,18 @@ elfcore_write_s390_system_call (bfd *abfd, s390_system_call, size); } +char * +elfcore_write_s390_tdb (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_tdb, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_TDB, s390_tdb, size); +} + char * elfcore_write_arm_vfp (bfd *abfd, char *buf, @@ -9259,6 +9565,42 @@ elfcore_write_arm_vfp (bfd *abfd, note_name, NT_ARM_VFP, arm_vfp, size); } +char * +elfcore_write_aarch_tls (bfd *abfd, + char *buf, + int *bufsiz, + const void *aarch_tls, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_TLS, aarch_tls, size); +} + +char * +elfcore_write_aarch_hw_break (bfd *abfd, + char *buf, + int *bufsiz, + const void *aarch_hw_break, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_HW_BREAK, aarch_hw_break, size); +} + +char * +elfcore_write_aarch_hw_watch (bfd *abfd, + char *buf, + int *bufsiz, + const void *aarch_hw_watch, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_HW_WATCH, aarch_hw_watch, size); +} + char * elfcore_write_register_note (bfd *abfd, char *buf, @@ -9293,8 +9635,16 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_s390_last_break (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-s390-system-call") == 0) return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-tdb") == 0) + return elfcore_write_s390_tdb (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-arm-vfp") == 0) return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-tls") == 0) + return elfcore_write_aarch_tls (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-hw-break") == 0) + return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-hw-watch") == 0) + return elfcore_write_aarch_hw_watch (abfd, buf, bufsiz, data, size); return NULL; } @@ -9453,7 +9803,9 @@ bfd_get_elf_phdrs (bfd *abfd, void *phdrs) } enum elf_reloc_type_class -_bfd_elf_reloc_type_class (const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED) +_bfd_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED) { return reloc_class_normal; } @@ -9556,7 +9908,7 @@ bfd_elf_bfd_from_remote_memory (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep, - int (*target_read_memory) (bfd_vma, bfd_byte *, int)) + int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type)) { return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory) (templ, ehdr_vma, loadbasep, target_read_memory); @@ -9685,8 +10037,8 @@ asection _bfd_elf_large_com_section SEC_IS_COMMON, NULL, "LARGE_COMMON", 0); void -_bfd_elf_set_osabi (bfd * abfd, - struct bfd_link_info * link_info ATTRIBUTE_UNUSED) +_bfd_elf_post_process_headers (bfd * abfd, + struct bfd_link_info * link_info ATTRIBUTE_UNUSED) { Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ @@ -9714,18 +10066,26 @@ _bfd_elf_is_function_type (unsigned int type) || type == STT_GNU_IFUNC); } -/* Return TRUE iff the ELF symbol SYM might be a function. Set *CODE_SEC - and *CODE_OFF to the function's entry point. */ +/* If the ELF symbol SYM might be a function in SEC, return the + function size and set *CODE_OFF to the function's entry point, + otherwise return zero. */ -bfd_boolean -_bfd_elf_maybe_function_sym (const asymbol *sym, - asection **code_sec, bfd_vma *code_off) +bfd_size_type +_bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec, + bfd_vma *code_off) { + bfd_size_type size; + if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT - | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0) - return FALSE; + | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0 + || sym->section != sec) + return 0; - *code_sec = sym->section; *code_off = sym->value; - return TRUE; + size = 0; + if (!(sym->flags & BSF_SYNTHETIC)) + size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; + if (size == 0) + size = 1; + return size; }