From a9c194974275104cd71d83f5a63111096734a9e5 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Thu, 19 Jan 2023 12:48:01 -0500 Subject: [PATCH] GP-2966: Consider aliases in debugger register mapping. --- .../DefaultDebuggerRegisterMapper.java | 38 ++++- .../LargestSubDebuggerRegisterMapper.java | 8 +- .../record/ObjectBasedTraceRecorder.java | 27 +--- .../DefaultDebuggerRegisterMapperTest.java | 132 ++++++++++++++++++ .../java/ghidra/dbg/util/PathMatcher.java | 4 + .../dbg/model/TestDebuggerObjectModel.java | 5 + .../ghidra/dbg/model/TestTargetRegister.java | 9 +- .../model/TestTargetRegisterContainer.java | 11 ++ .../database/guest/InternalTracePlatform.java | 45 ++++-- .../trace/model/guest/TracePlatform.java | 13 +- .../DBTraceObjectRegisterSupportTest.java | 19 +++ Ghidra/Processors/Toy/certification.manifest | 2 +- .../Processors/Toy/data/languages/toy.pspec | 18 +++ 13 files changed, 276 insertions(+), 55 deletions(-) create mode 100644 Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapperTest.java diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapper.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapper.java index 954fbab642..95ed649f58 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapper.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapper.java @@ -51,16 +51,30 @@ public class DefaultDebuggerRegisterMapper implements DebuggerRegisterMapper { collectFilteredLanguageRegs(); } - protected boolean testTraceRegister(Register lReg) { + protected boolean includeTraceRegister(Register lReg) { return lReg.isBaseRegister(); } protected synchronized void collectFilteredLanguageRegs() { for (Register lReg : language.getRegisters()) { - if (!testTraceRegister(lReg)) { + if (!includeTraceRegister(lReg)) { continue; } - filtLanguageRegs.put(normalizeName(lReg.getName()), lReg); + putLanguageRegister(filtLanguageRegs, lReg); + } + } + + protected synchronized void putLanguageRegister(Map map, Register lReg) { + map.put(normalizeName(lReg.getName()), lReg); + for (String alias : lReg.getAliases()) { + map.put(normalizeName(alias), lReg); + } + } + + protected synchronized void removeLanguageRegister(Map map, Register lReg) { + map.remove(normalizeName(lReg.getName())); + for (String alias : lReg.getAliases()) { + map.remove(normalizeName(alias)); } } @@ -70,7 +84,7 @@ public class DefaultDebuggerRegisterMapper implements DebuggerRegisterMapper { if (lReg == null) { return null; } - languageRegs.put(name, lReg); + putLanguageRegister(languageRegs, lReg); return lReg; } @@ -81,7 +95,7 @@ public class DefaultDebuggerRegisterMapper implements DebuggerRegisterMapper { return null; } targetRegs.put(name, tReg); - languageRegs.put(name, lReg); + putLanguageRegister(languageRegs, lReg); return lReg; } @@ -92,7 +106,7 @@ public class DefaultDebuggerRegisterMapper implements DebuggerRegisterMapper { return null; } targetRegs.remove(name); - languageRegs.remove(name); + removeLanguageRegister(languageRegs, lReg); return lReg; } @@ -115,7 +129,17 @@ public class DefaultDebuggerRegisterMapper implements DebuggerRegisterMapper { @Override public synchronized TargetRegister traceToTarget(Register lReg) { - return targetRegs.get(normalizeName(lReg.getName())); + TargetRegister tReg = targetRegs.get(normalizeName(lReg.getName())); + if (tReg != null) { + return tReg; + } + for (String alias : lReg.getAliases()) { + tReg = targetRegs.get(normalizeName(alias)); + if (tReg != null) { + return tReg; + } + } + return null; } @Override diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapper.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapper.java index cf142bcff8..891ff538b1 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapper.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapper.java @@ -40,7 +40,7 @@ public class LargestSubDebuggerRegisterMapper extends DefaultDebuggerRegisterMap } @Override - protected boolean testTraceRegister(Register lReg) { + protected boolean includeTraceRegister(Register lReg) { return true; } @@ -123,7 +123,7 @@ public class LargestSubDebuggerRegisterMapper extends DefaultDebuggerRegisterMap return null; } Register lReg = subs.last(); // largest - return targetRegs.get(normalizeName(lReg.getName())); + return super.traceToTarget(lReg); } @Override @@ -156,7 +156,7 @@ public class LargestSubDebuggerRegisterMapper extends DefaultDebuggerRegisterMap Msg.warn(this, "Potential register cache aliasing: " + lReg + " vs " + subs.last()); /** * After testing, there is a problem with data truncation. If, e.g., EAX is sent, - * followed by AX, and we expand to fill RAX, the we're going to truncate the upper 16 + * followed by AX, and we expand to fill RAX, then we're going to truncate the upper 16 * bits of EAX :( . To avoid this, we'll only map the largest register from target to * trace. We'll still warn as a courtesy, but we'll abort the mapping. */ @@ -164,7 +164,7 @@ public class LargestSubDebuggerRegisterMapper extends DefaultDebuggerRegisterMap } /** * TODO: A mapping with masks may be useful in the future, but as it is, the trace database - * will reject it. Furthermore, we'd still want to mark the whole base register is known, + * will reject it. Furthermore, we'd still want to mark the whole base register as known, * which is not intuitive, and makes me worry about that method. */ // return new RegisterValue(lReg, new BigInteger(1,value)).getBaseRegisterValue(); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/record/ObjectBasedTraceRecorder.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/record/ObjectBasedTraceRecorder.java index fdd73a1ae2..1af0e48d97 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/record/ObjectBasedTraceRecorder.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/record/ObjectBasedTraceRecorder.java @@ -543,9 +543,9 @@ public class ObjectBasedTraceRecorder implements TraceRecorder { } protected TargetRegisterBank isExactRegisterOnTarget(TracePlatform platform, - TargetRegisterContainer regContainer, String name) { + TargetRegisterContainer regContainer, Register register) { PathMatcher matcher = - platform.getConventionalRegisterPath(regContainer.getSchema(), List.of(), name); + platform.getConventionalRegisterPath(regContainer.getSchema(), List.of(), register); for (TargetObject targetObject : matcher.getCachedSuccessors(regContainer).values()) { if (!(targetObject instanceof TargetRegister targetRegister)) { continue; @@ -568,28 +568,7 @@ public class ObjectBasedTraceRecorder implements TraceRecorder { if (regContainer == null) { return null; } - TargetRegisterBank result; - String name = platform.getConventionalRegisterObjectName(register); - result = isExactRegisterOnTarget(platform, regContainer, name); - if (result != null) { - return result; - } - // Not totally case insensitive, but the sane cases - String upperName = name.toUpperCase(); - if (!name.equals(upperName)) { - result = isExactRegisterOnTarget(platform, regContainer, upperName); - if (result != null) { - return result; - } - } - String lowerName = name.toLowerCase(); - if (!name.equals(lowerName)) { - result = isExactRegisterOnTarget(platform, regContainer, lowerName); - if (result != null) { - return result; - } - } - return null; + return isExactRegisterOnTarget(platform, regContainer, register); } @Override diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapperTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapperTest.java new file mode 100644 index 0000000000..49ca41c7ec --- /dev/null +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/DefaultDebuggerRegisterMapperTest.java @@ -0,0 +1,132 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.mapping; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.util.Objects; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; + +import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; +import ghidra.app.services.ActionSource; +import ghidra.app.services.TraceRecorder; +import ghidra.dbg.model.TestTargetRegister; +import ghidra.dbg.model.TestTargetRegisterValue; +import ghidra.dbg.target.TargetObject; +import ghidra.dbg.target.TargetRegister; +import ghidra.program.model.lang.*; +import ghidra.test.ToyProgramBuilder; +import ghidra.trace.model.thread.TraceThread; + +public class DefaultDebuggerRegisterMapperTest extends AbstractGhidraHeadedDebuggerGUITest { + + static class TestTargetMapper extends DefaultDebuggerTargetTraceMapper { + public TestTargetMapper(TargetObject target) + throws LanguageNotFoundException, CompilerSpecNotFoundException { + super(target, new LanguageID(ToyProgramBuilder._TOY64_BE), + new CompilerSpecID("default"), Set.of()); + } + } + + protected static void assertSameRegister(TargetRegister expected, TargetObject actual) { + if (actual instanceof TestTargetRegister tr) { + assertEquals(expected, tr); + } + else if (actual instanceof TestTargetRegisterValue rv) { + assertEquals(expected, rv.desc); + } + else { + fail(); + } + } + + @Before + public void setUpMapperTest() throws Throwable { + createTestModel(); + mb.createTestProcessesAndThreads(); + mb.createTestThreadRegisterBanks(); + } + + protected DebuggerRegisterMapper doGetRegisterMapper(String toConfirm) + throws Throwable { + TraceRecorder recorder = modelService.recordTarget(mb.testProcess1, + new TestTargetMapper(mb.testProcess1), ActionSource.AUTOMATIC); + TraceThread thread1 = waitForValue(() -> recorder.getTraceThread(mb.testThread1)); + DebuggerRegisterMapper rm = waitForValue(() -> recorder.getRegisterMapper(thread1)); + waitForValue(() -> rm.getTargetRegister(toConfirm)); + return rm; + } + + protected DebuggerRegisterMapper getRegisterMapper() throws Throwable { + mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(), r -> true); + return doGetRegisterMapper("r0"); + } + + protected DebuggerRegisterMapper getRegisterMapperAliased() throws Throwable { + Register r0 = getToyBE64Language().getRegister("r0"); + mb.testProcess1.regs.addRegistersFromLanguage(getToyBE64Language(), r -> r != r0); + mb.testProcess1.regs.addRegister("a0", r0); + return doGetRegisterMapper("r1"); + } + + @Test + public void testTraceToTargetRegCanonical() throws Throwable { + DebuggerRegisterMapper rm = getRegisterMapper(); + TestTargetRegister tR0 = + Objects.requireNonNull(mb.testProcess1.regs.getCachedElements().get("r0")); + Register lR0 = Objects.requireNonNull(getToyBE64Language().getRegister("r0")); + + TargetRegister tReg = waitForValue(() -> rm.traceToTarget(lR0)); + assertSameRegister(tR0, tReg); + } + + @Test + public void testTargetToTraceRegCanonical() throws Throwable { + DebuggerRegisterMapper rm = getRegisterMapper(); + TestTargetRegister tR0 = + Objects.requireNonNull(mb.testProcess1.regs.getCachedElements().get("r0")); + Register lR0 = Objects.requireNonNull(getToyBE64Language().getRegister("r0")); + + Register lReg = waitForValue(() -> rm.targetToTrace(tR0)); + assertEquals(lR0, lReg); + } + + @Test + public void testTraceToTargetRegAlias() throws Throwable { + DebuggerRegisterMapper rm = getRegisterMapperAliased(); + TestTargetRegister tA0 = + Objects.requireNonNull(mb.testProcess1.regs.getCachedElements().get("a0")); + Register lR0 = Objects.requireNonNull(getToyBE64Language().getRegister("r0")); + + TargetRegister tReg = waitForValue(() -> rm.traceToTarget(lR0)); + assertSameRegister(tA0, tReg); + } + + @Test + public void testTargetToTraceRegAlias() throws Throwable { + DebuggerRegisterMapper rm = getRegisterMapperAliased(); + TestTargetRegister tA0 = + Objects.requireNonNull(mb.testProcess1.regs.getCachedElements().get("a0")); + Register lR0 = Objects.requireNonNull(getToyBE64Language().getRegister("r0")); + + Register lReg = waitForValue(() -> rm.targetToTrace(tA0)); + assertEquals(lR0, lReg); + } +} diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/util/PathMatcher.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/util/PathMatcher.java index 6e57476d70..92a5361e8b 100644 --- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/util/PathMatcher.java +++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/util/PathMatcher.java @@ -33,6 +33,10 @@ public class PathMatcher implements PathPredicates { patterns.add(pattern); } + public void addAll(PathMatcher matcher) { + patterns.addAll(matcher.patterns); + } + @Override public String toString() { return String.format("", StringUtils.join(patterns, "\n ")); diff --git a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestDebuggerObjectModel.java b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestDebuggerObjectModel.java index 43479a5430..8114db751a 100644 --- a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestDebuggerObjectModel.java +++ b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestDebuggerObjectModel.java @@ -156,6 +156,11 @@ public class TestDebuggerObjectModel extends EmptyDebuggerObjectModel { return TestTargetRegister.fromLanguageRegister(container, register); } + protected TestTargetRegister newTestTargetRegister(TestTargetRegisterContainer container, + String index, Register register) { + return TestTargetRegister.fromLanguageRegister(container, index, register); + } + protected TestTargetThreadContainer newTestTargetThreadContainer(TestTargetProcess process) { return new TestTargetThreadContainer(process); } diff --git a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegister.java b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegister.java index 847d1b8799..9fbf26f81d 100644 --- a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegister.java +++ b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegister.java @@ -27,10 +27,15 @@ public class TestTargetRegister extends DefaultTestTargetObject implements TargetRegister { + public static TestTargetRegister fromLanguageRegister(TestTargetRegisterContainer parent, + String index, Register register) { + return new TestTargetRegister(parent, PathUtils.makeKey(index), + (register.getBitLength() + 7) / 8, register.isProgramCounter()); + } + public static TestTargetRegister fromLanguageRegister( TestTargetRegisterContainer parent, Register register) { - return new TestTargetRegister(parent, PathUtils.makeKey(register.getName()), - (register.getBitLength() + 7) / 8, register.isProgramCounter()); + return fromLanguageRegister(parent, register.getName(), register); } protected final int byteLength; diff --git a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegisterContainer.java b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegisterContainer.java index cc241b071b..8d756805e2 100644 --- a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegisterContainer.java +++ b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/model/TestTargetRegisterContainer.java @@ -61,6 +61,11 @@ public class TestTargetRegisterContainer public TestTargetRegister addRegister(Register register) { TestTargetRegister tr = getModel().newTestTargetRegister(this, Objects.requireNonNull(register)); + doAddRegister(tr, register); + return tr; + } + + protected void doAddRegister(TestTargetRegister tr, Register register) { String reason = "Added " + register + " from Ghidra language"; changeElements(List.of(), List.of(tr), reason); List> banks; @@ -70,6 +75,12 @@ public class TestTargetRegisterContainer for (AbstractTestTargetRegisterBank bank : banks) { bank.addRegisterDescs(List.of(tr), reason); } + } + + public TestTargetRegister addRegister(String index, Register register) { + TestTargetRegister tr = + getModel().newTestTargetRegister(this, index, Objects.requireNonNull(register)); + doAddRegister(tr, register); return tr; } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java index 8f5ad69e37..682bc18530 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/guest/InternalTracePlatform.java @@ -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 listRegNames(Register register) { + Set 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 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 labels = symbolManager.labels() + Collection 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 path, - String name) { + Collection 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 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); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java index 06d6b077a2..db28758d77 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/guest/TracePlatform.java @@ -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 * *

