Merge remote-tracking branch

'origin/GP-5102_Dan_fixProgramModuleIndexer--SQUASHED' into patch
(Closes #7153)
This commit is contained in:
Ryan Kurtz
2024-12-03 10:11:01 -05:00
3 changed files with 74 additions and 45 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.
@@ -26,8 +26,7 @@ import ghidra.app.plugin.core.debug.utils.ProgramURLUtils;
import ghidra.framework.model.*;
import ghidra.framework.options.Options;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.AddressRangeImpl;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.trace.model.modules.TraceModule;
@@ -73,8 +72,7 @@ public class ProgramModuleIndexer implements DomainFolderChangeListener {
// TODO: Note language and prefer those from the same processor?
// Will get difficult with new OBTR, since I'd need a platform
// There's also the WoW64 issue....
protected record IndexEntry(String name, String dfID, NameSource source) {
}
protected record IndexEntry(String name, String dfID, NameSource source) {}
protected class ModuleChangeListener
implements DomainObjectListener, DomainObjectClosedListener {
@@ -383,7 +381,11 @@ public class ProgramModuleIndexer implements DomainFolderChangeListener {
public DomainFile getBestMatch(TraceModule module, Program currentProgram,
Collection<IndexEntry> entries) {
return getBestMatch(module.getBase().getAddressSpace(), module, currentProgram, entries);
Address base = module.getBase();
AddressSpace space = base == null
? module.getTrace().getBaseAddressFactory().getDefaultAddressSpace()
: base.getAddressSpace();
return getBestMatch(space, module, currentProgram, entries);
}
public List<IndexEntry> getBestEntries(TraceModule module) {
@@ -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.
@@ -69,6 +69,43 @@ import ghidra.util.table.GhidraTable;
@Category(NightlyCategory.class)
public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTest {
public static final String CTX_XML = """
<context>
<schema name='Session' elementResync='NEVER' attributeResync='ONCE'>
<attribute name='Processes' schema='ProcessContainer' />
</schema>
<schema name='ProcessContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element index='1' schema='Process' />
</schema>
<schema name='Process' elementResync='NEVER' attributeResync='ONCE'>
<attribute name='Modules' schema='ModuleContainer' />
<attribute name='Memory' schema='RegionContainer' />
</schema>
<schema name='RegionContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element schema='Region' />
</schema>
<schema name='Region' elementResync='NEVER' attributeResync='NEVER'>
<interface name='MemoryRegion' />
</schema>
<schema name='ModuleContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element schema='Module' />
</schema>
<schema name='Module' elementResync='NEVER' attributeResync='NEVER'>
<interface name='Module' />
<attribute name='Sections' schema='SectionContainer' />
</schema>
<schema name='SectionContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element schema='Section' />
</schema>
<schema name='Section' elementResync='NEVER' attributeResync='NEVER'>
<interface name='Section' />
</schema>
</context>""";
DebuggerModulesProvider provider;
protected TraceObjectModule modExe;
@@ -94,42 +131,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
public void activateObjectsMode() throws Exception {
// NOTE the use of index='1' allowing object-based managers to ID unique path
ctx = XmlSchemaContext.deserialize("""
<context>
<schema name='Session' elementResync='NEVER' attributeResync='ONCE'>
<attribute name='Processes' schema='ProcessContainer' />
</schema>
<schema name='ProcessContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element index='1' schema='Process' />
</schema>
<schema name='Process' elementResync='NEVER' attributeResync='ONCE'>
<attribute name='Modules' schema='ModuleContainer' />
<attribute name='Memory' schema='RegionContainer' />
</schema>
<schema name='RegionContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element schema='Region' />
</schema>
<schema name='Region' elementResync='NEVER' attributeResync='NEVER'>
<interface name='MemoryRegion' />
</schema>
<schema name='ModuleContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element schema='Module' />
</schema>
<schema name='Module' elementResync='NEVER' attributeResync='NEVER'>
<interface name='Module' />
<attribute name='Sections' schema='SectionContainer' />
</schema>
<schema name='SectionContainer' canonical='yes' elementResync='NEVER'
attributeResync='ONCE'>
<element schema='Section' />
</schema>
<schema name='Section' elementResync='NEVER' attributeResync='NEVER'>
<interface name='Section' />
</schema>
</context>""");
ctx = XmlSchemaContext.deserialize(CTX_XML);
try (Transaction tx = tb.startTransaction()) {
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
@@ -25,18 +25,26 @@ import org.junit.Test;
import db.Transaction;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProviderTest;
import ghidra.app.services.DebuggerStaticMappingService;
import ghidra.app.services.DebuggerStaticMappingService.MappedAddressRange;
import ghidra.dbg.target.schema.SchemaContext;
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
import ghidra.dbg.target.schema.XmlSchemaContext;
import ghidra.framework.model.DomainFile;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.database.ToyDBTraceBuilder;
import ghidra.trace.database.memory.DBTraceMemoryManager;
import ghidra.trace.database.target.DBTraceObject;
import ghidra.trace.database.target.DBTraceObjectManager;
import ghidra.trace.model.*;
import ghidra.trace.model.memory.TraceMemoryFlag;
import ghidra.trace.model.memory.TraceMemoryRegion;
import ghidra.trace.model.modules.*;
import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.TraceObjectKeyPath;
import ghidra.util.Msg;
// Not technically a GUI test, but must be carried out in the context of a plugin tool
@@ -667,4 +675,21 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg
assertMapsTwoWay(Long.MAX_VALUE, Long.MAX_VALUE);
assertMapsTwoWay(Long.MIN_VALUE, Long.MIN_VALUE);
}
@Test
public void testProposeModuleMappingNullBase() throws Throwable {
DBTraceObject objModBash;
try (Transaction tx = tb.startTransaction()) {
SchemaContext ctx = XmlSchemaContext.deserialize(DebuggerModulesProviderTest.CTX_XML);
DBTraceObjectManager objects = tb.trace.getObjectManager();
objects.createRootObject(ctx.getSchema(new SchemaName("Session")));
objModBash =
objects.createObject(TraceObjectKeyPath.parse("Processes[1].Modules[/bin/bash]"));
objModBash.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
}
TraceModule modBash = objModBash.queryInterface(TraceObjectModule.class);
assertEquals(Map.of(),
mappingService.proposeModuleMaps(List.of(modBash), List.of(program)));
}
}