hwasan_globals.cpp 3.0 KB

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