File: DebuggerBase.java

package info (click to toggle)
openjdk-25 25.0.1%2B8-1~deb13u1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 825,408 kB
  • sloc: java: 5,585,680; cpp: 1,333,948; xml: 1,321,242; ansic: 488,034; asm: 404,003; objc: 21,088; sh: 15,106; javascript: 13,265; python: 8,319; makefile: 2,518; perl: 357; awk: 351; pascal: 103; exp: 83; sed: 72; jsp: 24
file content (260 lines) | stat: -rw-r--r-- 10,038 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*
 * Copyright (c) 2020, Oracle 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.
 */

package nsk.jdi.HiddenClass.events;

import com.sun.jdi.ClassType;
import com.sun.jdi.ClassObjectReference;
import com.sun.jdi.Field;
import com.sun.jdi.Method;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;

import com.sun.jdi.event.EventSet;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.BreakpointRequest;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.ClassUnloadRequest;
import com.sun.jdi.request.ModificationWatchpointRequest;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import jdk.test.lib.Asserts;

import nsk.share.Log;
import nsk.share.jdi.ArgumentHandler;
import nsk.share.jdi.Binder;
import nsk.share.jdi.Debugee;
import nsk.share.jpda.IOPipe;

// This class is the test debugger base class
public class DebuggerBase {
    public static final int PASSED = 0;
    public static final int FAILED = 2;
    public static final int JCK_STATUS_BASE = 95;

    public static final String COMMAND_READY = "ready";
    public static final String COMMAND_RUN   = "run";
    public static final String COMMAND_DONE  = "done";
    public static final String COMMAND_ERROR = "error";
    public static final String COMMAND_QUIT  = "quit";

    public final Log log;

    private VirtualMachine vm;
    private Debugee debuggee = null;
    private IOPipe pipe = null;
    private EventRequestManager erManager = null;

    protected DebuggerBase(ArgumentHandler argHandler) {
        log = new Log(System.out, argHandler);
    }

    VirtualMachine vm() {
        return vm;
    }

    // Find a ReferenceType by a given type name.
    ReferenceType getReferenceType(String typeName) {
        List<ReferenceType> list = vm.classesByName(typeName);

        Asserts.assertFalse(list.size() == 0, "FAIL: type not found: " + typeName);
        Asserts.assertFalse(list.size() > 1, "FAIL: multiple types found: " + typeName);
        log.display("  Found type: " + typeName);
        return list.get(0);
    }

    // Find a Field by a given ReferenceType and a field name.
    Field findField(ReferenceType refType, String fieldName) {
        Field field = refType.fieldByName(fieldName);
        String fullName = refType.name() + "::" + fieldName;

        Asserts.assertNotNull(field, "FAIL: field not found: " + fullName);
        log.display("  Found field: " + fullName);
        return field;
    }

    // Find a Method by a given ReferenceType and a method name.
    Method findMethod(ReferenceType refType, String methodName) {
        List<Method> list = refType.methodsByName(methodName);
        String fullName = refType.name() + "::" + methodName;

        Asserts.assertFalse(list.size() == 0, "FAIL: method not found: " + fullName);
        Asserts.assertFalse(list.size() > 1, "FAIL: multiple methods found: " + fullName);

        log.display("  Found method: " + fullName);
        return list.get(0);
    }

    // Invoke a given static method in debuggee VM at an eventpoint.
    boolean invokeStaticMethod(ThreadReference thread, Method methodToInvoke) {
        boolean failedStatus = false;
        List<? extends Value> args = new ArrayList<>();
        int flags = (ClassObjectReference.INVOKE_NONVIRTUAL |
                     ClassObjectReference.INVOKE_SINGLE_THREADED);
        try {
            log.display("  invoking method: " + methodToInvoke);
            ClassType type = (ClassType)methodToInvoke.declaringType();
            Value val = type.invokeMethod(thread, methodToInvoke, args, flags);
            log.display("   method getHCField returned result: " + val);
        } catch (Exception ex) {
            log.complain("Exception in HC::getHCField method invocation: " + ex);
            failedStatus = true;
        }
        return failedStatus;
    }

    protected void launchDebuggee(ArgumentHandler argHandler, String debuggeeName) {
        Binder binder = new Binder(argHandler, log);
        log.display("\n# Connecting to debuggee");

        debuggee = binder.bindToDebugee(debuggeeName);
        debuggee.redirectStderr(log, "debuggee >");

        pipe = debuggee.createIOPipe();
        vm = debuggee.VM();
        erManager = vm.eventRequestManager();

        log.display("# Resuming debuggee");
        debuggee.resume();
    }

