X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf64-x86-64.c;h=8fae5fcb7867526b12d5b1d7024caf411962e3ac;hb=1788fc08f7a091f246a41cd14d2b612d4253e55b;hp=a9429b8c6cbb6cf1932510052256ba8d7f859a52;hpb=1da80baa66a91a51d46a48476dbc14b26eaf8f78;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index a9429b8c6c..8fae5fcb78 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -148,8 +148,12 @@ static reloc_howto_type x86_64_elf_howto_table[] = HOWTO(R_X86_64_PLTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", FALSE, MINUS_ONE, MINUS_ONE, FALSE), - EMPTY_HOWTO (32), - EMPTY_HOWTO (33), + HOWTO(R_X86_64_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, + bfd_elf_generic_reloc, "R_X86_64_SIZE32", FALSE, 0xffffffff, 0xffffffff, + FALSE), + HOWTO(R_X86_64_SIZE64, 0, 4, 64, FALSE, 0, complain_overflow_unsigned, + bfd_elf_generic_reloc, "R_X86_64_SIZE64", FALSE, MINUS_ONE, MINUS_ONE, + FALSE), HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_X86_64_GOTPC32_TLSDESC", @@ -173,7 +177,7 @@ static reloc_howto_type x86_64_elf_howto_table[] = R_X86_64_standard counts the number up to this point, and R_X86_64_vt_offset is the value to subtract from a reloc type of R_X86_64_GNU_VT* to form an index into this table. */ -#define R_X86_64_standard (R_X86_64_IRELATIVE + 1) +#define R_X86_64_standard (R_X86_64_RELATIVE64 + 1) #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard) /* GNU extension to record C++ vtable hierarchy. */ @@ -238,6 +242,8 @@ static const struct elf_reloc_map x86_64_reloc_map[] = { BFD_RELOC_X86_64_GOTPC64, R_X86_64_GOTPC64, }, { BFD_RELOC_X86_64_GOTPLT64, R_X86_64_GOTPLT64, }, { BFD_RELOC_X86_64_PLTOFF64, R_X86_64_PLTOFF64, }, + { BFD_RELOC_SIZE32, R_X86_64_SIZE32, }, + { BFD_RELOC_SIZE64, R_X86_64_SIZE64, }, { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, }, { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, }, { BFD_RELOC_X86_64_TLSDESC, R_X86_64_TLSDESC, }, @@ -449,7 +455,7 @@ elf_x86_64_write_core_note (bfd *abfd, char *buf, int *bufsiz, } else { - prpsinfo_t data; + prpsinfo64_t data; memset (&data, 0, sizeof (data)); strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); @@ -490,7 +496,7 @@ elf_x86_64_write_core_note (bfd *abfd, char *buf, int *bufsiz, } else { - prstatus_t prstat; + prstatus64_t prstat; memset (&prstat, 0, sizeof (prstat)); prstat.pr_pid = pid; prstat.pr_cursig = cursig; @@ -970,33 +976,26 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj, if (htab == NULL) return FALSE; - htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); + htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); if (!info->shared) - htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); + htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); if (!htab->sdynbss || (!info->shared && !htab->srelbss)) abort (); if (!info->no_ld_generated_unwind_info - && bfd_get_section_by_name (dynobj, ".eh_frame") == NULL + && htab->plt_eh_frame == NULL && htab->elf.splt != NULL) { - const struct elf_x86_64_backend_data *const abed - = get_elf_x86_64_backend_data (dynobj); - flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags; + flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY + | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED); htab->plt_eh_frame - = bfd_make_section_with_flags (dynobj, ".eh_frame", - flags | SEC_READONLY); + = bfd_make_section_anyway_with_flags (dynobj, ".eh_frame", flags); if (htab->plt_eh_frame == NULL || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3)) return FALSE; - - htab->plt_eh_frame->size = abed->eh_frame_plt_size; - htab->plt_eh_frame->contents - = bfd_alloc (dynobj, htab->plt_eh_frame->size); - memcpy (htab->plt_eh_frame->contents, - abed->eh_frame_plt, abed->eh_frame_plt_size); } return TRUE; } @@ -1529,82 +1528,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, break; } - /* Since STT_GNU_IFUNC symbol must go through PLT, we handle - it here if it is defined in a non-shared object. */ - if (h->type == STT_GNU_IFUNC - && h->def_regular) - { - /* It is referenced by a non-shared object. */ - h->ref_regular = 1; - h->needs_plt = 1; - - /* STT_GNU_IFUNC symbol must go through PLT. */ - h->plt.refcount += 1; - - /* STT_GNU_IFUNC needs dynamic sections. */ - if (htab->elf.dynobj == NULL) - htab->elf.dynobj = abfd; - - switch (r_type) - { - default: - if (h->root.root.string) - name = h->root.root.string; - else - name = bfd_elf_sym_name (abfd, symtab_hdr, isym, - NULL); - (*_bfd_error_handler) - (_("%B: relocation %s against STT_GNU_IFUNC " - "symbol `%s' isn't handled by %s"), abfd, - x86_64_elf_howto_table[r_type].name, - name, __FUNCTION__); - bfd_set_error (bfd_error_bad_value); - return FALSE; - - case R_X86_64_32: - if (ABI_64_P (abfd)) - goto not_pointer; - case R_X86_64_64: - h->non_got_ref = 1; - h->pointer_equality_needed = 1; - if (info->shared) - { - /* We must copy these reloc types into the output - file. Create a reloc section in dynobj and - make room for this reloc. */ - sreloc = _bfd_elf_create_ifunc_dyn_reloc - (abfd, info, sec, sreloc, - &((struct elf_x86_64_link_hash_entry *) h)->dyn_relocs); - if (sreloc == NULL) - return FALSE; - } - break; - - case R_X86_64_32S: - case R_X86_64_PC32: - case R_X86_64_PC64: -not_pointer: - h->non_got_ref = 1; - if (r_type != R_X86_64_PC32 - && r_type != R_X86_64_PC64) - h->pointer_equality_needed = 1; - break; - - case R_X86_64_PLT32: - break; - - case R_X86_64_GOTPCREL: - case R_X86_64_GOTPCREL64: - h->got.refcount += 1; - if (htab->elf.sgot == NULL - && !_bfd_elf_create_got_section (htab->elf.dynobj, - info)) - return FALSE; - break; - } - - continue; - } + /* It is referenced by a non-shared object. */ + h->ref_regular = 1; } if (! elf_x86_64_tls_transition (info, abfd, sec, NULL, @@ -1725,6 +1650,7 @@ not_pointer: (*_bfd_error_handler) (_("%B: '%s' accessed both as normal and thread local symbol"), abfd, name); + bfd_set_error (bfd_error_bad_value); return FALSE; } } @@ -1811,6 +1737,8 @@ not_pointer: case R_X86_64_PC32: case R_X86_64_PC64: case R_X86_64_64: + case R_X86_64_SIZE32: + case R_X86_64_SIZE64: pointer: if (h != NULL && info->executable) { @@ -2107,6 +2035,8 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, case R_X86_64_PC16: case R_X86_64_PC32: case R_X86_64_PC64: + case R_X86_64_SIZE32: + case R_X86_64_SIZE64: if (info->shared && (h == NULL || h->type != STT_GNU_IFUNC)) break; @@ -2141,10 +2071,44 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, { struct elf_x86_64_link_hash_table *htab; asection *s; + struct elf_x86_64_link_hash_entry *eh; + struct elf_dyn_relocs *p; /* STT_GNU_IFUNC symbol must go through PLT. */ if (h->type == STT_GNU_IFUNC) { + /* All local STT_GNU_IFUNC references must be treate as local + calls via local PLT. */ + if (h->ref_regular + && SYMBOL_CALLS_LOCAL (info, h)) + { + bfd_size_type pc_count = 0, count = 0; + struct elf_dyn_relocs **pp; + + eh = (struct elf_x86_64_link_hash_entry *) h; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + { + pc_count += p->pc_count; + p->count -= p->pc_count; + p->pc_count = 0; + count += p->count; + if (p->count == 0) + *pp = p->next; + else + pp = &p->next; + } + + if (pc_count || count) + { + h->needs_plt = 1; + h->non_got_ref = 1; + if (h->plt.refcount <= 0) + h->plt.refcount = 1; + else + h->plt.refcount += 1; + } + } + if (h->plt.refcount <= 0) { h->plt.offset = (bfd_vma) -1; @@ -2221,9 +2185,6 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, if (ELIMINATE_COPY_RELOCS) { - struct elf_x86_64_link_hash_entry * eh; - struct elf_dyn_relocs *p; - eh = (struct elf_x86_64_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { @@ -2579,6 +2540,154 @@ elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h, return TRUE; } +/* Convert + mov foo@GOTPCREL(%rip), %reg + to + lea foo(%rip), %reg + with the local symbol, foo. */ + +static bfd_boolean +elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec, + struct bfd_link_info *link_info) +{ + Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Rela *internal_relocs; + Elf_Internal_Rela *irel, *irelend; + bfd_byte *contents; + struct elf_x86_64_link_hash_table *htab; + bfd_boolean changed_contents; + bfd_boolean changed_relocs; + bfd_signed_vma *local_got_refcounts; + + /* Don't even try to convert non-ELF outputs. */ + if (!is_elf_hash_table (link_info->hash)) + return FALSE; + + /* Nothing to do if there are no codes, no relocations or no output. */ + if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC) + || sec->reloc_count == 0 + || discarded_section (sec)) + return TRUE; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + + /* Load the relocations for this section. */ + internal_relocs = (_bfd_elf_link_read_relocs + (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, + link_info->keep_memory)); + if (internal_relocs == NULL) + return FALSE; + + htab = elf_x86_64_hash_table (link_info); + changed_contents = FALSE; + changed_relocs = FALSE; + local_got_refcounts = elf_local_got_refcounts (abfd); + + /* Get the section contents. */ + if (elf_section_data (sec)->this_hdr.contents != NULL) + contents = elf_section_data (sec)->this_hdr.contents; + else + { + if (!bfd_malloc_and_get_section (abfd, sec, &contents)) + goto error_return; + } + + irelend = internal_relocs + sec->reloc_count; + for (irel = internal_relocs; irel < irelend; irel++) + { + unsigned int r_type = ELF32_R_TYPE (irel->r_info); + unsigned int r_symndx = htab->r_sym (irel->r_info); + unsigned int indx; + struct elf_link_hash_entry *h; + + if (r_type != R_X86_64_GOTPCREL) + continue; + + /* Get the symbol referred to by the reloc. */ + if (r_symndx < symtab_hdr->sh_info) + { + Elf_Internal_Sym *isym; + + isym = bfd_sym_from_r_symndx (&htab->sym_cache, + abfd, r_symndx); + + /* STT_GNU_IFUNC must keep R_X86_64_GOTPCREL relocation. */ + if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC + && bfd_get_8 (input_bfd, + contents + irel->r_offset - 2) == 0x8b) + { + bfd_put_8 (output_bfd, 0x8d, + contents + irel->r_offset - 2); + irel->r_info = htab->r_info (r_symndx, R_X86_64_PC32); + if (local_got_refcounts != NULL + && local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx] -= 1; + changed_contents = TRUE; + changed_relocs = TRUE; + } + continue; + } + + indx = r_symndx - symtab_hdr->sh_info; + h = elf_sym_hashes (abfd)[indx]; + BFD_ASSERT (h != NULL); + + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + /* STT_GNU_IFUNC must keep R_X86_64_GOTPCREL relocation. We also + avoid optimizing _DYNAMIC since ld.so may use its link-time + address. */ + if (h->def_regular + && h->type != STT_GNU_IFUNC + && h != htab->elf.hdynamic + && SYMBOL_REFERENCES_LOCAL (link_info, h) + && bfd_get_8 (input_bfd, + contents + irel->r_offset - 2) == 0x8b) + { + bfd_put_8 (output_bfd, 0x8d, + contents + irel->r_offset - 2); + irel->r_info = htab->r_info (r_symndx, R_X86_64_PC32); + if (h->got.refcount > 0) + h->got.refcount -= 1; + changed_contents = TRUE; + changed_relocs = TRUE; + } + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (!changed_contents && !link_info->keep_memory) + free (contents); + else + { + /* Cache the section contents for elf_link_input_bfd. */ + elf_section_data (sec)->this_hdr.contents = contents; + } + } + + if (elf_section_data (sec)->relocs != internal_relocs) + { + if (!changed_relocs) + free (internal_relocs); + else + elf_section_data (sec)->relocs = internal_relocs; + } + + return TRUE; + + error_return: + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + return FALSE; +} + /* Set the sizes of the dynamic sections. */ static bfd_boolean @@ -2606,7 +2715,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, /* Set the contents of the .interp section to the interpreter. */ if (info->executable) { - s = bfd_get_section_by_name (dynobj, ".interp"); + s = bfd_get_linker_section (dynobj, ".interp"); if (s == NULL) abort (); s->size = htab->dynamic_interpreter_size; @@ -2633,6 +2742,9 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, { struct elf_dyn_relocs *p; + if (!elf_x86_64_convert_mov_to_lea (ibfd, s, info)) + return FALSE; + for (p = (struct elf_dyn_relocs *) (elf_section_data (s)->local_dynrel); p != NULL; @@ -2773,15 +2885,10 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, if (htab->elf.sgotplt) { - struct elf_link_hash_entry *got; - got = elf_link_hash_lookup (elf_hash_table (info), - "_GLOBAL_OFFSET_TABLE_", - FALSE, FALSE, FALSE); - /* Don't allocate .got.plt section if there are no GOT nor PLT entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */ - if ((got == NULL - || !got->ref_regular_nonweak) + if ((htab->elf.hgot == NULL + || !htab->elf.hgot->ref_regular_nonweak) && (htab->elf.sgotplt->size == get_elf_backend_data (output_bfd)->got_header_size) && (htab->elf.splt == NULL @@ -2795,6 +2902,17 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, htab->elf.sgotplt->size = 0; } + if (htab->plt_eh_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && !bfd_is_abs_section (htab->elf.splt->output_section) + && _bfd_elf_eh_frame_present (info)) + { + const struct elf_x86_64_backend_data *arch_data + = (const struct elf_x86_64_backend_data *) bed->arch_data; + htab->plt_eh_frame->size = arch_data->eh_frame_plt_size; + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = FALSE; @@ -2808,6 +2926,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, || s == htab->elf.sgotplt || s == htab->elf.iplt || s == htab->elf.igotplt + || s == htab->plt_eh_frame || s == htab->sdynbss) { /* Strip this section if we don't need it; see the @@ -2859,11 +2978,16 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, } if (htab->plt_eh_frame != NULL - && htab->elf.splt != NULL - && htab->elf.splt->size != 0 - && (htab->elf.splt->flags & SEC_EXCLUDE) == 0) - bfd_put_32 (dynobj, htab->elf.splt->size, - htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + && htab->plt_eh_frame->contents != NULL) + { + const struct elf_x86_64_backend_data *arch_data + = (const struct elf_x86_64_backend_data *) bed->arch_data; + + memcpy (htab->plt_eh_frame->contents, + arch_data->eh_frame_plt, htab->plt_eh_frame->size); + bfd_put_32 (dynobj, htab->elf.splt->size, + htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + } if (htab->elf.dynamic_sections_created) { @@ -3088,14 +3212,18 @@ elf_x86_64_relocate_section (bfd *output_bfd, bfd_reloc_status_type r; int tls_type; asection *base_got; + bfd_vma st_size; r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_X86_64_GNU_VTINHERIT || r_type == (int) R_X86_64_GNU_VTENTRY) continue; - if (r_type >= R_X86_64_max) + if (r_type >= (int) R_X86_64_standard) { + (*_bfd_error_handler) + (_("%B: unrecognized relocation (0x%x) in section `%A'"), + input_bfd, input_section, r_type); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -3118,6 +3246,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); + st_size = sym->st_size; /* Relocate against local STT_GNU_IFUNC symbol. */ if (!info->relocatable @@ -3141,6 +3270,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, unresolved_reloc, warned); + st_size = h->size; } if (sec != NULL && discarded_section (sec)) @@ -3150,14 +3280,22 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (info->relocatable) continue; - if (rel->r_addend == 0 - && r_type == R_X86_64_64 - && !ABI_64_P (output_bfd)) + if (rel->r_addend == 0 && !ABI_64_P (output_bfd)) { - /* For x32, treat R_X86_64_64 like R_X86_64_32 and zero-extend - it to 64bit if addend is zero. */ - r_type = R_X86_64_32; - memset (contents + rel->r_offset + 4, 0, 4); + if (r_type == R_X86_64_64) + { + /* For x32, treat R_X86_64_64 like R_X86_64_32 and + zero-extend it to 64bit if addend is zero. */ + r_type = R_X86_64_32; + memset (contents + rel->r_offset + 4, 0, 4); + } + else if (r_type == R_X86_64_SIZE64) + { + /* For x32, treat R_X86_64_SIZE64 like R_X86_64_SIZE32 and + zero-extend it to 64bit if addend is zero. */ + r_type = R_X86_64_SIZE32; + memset (contents + rel->r_offset + 4, 0, 4); + } } /* Since STT_GNU_IFUNC symbol must go through PLT, we handle @@ -3538,6 +3676,26 @@ elf_x86_64_relocate_section (bfd *output_bfd, unresolved_reloc = FALSE; break; + case R_X86_64_SIZE32: + case R_X86_64_SIZE64: + if (h + && h->type == STT_TLS + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->root.u.def.section->output_section != NULL + && htab->elf.tls_sec == NULL) + { + (*_bfd_error_handler) + (_("%B: `%s' accessed both as normal and thread local symbol"), + input_bfd, h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + /* Set to symbol size. */ + relocation = st_size; + goto direct; + case R_X86_64_PC8: case R_X86_64_PC16: case R_X86_64_PC32: @@ -3610,6 +3768,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, /* FIXME: The ABI says the linker should make sure the value is the same when it's zeroextended to 64 bit. */ +direct: if ((input_section->flags & SEC_ALLOC) == 0) break; @@ -3617,7 +3776,9 @@ elf_x86_64_relocate_section (bfd *output_bfd, && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) - && (! IS_X86_64_PCREL_TYPE (r_type) + && ((! IS_X86_64_PCREL_TYPE (r_type) + && r_type != R_X86_64_SIZE32 + && r_type != R_X86_64_SIZE64) || ! SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared @@ -3686,19 +3847,28 @@ elf_x86_64_relocate_section (bfd *output_bfd, != (rel->r_addend & 0x80000000)) { const char *name; + int addend = rel->r_addend; if (h && h->root.root.string) name = h->root.root.string; else name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL); - (*_bfd_error_handler) - (_("%B: addend %ld in relocation %s against " - "symbol `%s' at 0x%lx in section `%A' is " - "out of range"), - input_bfd, input_section, - (long) rel->r_addend, - x86_64_elf_howto_table[r_type].name, - name, (unsigned long) rel->r_offset); + if (addend < 0) + (*_bfd_error_handler) + (_("%B: addend -0x%x in relocation %s against " + "symbol `%s' at 0x%lx in section `%A' is " + "out of range"), + input_bfd, input_section, addend, + x86_64_elf_howto_table[r_type].name, + name, (unsigned long) rel->r_offset); + else + (*_bfd_error_handler) + (_("%B: addend 0x%x in relocation %s against " + "symbol `%s' at 0x%lx in section `%A' is " + "out of range"), + input_bfd, input_section, addend, + x86_64_elf_howto_table[r_type].name, + name, (unsigned long) rel->r_offset); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -4191,13 +4361,16 @@ elf_x86_64_relocate_section (bfd *output_bfd, && h->def_dynamic) && _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset) != (bfd_vma) -1) - (*_bfd_error_handler) - (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), - input_bfd, - input_section, - (long) rel->r_offset, - howto->name, - h->root.root.string); + { + (*_bfd_error_handler) + (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + input_bfd, + input_section, + (long) rel->r_offset, + howto->name, + h->root.root.string); + return FALSE; + } do_relocation: r = _bfd_final_link_relocate (howto, input_bfd, input_section, @@ -4251,7 +4424,7 @@ static bfd_boolean elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym) + Elf_Internal_Sym *sym ATTRIBUTE_UNUSED) { struct elf_x86_64_link_hash_table *htab; const struct elf_x86_64_backend_data *const abed @@ -4294,7 +4467,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, || plt == NULL || gotplt == NULL || relplt == NULL) - return FALSE; + abort (); /* Get the index in the procedure linkage table which corresponds to this symbol. This is the index of this symbol @@ -4490,13 +4663,6 @@ do_glob_dat: elf_append_rela (output_bfd, htab->srelbss, &rela); } - /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. SYM may - be NULL for local symbols. */ - if (sym != NULL - && (strcmp (h->root.root.string, "_DYNAMIC") == 0 - || h == htab->elf.hgot)) - sym->st_shndx = SHN_ABS; - return TRUE; } @@ -4552,7 +4718,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, return FALSE; dynobj = htab->elf.dynobj; - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); if (htab->elf.dynamic_sections_created) { @@ -4721,7 +4887,8 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, } /* Adjust .eh_frame for .plt section. */ - if (htab->plt_eh_frame != NULL) + if (htab->plt_eh_frame != NULL + && htab->plt_eh_frame->contents != NULL) { if (htab->elf.splt != NULL && htab->elf.splt->size != 0