mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8298445: Add LeakSanitizer support in HotSpot
Reviewed-by: erikj, ihse
This commit is contained in:
parent
2e2e71e1fa
commit
27126157d9
@ -219,6 +219,9 @@ JDKOPT_SETUP_ADDRESS_SANITIZER
|
||||
# UndefinedBehaviorSanitizer
|
||||
JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER
|
||||
|
||||
# LeakSanitizer
|
||||
JDKOPT_SETUP_LEAK_SANITIZER
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Check dependencies for external and internal libraries.
|
||||
|
||||
@ -440,6 +440,39 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER],
|
||||
AC_SUBST(ASAN_ENABLED)
|
||||
])
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# LeakSanitizer
|
||||
#
|
||||
AC_DEFUN_ONCE([JDKOPT_SETUP_LEAK_SANITIZER],
|
||||
[
|
||||
UTIL_ARG_ENABLE(NAME: lsan, DEFAULT: false, RESULT: LSAN_ENABLED,
|
||||
DESC: [enable LeakSanitizer],
|
||||
CHECK_AVAILABLE: [
|
||||
AC_MSG_CHECKING([if LeakSanitizer (lsan) is available])
|
||||
if test "x$TOOLCHAIN_TYPE" = "xgcc" ||
|
||||
test "x$TOOLCHAIN_TYPE" = "xclang"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AVAILABLE=false
|
||||
fi
|
||||
],
|
||||
IF_ENABLED: [
|
||||
LSAN_CFLAGS="-fsanitize=leak -fno-omit-frame-pointer -DLEAK_SANITIZER"
|
||||
LSAN_LDFLAGS="-fsanitize=leak"
|
||||
JVM_CFLAGS="$JVM_CFLAGS $LSAN_CFLAGS"
|
||||
JVM_LDFLAGS="$JVM_LDFLAGS $LSAN_LDFLAGS"
|
||||
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $LSAN_CFLAGS"
|
||||
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $LSAN_CFLAGS"
|
||||
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $LSAN_CFLAGS"
|
||||
CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $LSAN_CFLAGS"
|
||||
LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $LSAN_LDFLAGS"
|
||||
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $LSAN_LDFLAGS"
|
||||
])
|
||||
AC_SUBST(LSAN_ENABLED)
|
||||
])
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# UndefinedBehaviorSanitizer
|
||||
|
||||
@ -448,6 +448,9 @@ JCOV_FILTERS=@JCOV_FILTERS@
|
||||
# AddressSanitizer
|
||||
ASAN_ENABLED:=@ASAN_ENABLED@
|
||||
|
||||
# LeakSanitizer
|
||||
LSAN_ENABLED:=@LSAN_ENABLED@
|
||||
|
||||
# UndefinedBehaviorSanitizer
|
||||
UBSAN_ENABLED:=@UBSAN_ENABLED@
|
||||
UBSAN_CFLAGS:=@UBSAN_CFLAGS@
|
||||
|
||||
@ -150,6 +150,10 @@ define SetupBuildLauncherBody
|
||||
$1_EXTRA_FILES += $(TOPDIR)/make/data/asan/asan_default_options.c
|
||||
endif
|
||||
|
||||
ifeq ($(LSAN_ENABLED), true)
|
||||
$1_EXTRA_FILES += $(TOPDIR)/make/data/lsan/lsan_default_options.c
|
||||
endif
|
||||
|
||||
$$(eval $$(call SetupJdkExecutable, BUILD_LAUNCHER_$1, \
|
||||
NAME := $1, \
|
||||
EXTRA_FILES := $$($1_EXTRA_FILES), \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, Google and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -50,8 +50,16 @@
|
||||
// used. You can override these options by setting the environment variable ASAN_OPTIONS.
|
||||
ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __asan_default_options() {
|
||||
return
|
||||
#ifndef LEAK_SANITIZER
|
||||
#ifdef LEAK_SANITIZER
|
||||
"leak_check_at_exit=0,"
|
||||
#else
|
||||
// ASan bundles LSan, however we only support LSan when it is explicitly requested during
|
||||
// configuration. Thus we disable it to match if it was not requested.
|
||||
"detect_leaks=0,"
|
||||
#endif
|
||||
"handle_segv=0";
|
||||
"print_suppressions=0,"
|
||||
"handle_segv=0,"
|
||||
// See https://github.com/google/sanitizers/issues/1322. Hopefully this is resolved
|
||||
// at some point and we can remove this option.
|
||||
"intercept_tls_get_addr=0";
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, Google and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
||||
67
make/data/lsan/lsan_default_options.c
Normal file
67
make/data/lsan/lsan_default_options.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Google and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef LEAK_SANITIZER
|
||||
#error "Build misconfigured, preprocessor macro LEAK_SANITIZER should be defined"
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && !defined(__clang__)) || __has_attribute(visibility)
|
||||
#define ATTRIBUTE_DEFAULT_VISIBILITY __attribute__((visibility("default")))
|
||||
#else
|
||||
#define ATTRIBUTE_DEFAULT_VISIBILITY
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && !defined(__clang__)) || __has_attribute(used)
|
||||
#define ATTRIBUTE_USED __attribute__((used))
|
||||
#else
|
||||
#define ATTRIBUTE_USED
|
||||
#endif
|
||||
|
||||
// Override weak symbol exposed by LSan to override default options. This is called by LSan
|
||||
// extremely early during library loading, before main is called. We need to override the default
|
||||
// options because LSan will perform leak checking at program exit. Unfortunately Hotspot does not
|
||||
// shutdown cleanly at the moment and some leaks occur, we want to ignore these. Instead we
|
||||
// explicitly perform leak checking early during JVM shutdown.
|
||||
ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __lsan_default_options() {
|
||||
return
|
||||
"print_suppressions=0,"
|
||||
"leak_check_at_exit=0,"
|
||||
// See https://github.com/google/sanitizers/issues/1322. Hopefully this is resolved
|
||||
// at some point and we can remove this option.
|
||||
"intercept_tls_get_addr=0";
|
||||
}
|
||||
|
||||
// Override weak symbol exposed by LSan to override default suppressions. This is called by LSan
|
||||
// extremely early during library loading, before main is called.
|
||||
ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __lsan_default_suppressions() {
|
||||
return
|
||||
// Remove after JDK-8297688 is resolved.
|
||||
"leak:^JLI_MemAlloc$\n"
|
||||
"leak:^JLI_StringDup$\n";
|
||||
}
|
||||
30
make/data/lsan/lsan_default_options.cpp
Normal file
30
make/data/lsan/lsan_default_options.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Google and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "./lsan_default_options.c"
|
||||
|
||||
} // extern "C"
|
||||
@ -32,6 +32,10 @@ ifeq ($(ASAN_ENABLED), true)
|
||||
GTEST_LAUNCHER_SRC += $(TOPDIR)/make/data/asan/asan_default_options.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(LSAN_ENABLED), true)
|
||||
GTEST_LAUNCHER_SRC += $(TOPDIR)/make/data/lsan/lsan_default_options.cpp
|
||||
endif
|
||||
|
||||
# On Windows, there are no internal debug symbols so must set copying to true
|
||||
# to get any at all.
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
|
||||
@ -1521,7 +1521,13 @@ endif
|
||||
ifeq ($(ASAN_ENABLED), true)
|
||||
# Any executable which launches the JVM and uses a custom launcher needs to explicitly link in the
|
||||
# default ASan options.
|
||||
BUILD_HOTSPOT_JTREG_EXTRA_FILES := $(TOPDIR)/make/data/asan/asan_default_options.c
|
||||
BUILD_HOTSPOT_JTREG_EXTRA_FILES += $(TOPDIR)/make/data/asan/asan_default_options.c
|
||||
endif
|
||||
|
||||
ifeq ($(LSAN_ENABLED), true)
|
||||
# Any executable which launches the JVM and uses a custom launcher needs to explicitly link in the
|
||||
# default LSan options.
|
||||
BUILD_HOTSPOT_JTREG_EXTRA_FILES += $(TOPDIR)/make/data/lsan/lsan_default_options.c
|
||||
endif
|
||||
|
||||
# This evaluation is expensive and should only be done if this target was
|
||||
|
||||
@ -135,7 +135,13 @@ endif
|
||||
ifeq ($(ASAN_ENABLED), true)
|
||||
# Any executable which launches the JVM and uses a custom launcher needs to explicitly link in the
|
||||
# default ASan options.
|
||||
BUILD_JDK_JTREG_EXTRA_FILES := $(TOPDIR)/make/data/asan/asan_default_options.c
|
||||
BUILD_JDK_JTREG_EXTRA_FILES += $(TOPDIR)/make/data/asan/asan_default_options.c
|
||||
endif
|
||||
|
||||
ifeq ($(LSAN_ENABLED), true)
|
||||
# Any executable which launches the JVM and uses a custom launcher needs to explicitly link in the
|
||||
# default LSan options.
|
||||
BUILD_JDK_JTREG_EXTRA_FILES += $(TOPDIR)/make/data/lsan/lsan_default_options.c
|
||||
endif
|
||||
|
||||
# This evaluation is expensive and should only be done if this target was
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
@ -50,6 +51,8 @@ Compiler::Compiler() : AbstractCompiler(compiler_c1) {
|
||||
void Compiler::init_c1_runtime() {
|
||||
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
|
||||
Arena* arena = new (mtCompiler) Arena(mtCompiler);
|
||||
// Ignore leaked arena, it is used by ValueType and Interval during initialization.
|
||||
LSAN_IGNORE_OBJECT(arena);
|
||||
Runtime1::initialize(buffer_blob);
|
||||
FrameMap::initialize();
|
||||
// initialize data structures
|
||||
|
||||
@ -75,6 +75,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/vmThread.hpp"
|
||||
#include "runtime/vmOperations.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "services/memTracker.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
@ -990,6 +991,8 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
|
||||
bool dynamic_mapped = (dynamic_mapinfo != nullptr && dynamic_mapinfo->is_mapped());
|
||||
char* cds_base = static_mapinfo->mapped_base();
|
||||
char* cds_end = dynamic_mapped ? dynamic_mapinfo->mapped_end() : static_mapinfo->mapped_end();
|
||||
// Register CDS memory region with LSan.
|
||||
LSAN_REGISTER_ROOT_REGION(cds_base, cds_end - cds_base);
|
||||
set_shared_metaspace_range(cds_base, static_mapinfo->mapped_end(), cds_end);
|
||||
_relocation_delta = static_mapinfo->relocation_delta();
|
||||
_requested_base_address = static_mapinfo->requested_base_address();
|
||||
|
||||
@ -62,6 +62,7 @@
|
||||
#include "runtime/os.inline.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "runtime/vmThread.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "services/memoryService.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
@ -329,6 +330,9 @@ void CodeCache::initialize_heaps() {
|
||||
ReservedSpace non_method_space = rest.first_part(non_nmethod_size);
|
||||
ReservedSpace non_profiled_space = rest.last_part(non_nmethod_size);
|
||||
|
||||
// Register CodeHeaps with LSan as we sometimes embed pointers to malloc memory.
|
||||
LSAN_REGISTER_ROOT_REGION(rs.base(), rs.size());
|
||||
|
||||
// Non-nmethods (stubs, adapters, ...)
|
||||
add_heap(non_method_space, "CodeHeap 'non-nmethods'", CodeBlobType::NonNMethod);
|
||||
// Tier 2 and tier 3 (profiled) methods
|
||||
@ -1194,6 +1198,8 @@ void CodeCache::initialize() {
|
||||
FLAG_SET_ERGO(ProfiledCodeHeapSize, 0);
|
||||
FLAG_SET_ERGO(NonProfiledCodeHeapSize, 0);
|
||||
ReservedCodeSpace rs = reserve_heap_memory(ReservedCodeCacheSize);
|
||||
// Register CodeHeaps with LSan as we sometimes embed pointers to malloc memory.
|
||||
LSAN_REGISTER_ROOT_REGION(rs.base(), rs.size());
|
||||
add_heap(rs, "CodeCache", CodeBlobType::All);
|
||||
}
|
||||
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
|
||||
|
||||
@ -272,6 +273,9 @@ bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod
|
||||
needs_ic_stub_refill = true;
|
||||
return false;
|
||||
}
|
||||
// LSan appears unable to follow malloc-based memory consistently when embedded as an immediate
|
||||
// in generated machine code. So we have to ignore it.
|
||||
LSAN_IGNORE_OBJECT(holder);
|
||||
} else {
|
||||
assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable");
|
||||
// Can be different than selected_method->vtable_index(), due to package-private etc.
|
||||
@ -442,6 +446,9 @@ bool CompiledIC::set_to_monomorphic(CompiledICInfo& info) {
|
||||
delete holder;
|
||||
return false;
|
||||
}
|
||||
// LSan appears unable to follow malloc-based memory consistently when embedded as an
|
||||
// immediate in generated machine code. So we have to ignore it.
|
||||
LSAN_IGNORE_OBJECT(holder);
|
||||
if (TraceICs) {
|
||||
ResourceMark rm(thread);
|
||||
tty->print_cr ("IC@" INTPTR_FORMAT ": monomorphic to interpreter via icholder ", p2i(instruction_address()));
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "sanitizers/address.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "services/memTracker.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
@ -239,6 +240,10 @@ VirtualSpaceNode::VirtualSpaceNode(ReservedSpace rs, bool owns_rs, CommitLimiter
|
||||
// Poison the memory region. It will be unpoisoned later on a per-chunk base for chunks that are
|
||||
// handed to arenas.
|
||||
ASAN_POISON_MEMORY_REGION(rs.base(), rs.size());
|
||||
|
||||
// Register memory region related to Metaspace. The Metaspace contains lots of pointers to malloc
|
||||
// memory.
|
||||
LSAN_REGISTER_ROOT_REGION(rs.base(), rs.size());
|
||||
}
|
||||
|
||||
// Create a node of a given size (it will create its own space).
|
||||
@ -270,11 +275,15 @@ VirtualSpaceNode* VirtualSpaceNode::create_node(ReservedSpace rs, CommitLimiter*
|
||||
VirtualSpaceNode::~VirtualSpaceNode() {
|
||||
DEBUG_ONLY(verify_locked();)
|
||||
|
||||
// Unregister memory region related to Metaspace.
|
||||
LSAN_UNREGISTER_ROOT_REGION(_rs.base(), _rs.size());
|
||||
|
||||
// Undo the poisoning before potentially unmapping memory. This ensures that future mappings at
|
||||
// the same address do not unexpectedly fail with use-after-poison.
|
||||
ASAN_UNPOISON_MEMORY_REGION(_rs.base(), _rs.size());
|
||||
|
||||
UL(debug, ": dies.");
|
||||
|
||||
if (_owns_rs) {
|
||||
_rs.release();
|
||||
}
|
||||
|
||||
@ -75,6 +75,7 @@
|
||||
#include "runtime/jniHandles.hpp"
|
||||
#include "runtime/threads.hpp"
|
||||
#include "runtime/timerTrace.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "services/memoryService.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/autoRestore.hpp"
|
||||
@ -751,7 +752,11 @@ bool Universe::contains_non_oop_word(void* p) {
|
||||
}
|
||||
|
||||
static void initialize_global_behaviours() {
|
||||
CompiledICProtectionBehaviour::set_current(new DefaultICProtectionBehaviour());
|
||||
DefaultICProtectionBehaviour* protection_behavior = new DefaultICProtectionBehaviour();
|
||||
// Ignore leak of DefaultICProtectionBehaviour. It is overriden by some GC implementations and the
|
||||
// pointer is leaked once.
|
||||
LSAN_IGNORE_OBJECT(protection_behavior);
|
||||
CompiledICProtectionBehaviour::set_current(protection_behavior);
|
||||
}
|
||||
|
||||
jint universe_init() {
|
||||
|
||||
@ -59,6 +59,7 @@
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "runtime/signature.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
|
||||
|
||||
@ -983,6 +984,8 @@ void MethodHandles::trace_method_handle_interpreter_entry(MacroAssembler* _masm,
|
||||
}
|
||||
jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
|
||||
trace_method_handle(_masm, qname);
|
||||
// LSan appears unable to keep track of qname, ignore it.
|
||||
LSAN_IGNORE_OBJECT(qname);
|
||||
// Note: Don't free the allocated char array because it's used
|
||||
// during runtime.
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "code/icBuffer.hpp"
|
||||
#include "compiler/compiler_globals.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/gcHeapSummary.hpp"
|
||||
#include "interpreter/bytecodes.hpp"
|
||||
#include "logging/logAsyncWriter.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
@ -43,6 +44,7 @@
|
||||
#include "runtime/init.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "services/memTracker.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#if INCLUDE_JVMCI
|
||||
@ -123,6 +125,14 @@ jint init_globals() {
|
||||
if (status != JNI_OK)
|
||||
return status;
|
||||
|
||||
#ifdef LEAK_SANITIZER
|
||||
{
|
||||
// Register the Java heap with LSan.
|
||||
VirtualSpaceSummary summary = Universe::heap()->create_heap_space_summary();
|
||||
LSAN_REGISTER_ROOT_REGION(summary.start(), summary.reserved_size());
|
||||
}
|
||||
#endif // LEAK_SANITIZER
|
||||
|
||||
AsyncLogWriter::initialize();
|
||||
gc_barrier_stubs_init(); // depends on universe_init, must be before interpreter_init
|
||||
continuations_init(); // must precede continuation stub generation
|
||||
@ -183,6 +193,13 @@ void exit_globals() {
|
||||
StringTable::dump(tty);
|
||||
}
|
||||
ostream_exit();
|
||||
#ifdef LEAK_SANITIZER
|
||||
{
|
||||
// Unregister the Java heap with LSan.
|
||||
VirtualSpaceSummary summary = Universe::heap()->create_heap_space_summary();
|
||||
LSAN_UNREGISTER_ROOT_REGION(summary.start(), summary.reserved_size());
|
||||
}
|
||||
#endif // LEAK_SANITIZER
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -72,6 +72,7 @@
|
||||
#include "runtime/vmOperations.hpp"
|
||||
#include "runtime/vmThread.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "services/memTracker.hpp"
|
||||
#include "utilities/dtrace.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
@ -416,6 +417,30 @@ void before_exit(JavaThread* thread, bool halt) {
|
||||
}
|
||||
}
|
||||
|
||||
// At this point only one thread is executing this logic. Any other threads
|
||||
// attempting to invoke before_exit() will wait above and return early once
|
||||
// this thread finishes before_exit().
|
||||
|
||||
// Do not add any additional shutdown logic between the above mutex logic and
|
||||
// leak sanitizer logic below. Any additional shutdown code which performs some
|
||||
// cleanup should be added after the leak sanitizer logic below.
|
||||
|
||||
#ifdef LEAK_SANITIZER
|
||||
// If we are built with LSan, we need to perform leak checking. If we are
|
||||
// terminating normally, not halting and no VM error, we perform a normal
|
||||
// leak check which terminates if leaks are found. If we are not terminating
|
||||
// normally, halting or VM error, we perform a recoverable leak check which
|
||||
// prints leaks but will not terminate.
|
||||
if (!halt && !VMError::is_error_reported()) {
|
||||
LSAN_DO_LEAK_CHECK();
|
||||
} else {
|
||||
// Ignore the return value.
|
||||
static_cast<void>(LSAN_DO_RECOVERABLE_LEAK_CHECK());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Actual shutdown logic begins here.
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
if (EnableJVMCI) {
|
||||
JVMCI::shutdown(thread);
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "runtime/nonJavaThread.hpp"
|
||||
#include "runtime/osThread.hpp"
|
||||
#include "runtime/task.hpp"
|
||||
#include "sanitizers/leak.hpp"
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#include "utilities/singleWriterSynchronizer.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
@ -285,6 +286,7 @@ void WatcherThread::run() {
|
||||
// Signal that it is terminated
|
||||
{
|
||||
MutexLocker mu(Terminator_lock, Mutex::_no_safepoint_check_flag);
|
||||
LSAN_IGNORE_OBJECT(_watcher_thread);
|
||||
_watcher_thread = nullptr;
|
||||
Terminator_lock->notify_all();
|
||||
}
|
||||
|
||||
93
src/hotspot/share/sanitizers/leak.hpp
Normal file
93
src/hotspot/share/sanitizers/leak.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Google and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_SANITIZERS_LEAK_HPP
|
||||
#define SHARE_SANITIZERS_LEAK_HPP
|
||||
|
||||
#ifdef LEAK_SANITIZER
|
||||
#include <sanitizer/lsan_interface.h>
|
||||
#endif
|
||||
|
||||
// LSAN_REGISTER_ROOT_REGION()/LSAN_UNREGISTER_ROOT_REGION()
|
||||
//
|
||||
// Register/unregister regions of memory with LSan. LSan scans these regions looking for
|
||||
// pointers to malloc memory. This is only necessary when pointers to malloc memory are
|
||||
// located in memory that is not returned by malloc, such as mapped memory. LSan will
|
||||
// skip inaccessible parts of the region, such as those that are not readable.
|
||||
#ifdef LEAK_SANITIZER
|
||||
#define LSAN_REGISTER_ROOT_REGION(addr, size) __lsan_register_root_region((addr), (size))
|
||||
#define LSAN_UNREGISTER_ROOT_REGION(addr, size) __lsan_unregister_root_region((addr), (size))
|
||||
#else
|
||||
#define LSAN_REGISTER_ROOT_REGION(addr, size) \
|
||||
do { \
|
||||
if (false) { \
|
||||
((void) (addr)); \
|
||||
((void) (size)); \
|
||||
} \
|
||||
} while (false)
|
||||
#define LSAN_UNREGISTER_ROOT_REGION(addr, size) \
|
||||
do { \
|
||||
if (false) { \
|
||||
((void) (addr)); \
|
||||
((void) (size)); \
|
||||
} \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
// LSAN_IGNORE_OBJECT()
|
||||
//
|
||||
// Causes LSan to ignore any leaks related to the object. Should only be used
|
||||
// in cases where leaks are intentional or where LSan will be unable to discover
|
||||
// pointers to object, for example due to pointers being stored unaligned.
|
||||
#ifdef LEAK_SANITIZER
|
||||
#define LSAN_IGNORE_OBJECT(object) __lsan_ignore_object(object)
|
||||
#else
|
||||
#define LSAN_IGNORE_OBJECT(object) \
|
||||
do { \
|
||||
if (false) { \
|
||||
((void) (object)); \
|
||||
} \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
// LSAN_DO_LEAK_CHECK()
|
||||
//
|
||||
// Perform a leak check, terminating the process if leaks are found. LSan will
|
||||
// skip performing leak checks at process exit and further calls will be ignored.
|
||||
#ifdef LEAK_SANITIZER
|
||||
#define LSAN_DO_LEAK_CHECK() __lsan_do_leak_check()
|
||||
#else
|
||||
#define LSAN_DO_LEAK_CHECK() ((void) 0)
|
||||
#endif
|
||||
|
||||
// LSAN_DO_RECOVERABLE_LEAK_CHECK()
|
||||
//
|
||||
// Perform a leak check without terminating if leaks are found.
|
||||
#ifdef LEAK_SANITIZER
|
||||
#define LSAN_DO_RECOVERABLE_LEAK_CHECK() __lsan_do_recoverable_leak_check()
|
||||
#else
|
||||
#define LSAN_DO_RECOVERABLE_LEAK_CHECK() ((int) 0)
|
||||
#endif
|
||||
|
||||
#endif // SHARE_SANITIZERS_ADDRESS_HPP
|
||||
Loading…
x
Reference in New Issue
Block a user