---
debug/mcdstub/mcdstub.c | 300 ++++++++++++++++++++++++++++------------
1 file changed, 215 insertions(+), 85 deletions(-)
diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c
index f97bccf409..d59c4ac078 100644
--- a/debug/mcdstub/mcdstub.c
+++ b/debug/mcdstub/mcdstub.c
@@ -65,6 +65,91 @@ static void mcd_sigterm_handler(int signal)
}
#endif
+/**
+ * mcd_get_process() - Returns the process of the provided pid.
+ *
+ * @pid: The process ID.
+ */
+static MCDProcess *mcd_get_process(uint32_t pid)
+{
+ int i;
+
+ if (!pid) {
+ /* 0 means any process, we take the first one */
+ return &mcdserver_state.processes[0];
+ }
+
+ for (i = 0; i < mcdserver_state.process_num; i++) {
+ if (mcdserver_state.processes[i].pid == pid) {
+ return &mcdserver_state.processes[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * mcd_get_cpu_pid() - Returns the process ID of the provided CPU.
+ *
+ * @cpu: The CPU state.
+ */
+static uint32_t mcd_get_cpu_pid(CPUState *cpu)
+{
+ if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) {
+ /* Return the default process' PID */
+ int index = mcdserver_state.process_num - 1;
+ return mcdserver_state.processes[index].pid;
+ }
+ return cpu->cluster_index + 1;
+}
+
+/**
+ * mcd_get_cpu_process() - Returns the process of the provided CPU.
+ *
+ * @cpu: The CPU state.
+ */
+static MCDProcess *mcd_get_cpu_process(CPUState *cpu)
+{
+ return mcd_get_process(mcd_get_cpu_pid(cpu));
+}
+
+/**
+ * mcd_next_attached_cpu() - Returns the first CPU with an attached process
+ * starting after the
+ * provided cpu.
+ *
+ * @cpu: The CPU to start from.
+ */
+static CPUState *mcd_next_attached_cpu(CPUState *cpu)
+{
+ cpu = CPU_NEXT(cpu);
+
+ while (cpu) {
+ if (mcd_get_cpu_process(cpu)->attached) {
+ break;
+ }
+
+ cpu = CPU_NEXT(cpu);
+ }
+
+ return cpu;
+}
+
+/**
+ * mcd_first_attached_cpu() - Returns the first CPU with an attached process.
+ */
+static CPUState *mcd_first_attached_cpu(void)
+{
+ CPUState *cpu = first_cpu;
+ MCDProcess *process = mcd_get_cpu_process(cpu);
+
+ if (!process->attached) {
+ return mcd_next_attached_cpu(cpu);
+ }
+
+ return cpu;
+}
+
/**
* mcd_vm_state_change() - Handles a state change of the QEMU VM.
*
@@ -284,6 +369,117 @@ static void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd)
}
}
+/**
+ * init_resets() - Initializes the resets info.
+ *
+ * This function currently only adds all theoretical possible resets to the
+ * resets GArray. None of the resets work at the moment. The resets are:
+ * "full_system_reset", "gpr_reset" and "memory_reset".
+ * @resets: GArray with possible resets.
+ */
+static int init_resets(GArray *resets)
+{
+ mcd_reset_st system_reset = { .id = 0, .name = RESET_SYSTEM};
+ mcd_reset_st gpr_reset = { .id = 1, .name = RESET_GPR};
+ mcd_reset_st memory_reset = { .id = 2, .name = RESET_MEMORY};
+ g_array_append_vals(resets, (gconstpointer)&system_reset, 1);
+ g_array_append_vals(resets, (gconstpointer)&gpr_reset, 1);
+ g_array_append_vals(resets, (gconstpointer)&memory_reset, 1);
+ return 0;
+}
+
+/**
+ * init_trigger() - Initializes the trigger info.
+ *
+ * This function adds the types of trigger, their possible options and actions
+ * to the trigger struct.
+ * @trigger: Struct with all trigger info.
+ */
+static int init_trigger(mcd_trigger_into_st *trigger)
+{
+ snprintf(trigger->type, sizeof(trigger->type),
+ "%d,%d,%d,%d", MCD_BREAKPOINT_HW, MCD_BREAKPOINT_READ,
+ MCD_BREAKPOINT_WRITE, MCD_BREAKPOINT_RW);
+ snprintf(trigger->option, sizeof(trigger->option),
+ "%s", MCD_TRIG_OPT_VALUE);
+ snprintf(trigger->action, sizeof(trigger->action),
+ "%s", MCD_TRIG_ACT_BREAK);
+ /* there can be 16 breakpoints and 16 watchpoints each */
+ trigger->nr_trigger = 16;
+ return 0;
+}
+
+/**
+ * handle_open_server() - Handler for opening the MCD server.
+ *
+ * This is the first function that gets called from the MCD Shared Library.
+ * It initializes core indepent data with the :c:func:`init_resets` and
+ * \reg init_trigger functions. It also send the TCP_HANDSHAKE_SUCCESS
+ * packet back to the library to confirm the mcdstub is ready for further
+ * communication.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_open_server(GArray *params, void *user_ctx)
+{
+ /* initialize core-independent data */
+ int return_value = 0;
+ mcdserver_state.resets = g_array_new(false, true, sizeof(mcd_reset_st));
+ return_value = init_resets(mcdserver_state.resets);
+ if (return_value != 0) {
+ g_assert_not_reached();
+ }
+ return_value = init_trigger(&mcdserver_state.trigger);
+ if (return_value != 0) {
+ g_assert_not_reached();
+ }
+
+ mcd_put_packet(TCP_HANDSHAKE_SUCCESS);
+}
+
+/**
+ * mcd_vm_start() - Starts all CPUs with the vm_start function.
+ */
+static void mcd_vm_start(void)
+{
+ if (!runstate_needs_reset() && !runstate_is_running()) {
+ vm_start();
+ }
+}
+
+/**
+ * handle_close_server() - Handler for closing the MCD server.
+ *
+ * This function detaches the debugger (process) and frees up memory.
+ * Then it start the QEMU VM with :c:func:`mcd_vm_start`.
+ * @params: GArray with all TCP packet parameters.
+ */
+static void handle_close_server(GArray *params, void *user_ctx)
+{
+ uint32_t pid = 1;
+ MCDProcess *process = mcd_get_process(pid);
+
+ /*
+ * 1. free memory
+ * TODO: do this only if there are no processes attached anymore!
+ */
+ g_list_free(mcdserver_state.all_memspaces);
+ g_list_free(mcdserver_state.all_reggroups);
+ g_list_free(mcdserver_state.all_registers);
+ g_array_free(mcdserver_state.resets, TRUE);
+
+ /* 2. detach */
+ process->attached = false;
+
+ /* 3. reset process */
+ if (pid == mcd_get_cpu_pid(mcdserver_state.c_cpu)) {
+ mcdserver_state.c_cpu = mcd_first_attached_cpu();
+ }
+ if (!mcdserver_state.c_cpu) {
+ /* no more processes attached */
+ mcd_vm_start();
+ }
+}
+
/**
* mcd_handle_packet() - Evaluates the type of received packet and chooses the
* correct handler.
@@ -302,6 +498,25 @@ static int mcd_handle_packet(const char *line_buf)
const MCDCmdParseEntry *cmd_parser = NULL;
switch (line_buf[0]) {
+ case TCP_CHAR_OPEN_SERVER:
+ {
+ static MCDCmdParseEntry open_server_cmd_desc = {
+ .handler = handle_open_server,
+ };
+ open_server_cmd_desc.cmd = (char[2]) { TCP_CHAR_OPEN_SERVER, '\0' };
+ cmd_parser = &open_server_cmd_desc;
+ }
+ break;
+ case TCP_CHAR_CLOSE_SERVER:
+ {
+ static MCDCmdParseEntry close_server_cmd_desc = {
+ .handler = handle_close_server,
+ };
+ close_server_cmd_desc.cmd =
+ (char[2]) { TCP_CHAR_CLOSE_SERVER, '\0' };
+ cmd_parser = &close_server_cmd_desc;
+ }
+ break;
default:
/* command not supported */
mcd_put_packet("");
@@ -422,91 +637,6 @@ static void mcd_chr_receive(void *opaque, const uint8_t *buf, int size)
}
}
-/**
- * mcd_get_process() - Returns the process of the provided pid.
- *
- * @pid: The process ID.
- */
-static MCDProcess *mcd_get_process(uint32_t pid)
-{
- int i;
-
- if (!pid) {
- /* 0 means any process, we take the first one */
- return &mcdserver_state.processes[0];
- }
-
- for (i = 0; i < mcdserver_state.process_num; i++) {
- if (mcdserver_state.processes[i].pid == pid) {
- return &mcdserver_state.processes[i];
- }
- }
-
- return NULL;
-}
-
-/**
- * mcd_get_cpu_pid() - Returns the process ID of the provided CPU.
- *
- * @cpu: The CPU state.
- */
-static uint32_t mcd_get_cpu_pid(CPUState *cpu)
-{
- if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) {
- /* Return the default process' PID */
- int index = mcdserver_state.process_num - 1;
- return mcdserver_state.processes[index].pid;
- }
- return cpu->cluster_index + 1;
-}
-
-/**
- * mcd_get_cpu_process() - Returns the process of the provided CPU.
- *
- * @cpu: The CPU state.
- */
-static MCDProcess *mcd_get_cpu_process(CPUState *cpu)
-{
- return mcd_get_process(mcd_get_cpu_pid(cpu));
-}
-
-/**
- * mcd_next_attached_cpu() - Returns the first CPU with an attached process
- * starting after the
- * provided cpu.
- *
- * @cpu: The CPU to start from.
- */
-static CPUState *mcd_next_attached_cpu(CPUState *cpu)
-{
- cpu = CPU_NEXT(cpu);
-
- while (cpu) {
- if (mcd_get_cpu_process(cpu)->attached) {
- break;
- }
-
- cpu = CPU_NEXT(cpu);
- }
-
- return cpu;
-}
-
-/**
- * mcd_first_attached_cpu() - Returns the first CPU with an attached process.
- */
-static CPUState *mcd_first_attached_cpu(void)
-{
- CPUState *cpu = first_cpu;
- MCDProcess *process = mcd_get_cpu_process(cpu);
-
- if (!process->attached) {
- return mcd_next_attached_cpu(cpu);
- }
-
- return cpu;
-}
-
/**
* mcd_chr_event() - Handles a TCP client connect.
*
--
2.34.1