* 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 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 path, - String name); + Collection names); /** * Get the expected path where an object defining the register value would be diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java index a63d447668..556a539854 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/guest/DBTraceObjectRegisterSupportTest.java @@ -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); + } } diff --git a/Ghidra/Processors/Toy/certification.manifest b/Ghidra/Processors/Toy/certification.manifest index 0e477e8798..c7b7516794 100644 --- a/Ghidra/Processors/Toy/certification.manifest +++ b/Ghidra/Processors/Toy/certification.manifest @@ -12,7 +12,7 @@ data/languages/old/v01stuff/toyInstructions.sinc||GHIDRA||||END| data/languages/old/v01stuff/toyPosStack.cspec||GHIDRA||||END| data/languages/toy.cspec||GHIDRA||||END| data/languages/toy.ldefs||GHIDRA||||END| -data/languages/toy.pspec||GHIDRA||reviewed||END| +data/languages/toy.pspec||GHIDRA||||END| data/languages/toy.sinc||GHIDRA||||END| data/languages/toy64-long8.cspec||GHIDRA||||END| data/languages/toy64.cspec||GHIDRA||||END| diff --git a/Ghidra/Processors/Toy/data/languages/toy.pspec b/Ghidra/Processors/Toy/data/languages/toy.pspec index 114b5c47a8..5205bc93d2 100644 --- a/Ghidra/Processors/Toy/data/languages/toy.pspec +++ b/Ghidra/Processors/Toy/data/languages/toy.pspec @@ -2,4 +2,22 @@ + + + + + + + + + + + + + + + + + +