@@ -2860,7 +2860,7 @@ static void gdb_sigterm_handler(int signal)
}
#endif
-int gdbserver_start(const char *device)
+int gdbserver_start(const char *device, unsigned long long hbreak)
{
GDBState *s;
char gdbstub_device_name[128];
@@ -2916,6 +2916,9 @@ int gdbserver_start(const char *device)
s->state = chr ? RS_IDLE : RS_INACTIVE;
s->mon_chr = mon_chr;
+ if (hbreak != (unsigned long long)-1) {
+ gdb_breakpoint_insert(hbreak, 1, GDB_BREAKPOINT_HW);
+ }
return 0;
}
#endif
@@ -35,7 +35,7 @@ void gdb_register_coprocessor(CPUState *env,
#ifdef CONFIG_USER_ONLY
int gdbserver_start(int);
#else
-int gdbserver_start(const char *port);
+int gdbserver_start(const char *port, unsigned long long hbreak);
#endif
/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
@@ -1137,7 +1137,7 @@ static void do_gdbserver(Monitor *mon, const QDict *qdict)
const char *device = qdict_get_try_str(qdict, "device");
if (!device)
device = "tcp::" DEFAULT_GDBSTUB_PORT;
- if (gdbserver_start(device) < 0) {
+ if (gdbserver_start(device, -1) < 0) {
monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
device);
} else if (strcmp(device, "none") == 0) {
@@ -2194,6 +2194,16 @@ Shorthand for -gdb tcp::1234, i.e. open a gdbserver on TCP port 1234
(@pxref{gdb_usage}).
ETEXI
+DEF("hb", HAS_ARG, QEMU_OPTION_breakpoint, \
+ "-hb addr set an hardware breakpoint at address addr\n",
+ QEMU_ARCH_ALL)
+STEXI
+@item -hb @var{addr}
+@findex -hb
+Set an hardware breakpoint at address @var{addr}, by default implies "-s".
+ETEXI
+
+
DEF("d", HAS_ARG, QEMU_OPTION_d, \
"-d item1,... output log to /tmp/qemu.log (use -d ? for a list of log items)\n",
QEMU_ARCH_ALL)
@@ -188,6 +188,7 @@ int mem_prealloc = 0; /* force preallocation of physical target memory */
int nb_nics;
NICInfo nd_table[MAX_NICS];
int autostart;
+unsigned long long hbreak;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
QEMUClock *rtc_clock;
@@ -2222,6 +2223,7 @@ int main(int argc, char **argv, char **envp)
nb_nics = 0;
autostart= 1;
+ hbreak = -1;
/* first pass of option parsing */
optind = 1;
@@ -2582,6 +2584,13 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_S:
autostart = 0;
break;
+ case QEMU_OPTION_breakpoint:
+ hbreak = strtoull(optarg, NULL, 0);
+ /* hbreak needs a gdb server */
+ if (gdbstub_dev == NULL) {
+ gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
+ }
+ break;
case QEMU_OPTION_k:
keyboard_layout = optarg;
break;
@@ -3442,7 +3451,7 @@ int main(int argc, char **argv, char **envp)
}
text_consoles_set_display(ds);
- if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
+ if (gdbstub_dev && gdbserver_start(gdbstub_dev, hbreak) < 0) {
fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
gdbstub_dev);
exit(1);
When qemu is started with '-S' to freeze at startup and gdb is connected to inner gdb server, gdb is using by default 16-bit real-mode. Then if we put a breakpoint inside kernel linux, the CPU is switched to 32/64-bit protected mode but GDB is always in 16 bit real-mode. The size of the registers dump differs and GDB is not able to manage it. See the following thread for more details: "Failed to use gdb with qemu 15.1 (with and without kvm support)" http://permalink.gmane.org/gmane.comp.emulators.qemu/133120 By adding a breakpoint at startup, we can connect GDB to qemu gdb server when CPU is already in protected mode. Example: - find the address of the symbol to stop on. $ nm ../linux/vmlinux | grep start_kernel ffffffff81ad391f T start_kernel ffffffff81ad334a T x86_64_start_kernel ffffffff81ad6a9c T xen_start_kernel - Then start qemu with the breakpoint option (-hb): ./x86_64-softmmu/qemu-system-x86_64 -kernel ../linux/arch/x86/boot/bzImage \ -append console=ttyS0 -nographic \ -hb 0xffffffff81ad391f - and now start GDB: $ gdb (gdb) set arch i386:x86-64 The target architecture is assumed to be i386:x86-64 (gdb) sym vmlinux Reading symbols from /home/laurent/linux/vmlinux...done. (gdb) target remote :1234 Remote debugging using :1234 start_kernel () at init/main.c:468 468 { (gdb) x/i $pc => 0xffffffff81ad391f <start_kernel>: push %rbp (gdb) c Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- gdbstub.c | 5 ++++- gdbstub.h | 2 +- monitor.c | 2 +- qemu-options.hx | 10 ++++++++++ vl.c | 11 ++++++++++- 5 files changed, 26 insertions(+), 4 deletions(-)