summaryrefslogtreecommitdiff
path: root/compiler-rt/lib/hwasan
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/hwasan')
-rw-r--r--compiler-rt/lib/hwasan/hwasan.cpp140
-rw-r--r--compiler-rt/lib/hwasan/hwasan.h29
-rw-r--r--compiler-rt/lib/hwasan/hwasan_allocator.cpp2
-rw-r--r--compiler-rt/lib/hwasan/hwasan_flags.inc2
-rw-r--r--compiler-rt/lib/hwasan/hwasan_globals.cpp91
-rw-r--r--compiler-rt/lib/hwasan/hwasan_globals.h49
-rw-r--r--compiler-rt/lib/hwasan/hwasan_linux.cpp7
-rw-r--r--compiler-rt/lib/hwasan/hwasan_report.cpp106
-rw-r--r--compiler-rt/lib/hwasan/hwasan_thread.cpp6
-rw-r--r--compiler-rt/lib/hwasan/hwasan_thread.h14
10 files changed, 269 insertions, 177 deletions
diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp
index 7b5c6c694be9..d67a88d455ef 100644
--- a/compiler-rt/lib/hwasan/hwasan.cpp
+++ b/compiler-rt/lib/hwasan/hwasan.cpp
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#include "hwasan.h"
+
#include "hwasan_checks.h"
#include "hwasan_dynamic_shadow.h"
+#include "hwasan_globals.h"
#include "hwasan_poisoning.h"
#include "hwasan_report.h"
#include "hwasan_thread.h"
@@ -36,21 +38,6 @@ using namespace __sanitizer;
namespace __hwasan {
-void EnterSymbolizer() {
- Thread *t = GetCurrentThread();
- CHECK(t);
- t->EnterSymbolizer();
-}
-void ExitSymbolizer() {
- Thread *t = GetCurrentThread();
- CHECK(t);
- t->LeaveSymbolizer();
-}
-bool IsInSymbolizer() {
- Thread *t = GetCurrentThread();
- return t && t->InSymbolizer();
-}
-
static Flags hwasan_flags;
Flags *flags() {
@@ -201,108 +188,28 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(
uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
Thread *t = GetCurrentThread();
if (!t) {
- // the thread is still being created.
+ // The thread is still being created, or has already been destroyed.
size = 0;
return;
}
- if (!StackTrace::WillUseFastUnwind(request_fast)) {
- // Block reports from our interceptors during _Unwind_Backtrace.
- SymbolizerScope sym_scope;
- return Unwind(max_depth, pc, bp, context, 0, 0, request_fast);
- }
- if (StackTrace::WillUseFastUnwind(request_fast))
- Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true);
- else
- Unwind(max_depth, pc, 0, context, 0, 0, false);
-}
-
-struct hwasan_global {
- s32 gv_relptr;
- u32 info;
-};
-
-static void InitGlobals(const hwasan_global *begin, const hwasan_global *end) {
- for (auto *desc = begin; desc != end; ++desc) {
- uptr gv = reinterpret_cast<uptr>(desc) + desc->gv_relptr;
- uptr size = desc->info & 0xffffff;
- uptr full_granule_size = RoundDownTo(size, 16);
- u8 tag = desc->info >> 24;
- TagMemoryAligned(gv, full_granule_size, tag);
- if (size % 16)
- TagMemoryAligned(gv + full_granule_size, 16, size % 16);
- }
+ Unwind(max_depth, pc, bp, context, t->stack_top(), t->stack_bottom(),
+ request_fast);
}
-enum { NT_LLVM_HWASAN_GLOBALS = 3 };
-
-struct hwasan_global_note {
- s32 begin_relptr;
- s32 end_relptr;
-};
-
-// Check that the given library meets the code model requirements for tagged
-// globals. These properties are not checked at link time so they need to be
-// checked at runtime.
-static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr,
- ElfW(Half) phnum) {
- ElfW(Addr) min_addr = -1ull, max_addr = 0;
- for (unsigned i = 0; i != phnum; ++i) {
- if (phdr[i].p_type != PT_LOAD)
- continue;
- ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz;
- if (min_addr > lo)
- min_addr = lo;
- if (max_addr < hi)
- max_addr = hi;
- }
-
- if (max_addr - min_addr > 1ull << 32) {
- Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n");
- Die();
- }
- if (max_addr > 1ull << 48) {
- Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n");
- Die();
- }
-}
-
-static void InitGlobalsFromPhdrs(ElfW(Addr) base, const ElfW(Phdr) * phdr,
- ElfW(Half) phnum) {
- for (unsigned i = 0; i != phnum; ++i) {
- if (phdr[i].p_type != PT_NOTE)
- continue;
- const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr);
- const char *nend = note + phdr[i].p_memsz;
- while (note < nend) {
- auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note);
- const char *name = note + sizeof(ElfW(Nhdr));
- const char *desc = name + RoundUpTo(nhdr->n_namesz, 4);
- if (nhdr->n_type != NT_LLVM_HWASAN_GLOBALS ||
- internal_strcmp(name, "LLVM") != 0) {
- note = desc + RoundUpTo(nhdr->n_descsz, 4);
- continue;
- }
-
- // Only libraries with instrumented globals need to be checked against the
- // code model since they use relocations that aren't checked at link time.
- CheckCodeModel(base, phdr, phnum);
-
- auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc);
- auto *global_begin = reinterpret_cast<const hwasan_global *>(
- note + global_note->begin_relptr);
- auto *global_end = reinterpret_cast<const hwasan_global *>(
- note + global_note->end_relptr);
- InitGlobals(global_begin, global_end);
- return;
- }
- }
+static bool InitializeSingleGlobal(const hwasan_global &global) {
+ uptr full_granule_size = RoundDownTo(global.size(), 16);
+ TagMemoryAligned(global.addr(), full_granule_size, global.tag());
+ if (global.size() % 16)
+ TagMemoryAligned(global.addr() + full_granule_size, 16, global.size() % 16);
+ return false;
}
static void InitLoadedGlobals() {
dl_iterate_phdr(
- [](dl_phdr_info *info, size_t size, void *data) {
- InitGlobalsFromPhdrs(info->dlpi_addr, info->dlpi_phdr,
- info->dlpi_phnum);
+ [](dl_phdr_info *info, size_t /* size */, void * /* data */) -> int {
+ for (const hwasan_global &global : HwasanGlobalsFor(
+ info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum))
+ InitializeSingleGlobal(global);
return 0;
},
nullptr);
@@ -343,11 +250,13 @@ void __hwasan_init_static() {
// Fortunately, since this is a statically linked executable we can use the
// linker-defined symbol __ehdr_start to find the only relevant set of phdrs.
extern ElfW(Ehdr) __ehdr_start;
- InitGlobalsFromPhdrs(
- 0,
- reinterpret_cast<const ElfW(Phdr) *>(
- reinterpret_cast<const char *>(&__ehdr_start) + __ehdr_start.e_phoff),
- __ehdr_start.e_phnum);
+ for (const hwasan_global &global : HwasanGlobalsFor(
+ /* base */ 0,
+ reinterpret_cast<const ElfW(Phdr) *>(
+ reinterpret_cast<const char *>(&__ehdr_start) +
+ __ehdr_start.e_phoff),
+ __ehdr_start.e_phnum))
+ InitializeSingleGlobal(global);
}
void __hwasan_init() {
@@ -387,8 +296,6 @@ void __hwasan_init() {
InstallDeadlySignalHandlers(HwasanOnDeadlySignal);
InstallAtExitHandler(); // Needs __cxa_atexit interceptor.
- Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
-
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
HwasanTSDInit();
@@ -408,7 +315,8 @@ void __hwasan_init() {
void __hwasan_library_loaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
ElfW(Half) phnum) {
- InitGlobalsFromPhdrs(base, phdr, phnum);
+ for (const hwasan_global &global : HwasanGlobalsFor(base, phdr, phnum))
+ InitializeSingleGlobal(global);
}
void __hwasan_library_unloaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
diff --git a/compiler-rt/lib/hwasan/hwasan.h b/compiler-rt/lib/hwasan/hwasan.h
index 64cdcf30f5c7..8cbd9e74e335 100644
--- a/compiler-rt/lib/hwasan/hwasan.h
+++ b/compiler-rt/lib/hwasan/hwasan.h
@@ -72,16 +72,13 @@ extern int hwasan_inited;
extern bool hwasan_init_is_running;
extern int hwasan_report_count;
-bool ProtectRange(uptr beg, uptr end);
bool InitShadow();
void InitPrctl();
void InitThreads();
void MadviseShadow();
-char *GetProcSelfMaps();
void InitializeInterceptors();
void HwasanAllocatorInit();
-void HwasanAllocatorThreadFinish();
void *hwasan_malloc(uptr size, StackTrace *stack);
void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack);
@@ -95,24 +92,8 @@ int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size,
StackTrace *stack);
void hwasan_free(void *ptr, StackTrace *stack);
-void InstallTrapHandler();
void InstallAtExitHandler();
-void EnterSymbolizer();
-void ExitSymbolizer();
-bool IsInSymbolizer();
-
-struct SymbolizerScope {
- SymbolizerScope() { EnterSymbolizer(); }
- ~SymbolizerScope() { ExitSymbolizer(); }
-};
-
-// Returns a "chained" origin id, pointing to the given stack trace followed by
-// the previous origin id.
-u32 ChainOrigin(u32 id, StackTrace *stack);
-
-const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
-
#define GET_MALLOC_STACK_TRACE \
BufferedStackTrace stack; \
if (hwasan_inited) \
@@ -134,16 +115,6 @@ const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
stack.Print(); \
}
-class ScopedThreadLocalStateBackup {
- public:
- ScopedThreadLocalStateBackup() { Backup(); }
- ~ScopedThreadLocalStateBackup() { Restore(); }
- void Backup();
- void Restore();
- private:
- u64 va_arg_overflow_size_tls;
-};
-
void HwasanTSDInit();
void HwasanTSDThreadInit();
diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
index 81a57d3afd4d..1d82db0e3944 100644
--- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
@@ -363,7 +363,7 @@ int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size,
// OOM error is already taken care of by HwasanAllocate.
return errno_ENOMEM;
CHECK(IsAligned((uptr)ptr, alignment));
- *memptr = ptr;
+ *(void **)UntagPtr(memptr) = ptr;
return 0;
}
diff --git a/compiler-rt/lib/hwasan/hwasan_flags.inc b/compiler-rt/lib/hwasan/hwasan_flags.inc
index dffbf56cb155..8e431d9c4ff9 100644
--- a/compiler-rt/lib/hwasan/hwasan_flags.inc
+++ b/compiler-rt/lib/hwasan/hwasan_flags.inc
@@ -33,7 +33,7 @@ HWASAN_FLAG(bool, disable_allocator_tagging, false, "")
HWASAN_FLAG(bool, random_tags, true, "")
HWASAN_FLAG(
- int, max_malloc_fill_size, 0x1000, // By default, fill only the first 4K.
+ int, max_malloc_fill_size, 0,
"HWASan allocator flag. max_malloc_fill_size is the maximal amount of "
"bytes that will be filled with malloc_fill_byte on malloc.")
diff --git a/compiler-rt/lib/hwasan/hwasan_globals.cpp b/compiler-rt/lib/hwasan/hwasan_globals.cpp
new file mode 100644
index 000000000000..d71bcd792e1f
--- /dev/null
+++ b/compiler-rt/lib/hwasan/hwasan_globals.cpp
@@ -0,0 +1,91 @@
+//===-- hwasan_globals.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer globals-specific runtime.
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_globals.h"
+
+namespace __hwasan {
+
+enum { NT_LLVM_HWASAN_GLOBALS = 3 };
+struct hwasan_global_note {
+ s32 begin_relptr;
+ s32 end_relptr;
+};
+
+// Check that the given library meets the code model requirements for tagged
+// globals. These properties are not checked at link time so they need to be
+// checked at runtime.
+static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum) {
+ ElfW(Addr) min_addr = -1ull, max_addr = 0;
+ for (unsigned i = 0; i != phnum; ++i) {
+ if (phdr[i].p_type != PT_LOAD)
+ continue;
+ ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz;
+ if (min_addr > lo)
+ min_addr = lo;
+ if (max_addr < hi)
+ max_addr = hi;
+ }
+
+ if (max_addr - min_addr > 1ull << 32) {
+ Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n");
+ Die();
+ }
+ if (max_addr > 1ull << 48) {
+ Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n");
+ Die();
+ }
+}
+
+ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base,
+ const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum) {
+ // Read the phdrs from this DSO.
+ for (unsigned i = 0; i != phnum; ++i) {
+ if (phdr[i].p_type != PT_NOTE)
+ continue;
+
+ const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr);
+ const char *nend = note + phdr[i].p_memsz;
+
+ // Traverse all the notes until we find a HWASan note.
+ while (note < nend) {
+ auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note);
+ const char *name = note + sizeof(ElfW(Nhdr));
+ const char *desc = name + RoundUpTo(nhdr->n_namesz, 4);
+
+ // Discard non-HWASan-Globals notes.
+ if (nhdr->n_type != NT_LLVM_HWASAN_GLOBALS ||
+ internal_strcmp(name, "LLVM") != 0) {
+ note = desc + RoundUpTo(nhdr->n_descsz, 4);
+ continue;
+ }
+
+ // Only libraries with instrumented globals need to be checked against the
+ // code model since they use relocations that aren't checked at link time.
+ CheckCodeModel(base, phdr, phnum);
+
+ auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc);
+ auto *globals_begin = reinterpret_cast<const hwasan_global *>(
+ note + global_note->begin_relptr);
+ auto *globals_end = reinterpret_cast<const hwasan_global *>(
+ note + global_note->end_relptr);
+
+ return {globals_begin, globals_end};
+ }
+ }
+
+ return {};
+}
+
+} // namespace __hwasan
diff --git a/compiler-rt/lib/hwasan/hwasan_globals.h b/compiler-rt/lib/hwasan/hwasan_globals.h
new file mode 100644
index 000000000000..fd7adf7a0588
--- /dev/null
+++ b/compiler-rt/lib/hwasan/hwasan_globals.h
@@ -0,0 +1,49 @@
+//===-- hwasan_globals.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Private Hwasan header.
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_GLOBALS_H
+#define HWASAN_GLOBALS_H
+
+#include <link.h>
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __hwasan {
+// This object should only ever be casted over the global (i.e. not constructed)
+// in the ELF PT_NOTE in order for `addr()` to work correctly.
+struct hwasan_global {
+ // The size of this global variable. Note that the size in the descriptor is
+ // max 1 << 24. Larger globals have multiple descriptors.
+ uptr size() const { return info & 0xffffff; }
+ // The fully-relocated address of this global.
+ uptr addr() const { return reinterpret_cast<uintptr_t>(this) + gv_relptr; }
+ // The static tag of this global.
+ u8 tag() const { return info >> 24; };
+
+ // The relative address between the start of the descriptor for the HWASan
+ // global (in the PT_NOTE), and the fully relocated address of the global.
+ s32 gv_relptr;
+ u32 info;
+};
+
+// Walk through the specific DSO (as specified by the base, phdr, and phnum),
+// and return the range of the [beginning, end) of the HWASan globals descriptor
+// array.
+ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base,
+ const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum);
+
+} // namespace __hwasan
+
+#endif // HWASAN_GLOBALS_H
diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cpp b/compiler-rt/lib/hwasan/hwasan_linux.cpp
index ed0f30161b02..f1e830ddf901 100644
--- a/compiler-rt/lib/hwasan/hwasan_linux.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_linux.cpp
@@ -354,8 +354,11 @@ void AndroidTestTlsSlot() {}
#endif
Thread *GetCurrentThread() {
- auto *R = (StackAllocationsRingBuffer *)GetCurrentThreadLongPtr();
- return hwasanThreadList().GetThreadByBufferAddress((uptr)(R->Next()));
+ uptr *ThreadLongPtr = GetCurrentThreadLongPtr();
+ if (UNLIKELY(*ThreadLongPtr == 0))
+ return nullptr;
+ auto *R = (StackAllocationsRingBuffer *)ThreadLongPtr;
+ return hwasanThreadList().GetThreadByBufferAddress((uptr)R->Next());
}
struct AccessInfo {
diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index 5df8c0ac9106..206aa601903e 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -11,10 +11,14 @@
// Error reporting.
//===----------------------------------------------------------------------===//
+#include "hwasan_report.h"
+
+#include <dlfcn.h>
+
#include "hwasan.h"
#include "hwasan_allocator.h"
+#include "hwasan_globals.h"
#include "hwasan_mapping.h"
-#include "hwasan_report.h"
#include "hwasan_thread.h"
#include "hwasan_thread_list.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
@@ -122,21 +126,43 @@ class Decorator: public __sanitizer::SanitizerCommonDecorator {
const char *Thread() { return Green(); }
};
-// Returns the index of the rb element that matches tagged_addr (plus one),
-// or zero if found nothing.
-uptr FindHeapAllocation(HeapAllocationsRingBuffer *rb,
- uptr tagged_addr,
- HeapAllocationRecord *har) {
- if (!rb) return 0;
+static bool FindHeapAllocation(HeapAllocationsRingBuffer *rb, uptr tagged_addr,
+ HeapAllocationRecord *har, uptr *ring_index,
+ uptr *num_matching_addrs,
+ uptr *num_matching_addrs_4b) {
+ if (!rb) return false;
+
+ *num_matching_addrs = 0;
+ *num_matching_addrs_4b = 0;
for (uptr i = 0, size = rb->size(); i < size; i++) {
auto h = (*rb)[i];
if (h.tagged_addr <= tagged_addr &&
h.tagged_addr + h.requested_size > tagged_addr) {
*har = h;
- return i + 1;
+ *ring_index = i;
+ return true;
+ }
+
+ // Measure the number of heap ring buffer entries that would have matched
+ // if we had only one entry per address (e.g. if the ring buffer data was
+ // stored at the address itself). This will help us tune the allocator
+ // implementation for MTE.
+ if (UntagAddr(h.tagged_addr) <= UntagAddr(tagged_addr) &&
+ UntagAddr(h.tagged_addr) + h.requested_size > UntagAddr(tagged_addr)) {
+ ++*num_matching_addrs;
+ }
+
+ // Measure the number of heap ring buffer entries that would have matched
+ // if we only had 4 tag bits, which is the case for MTE.
+ auto untag_4b = [](uptr p) {
+ return p & ((1ULL << 60) - 1);
+ };
+ if (untag_4b(h.tagged_addr) <= untag_4b(tagged_addr) &&
+ untag_4b(h.tagged_addr) + h.requested_size > untag_4b(tagged_addr)) {
+ ++*num_matching_addrs_4b;
}
}
- return 0;
+ return false;
}
static void PrintStackAllocations(StackAllocationsRingBuffer *sa,
@@ -221,6 +247,42 @@ static bool TagsEqual(tag_t tag, tag_t *tag_ptr) {
return tag == inline_tag;
}
+// HWASan globals store the size of the global in the descriptor. In cases where
+// we don't have a binary with symbols, we can't grab the size of the global
+// from the debug info - but we might be able to retrieve it from the
+// descriptor. Returns zero if the lookup failed.
+static uptr GetGlobalSizeFromDescriptor(uptr ptr) {
+ // Find the ELF object that this global resides in.
+ Dl_info info;
+ dladdr(reinterpret_cast<void *>(ptr), &info);
+ auto *ehdr = reinterpret_cast<const ElfW(Ehdr) *>(info.dli_fbase);
+ auto *phdr_begin = reinterpret_cast<const ElfW(Phdr) *>(
+ reinterpret_cast<const u8 *>(ehdr) + ehdr->e_phoff);
+
+ // Get the load bias. This is normally the same as the dli_fbase address on
+ // position-independent code, but can be different on non-PIE executables,
+ // binaries using LLD's partitioning feature, or binaries compiled with a
+ // linker script.
+ ElfW(Addr) load_bias = 0;
+ for (const auto &phdr :
+ ArrayRef<const ElfW(Phdr)>(phdr_begin, phdr_begin + ehdr->e_phnum)) {
+ if (phdr.p_type != PT_LOAD || phdr.p_offset != 0)
+ continue;
+ load_bias = reinterpret_cast<ElfW(Addr)>(ehdr) - phdr.p_vaddr;
+ break;
+ }
+
+ // Walk all globals in this ELF object, looking for the one we're interested
+ // in. Once we find it, we can stop iterating and return the size of the
+ // global we're interested in.
+ for (const hwasan_global &global :
+ HwasanGlobalsFor(load_bias, phdr_begin, ehdr->e_phnum))
+ if (global.addr() <= ptr && ptr < global.addr() + global.size())
+ return global.size();
+
+ return 0;
+}
+
void PrintAddressDescription(
uptr tagged_addr, uptr access_size,
StackAllocationsRingBuffer *current_stack_allocations) {
@@ -297,9 +359,19 @@ void PrintAddressDescription(
candidate == left ? "right" : "left", info.size, info.name,
info.start, info.start + info.size, module_name);
} else {
- Printf("%p is located to the %s of a global variable in (%s+0x%x)\n",
- untagged_addr, candidate == left ? "right" : "left",
- module_name, module_address);
+ uptr size = GetGlobalSizeFromDescriptor(mem);
+ if (size == 0)
+ // We couldn't find the size of the global from the descriptors.
+ Printf(
+ "%p is located to the %s of a global variable in (%s+0x%x)\n",
+ untagged_addr, candidate == left ? "right" : "left",
+ module_name, module_address);
+ else
+ Printf(
+ "%p is located to the %s of a %zd-byte global variable in "
+ "(%s+0x%x)\n",
+ untagged_addr, candidate == left ? "right" : "left", size,
+ module_name, module_address);
}
num_descriptions_printed++;
}
@@ -309,7 +381,10 @@ void PrintAddressDescription(
hwasanThreadList().VisitAllLiveThreads([&](Thread *t) {
// Scan all threads' ring buffers to find if it's a heap-use-after-free.
HeapAllocationRecord har;
- if (uptr D = FindHeapAllocation(t->heap_allocations(), tagged_addr, &har)) {
+ uptr ring_index, num_matching_addrs, num_matching_addrs_4b;
+ if (FindHeapAllocation(t->heap_allocations(), tagged_addr, &har,
+ &ring_index, &num_matching_addrs,
+ &num_matching_addrs_4b)) {
Printf("%s", d.Location());
Printf("%p is located %zd bytes inside of %zd-byte region [%p,%p)\n",
untagged_addr, untagged_addr - UntagAddr(har.tagged_addr),
@@ -327,8 +402,11 @@ void PrintAddressDescription(
// Print a developer note: the index of this heap object
// in the thread's deallocation ring buffer.
- Printf("hwasan_dev_note_heap_rb_distance: %zd %zd\n", D,
+ Printf("hwasan_dev_note_heap_rb_distance: %zd %zd\n", ring_index + 1,
flags()->heap_history_size);
+ Printf("hwasan_dev_note_num_matching_addrs: %zd\n", num_matching_addrs);
+ Printf("hwasan_dev_note_num_matching_addrs_4b: %zd\n",
+ num_matching_addrs_4b);
t->Announce();
num_descriptions_printed++;
diff --git a/compiler-rt/lib/hwasan/hwasan_thread.cpp b/compiler-rt/lib/hwasan/hwasan_thread.cpp
index cabf614c005c..b81a6350c05c 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_thread.cpp
@@ -90,6 +90,12 @@ void Thread::Destroy() {
if (heap_allocations_)
heap_allocations_->Delete();
DTLS_Destroy();
+ // Unregister this as the current thread.
+ // Instrumented code can not run on this thread from this point onwards, but
+ // malloc/free can still be served. Glibc may call free() very late, after all
+ // TSD destructors are done.
+ CHECK_EQ(GetCurrentThread(), this);
+ *GetCurrentThreadLongPtr() = 0;
}
void Thread::Print(const char *Prefix) {
diff --git a/compiler-rt/lib/hwasan/hwasan_thread.h b/compiler-rt/lib/hwasan/hwasan_thread.h
index 42c1e9e124b0..ebcdb791fb36 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread.h
+++ b/compiler-rt/lib/hwasan/hwasan_thread.h
@@ -38,14 +38,6 @@ class Thread {
return addr >= stack_bottom_ && addr < stack_top_;
}
- bool InSignalHandler() { return in_signal_handler_; }
- void EnterSignalHandler() { in_signal_handler_++; }
- void LeaveSignalHandler() { in_signal_handler_--; }
-
- bool InSymbolizer() { return in_symbolizer_; }
- void EnterSymbolizer() { in_symbolizer_++; }
- void LeaveSymbolizer() { in_symbolizer_--; }
-
AllocatorCache *allocator_cache() { return &allocator_cache_; }
HeapAllocationsRingBuffer *heap_allocations() { return heap_allocations_; }
StackAllocationsRingBuffer *stack_allocations() { return stack_allocations_; }
@@ -54,7 +46,6 @@ class Thread {
void DisableTagging() { tagging_disabled_++; }
void EnableTagging() { tagging_disabled_--; }
- bool TaggingIsDisabled() const { return tagging_disabled_; }
u64 unique_id() const { return unique_id_; }
void Announce() {
@@ -76,9 +67,6 @@ class Thread {
uptr tls_begin_;
uptr tls_end_;
- unsigned in_signal_handler_;
- unsigned in_symbolizer_;
-
u32 random_state_;
u32 random_buffer_;
@@ -86,8 +74,6 @@ class Thread {
HeapAllocationsRingBuffer *heap_allocations_;
StackAllocationsRingBuffer *stack_allocations_;
- static void InsertIntoThreadList(Thread *t);
- static void RemoveFromThreadList(Thread *t);
Thread *next_; // All live threads form a linked list.
u64 unique_id_; // counting from zero.