hwasan_globals.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //===-- hwasan_globals.cpp ------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of HWAddressSanitizer.
  10. //
  11. // HWAddressSanitizer globals-specific runtime.
  12. //===----------------------------------------------------------------------===//
  13. #include "hwasan_globals.h"
  14. #include "sanitizer_common/sanitizer_array_ref.h"
  15. namespace __hwasan {
  16. enum { NT_LLVM_HWASAN_GLOBALS = 3 };
  17. struct hwasan_global_note {
  18. s32 begin_relptr;
  19. s32 end_relptr;
  20. };
  21. // Check that the given library meets the code model requirements for tagged
  22. // globals. These properties are not checked at link time so they need to be
  23. // checked at runtime.
  24. static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr,
  25. ElfW(Half) phnum) {
  26. ElfW(Addr) min_addr = -1ull, max_addr = 0;
  27. for (unsigned i = 0; i != phnum; ++i) {
  28. if (phdr[i].p_type != PT_LOAD)
  29. continue;
  30. ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz;
  31. if (min_addr > lo)
  32. min_addr = lo;
  33. if (max_addr < hi)
  34. max_addr = hi;
  35. }
  36. if (max_addr - min_addr > 1ull << 32) {
  37. Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n");
  38. Die();
  39. }
  40. if (max_addr > 1ull << 48) {
  41. Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n");
  42. Die();
  43. }
  44. }
  45. ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base,
  46. const ElfW(Phdr) * phdr,
  47. ElfW(Half) phnum) {
  48. // Read the phdrs from this DSO.
  49. for (unsigned i = 0; i != phnum; ++i) {
  50. if (phdr[i].p_type != PT_NOTE)
  51. continue;
  52. const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr);
  53. const char *nend = note + phdr[i].p_memsz;
  54. // Traverse all the notes until we find a HWASan note.
  55. while (note < nend) {
  56. auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note);
  57. const char *name = note + sizeof(ElfW(Nhdr));
  58. const char *desc = name + RoundUpTo(nhdr->n_namesz, 4);
  59. // Discard non-HWASan-Globals notes.
  60. if (nhdr->n_type != NT_LLVM_HWASAN_GLOBALS ||
  61. internal_strcmp(name, "LLVM") != 0) {
  62. note = desc + RoundUpTo(nhdr->n_descsz, 4);
  63. continue;
  64. }
  65. // Only libraries with instrumented globals need to be checked against the
  66. // code model since they use relocations that aren't checked at link time.
  67. CheckCodeModel(base, phdr, phnum);
  68. auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc);
  69. auto *globals_begin = reinterpret_cast<const hwasan_global *>(
  70. note + global_note->begin_relptr);
  71. auto *globals_end = reinterpret_cast<const hwasan_global *>(
  72. note + global_note->end_relptr);
  73. return {globals_begin, globals_end};
  74. }
  75. }
  76. return {};
  77. }
  78. } // namespace __hwasan