Skip to content

Commit 0c08aa0

Browse files
committed
Merge remote-tracking branch 'origin/GP-2163_Dan_dbgChoosePlatformMenu--SQUASHED'
2 parents a05d594 + 957e74e commit 0c08aa0

File tree

38 files changed

+1555
-134
lines changed

38 files changed

+1555
-134
lines changed

Ghidra/Debug/Debugger/certification.manifest

+2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ src/main/help/help/topics/DebuggerObjectsPlugin/images/stepover.png||GHIDRA||||E
9797
src/main/help/help/topics/DebuggerObjectsPlugin/images/stop.png||GHIDRA||||END|
9898
src/main/help/help/topics/DebuggerPcodeStepperPlugin/DebuggerPcodeStepperPlugin.html||GHIDRA||||END|
9999
src/main/help/help/topics/DebuggerPcodeStepperPlugin/images/DebuggerPcodeStepperPlugin.png||GHIDRA||||END|
100+
src/main/help/help/topics/DebuggerPlatformPlugin/DebuggerPlatformPlugin.html||GHIDRA||||END|
101+
src/main/help/help/topics/DebuggerPlatformPlugin/images/DebuggerSelectPlatformOfferDialog.png||GHIDRA||||END|
100102
src/main/help/help/topics/DebuggerRegionsPlugin/DebuggerRegionsPlugin.html||GHIDRA||||END|
101103
src/main/help/help/topics/DebuggerRegionsPlugin/images/DebuggerRegionMapProposalDialog.png||GHIDRA||||END|
102104
src/main/help/help/topics/DebuggerRegionsPlugin/images/DebuggerRegionsPlugin.png||GHIDRA||||END|

Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml

+4
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@
169169
sortgroup="p1"
170170
target="help/topics/DebuggerTraceViewDiffPlugin/DebuggerTraceViewDiffPlugin.html" />
171171

172+
<tocdef id="DebuggerPlatformPlugin" text="Platform Selection"
173+
sortgroup="p2"
174+
target="help/topics/DebuggerPlatformPlugin/DebuggerPlatformPlugin.html" />
175+
172176
<tocdef id="DebuggerBots" text="Bots: Workflow Automation"
173177
sortgroup="q"
174178
target="help/topics/DebuggerBots/DebuggerBots.html" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE doctype PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
2+
3+
<HTML>
4+
<HEAD>
5+
<META name="generator" content=
6+
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
7+
8+
<TITLE>Debugger: Platform Selection</TITLE>
9+
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
10+
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
11+
</HEAD>
12+
13+
<BODY lang="EN-US">
14+
<H1><A name="plugin"></A>Debugger: Platform Selection</H1>
15+
16+
<P>The Debugger allows the user to work with multiple platforms, i.e., architectures,
17+
compilers, etc., within the context of a single debug target. This plugin allows the user to
18+
switch among platforms and/or introduce new platforms via overrides.</P>
19+
20+
<P>Note we are in a transitional period between two trace database conventions. This plugin is
21+
a necessary component when working with the new convention. In the legacy convention, the
22+
system must ascertain the target's language and compiler at the time it begins recording. If it
23+
fails or makes an incorrect decision, the UI remains mostly empty, or worse, the system
24+
interrogates and instructs the target using the wrong architecture. This mode still works in
25+
most circumstances and is the default and recommended convention. Additional platforms can
26+
still be introduced, but there is perhaps little use for doing so. One case might be to, e.g.,
27+
disassemble JVM bytecodes when debugging a Java process at the native level.</P>
28+
29+
<P>In the new convention, the system always records the target, using the "DATA" language,
30+
i.e., no language. The object tree is recorded, and objects with memory are assigned overlay
31+
spaces where their contents are recorded. The only way to disassemble instructions is to add a
32+
guest platform. This plugin will do that automatically, in more or less the same fashion as the
33+
language and compiler are ascertained in legacy mode. If this fails, the recording still
34+
proceeds, and most of the UI is still useful. The user can add (perhaps by trial and error) the
35+
correct platform later. In the meantime, memory, registers, threads, etc., are all still
36+
displayed.</P>
37+
38+
<H2>Actions</H2>
39+
40+
<P>This plugin adds actions into the Debugger menu under "Choose Platform."</P>
41+
42+
<H3><A name="choose_platform"></A>Choose Platform</H3>
43+
44+
<P>This action adds or changes to a specific platform in the current trace. One of these
45+
actions is presented for each recommended or previously chosen platform, if any. The
46+
recommendations are given by an opinion service, so new options may be added by extension
47+
modules. It is possible there are no recommendations for the current trace. The current
48+
platform is designated by a check mark or other selection indicator.</P>
49+
50+
<H3><A name="choose_more_platforms"></A><A name="prev_diff"></A>More...</H3>
51+
52+
<P>This action is enabled whenever there is a current trace. It presents a dialog with the
53+
recommended platforms for the trace.</P>
54+
55+
<TABLE width="100%">
56+
<TBODY>
57+
<TR>
58+
<TD align="center" width="100%"><IMG alt="" border="1" src=
59+
"images/DebuggerSelectPlatformOfferDialog.png"></TD>
60+
</TR>
61+
</TBODY>
62+
</TABLE>
63+
64+
<P>The "Show Only Recommended Offers" check can be disabled to display override offers as well.
65+
Selecting an offer and confirming the dialog will add or change to the selected platform in the
66+
trace. Furthermore, the choice will be added to the "Choose Platform" menu until the trace is
67+
closed.</P>
68+
</BODY>
69+
</HTML>

Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/DebuggerCoordinates.java

