@@ -3,10 +3,8 @@
#define DEFAULT_MCDSTUB_PORT "1235"
#define TYPE_CHARDEV_MCD "chardev-mcd"
-#define MX_INPUT_LENGTH 9
-#define MCD_TCP_DATALEN 80
-/* MCD breakpoint/watchpoint types */
+// breakpoint defines
#define MCD_BREAKPOINT_SW 0
#define MCD_BREAKPOINT_HW 1
#define MCD_WATCHPOINT_WRITE 2
@@ -16,8 +14,6 @@
/**
* mcd_tcp_server_start: start the tcp server to connect via mcd
* @device: connection spec for mcd
- *
- * This is a TCP port
*/
int mcdserver_start(const char *device);
@@ -1,5 +1,5 @@
-#ifndef _SYSCALLS_H_
-#define _SYSCALLS_H_
+#ifndef _MCD_SYSCALLS_H_
+#define _MCD_SYSCALLS_H_
typedef void (*gdb_syscall_complete_cb)(CPUState *cpu, uint64_t ret, int err);
@@ -1,8 +1,3 @@
-/*
- * this header includes a lookup table for the transmitted messages over the tcp connection to trace32,
- * as well as function declarations for all functios used inside the mcdstub
- */
-
#ifndef MCDSTUB_INTERNALS_H
#define MCDSTUB_INTERNALS_H
@@ -10,19 +5,33 @@
#include "chardev/char.h"
#include "hw/core/cpu.h"
// just used for the register xml files
-#include "exec/gdbstub.h" /* xml_builtin */
+#include "exec/gdbstub.h"
#define MAX_PACKET_LENGTH 1024
// trigger defines
-#define MCD_TRIG_TYPE_IP 0x00000001
-#define MCD_TRIG_TYPE_READ 0x00000002
-#define MCD_TRIG_TYPE_WRITE 0x00000004
-#define MCD_TRIG_TYPE_RW 0x00000008
#define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008
#define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001
+typedef uint32_t mcd_trig_type_et;
+// TODO: replace mcd defines with custom layer
+enum {
+ MCD_TRIG_TYPE_UNDEFINED = 0x00000000, /**< Undefined trigger type. */
+ MCD_TRIG_TYPE_IP = 0x00000001, /**< Trigger on a changing instruction pointer. */
+ MCD_TRIG_TYPE_READ = 0x00000002, /**< Trigger on a read data access to a specific address or address range. */
+ MCD_TRIG_TYPE_WRITE = 0x00000004, /**< Trigger on a write data access to a specific address or address range. */
+ MCD_TRIG_TYPE_RW = 0x00000008, /**< Trigger on a read or a write data access to a specific address or
+ address range. */
+ MCD_TRIG_TYPE_NOCYCLE = 0x00000010, /**< Trigger on core information other than an IP or data compare trigger. */
+ MCD_TRIG_TYPE_TRIG_BUS = 0x00000020, /**< Trigger on a trigger bus combination. */
+ MCD_TRIG_TYPE_COUNTER = 0x00000040, /**< Trigger on an elapsed trigger counter. */
+ MCD_TRIG_TYPE_CUSTOM = 0x00000080, /**< Custom trigger using standard format as defined by \ref mcd_trig_custom_st. */
+ MCD_TRIG_TYPE_CUSTOM_LO = 0x00010000, /**< Begin Range: User defined trigger types. */
+ MCD_TRIG_TYPE_CUSTOM_HI = 0x40000000, /**< End Range: User defined trigger types. */
+};
+
typedef uint32_t mcd_core_event_et;
+// TODO: replace mcd defines with custom layer
enum {
MCD_CORE_EVENT_NONE = 0x00000000, /**< No since the last poll. */
MCD_CORE_EVENT_MEMORY_CHANGE = 0x00000001, /**< Memory content has changed. */
@@ -50,10 +59,11 @@ enum {
#define RESET_GPR "gpr_reset"
#define RESET_MEMORY "memory_reset"
-// more
-#define QUERY_TOTAL_NUMBER 12 //FIXME: set this to a usefull value in the end
+// misc
+#define QUERY_TOTAL_NUMBER 12
#define CMD_SCHEMA_LENGTH 5
#define MCD_SYSTEM_NAME "qemu-system"
+
// tcp query packet values templates
#define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device"
@@ -65,13 +75,14 @@ enum {
#define STATE_STR_INIT_HALTED "vm halted since boot"
#define STATE_STR_INIT_RUNNING "vm running since boot"
#define STATE_STR_BREAK_HW "stopped beacuse of HW breakpoint"
+#define STATE_STEP_PERFORMED "stopped beacuse of single step"
#define STATE_STR_BREAK_READ(d) "stopped beacuse of read access at " #d
#define STATE_STR_BREAK_WRITE(d) "stopped beacuse of write access at " #d
#define STATE_STR_BREAK_RW(d) "stopped beacuse of read or write access at " #d
#define STATE_STR_BREAK_UNKNOWN "stopped for unknown reason"
-// GDB stuff thats needed for GDB function, which we use
typedef struct GDBRegisterState {
+ // needed for the used gdb functions
int base_reg;
int num_regs;
gdb_get_reg_cb get_reg;
@@ -80,12 +91,7 @@ typedef struct GDBRegisterState {
struct GDBRegisterState *next;
} GDBRegisterState;
-/*
- * struct for an MCD Process, each process can establish one connection
- */
-
typedef struct MCDProcess {
- //this is a relict from the gdb process, we might be able to delete this
uint32_t pid;
bool attached;
@@ -99,35 +105,16 @@ typedef struct MCDCmdParseEntry {
char schema[CMD_SCHEMA_LENGTH];
} MCDCmdParseEntry;
-typedef enum MCDThreadIdKind {
- GDB_ONE_THREAD = 0,
- GDB_ALL_THREADS, /* One process, all threads */
- GDB_ALL_PROCESSES,
- GDB_READ_THREAD_ERR
-} MCDThreadIdKind;
-
typedef union MCDCmdVariant {
const char *data;
int data_int;
uint64_t data_uint64_t;
int query_handle;
int cpu_id;
- struct {
- MCDThreadIdKind kind;
- uint32_t pid;
- uint32_t tid;
- } thread_id;
-
} MCDCmdVariant;
#define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i))
-
-/*
- * not sure for what this is used exactly
- */
-
-
enum RSState {
RS_INACTIVE,
RS_IDLE,
@@ -162,19 +149,14 @@ typedef struct MCDState {
int line_csum; /* checksum at the end of the packet */
GByteArray *last_packet;
int signal;
- //the next one is about stub compatibility and we should be able to assume this is true anyway
- //bool multiprocess;
+
MCDProcess *processes;
int process_num;
GString *str_buf;
GByteArray *mem_buf;
- // maybe we don't need those flags
int sstep_flags;
int supported_sstep_flags;
- // my stuff
- RunState vm_current_state;
- RunState vm_previous_state;
uint32_t query_cpu_id;
GList *all_memspaces;
GList *all_reggroups;
@@ -236,9 +218,6 @@ typedef struct mcd_reset_st {
uint8_t id;
} mcd_reset_st;
-// Inline utility function, convert from int to hex and back
-
-
static inline int fromhex(int v)
{
if (v >= '0' && v <= '9') {
@@ -283,7 +262,6 @@ int mcd_put_packet(const char *buf);
int mcd_put_packet_binary(const char *buf, int len, bool dump);
bool mcd_got_immediate_ack(void);
void mcd_put_buffer(const uint8_t *buf, int len);
-void mcd_set_stop_cpu(CPUState *cpu);
MCDProcess *mcd_get_cpu_process(CPUState *cpu);
uint32_t mcd_get_cpu_pid(CPUState *cpu);
MCDProcess *mcd_get_process(uint32_t pid);
@@ -297,6 +275,7 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd);
int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds);
int cmd_parse_params(const char *data, const char *schema, GArray *params);
void handle_vm_start(GArray *params, void *user_ctx);
+void handle_vm_step(GArray *params, void *user_ctx);
void handle_vm_stop(GArray *params, void *user_ctx);
void handle_gen_query(GArray *params, void *user_ctx);
int mcd_get_cpu_index(CPUState *cpu);
@@ -312,6 +291,7 @@ void handle_close_server(GArray *params, void *user_ctx);
void handle_close_core(GArray *params, void *user_ctx);
void handle_query_trigger(GArray *params, void *user_ctx);
void mcd_vm_start(void);
+int mcd_vm_sstep(CPUState *cpu);
void mcd_vm_stop(void);
void handle_query_reg_groups_f(GArray *params, void *user_ctx);
void handle_query_reg_groups_c(GArray *params, void *user_ctx);
@@ -328,6 +308,7 @@ void handle_write_register(GArray *params, void *user_ctx);
void handle_read_memory(GArray *params, void *user_ctx);
void handle_write_memory(GArray *params, void *user_ctx);
int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg);
+int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg);
int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len);
int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len);
@@ -337,7 +318,7 @@ int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray* reggroups, GArray* registe
int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray* registers, int* current_group_id);
int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers);
-/* sycall handling */
+// sycall handling
void mcd_syscall_reset(void);
void mcd_disable_syscalls(void);
@@ -6,7 +6,8 @@
// tcp data characters
#define TCP_CHAR_OPEN_SERVER 'I'
#define TCP_CHAR_OPEN_CORE 'i'
-#define TCP_CHAR_GO 'c'
+#define TCP_CHAR_GO 'C'
+#define TCP_CHAR_STEP 'c'
#define TCP_CHAR_BREAK 'b'
#define TCP_CHAR_QUERY 'q'
#define TCP_CHAR_CLOSE_SERVER 'D'
@@ -1,10 +1,9 @@
/*
- * This is the main mcdstub. It needs to be complemented by other mcd stubs for each target.
+ * This is the main mcdstub.
*/
#include "mcd_shared_defines.h"
-//from original gdbstub.c
#include "qemu/osdep.h"
#include "qemu/ctype.h"
#include "qemu/cutils.h"
@@ -14,15 +13,12 @@
#include "mcdstub/syscalls.h"
#include "hw/cpu/cluster.h"
#include "hw/boards.h"
-
#include "sysemu/hw_accel.h"
#include "sysemu/runstate.h"
#include "exec/replay-core.h"
#include "exec/hwaddr.h"
-
#include "internals.h"
-//from original softmmu.c (minus what was already here)
#include "qapi/error.h"
#include "exec/tb-flush.h"
#include "sysemu/cpus.h"
@@ -31,7 +27,7 @@
#include "chardev/char-fe.h"
#include "monitor/monitor.h"
-//architecture specific stuff
+// architecture specific stubs
#include "target/arm/mcdstub.h"
// FIXME: delete the following line and check if it worked
@@ -39,7 +35,6 @@
typedef struct {
CharBackend chr;
- //Chardev *mon_chr;
} MCDSystemState;
MCDSystemState mcdserver_system_state;
@@ -60,8 +55,6 @@ void mcd_init_mcdserver_state(void)
* By default try to use no IRQs and no timers while single
* stepping so as to make single stepping like a typical ICE HW step.
*/
- // TODO:
- // this is weird and we might not actually need it after all
mcdserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags();
mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
mcdserver_state.sstep_flags &= mcdserver_state.supported_sstep_flags;
@@ -106,7 +99,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_reset_c,
.cmd = QUERY_ARG_RESET QUERY_CONSEQUTIVE,
};
- strcpy(query_reset_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' });
+ strcpy(query_reset_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' });
mcd_query_cmds_table[cmd_number] = query_reset_c;
cmd_number++;
@@ -121,7 +114,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_mem_spaces_f,
.cmd = QUERY_ARG_MEMORY QUERY_FIRST,
};
- strcpy(query_mem_spaces_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' });
+ strcpy(query_mem_spaces_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' });
mcd_query_cmds_table[cmd_number] = query_mem_spaces_f;
cmd_number++;
@@ -129,7 +122,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_mem_spaces_c,
.cmd = QUERY_ARG_MEMORY QUERY_CONSEQUTIVE,
};
- strcpy(query_mem_spaces_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' });
+ strcpy(query_mem_spaces_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' });
mcd_query_cmds_table[cmd_number] = query_mem_spaces_c;
cmd_number++;
@@ -137,7 +130,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_reg_groups_f,
.cmd = QUERY_ARG_REGGROUP QUERY_FIRST,
};
- strcpy(query_reg_groups_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' });
+ strcpy(query_reg_groups_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' });
mcd_query_cmds_table[cmd_number] = query_reg_groups_f;
cmd_number++;
@@ -145,7 +138,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_reg_groups_c,
.cmd = QUERY_ARG_REGGROUP QUERY_CONSEQUTIVE,
};
- strcpy(query_reg_groups_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' });
+ strcpy(query_reg_groups_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' });
mcd_query_cmds_table[cmd_number] = query_reg_groups_c;
cmd_number++;
@@ -153,7 +146,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_regs_f,
.cmd = QUERY_ARG_REG QUERY_FIRST,
};
- strcpy(query_regs_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' });
+ strcpy(query_regs_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' });
mcd_query_cmds_table[cmd_number] = query_regs_f;
cmd_number++;
@@ -161,7 +154,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_regs_c,
.cmd = QUERY_ARG_REG QUERY_CONSEQUTIVE,
};
- strcpy(query_regs_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' });
+ strcpy(query_regs_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' });
mcd_query_cmds_table[cmd_number] = query_regs_c;
cmd_number++;
@@ -169,7 +162,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) {
.handler = handle_query_state,
.cmd = QUERY_ARG_STATE,
};
- strcpy(query_state.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' });
+ strcpy(query_state.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' });
mcd_query_cmds_table[cmd_number] = query_state;
}
@@ -258,12 +251,8 @@ int pid_order(const void *a, const void *b)
int mcdserver_start(const char *device)
{
- //might wann add tracing later (no idea for what this is used)
- //trace_gdbstub_op_start(device);
-
char mcdstub_device_name[128];
Chardev *chr = NULL;
- //Chardev *mon_chr;
if (!first_cpu) {
error_report("mcdstub: meaningless to attach to a "
@@ -271,7 +260,6 @@ int mcdserver_start(const char *device)
return -1;
}
- //
if (!mcd_supports_guest_debug()) {
error_report("mcdstub: current accelerator doesn't "
"support guest debugging");
@@ -282,7 +270,7 @@ int mcdserver_start(const char *device)
return -1;
}
- //if device == default -> set device = tcp::1235
+ // if device == default -> set device = tcp::1235
if (strcmp(device, "default") == 0) {
device = "tcp::1235";
}
@@ -303,7 +291,6 @@ int mcdserver_start(const char *device)
sigaction(SIGINT, &act, NULL);
}
#endif
-
chr = qemu_chr_new_noreplay("mcd", device, true, NULL);
if (!chr) {
return -1;
@@ -314,13 +301,8 @@ int mcdserver_start(const char *device)
mcd_init_mcdserver_state();
qemu_add_vm_change_state_handler(mcd_vm_state_change, NULL);
-
- /* Initialize a monitor terminal for mcd */
- //mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_MCD, NULL, NULL, &error_abort);
- //monitor_init_hmp(mon_chr, false, &error_abort);
} else {
qemu_chr_fe_deinit(&mcdserver_system_state.chr, true);
- //mon_chr = mcdserver_system_state.mon_chr;
reset_mcdserver_state();
}
@@ -334,7 +316,6 @@ int mcdserver_start(const char *device)
NULL, &mcdserver_state, NULL, true);
}
mcdserver_state.state = chr ? RS_IDLE : RS_INACTIVE;
- //mcdserver_system_state.mon_chr = mon_chr;
mcd_syscall_reset();
return 0;
@@ -360,107 +341,80 @@ void mcd_read_byte(uint8_t ch)
uint8_t reply;
if (mcdserver_state.last_packet->len) {
- /* Waiting for a response to the last packet. If we see the start
- of a new command then abandon the previous response. */
if (ch == TCP_NOT_ACKNOWLEDGED) {
- //the previous packet was not akcnowledged
- //trace_gdbstub_err_got_nack();
- //we are resending the last packet
+ // the previous packet was not akcnowledged
mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len);
}
else if (ch == TCP_ACKNOWLEDGED) {
- //the previous packet was acknowledged
- //trace_gdbstub_io_got_ack();
+ // the previous packet was acknowledged
}
if (ch == TCP_ACKNOWLEDGED || ch == TCP_COMMAND_START) {
- //either acknowledged or a new communication starts -> we discard previous communication
+ // either acknowledged or a new communication starts -> discard previous packet
g_byte_array_set_size(mcdserver_state.last_packet, 0);
}
if (ch != TCP_COMMAND_START) {
- // we only continue if we are processing a new commant. otherwise we skip to ne next character in the packet which sould be a $
+ // skip to the next char
return;
}
}
- //if (runstate_is_running()) {
- /* when the CPU is running, we cannot do anything except stop
- it when receiving a char */
- //vm_stop(RUN_STATE_PAUSED);
- //}
- //else {
- switch(mcdserver_state.state) {
- case RS_IDLE:
- if (ch == TCP_COMMAND_START) {
- /* start of command packet */
- mcdserver_state.line_buf_index = 0;
- mcdserver_state.line_sum = 0;
- mcdserver_state.state = RS_GETLINE;
- }
- else {
- //new communication has to start with a $
- //trace_gdbstub_err_garbage(ch);
- }
- break;
- case RS_GETLINE:
- if (ch == TCP_COMMAND_END) {
- /* end of command, start of checksum*/
- mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0;
- //mcdserver_state.line_sum += ch;
- mcdserver_state.state = RS_DATAEND;
- }
- else if (mcdserver_state.line_buf_index >= sizeof(mcdserver_state.line_buf) - 1) {
- //the input string is too long for the linebuffer!
- //trace_gdbstub_err_overrun();
- mcdserver_state.state = RS_IDLE;
- }
- else {
- /* unescaped command character */
- //this means the character is part of the real content fo the packet and we copy it to the line_buf
- mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = ch;
- mcdserver_state.line_sum += ch;
- }
- break;
- case RS_DATAEND:
- // we are now done with copying the data and in the suffix of the packet
- // TODO: maybe wanna implement a checksum or sth like the gdb protocol has
-
- if (ch == TCP_WAS_NOT_LAST) {
- // ~ indicates that there is an additional package coming
- //acknowledged -> send +
- reply = TCP_ACKNOWLEDGED;
- mcd_put_buffer(&reply, 1);
- mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf);
- }
- else if (ch == TCP_WAS_LAST) {
- //acknowledged -> send +
- // | indicates that there is no additional package coming
- reply = TCP_ACKNOWLEDGED;
- mcd_put_buffer(&reply, 1);
- mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf);
- }
- else {
- //trace_gdbstub_err_checksum_incorrect(mcdserver_state.line_sum, mcdserver_state.line_csum);
- //not acknowledged -> send -
- reply = TCP_NOT_ACKNOWLEDGED;
- mcd_put_buffer(&reply, 1);
- //waiting for package to get resent
- mcdserver_state.state = RS_IDLE;
- }
- break;
- default:
- abort();
+
+ switch(mcdserver_state.state) {
+ case RS_IDLE:
+ if (ch == TCP_COMMAND_START) {
+ // start of command packet
+ mcdserver_state.line_buf_index = 0;
+ mcdserver_state.line_sum = 0;
+ mcdserver_state.state = RS_GETLINE;
+ }
+ break;
+ case RS_GETLINE:
+ if (ch == TCP_COMMAND_END) {
+ // end of command
+ mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0;
+ mcdserver_state.state = RS_DATAEND;
+ }
+ else if (mcdserver_state.line_buf_index >= sizeof(mcdserver_state.line_buf) - 1) {
+ // the input string is too long for the linebuffer!
+ mcdserver_state.state = RS_IDLE;
+ }
+ else {
+ // copy the content to the line_buf
+ mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = ch;
+ mcdserver_state.line_sum += ch;
+ }
+ break;
+ case RS_DATAEND:
+ if (ch == TCP_WAS_NOT_LAST) {
+ reply = TCP_ACKNOWLEDGED;
+ mcd_put_buffer(&reply, 1);
+ mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf);
+ }
+ else if (ch == TCP_WAS_LAST) {
+ reply = TCP_ACKNOWLEDGED;
+ mcd_put_buffer(&reply, 1);
+ mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf);
}
- //}
+ else {
+ // not acknowledged!
+ reply = TCP_NOT_ACKNOWLEDGED;
+ mcd_put_buffer(&reply, 1);
+ // waiting for package to get resent
+ mcdserver_state.state = RS_IDLE;
+ }
+ break;
+ default:
+ abort();
+ }
}
int mcd_handle_packet(const char *line_buf)
{
- // decides what function (handler) to call depending on what the first character in the line_buf is!
+ // decides what function (handler) to call depending on the first character in the line_buf
const MCDCmdParseEntry *cmd_parser = NULL;
switch (line_buf[0]) {
case TCP_CHAR_OPEN_SERVER:
- // handshake and lookup initialization
{
static MCDCmdParseEntry open_server_cmd_desc = {
.handler = handle_open_server,
@@ -470,7 +424,6 @@ int mcd_handle_packet(const char *line_buf)
}
break;
case TCP_CHAR_GO:
- // go command
{
static MCDCmdParseEntry go_cmd_desc = {
.handler = handle_vm_start,
@@ -479,8 +432,17 @@ int mcd_handle_packet(const char *line_buf)
cmd_parser = &go_cmd_desc;
}
break;
+ case TCP_CHAR_STEP:
+ {
+ static MCDCmdParseEntry step_cmd_desc = {
+ .handler = handle_vm_step,
+ };
+ step_cmd_desc.cmd = (char[2]) { TCP_CHAR_STEP, '\0' };
+ strcpy(step_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' });
+ cmd_parser = &step_cmd_desc;
+ }
+ break;
case TCP_CHAR_BREAK:
- // go command
{
static MCDCmdParseEntry break_cmd_desc = {
.handler = handle_vm_stop,
@@ -495,7 +457,6 @@ int mcd_handle_packet(const char *line_buf)
mcd_exit(0);
exit(0);
case TCP_CHAR_QUERY:
- //query inquiry
{
static MCDCmdParseEntry query_cmd_desc = {
.handler = handle_gen_query,
@@ -550,7 +511,7 @@ int mcd_handle_packet(const char *line_buf)
.handler = handle_read_register,
};
read_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_READ_REGISTER, '\0' };
- strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' });
+ strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, '\0' });
cmd_parser = &read_reg_cmd_desc;
}
break;
@@ -560,7 +521,7 @@ int mcd_handle_packet(const char *line_buf)
.handler = handle_write_register,
};
write_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_WRITE_REGISTER, '\0' };
- strcpy(write_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' });
+ strcpy(write_reg_cmd_desc.schema, (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' });
cmd_parser = &write_reg_cmd_desc;
}
break;
@@ -585,13 +546,13 @@ int mcd_handle_packet(const char *line_buf)
}
break;
default:
- // could not perform the command (because its unknown)
+ // command not supported
mcd_put_packet("");
break;
}
if (cmd_parser) {
- // now parse commands and run the selected function (handler)
+ // parse commands and run the selected handler function
run_cmd_parser(line_buf, cmd_parser);
}
@@ -599,21 +560,29 @@ int mcd_handle_packet(const char *line_buf)
}
void handle_vm_start(GArray *params, void *user_ctx) {
- // todo add partial restart with arguments and so on
+ // TODO: add partial restart with arguments and so on
mcd_vm_start();
}
+void handle_vm_step(GArray *params, void *user_ctx) {
+ // TODO: add partial restart with arguments and so on
+ uint32_t cpu_id = get_param(params, 0)->cpu_id;
+
+ CPUState *cpu = mcd_get_cpu(cpu_id);
+ mcd_vm_sstep(cpu);
+}
+
+
void handle_vm_stop(GArray *params, void *user_ctx) {
- // todo add partial stop with arguments and so on
+ // TODO: add partial stop with arguments and so on
mcd_vm_stop();
}
-void handle_gen_query(GArray *params, void *user_ctx)
-{
+void handle_gen_query(GArray *params, void *user_ctx) {
if (!params->len) {
return;
}
- //now iterate over all possible query functions and execute the right one
+ // iterate over all possible query functions and execute the right one
if (process_string_cmd(NULL, get_param(params, 0)->data,
mcdserver_state.mcd_query_cmds_table,
ARRAY_SIZE(mcdserver_state.mcd_query_cmds_table))) {
@@ -621,8 +590,7 @@ void handle_gen_query(GArray *params, void *user_ctx)
}
}
-void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd)
-{
+void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) {
if (!data) {
return;
}
@@ -630,8 +598,6 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd)
g_string_set_size(mcdserver_state.str_buf, 0);
g_byte_array_set_size(mcdserver_state.mem_buf, 0);
- /* In case there was an error during the command parsing we must
- * send a NULL packet to indicate the command is not supported */
if (process_string_cmd(NULL, data, cmd, 1)) {
mcd_put_packet("");
}
@@ -655,11 +621,11 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) {
const char *remaining_data = data;
for (int i = 0; i<strlen(schema); i++) {
- // get correct part of string
+ // get correct part of data
char *separator = strchr(remaining_data, ARGUMENT_SEPARATOR);
if (separator) {
- // we multiple arguments left
+ // multiple arguments
int seperator_index = (int)(separator - remaining_data);
strncpy(data_buffer, remaining_data, seperator_index);
data_buffer[seperator_index] = 0;
@@ -675,12 +641,11 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) {
MCDCmdVariant this_param;
switch (schema[i]) {
case ARG_SCHEMA_STRING:
- // a string has to be the last argument
+ // this has to be the last argument
this_param.data = remaining_data;
g_array_append_val(params, this_param);
break;
case ARG_SCHEMA_HEXDATA:
- // a string has to be the last argument
g_string_printf(mcdserver_state.str_buf, "%s", data_buffer);
break;
case ARG_SCHEMA_INT:
@@ -706,8 +671,7 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) {
return 0;
}
-int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds)
-{
+int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds) {
int i;
g_autoptr(GArray) params = g_array_new(false, true, sizeof(MCDCmdVariant));
@@ -717,23 +681,21 @@ int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry
for (i = 0; i < num_cmds; i++) {
const MCDCmdParseEntry *cmd = &cmds[i];
- //terminate if we don't have handler and cmd
g_assert(cmd->handler && cmd->cmd);
- // if data and command are different continue
+ // continue if data and command are different
if (strncmp(data, cmd->cmd, strlen(cmd->cmd))) {
continue;
}
- // if a schema is provided we need to extract parameters from the data string
if (strlen(cmd->schema)) {
- // this only gets the data from data beginning after the command name
+ // extract data for parameters
if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, params)) {
return -1;
}
}
- // the correct handler function is called
+ // call handler
cmd->handler(params, user_ctx);
return 0;
}
@@ -741,25 +703,16 @@ int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry
return -1;
}
-void mcd_exit(int code)
-{
- char buf[4];
-
+void mcd_exit(int code) {
+ // terminate qemu
if (!mcdserver_state.init) {
return;
}
- //trace_gdbstub_op_exiting((uint8_t)code);
-
- //need to check what is sent here and dapt it to my needs
- snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
- mcd_put_packet(buf);
-
qemu_chr_fe_deinit(&mcdserver_system_state.chr, true);
}
-void mcd_chr_event(void *opaque, QEMUChrEvent event)
-{
+void mcd_chr_event(void *opaque, QEMUChrEvent event) {
int i;
MCDState *s = (MCDState *) opaque;
@@ -771,19 +724,13 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event)
}
s->c_cpu = mcd_first_attached_cpu();
-
- //vm_stop(RUN_STATE_PAUSED);
- //TODO: this might not be necessary
- //replay_gdb_attached();
- //gdb_has_xml = false;
break;
default:
break;
}
}
-bool mcd_supports_guest_debug(void)
-{
+bool mcd_supports_guest_debug(void) {
const AccelOpsClass *ops = cpus_get_accel();
if (ops->supports_guest_debug) {
return ops->supports_guest_debug();
@@ -792,29 +739,23 @@ bool mcd_supports_guest_debug(void)
}
#ifndef _WIN32
-void mcd_sigterm_handler(int signal)
-{
+void mcd_sigterm_handler(int signal) {
if (runstate_is_running()) {
vm_stop(RUN_STATE_PAUSED);
}
}
#endif
-void mcd_vm_state_change(void *opaque, bool running, RunState state)
-{
+void mcd_vm_state_change(void *opaque, bool running, RunState state) {
CPUState *cpu = mcdserver_state.c_cpu;
- // update cpu state
- mcdserver_state.vm_previous_state = mcdserver_state.vm_current_state;
- mcdserver_state.vm_current_state = state;
-
if (mcdserver_state.state == RS_INACTIVE) {
return;
}
if (cpu == NULL) {
if (running) {
- // this is the case if qemu starts the vm before any mcd is connected
+ // this is the case if qemu starts the vm before a mcd client is connected
const char *mcd_state;
mcd_state = CORE_STATE_RUNNING;
const char *info_str;
@@ -857,8 +798,13 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state)
stop_str = STATE_STR_BREAK_UNKNOWN;
}
cpu->watchpoint_hit = NULL;
- } else {
- // "hardware" breakpoint hit!
+ }
+ else if (cpu->singlestep_enabled){
+ // we land here when a single step is performed
+ cpu_single_step(cpu, 0);
+ stop_str = STATE_STEP_PERFORMED;
+ }
+ else {
trig_id = MCD_TRIG_TYPE_IP;
stop_str = STATE_STR_BREAK_HW;
tb_flush(cpu);
@@ -870,47 +816,40 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state)
stop_str = "";
break;
case RUN_STATE_WATCHDOG:
+ printf("runstate watchdog hit\n");
info_str = STATE_STR_UNKNOWN(cpu->cpu_index);
mcd_state = CORE_STATE_UNKNOWN;
stop_str = "";
- printf("runstate watchdog hit\n");
break;
default:
info_str = STATE_STR_UNKNOWN(cpu->cpu_index);
mcd_state = CORE_STATE_UNKNOWN;
stop_str = "";
- // we don't care;
break;
}
+ // set state for c_cpu
mcdserver_state.cpu_state.state = mcd_state;
mcdserver_state.cpu_state.trig_id = trig_id;
mcdserver_state.cpu_state.stop_str = stop_str;
mcdserver_state.cpu_state.info_str = info_str;
-
- /* disable single step if it was enabled */
- cpu_single_step(cpu, 0);
}
-int mcd_put_packet(const char *buf)
-{
+int mcd_put_packet(const char *buf) {
return mcd_put_packet_binary(buf, strlen(buf), false);
}
-void mcd_put_strbuf(void)
-{
+void mcd_put_strbuf(void) {
mcd_put_packet(mcdserver_state.str_buf->str);
}
-int mcd_put_packet_binary(const char *buf, int len, bool dump)
-{
+int mcd_put_packet_binary(const char *buf, int len, bool dump) {
for(;;) {
- //super interesting if we want a chekcsum or something like that here!!
g_byte_array_set_size(mcdserver_state.last_packet, 0);
- g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "$", 1);
+ g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_COMMAND_START, '\0' }, 1);
g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) buf, len);
- g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "#", 1);
- g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "|", 1);
+ g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_COMMAND_END, '\0' }, 1);
+ g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_WAS_LAST, '\0' }, 1);
mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len);
@@ -921,53 +860,28 @@ int mcd_put_packet_binary(const char *buf, int len, bool dump)
return 0;
}
-bool mcd_got_immediate_ack(void)
-{
+bool mcd_got_immediate_ack(void) {
return true;
}
-void mcd_put_buffer(const uint8_t *buf, int len)
-{
- /*
- * XXX this blocks entire thread. Rewrite to use
- * qemu_chr_fe_write and background I/O callbacks
- */
+void mcd_put_buffer(const uint8_t *buf, int len) {
qemu_chr_fe_write_all(&mcdserver_system_state.chr, buf, len);
}
-void mcd_set_stop_cpu(CPUState *cpu)
-{
- MCDProcess *p = mcd_get_cpu_process(cpu);
-
- if (!p->attached) {
- /*
- * Having a stop CPU corresponding to a process that is not attached
- * confuses GDB. So we ignore the request.
- */
- return;
- }
- //FIXME: we probably can delete this because in the opern_core function we set these two anyway
- mcdserver_state.c_cpu = cpu;
-}
-
-MCDProcess *mcd_get_cpu_process(CPUState *cpu)
-{
+MCDProcess *mcd_get_cpu_process(CPUState *cpu) {
return mcd_get_process(mcd_get_cpu_pid(cpu));
}
-uint32_t mcd_get_cpu_pid(CPUState *cpu)
-{
+uint32_t mcd_get_cpu_pid(CPUState *cpu) {
if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) {
- /* Return the default process' PID */
+ // Return the default process' PID
int index = mcdserver_state.process_num - 1;
return mcdserver_state.processes[index].pid;
}
- // TODO: maybe +1 because we start numbering at 1
return cpu->cluster_index + 1;
}
-MCDProcess *mcd_get_process(uint32_t pid)
-{
+MCDProcess *mcd_get_process(uint32_t pid) {
int i;
if (!pid) {
@@ -997,8 +911,7 @@ CPUState* mcd_get_cpu(uint32_t i_cpu_index) {
return cpu;
}
-CPUState *mcd_first_attached_cpu(void)
-{
+CPUState *mcd_first_attached_cpu(void) {
CPUState *cpu = first_cpu;
MCDProcess *process = mcd_get_cpu_process(cpu);
@@ -1009,8 +922,7 @@ CPUState *mcd_first_attached_cpu(void)
return cpu;
}
-CPUState *mcd_next_attached_cpu(CPUState *cpu)
-{
+CPUState *mcd_next_attached_cpu(CPUState *cpu) {
cpu = CPU_NEXT(cpu);
while (cpu) {
@@ -1024,14 +936,11 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu)
return cpu;
}
-int mcd_get_cpu_index(CPUState *cpu)
-{
- // TODO: maybe plus 1 because we start numbering at 1
+int mcd_get_cpu_index(CPUState *cpu) {
return cpu->cpu_index + 1;
}
-CPUState *get_first_cpu_in_process(MCDProcess *process)
-{
+CPUState *get_first_cpu_in_process(MCDProcess *process) {
CPUState *cpu;
CPU_FOREACH(cpu) {
@@ -1043,8 +952,7 @@ CPUState *get_first_cpu_in_process(MCDProcess *process)
return NULL;
}
-CPUState *find_cpu(uint32_t thread_id)
-{
+CPUState *find_cpu(uint32_t thread_id) {
CPUState *cpu;
CPU_FOREACH(cpu) {
@@ -1080,7 +988,7 @@ void parse_reg_xml(const char *xml, int size, GArray* registers) {
c_ptr = &c;
if (still_to_skip>0) {
- // skip chars unwanted chars
+ // skip unwanted chars
still_to_skip --;
continue;
}
@@ -1172,9 +1080,7 @@ void parse_reg_xml(const char *xml, int size, GArray* registers) {
}
int int_cmp(gconstpointer a, gconstpointer b) {
- int a_int = *(int*)a;
- int b_int = *(int*)b;
- if (a_int == b_int) {
+ if (*(int*)a == *(int*)b) {
return 0;
}
else {
@@ -1285,7 +1191,7 @@ int init_trigger(mcd_trigger_st* trigger) {
}
void handle_open_server(GArray *params, void *user_ctx) {
- // initialize some core-independent data
+ // 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);
@@ -1301,8 +1207,6 @@ void handle_query_system(GArray *params, void *user_ctx) {
}
void handle_query_cores(GArray *params, void *user_ctx) {
- //TODO: add cluster support: in gdb each inferior (process) handles one cluster we might want to have sth similar here
-
// get first cpu
CPUState *cpu = mcd_first_attached_cpu();
if (!cpu) {
@@ -1316,10 +1220,9 @@ void handle_query_cores(GArray *params, void *user_ctx) {
gchar *arch = cc->gdb_arch_name(cpu);
int nr_cores = cpu->nr_cores;
-
char device_name[] = DEVICE_NAME_TEMPLATE(arch);
g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%s.%s=%d.",
- TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_ARGUMENT_AMOUNT_CORE, nr_cores);
+ TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_ARGUMENT_AMOUNT_CORE, nr_cores);
mcd_put_strbuf();
g_free(arch);
}
@@ -1441,7 +1344,6 @@ int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers) {
}
void handle_open_core(GArray *params, void *user_ctx) {
- // get the cpu whith the given id
uint32_t cpu_id = get_param(params, 0)->cpu_id;
CPUState *cpu = mcd_get_cpu(cpu_id);
mcdserver_state.c_cpu = cpu;
@@ -1501,9 +1403,7 @@ void handle_open_core(GArray *params, void *user_ctx) {
}
void handle_query_reset_f(GArray *params, void *user_ctx) {
- // resetting has to be done over a monitor (look ar Rcmd) so we tell MCD that we can reset but this still need to be implemented
- // we only support one reset over this monitor and that would be a full "system_restart"
- // reset options are the same for every cpu!
+ // TODO: vull reset over the qemu monitor
// 1. check length
int nb_resets = mcdserver_state.resets->len;
@@ -1518,7 +1418,6 @@ void handle_query_reset_f(GArray *params, void *user_ctx) {
mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, 0);
g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id);
mcd_put_strbuf();
- // TODO: we still need to implement the gpr and memory reset here!
}
void handle_query_reset_c(GArray *params, void *user_ctx) {
@@ -1539,7 +1438,6 @@ void handle_query_reset_c(GArray *params, void *user_ctx) {
mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, query_index);
g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id);
mcd_put_strbuf();
- // TODO: we still need to implement the gpr and memory reset here!
}
void handle_close_core(GArray *params, void *user_ctx) {
@@ -1575,7 +1473,7 @@ void handle_close_server(GArray *params, void *user_ctx) {
mcdserver_state.c_cpu = mcd_first_attached_cpu();
}
if (!mcdserver_state.c_cpu) {
- /* No more process attached */
+ // no more processes attached
mcd_disable_syscalls();
mcd_vm_start();
}
@@ -1595,10 +1493,15 @@ void mcd_vm_start(void) {
}
}
+int mcd_vm_sstep(CPUState *cpu) {
+ cpu_single_step(mcdserver_state.c_cpu, mcdserver_state.sstep_flags);
+ mcd_vm_start();
+ return 0;
+}
+
void mcd_vm_stop(void) {
if (runstate_is_running()) {
- //might want to have DEBUG state here but idk
- vm_stop(RUN_STATE_PAUSED);
+ vm_stop(RUN_STATE_DEBUG);
}
}
@@ -1724,7 +1627,7 @@ void handle_query_regs_f(GArray *params, void *user_ctx) {
}
void handle_query_regs_c(GArray *params, void *user_ctx) {
- // this funcitons send all reg groups except for the first
+ // this funcitons send all regs except for the first
// 1. get parameter and registers
int query_index = get_param(params, 0)->query_handle;
uint32_t cpu_id = mcdserver_state.query_cpu_id;
@@ -1750,16 +1653,12 @@ void handle_query_regs_c(GArray *params, void *user_ctx) {
}
void handle_reset(GArray *params, void *user_ctx) {
- int reset_id = get_param(params, 0)->data_int;
- //int bool_halt_after_reset = get_param(params, 1)->data_int;
- if (reset_id>=0) {
- //fun for the compiler
- }
+ //int reset_id = get_param(params, 0)->data_int;
+ // TODO: implement resets
}
void handle_query_state(GArray *params, void *user_ctx) {
- // send state from correct core
- //uint32_t cpu_id = get_param(params, 0)->cpu_id;
+ // TODO: multicore support
// get state info
mcd_cpu_state_st state_info = mcdserver_state.cpu_state;
mcd_core_event_et event = MCD_CORE_EVENT_NONE;
@@ -1795,6 +1694,19 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) {
}
}
+int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg) {
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ gchar *arch = cc->gdb_arch_name(cpu);
+ if (strcmp(arch, "arm")==0) {
+ g_free(arch);
+ return arm_mcd_write_register(cpu, buf, reg);
+ }
+ else {
+ g_free(arch);
+ return 0;
+ }
+}
+
void mcd_memtohex(GString *buf, const uint8_t *mem, int len) {
int i, c;
for(i = 0; i < len; i++) {
@@ -1817,18 +1729,28 @@ void mcd_hextomem(GByteArray *mem, const char *buf, int len) {
void handle_read_register(GArray *params, void *user_ctx) {
uint32_t cpu_id = get_param(params, 0)->cpu_id;
- int reg_num = get_param(params, 1)->data_int;
+ uint64_t reg_num = get_param(params, 1)->data_int;
int reg_size;
CPUState *cpu = mcd_get_cpu(cpu_id);
-
reg_size = mcd_read_register(cpu, mcdserver_state.mem_buf, reg_num);
- mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, reg_size);
+ mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, reg_size);
mcd_put_strbuf();
}
void handle_write_register(GArray *params, void *user_ctx) {
+ uint32_t cpu_id = get_param(params, 0)->cpu_id;
+ uint64_t reg_num = get_param(params, 1)->data_int;
+ uint32_t reg_size = get_param(params, 2)->data_int;
+ CPUState *cpu = mcd_get_cpu(cpu_id);
+ mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, reg_size);
+ if (mcd_write_register(cpu, mcdserver_state.mem_buf, reg_num)==0) {
+ mcd_put_packet(TCP_EXECUTION_ERROR);
+ }
+ else {
+ mcd_put_packet(TCP_EXECUTION_SUCCESS);
+ }
}
int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) {
@@ -1836,7 +1758,6 @@ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) {
//TODO: add physical mem cpu_physical_memory_read(addr, buf, len);
cc = CPU_GET_CLASS(cpu);
if (cc->memory_rw_debug) {
- // TODO: check out the difference between those two calls
return cc->memory_rw_debug(cpu, addr, buf, len, false);
}
@@ -1848,7 +1769,6 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) {
//TODO: add physical mem cpu_physical_memory_read(addr, buf, len);
cc = CPU_GET_CLASS(cpu);
if (cc->memory_rw_debug) {
- // TODO: check out the difference between those two calls
return cc->memory_rw_debug(cpu, addr, buf, len, true);
}
@@ -306,7 +306,7 @@ void cpu_handle_guest_debug(CPUState *cpu)
cpu_single_step(cpu, 0);
}
} else {
- gdb_set_stop_cpu(cpu);
+ //gdb_set_stop_cpu(cpu);
qemu_system_debug_request();
cpu->stopped = true;
}
@@ -8,7 +8,7 @@
static inline int mcd_get_reg32(GByteArray *buf, uint32_t val)
{
- //FIXME: move this to a separate file
+ //TODO: move this to a separate file
// convert endianess if necessary
uint32_t to_long = tswap32(val);
g_byte_array_append(buf, (uint8_t *) &to_long, 4);
@@ -17,7 +17,7 @@ static inline int mcd_get_reg32(GByteArray *buf, uint32_t val)
static inline int mcd_get_zeroes(GByteArray *array, size_t len)
{
- //FIXME: move this to a separate file
+ //TODO: move this to a separate file
guint oldlen = array->len;
g_byte_array_set_size(array, oldlen + len);
memset(array->data + oldlen, 0, len);
@@ -44,9 +44,6 @@ const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname)
}
int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) {
- //CPUClass *cc = CPU_GET_CLASS(cpu);
- //CPUArchState *env = cpu->env_ptr;
-
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
@@ -70,6 +67,61 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) {
return mcd_get_reg32(mem_buf, cpsr_read(env));
}
}
- //TODO: add funcitons for regs with higher numbers (including cp_regs)
+ //TODO: add funcitons for the remaining regs (including cp_regs)
+ return 0;
+}
+
+int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) {
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+ uint32_t tmp;
+
+ tmp = ldl_p(mem_buf);
+ tmp = *((uint32_t*)mem_buf->data);
+
+ /*
+ * Mask out low bits of PC to workaround gdb bugs.
+ * This avoids an assert in thumb_tr_translate_insn, because it is
+ * architecturally impossible to misalign the pc.
+ * This will probably cause problems if we ever implement the
+ * Jazelle DBX extensions.
+ */
+ if (n == 15) {
+ tmp &= ~1;
+ }
+
+ if (n < 16) {
+ /* Core integer register. */
+ if (n == 13 && arm_feature(env, ARM_FEATURE_M)) {
+ /* M profile SP low bits are always 0 */
+ tmp &= ~3;
+ }
+ env->regs[n] = tmp;
+ return 4;
+ }
+ if (n < 24) { /* 16-23 */
+ /* FPA registers (ignored). */
+ return 4;
+ }
+ switch (n) {
+ case 24:
+ /* FPA status register (ignored). */
+ return 4;
+ case 25:
+ /* CPSR, or XPSR for M-profile */
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ /*
+ * Don't allow writing to XPSR.Exception as it can cause
+ * a transition into or out of handler mode (it's not
+ * writable via the MSR insn so this is a reasonable
+ * restriction). Other fields are safe to update.
+ */
+ xpsr_write(env, tmp, ~XPSR_EXCP);
+ } else {
+ cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
+ }
+ return 4;
+ }
+ //TODO: add funcitons for the remaining regs (including cp_regs)
return 0;
-}
\ No newline at end of file
+}
@@ -3,5 +3,6 @@
const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname);
int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n);
+int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n);
#endif /* ARM_MCDSTUB_H */
From: neder <nicolas.eder@lauterbach.com> --- include/exec/mcdstub.h | 6 +- include/mcdstub/syscalls.h | 4 +- mcdstub/internals.h | 77 +++---- mcdstub/mcd_shared_defines.h | 3 +- mcdstub/mcdstub.c | 428 ++++++++++++++--------------------- softmmu/cpus.c | 2 +- target/arm/mcdstub.c | 66 +++++- target/arm/mcdstub.h | 1 + 8 files changed, 269 insertions(+), 318 deletions(-)