mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-5271: Fix break/watchpoints with lldb. Many framework changes.
This commit is contained in:
parent
3bfcb8695f
commit
2a41c8fe6b
16 changed files with 335 additions and 260 deletions
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -272,6 +272,13 @@ public class DBTraceBreakpoint
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive(long snap) {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
return lifespan.contains(snap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPlacedSnap() {
|
||||
try (LockHold hold = LockHold.lock(space.lock.readLock())) {
|
||||
|
|
|
@ -196,6 +196,13 @@ public class DBTraceObjectBreakpointLocation
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive(long snap) {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return object.isAlive(snap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lifespan computeSpan() {
|
||||
Lifespan span = TraceObjectBreakpointLocation.super.computeSpan();
|
||||
|
|
|
@ -106,6 +106,13 @@ public class DBTraceObjectBreakpointSpec
|
|||
return computeSpan();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive(long snap) {
|
||||
try (LockHold hold = object.getTrace().lockRead()) {
|
||||
return object.isAlive(snap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPlacedSnap() {
|
||||
return computeMinSnap();
|
||||
|
|
|
@ -163,23 +163,36 @@ public class DBTraceObject extends DBAnnotatedObject implements TraceObject {
|
|||
}
|
||||
}
|
||||
|
||||
protected LifeSet ensureCachedLife() {
|
||||
if (cachedLife != null) {
|
||||
return cachedLife;
|
||||
}
|
||||
MutableLifeSet result = new DefaultLifeSet();
|
||||
getCanonicalParents(Lifespan.ALL).forEach(v -> result.add(v.getLifespan()));
|
||||
cachedLife = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LifeSet getLife() {
|
||||
try (LockHold hold = manager.trace.lockRead()) {
|
||||
if (cachedLife != null) {
|
||||
synchronized (cachedLife) {
|
||||
return DefaultLifeSet.copyOf(cachedLife);
|
||||
}
|
||||
}
|
||||
MutableLifeSet result = new DefaultLifeSet();
|
||||
getCanonicalParents(Lifespan.ALL).forEach(v -> result.add(v.getLifespan()));
|
||||
cachedLife = result;
|
||||
LifeSet result = ensureCachedLife();
|
||||
synchronized (result) {
|
||||
return DefaultLifeSet.copyOf(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive(long snap) {
|
||||
try (LockHold hold = manager.trace.lockRead()) {
|
||||
LifeSet result = ensureCachedLife();
|
||||
synchronized (result) {
|
||||
return result.contains(snap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected DBTraceObject doCreateCanonicalParentObject() {
|
||||
return manager.doCreateObject(path.parent());
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -23,6 +23,7 @@ import ghidra.pcode.exec.SleighUtils;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -105,9 +106,21 @@ public interface TraceBreakpoint extends TraceUniqueObject {
|
|||
* Get the lifespan of this breakpoint
|
||||
*
|
||||
* @return the lifespan
|
||||
* @deprecated Either this method no longer makes sense, or we need to wrap a
|
||||
* {@link TraceObjectValue} instead. Even then, the attribute values can vary over
|
||||
* the lifespan.
|
||||
*/
|
||||
@Deprecated(since = "11.3", forRemoval = true)
|
||||
Lifespan getLifespan();
|
||||
|
||||
/**
|
||||
* Check if the breakpoint is present at the given snap
|
||||
*
|
||||
* @param snap the snap
|
||||
* @return true if alive, false if not
|
||||
*/
|
||||
boolean isAlive(long snap);
|
||||
|
||||
/**
|
||||
* Get the placed snap of this breakpoint
|
||||
*
|
||||
|
|
|
@ -180,6 +180,17 @@ public interface TraceObject extends TraceUniqueObject {
|
|||
*/
|
||||
LifeSet getLife();
|
||||
|
||||
/**
|
||||
* Check if the object is alive at the given snap
|
||||
*
|
||||
* <p>
|
||||
* This is preferable to {@link #getLife()}, when we only need to check one snap
|
||||
*
|
||||
* @param snap the snap
|
||||
* @return true if alive, false if not
|
||||
*/
|
||||
boolean isAlive(long snap);
|
||||
|
||||
/**
|
||||
* Inserts this object at its canonical path for the given lifespan
|
||||
*
|
||||
|
|
|
@ -497,18 +497,23 @@ public interface TraceObjectSchema {
|
|||
public void nextLevel() {
|
||||
Set<T> nextLevel = new HashSet<>();
|
||||
for (T ent : allOnLevel) {
|
||||
if (!descend(ent)) {
|
||||
continue;
|
||||
if (descendAttributes(ent)) {
|
||||
expandAttributes(nextLevel, ent);
|
||||
expandDefaultAttribute(nextLevel, ent);
|
||||
}
|
||||
if (descendElements(ent)) {
|
||||
expandElements(nextLevel, ent);
|
||||
expandDefaultElement(nextLevel, ent);
|
||||
}
|
||||
expandAttributes(nextLevel, ent);
|
||||
expandDefaultAttribute(nextLevel, ent);
|
||||
expandElements(nextLevel, ent);
|
||||
expandDefaultElement(nextLevel, ent);
|
||||
}
|
||||
allOnLevel = nextLevel;
|
||||
}
|
||||
|
||||
public boolean descend(T ent) {
|
||||
public boolean descendAttributes(T ent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean descendElements(T ent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -549,10 +554,15 @@ public interface TraceObjectSchema {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean descend(SearchEntry ent) {
|
||||
public boolean descendAttributes(SearchEntry ent) {
|
||||
return ent.schema.getInterfaces().contains(TraceObjectAggregate.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean descendElements(SearchEntry ent) {
|
||||
return ent.schema.isCanonicalContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expandAttribute(Set<SearchEntry> nextLevel, SearchEntry ent,
|
||||
TraceObjectSchema schema, KeyPath path) {
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
package ghidra.dbg.target.schema;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jdom.JDOMException;
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.trace.model.breakpoint.TraceObjectBreakpointLocation;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.target.schema.*;
|
||||
import ghidra.trace.model.target.schema.DefaultTraceObjectSchema.DefaultAttributeSchema;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.*;
|
||||
|
@ -75,4 +78,35 @@ public class XmlTargetObjectSchemaTest {
|
|||
SchemaContext result = XmlSchemaContext.deserialize(SCHEMA_XML);
|
||||
assertEquals(CTX, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMultipleImpls() throws Exception {
|
||||
SchemaContext ctx = XmlSchemaContext.deserialize("""
|
||||
<context>
|
||||
<schema name="root">
|
||||
<interface name="Aggregate" />
|
||||
<attribute name="Watches" schema="WatchContainer" />
|
||||
<attribute name="Breaks" schema="BreakContainer" />
|
||||
</schema>
|
||||
<schema name="WatchContainer" canonical="yes">
|
||||
<element schema="Watch" />
|
||||
</schema>
|
||||
<schema name="Watch">
|
||||
<interface name="BreakpointSpec" />
|
||||
<interface name="BreakpointLocation" />
|
||||
</schema>
|
||||
<schema name="BreakContainer" canonical="yes">
|
||||
<element schema="Break" />
|
||||
</schema>
|
||||
<schema name="Break">
|
||||
<interface name="BreakpointSpec" />
|
||||
<interface name="BreakpointLocation" />
|
||||
</schema>
|
||||
</context>
|
||||
""");
|
||||
|
||||
KeyPath found = ctx.getSchema(new SchemaName("root"))
|
||||
.searchForSuitable(TraceObjectBreakpointLocation.class, KeyPath.ROOT);
|
||||
assertNotNull(found);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue