Path: blob/master/runtime/gc_check/CheckVMThreadStacks.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2014 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "CheckEngine.hpp"23#include "CheckVMThreadStacks.hpp"24#include "ModronTypes.hpp"25#include "ScanFormatter.hpp"2627/**28* Wrapper for GC_CheckEngine::checkSlot being used by GC_VMThreadStackSlotIterator::scanSlots29*30* @param objectIndirect the slot to be verified31* @param localData the same value that was passed to GC_VMThreadStackSlotIterator::scanSlots32* in the <code>userData</code> parameter33* @param isDerivedPointer legacy - not used34* @param objectIndirectBase the object that contains the slot35*36* @see GC_VMThreadStackSlotIterator::scanSlots37*/38void39checkStackSlotIterator(J9JavaVM *javaVM, J9Object **objectIndirect, void *localData, J9StackWalkState *walkState, const void *stackLocation)40{41GC_CheckVMThreadStacks::checkStackIteratorData *checkStackIteratorData = (GC_CheckVMThreadStacks::checkStackIteratorData *)localData;4243if (J9MODRON_SLOT_ITERATOR_RECOVERABLE_ERROR == checkStackIteratorData->gcCheck->checkSlotStack(checkStackIteratorData->gcCheck->getJavaVM(), objectIndirect, checkStackIteratorData->walkThread, stackLocation)) {44checkStackIteratorData->numberOfErrors += 1;45}46}4748/**49* Wrapper for GC_CheckEngine::checkSlot being used by GC_VMThreadStackSlotIterator::scanSlots50*51* @param objectIndirect the slot to be printed52* @param localData the same value that was passed to GC_VMThreadStackSlotIterator::scanSlots53* in the <code>userData</code> parameter54* @param isDerivedPointer legacy - not used55* @param objectIndirectBase the object that contains the slot56*57* @see GC_VMThreadStackSlotIterator::scanSlots58*/59void60printStackSlotIterator(J9JavaVM *javaVM, J9Object **objectIndirect, void *localData, J9StackWalkState *walkState, const void *stackLocation)61{62GC_CheckVMThreadStacks::printStackIteratorData *printStackIteratorData = (GC_CheckVMThreadStacks::printStackIteratorData *)localData;6364printStackIteratorData->scanFormatter->entry((void *) *objectIndirect);65}6667GC_Check *68GC_CheckVMThreadStacks::newInstance(J9JavaVM *javaVM, GC_CheckEngine *engine)69{70MM_Forge *forge = MM_GCExtensions::getExtensions(javaVM)->getForge();7172GC_CheckVMThreadStacks *check = (GC_CheckVMThreadStacks *) forge->allocate(sizeof(GC_CheckVMThreadStacks), MM_AllocationCategory::DIAGNOSTIC, J9_GET_CALLSITE());73if(check) {74new(check) GC_CheckVMThreadStacks(javaVM, engine);75}76return check;77}7879void80GC_CheckVMThreadStacks::kill()81{82MM_Forge *forge = MM_GCExtensions::getExtensions(_javaVM)->getForge();83forge->free(this);84}8586void87GC_CheckVMThreadStacks::check()88{89GC_VMThreadListIterator vmThreadListIterator(_javaVM);90J9VMThread *walkThread;91#if defined(J9VM_INTERP_VERBOSE)92bool doStackDump = _engine->isStackDumpAlwaysDisplayed();93#endif /* J9VM_INTERP_VERBOSE */9495while((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {96J9VMThread *toScanWalkThread;97checkStackIteratorData localData = { _engine, walkThread, 0 };98toScanWalkThread = walkThread;99if (NULL != toScanWalkThread) {100GC_VMThreadStackSlotIterator::scanSlots(toScanWalkThread, toScanWalkThread, (void *)&localData, checkStackSlotIterator, false, false);101102#if defined(J9VM_INTERP_VERBOSE)103if (_javaVM->verboseStackDump && (doStackDump || (localData.numberOfErrors > 0))) {104_javaVM->verboseStackDump(toScanWalkThread, "bad object detected on stack");105}106#endif /* J9VM_INTERP_VERBOSE */107}108}109}110111void112GC_CheckVMThreadStacks::print()113{114GC_VMThreadListIterator newVMThreadListIterator(_javaVM);115J9VMThread *walkThread;116117/* call into the VM to print slots and stacks for each thread. */118GC_ScanFormatter formatter(_portLibrary, "thread stacks");119while((walkThread = newVMThreadListIterator.nextVMThread()) != NULL) {120121/* first we print the stack slots */122formatter.section("thread slots", (void *) walkThread);123J9VMThread *toScanWalkThread;124printStackIteratorData localData = { &formatter, walkThread};125toScanWalkThread = walkThread;126GC_VMThreadStackSlotIterator::scanSlots(toScanWalkThread, toScanWalkThread, (void *)&localData, printStackSlotIterator, false, false);127formatter.endSection();128129/* then we print the stack trace itself */130formatter.section("thread stack", (void *) walkThread);131_javaVM->internalVMFunctions->dumpStackTrace(walkThread);132formatter.endSection();133}134formatter.end("thread stacks");135}136137138139