tls.c 1.4 KB

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