mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-02 16:33:49 +00:00
GP-1309: Making GDB manager's line separator configurable
.
This commit is contained in:
parent
0655f76e91
commit
6cc519f2aa
|
@ -44,6 +44,8 @@ public class GdbInJvmDebuggerModelFactory implements DebuggerModelFactory {
|
|||
public final Property<Boolean> useExistingOption =
|
||||
Property.fromAccessors(boolean.class, this::isUseExisting, this::setUseExisting);
|
||||
|
||||
// TODO: newLine option?
|
||||
|
||||
@Override
|
||||
public CompletableFuture<? extends DebuggerObjectModel> build() {
|
||||
// TODO: Choose Linux or Windows pty based on host OS
|
||||
|
|
|
@ -58,6 +58,12 @@ public class GdbOverSshDebuggerModelFactory implements DebuggerModelFactory {
|
|||
public final Property<String> keyFileOption =
|
||||
Property.fromAccessors(String.class, this::getKeyFile, this::setKeyFile);
|
||||
|
||||
// Always default to false, despite local system, because remote is likely Linux.
|
||||
private boolean useCrlf = false;
|
||||
@FactoryOption("Use DOS line endings (unchecked for UNIX)")
|
||||
public final Property<Boolean> crlfNewLineOption =
|
||||
Property.fromAccessors(Boolean.class, this::isUseCrlf, this::setUseCrlf);
|
||||
|
||||
@Override
|
||||
public CompletableFuture<? extends DebuggerObjectModel> build() {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
@ -68,6 +74,12 @@ public class GdbOverSshDebuggerModelFactory implements DebuggerModelFactory {
|
|||
factory.setUsername(username);
|
||||
return new GdbModelImpl(factory);
|
||||
}).thenCompose(model -> {
|
||||
if (useCrlf) {
|
||||
model.setDosNewLine();
|
||||
}
|
||||
else {
|
||||
model.setUnixNewLine();
|
||||
}
|
||||
return model.startGDB(existing ? null : gdbCmd, new String[] {}).thenApply(__ -> model);
|
||||
});
|
||||
}
|
||||
|
@ -125,4 +137,12 @@ public class GdbOverSshDebuggerModelFactory implements DebuggerModelFactory {
|
|||
public void setKeyFile(String keyFile) {
|
||||
this.keyFile = keyFile;
|
||||
}
|
||||
|
||||
public boolean isUseCrlf() {
|
||||
return useCrlf;
|
||||
}
|
||||
|
||||
public void setUseCrlf(boolean useCrlf) {
|
||||
this.useCrlf = useCrlf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ public class GdbLocalDebuggerModelFactory extends AbstractGadpLocalDebuggerModel
|
|||
public final Property<Boolean> useExistingOption =
|
||||
Property.fromAccessors(boolean.class, this::isUseExisting, this::setUseExisting);
|
||||
|
||||
// TODO: newLine option?
|
||||
|
||||
@Override
|
||||
public boolean isCompatible() {
|
||||
// TODO: Could potentially support GDB on Windows, but the pty thing would need porting.
|
||||
|
|
|
@ -107,6 +107,37 @@ public interface GdbManager extends AutoCloseable, GdbBreakpointInsertions {
|
|||
return new GdbManagerImpl(ptyFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the line terminator (separator) used to serialize commands to GDB
|
||||
*
|
||||
* <p>
|
||||
* Because the manager may be communicating to GDB running remotely, possibly on another
|
||||
* platform, it may be necessary to customize the line terminator. The manager will default to
|
||||
* the line terminator used by the local system, i.e., {@link System#lineSeparator()}.
|
||||
*
|
||||
* <p>
|
||||
* While permitted, it is not advisable to modify this parameter while the manager is running.
|
||||
* Chances are, if this was mis-configured, the manager and session are hopelessly out of sync.
|
||||
* Start a new properly configured session instead.
|
||||
*
|
||||
* @param newLine the line separator to use
|
||||
*/
|
||||
public void setNewLine(String newLine);
|
||||
|
||||
/**
|
||||
* Set to UNIX-style (CR) line terminator
|
||||
*/
|
||||
default void setUnixNewLine() {
|
||||
setNewLine("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to DOS-style (CRLF) line terminator
|
||||
*/
|
||||
default void setDosNewLine() {
|
||||
setNewLine("\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch GDB
|
||||
*
|
||||
|
|
|
@ -45,6 +45,7 @@ import ghidra.dbg.util.PrefixMap;
|
|||
import ghidra.framework.Application;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
import sun.misc.Signal;
|
||||
import sun.misc.SignalHandler;
|
||||
|
@ -75,7 +76,7 @@ public class GdbManagerImpl implements GdbManager {
|
|||
}
|
||||
|
||||
private static final boolean LOG_IO =
|
||||
Boolean.getBoolean("agent.gdb.manager.log");
|
||||
Boolean.getBoolean("agent.gdb.manager.log") || SystemUtilities.isInDevelopmentMode();
|
||||
private static PrintWriter DBG_LOG = null;
|
||||
private static final String PROMPT_GDB = "(gdb)";
|
||||
public static final int INTERRUPT_MAX_RETRIES = 3;
|
||||
|
@ -158,6 +159,8 @@ public class GdbManagerImpl implements GdbManager {
|
|||
private PtyThread cliThread;
|
||||
private PtyThread mi2Thread;
|
||||
|
||||
private String newLine = System.lineSeparator();
|
||||
|
||||
private final AsyncLock cmdLock = new AsyncLock();
|
||||
private final AtomicReference<AsyncLock.Hold> cmdLockHold = new AtomicReference<>(null);
|
||||
private ExecutorService executor;
|
||||
|
@ -205,8 +208,11 @@ public class GdbManagerImpl implements GdbManager {
|
|||
try {
|
||||
File userSettings = Application.getUserSettingsDirectory();
|
||||
File logFile = new File(userSettings, "GDB.log");
|
||||
if (!logFile.canWrite()) {
|
||||
throw new AssertionError(logFile.getPath() + " appears to be unwritable");
|
||||
try {
|
||||
logFile.createNewFile();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new AssertionError(logFile.getPath() + " appears to be unwritable", e);
|
||||
}
|
||||
DBG_LOG = new PrintWriter(new FileOutputStream(logFile));
|
||||
}
|
||||
|
@ -559,6 +565,11 @@ public class GdbManagerImpl implements GdbManager {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNewLine(String newLine) {
|
||||
this.newLine = newLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(String gdbCmd, String... args) throws IOException {
|
||||
List<String> fullargs = new ArrayList<>();
|
||||
|
@ -592,7 +603,8 @@ public class GdbManagerImpl implements GdbManager {
|
|||
|
||||
cliThread = iniThread;
|
||||
cliThread.setName("GDB Read CLI");
|
||||
cliThread.writer.println("new-ui mi2 " + mi2Pty.getChild().nullSession());
|
||||
cliThread.writer
|
||||
.print("new-ui mi2 " + mi2Pty.getChild().nullSession() + newLine);
|
||||
cliThread.writer.flush();
|
||||
|
||||
mi2Thread = new PtyThread(mi2Pty, Channel.STDOUT, Interpreter.MI2);
|
||||
|
@ -743,7 +755,7 @@ public class GdbManagerImpl implements GdbManager {
|
|||
Interpreter interpreter = cmd.getInterpreter();
|
||||
PrintWriter wr = getWriter(interpreter);
|
||||
//Msg.debug(this, "STDIN: " + text);
|
||||
wr.println(text);
|
||||
wr.print(text + newLine);
|
||||
wr.flush();
|
||||
if (LOG_IO) {
|
||||
DBG_LOG.println(">" + interpreter + ": " + text);
|
||||
|
|
|
@ -131,6 +131,14 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel {
|
|||
}
|
||||
}
|
||||
|
||||
public void setUnixNewLine() {
|
||||
gdb.setUnixNewLine();
|
||||
}
|
||||
|
||||
public void setDosNewLine() {
|
||||
gdb.setDosNewLine();
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> startGDB(String gdbCmd, String[] args) {
|
||||
try {
|
||||
gdb.start(gdbCmd, args);
|
||||
|
|
Loading…
Reference in a new issue