1 1.13 christos /* $NetBSD: t_ifunc.c,v 1.13 2022/06/21 16:24:37 christos Exp $ */ 2 1.1 joerg 3 1.1 joerg /* 4 1.1 joerg * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 1.1 joerg * All rights reserved. 6 1.1 joerg * 7 1.1 joerg * Redistribution and use in source and binary forms, with or without 8 1.1 joerg * modification, are permitted provided that the following conditions 9 1.1 joerg * are met: 10 1.1 joerg * 1. Redistributions of source code must retain the above copyright 11 1.1 joerg * notice, this list of conditions and the following disclaimer. 12 1.1 joerg * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 joerg * notice, this list of conditions and the following disclaimer in the 14 1.1 joerg * documentation and/or other materials provided with the distribution. 15 1.1 joerg * 16 1.1 joerg * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17 1.1 joerg * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 1.1 joerg * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 1.1 joerg * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.1 joerg * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21 1.1 joerg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 1.1 joerg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 1.1 joerg * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 joerg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 1.1 joerg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 1.1 joerg * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 1.1 joerg * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 joerg */ 29 1.1 joerg 30 1.1 joerg #include <sys/types.h> 31 1.1 joerg 32 1.1 joerg #include <atf-c.h> 33 1.1 joerg #include <dlfcn.h> 34 1.1 joerg #include <util.h> 35 1.1 joerg 36 1.2 christos #include "h_macros.h" 37 1.1 joerg 38 1.11 skrll #if \ 39 1.12 skrll defined(__aarch64__) || \ 40 1.11 skrll defined(__arm__) || \ 41 1.11 skrll defined(__i386__) || \ 42 1.13 christos defined(__powerpc__) || \ 43 1.11 skrll defined(__sparc__) || \ 44 1.11 skrll defined(__x86_64__) 45 1.7 maya #define LINKER_SUPPORT 1 46 1.6 martin #else 47 1.7 maya #define LINKER_SUPPORT 0 48 1.6 martin #endif 49 1.6 martin 50 1.1 joerg ATF_TC(rtld_ifunc); 51 1.1 joerg 52 1.1 joerg ATF_TC_HEAD(rtld_ifunc, tc) 53 1.1 joerg { 54 1.1 joerg atf_tc_set_md_var(tc, "descr", "ifunc functions are resolved"); 55 1.1 joerg } 56 1.1 joerg 57 1.1 joerg ATF_TC_BODY(rtld_ifunc, tc) 58 1.1 joerg { 59 1.1 joerg const char *envstr[] = { 60 1.1 joerg "0", "1" 61 1.1 joerg }; 62 1.8 joerg long long expected_result[] = { 63 1.8 joerg 0xdeadbeefll, 0xbeefdeadll 64 1.1 joerg }; 65 1.1 joerg void *handle; 66 1.8 joerg long long (*sym)(void); 67 1.8 joerg long long result; 68 1.1 joerg const char *error; 69 1.1 joerg size_t i; 70 1.1 joerg 71 1.7 maya if (!LINKER_SUPPORT) 72 1.7 maya atf_tc_skip("Missing linker support for ifunc relocations"); 73 1.3 joerg 74 1.1 joerg for (i = 0; i < __arraycount(envstr); ++i) { 75 1.1 joerg setenv("USE_IFUNC2", envstr[i], 1); 76 1.1 joerg 77 1.1 joerg handle = dlopen("libh_helper_ifunc_dso.so", RTLD_LAZY); 78 1.1 joerg error = dlerror(); 79 1.1 joerg ATF_CHECK(error == NULL); 80 1.1 joerg ATF_CHECK(handle != NULL); 81 1.1 joerg 82 1.1 joerg sym = dlsym(handle, "ifunc"); 83 1.1 joerg error = dlerror(); 84 1.1 joerg ATF_CHECK(error == NULL); 85 1.1 joerg ATF_CHECK(sym != NULL); 86 1.1 joerg 87 1.1 joerg result = (*sym)(); 88 1.1 joerg ATF_CHECK(result == expected_result[i]); 89 1.1 joerg 90 1.1 joerg dlclose(handle); 91 1.1 joerg error = dlerror(); 92 1.1 joerg ATF_CHECK(error == NULL); 93 1.1 joerg 94 1.1 joerg char *command; 95 1.8 joerg easprintf(&command, "%s/h_ifunc %lld", 96 1.1 joerg atf_tc_get_config_var(tc, "srcdir"), expected_result[i]); 97 1.1 joerg if (system(command) != EXIT_SUCCESS) 98 1.1 joerg atf_tc_fail("Test failed; see output for details"); 99 1.1 joerg free(command); 100 1.1 joerg } 101 1.1 joerg } 102 1.1 joerg 103 1.3 joerg ATF_TC(rtld_hidden_ifunc); 104 1.3 joerg 105 1.3 joerg ATF_TC_HEAD(rtld_hidden_ifunc, tc) 106 1.3 joerg { 107 1.3 joerg atf_tc_set_md_var(tc, "descr", "hidden ifunc functions are resolved"); 108 1.3 joerg } 109 1.3 joerg 110 1.3 joerg ATF_TC_BODY(rtld_hidden_ifunc, tc) 111 1.3 joerg { 112 1.3 joerg const char *envstr[] = { 113 1.3 joerg "0", "1" 114 1.3 joerg }; 115 1.8 joerg long long expected_result[] = { 116 1.8 joerg 0xdeadbeefll, 0xbeefdeadll 117 1.3 joerg }; 118 1.3 joerg void *handle; 119 1.8 joerg long long (*sym)(void); 120 1.8 joerg long long (*(*sym2)(void))(void); 121 1.8 joerg long long result; 122 1.3 joerg const char *error; 123 1.3 joerg size_t i; 124 1.3 joerg 125 1.7 maya if (!LINKER_SUPPORT) 126 1.7 maya atf_tc_skip("Missing linker support for ifunc relocations"); 127 1.6 martin 128 1.3 joerg for (i = 0; i < __arraycount(envstr); ++i) { 129 1.3 joerg setenv("USE_IFUNC2", envstr[i], 1); 130 1.3 joerg 131 1.3 joerg handle = dlopen("libh_helper_ifunc_dso.so", RTLD_LAZY); 132 1.3 joerg error = dlerror(); 133 1.3 joerg ATF_CHECK(error == NULL); 134 1.3 joerg ATF_CHECK(handle != NULL); 135 1.3 joerg 136 1.3 joerg sym = dlsym(handle, "ifunc_plt"); 137 1.3 joerg error = dlerror(); 138 1.3 joerg ATF_CHECK(error == NULL); 139 1.3 joerg ATF_CHECK(sym != NULL); 140 1.3 joerg 141 1.3 joerg result = (*sym)(); 142 1.3 joerg ATF_CHECK(result == expected_result[!i]); 143 1.3 joerg 144 1.4 joerg sym2 = dlsym(handle, "ifunc_indirect"); 145 1.4 joerg error = dlerror(); 146 1.4 joerg ATF_CHECK(error == NULL); 147 1.4 joerg ATF_CHECK(sym2 != NULL); 148 1.4 joerg 149 1.4 joerg sym = (*sym2)(); 150 1.4 joerg result = (*sym)(); 151 1.4 joerg ATF_CHECK(result == expected_result[!i]); 152 1.4 joerg 153 1.3 joerg dlclose(handle); 154 1.3 joerg error = dlerror(); 155 1.3 joerg ATF_CHECK(error == NULL); 156 1.3 joerg 157 1.3 joerg char *command; 158 1.8 joerg easprintf(&command, "%s/h_ifunc %lld", 159 1.3 joerg atf_tc_get_config_var(tc, "srcdir"), expected_result[i]); 160 1.3 joerg if (system(command) != EXIT_SUCCESS) 161 1.3 joerg atf_tc_fail("Test failed; see output for details"); 162 1.3 joerg free(command); 163 1.3 joerg } 164 1.3 joerg } 165 1.3 joerg 166 1.5 joerg ATF_TC(rtld_main_ifunc); 167 1.5 joerg ATF_TC_HEAD(rtld_main_ifunc, tc) 168 1.5 joerg { 169 1.5 joerg atf_tc_set_md_var(tc, "descr", 170 1.5 joerg "ifunc functions are resolved in the executable"); 171 1.5 joerg } 172 1.5 joerg 173 1.7 maya #if LINKER_SUPPORT 174 1.8 joerg static long long 175 1.5 joerg ifunc_helper(void) 176 1.5 joerg { 177 1.8 joerg return 0xdeadbeefll; 178 1.5 joerg } 179 1.5 joerg 180 1.5 joerg static __attribute__((used)) 181 1.8 joerg long long (*resolve_ifunc(void))(void) 182 1.5 joerg { 183 1.5 joerg return ifunc_helper; 184 1.5 joerg } 185 1.5 joerg __hidden_ifunc(ifunc, resolve_ifunc); 186 1.7 maya #endif 187 1.8 joerg long long ifunc(void); 188 1.5 joerg 189 1.5 joerg ATF_TC_BODY(rtld_main_ifunc, tc) 190 1.5 joerg { 191 1.7 maya if (!LINKER_SUPPORT) 192 1.7 maya atf_tc_skip("Missing linker support for ifunc relocations"); 193 1.8 joerg ATF_CHECK(ifunc() == 0xdeadbeefll); 194 1.5 joerg } 195 1.5 joerg 196 1.1 joerg ATF_TP_ADD_TCS(tp) 197 1.1 joerg { 198 1.1 joerg ATF_TP_ADD_TC(tp, rtld_ifunc); 199 1.3 joerg ATF_TP_ADD_TC(tp, rtld_hidden_ifunc); 200 1.5 joerg ATF_TP_ADD_TC(tp, rtld_main_ifunc); 201 1.9 maya return atf_no_error(); 202 1.1 joerg } 203