diff options
author | Xi Ruoyao <xry111@xry111.site> | 2024-06-30 15:18:21 +0800 |
---|---|---|
committer | liuzhensong <liuzhensong@loongson.cn> | 2024-07-05 12:11:10 +0800 |
commit | 1c31db21fe6555e1a9b2a33b95a0125250c517d8 (patch) | |
tree | c86134cf912d91bd775324deb17c5a244d0454f1 /bfd | |
parent | fc111d56dd5128d633201ef81f6e5dd5b86c24c1 (diff) | |
download | binutils-1c31db21fe6555e1a9b2a33b95a0125250c517d8.zip binutils-1c31db21fe6555e1a9b2a33b95a0125250c517d8.tar.gz binutils-1c31db21fe6555e1a9b2a33b95a0125250c517d8.tar.bz2 |
LoongArch: Reject R_LARCH_32 from becoming a runtime reloc in ELFCLASS64
We were converting R_LARCH_32 to R_LARCH_RELATIVE for ELFCLASS64:
$ cat t.s
.data
x:
.4byte x
.4byte 0xdeadbeef
$ as/as-new t.s -o t.o
$ ld/ld-new -shared t.o
$ objdump -R
a.out: file format elf64-loongarch
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00000000000001a8 R_LARCH_RELATIVE *ABS*+0x00000000000001a8
But this is just wrong: at runtime the dynamic linker will run
*(uintptr *)&x += load_address, clobbering the next 4 bytes of data
("0xdeadbeef" in the example).
If we keep the R_LARCH_32 reloc as-is in ELFCLASS64, it'll be rejected
by the Glibc dynamic linker anyway. And it does not make too much sense
to modify Glibc to support it. So we can just reject it like x86_64:
relocation R_X86_64_32 against `.data' can not be used when making a
shared object; recompile with -fPIC
or RISC-V:
relocation R_RISCV_32 against non-absolute symbol `a local symbol'
can not be used in RV64 when making a shared object
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/elfnn-loongarch.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index da84aab..41463ea 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -1036,8 +1036,32 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, only_need_pcrel = 1; break; - case R_LARCH_JUMP_SLOT: case R_LARCH_32: + if (ARCH_SIZE > 32 + && bfd_link_pic (info) + && (sec->flags & SEC_ALLOC) != 0) + { + bool is_abs_symbol = false; + + if (r_symndx < symtab_hdr->sh_info) + is_abs_symbol = isym->st_shndx == SHN_ABS; + else + is_abs_symbol = bfd_is_abs_symbol (&h->root); + + if (!is_abs_symbol) + { + _bfd_error_handler + (_("%pB: relocation R_LARCH_32 against non-absolute " + "symbol `%s' cannot be used in ELFCLASS64 when " + "making a shared object or PIE"), + abfd, h ? h->root.root.string : "a local symbol"); + bfd_set_error (bfd_error_bad_value); + return false; + } + } + + /* Fall through. */ + case R_LARCH_JUMP_SLOT: case R_LARCH_64: need_dynreloc = 1; @@ -2859,8 +2883,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, outrel.r_addend = relocation + rel->r_addend; } - /* No alloc space of func allocate_dynrelocs. */ + /* No alloc space of func allocate_dynrelocs. + No alloc space of invalid R_LARCH_32 in ELFCLASS64. */ if (unresolved_reloc + && (ARCH_SIZE == 32 || r_type != R_LARCH_32) && !(h && (h->is_weakalias || !h->dyn_relocs))) loongarch_elf_append_rela (output_bfd, sreloc, &outrel); } |