From 16eb5139f16afc99365e68fd01d95c3647a66932 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 2 Oct 2024 19:57:03 +0900 Subject: [PATCH] [RISC-V] Set DT_RISCV_VARIANT_CC if there's a dynamic symbol with STO_RISCV_VARIANT_CC --- src/elf.h | 24 ++++++++++++++++++++---- src/output-chunks.cc | 16 ++++++++++++++++ test/arch-riscv64-variant-cc.sh | 21 +++++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100755 test/arch-riscv64-variant-cc.sh diff --git a/src/elf.h b/src/elf.h index 64bcdccbdd..ae17132a4b 100644 --- a/src/elf.h +++ b/src/elf.h @@ -296,6 +296,7 @@ enum : u32 { DT_VERNEEDNUM = 0x6fffffff, DT_PPC_GOT = 0x70000000, DT_PPC64_GLINK = 0x70000000, + DT_RISCV_VARIANT_CC = 0x70000001, DT_AARCH64_VARIANT_PCS = 0x70000005, DT_AUXILIARY = 0x7ffffffd, DT_FILTER = 0x7fffffff, @@ -1488,6 +1489,10 @@ struct ElfSym { u8 : 7; u8 arm64_variant_pcs : 1; }; + struct { + u8 : 7; + u8 riscv_variant_cc : 1; + }; struct { u8 : 5; u8 ppc64_local_entry : 3; @@ -1502,6 +1507,7 @@ struct ElfSym { u8 st_visibility : 2; }; u8 arm64_variant_pcs : 1; + u8 riscv_variant_cc : 1; u8 ppc64_local_entry : 3; }; #endif @@ -1526,13 +1532,23 @@ struct ElfSym { #ifdef __LITTLE_ENDIAN__ u8 st_type : 4; u8 st_bind : 4; - u8 st_visibility : 2; - u8 : 6; + union { + u8 st_visibility : 2; + struct { + u8 : 7; + u8 riscv_variant_cc : 1; + }; + }; #else u8 st_bind : 4; u8 st_type : 4; - u8 : 6; - u8 st_visibility : 2; + union { + struct { + u8 : 6; + u8 st_visibility : 2; + }; + u8 riscv_variant_cc : 1; + }; #endif U16 st_shndx; diff --git a/src/output-chunks.cc b/src/output-chunks.cc index 408183f03e..9a30c81dcb 100644 --- a/src/output-chunks.cc +++ b/src/output-chunks.cc @@ -674,6 +674,15 @@ static bool contains_variant_pcs(Context &ctx) { return false; } +// RISC-V has the same feature but with different names. +template +static bool contains_variant_cc(Context &ctx) { + for (Symbol *sym : ctx.plt->symbols) + if (sym->esym().riscv_variant_cc) + return true; + return false; +} + template static std::vector> create_dynamic_section(Context &ctx) { std::vector> vec; @@ -827,6 +836,10 @@ static std::vector> create_dynamic_section(Context &ctx) { if (contains_variant_pcs(ctx)) define(DT_AARCH64_VARIANT_PCS, 0); + if constexpr (is_riscv) + if (contains_variant_cc(ctx)) + define(DT_RISCV_VARIANT_CC, 0); + if constexpr (is_ppc32) define(DT_PPC_GOT, ctx.gotplt->shdr.sh_addr); @@ -1768,6 +1781,9 @@ ElfSym to_output_esym(Context &ctx, Symbol &sym, u32 st_name, if constexpr (is_arm64) esym.arm64_variant_pcs = sym.esym().arm64_variant_pcs; + if constexpr (is_riscv) + esym.riscv_variant_cc = sym.esym().riscv_variant_cc; + if constexpr (is_ppc64v2) esym.ppc64_local_entry = sym.esym().ppc64_local_entry; diff --git a/test/arch-riscv64-variant-cc.sh b/test/arch-riscv64-variant-cc.sh new file mode 100755 index 0000000000..af6a268312 --- /dev/null +++ b/test/arch-riscv64-variant-cc.sh @@ -0,0 +1,21 @@ +#!/bin/bash +. $(dirname $0)/common.inc + +cat < /dev/null || skip +.global foo +.type foo, %function +.variant_cc foo +foo: + ret +EOF + +$CC -B. -shared -o $t/b.so $t/a.o +readelf -W --dyn-syms $t/b.so | grep foo | grep -Fq '[VARIANT_CC]' + +cat <