GP-2839: issues from review

GP-2839: error checks
GP-2839: base logic for dbgeng options
This commit is contained in:
d-millar 2022-11-15 17:25:26 -05:00
parent 707ec9288d
commit 5409324737
12 changed files with 214 additions and 45 deletions

View File

@ -240,6 +240,39 @@ public interface DebugClient extends DebugClientReentrant {
}
}
public enum DebugEngCreateFlags implements BitmaskUniverse {
DEBUG_ECREATE_PROCESS_DEFAULT(0x00000000),
DEBUG_ECREATE_INHERIT_HANDLES(0x00000001),
DEBUG_ECREATE_USE_VERIFIER_FLAGS(0x00000002),
DEBUG_ECREATE_USE_IMPLICIT_COMMAND_LINE(0x00000004);
DebugEngCreateFlags(int mask) {
this.mask = mask;
}
private final int mask;
@Override
public long getMask() {
return mask;
}
}
public enum DebugVerifierFlags implements BitmaskUniverse {
DEBUG_VERIFIER_DEFAULT(0x00000000);
DebugVerifierFlags(int mask) {
this.mask = mask;
}
private final int mask;
@Override
public long getMask() {
return mask;
}
}
public enum DebugEndSessionFlags {
DEBUG_END_PASSIVE(0x00000000),
DEBUG_END_ACTIVE_TERMINATE(0x00000001),
@ -365,7 +398,10 @@ public interface DebugClient extends DebugClientReentrant {
void attachProcess(DebugServerId si, long processId, BitmaskSet<DebugAttachFlags> attachFlags);
void createProcess(DebugServerId si, String commandLine,
BitmaskSet<DebugCreateFlags> createFlags);
String initialDirectory, String environment,
BitmaskSet<DebugCreateFlags> createFlags,
BitmaskSet<DebugEngCreateFlags> engCreateFlags,
BitmaskSet<DebugVerifierFlags> verifierFlags);
void createProcessAndAttach(DebugServerId si, String commandLine,
BitmaskSet<DebugCreateFlags> createFlags, int processId,

View File

@ -193,9 +193,19 @@ public class DebugClientImpl1 implements DebugClientInternal {
@Override
public void createProcess(DebugServerId si, String commandLine,
BitmaskSet<DebugCreateFlags> createFlags) {
String unusedInitialDirectory, String unusedEnvironment,
BitmaskSet<DebugCreateFlags> createFlags,
BitmaskSet<DebugEngCreateFlags> unusedEngCreateFlags,
BitmaskSet<DebugVerifierFlags> unusedVerifierFlags) {
ULONGLONG ullServer = new ULONGLONG(si.id);
ULONG ulFlags = new ULONG(createFlags.getBitmask());
if (unusedInitialDirectory != null) {
throw new UnsupportedOperationException(
"IDebugClient1 does not support 'initial directory'");
}
if (unusedEnvironment != null) {
throw new UnsupportedOperationException("IDebugClient1 does not support 'environment'");
}
COMUtils.checkRC(jnaClient.CreateProcess(ullServer, commandLine, ulFlags));
}

View File

@ -18,14 +18,12 @@ package agent.dbgeng.impl.dbgeng.client;
import com.sun.jna.Native;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef.*;
import agent.dbgeng.dbgeng.DebugRunningProcess;
import agent.dbgeng.dbgeng.DebugServerId;
import agent.dbgeng.dbgeng.DebugRunningProcess.Description.ProcessDescriptionFlags;
import agent.dbgeng.jna.dbgeng.client.IDebugClient3;
import com.sun.jna.platform.win32.COM.COMUtils;
import agent.dbgeng.dbgeng.DebugRunningProcess;
import agent.dbgeng.dbgeng.DebugRunningProcess.Description.ProcessDescriptionFlags;
import agent.dbgeng.dbgeng.DebugServerId;
import agent.dbgeng.jna.dbgeng.client.IDebugClient3;
import ghidra.comm.util.BitmaskSet;
public class DebugClientImpl3 extends DebugClientImpl2 {
@ -38,9 +36,19 @@ public class DebugClientImpl3 extends DebugClientImpl2 {
@Override
public void createProcess(DebugServerId si, String commandLine,
BitmaskSet<DebugCreateFlags> createFlags) {
String unusedInitialDirectory, String unusedEnvironment,
BitmaskSet<DebugCreateFlags> createFlags,
BitmaskSet<DebugEngCreateFlags> unusedEngCreateFlags,
BitmaskSet<DebugVerifierFlags> unusedVerifierFlags) {
ULONGLONG ullServer = new ULONGLONG(si.id);
ULONG ulFlags = new ULONG(createFlags.getBitmask());
if (unusedInitialDirectory != null) {
throw new UnsupportedOperationException(
"IDebugClient3 does not support 'initial directory'");
}
if (unusedEnvironment != null) {
throw new UnsupportedOperationException("IDebugClient3 does not support 'environment'");
}
COMUtils.checkRC(jnaClient.CreateProcessWide(ullServer, new WString(commandLine), ulFlags));
}

View File

@ -16,16 +16,17 @@
package agent.dbgeng.impl.dbgeng.client;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGLONGByReference;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.COM.COMUtils;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.impl.dbgeng.event.WrapCallbackIDebugEventCallbacksWide;
import agent.dbgeng.impl.dbgeng.io.WrapCallbackIDebugOutputCallbacksWide;
import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_CREATE_PROCESS_OPTIONS;
import agent.dbgeng.jna.dbgeng.client.IDebugClient5;
import agent.dbgeng.jna.dbgeng.event.ListenerIDebugEventCallbacksWide;
import agent.dbgeng.jna.dbgeng.io.ListenerIDebugOutputCallbacksWide;
import ghidra.comm.util.BitmaskSet;
public class DebugClientImpl5 extends DebugClientImpl4 {
private final IDebugClient5 jnaClient;
@ -35,6 +36,26 @@ public class DebugClientImpl5 extends DebugClientImpl4 {
this.jnaClient = jnaClient;
}
@Override
public void createProcess(DebugServerId si, String commandLine,
String initialDirectory, String environment,
BitmaskSet<DebugCreateFlags> createFlags,
BitmaskSet<DebugEngCreateFlags> engCreateFlags,
BitmaskSet<DebugVerifierFlags> verifierFlags) {
ULONGLONG ullServer = new ULONGLONG(si.id);
DEBUG_CREATE_PROCESS_OPTIONS options = new DEBUG_CREATE_PROCESS_OPTIONS();
options.CreateFlags = new ULONG(createFlags.getBitmask());
options.EngCreateFlags = new ULONG(engCreateFlags.getBitmask());
options.VerifierFlags = new ULONG(verifierFlags.getBitmask());
ULONG ulOptionsBufferSize = new ULONG(options.size());
WString cmdLine = new WString(commandLine);
WString initDir = initialDirectory == null ? null : new WString(initialDirectory);
WString env = environment == null ? null : new WString(environment);
COMUtils.checkRC(jnaClient.CreateProcess2Wide(ullServer, cmdLine,
options, ulOptionsBufferSize,
initDir, env));
}
@Override
public void attachKernel(long flags, String options) {
ULONG connectFlags = new ULONG(flags);

View File

@ -503,4 +503,22 @@ public interface DbgEngNative extends StdCallLibrary {
}
}
public static class DEBUG_CREATE_PROCESS_OPTIONS extends Structure {
public static class ByReference extends DEBUG_CREATE_PROCESS_OPTIONS
implements Structure.ByReference {
}
public static final List<String> FIELDS = createFieldsOrder(
"CreateFlags", "EngCreateFlags", "VerifierFlags", "Reserved");
public ULONG CreateFlags;
public ULONG EngCreateFlags;
public ULONG VerifierFlags;
public ULONG Reserved;
@Override
protected List<String> getFieldOrder() {
return FIELDS;
}
}
}

View File

@ -21,6 +21,7 @@ import com.sun.jna.platform.win32.Guid.IID;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_CREATE_PROCESS_OPTIONS;
import agent.dbgeng.jna.dbgeng.UnknownWithUtils.VTableIndex;
import agent.dbgeng.jna.dbgeng.event.IDebugEventCallbacksWide;
import agent.dbgeng.jna.dbgeng.io.IDebugOutputCallbacksWide;
@ -89,7 +90,7 @@ public interface IDebugClient5 extends IDebugClient4 {
HRESULT GetOutputLinePrefixWide(char[] Buffer, ULONG BufferSize, ULONGByReference PrefixSize);
HRESULT SetOuutputLinePrefixWide(WString Prefix);
HRESULT SetOutputLinePrefixWide(WString Prefix);
HRESULT GetIdentityWide(char[] Buffer, ULONG BufferSize, ULONGByReference IdentitySize);
@ -102,7 +103,8 @@ public interface IDebugClient5 extends IDebugClient4 {
HRESULT CreateProcess2(ULONGLONG Server, String CommandLine, Pointer OptionsBuffer,
ULONG OptionsBufferSize, String InitialDirectory, String Environment);
HRESULT CreateProcess2Wide(ULONGLONG Server, WString CommandLine, Pointer OptionsBuffer,
HRESULT CreateProcess2Wide(ULONGLONG Server, WString CommandLine,
DEBUG_CREATE_PROCESS_OPTIONS OptionsBuffer,
ULONG OptionsBufferSize, WString InitialDirectory, WString Environment);
HRESULT CreateProcessAndAttach2(ULONGLONG Server, String CommandLine, Pointer OptionsBuffer,

View File

@ -19,6 +19,7 @@ import com.sun.jna.*;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_CREATE_PROCESS_OPTIONS;
import agent.dbgeng.jna.dbgeng.event.IDebugEventCallbacksWide;
import agent.dbgeng.jna.dbgeng.io.IDebugOutputCallbacksWide;
@ -93,7 +94,7 @@ public class WrapIDebugClient5 extends WrapIDebugClient4 implements IDebugClient
}
@Override
public HRESULT SetOuutputLinePrefixWide(WString Prefix) {
public HRESULT SetOutputLinePrefixWide(WString Prefix) {
return _invokeHR(VTIndices5.SET_OUTPUT_LINE_PREFIX_WIDE, getPointer(), Prefix);
}
@ -127,7 +128,8 @@ public class WrapIDebugClient5 extends WrapIDebugClient4 implements IDebugClient
}
@Override
public HRESULT CreateProcess2Wide(ULONGLONG Server, WString CommandLine, Pointer OptionsBuffer,
public HRESULT CreateProcess2Wide(ULONGLONG Server, WString CommandLine,
DEBUG_CREATE_PROCESS_OPTIONS OptionsBuffer,
ULONG OptionsBufferSize, WString InitialDirectory, WString Environment) {
return _invokeHR(VTIndices5.CREATE_PROCESS2_WIDE, getPointer(), Server, CommandLine,
OptionsBuffer, OptionsBufferSize, InitialDirectory, Environment);

View File

@ -21,7 +21,7 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.dbgeng.DebugClient.DebugCreateFlags;
import agent.dbgeng.dbgeng.DebugClient.*;
import agent.dbgeng.manager.*;
import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent;
import agent.dbgeng.manager.evt.DbgProcessCreatedEvent;
@ -36,10 +36,24 @@ public class DbgLaunchProcessCommand extends AbstractDbgCommand<DbgThread> {
private DbgProcessCreatedEvent created = null;
private boolean completed = false;
private List<String> args;
private String initialDirectory;
private String environment;
private BitmaskSet<DebugCreateFlags> createFlags;
private BitmaskSet<DebugEngCreateFlags> engCreateFlags;
private BitmaskSet<DebugVerifierFlags> verifierFlags;
public DbgLaunchProcessCommand(DbgManagerImpl manager, List<String> args) {
public DbgLaunchProcessCommand(DbgManagerImpl manager, List<String> args,
String initialDirectory, String environment,
BitmaskSet<DebugCreateFlags> createFlags,
BitmaskSet<DebugEngCreateFlags> engCreateFlags,
BitmaskSet<DebugVerifierFlags> verifierFlags) {
super(manager);
this.args = args;
this.initialDirectory = initialDirectory;
this.environment = environment;
this.createFlags = createFlags;
this.engCreateFlags = engCreateFlags;
this.verifierFlags = verifierFlags;
}
@Override
@ -69,15 +83,27 @@ public class DbgLaunchProcessCommand extends AbstractDbgCommand<DbgThread> {
List<String> newArgs = new ArrayList<>();
for (String arg : args) {
String na = arg;
if (arg.startsWith("/")) {
na = na.substring(1);
}
na = na.replace("/", "\\");
newArgs.add(na);
newArgs.add(fixPath(arg));
}
initialDirectory = fixPath(initialDirectory);
environment = fixPath(environment);
dbgeng.createProcess(dbgeng.getLocalServer(), StringUtils.join(newArgs, " "),
BitmaskSet.of(DebugCreateFlags.DEBUG_PROCESS));
initialDirectory, environment, createFlags, engCreateFlags, verifierFlags);
manager.waitForEventEx();
}
private String fixPath(String input) {
if (input.equals("")) {
return null;
}
String output = input;
if (input.startsWith("/")) {
output = output.substring(1);
}
output = output.replace("/", "\\");
output = output.replace("\\0", "\0");
return output;
}
}

View File

@ -47,6 +47,8 @@ import agent.dbgeng.model.iface2.DbgModelTargetObject;
import agent.dbgeng.model.iface2.DbgModelTargetThread;
import ghidra.async.*;
import ghidra.comm.util.BitmaskSet;
import ghidra.dbg.target.TargetLauncher.CmdLineParser;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.util.HandlerMap;
import ghidra.lifecycle.Internal;
@ -1352,12 +1354,37 @@ public class DbgManagerImpl implements DbgManager {
@Override
public CompletableFuture<?> launch(List<String> args) {
return execute(new DbgLaunchProcessCommand(this, args));
BitmaskSet<DebugCreateFlags> cf = BitmaskSet.of(DebugCreateFlags.DEBUG_PROCESS);
BitmaskSet<DebugEngCreateFlags> ef =
BitmaskSet.of(DebugEngCreateFlags.DEBUG_ECREATE_PROCESS_DEFAULT);
BitmaskSet<DebugVerifierFlags> vf =
BitmaskSet.of(DebugVerifierFlags.DEBUG_VERIFIER_DEFAULT);
return execute(new DbgLaunchProcessCommand(this, args,
null, null, cf, ef, vf));
}
@Override
public CompletableFuture<Void> launch(Map<String, ?> args) {
return CompletableFuture.completedFuture(null);
public CompletableFuture<Void> launch(Map<String, ?> map) {
List<String> args =
CmdLineParser.tokenize(TargetCmdLineLauncher.PARAMETER_CMDLINE_ARGS.get(map));
String initDir = (String) map.get("dir");
String env = (String) map.get("env");
Integer cfVal = (Integer) map.get("cf");
Integer efVal = (Integer) map.get("ef");
Integer vfVal = (Integer) map.get("vf");
BitmaskSet<DebugCreateFlags> cf =
new BitmaskSet<DebugCreateFlags>(DebugCreateFlags.class,
cfVal == null ? 1 : cfVal);
BitmaskSet<DebugEngCreateFlags> ef =
new BitmaskSet<DebugEngCreateFlags>(DebugEngCreateFlags.class,
efVal == null ? 0 : efVal);
BitmaskSet<DebugVerifierFlags> vf =
new BitmaskSet<DebugVerifierFlags>(DebugVerifierFlags.class,
vfVal == null ? 0 : vfVal);
execute(new DbgLaunchProcessCommand(this, args,
initDir, env, cf, ef, vf));
return AsyncUtils.NIL;
}
public CompletableFuture<?> openFile(Map<String, ?> args) {

View File

@ -19,9 +19,6 @@ import java.util.*;
import java.util.concurrent.CompletableFuture;
import agent.dbgeng.model.iface2.DbgModelTargetConnector;
import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec;
import ghidra.dbg.error.DebuggerUserException;
import ghidra.dbg.target.TargetMethod;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
@ -63,8 +60,24 @@ public class DbgModelTargetProcessLaunchConnectorImpl extends DbgModelTargetObje
HashMap<String, ParameterDescription<?>> map =
new HashMap<String, ParameterDescription<?>>();
ParameterDescription<String> param = ParameterDescription.create(String.class, "args", true,
"", "Cmd", "executable to be launched");
null, "Cmd", "executable to be launched");
ParameterDescription<String> initDir =
ParameterDescription.create(String.class, "dir", false,
null, "Dir", "initial directory");
ParameterDescription<String> env = ParameterDescription.create(String.class, "env", false,
null, "Env (sep=/0)", "environment block");
ParameterDescription<Integer> cf = ParameterDescription.create(Integer.class, "cf", true,
1, "Create Flags", "creation flags");
ParameterDescription<Integer> ef = ParameterDescription.create(Integer.class, "ef", false,
0, "Create Flags (Eng)", "engine creation flags");
ParameterDescription<Integer> vf = ParameterDescription.create(Integer.class, "vf", false,
0, "Verifier Flags", "verifier flags");
map.put("args", param);
map.put("dir", initDir);
map.put("env", env);
map.put("cf", cf);
map.put("ef", ef);
map.put("vf", vf);
return map;
}
@ -75,15 +88,14 @@ public class DbgModelTargetProcessLaunchConnectorImpl extends DbgModelTargetObje
@Override
public CompletableFuture<Void> launch(Map<String, ?> args) {
return launch(
CmdLineParser.tokenize(TargetCmdLineLauncher.PARAMETER_CMDLINE_ARGS.get(args)));
return getManager().launch(args);
}
public CompletableFuture<Void> launch(List<String> args) {
return AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
getManager().launch(args).handle(seq::nextIgnore);
}).finish().exceptionally((exc) -> {
throw new DebuggerUserException("Launch failed for " + args);
});
}
// public CompletableFuture<Void> launch(List<String> args) {
// return AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
// getManager().launch(args).handle(seq::nextIgnore);
// }).finish().exceptionally((exc) -> {
// throw new DebuggerUserException("Launch failed for " + args);
// });
// }
}

View File

@ -16,7 +16,7 @@
package agent.dbgeng.dbgeng;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeTrue;
import static org.junit.Assume.*;
import java.io.*;
import java.nio.ByteBuffer;
@ -848,8 +848,10 @@ public class DbgEngTest extends AbstractGhidraHeadlessIntegrationTest {
//System.out.println("Attaching...");
//client.attachProcess(client.getLocalServer(), proc.pid, BitmaskSet.of());
client.createProcess(client.getLocalServer(), specimenA,
BitmaskSet.of(DebugCreateFlags.DEBUG_PROCESS));
client.createProcess(client.getLocalServer(), specimenA, "", "",
BitmaskSet.of(DebugCreateFlags.DEBUG_PROCESS),
BitmaskSet.of(DebugEngCreateFlags.DEBUG_ECREATE_PROCESS_DEFAULT),
BitmaskSet.of(DebugVerifierFlags.DEBUG_VERIFIER_DEFAULT));
cb.lastReg = null;
//while (cb.lastReg == null) {

View File

@ -109,8 +109,13 @@ public class WrappedDbgModel
@Override
public void createProcess(DebugServerId si, String commandLine,
BitmaskSet<DebugCreateFlags> createFlags) {
client.createProcess(si, commandLine, createFlags);
String initialDirectory, String environment,
BitmaskSet<DebugCreateFlags> createFlags,
BitmaskSet<DebugEngCreateFlags> engCreateFlags,
BitmaskSet<DebugVerifierFlags> verifierFlags) {
client.createProcess(si, commandLine,
initialDirectory, environment,
createFlags, engCreateFlags, verifierFlags);
}
@Override