diff mbox series

[v5,04/18] gdbstub: DebugClass added to system mode.

Message ID 20231220162555.19545-5-nicolas.eder@lauterbach.com
State New
Headers show
Series first version of mcdstub | expand

Commit Message

nicolas.eder@lauterbach.com Dec. 20, 2023, 4:25 p.m. UTC
This class is used to abstract debug features between different debuggers
---
 debug/common/debug.c     | 33 +++++++++++++++++++++++++++++++++
 debug/common/meson.build |  1 +
 debug/gdbstub/system.c   | 18 ++++++++++++++++++
 debug/meson.build        |  1 +
 include/hw/boards.h      |  1 +
 include/qemu/debug.h     | 20 ++++++++++++++++++++
 include/qemu/typedefs.h  |  2 ++
 system/cpus.c            |  9 ++++++++-
 8 files changed, 84 insertions(+), 1 deletion(-)

Comments

Alex Bennée Feb. 29, 2024, 4:35 p.m. UTC | #1
Nicolas Eder <nicolas.eder@lauterbach.com> writes:

> This class is used to abstract debug features between different debuggers
> ---
>  debug/common/debug.c     | 33 +++++++++++++++++++++++++++++++++
>  debug/common/meson.build |  1 +
>  debug/gdbstub/system.c   | 18 ++++++++++++++++++
>  debug/meson.build        |  1 +
>  include/hw/boards.h      |  1 +
>  include/qemu/debug.h     | 20 ++++++++++++++++++++
>  include/qemu/typedefs.h  |  2 ++
>  system/cpus.c            |  9 ++++++++-
>  8 files changed, 84 insertions(+), 1 deletion(-)
>
> diff --git a/debug/common/debug.c b/debug/common/debug.c
> index c24aaf1202..476c969c98 100644
> --- a/debug/common/debug.c
> +++ b/debug/common/debug.c
> @@ -16,3 +16,36 @@
>   *
>   * SPDX-License-Identifier: LGPL-2.0+
>   */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/debug.h"
> +#include "qom/object_interfaces.h"
> +
> +static void debug_instance_init(Object *obj)
> +{
> +}
> +
> +static void debug_finalize(Object *obj)
> +{
> +}
> +
> +static void debug_class_init(ObjectClass *oc, void *data)
> +{
> +}
> +
> +static const TypeInfo debug_info = {
> +    .name = TYPE_DEBUG,
> +    .parent = TYPE_OBJECT,
> +    .instance_size = sizeof(DebugState),
> +    .instance_init = debug_instance_init,
> +    .instance_finalize = debug_finalize,
> +    .class_size = sizeof(DebugClass),
> +    .class_init = debug_class_init
> +};
> +
> +static void debug_register_types(void)
> +{
> +    type_register_static(&debug_info);
> +}

You shouldn't need empty functions if you are not using them. Moreover
you should use the inheritance feature and have something like:

static void gdb_debug_class_init(ObjectClass *klass, void *data)
{
    DebugClass *dc = DEBUG_CLASS(klass);
    dc->set_stop_cpu = gdb_set_stop_cpu;
};

static const TypeInfo debug_info[] = {
    {
        .name = TYPE_DEBUG,
        .parent = TYPE_OBJECT,
        .instance_size = sizeof(DebugState),
        .class_size = sizeof(DebugClass),
        .abstract = true,
    },
    {
        .name = TYPE_GDB_DEBUG,
        .parent = TYPE_DEBUG,
        .class_init = gdb_debug_class_init,
    },
};

DEFINE_TYPES(debug_info)


> +
<snip>
>  
> +/**
> + * gdb_init_debug_class() - initialize gdb-specific DebugClass
> + */
> +static void gdb_init_debug_class(void)
> +{
> +    Object *obj;
> +    obj = object_new(TYPE_DEBUG);
> +    DebugState *ds = DEBUG(obj);
> +    DebugClass *dc = DEBUG_GET_CLASS(ds);
> +    dc->set_stop_cpu = gdb_set_stop_cpu;

This should be part of the class init above

> +    MachineState *ms = MACHINE(qdev_get_machine());
> +    ms->debug_state = ds;
> +}
>          }
>      } else {
> -        gdb_set_stop_cpu(cpu);
> +        MachineState *ms = MACHINE(qdev_get_machine());
> +        DebugState *ds = ms->debug_state;
> +        DebugClass *dc = DEBUG_GET_CLASS(ds);
> +
> +        if (dc->set_stop_cpu) {
> +            dc->set_stop_cpu(cpu);
> +        }

If there is no explicit state perhaps we should just save the class
rather than the instance.

>          qemu_system_debug_request();
>          cpu->stopped = true;
>      }
nicolas.eder@lauterbach.com March 5, 2024, 11:27 a.m. UTC | #2
Hi Alex,

I managed to include all of your feedback except for the one on this patch:

> You shouldn't need empty functions if you are not using them. Moreover
> you should use the inheritance feature and have something like:
>
> static void gdb_debug_class_init(ObjectClass *klass, void *data)
> {
>      DebugClass *dc = DEBUG_CLASS(klass);
>      dc->set_stop_cpu = gdb_set_stop_cpu;
> };
>
> static const TypeInfo debug_info[] = {
>      {
>          .name = TYPE_DEBUG,
>          .parent = TYPE_OBJECT,
>          .instance_size = sizeof(DebugState),
>          .class_size = sizeof(DebugClass),
>          .abstract = true,
>      },
>      {
>          .name = TYPE_GDB_DEBUG,
>          .parent = TYPE_DEBUG,
>          .class_init = gdb_debug_class_init,
>      },
> };
>
> DEFINE_TYPES(debug_info)

My approach was to delete debug/common/debug.c and put the above code 
into debug/gdbstub/system.c and an analog version for MCD in 
debug/mcdstub/mcdstub.c. However, I don't know when to store the 
DebugClass to the MachineState (MachineState *ms = 
MACHINE(qdev_get_machine()); ms->debug_class = dc;). It doesn't seem to 
work when inside of gdb_debug_class_init().

I still lack an understanding of when/how exactly gdb_debug_class_init() 
is called.

Was my approach wrong and when should I store the DebugClass?

Best regards,

Nicolas
diff mbox series

Patch

diff --git a/debug/common/debug.c b/debug/common/debug.c
index c24aaf1202..476c969c98 100644
--- a/debug/common/debug.c
+++ b/debug/common/debug.c
@@ -16,3 +16,36 @@ 
  *
  * SPDX-License-Identifier: LGPL-2.0+
  */
+
+#include "qemu/osdep.h"
+#include "qemu/debug.h"
+#include "qom/object_interfaces.h"
+
+static void debug_instance_init(Object *obj)
+{
+}
+
+static void debug_finalize(Object *obj)
+{
+}
+
+static void debug_class_init(ObjectClass *oc, void *data)
+{
+}
+
+static const TypeInfo debug_info = {
+    .name = TYPE_DEBUG,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(DebugState),
+    .instance_init = debug_instance_init,
+    .instance_finalize = debug_finalize,
+    .class_size = sizeof(DebugClass),
+    .class_init = debug_class_init
+};
+
+static void debug_register_types(void)
+{
+    type_register_static(&debug_info);
+}
+
+type_init(debug_register_types);
diff --git a/debug/common/meson.build b/debug/common/meson.build
index e69de29bb2..815cb6f0fc 100644
--- a/debug/common/meson.build
+++ b/debug/common/meson.build
@@ -0,0 +1 @@ 
+system_ss.add(files('debug.c'))
diff --git a/debug/gdbstub/system.c b/debug/gdbstub/system.c
index 83fd452800..06bc580147 100644
--- a/debug/gdbstub/system.c
+++ b/debug/gdbstub/system.c
@@ -14,6 +14,7 @@ 
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "qemu/cutils.h"
+#include "qemu/debug.h"
 #include "exec/gdbstub.h"
 #include "gdbstub/syscalls.h"
 #include "exec/hwaddr.h"
@@ -46,6 +47,20 @@  static void reset_gdbserver_state(void)
     gdbserver_state.allow_stop_reply = false;
 }
 
+/**
+ * gdb_init_debug_class() - initialize gdb-specific DebugClass
+ */
+static void gdb_init_debug_class(void)
+{
+    Object *obj;
+    obj = object_new(TYPE_DEBUG);
+    DebugState *ds = DEBUG(obj);
+    DebugClass *dc = DEBUG_GET_CLASS(ds);
+    dc->set_stop_cpu = gdb_set_stop_cpu;
+    MachineState *ms = MACHINE(qdev_get_machine());
+    ms->debug_state = ds;
+}
+
 /*
  * Return the GDB index for a given vCPU state.
  *
@@ -405,6 +420,9 @@  int gdbserver_start(const char *device)
     gdbserver_system_state.mon_chr = mon_chr;
     gdb_syscall_reset();
 
+    /* create new debug object */
+    gdb_init_debug_class();
+
     return 0;
 }
 
diff --git a/debug/meson.build b/debug/meson.build
index a5b093f31e..f46ab14af9 100644
--- a/debug/meson.build
+++ b/debug/meson.build
@@ -1 +1,2 @@ 
+subdir('common')
 subdir('gdbstub')
diff --git a/include/hw/boards.h b/include/hw/boards.h
index da85f86efb..2e28913afc 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -400,6 +400,7 @@  struct MachineState {
     CpuTopology smp;
     struct NVDIMMState *nvdimms_state;
     struct NumaState *numa_state;
+    DebugState *debug_state;
 };
 
 #define DEFINE_MACHINE(namestr, machine_initfn) \
diff --git a/include/qemu/debug.h b/include/qemu/debug.h
index c24aaf1202..9526f9fb48 100644
--- a/include/qemu/debug.h
+++ b/include/qemu/debug.h
@@ -16,3 +16,23 @@ 
  *
  * SPDX-License-Identifier: LGPL-2.0+
  */
+
+#ifndef QEMU_DEBUG_H
+#define QEMU_DEBUG_H
+
+#include "qom/object.h"
+#include "qemu/typedefs.h"
+
+struct DebugClass {
+    ObjectClass parent_class;
+    void (*set_stop_cpu)(CPUState *cpu);
+};
+
+struct DebugState {
+    Object parent_obj;
+};
+
+#define TYPE_DEBUG "debug"
+OBJECT_DECLARE_TYPE(DebugState, DebugClass, DEBUG)
+
+#endif /* QEMU_DEBUG_H */
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 5abdbc3874..e48b544173 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -46,6 +46,8 @@  typedef struct CpuInfoFast CpuInfoFast;
 typedef struct CPUJumpCache CPUJumpCache;
 typedef struct CPUState CPUState;
 typedef struct CPUTLBEntryFull CPUTLBEntryFull;
+typedef struct DebugClass DebugClass;
+typedef struct DebugState DebugState;
 typedef struct DeviceListener DeviceListener;
 typedef struct DeviceState DeviceState;
 typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
diff --git a/system/cpus.c b/system/cpus.c
index a444a747f0..7a7fff14bc 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -25,6 +25,7 @@ 
 #include "qemu/osdep.h"
 #include "monitor/monitor.h"
 #include "qemu/coroutine-tls.h"
+#include "qemu/debug.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-machine.h"
 #include "qapi/qapi-commands-misc.h"
@@ -313,7 +314,13 @@  void cpu_handle_guest_debug(CPUState *cpu)
             cpu_single_step(cpu, 0);
         }
     } else {
-        gdb_set_stop_cpu(cpu);
+        MachineState *ms = MACHINE(qdev_get_machine());
+        DebugState *ds = ms->debug_state;
+        DebugClass *dc = DEBUG_GET_CLASS(ds);
+
+        if (dc->set_stop_cpu) {
+            dc->set_stop_cpu(cpu);
+        }
         qemu_system_debug_request();
         cpu->stopped = true;
     }