+75-28
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
import ghidra.trace.database.DBTraceUtils;
3232
import ghidra.trace.model.Trace;
3333
import ghidra.trace.model.program.TraceProgramView;
34+
import ghidra.trace.model.stack.TraceObjectStackFrame;
35+
import ghidra.trace.model.target.TraceObject;
36+
import ghidra.trace.model.target.TraceObjectKeyPath;
37+
import ghidra.trace.model.thread.TraceObjectThread;
3438
import ghidra.trace.model.thread.TraceThread;
3539
import ghidra.trace.model.time.TraceSnapshot;
3640
import ghidra.trace.model.time.schedule.TraceSchedule;
@@ -40,13 +44,9 @@
4044
import ghidra.util.NotOwnerException;
4145

4246
public class DebuggerCoordinates {
47+
4348
public static final DebuggerCoordinates NOWHERE =
44-
new DebuggerCoordinates(null, null, null, null, TraceSchedule.ZERO, 0) {
45-
@Override
46-
public void writeDataState(PluginTool tool, SaveState saveState, String key) {
47-
// Write nothing
48-
}
49-
};
49+
new DebuggerCoordinates(null, null, null, null, TraceSchedule.ZERO, 0, null);
5050

5151
private static final String KEY_TRACE_PROJ_LOC = "TraceProjLoc";
5252
private static final String KEY_TRACE_PROJ_NAME = "TraceProjName";
@@ -55,35 +55,38 @@ public void writeDataState(PluginTool tool, SaveState saveState, String key) {
5555
private static final String KEY_THREAD_KEY = "ThreadKey";
5656
private static final String KEY_TIME = "Time";
5757
private static final String KEY_FRAME = "Frame";
58+
private static final String KEY_OBJ_PATH = "ObjectPath";
5859

5960
public static DebuggerCoordinates all(Trace trace, TraceRecorder recorder, TraceThread thread,
60-
TraceProgramView view, TraceSchedule time, Integer frame) {
61+
TraceProgramView view, TraceSchedule time, Integer frame, TraceObject object) {
6162
if (trace == NOWHERE.trace && recorder == NOWHERE.recorder && thread == NOWHERE.thread &&
62-
view == NOWHERE.view && time == NOWHERE.time && frame == NOWHERE.frame) {
63+
view == NOWHERE.view && time == NOWHERE.time && frame == NOWHERE.frame &&
64+
object == NOWHERE.object) {
6365
return NOWHERE;
6466
}
65-
return new DebuggerCoordinates(trace, recorder, thread, view, time, frame);
67+
return new DebuggerCoordinates(trace, recorder, thread, view, time, frame, object);
6668
}
6769

6870
public static DebuggerCoordinates trace(Trace trace) {
6971
if (trace == null) {
7072
return NOWHERE;
7173
}
72-
return all(trace, null, null, null, null, null);
74+
return all(trace, null, null, null, null, null, null);
7375
}
7476

7577
public static DebuggerCoordinates recorder(TraceRecorder recorder) {
7678
return all(recorder == null ? null : recorder.getTrace(), recorder,
77-
null, null, recorder == null ? null : TraceSchedule.snap(recorder.getSnap()), null);
79+
null, null, recorder == null ? null : TraceSchedule.snap(recorder.getSnap()), null,
80+
null);
7881
}
7982

8083
public static DebuggerCoordinates thread(TraceThread thread) {
81-
return all(thread == null ? null : thread.getTrace(), null, thread,
82-
null, null, null);
84+
return all(thread == null ? null : thread.getTrace(), null, thread, null, null, null, null);
8385
}
8486

8587
public static DebuggerCoordinates rawView(TraceProgramView view) {
86-
return all(view.getTrace(), null, null, view, TraceSchedule.snap(view.getSnap()), null);
88+
return all(view.getTrace(), null, null, view, TraceSchedule.snap(view.getSnap()), null,
89+
null);
8790
}
8891

8992
public static DebuggerCoordinates view(TraceProgramView view) {
@@ -107,24 +110,39 @@ public static DebuggerCoordinates view(TraceProgramView view) {
107110
}
108111

109112
public static DebuggerCoordinates snap(long snap) {
110-
return all(null, null, null, null, TraceSchedule.snap(snap), null);
113+
return all(null, null, null, null, TraceSchedule.snap(snap), null, null);
111114
}
112115

113116
public static DebuggerCoordinates time(String time) {
114117
return time(TraceSchedule.parse(time));
115118
}
116119

117120
public static DebuggerCoordinates time(TraceSchedule time) {
118-
return all(null, null, null, null, time, null);
121+
return all(null, null, null, null, time, null, null);
119122
}
120123

121124
public static DebuggerCoordinates frame(int frame) {
122-
return all(null, null, null, null, null, frame);
125+
return all(null, null, null, null, null, frame, null);
126+
}
127+
128+
public static DebuggerCoordinates object(TraceObject object) {
129+
if (object == null) {
130+
return NOWHERE;
131+
}
132+
TraceObjectThread thread = object.queryCanonicalAncestorsInterface(TraceObjectThread.class)
133+
.findFirst()
134+
.orElse(null);
135+
TraceObjectStackFrame frame =
136+
object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class)
137+
.findFirst()
138+
.orElse(null);
139+
return all(object.getTrace(), null, thread, null, null,
140+
frame == null ? null : frame.getLevel(), object);
123141
}
124142

125143
public static DebuggerCoordinates threadSnap(TraceThread thread, long snap) {
126144
return all(thread == null ? null : thread.getTrace(), null, thread, null,
127-
TraceSchedule.snap(snap), null);
145+
TraceSchedule.snap(snap), null, null);
128146
}
129147

130148
public static boolean equalsIgnoreRecorderAndView(DebuggerCoordinates a,
@@ -150,29 +168,31 @@ public static boolean equalsIgnoreRecorderAndView(DebuggerCoordinates a,
150168
private final TraceProgramView view;
151169
private final TraceSchedule time;
152170
private final Integer frame;
171+
private final TraceObject object;
153172

154173
private final int hash;
155174

156175
private Long viewSnap;
157176
private DefaultTraceTimeViewport viewport;
158177

159178
protected DebuggerCoordinates(Trace trace, TraceRecorder recorder, TraceThread thread,
160-
TraceProgramView view, TraceSchedule time, Integer frame) {
179+
TraceProgramView view, TraceSchedule time, Integer frame, TraceObject object) {
161180
this.trace = trace;
162181
this.recorder = recorder;
163182
this.thread = thread;
164183
this.view = view;
165184
this.time = time;
166185
this.frame = frame;
186+
this.object = object;
167187

168-
this.hash = Objects.hash(trace, recorder, thread, view, time, frame);
188+
this.hash = Objects.hash(trace, recorder, thread, view, time, frame, object);
169189
}
170190

171191
@Override
172192
public String toString() {
173193
return String.format(
174-
"Coords(trace=%s,recorder=%s,thread=%s,view=%s,time=%s,frame=%d)",
175-
trace, recorder, thread, view, time, frame);
194+
"Coords(trace=%s,recorder=%s,thread=%s,view=%s,time=%s,frame=%d,object=%d)",
195+
trace, recorder, thread, view, time, frame, object);
176196
}
177197

178198
@Override
@@ -199,6 +219,10 @@ public boolean equals(Object obj) {
199219
if (!Objects.equals(this.frame, that.frame)) {
200220
return false;
201221
}
222+
if (!Objects.equals(this.object, that.object)) {
223+
return false;
224+
}
225+
202226
return true;
203227
}
204228

@@ -216,7 +240,7 @@ public TraceRecorder getRecorder() {
216240
}
217241

218242
public DebuggerCoordinates withRecorder(TraceRecorder newRecorder) {
219-
return all(trace, newRecorder, thread, view, time, frame);
243+
return all(trace, newRecorder, thread, view, time, frame, object);
220244
}
221245

222246
public TraceThread getThread() {
@@ -235,7 +259,7 @@ public DebuggerCoordinates withReFoundThread() {
235259
}
236260

237261
public DebuggerCoordinates withThread(TraceThread newThread) {
238-
return all(trace, recorder, newThread, view, time, frame);
262+
return all(trace, recorder, newThread, view, time, frame, object);
239263
}
240264

241265
public TraceProgramView getView() {
@@ -254,15 +278,19 @@ public Long getSnap() {
254278
*/
255279
public DebuggerCoordinates withSnap(Long newSnap) {
256280
return all(trace, recorder, thread, view,
257-
newSnap == null ? time : TraceSchedule.snap(newSnap), frame);
281+
newSnap == null ? time : TraceSchedule.snap(newSnap), frame, object);
258282
}
259283

260284
public DebuggerCoordinates withTime(TraceSchedule newTime) {
261-
return all(trace, recorder, thread, view, newTime, frame);
285+
return all(trace, recorder, thread, view, newTime, frame, object);
262286
}
263287

264288
public DebuggerCoordinates withView(TraceProgramView newView) {
265-
return all(trace, recorder, thread, newView, time, frame);
289+
return all(trace, recorder, thread, newView, time, frame, object);
290+
}
291+
292+
public DebuggerCoordinates withObject(TraceObject newObject) {
293+
return all(trace, recorder, thread, view, time, frame, newObject);
266294
}
267295

268296
public TraceSchedule getTime() {
@@ -273,6 +301,10 @@ public Integer getFrame() {
273301
return frame;
274302
}
275303

304+
public TraceObject getObject() {
305+
return object;
306+
}
307+
276308
public synchronized long getViewSnap() {
277309
if (viewSnap != null) {
278310
return viewSnap;
@@ -304,6 +336,9 @@ public synchronized TraceTimeViewport getViewport() {
304336
}
305337

306338
public void writeDataState(PluginTool tool, SaveState saveState, String key) {
339+
if (this == NOWHERE) {
340+
return;
341+
}
307342
SaveState coordState = new SaveState();
308343
// for NOWHERE, key should be completely omitted
309344
if (trace != null) {
@@ -410,9 +445,21 @@ public static DebuggerCoordinates readDataState(PluginTool tool, SaveState saveS
410445
if (coordState.hasValue(KEY_FRAME)) {
411446
frame = coordState.getInt(KEY_FRAME, 0);
412447
}
448+
TraceObject object = null;
449+
if (trace != null && coordState.hasValue(KEY_OBJ_PATH)) {
450+
String pathString = coordState.getString(KEY_OBJ_PATH, "");
451+
try {
452+
TraceObjectKeyPath path = TraceObjectKeyPath.parse(pathString);
453+
object = trace.getObjectManager().getObjectByCanonicalPath(path);
454+
}
455+
catch (Exception e) {
456+
Msg.error(DebuggerCoordinates.class, "Could not restore object: " + pathString, e);
457+
object = trace.getObjectManager().getRootObject();
458+
}
459+
}
413460

414461
DebuggerCoordinates coords =
415-
DebuggerCoordinates.all(trace, null, thread, null, time, frame);
462+
DebuggerCoordinates.all(trace, null, thread, null, time, frame, object);
416463
if (!resolve) {
417464
return coords;
418465
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* ###
2+
* IP: GHIDRA
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package ghidra.app.plugin.core.debug.event;
17+
18+
import ghidra.app.plugin.core.debug.mapping.DebuggerPlatformMapper;
19+
import ghidra.framework.plugintool.PluginEvent;
20+
import ghidra.trace.model.Trace;
21+
22+
public class DebuggerPlatformPluginEvent extends PluginEvent {
23+
static final String NAME = "Platform";
24+
25+
private final Trace trace;
26+
private final DebuggerPlatformMapper mapper;
27+
28+
public DebuggerPlatformPluginEvent(String sourceName, Trace trace,
29+
DebuggerPlatformMapper mapper) {
30+
super(sourceName, NAME);
31+
this.trace = trace;
32+
this.mapper = mapper;
33+
}
34+
35+
public Trace getTrace() {
36+
return trace;
37+
}
38+
39+
public DebuggerPlatformMapper getMapper() {
40+
return mapper;
41+
}
42+
}

0 commit comments

Comments
 (0)