mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-2966: Consider aliases in debugger register mapping.
This commit is contained in:
parent
942d60eeac
commit
a9c1949742
13 changed files with 276 additions and 55 deletions
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package ghidra.trace.database.guest;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetRegister;
|
||||
|
@ -80,41 +79,58 @@ public interface InternalTracePlatform extends TracePlatform {
|
|||
return result;
|
||||
}
|
||||
|
||||
default List<String> listRegNames(Register register) {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
result.add(register.getName());
|
||||
result.add(register.getName().toUpperCase());
|
||||
result.add(register.getName().toLowerCase());
|
||||
for (String alias : register.getAliases()) {
|
||||
result.add(alias);
|
||||
result.add(alias.toUpperCase());
|
||||
result.add(alias.toLowerCase());
|
||||
}
|
||||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getConventionalRegisterObjectName(Register register) {
|
||||
default Collection<String> getConventionalRegisterObjectNames(Register register) {
|
||||
Address pmin = mapGuestToHost(register.getAddress());
|
||||
if (pmin == null) {
|
||||
return register.getName();
|
||||
return listRegNames(register);
|
||||
}
|
||||
TraceSymbolManager symbolManager = getTrace().getSymbolManager();
|
||||
TraceNamespaceSymbol nsRegMap = symbolManager.namespaces().getGlobalNamed(regMap(register));
|
||||
Collection<? extends TraceLabelSymbol> labels = symbolManager.labels()
|
||||
Collection<String> labels = symbolManager.labels()
|
||||
.getAt(0, null, pmin, false)
|
||||
.stream()
|
||||
.filter(s -> s.getParentNamespace() == nsRegMap)
|
||||
.map(TraceSymbol::getName)
|
||||
.toList();
|
||||
if (labels.isEmpty()) {
|
||||
return register.getName();
|
||||
if (!labels.isEmpty()) {
|
||||
return labels;
|
||||
}
|
||||
// primary is listed first, so take it
|
||||
return labels.iterator().next().getName();
|
||||
return listRegNames(register);
|
||||
}
|
||||
|
||||
@Override
|
||||
default PathMatcher getConventionalRegisterPath(TargetObjectSchema schema, List<String> path,
|
||||
String name) {
|
||||
Collection<String> names) {
|
||||
PathMatcher matcher = schema.searchFor(TargetRegister.class, path, true);
|
||||
if (matcher.isEmpty()) {
|
||||
return matcher;
|
||||
}
|
||||
return matcher.applyKeys(Align.RIGHT, List.of(name));
|
||||
PathMatcher result = new PathMatcher();
|
||||
for (String name:names) {
|
||||
result.addAll(matcher.applyKeys(Align.RIGHT, List.of(name)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
default PathMatcher getConventionalRegisterPath(TargetObjectSchema schema, List<String> path,
|
||||
Register register) {
|
||||
return getConventionalRegisterPath(schema, path,
|
||||
getConventionalRegisterObjectName(register));
|
||||
getConventionalRegisterObjectNames(register));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -156,6 +172,11 @@ public interface InternalTracePlatform extends TracePlatform {
|
|||
if (nsRegMap == null) {
|
||||
nsRegMap = namespaces.add(regMap, globals, SourceType.USER_DEFINED);
|
||||
}
|
||||
TraceLabelSymbol exists = symbolManager.labels()
|
||||
.getChildWithNameAt(objectName, getIntKey(), null, hostAddr, nsRegMap);
|
||||
if (exists != null) {
|
||||
return exists;
|
||||
}
|
||||
return symbolManager.labels()
|
||||
.create(0, null, hostAddr, objectName, nsRegMap, SourceType.USER_DEFINED);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package ghidra.trace.model.guest;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
|
@ -171,27 +172,29 @@ public interface TracePlatform {
|
|||
AddressRange getConventionalRegisterRange(AddressSpace overlay, Register register);
|
||||
|
||||
/**
|
||||
* Get the name or index of the register object for the given platform register
|
||||
* Get the names or indices of the register object for the given platform register
|
||||
*
|
||||
* <p>
|
||||
* This will check for a label in the host physical space, allowing a mapper to specify an
|
||||
* alternative register object name. See {@link #addRegisterMapOverride(Register, String)}.
|
||||
* alternative register object name. See {@link #addRegisterMapOverride(Register, String)}. If
|
||||
* one exists, then only that name is returned. Otherwise, the given register's names and
|
||||
* aliases are all returned as defined and in all-upper and all-lower case.
|
||||
*
|
||||
* @param register the platform register
|
||||
* @return the mapped name
|
||||
*/
|
||||
String getConventionalRegisterObjectName(Register register);
|
||||
Collection<String> getConventionalRegisterObjectNames(Register register);
|
||||
|
||||
/**
|
||||
* Get the expected path where an object defining the register value would be
|
||||
*
|
||||
* @param schema the schema of the register container
|
||||
* @param path the path to the register container
|
||||
* @param name the name of the register on the target
|
||||
* @param names the possible names of the register on the target
|
||||
* @return the path matcher, possibly empty
|
||||
*/
|
||||
PathMatcher getConventionalRegisterPath(TargetObjectSchema schema, List<String> path,
|
||||
String name);
|
||||
Collection<String> names);
|
||||
|
||||
/**
|
||||
* Get the expected path where an object defining the register value would be
|
||||
|
|
|
@ -459,4 +459,23 @@ public class DBTraceObjectRegisterSupportTest extends AbstractGhidraHeadlessInte
|
|||
assertMatches("Targets[0].Threads[0].Registers.User[r0]",
|
||||
b.host.getConventionalRegisterPath(overlay, b.reg("r0")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlatformGetConventionalRegisterPathAlias() throws Throwable {
|
||||
AddressSpace registers = b.trace.getBaseAddressFactory().getRegisterSpace();
|
||||
AddressSpace overlay;
|
||||
Register r0;
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
root = manager.createRootObject(ctx.getSchema(new SchemaName("Session"))).getChild();
|
||||
r0 = b.language.getRegister("r0");
|
||||
overlay = b.trace.getMemoryManager()
|
||||
.createOverlayAddressSpace("Targets[0].Threads[0].Registers", registers);
|
||||
}
|
||||
|
||||
PathMatcher matcher = b.host.getConventionalRegisterPath(overlay, r0);
|
||||
assertMatches("Targets[0].Threads[0].Registers.User[r0]", matcher);
|
||||
assertMatches("Targets[0].Threads[0].Registers.User[a0]", matcher);
|
||||
assertMatches("Targets[0].Threads[0].Registers.User[R0]", matcher);
|
||||
assertMatches("Targets[0].Threads[0].Registers.User[A0]", matcher);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue