X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfnn-riscv.c;h=46f0100ace3da966ee94932df17cfc1721266451;hb=27eea7ff8e66a9e317e00f949e3e7cedf78946b9;hp=4ffe6a36e68f6c6c8e2301627dceedfef908f2db;hpb=9d1da81b261a20050ef2ad01a5b4c8cf78404222;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 4ffe6a36e6..46f0100ace 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -1,5 +1,5 @@ /* RISC-V-specific support for NN-bit ELF. - Copyright (C) 2011-2019 Free Software Foundation, Inc. + Copyright (C) 2011-2020 Free Software Foundation, Inc. Contributed by Andrew Waterman (andrew@sifive.com). Based on TILE-Gx and MIPS targets. @@ -1787,6 +1787,7 @@ riscv_elf_relocate_section (bfd *output_bfd, int r_type = ELFNN_R_TYPE (rel->r_info), tls_type; reloc_howto_type *howto = riscv_elf_rtype_to_howto (input_bfd, r_type); const char *msg = NULL; + char *msg_buf = NULL; bfd_boolean resolved_to_zero; if (howto == NULL @@ -1986,10 +1987,11 @@ riscv_elf_relocate_section (bfd *output_bfd, break; case R_RISCV_CALL: + case R_RISCV_CALL_PLT: /* Handle a call to an undefined weak function. This won't be relaxed, so we have to handle it here. */ if (h != NULL && h->root.type == bfd_link_hash_undefweak - && h->plt.offset == MINUS_ONE) + && (!bfd_link_pic (info) || h->plt.offset == MINUS_ONE)) { /* We can use x0 as the base register. */ bfd_vma insn = bfd_get_32 (input_bfd, @@ -2002,9 +2004,9 @@ riscv_elf_relocate_section (bfd *output_bfd, } /* Fall through. */ - case R_RISCV_CALL_PLT: case R_RISCV_JAL: case R_RISCV_RVC_JUMP: + /* This line has to match the check in _bfd_riscv_relax_section. */ if (bfd_link_pic (info) && h != NULL && h->plt.offset != MINUS_ONE) { /* Refer to the PLT entry. */ @@ -2088,6 +2090,7 @@ riscv_elf_relocate_section (bfd *output_bfd, || (h != NULL && h->type == STT_SECTION)) && rel->r_addend) { + msg = _("%pcrel_lo section symbol with an addend"); r = bfd_reloc_dangerous; break; } @@ -2302,24 +2305,42 @@ riscv_elf_relocate_section (bfd *output_bfd, && _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset) != (bfd_vma) -1) { - (*_bfd_error_handler) - (_("%pB(%pA+%#" PRIx64 "): " - "unresolvable %s relocation against symbol `%s'"), - input_bfd, - input_section, - (uint64_t) rel->r_offset, - howto->name, - h->root.root.string); - - bfd_set_error (bfd_error_bad_value); - ret = FALSE; - goto out; + switch (r_type) + { + case R_RISCV_CALL: + case R_RISCV_JAL: + case R_RISCV_RVC_JUMP: + if (asprintf (&msg_buf, + _("%%X%%P: relocation %s against `%s' can " + "not be used when making a shared object; " + "recompile with -fPIC\n"), + howto->name, + h->root.root.string) == -1) + msg_buf = NULL; + break; + + default: + if (asprintf (&msg_buf, + _("%%X%%P: unresolvable %s relocation against " + "symbol `%s'\n"), + howto->name, + h->root.root.string) == -1) + msg_buf = NULL; + break; + } + + msg = msg_buf; + r = bfd_reloc_notsupported; } if (r == bfd_reloc_ok) r = perform_relocation (howto, rel, relocation, input_section, input_bfd, contents); + /* We should have already detected the error and set message before. + If the error message isn't set since the linker runs out of memory + or we don't set it before, then we should set the default message + with the "internal error" string here. */ switch (r) { case bfd_reloc_ok: @@ -2338,17 +2359,21 @@ riscv_elf_relocate_section (bfd *output_bfd, break; case bfd_reloc_outofrange: - msg = _("%X%P: internal error: out of range error\n"); + if (msg == NULL) + msg = _("%X%P: internal error: out of range error\n"); break; case bfd_reloc_notsupported: - msg = _("%X%P: internal error: unsupported relocation error\n"); + if (msg == NULL) + msg = _("%X%P: internal error: unsupported relocation error\n"); break; case bfd_reloc_dangerous: + /* The error message should already be set. */ + if (msg == NULL) + msg = _("dangerous relocation error"); info->callbacks->reloc_dangerous - (info, "%pcrel_lo section symbol with an addend", input_bfd, - input_section, rel->r_offset); + (info, msg, input_bfd, input_section, rel->r_offset); break; default: @@ -2356,9 +2381,14 @@ riscv_elf_relocate_section (bfd *output_bfd, break; } - if (msg) + /* Do not report error message for the dangerous relocation again. */ + if (msg && r != bfd_reloc_dangerous) info->callbacks->einfo (msg); + /* Free the unused `msg_buf` if needed. */ + if (msg_buf) + free (msg_buf); + /* We already reported the error via a callback, so don't try to report it again by returning false. That leads to spurious errors. */ ret = TRUE; @@ -3465,9 +3495,16 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec, int rd, r_type, len = 4, rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC; /* If the call crosses section boundaries, an alignment directive could - cause the PC-relative offset to later increase. */ - if (VALID_UJTYPE_IMM (foff) && sym_sec->output_section != sec->output_section) - foff += (foff < 0 ? -max_alignment : max_alignment); + cause the PC-relative offset to later increase, so we need to add in the + max alignment of any section inclusive from the call to the target. + Otherwise, we only need to use the alignment of the current section. */ + if (VALID_UJTYPE_IMM (foff)) + { + if (sym_sec->output_section == sec->output_section + && sym_sec->output_section != bfd_abs_section_ptr) + max_alignment = (bfd_vma) 1 << sym_sec->output_section->alignment_power; + foff += (foff < 0 ? -max_alignment : max_alignment); + } /* See if this function call can be shortened. */ if (!VALID_UJTYPE_IMM (foff) && !(!bfd_link_pic (link_info) && near_zero)) @@ -4092,7 +4129,9 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, undefined_weak = TRUE; } - if (h->plt.offset != MINUS_ONE) + /* This line has to match the check in riscv_elf_relocate_section + in the R_RISCV_CALL[_PLT] case. */ + if (bfd_link_pic (info) && h->plt.offset != MINUS_ONE) { sym_sec = htab->elf.splt; symval = h->plt.offset;