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