glibc.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include <elf.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdlib.h>
  5. #include <sys/stat.h>
  6. #include <sys/types.h>
  7. #include <unistd.h>
  8. #include "glibc.h"
  9. #include "features.h"
  10. namespace {
  11. void ReadAuxVector(Elf64_auxv_t** begin, Elf64_auxv_t** end) noexcept {
  12. int fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC);
  13. if (fd == -1) {
  14. return;
  15. }
  16. constexpr size_t item_size = sizeof(Elf64_auxv_t);
  17. constexpr size_t block_size = item_size * 32;
  18. size_t bytes_read = 0;
  19. size_t size = 0;
  20. struct TBuffer {
  21. ~TBuffer() {
  22. free(Pointer);
  23. }
  24. char* Pointer = nullptr;
  25. } buffer;
  26. while (true) {
  27. size_t bytes_left = size - bytes_read;
  28. if (!bytes_left) {
  29. size += block_size;
  30. char* new_buffer = (char*)realloc(buffer.Pointer, size);
  31. if (!new_buffer) {
  32. return;
  33. }
  34. buffer.Pointer = new_buffer;
  35. continue;
  36. }
  37. ssize_t r = read(fd, buffer.Pointer + bytes_read, bytes_left);
  38. if (!r) {
  39. break;
  40. } else if (r < 0) {
  41. if (errno == EINTR) {
  42. continue;
  43. } else {
  44. return;
  45. }
  46. }
  47. bytes_read += r;
  48. }
  49. size_t item_count = bytes_read / item_size;
  50. *begin = (Elf64_auxv_t*)buffer.Pointer;
  51. *end = (Elf64_auxv_t*)(buffer.Pointer + item_count * item_size);
  52. buffer.Pointer = nullptr;
  53. }
  54. }
  55. extern "C" {
  56. weak unsigned long __getauxval(unsigned long item);
  57. }
  58. namespace NUbuntuCompat {
  59. TGlibc::TGlibc() noexcept
  60. : AuxVectorBegin(nullptr)
  61. , AuxVectorEnd(nullptr)
  62. {
  63. if (!__getauxval) {
  64. ReadAuxVector((Elf64_auxv_t**)&AuxVectorBegin, (Elf64_auxv_t**)&AuxVectorEnd);
  65. }
  66. Secure = (bool)GetAuxVal(AT_SECURE);
  67. }
  68. TGlibc::~TGlibc() noexcept {
  69. free(AuxVectorBegin);
  70. }
  71. unsigned long TGlibc::GetAuxVal(unsigned long item) noexcept {
  72. if (__getauxval) {
  73. return __getauxval(item);
  74. }
  75. for (Elf64_auxv_t* p = (Elf64_auxv_t*)AuxVectorBegin; p < (Elf64_auxv_t*)AuxVectorEnd; ++p) {
  76. if (p->a_type == item) {
  77. return p->a_un.a_val;
  78. }
  79. }
  80. errno = ENOENT;
  81. return 0;
  82. }
  83. bool TGlibc::IsSecure() noexcept {
  84. return Secure;
  85. }
  86. static TGlibc __attribute__((__init_priority__(101))) GlibcInstance;
  87. TGlibc& GetGlibc() noexcept {
  88. return GlibcInstance;
  89. }
  90. }