tls.c 1.3 KB

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