0N/A/*
1472N/A * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
0N/Aimport sun.jvm.hotspot.oops.*;
0N/Aimport sun.jvm.hotspot.runtime.*;
0N/Aimport sun.jvm.hotspot.tools.*;
0N/Aimport sun.jvm.hotspot.utilities.*;
0N/A
0N/A/**
0N/A We don't run any of the "standard" SA command line tools for sanity
0N/A check. This is because the standard tools print addresses in hex
0N/A which could change legally. Also, textual comparison of output may
0N/A not match because of other reasons as well. This tool checks
0N/A validity of threads and frames logically. This class has reference
0N/A frame names from "known" threads. The debuggee is assumed to run
0N/A "LibprocTest.java".
0N/A*/
0N/A
0N/Apublic class LibprocClient extends Tool {
0N/A
0N/A public void run() {
0N/A // try to get VM version and check
0N/A String version = VM.getVM().getVMRelease();
0N/A Assert.that(version.startsWith("1.5"), "1.5 expected");
0N/A
0N/A // try getting threads
0N/A Threads threads = VM.getVM().getThreads();
0N/A boolean mainTested = false;
0N/A
0N/A // check frames of each thread
0N/A for (JavaThread cur = threads.first(); cur != null; cur = cur.next()) {
0N/A if (cur.isJavaThread()) {
0N/A String name = cur.getThreadName();
0N/A // testing of basic frame walking for all threads
0N/A for (JavaVFrame vf = getLastJavaVFrame(cur); vf != null; vf = vf.javaSender()) {
0N/A checkFrame(vf);
0N/A }
0N/A
0N/A // special testing for "known" threads. For now, only "main" thread.
0N/A if (name.equals("main")) {
0N/A checkMainThread(cur);
0N/A mainTested = true;
0N/A }
0N/A }
0N/A }
0N/A Assert.that(mainTested, "main thread missing");
0N/A }
0N/A
0N/A public static void main(String[] args) {
0N/A try {
0N/A LibprocClient lc = new LibprocClient();
0N/A lc.start(args);
0N/A lc.getAgent().detach();
0N/A System.out.println("\nPASSED\n");
0N/A } catch (Exception exp) {
0N/A System.out.println("\nFAILED\n");
0N/A exp.printStackTrace();
0N/A }
0N/A }
0N/A
0N/A // -- Internals only below this point
0N/A private static JavaVFrame getLastJavaVFrame(JavaThread cur) {
0N/A RegisterMap regMap = cur.newRegisterMap(true);
0N/A Frame f = cur.getCurrentFrameGuess();
0N/A if (f == null) {
0N/A System.err.println(" (Unable to get a top most frame)");
0N/A return null;
0N/A }
0N/A VFrame vf = VFrame.newVFrame(f, regMap, cur, true, true);
0N/A if (vf == null) {
0N/A System.err.println(" (Unable to create vframe for topmost frame guess)");
0N/A return null;
0N/A }
0N/A if (vf.isJavaFrame()) {
0N/A return (JavaVFrame) vf;
0N/A }
0N/A return (JavaVFrame) vf.javaSender();
0N/A }
0N/A
0N/A private void checkMethodSignature(Symbol sig) {
0N/A SignatureIterator itr = new SignatureIterator(sig) {
0N/A public void doBool () {}
0N/A public void doChar () {}
0N/A public void doFloat () {}
0N/A public void doDouble() {}
0N/A public void doByte () {}
0N/A public void doShort () {}
0N/A public void doInt () {}
0N/A public void doLong () {}
0N/A public void doVoid () {}
0N/A public void doObject(int begin, int end) {}
0N/A public void doArray (int begin, int end) {}
0N/A };
0N/A // this will throw RuntimeException for any invalid item in signature.
0N/A itr.iterate();
0N/A }
0N/A
0N/A private void checkBCI(Method m, int bci) {
0N/A if (! m.isNative()) {
0N/A byte[] buf = m.getByteCode();
0N/A Assert.that(bci >= 0 && bci < buf.length, "invalid bci, not in code range");
0N/A if (m.hasLineNumberTable()) {
0N/A int lineNum = m.getLineNumberFromBCI(bci);
0N/A Assert.that(lineNum >= 0, "expecting non-negative line number");
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void checkMethodHolder(Method method) {
0N/A Klass klass = method.getMethodHolder();
0N/A Assert.that(klass != null, "expecting non-null instance klass");
0N/A }
0N/A
0N/A private void checkFrame(JavaVFrame vf) {
0N/A Method method = vf.getMethod();
0N/A Assert.that(method != null, "expecting a non-null method here");
0N/A Assert.that(method.getName() != null, "expecting non-null method name");
0N/A checkMethodHolder(method);
0N/A checkMethodSignature(method.getSignature());
0N/A checkBCI(method, vf.getBCI());
0N/A }
0N/A
0N/A // from the test case LibprocTest.java - in the main thread we
0N/A // should see frames as below
0N/A private static String[] mainThreadMethods = new String[] {
0N/A "java.lang.Object.wait(long)",
0N/A "java.lang.Object.wait()",
0N/A "LibprocTest.main(java.lang.String[])"
0N/A };
0N/A
0N/A private void checkMainThread(JavaThread thread) {
0N/A checkFrames(thread, mainThreadMethods);
0N/A }
0N/A
0N/A private void checkFrames(JavaThread thread, String[] expectedMethodNames) {
0N/A int i = 0;
0N/A for (JavaVFrame vf = getLastJavaVFrame(thread); vf != null; vf = vf.javaSender(), i++) {
0N/A Method m = vf.getMethod();
0N/A Assert.that(m.externalNameAndSignature().equals(expectedMethodNames[i]),
0N/A "expected frame missing");
0N/A }
0N/A }
0N/A}