aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNelson Chu <nelson@rivosinc.com>2024-04-29 17:44:51 +0800
committerNelson Chu <nelson@rivosinc.com>2024-05-28 01:38:17 +0800
commit1d7a877a0f74a7b90d70ca8cc3c0db9461619b1a (patch)
tree1e179925fd667b8424bd753f08b888f7c825c10a
parent6f779908fd6d7c85197ab13949a9dc5e6d4f1458 (diff)
downloadbinutils-1d7a877a0f74a7b90d70ca8cc3c0db9461619b1a.zip
binutils-1d7a877a0f74a7b90d70ca8cc3c0db9461619b1a.tar.gz
binutils-1d7a877a0f74a7b90d70ca8cc3c0db9461619b1a.tar.bz2
RISC-V: Segment fault for kernel purgatory when linking.
This was originally reported by Ard Biesheuvel <ardb@kernel.org>. The followings are reproduce steps, https://lore.kernel.org/all/202404260640.9GQVTmrw-lkp@intel.com/T/#u The segment fault happens in the riscv_elf_finish_dynamic_sections when the output got section is an ABS. Refer to MIPS code, they added an extra bfd_is_abs_section check to avoid ABS got, so this seems the right and easier way to go in the short-term. bfd/ * elfnn-riscv.c (riscv_elf_finish_dynamic_sections): Set sh_entsize and fill the got entries only when the got isn't an ABS section, and the size of got is larger than zero. The similar goes for gotplt, except we already reported error when the gotplt is an ABS.
-rw-r--r--bfd/elfnn-riscv.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 604f6de..3fc8726 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3569,7 +3569,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
}
}
- if (htab->elf.sgotplt)
+ if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
{
asection *output_section = htab->elf.sgotplt->output_section;
@@ -3580,31 +3580,28 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
return false;
}
- if (htab->elf.sgotplt->size > 0)
- {
- /* Write the first two entries in .got.plt, needed for the dynamic
- linker. */
- bfd_put_NN (output_bfd, (bfd_vma) -1, htab->elf.sgotplt->contents);
- bfd_put_NN (output_bfd, (bfd_vma) 0,
- htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
- }
+ /* Write the first two entries in .got.plt, needed for the dynamic
+ linker. */
+ bfd_put_NN (output_bfd, (bfd_vma) -1, htab->elf.sgotplt->contents);
+ bfd_put_NN (output_bfd, (bfd_vma) 0,
+ htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
}
- if (htab->elf.sgot)
+ if (htab->elf.sgot && htab->elf.sgot->size > 0)
{
asection *output_section = htab->elf.sgot->output_section;
- if (htab->elf.sgot->size > 0)
+ if (!bfd_is_abs_section (output_section))
{
/* Set the first entry in the global offset table to the address of
the dynamic section. */
bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
- }
- elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
+ elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
+ }
}
/* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */