GP-3207: Fix JNA/COM interface priority (dbgeng/model)

This commit is contained in:
Dan 2023-03-16 15:07:43 -04:00
parent 628642461c
commit 70e0170e03
69 changed files with 589 additions and 762 deletions

View file

@ -16,10 +16,12 @@
package agent.dbgeng.impl.dbgeng;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.IID;
import com.sun.jna.platform.win32.Guid.REFIID;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinNT.HRESULT;
@ -35,28 +37,33 @@ public abstract class DbgEngUtil {
private DbgEngUtil() {
}
public record Preferred<T> (REFIID refiid, Class<? extends T> cls) {
public Preferred(IID iid, Class<? extends T> cls) {
this(new REFIID(iid), cls);
}
}
public static interface InterfaceSupplier {
HRESULT get(REFIID refiid, PointerByReference pClient);
}
@SuppressWarnings("unchecked")
public static <I> I tryPreferredInterfaces(Class<I> cls,
Map<REFIID, ? extends Class<?>> preferred, InterfaceSupplier supplier) {
public static <I, T> I tryPreferredInterfaces(Class<I> cls, List<Preferred<T>> preferred,
InterfaceSupplier supplier) {
PointerByReference ppClient = new PointerByReference();
for (Map.Entry<REFIID, ? extends Class<?>> ent : preferred.entrySet()) {
for (Preferred<T> pref : preferred) {
try {
COMUtils.checkRC(supplier.get(ent.getKey(), ppClient));
COMUtils.checkRC(supplier.get(pref.refiid, ppClient));
if (ppClient.getValue() == null) {
continue;
}
Object impl =
ent.getValue().getConstructor(Pointer.class).newInstance(ppClient.getValue());
Method instanceFor = cls.getMethod("instanceFor", ent.getValue());
T impl = pref.cls.getConstructor(Pointer.class).newInstance(ppClient.getValue());
Method instanceFor = cls.getMethod("instanceFor", pref.cls);
Object instance = instanceFor.invoke(null, impl);
return (I) instance;
}
catch (COMException e) {
Msg.debug(DbgEngUtil.class, e + " (" + ent.getValue() + ")");
Msg.debug(DbgEngUtil.class, e + " (" + pref.cls + ")");
// TODO: Only try next on E_NOINTERFACE?
// Try next
}

View file

@ -15,14 +15,15 @@
*/
package agent.dbgeng.impl.dbgeng.advanced;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.DebugAdvanced;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.jna.dbgeng.advanced.*;
import ghidra.comm.util.BitmaskUniverse;
import ghidra.util.datastruct.WeakValueHashMap;
@ -42,11 +43,10 @@ public interface DebugAdvancedInternal extends DebugAdvanced {
return DbgEngUtil.lazyWeakCache(CACHE, advanced, DebugAdvancedImpl3::new);
}
Map<REFIID, Class<? extends WrapIDebugAdvanced>> PREFERRED_ADVANCED_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugAdvanced3.IID_IDEBUG_ADVANCED3), WrapIDebugAdvanced3.class),
Map.entry(new REFIID(IDebugAdvanced2.IID_IDEBUG_ADVANCED2), WrapIDebugAdvanced2.class),
Map.entry(new REFIID(IDebugAdvanced.IID_IDEBUG_ADVANCED), WrapIDebugAdvanced.class));
List<Preferred<WrapIDebugAdvanced>> PREFERRED_ADVANCED_IIDS = List.of(
new Preferred<>(IDebugAdvanced3.IID_IDEBUG_ADVANCED3, WrapIDebugAdvanced3.class),
new Preferred<>(IDebugAdvanced2.IID_IDEBUG_ADVANCED2, WrapIDebugAdvanced2.class),
new Preferred<>(IDebugAdvanced.IID_IDEBUG_ADVANCED, WrapIDebugAdvanced.class));
static DebugAdvancedInternal tryPreferredInterfaces(InterfaceSupplier supplier) {
return DbgEngUtil.tryPreferredInterfaces(DebugAdvancedInternal.class,

View file

@ -15,14 +15,15 @@
*/
package agent.dbgeng.impl.dbgeng.breakpoint;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.DebugBreakpoint;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.impl.dbgeng.control.DebugControlInternal;
import agent.dbgeng.jna.dbgeng.breakpoint.*;
import ghidra.util.datastruct.WeakValueHashMap;
@ -42,14 +43,10 @@ public interface DebugBreakpointInternal extends DebugBreakpoint {
return DbgEngUtil.lazyWeakCache(CACHE, bp, DebugBreakpointImpl3::new);
}
Map<REFIID, Class<? extends WrapIDebugBreakpoint>> PREFERRED_BREAKPOINT_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugBreakpoint3.IID_IDEBUG_BREAKPOINT3),
WrapIDebugBreakpoint3.class),
Map.entry(new REFIID(IDebugBreakpoint2.IID_IDEBUG_BREAKPOINT2),
WrapIDebugBreakpoint2.class),
Map.entry(new REFIID(IDebugBreakpoint.IID_IDEBUG_BREAKPOINT),
WrapIDebugBreakpoint.class));
List<Preferred<WrapIDebugBreakpoint>> PREFERRED_BREAKPOINT_IIDS = List.of(
new Preferred<>(IDebugBreakpoint3.IID_IDEBUG_BREAKPOINT3, WrapIDebugBreakpoint3.class),
new Preferred<>(IDebugBreakpoint2.IID_IDEBUG_BREAKPOINT2, WrapIDebugBreakpoint2.class),
new Preferred<>(IDebugBreakpoint.IID_IDEBUG_BREAKPOINT, WrapIDebugBreakpoint.class));
static DebugBreakpointInternal tryPreferredInterfaces(DebugControlInternal control,
InterfaceSupplier supplier) {

View file

@ -15,14 +15,15 @@
*/
package agent.dbgeng.impl.dbgeng.client;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.DebugClient;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.impl.dbgeng.control.DebugControlInternal;
import agent.dbgeng.jna.dbgeng.client.*;
import ghidra.util.datastruct.WeakValueHashMap;
@ -66,15 +67,14 @@ public interface DebugClientInternal extends DebugClient {
return DbgEngUtil.lazyWeakCache(CACHE, client, DebugClientImpl7::new);
}
Map<REFIID, Class<? extends WrapIDebugClient>> PREFERRED_CLIENT_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugClient7.IID_IDEBUG_CLIENT7), WrapIDebugClient7.class),
Map.entry(new REFIID(IDebugClient6.IID_IDEBUG_CLIENT6), WrapIDebugClient6.class),
Map.entry(new REFIID(IDebugClient5.IID_IDEBUG_CLIENT5), WrapIDebugClient5.class),
Map.entry(new REFIID(IDebugClient4.IID_IDEBUG_CLIENT4), WrapIDebugClient4.class),
Map.entry(new REFIID(IDebugClient3.IID_IDEBUG_CLIENT3), WrapIDebugClient3.class),
Map.entry(new REFIID(IDebugClient2.IID_IDEBUG_CLIENT2), WrapIDebugClient2.class),
Map.entry(new REFIID(IDebugClient.IID_IDEBUG_CLIENT), WrapIDebugClient.class));
List<Preferred<WrapIDebugClient>> PREFERRED_CLIENT_IIDS = List.of(
new Preferred<>(IDebugClient7.IID_IDEBUG_CLIENT7, WrapIDebugClient7.class),
new Preferred<>(IDebugClient6.IID_IDEBUG_CLIENT6, WrapIDebugClient6.class),
new Preferred<>(IDebugClient5.IID_IDEBUG_CLIENT5, WrapIDebugClient5.class),
new Preferred<>(IDebugClient4.IID_IDEBUG_CLIENT4, WrapIDebugClient4.class),
new Preferred<>(IDebugClient3.IID_IDEBUG_CLIENT3, WrapIDebugClient3.class),
new Preferred<>(IDebugClient2.IID_IDEBUG_CLIENT2, WrapIDebugClient2.class),
new Preferred<>(IDebugClient.IID_IDEBUG_CLIENT, WrapIDebugClient.class));
static DebugClientInternal tryPreferredInterfaces(InterfaceSupplier supplier) {
return DbgEngUtil.tryPreferredInterfaces(DebugClientInternal.class, PREFERRED_CLIENT_IIDS,

View file

@ -15,14 +15,15 @@
*/
package agent.dbgeng.impl.dbgeng.control;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.DebugControl;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.jna.dbgeng.breakpoint.IDebugBreakpoint;
import agent.dbgeng.jna.dbgeng.control.*;
import ghidra.util.datastruct.WeakValueHashMap;
@ -58,15 +59,14 @@ public interface DebugControlInternal extends DebugControl {
return DbgEngUtil.lazyWeakCache(CACHE, control, DebugControlImpl7::new);
}
Map<REFIID, Class<? extends WrapIDebugControl>> PREFERRED_CONTROL_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugControl7.IID_IDEBUG_CONTROL7), WrapIDebugControl7.class),
Map.entry(new REFIID(IDebugControl6.IID_IDEBUG_CONTROL6), WrapIDebugControl6.class),
Map.entry(new REFIID(IDebugControl5.IID_IDEBUG_CONTROL5), WrapIDebugControl5.class),
Map.entry(new REFIID(IDebugControl4.IID_IDEBUG_CONTROL4), WrapIDebugControl4.class),
Map.entry(new REFIID(IDebugControl3.IID_IDEBUG_CONTROL3), WrapIDebugControl3.class),
Map.entry(new REFIID(IDebugControl2.IID_IDEBUG_CONTROL2), WrapIDebugControl2.class),
Map.entry(new REFIID(IDebugControl.IID_IDEBUG_CONTROL), WrapIDebugControl.class));
List<Preferred<WrapIDebugControl>> PREFERRED_CONTROL_IIDS = List.of(
new Preferred<>(IDebugControl7.IID_IDEBUG_CONTROL7, WrapIDebugControl7.class),
new Preferred<>(IDebugControl6.IID_IDEBUG_CONTROL6, WrapIDebugControl6.class),
new Preferred<>(IDebugControl5.IID_IDEBUG_CONTROL5, WrapIDebugControl5.class),
new Preferred<>(IDebugControl4.IID_IDEBUG_CONTROL4, WrapIDebugControl4.class),
new Preferred<>(IDebugControl3.IID_IDEBUG_CONTROL3, WrapIDebugControl3.class),
new Preferred<>(IDebugControl2.IID_IDEBUG_CONTROL2, WrapIDebugControl2.class),
new Preferred<>(IDebugControl.IID_IDEBUG_CONTROL, WrapIDebugControl.class));
static DebugControlInternal tryPreferredInterfaces(InterfaceSupplier supplier) {
return DbgEngUtil.tryPreferredInterfaces(DebugControlInternal.class, PREFERRED_CONTROL_IIDS,

View file

@ -15,14 +15,15 @@
*/
package agent.dbgeng.impl.dbgeng.dataspaces;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.DebugDataSpaces;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.jna.dbgeng.dataspaces.*;
import ghidra.util.datastruct.WeakValueHashMap;
@ -45,16 +46,11 @@ public interface DebugDataSpacesInternal extends DebugDataSpaces {
return DbgEngUtil.lazyWeakCache(CACHE, data, DebugDataSpacesImpl4::new);
}
Map<REFIID, Class<? extends WrapIDebugDataSpaces>> PREFERRED_DATA_SPACES_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugDataSpaces4.IID_IDEBUG_DATA_SPACES4),
WrapIDebugDataSpaces4.class),
Map.entry(new REFIID(IDebugDataSpaces3.IID_IDEBUG_DATA_SPACES3),
WrapIDebugDataSpaces3.class),
Map.entry(new REFIID(IDebugDataSpaces2.IID_IDEBUG_DATA_SPACES2),
WrapIDebugDataSpaces2.class),
Map.entry(new REFIID(IDebugDataSpaces.IID_IDEBUG_DATA_SPACES),
WrapIDebugDataSpaces.class));
List<Preferred<WrapIDebugDataSpaces>> PREFERRED_DATA_SPACES_IIDS = List.of(
new Preferred<>(IDebugDataSpaces4.IID_IDEBUG_DATA_SPACES4, WrapIDebugDataSpaces4.class),
new Preferred<>(IDebugDataSpaces3.IID_IDEBUG_DATA_SPACES3, WrapIDebugDataSpaces3.class),
new Preferred<>(IDebugDataSpaces2.IID_IDEBUG_DATA_SPACES2, WrapIDebugDataSpaces2.class),
new Preferred<>(IDebugDataSpaces.IID_IDEBUG_DATA_SPACES, WrapIDebugDataSpaces.class));
static DebugDataSpacesInternal tryPreferredInterfaces(InterfaceSupplier supplier) {
return DbgEngUtil.tryPreferredInterfaces(DebugDataSpacesInternal.class,

View file

@ -15,14 +15,15 @@
*/
package agent.dbgeng.impl.dbgeng.registers;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.DebugRegisters;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.jna.dbgeng.registers.*;
import ghidra.util.datastruct.WeakValueHashMap;
@ -37,12 +38,9 @@ public interface DebugRegistersInternal extends DebugRegisters {
return DbgEngUtil.lazyWeakCache(CACHE, registers, DebugRegistersImpl2::new);
}
Map<REFIID, Class<? extends WrapIDebugRegisters>> PREFERRED_REGISTERS_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugRegisters2.IID_IDEBUG_REGISTERS2),
WrapIDebugRegisters2.class),
Map.entry(new REFIID(IDebugRegisters.IID_IDEBUG_REGISTERS),
WrapIDebugRegisters.class));
List<Preferred<WrapIDebugRegisters>> PREFERRED_REGISTERS_IIDS = List.of(
new Preferred<>(IDebugRegisters2.IID_IDEBUG_REGISTERS2, WrapIDebugRegisters2.class),
new Preferred<>(IDebugRegisters.IID_IDEBUG_REGISTERS, WrapIDebugRegisters.class));
static DebugRegistersInternal tryPreferredInterfaces(InterfaceSupplier supplier) {
return DbgEngUtil.tryPreferredInterfaces(DebugRegistersInternal.class,

View file

@ -15,15 +15,16 @@
*/
package agent.dbgeng.impl.dbgeng.symbols;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.dbgeng.DebugModule.DebugModuleName;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.jna.dbgeng.symbols.*;
import ghidra.util.datastruct.WeakValueHashMap;
@ -50,13 +51,12 @@ public interface DebugSymbolsInternal extends DebugSymbols {
return DbgEngUtil.lazyWeakCache(CACHE, symbols, DebugSymbolsImpl5::new);
}
Map<REFIID, Class<? extends WrapIDebugSymbols>> PREFFERED_SYMBOLS_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugSymbols5.IID_IDEBUG_SYMBOLS5), WrapIDebugSymbols5.class),
Map.entry(new REFIID(IDebugSymbols4.IID_IDEBUG_SYMBOLS4), WrapIDebugSymbols4.class),
Map.entry(new REFIID(IDebugSymbols3.IID_IDEBUG_SYMBOLS3), WrapIDebugSymbols3.class),
Map.entry(new REFIID(IDebugSymbols2.IID_IDEBUG_SYMBOLS2), WrapIDebugSymbols2.class),
Map.entry(new REFIID(IDebugSymbols.IID_IDEBUG_SYMBOLS), WrapIDebugSymbols.class));
List<Preferred<WrapIDebugSymbols>> PREFFERED_SYMBOLS_IIDS = List.of(
new Preferred<>(IDebugSymbols5.IID_IDEBUG_SYMBOLS5, WrapIDebugSymbols5.class),
new Preferred<>(IDebugSymbols4.IID_IDEBUG_SYMBOLS4, WrapIDebugSymbols4.class),
new Preferred<>(IDebugSymbols3.IID_IDEBUG_SYMBOLS3, WrapIDebugSymbols3.class),
new Preferred<>(IDebugSymbols2.IID_IDEBUG_SYMBOLS2, WrapIDebugSymbols2.class),
new Preferred<>(IDebugSymbols.IID_IDEBUG_SYMBOLS, WrapIDebugSymbols.class));
static DebugSymbolsInternal tryPreferredInterfaces(InterfaceSupplier supplier) {
return DbgEngUtil.tryPreferredInterfaces(DebugSymbolsInternal.class, PREFFERED_SYMBOLS_IIDS,

View file

@ -15,14 +15,15 @@
*/
package agent.dbgeng.impl.dbgeng.sysobj;
import java.util.List;
import java.util.Map;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.REFIID;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.InterfaceSupplier;
import agent.dbgeng.impl.dbgeng.DbgEngUtil.Preferred;
import agent.dbgeng.jna.dbgeng.sysobj.*;
import ghidra.util.datastruct.WeakValueHashMap;
@ -45,16 +46,15 @@ public interface DebugSystemObjectsInternal extends DebugSystemObjects {
return DbgEngUtil.lazyWeakCache(CACHE, sysobj, DebugSystemObjectsImpl4::new);
}
Map<REFIID, Class<? extends WrapIDebugSystemObjects>> PREFERRED_SYSTEM_OBJECTS_IIDS =
Map.ofEntries(
Map.entry(new REFIID(IDebugSystemObjects4.IID_IDEBUG_SYSTEM_OBJECTS4),
WrapIDebugSystemObjects4.class),
Map.entry(new REFIID(IDebugSystemObjects3.IID_IDEBUG_SYSTEM_OBJECTS3),
WrapIDebugSystemObjects3.class),
Map.entry(new REFIID(IDebugSystemObjects2.IID_IDEBUG_SYSTEM_OBJECTS2),
WrapIDebugSystemObjects2.class),
Map.entry(new REFIID(IDebugSystemObjects.IID_IDEBUG_SYSTEM_OBJECTS),
WrapIDebugSystemObjects.class));
List<Preferred<WrapIDebugSystemObjects>> PREFERRED_SYSTEM_OBJECTS_IIDS = List.of(
new Preferred<>(IDebugSystemObjects4.IID_IDEBUG_SYSTEM_OBJECTS4,
WrapIDebugSystemObjects4.class),
new Preferred<>(IDebugSystemObjects3.IID_IDEBUG_SYSTEM_OBJECTS3,
WrapIDebugSystemObjects3.class),
new Preferred<>(IDebugSystemObjects2.IID_IDEBUG_SYSTEM_OBJECTS2,
WrapIDebugSystemObjects2.class),
new Preferred<>(IDebugSystemObjects.IID_IDEBUG_SYSTEM_OBJECTS,
WrapIDebugSystemObjects.class));
static DebugSystemObjectsInternal tryPreferredInterfaces(InterfaceSupplier supplier) {
return DbgEngUtil.tryPreferredInterfaces(DebugSystemObjectsInternal.class,