mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-1076: Adding diagnostic messages, esp., "new session" to GDB connector.
This commit is contained in:
parent
901f888510
commit
18f3075201
7 changed files with 39 additions and 11 deletions
|
@ -48,7 +48,7 @@ public class GdbInJvmDebuggerModelFactory implements DebuggerModelFactory {
|
||||||
public CompletableFuture<? extends DebuggerObjectModel> build() {
|
public CompletableFuture<? extends DebuggerObjectModel> build() {
|
||||||
// TODO: Choose Linux or Windows pty based on host OS
|
// TODO: Choose Linux or Windows pty based on host OS
|
||||||
GdbModelImpl model = new GdbModelImpl(new LinuxPtyFactory());
|
GdbModelImpl model = new GdbModelImpl(new LinuxPtyFactory());
|
||||||
return model.startGDB(gdbCmd, new String[] {}).thenApply(__ -> model);
|
return model.startGDB(existing ? null : gdbCmd, new String[] {}).thenApply(__ -> model);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,7 +22,6 @@ import agent.gdb.pty.ssh.GhidraSshPtyFactory;
|
||||||
import ghidra.dbg.DebuggerModelFactory;
|
import ghidra.dbg.DebuggerModelFactory;
|
||||||
import ghidra.dbg.DebuggerObjectModel;
|
import ghidra.dbg.DebuggerObjectModel;
|
||||||
import ghidra.dbg.util.ConfigurableFactory.FactoryDescription;
|
import ghidra.dbg.util.ConfigurableFactory.FactoryDescription;
|
||||||
import ghidra.dbg.util.ConfigurableFactory.FactoryOption;
|
|
||||||
|
|
||||||
@FactoryDescription(
|
@FactoryDescription(
|
||||||
brief = "GNU gdb via SSH",
|
brief = "GNU gdb via SSH",
|
||||||
|
@ -69,7 +68,7 @@ public class GdbOverSshDebuggerModelFactory implements DebuggerModelFactory {
|
||||||
factory.setUsername(username);
|
factory.setUsername(username);
|
||||||
return new GdbModelImpl(factory);
|
return new GdbModelImpl(factory);
|
||||||
}).thenCompose(model -> {
|
}).thenCompose(model -> {
|
||||||
return model.startGDB(gdbCmd, new String[] {}).thenApply(__ -> model);
|
return model.startGDB(existing ? null : gdbCmd, new String[] {}).thenApply(__ -> model);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package agent.gdb.manager.impl;
|
package agent.gdb.manager.impl;
|
||||||
|
|
||||||
import static ghidra.async.AsyncUtils.*;
|
import static ghidra.async.AsyncUtils.loop;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.*;
|
import java.util.concurrent.atomic.*;
|
||||||
|
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.python.core.PyDictionary;
|
import org.python.core.PyDictionary;
|
||||||
import org.python.util.InteractiveConsole;
|
import org.python.util.InteractiveConsole;
|
||||||
|
@ -612,12 +614,20 @@ public class GdbManagerImpl implements GdbManager {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Pty mi2Pty = ptyFactory.openpty();
|
Pty mi2Pty = ptyFactory.openpty();
|
||||||
Msg.info(this, "Agent is waiting for GDB/MI v2 interpreter at " +
|
String mi2PtyName = mi2Pty.getChild().nullSession();
|
||||||
mi2Pty.getChild().nullSession());
|
Msg.info(this, "Agent is waiting for GDB/MI v2 interpreter at " + mi2PtyName);
|
||||||
mi2Thread = new PtyThread(mi2Pty, Channel.STDOUT, Interpreter.MI2);
|
mi2Thread = new PtyThread(mi2Pty, Channel.STDOUT, Interpreter.MI2);
|
||||||
mi2Thread.setName("GDB Read MI2");
|
mi2Thread.setName("GDB Read MI2");
|
||||||
|
|
||||||
mi2Thread.start();
|
mi2Thread.start();
|
||||||
|
|
||||||
|
int choice = JOptionPane.showConfirmDialog(null,
|
||||||
|
"Please enter \"new-ui mi2 " + mi2PtyName + "\" in an existing gdb session. " +
|
||||||
|
"Alternatively, disable 'use existing session' to launch a new session.",
|
||||||
|
"Waiting for GDB/MI session", JOptionPane.OK_CANCEL_OPTION);
|
||||||
|
if (choice == JOptionPane.CANCEL_OPTION) {
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.*;
|
||||||
import agent.gdb.pty.PtyChild;
|
import agent.gdb.pty.PtyChild;
|
||||||
import agent.gdb.pty.PtySession;
|
import agent.gdb.pty.PtySession;
|
||||||
import agent.gdb.pty.local.LocalProcessPtySession;
|
import agent.gdb.pty.local.LocalProcessPtySession;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public class LinuxPtyChild extends LinuxPtyEndpoint implements PtyChild {
|
public class LinuxPtyChild extends LinuxPtyEndpoint implements PtyChild {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -81,8 +82,14 @@ public class LinuxPtyChild extends LinuxPtyEndpoint implements PtyChild {
|
||||||
}
|
}
|
||||||
builder.inheritIO();
|
builder.inheritIO();
|
||||||
|
|
||||||
|
try {
|
||||||
return new LocalProcessPtySession(builder.start());
|
return new LocalProcessPtySession(builder.start());
|
||||||
}
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Msg.error(this, "Could not start process with args " + args, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected PtySession sessionUsingPythonLeader(String[] args, Map<String, String> env)
|
protected PtySession sessionUsingPythonLeader(String[] args, Map<String, String> env)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package agent.gdb.pty.linux;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import ghidra.util.Msg;
|
||||||
import jnr.posix.POSIX;
|
import jnr.posix.POSIX;
|
||||||
import jnr.posix.POSIXFactory;
|
import jnr.posix.POSIXFactory;
|
||||||
|
|
||||||
|
@ -80,6 +81,7 @@ public class LinuxPtySessionLeader {
|
||||||
checkErr(() -> LIB_POSIX.execv(subArgs.get(0), subArgs.toArray(new String[0])));
|
checkErr(() -> LIB_POSIX.execv(subArgs.get(0), subArgs.toArray(new String[0])));
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
|
Msg.error(this, "Could not execv with args " + subArgs, t);
|
||||||
try {
|
try {
|
||||||
checkErr(() -> LIB_POSIX.dup2(bk, 2));
|
checkErr(() -> LIB_POSIX.dup2(bk, 2));
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import ch.ethz.ssh2.Connection;
|
||||||
import ch.ethz.ssh2.KnownHosts;
|
import ch.ethz.ssh2.KnownHosts;
|
||||||
import docking.DockingWindowManager;
|
import docking.DockingWindowManager;
|
||||||
import docking.widgets.PasswordDialog;
|
import docking.widgets.PasswordDialog;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
public class GhidraSshPtyFactory implements PtyFactory {
|
public class GhidraSshPtyFactory implements PtyFactory {
|
||||||
|
@ -97,7 +98,8 @@ public class GhidraSshPtyFactory implements PtyFactory {
|
||||||
// TODO: Find an API that uses char[] so I can clear it!
|
// TODO: Find an API that uses char[] so I can clear it!
|
||||||
String password = new String(promptPassword(hostname, "Password for " + username));
|
String password = new String(promptPassword(hostname, "Password for " + username));
|
||||||
if (!sshConn.authenticateWithPassword(username, password)) {
|
if (!sshConn.authenticateWithPassword(username, password)) {
|
||||||
throw new IOException("Authentication failed");
|
Msg.error(this, "SSH password authentication failed");
|
||||||
|
throw new IOException("SSH password authentication failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -108,14 +110,16 @@ public class GhidraSshPtyFactory implements PtyFactory {
|
||||||
}
|
}
|
||||||
String password = new String(promptPassword(hostname, "Password for " + pemFile));
|
String password = new String(promptPassword(hostname, "Password for " + pemFile));
|
||||||
if (!sshConn.authenticateWithPublicKey(username, pemFile, password)) {
|
if (!sshConn.authenticateWithPublicKey(username, pemFile, password)) {
|
||||||
throw new IOException("Authentication failed");
|
Msg.error(this, "SSH pukey authentication failed");
|
||||||
|
throw new IOException("SSH pukey authentication failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
success = true;
|
success = true;
|
||||||
return sshConn;
|
return sshConn;
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
throw new IOException("User cancelled", e);
|
Msg.error(this, "SSH connection/authentication cancelled by user");
|
||||||
|
throw new IOException("SSH connection/authentication cancelled by user", e);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|
|
@ -49,7 +49,13 @@ public class SshPtyChild extends SshPtyEndpoint implements PtyChild {
|
||||||
.collect(Collectors.joining(" ")) +
|
.collect(Collectors.joining(" ")) +
|
||||||
" ";
|
" ";
|
||||||
String cmdStr = Stream.of(args).collect(Collectors.joining(" "));
|
String cmdStr = Stream.of(args).collect(Collectors.joining(" "));
|
||||||
|
try {
|
||||||
session.execCommand(envStr + cmdStr);
|
session.execCommand(envStr + cmdStr);
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
Msg.error(this, "Could not execute remote command: " + envStr + cmdStr, t);
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
return new SshPtySession(session);
|
return new SshPtySession(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue