GP-2177: schema fix for missing registers

GP-2177(SQRB): fire threadCreated
GP-2177_SQRB: spare the VM on E_NOINTERFACE
GP-2177_SQRB: check id plus pid/tid
GP-2177_SQRB: init for dbgmodel RegisterBanks plus bandaid for recorder
GP-2177_SQRB: filter nulls from traceToTarget
GP-2177: extraneous cleanup
GP-2177: clear bpts on process death
GP-2968: fixes from review
GP-2177: not directly related, but...
GP-2177: CACHE needs to be cleared and must follow actual native delete
GP-2177: first pass at bpt errors
This commit is contained in:
d-millar 2023-01-23 15:46:11 -05:00
parent ba0b42dc82
commit dee3de5672
19 changed files with 171 additions and 57 deletions

View file

@ -132,4 +132,6 @@ public interface DebugBreakpoint {
void setDataParameters(int size, BitmaskSet<BreakAccess> access); void setDataParameters(int size, BitmaskSet<BreakAccess> access);
void setDataParameters(int size, BreakAccess... access); void setDataParameters(int size, BreakAccess... access);
void dispose();
} }

View file

@ -51,7 +51,14 @@ public class DebugBreakpointImpl1 implements DebugBreakpointInternal {
@Override @Override
public void remove() { public void remove() {
control.removeBreakpoint(jnaBreakpoint); control.removeBreakpoint(jnaBreakpoint);
// If we do this here, dispose will fail
//jnaBreakpoint = null;
}
@Override
public void dispose() {
// Prevent accidental access. Will be released during GC. NPE is better than segfault. // Prevent accidental access. Will be released during GC. NPE is better than segfault.
CACHE.remove(jnaBreakpoint.getPointer());
jnaBreakpoint = null; jnaBreakpoint = null;
} }
@ -184,4 +191,5 @@ public class DebugBreakpointImpl1 implements DebugBreakpointInternal {
public void setDataParameters(int size, BreakAccess... access) { public void setDataParameters(int size, BreakAccess... access) {
setDataParameters(size, BitmaskSet.of(access)); setDataParameters(size, BitmaskSet.of(access));
} }
} }

View file

