diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-gdb.sh
new file mode 100755
index 0000000000..54bc6932b1
--- /dev/null
+++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/qemu-gdb.sh
@@ -0,0 +1,78 @@
+#!/usr/bin/bash
+## ###
+# IP: GHIDRA
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+#@title qemu + gdb
+#@desc
+#@desc Launch with qemu and connect with gdb
+#@desc This will launch the target on the local machine using qemu. Then in a second
+#@desc terminal, it will connect gdb to QEMU's GDBstub.
+#@desc GDB must already be installed on your system, it must support your target architecture
+#@desc (you may install gdb-multiarch), and it must embed the Python 3 interpreter. You
+#@desc will also need protobuf installed for Python 3.
+#@desc
+#@menu-group qemu
+#@icon icon.debugger
+#@help TraceRmiLauncherServicePlugin#gdb
+#@enum StartCmd:str run start starti
+#@arg :str "Image" "The target binary executable image"
+#@args "Arguments" "Command-line arguments to pass to the target"
+#@env GHIDRA_LANG_EXTTOOL_qemu:str="" "Path to qemu" "The path to qemu for the target architecture."
+#@env QEMU_GDB:int=12345 "QEMU Port" "Port for gdb connection to qemu"
+#@env OPT_EXTRA_QEMU_ARGS:str="" "Extra qemu arguments" "Extra arguments to pass to qemu. Use with care."
+#@env OPT_GDB_PATH:str="gdb-multiarch" "Path to gdb" "The path to gdb. Omit the full path to resolve using the system PATH."
+#@env OPT_EXTRA_TTY:bool=false "QEMU TTY" "Provide a separate terminal emulator for the target."
+#@tty TTY_TARGET if env:OPT_EXTRA_TTY
+
+if [ -d ${GHIDRA_HOME}/ghidra/.git ]
+then
+ export PYTHONPATH=$GHIDRA_HOME/ghidra/Ghidra/Debug/Debugger-agent-gdb/build/pypkg/src:$PYTHONPATH
+ export PYTHONPATH=$GHIDRA_HOME/ghidra/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src:$PYTHONPATH
+elif [ -d ${GHIDRA_HOME}/.git ]
+then
+ export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-agent-gdb/build/pypkg/src:$PYTHONPATH
+ export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src:$PYTHONPATH
+else
+ export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-agent-gdb/pypkg/src:$PYTHONPATH
+ export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/pypkg/src:$PYTHONPATH
+fi
+
+target_image="$1"
+
+if [ -z "$TTY_TARGET" ]
+then
+ "$GHIDRA_LANG_EXTTOOL_qemu" $@ &
+else
+ "$GHIDRA_LANG_EXTTOOL_qemu" $@ <$TTY_TARGET >$TTY_TARGET 2>&1 &
+fi
+
+# Give QEMU a moment to open the socket
+sleep 0.1
+
+"$OPT_GDB_PATH" \
+ -q \
+ -ex "set pagination off" \
+ -ex "set confirm off" \
+ -ex "show version" \
+ -ex "python import ghidragdb" \
+ -ex "file \"$target_image\"" \
+ -ex "set args $target_args" \
+ -ex "set inferior-tty $TTY_TARGET" \
+ -ex "ghidra trace connect \"$GHIDRA_TRACE_RMI_ADDR\"" \
+ -ex "ghidra trace start" \
+ -ex "ghidra trace sync-enable" \
+ -ex "target remote localhost:$QEMU_GDB" \
+ -ex "set confirm on" \
+ -ex "set pagination on"
diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py
index 96a282006d..f861bb550f 100644
--- a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py
+++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py
@@ -513,7 +513,8 @@ def install_hooks():
gdb.events.exited.connect(on_exited) # Inferior exited
gdb.events.clear_objfiles.connect(on_clear_objfiles)
- gdb.events.free_objfile.connect(on_free_objfile)
+ if hasattr(gdb.events, 'free_objfile'):
+ gdb.events.free_objfile.connect(on_free_objfile)
gdb.events.new_objfile.connect(on_new_objfile)
gdb.events.breakpoint_created.connect(on_breakpoint_created)
@@ -547,7 +548,8 @@ def remove_hooks():
gdb.events.exited.disconnect(on_exited) # Inferior exited
gdb.events.clear_objfiles.disconnect(on_clear_objfiles)
- gdb.events.free_objfile.disconnect(on_free_objfile)
+ if hasattr(gdb.events, 'free_objfile'):
+ gdb.events.free_objfile.disconnect(on_free_objfile)
gdb.events.new_objfile.disconnect(on_new_objfile)
gdb.events.breakpoint_created.disconnect(on_breakpoint_created)
diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java
index fcd6bd8e60..ee2e90b327 100644
--- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java
+++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractScriptTraceRmiLaunchOffer.java
@@ -102,6 +102,7 @@ public abstract class AbstractScriptTraceRmiLaunchOffer extends AbstractTraceRmi
List commandLine = new ArrayList<>();
Map env = new HashMap<>(System.getenv());
prepareSubprocess(commandLine, env, args, address);
+ env.put("GHIDRA_LANGUAGE_ID", program.getLanguageID().toString());
for (Map.Entry ent : attrs.extraTtys().entrySet()) {
if (!ent.getValue().isActive(args)) {
diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java
index ab6ac8dc99..1aab3f8287 100644
--- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java
+++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java
@@ -64,6 +64,8 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
public static final String PREFIX_DBGLAUNCH = "DBGLAUNCH_";
public static final String PARAM_DISPLAY_IMAGE = "Image";
+ public static final String PREFIX_PARAM_EXTTOOL = "env:GHIDRA_LANG_EXTTOOL_";
+
public static final int DEFAULT_TIMEOUT_MILLIS = 10000;
protected record PtyTerminalSession(Terminal terminal, Pty pty, PtySession session,
@@ -273,6 +275,15 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
}
paramImage = (ParameterDescription) param;
}
+ else if (param.name.startsWith(PREFIX_PARAM_EXTTOOL)) {
+ String tool = param.name.substring(PREFIX_PARAM_EXTTOOL.length());
+ List names =
+ program.getLanguage().getLanguageDescription().getExternalNames(tool);
+ if (names != null && !names.isEmpty()) {
+ var paramStr = (ParameterDescription) param;
+ paramStr.set(map, names.get(0));
+ }
+ }
}
if (paramImage != null) {
File imageFile = TraceRmiLauncherServicePlugin.getProgramPath(program);
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DefaultModuleMapProposal.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DefaultModuleMapProposal.java
index 3a3465f593..4f49a8aca8 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DefaultModuleMapProposal.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DefaultModuleMapProposal.java
@@ -31,6 +31,16 @@ import ghidra.trace.model.modules.TraceModule;
public class DefaultModuleMapProposal
extends AbstractMapProposal
implements ModuleMapProposal {
+ protected static final int BLOCK_BITS = 12;
+ protected static final int BLOCK_SIZE = 1 << BLOCK_BITS;
+ protected static final long BLOCK_MASK = -1L << BLOCK_BITS;
+
+ protected static AddressRange quantize(AddressRange range) {
+ AddressSpace space = range.getAddressSpace();
+ Address min = space.getAddress(range.getMinAddress().getOffset() & BLOCK_MASK);
+ Address max = space.getAddress(range.getMaxAddress().getOffset() | ~BLOCK_MASK);
+ return new AddressRangeImpl(min, max);
+ }
/**
* A module-program entry in a proposed module map
@@ -129,8 +139,8 @@ public class DefaultModuleMapProposal
public void setProgram(Program program) {
setToObject(program, program);
try {
- this.moduleRange =
- new AddressRangeImpl(getModule().getBase(), computeImageSize(program));
+ this.moduleRange = quantize(
+ new AddressRangeImpl(getModule().getBase(), computeImageSize(program)));
}
catch (AddressOverflowException e) {
// This is terribly unlikely
@@ -203,7 +213,7 @@ public class DefaultModuleMapProposal
private void processModule() {
moduleBase = module.getBase();
try {
- moduleRange = new AddressRangeImpl(moduleBase, imageSize);
+ moduleRange = quantize(new AddressRangeImpl(moduleBase, imageSize));
}
catch (AddressOverflowException e) {
return; // Just score it as having no matches?
diff --git a/Ghidra/Processors/68000/data/languages/68000.ldefs b/Ghidra/Processors/68000/data/languages/68000.ldefs
index c93a4c0df0..075e521cbe 100644
--- a/Ghidra/Processors/68000/data/languages/68000.ldefs
+++ b/Ghidra/Processors/68000/data/languages/68000.ldefs
@@ -17,6 +17,7 @@
+
+
+
+
diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs b/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs
index a33d0cac6a..da3a7b1b3b 100644
--- a/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs
+++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64.ldefs
@@ -14,6 +14,7 @@
+
+
+
+
diff --git a/Ghidra/Processors/ARM/data/languages/ARM.ldefs b/Ghidra/Processors/ARM/data/languages/ARM.ldefs
index 3705510473..972573ac56 100644
--- a/Ghidra/Processors/ARM/data/languages/ARM.ldefs
+++ b/Ghidra/Processors/ARM/data/languages/ARM.ldefs
@@ -23,6 +23,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Processors/Loongarch/data/languages/loongarch.ldefs b/Ghidra/Processors/Loongarch/data/languages/loongarch.ldefs
index e49fbe075b..e0ea214f42 100644
--- a/Ghidra/Processors/Loongarch/data/languages/loongarch.ldefs
+++ b/Ghidra/Processors/Loongarch/data/languages/loongarch.ldefs
@@ -41,6 +41,7 @@
Loongson 3 64-bit with 32-bit FP
+
Loongson 3 64-bit with 64-bit FP
+
\ No newline at end of file
diff --git a/Ghidra/Processors/MIPS/data/languages/mips.ldefs b/Ghidra/Processors/MIPS/data/languages/mips.ldefs
index 17cbf93a8f..bb5e61c939 100644
--- a/Ghidra/Processors/MIPS/data/languages/mips.ldefs
+++ b/Ghidra/Processors/MIPS/data/languages/mips.ldefs
@@ -17,6 +17,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ghidra/Processors/Sparc/data/languages/SparcV9.ldefs b/Ghidra/Processors/Sparc/data/languages/SparcV9.ldefs
index 9121216ec6..2477899954 100644
--- a/Ghidra/Processors/Sparc/data/languages/SparcV9.ldefs
+++ b/Ghidra/Processors/Sparc/data/languages/SparcV9.ldefs
@@ -14,6 +14,7 @@
+
+
diff --git a/Ghidra/Processors/SuperH4/data/languages/SuperH4.ldefs b/Ghidra/Processors/SuperH4/data/languages/SuperH4.ldefs
index d51da4fc99..e1ab74b65d 100644
--- a/Ghidra/Processors/SuperH4/data/languages/SuperH4.ldefs
+++ b/Ghidra/Processors/SuperH4/data/languages/SuperH4.ldefs
@@ -14,6 +14,7 @@
+
+
diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs b/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs
index 45830597eb..94989266b8 100644
--- a/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs
+++ b/Ghidra/Processors/Xtensa/data/languages/xtensa.ldefs
@@ -14,6 +14,7 @@
+
+
diff --git a/Ghidra/Processors/x86/data/languages/x86.ldefs b/Ghidra/Processors/x86/data/languages/x86.ldefs
index 85c0c6801b..49e851632a 100644
--- a/Ghidra/Processors/x86/data/languages/x86.ldefs
+++ b/Ghidra/Processors/x86/data/languages/x86.ldefs
@@ -30,6 +30,7 @@
+
+