    protected boolean shutdownDebuggee() {
        boolean debuggeeFailed = false;
        log.display("\n# Shutting down debuggee");

        // wait for debuggee exits and analize its exit code
        log.display("# Waiting for debuggee terminating");
        int debuggeeStatus = debuggee.endDebugee();
        if (debuggeeStatus == PASSED + JCK_STATUS_BASE) {
            log.display("# Debuggee PASSED with exit code: " + debuggeeStatus);
        } else {
            log.complain("# Debuggee FAILED with exit code: " + debuggeeStatus);
            debuggeeFailed = true;
        }
        return debuggeeFailed;
    }

    protected EventRequest enableBreakpointRequest(Method method) {
        log.display("\n# Creating BreakpointRequest");
        BreakpointRequest request = erManager.createBreakpointRequest(method.location());
        Asserts.assertNotNull(request, "FAIL: unable to create BreakpointRequest");

        // enable event request
        request.enable();
        log.display("  Enabled BreakpointRequest");
        return request;
    }

    protected EventRequest enableClassPrepareRequest(String classFilter) {
        log.display("\n# Creating ClassPrepareRequest");
        ClassPrepareRequest request = erManager.createClassPrepareRequest();
        Asserts.assertNotNull(request, "FAIL: unable to create ClassPrepareRequest");

        if (classFilter != null) {
            log.display("  Adding filter to ClassPrepareRequest: " + classFilter);
            request.addClassFilter(classFilter);
        }
        // enable event request
        request.enable();
        log.display("  Enabled ClassPrepareRequest");
        return request;
    }

    protected EventRequest enableClassUnloadRequest(String classFilter) {
        log.display("\n# Creating request for ClassUnloadEvent");
        ClassUnloadRequest request = erManager.createClassUnloadRequest();
        Asserts.assertNotNull(request, "FAIL: unable to create ClassUnloadRequest");

        if (classFilter != null) {
            log.display("  Adding filter to ClassUnloadRequest: " + classFilter);
            request.addClassFilter(classFilter);
        }
        // enable event request
        request.enable();
        log.display("  Enabled ClassUnloadRequest");
        return request;
    }

    protected EventRequest enableModificationWatchpointRequest(Field field, String classFilter) {
        log.display("\n# Creating request for ModificationWatchpointRequest");

        ModificationWatchpointRequest request = erManager.createModificationWatchpointRequest(field);
        Asserts.assertNotNull(request, "FAIL: unable to create ModificationWatchpointRequest");

        if (classFilter != null) {
            log.display("  Adding filter to ModificationWatchpointRequest: " + classFilter);
            request.addClassFilter(classFilter);
        }
        // enable event request
        request.enable();
        log.display("  Enabled ModificationWatchpointRequest");
        return request;
    }

    protected void disableRequest(EventRequest eq, String reqestName) {
        // disable event requests to prevent appearance of further events
        if (eq != null && eq.isEnabled()) {
            log.display("  Disabling " + reqestName);
            eq.disable();
        }
    }

    // sync on the COMMAND_READY
    protected void readyCmdSync() {
        // wait for READY signal from debugee
        log.display("\n# Waiting for command: " + COMMAND_READY);
        String command = pipe.readln();
        Asserts.assertFalse(command == null || !command.equals(COMMAND_READY),
                            "FAIL: unexpected debuggee's command: " + command);
        log.display("\n# Got command: " + COMMAND_READY);
    }

    // sync on the COMMAND_RUN
    protected void runCmdSync() {
        // activate debugee
        log.display("\n# Sending command: " + COMMAND_RUN);
        pipe.println(COMMAND_RUN);
    }

    // sync on the COMMAND_DONE
    protected void doneCmdSync() {
        // wait for DONE signal from debugee
        log.display("\n# Waiting for command: " + COMMAND_DONE);
        String command = pipe.readln();
        Asserts.assertFalse(command == null || !command.equals(COMMAND_DONE),
                    "FAIL: unexpected debuggee's command: " + command);
        log.display("\n# Got command: " + COMMAND_DONE);
    }

    // sync on the COMMAND_QUIT
    protected void quitCmdSync() {
        // force debugee to exit
        log.display("\n# Sending command: " + COMMAND_QUIT);
        pipe.println(COMMAND_QUIT);
    }
}