mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-02 01:37:11 +08:00
GP-5102: Fix NPE when TraceModule.getBase() is null during mapping.
This commit is contained in:
+7
-5
@@ -26,8 +26,7 @@ import ghidra.app.plugin.core.debug.utils.ProgramURLUtils;
|
|||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.AddressRangeImpl;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.modules.TraceModule;
|
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?
|
// TODO: Note language and prefer those from the same processor?
|
||||||
// Will get difficult with new OBTR, since I'd need a platform
|
// Will get difficult with new OBTR, since I'd need a platform
|
||||||
// There's also the WoW64 issue....
|
// 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
|
protected class ModuleChangeListener
|
||||||
implements DomainObjectListener, DomainObjectClosedListener {
|
implements DomainObjectListener, DomainObjectClosedListener {
|
||||||
@@ -383,7 +381,11 @@ public class ProgramModuleIndexer implements DomainFolderChangeListener {
|
|||||||
|
|
||||||
public DomainFile getBestMatch(TraceModule module, Program currentProgram,
|
public DomainFile getBestMatch(TraceModule module, Program currentProgram,
|
||||||
Collection<IndexEntry> entries) {
|
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) {
|
public List<IndexEntry> getBestEntries(TraceModule module) {
|
||||||
|
|||||||
+29
-27
@@ -69,32 +69,7 @@ import ghidra.util.table.GhidraTable;
|
|||||||
@Category(NightlyCategory.class)
|
@Category(NightlyCategory.class)
|
||||||
public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
DebuggerModulesProvider provider;
|
public static final String CTX_XML = """
|
||||||
|
|
||||||
protected TraceObjectModule modExe;
|
|
||||||
protected TraceObjectSection secExeText;
|
|
||||||
protected TraceObjectSection secExeData;
|
|
||||||
|
|
||||||
protected TraceObjectModule modLib;
|
|
||||||
protected TraceObjectSection secLibText;
|
|
||||||
protected TraceObjectSection secLibData;
|
|
||||||
|
|
||||||
protected SchemaContext ctx;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createTrace(String langID) throws IOException {
|
|
||||||
super.createTrace(langID);
|
|
||||||
try {
|
|
||||||
activateObjectsMode();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void activateObjectsMode() throws Exception {
|
|
||||||
// NOTE the use of index='1' allowing object-based managers to ID unique path
|
|
||||||
ctx = XmlSchemaContext.deserialize("""
|
|
||||||
<context>
|
<context>
|
||||||
<schema name='Session' elementResync='NEVER' attributeResync='ONCE'>
|
<schema name='Session' elementResync='NEVER' attributeResync='ONCE'>
|
||||||
<attribute name='Processes' schema='ProcessContainer' />
|
<attribute name='Processes' schema='ProcessContainer' />
|
||||||
@@ -129,7 +104,34 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
<schema name='Section' elementResync='NEVER' attributeResync='NEVER'>
|
<schema name='Section' elementResync='NEVER' attributeResync='NEVER'>
|
||||||
<interface name='Section' />
|
<interface name='Section' />
|
||||||
</schema>
|
</schema>
|
||||||
</context>""");
|
</context>""";
|
||||||
|
|
||||||
|
DebuggerModulesProvider provider;
|
||||||
|
|
||||||
|
protected TraceObjectModule modExe;
|
||||||
|
protected TraceObjectSection secExeText;
|
||||||
|
protected TraceObjectSection secExeData;
|
||||||
|
|
||||||
|
protected TraceObjectModule modLib;
|
||||||
|
protected TraceObjectSection secLibText;
|
||||||
|
protected TraceObjectSection secLibData;
|
||||||
|
|
||||||
|
protected SchemaContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createTrace(String langID) throws IOException {
|
||||||
|
super.createTrace(langID);
|
||||||
|
try {
|
||||||
|
activateObjectsMode();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateObjectsMode() throws Exception {
|
||||||
|
// NOTE the use of index='1' allowing object-based managers to ID unique path
|
||||||
|
ctx = XmlSchemaContext.deserialize(CTX_XML);
|
||||||
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
tb.trace.getObjectManager().createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
|
|||||||
+25
@@ -25,18 +25,26 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
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;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService.MappedAddressRange;
|
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.framework.model.DomainFile;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
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.*;
|
||||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||||
import ghidra.trace.model.modules.*;
|
import ghidra.trace.model.modules.*;
|
||||||
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.TraceObjectKeyPath;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
// Not technically a GUI test, but must be carried out in the context of a plugin tool
|
// 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.MAX_VALUE, Long.MAX_VALUE);
|
||||||
assertMapsTwoWay(Long.MIN_VALUE, Long.MIN_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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user