@ -24,14 +24,20 @@ import com.sun.jna.platform.win32.COM.COMUtils;
import agent.dbgeng.jna.dbgeng.breakpoint.IDebugBreakpoint2; import agent.dbgeng.jna.dbgeng.breakpoint.IDebugBreakpoint2;
public class DebugBreakpointImpl2 extends DebugBreakpointImpl1 { public class DebugBreakpointImpl2 extends DebugBreakpointImpl1 {
@SuppressWarnings("unused")
private final IDebugBreakpoint2 jnaBreakpoint; private IDebugBreakpoint2 jnaBreakpoint;
public DebugBreakpointImpl2(IDebugBreakpoint2 jnaBreakpoint) { public DebugBreakpointImpl2(IDebugBreakpoint2 jnaBreakpoint) {
super(jnaBreakpoint); super(jnaBreakpoint);
this.jnaBreakpoint = jnaBreakpoint; this.jnaBreakpoint = jnaBreakpoint;
} }
@Override
public void dispose() {
super.dispose();
jnaBreakpoint = null;
}
@Override @Override
public String getOffsetExpression() { public String getOffsetExpression() {
ULONGByReference pulExpressionSize = new ULONGByReference(); ULONGByReference pulExpressionSize = new ULONGByReference();

View file

@ -19,10 +19,16 @@ import agent.dbgeng.jna.dbgeng.breakpoint.IDebugBreakpoint3;
public class DebugBreakpointImpl3 extends DebugBreakpointImpl2 { public class DebugBreakpointImpl3 extends DebugBreakpointImpl2 {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final IDebugBreakpoint3 jnaBreakpoint; private IDebugBreakpoint3 jnaBreakpoint;
public DebugBreakpointImpl3(IDebugBreakpoint3 jnaBreakpoint) { public DebugBreakpointImpl3(IDebugBreakpoint3 jnaBreakpoint) {
super(jnaBreakpoint); super(jnaBreakpoint);
this.jnaBreakpoint = jnaBreakpoint; this.jnaBreakpoint = jnaBreakpoint;
} }
@Override
public void dispose() {
super.dispose();
jnaBreakpoint = null;
}
} }

View file

@ -44,6 +44,9 @@ public class DebugDataSpacesImpl2 extends DebugDataSpacesImpl1 {
if (hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) { if (hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) {
return null; return null;
} }
if (hr.equals(COMUtilsExtra.E_NOINTERFACE)) {
return null;
}
COMUtils.checkRC(hr); COMUtils.checkRC(hr);
return new DebugMemoryBasicInformation(pInfo.BaseAddress.longValue(), return new DebugMemoryBasicInformation(pInfo.BaseAddress.longValue(),

View file

@ -19,12 +19,11 @@ import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.IID; import com.sun.jna.platform.win32.Guid.IID;
import com.sun.jna.platform.win32.WinDef.*; import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.platform.win32.COM.IUnknown;
import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_BREAKPOINT_PARAMETERS; import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_BREAKPOINT_PARAMETERS;
import agent.dbgeng.jna.dbgeng.UnknownWithUtils.VTableIndex; import agent.dbgeng.jna.dbgeng.UnknownWithUtils.VTableIndex;
import com.sun.jna.platform.win32.COM.IUnknown;
public interface IDebugBreakpoint extends IUnknown { public interface IDebugBreakpoint extends IUnknown {
final IID IID_IDEBUG_BREAKPOINT = new IID("5bd9d474-5975-423a-b88b-65a8e7110e65"); final IID IID_IDEBUG_BREAKPOINT = new IID("5bd9d474-5975-423a-b88b-65a8e7110e65");
@ -101,4 +100,6 @@ public interface IDebugBreakpoint extends IUnknown {
HRESULT SetOffsetExpression(String Expression); HRESULT SetOffsetExpression(String Expression);
HRESULT GetParameters(DEBUG_BREAKPOINT_PARAMETERS.ByReference Params); HRESULT GetParameters(DEBUG_BREAKPOINT_PARAMETERS.ByReference Params);
Pointer getPointer();
} }

View file

@ -299,7 +299,12 @@ public class DbgBreakpointInfo {
} }
} }
/*public long getAddressAsLong() { public void remove() {
return locations.get(0).addrAsLong(); bpt.remove();
}*/ // getOffset instead }
public void dispose() {
bpt.dispose();
}
} }

View file

@ -17,7 +17,6 @@ package agent.dbgeng.manager.cmd;
import agent.dbgeng.dbgeng.DebugBreakpoint; import agent.dbgeng.dbgeng.DebugBreakpoint;
import agent.dbgeng.dbgeng.DebugControl; import agent.dbgeng.dbgeng.DebugControl;
import agent.dbgeng.manager.DbgCause;
import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.manager.impl.DbgManagerImpl;
/** /**
@ -36,9 +35,10 @@ public class DbgDeleteBreakpointsCommand extends AbstractDbgCommand<Void> {
public void invoke() { public void invoke() {
DebugControl control = manager.getControl(); DebugControl control = manager.getControl();
for (long id : numbers) { for (long id : numbers) {
manager.doBreakpointDeleted(id, DbgCause.Causes.UNCLAIMED);
DebugBreakpoint bp = control.getBreakpointById((int) id); DebugBreakpoint bp = control.getBreakpointById((int) id);
bp.remove(); if (bp != null) {
bp.remove();
}
} }
} }
} }

View file

@ -144,15 +144,19 @@ public class DbgManagerImpl implements DbgManager {
public DbgThreadImpl getThreadComputeIfAbsent(DebugThreadId id, DbgProcessImpl process, public DbgThreadImpl getThreadComputeIfAbsent(DebugThreadId id, DbgProcessImpl process,
int tid, boolean fire) { int tid, boolean fire) {
synchronized (threads) { synchronized (threads) {
if (!threads.containsKey(id)) { if (threads.containsKey(id)) {
DbgThreadImpl thread = new DbgThreadImpl(this, process, id, tid); DbgThreadImpl existingThread = threads.get(id);
thread.add(); if (existingThread.getTid() == tid) {
if (fire) { return existingThread;
Causes cause = DbgCause.Causes.UNCLAIMED;
getEventListeners().fire.threadCreated(thread, cause);
getEventListeners().fire.threadSelected(thread, null, cause);
} }
} }
DbgThreadImpl thread = new DbgThreadImpl(this, process, id, tid);
thread.add();
if (fire) {
Causes cause = DbgCause.Causes.UNCLAIMED;
getEventListeners().fire.threadCreated(thread, cause);
getEventListeners().fire.threadSelected(thread, null, cause);
}
return threads.get(id); return threads.get(id);
} }
} }
@ -218,13 +222,17 @@ public class DbgManagerImpl implements DbgManager {
public DbgProcessImpl getProcessComputeIfAbsent(DebugProcessId id, int pid, boolean fire) { public DbgProcessImpl getProcessComputeIfAbsent(DebugProcessId id, int pid, boolean fire) {
synchronized (processes) { synchronized (processes) {
if (!processes.containsKey(id)) { if (processes.containsKey(id)) {
DbgProcessImpl process = new DbgProcessImpl(this, id, pid); DbgProcessImpl existingProc = processes.get(id);
process.add(); if (existingProc.getPid() == pid) {
if (fire) { return existingProc;
getEventListeners().fire.processAdded(process, DbgCause.Causes.UNCLAIMED);
} }
} }
DbgProcessImpl process = new DbgProcessImpl(this, id, pid);
process.add();
if (fire) {
getEventListeners().fire.processAdded(process, DbgCause.Causes.UNCLAIMED);
}
return processes.get(id); return processes.get(id);
} }
} }
@ -730,7 +738,7 @@ public class DbgManagerImpl implements DbgManager {
int tid = so.getCurrentThreadSystemId(); int tid = so.getCurrentThreadSystemId();
DbgThreadImpl thread = getThreadComputeIfAbsent(eventId, process, tid, true); DbgThreadImpl thread = getThreadComputeIfAbsent(eventId, process, tid, true);
getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.eventSelected(evt, evt.getCause());
//getEventListeners().fire.threadCreated(thread, DbgCause.Causes.UNCLAIMED); getEventListeners().fire.threadCreated(thread, DbgCause.Causes.UNCLAIMED);
getEventListeners().fire.threadSelected(thread, null, evt.getCause()); getEventListeners().fire.threadSelected(thread, null, evt.getCause());
String key = Integer.toHexString(eventId.id); String key = Integer.toHexString(eventId.id);
@ -1105,6 +1113,11 @@ public class DbgManagerImpl implements DbgManager {
long bptId = evt.getId(); long bptId = evt.getId();
if (bptId == DbgEngUtil.DEBUG_ANY_ID.longValue()) { if (bptId == DbgEngUtil.DEBUG_ANY_ID.longValue()) {
changeBreakpoints(); changeBreakpoints();
for (DbgBreakpointInfo bptInfo : breakpoints.values()) {
if (bptInfo.getProc().equals(currentProcess)) {
doBreakpointDeleted(bptInfo.getNumber(), evt.getCause());
}
}
} }
else { else {
DebugBreakpoint bpt = getControl().getBreakpointById((int) bptId); DebugBreakpoint bpt = getControl().getBreakpointById((int) bptId);
@ -1112,17 +1125,27 @@ public class DbgManagerImpl implements DbgManager {
doBreakpointDeleted(bptId, evt.getCause()); doBreakpointDeleted(bptId, evt.getCause());
return; return;
} }
DbgBreakpointInfo knownBreakpoint = getKnownBreakpoint(bptId); DbgBreakpointInfo knownBreakpoint = breakpoints.get(bptId);
if (knownBreakpoint == null) { if (knownBreakpoint == null) {
breakpointInfo = new DbgBreakpointInfo(bpt, getCurrentProcess()); breakpointInfo = new DbgBreakpointInfo(bpt, getCurrentProcess());
if (breakpointInfo.getOffset() != null) { if (breakpointInfo.getOffset() != null) {
doBreakpointCreated(breakpointInfo, evt.getCause()); addKnownBreakpoint(breakpointInfo, false);
// NB: we don't want to create this here as the address is 0s
//doBreakpointCreated(breakpointInfo, evt.getCause());
} }
return; return;
} }
breakpointInfo = knownBreakpoint; breakpointInfo = knownBreakpoint;
Long initOffset = breakpointInfo.getOffset();
breakpointInfo.setBreakpoint(bpt); breakpointInfo.setBreakpoint(bpt);
doBreakpointModified(breakpointInfo, evt.getCause()); if (!breakpointInfo.getOffset().equals(0L)) {
if (initOffset.equals(0L)) {
doBreakpointCreated(breakpointInfo, evt.getCause());
}
else {
doBreakpointModified(breakpointInfo, evt.getCause());
}
}
} }
} }
} }
@ -1145,7 +1168,7 @@ public class DbgManagerImpl implements DbgManager {
*/ */
@Internal @Internal
public void doBreakpointCreated(DbgBreakpointInfo newInfo, DbgCause cause) { public void doBreakpointCreated(DbgBreakpointInfo newInfo, DbgCause cause) {
addKnownBreakpoint(newInfo, false); addKnownBreakpoint(newInfo, true);
getEventListeners().fire.breakpointCreated(newInfo, cause); getEventListeners().fire.breakpointCreated(newInfo, cause);
} }
@ -1174,6 +1197,7 @@ public class DbgManagerImpl implements DbgManager {
return; return;
} }
getEventListeners().fire.breakpointDeleted(oldInfo, cause); getEventListeners().fire.breakpointDeleted(oldInfo, cause);
oldInfo.dispose();
} }
protected void doBreakpointModifiedSameLocations(DbgBreakpointInfo newInfo, protected void doBreakpointModifiedSameLocations(DbgBreakpointInfo newInfo,

View file

@ -59,16 +59,22 @@ public interface DbgModelTargetBreakpointSpec extends //
@Override @Override
public default String getExpression() { public default String getExpression() {
return getBreakpointInfo().getExpression(); DbgBreakpointInfo info = getBreakpointInfo();
return info == null ? null : info.getExpression();
} }
public default long getNumber() { public default long getNumber() {
return getBreakpointInfo().getNumber(); DbgBreakpointInfo info = getBreakpointInfo();
return info == null ? null : info.getNumber();
} }
@Override @Override
public default TargetBreakpointKindSet getKinds() { public default TargetBreakpointKindSet getKinds() {
switch (getBreakpointInfo().getType()) { DbgBreakpointInfo info = getBreakpointInfo();
if (info == null) {
return TargetBreakpointKindSet.of();
}
switch (info.getType()) {
case BREAKPOINT: case BREAKPOINT:
return TargetBreakpointKindSet.of(TargetBreakpointKind.SW_EXECUTE); return TargetBreakpointKindSet.of(TargetBreakpointKind.SW_EXECUTE);
case HW_BREAKPOINT: case HW_BREAKPOINT:

View file

@ -23,8 +23,10 @@ import com.sun.jna.platform.win32.OleAuto;
import com.sun.jna.platform.win32.WTypes.BSTR; import com.sun.jna.platform.win32.WTypes.BSTR;
import com.sun.jna.platform.win32.WTypes.BSTRByReference; import com.sun.jna.platform.win32.WTypes.BSTRByReference;
import com.sun.jna.platform.win32.WinDef.*; import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.platform.win32.COM.COMUtils; import com.sun.jna.platform.win32.COM.COMUtils;
import agent.dbgeng.dbgeng.COMUtilsExtra;
import agent.dbgmodel.dbgmodel.DbgModel; import agent.dbgmodel.dbgmodel.DbgModel;
import agent.dbgmodel.dbgmodel.DbgModel.OpaqueCleanable; import agent.dbgmodel.dbgmodel.DbgModel.OpaqueCleanable;
import agent.dbgmodel.dbgmodel.debughost.DebugHostContext; import agent.dbgmodel.dbgmodel.debughost.DebugHostContext;
@ -55,8 +57,11 @@ public class DebugHostMemoryImpl1 implements DebugHostMemoryInternal {
Pointer pContext = context.getPointer(); Pointer pContext = context.getPointer();
ULONGLONG pulBufferSize = new ULONGLONG(bufferSize); ULONGLONG pulBufferSize = new ULONGLONG(bufferSize);
ULONGLONGByReference pulBytesRead = new ULONGLONGByReference(); ULONGLONGByReference pulBytesRead = new ULONGLONGByReference();
COMUtils.checkRC( HRESULT hr = jnaData.ReadBytes(pContext, location, buffer, pulBufferSize, pulBytesRead);
jnaData.ReadBytes(pContext, location, buffer, pulBufferSize, pulBytesRead)); if (hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) {
return 0;
}
COMUtils.checkRC(hr);
long read = pulBytesRead.getValue().longValue(); long read = pulBytesRead.getValue().longValue();
buffer.position((int) (read + buffer.position())); buffer.position((int) (read + buffer.position()));
return read; return read;

View file

@ -156,6 +156,10 @@ public class ModelObjectImpl implements ModelObjectInternal {
Msg.debug(this, searchKey + " cannot be read"); Msg.debug(this, searchKey + " cannot be read");
return null; return null;
} }
if (hr.equals(COMUtilsExtra.E_NOINTERFACE)) {
Msg.debug(this, searchKey + " missing interface");
return null;
}
COMUtils.checkRC(hr); COMUtils.checkRC(hr);
ModelObject retval = getObjectWithMetadata(ppObject, ppMetadata); ModelObject retval = getObjectWithMetadata(ppObject, ppMetadata);

View file

@ -249,15 +249,9 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
} }
if (proxy instanceof TargetExecutionStateful) { if (proxy instanceof TargetExecutionStateful) {
if (isValid()) { if (isValid()) {
if (attributes.containsKey(TargetExecutionStateful.STATE_ATTRIBUTE_NAME)) { TargetExecutionStateful stateful = (TargetExecutionStateful) proxy;
TargetExecutionStateful stateful = (TargetExecutionStateful) proxy; TargetExecutionState state = stateful.getExecutionState();
TargetExecutionState state = stateful.getExecutionState(); attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state);
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state);
}
else {
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME,
TargetExecutionState.INACTIVE);
}
} }
} }
if (proxy instanceof TargetAttacher) { if (proxy instanceof TargetAttacher) {

View file

@ -285,8 +285,9 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
List<String> xpath = new ArrayList<>(); List<String> xpath = new ArrayList<>();
xpath.addAll(objPath); xpath.addAll(objPath);
xpath.addAll(ext); xpath.addAll(ext);
// NB: fetchModelObject may have to be called with false
return AsyncUtils.sequence(TypeSpec.cls(DbgModelTargetObject.class)).then(seq -> { return AsyncUtils.sequence(TypeSpec.cls(DbgModelTargetObject.class)).then(seq -> {
getModel().fetchModelObject(xpath).handle(seq::next); getModel().fetchModelObject(xpath, false).handle(seq::next);
}, TypeSpec.cls(TargetObject.class)).then((pobj, seq) -> { }, TypeSpec.cls(TargetObject.class)).then((pobj, seq) -> {
if (pobj == null) { if (pobj == null) {
seq.exit(); seq.exit();

View file

@ -263,7 +263,14 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
} }
} }
if (proxy instanceof TargetExecutionStateful) { if (proxy instanceof TargetExecutionStateful) {
setExecutionState(exec, "Refreshed"); if (proxy instanceof DbgModelTargetSession) {
if (state != DbgState.EXIT) {
setExecutionState(exec, "Refreshed");
}
}
else {
setExecutionState(exec, "Refreshed");
}
} }
} }
@ -306,6 +313,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
return; return;
} }
if (proxy instanceof DbgModelTargetRegisterContainer || // if (proxy instanceof DbgModelTargetRegisterContainer || //
proxy instanceof DbgModelTargetRegisterBank || //
proxy.getName().equals("Stack") || proxy.getName().equals("Stack") ||
proxy.getName().equals("Debug")) { proxy.getName().equals("Debug")) {
requestAttributes(false); requestAttributes(false);
@ -403,9 +411,11 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
List<DelegateDbgModel2TargetObject> delegates = new ArrayList<>(); List<DelegateDbgModel2TargetObject> delegates = new ArrayList<>();
TargetObject stack = TargetObject stack =
(TargetObject) getCachedAttribute("Stack"); (TargetObject) getCachedAttribute("Stack");
DbgModelTargetStack frames = if (stack != null) {
(DbgModelTargetStack) stack.getCachedAttribute("Frames"); DbgModelTargetStack frames =
delegates.add((DelegateDbgModel2TargetObject) frames.getDelegate()); (DbgModelTargetStack) stack.getCachedAttribute("Frames");
delegates.add((DelegateDbgModel2TargetObject) frames.getDelegate());
}
DbgModelTargetRegisterContainer container = DbgModelTargetRegisterContainer container =
(DbgModelTargetRegisterContainer) getCachedAttribute("Registers"); (DbgModelTargetRegisterContainer) getCachedAttribute("Registers");
delegates.add((DelegateDbgModel2TargetObject) container.getDelegate()); delegates.add((DelegateDbgModel2TargetObject) container.getDelegate());

View file

@ -454,6 +454,7 @@
<attribute name="rdi" schema="RegisterDescriptor" required="yes" /> <attribute name="rdi" schema="RegisterDescriptor" required="yes" />
<attribute name="rsi" schema="RegisterDescriptor" required="yes" /> <attribute name="rsi" schema="RegisterDescriptor" required="yes" />
<attribute name="rip" schema="RegisterDescriptor" required="yes" /> <attribute name="rip" schema="RegisterDescriptor" required="yes" />
<attribute name="rbp" schema="RegisterDescriptor" required="yes" />
<attribute name="rsp" schema="RegisterDescriptor" required="yes" /> <attribute name="rsp" schema="RegisterDescriptor" required="yes" />
<attribute name="r8" schema="RegisterDescriptor" required="yes" /> <attribute name="r8" schema="RegisterDescriptor" required="yes" />
<attribute name="r9" schema="RegisterDescriptor" required="yes" /> <attribute name="r9" schema="RegisterDescriptor" required="yes" />
@ -464,6 +465,31 @@
<attribute name="r14" schema="RegisterDescriptor" required="yes" /> <attribute name="r14" schema="RegisterDescriptor" required="yes" />
<attribute name="r15" schema="RegisterDescriptor" required="yes" /> <attribute name="r15" schema="RegisterDescriptor" required="yes" />
<attribute name="efl" schema="RegisterDescriptor" required="yes" /> <attribute name="efl" schema="RegisterDescriptor" required="yes" />
<attribute name="dr0" schema="RegisterDescriptor" required="no" />
<attribute name="dr1" schema="RegisterDescriptor" required="no" />
<attribute name="dr2" schema="RegisterDescriptor" required="no" />
<attribute name="dr3" schema="RegisterDescriptor" required="no" />
<attribute name="dr6" schema="RegisterDescriptor" required="no" />
<attribute name="dr7" schema="RegisterDescriptor" required="no" />
<attribute name="cs" schema="RegisterDescriptor" required="no" />
<attribute name="ds" schema="RegisterDescriptor" required="no" />
<attribute name="es" schema="RegisterDescriptor" required="no" />
<attribute name="fs" schema="RegisterDescriptor" required="no" />
<attribute name="gs" schema="RegisterDescriptor" required="no" />
<attribute name="ss" schema="RegisterDescriptor" required="no" />
<attribute name="af" schema="RegisterDescriptor" required="no" />
<attribute name="cf" schema="RegisterDescriptor" required="no" />
<attribute name="df" schema="RegisterDescriptor" required="no" />
<attribute name="if" schema="RegisterDescriptor" required="no" />
<attribute name="of" schema="RegisterDescriptor" required="no" />
<attribute name="pf" schema="RegisterDescriptor" required="no" />
<attribute name="sf" schema="RegisterDescriptor" required="no" />
<attribute name="tf" schema="RegisterDescriptor" required="no" />
<attribute name="zf" schema="RegisterDescriptor" required="no" />
<attribute name="iopl" schema="RegisterDescriptor" required="no" />
<attribute name="vif" schema="RegisterDescriptor" required="no" />
<attribute name="vip" schema="RegisterDescriptor" required="no" />
<attribute name="rflags" schema="RegisterDescriptor" required="no" />
<attribute schema="OBJECT" /> <attribute schema="OBJECT" />
</schema> </schema>
<schema name="Stack" canonical="yes" elementResync="NEVER" attributeResync="NEVER"> <schema name="Stack" canonical="yes" elementResync="NEVER" attributeResync="NEVER">

View file

@ -52,6 +52,8 @@ public class DebuggerPlaceBreakpointDialog extends DialogComponentProvider {
private JTextField fieldLength; private JTextField fieldLength;
private JComboBox<String> fieldKinds; private JComboBox<String> fieldKinds;
private JTextField fieldName; private JTextField fieldName;
private PluginTool tool;
private String statusText = null;
public DebuggerPlaceBreakpointDialog() { public DebuggerPlaceBreakpointDialog() {
super(AbstractSetBreakpointAction.NAME, true, true, true, false); super(AbstractSetBreakpointAction.NAME, true, true, true, false);
@ -150,10 +152,12 @@ public class DebuggerPlaceBreakpointDialog extends DialogComponentProvider {
this.fieldLength.setText(Long.toUnsignedString(length)); this.fieldLength.setText(Long.toUnsignedString(length));
this.fieldKinds.setSelectedItem(TraceBreakpointKindSet.encode(kinds)); this.fieldKinds.setSelectedItem(TraceBreakpointKindSet.encode(kinds));
this.fieldName.setText(""); this.fieldName.setText("");
this.tool = tool;
validateAddress(); validateAddress();
setTitle(title); setTitle(title);
statusText = null;
tool.showDialog(this); tool.showDialog(this);
} }
@ -181,13 +185,20 @@ public class DebuggerPlaceBreakpointDialog extends DialogComponentProvider {
name = fieldName.getText(); name = fieldName.getText();
ProgramLocation loc = new ProgramLocation(program, address); ProgramLocation loc = new ProgramLocation(program, address);
service.placeBreakpointAt(loc, length, kinds, name).thenAccept(__ -> { service.placeBreakpointAt(loc, length, kinds, name).exceptionally(ex -> {
close();
}).exceptionally(ex -> {
ex = AsyncUtils.unwrapThrowable(ex); ex = AsyncUtils.unwrapThrowable(ex);
setStatusText(ex.getMessage(), MessageType.ERROR, true); statusText = ex.getMessage(); // will be set when dialog is shown later
tool.showDialog(this);
return null; return null;
}); });
close();
}
@Override
protected void dialogShown() {
if (statusText != null) {
setStatusText(statusText, MessageType.ERROR, true);
}
} }
/* testing */ /* testing */

View file

@ -164,15 +164,17 @@ public class DefaultThreadRecorder implements ManagedThreadRecorder {
if (regMapper == null) { if (regMapper == null) {
throw new IllegalStateException("Have not found register descriptions for " + thread); throw new IllegalStateException("Have not found register descriptions for " + thread);
} }
if (!regMapper.getRegistersOnTarget().containsAll(registers)) { List<TargetRegister> tRegs = registers.stream()
throw new IllegalArgumentException( .map(regMapper::traceToTarget)
"All given registers must be recognized by the target"); .filter(Objects::nonNull)
.collect(Collectors.toList());
if (tRegs.size() < registers.size()) {
Msg.warn(this,
"All requested registers must be recognized by the model as registers");
} }
if (registers.isEmpty()) { if (registers.isEmpty()) {
return CompletableFuture.completedFuture(Map.of()); return CompletableFuture.completedFuture(Map.of());
} }
List<TargetRegister> tRegs =
registers.stream().map(regMapper::traceToTarget).collect(Collectors.toList());
Set<TargetRegisterBank> banks = getTargetRegisterBank(thread, frameLevel); Set<TargetRegisterBank> banks = getTargetRegisterBank(thread, frameLevel);
if (banks == null) { if (banks == null) {

View file

@ -416,7 +416,7 @@ public class MarkerManager implements MarkerService {
} }
private Color getBackgroundColor(Program program, MarkerSetCacheEntry entry, Address address) { private Color getBackgroundColor(Program program, MarkerSetCacheEntry entry, Address address) {
return entry.getBackgroundColor(address); return entry == null ? null : entry.getBackgroundColor(address);
} }
public GoToService getGoToService() { public GoToService getGoToService() {