1 // SPDX-License-Identifier: GPL-2.0 2 #include <errno.h> 3 #include <linux/unistd.h> 4 5 #include <sys/ptrace.h> 6 #include <sys/syscall.h> 7 #include <unistd.h> 8 9 #include <sysdep/tls.h> 10 11 #ifndef PTRACE_GET_THREAD_AREA 12 #define PTRACE_GET_THREAD_AREA 25 13 #endif 14 15 #ifndef PTRACE_SET_THREAD_AREA 16 #define PTRACE_SET_THREAD_AREA 26 17 #endif 18 19 /* Checks whether host supports TLS, and sets *tls_min according to the value 20 * valid on the host. 21 * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */ 22 void check_host_supports_tls(int *supports_tls, int *tls_min) 23 { 24 /* Values for x86 and x86_64.*/ 25 int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64}; 26 int i; 27 28 for (i = 0; i < ARRAY_SIZE(val); i++) { 29 user_desc_t info; 30 info.entry_number = val[i]; 31 32 if (syscall(__NR_get_thread_area, &info) == 0) { 33 *tls_min = val[i]; 34 *supports_tls = 1; 35 return; 36 } else { 37 if (errno == EINVAL) 38 continue; 39 else if (errno == ENOSYS) 40 *supports_tls = 0; 41 return; 42 } 43 } 44 45 *supports_tls = 0; 46 } 47 48 int os_set_thread_area(user_desc_t *info, int pid) 49 { 50 int ret; 51 52 ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number, 53 (unsigned long) info); 54 if (ret < 0) 55 ret = -errno; 56 return ret; 57 } 58 59 int os_get_thread_area(user_desc_t *info, int pid) 60 { 61 int ret; 62 63 ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number, 64 (unsigned long) info); 65 if (ret < 0) 66 ret = -errno; 67 return ret; 68 } 69