18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <errno.h> 38c2ecf20Sopenharmony_ci#include <linux/unistd.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <sys/ptrace.h> 68c2ecf20Sopenharmony_ci#include <sys/syscall.h> 78c2ecf20Sopenharmony_ci#include <unistd.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <sysdep/tls.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#ifndef PTRACE_GET_THREAD_AREA 128c2ecf20Sopenharmony_ci#define PTRACE_GET_THREAD_AREA 25 138c2ecf20Sopenharmony_ci#endif 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifndef PTRACE_SET_THREAD_AREA 168c2ecf20Sopenharmony_ci#define PTRACE_SET_THREAD_AREA 26 178c2ecf20Sopenharmony_ci#endif 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* Checks whether host supports TLS, and sets *tls_min according to the value 208c2ecf20Sopenharmony_ci * valid on the host. 218c2ecf20Sopenharmony_ci * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */ 228c2ecf20Sopenharmony_civoid check_host_supports_tls(int *supports_tls, int *tls_min) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci /* Values for x86 and x86_64.*/ 258c2ecf20Sopenharmony_ci int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64}; 268c2ecf20Sopenharmony_ci int i; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(val); i++) { 298c2ecf20Sopenharmony_ci user_desc_t info; 308c2ecf20Sopenharmony_ci info.entry_number = val[i]; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci if (syscall(__NR_get_thread_area, &info) == 0) { 338c2ecf20Sopenharmony_ci *tls_min = val[i]; 348c2ecf20Sopenharmony_ci *supports_tls = 1; 358c2ecf20Sopenharmony_ci return; 368c2ecf20Sopenharmony_ci } else { 378c2ecf20Sopenharmony_ci if (errno == EINVAL) 388c2ecf20Sopenharmony_ci continue; 398c2ecf20Sopenharmony_ci else if (errno == ENOSYS) 408c2ecf20Sopenharmony_ci *supports_tls = 0; 418c2ecf20Sopenharmony_ci return; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci *supports_tls = 0; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciint os_set_thread_area(user_desc_t *info, int pid) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci int ret; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number, 538c2ecf20Sopenharmony_ci (unsigned long) info); 548c2ecf20Sopenharmony_ci if (ret < 0) 558c2ecf20Sopenharmony_ci ret = -errno; 568c2ecf20Sopenharmony_ci return ret; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ciint os_get_thread_area(user_desc_t *info, int pid) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci int ret; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number, 648c2ecf20Sopenharmony_ci (unsigned long) info); 658c2ecf20Sopenharmony_ci if (ret < 0) 668c2ecf20Sopenharmony_ci ret = -errno; 678c2ecf20Sopenharmony_ci return ret; 688c2ecf20Sopenharmony_ci} 69