xref: /aosp_15_r20/bionic/tests/ifunc_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <sys/auxv.h>
20*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
21*8d67ca89SAndroid Build Coastguard Worker #include <sys/ifunc.h>
22*8d67ca89SAndroid Build Coastguard Worker #endif
23*8d67ca89SAndroid Build Coastguard Worker 
24*8d67ca89SAndroid Build Coastguard Worker typedef int (*fn_ptr_t)();
25*8d67ca89SAndroid Build Coastguard Worker 
ret42()26*8d67ca89SAndroid Build Coastguard Worker int ret42() {
27*8d67ca89SAndroid Build Coastguard Worker   return 42;
28*8d67ca89SAndroid Build Coastguard Worker }
29*8d67ca89SAndroid Build Coastguard Worker 
resolver()30*8d67ca89SAndroid Build Coastguard Worker extern "C" fn_ptr_t resolver() {
31*8d67ca89SAndroid Build Coastguard Worker   return ret42;
32*8d67ca89SAndroid Build Coastguard Worker }
33*8d67ca89SAndroid Build Coastguard Worker 
34*8d67ca89SAndroid Build Coastguard Worker int ifunc() __attribute__((ifunc("resolver")));
35*8d67ca89SAndroid Build Coastguard Worker 
TEST(ifunc,function)36*8d67ca89SAndroid Build Coastguard Worker TEST(ifunc, function) {
37*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(42, ifunc());
38*8d67ca89SAndroid Build Coastguard Worker }
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
41*8d67ca89SAndroid Build Coastguard Worker 
42*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
43*8d67ca89SAndroid Build Coastguard Worker 
44*8d67ca89SAndroid Build Coastguard Worker static uint64_t g_hwcap;
45*8d67ca89SAndroid Build Coastguard Worker static __ifunc_arg_t g_arg;
46*8d67ca89SAndroid Build Coastguard Worker 
hwcap_resolver(uint64_t hwcap,__ifunc_arg_t * arg)47*8d67ca89SAndroid Build Coastguard Worker extern "C" fn_ptr_t hwcap_resolver(uint64_t hwcap, __ifunc_arg_t* arg)
48*8d67ca89SAndroid Build Coastguard Worker     __attribute__((no_sanitize("hwaddress"))) {
49*8d67ca89SAndroid Build Coastguard Worker   g_hwcap = hwcap;
50*8d67ca89SAndroid Build Coastguard Worker   g_arg = *arg;
51*8d67ca89SAndroid Build Coastguard Worker   return ret42;
52*8d67ca89SAndroid Build Coastguard Worker }
53*8d67ca89SAndroid Build Coastguard Worker 
54*8d67ca89SAndroid Build Coastguard Worker #elif defined(__arm__)
55*8d67ca89SAndroid Build Coastguard Worker 
56*8d67ca89SAndroid Build Coastguard Worker static unsigned long g_hwcap;
57*8d67ca89SAndroid Build Coastguard Worker 
hwcap_resolver(unsigned long hwcap)58*8d67ca89SAndroid Build Coastguard Worker extern "C" fn_ptr_t hwcap_resolver(unsigned long hwcap) {
59*8d67ca89SAndroid Build Coastguard Worker   g_hwcap = hwcap;
60*8d67ca89SAndroid Build Coastguard Worker   return ret42;
61*8d67ca89SAndroid Build Coastguard Worker }
62*8d67ca89SAndroid Build Coastguard Worker 
63*8d67ca89SAndroid Build Coastguard Worker #elif defined(__riscv)
64*8d67ca89SAndroid Build Coastguard Worker 
65*8d67ca89SAndroid Build Coastguard Worker #include <sys/hwprobe.h>
66*8d67ca89SAndroid Build Coastguard Worker 
67*8d67ca89SAndroid Build Coastguard Worker static uint64_t g_hwcap;
68*8d67ca89SAndroid Build Coastguard Worker static __riscv_hwprobe_t g_hwprobe_ptr;
69*8d67ca89SAndroid Build Coastguard Worker static void* g_null;
70*8d67ca89SAndroid Build Coastguard Worker 
71*8d67ca89SAndroid Build Coastguard Worker static riscv_hwprobe g_hwprobes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0}};
72*8d67ca89SAndroid Build Coastguard Worker 
hwcap_resolver(uint64_t hwcap,__riscv_hwprobe_t hwprobe_ptr,void * null)73*8d67ca89SAndroid Build Coastguard Worker extern "C" fn_ptr_t hwcap_resolver(uint64_t hwcap, __riscv_hwprobe_t hwprobe_ptr, void* null) {
74*8d67ca89SAndroid Build Coastguard Worker   g_hwcap = hwcap;
75*8d67ca89SAndroid Build Coastguard Worker   g_hwprobe_ptr = hwprobe_ptr;
76*8d67ca89SAndroid Build Coastguard Worker   g_null = null;
77*8d67ca89SAndroid Build Coastguard Worker 
78*8d67ca89SAndroid Build Coastguard Worker   // Ensure that __riscv_hwprobe() can be called from an ifunc.
79*8d67ca89SAndroid Build Coastguard Worker   if ((*hwprobe_ptr)(g_hwprobes, 1, 0, nullptr, 0) != 0) return nullptr;
80*8d67ca89SAndroid Build Coastguard Worker   return ret42;
81*8d67ca89SAndroid Build Coastguard Worker }
82*8d67ca89SAndroid Build Coastguard Worker 
83*8d67ca89SAndroid Build Coastguard Worker #else
84*8d67ca89SAndroid Build Coastguard Worker 
hwcap_resolver()85*8d67ca89SAndroid Build Coastguard Worker extern "C" fn_ptr_t hwcap_resolver() {
86*8d67ca89SAndroid Build Coastguard Worker   return ret42;
87*8d67ca89SAndroid Build Coastguard Worker }
88*8d67ca89SAndroid Build Coastguard Worker 
89*8d67ca89SAndroid Build Coastguard Worker #endif
90*8d67ca89SAndroid Build Coastguard Worker 
91*8d67ca89SAndroid Build Coastguard Worker int hwcap() __attribute__((ifunc("hwcap_resolver")));
92*8d67ca89SAndroid Build Coastguard Worker 
TEST(ifunc,hwcap)93*8d67ca89SAndroid Build Coastguard Worker TEST(ifunc, hwcap) {
94*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(42, hwcap());
95*8d67ca89SAndroid Build Coastguard Worker 
96*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
97*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(getauxval(AT_HWCAP) | _IFUNC_ARG_HWCAP, g_hwcap);
98*8d67ca89SAndroid Build Coastguard Worker 
99*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(sizeof(__ifunc_arg_t), g_arg._size);
100*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(getauxval(AT_HWCAP), g_arg._hwcap);
101*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(getauxval(AT_HWCAP2), g_arg._hwcap2);
102*8d67ca89SAndroid Build Coastguard Worker #elif defined(__arm__)
103*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(getauxval(AT_HWCAP), g_hwcap);
104*8d67ca89SAndroid Build Coastguard Worker #elif defined(__riscv)
105*8d67ca89SAndroid Build Coastguard Worker   printf("hwcap=%lx hwprobe_ptr=%p (__riscv_hwprobe=%p) null=%p\n", g_hwcap, g_hwprobe_ptr,
106*8d67ca89SAndroid Build Coastguard Worker          __riscv_hwprobe, g_null);
107*8d67ca89SAndroid Build Coastguard Worker 
108*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(getauxval(AT_HWCAP), g_hwcap);
109*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, g_null);
110*8d67ca89SAndroid Build Coastguard Worker 
111*8d67ca89SAndroid Build Coastguard Worker   riscv_hwprobe probes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0}};
112*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, __riscv_hwprobe(probes, 1, 0, nullptr, 0));
113*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(probes[0].value, g_hwprobes[0].value);
114*8d67ca89SAndroid Build Coastguard Worker #endif
115*8d67ca89SAndroid Build Coastguard Worker }
116*8d67ca89SAndroid Build Coastguard Worker 
117*8d67ca89SAndroid Build Coastguard Worker #endif  // defined(__BIONIC__)
118