return ERROR_OK;
}
-/* Convert register to string of bits. NB! The # of bits in the
+
+static int gdb_reg_pos(target_t *target, int pos, int len)
+{
+ if (target->endianness == TARGET_LITTLE_ENDIAN)
+ return pos;
+ else
+ return len - 1 - pos;
+}
+
+/* Convert register to string of bytes. NB! The # of bits in the
* register might be non-divisible by 8(a byte), in which
- * case an entire byte is shown. */
+ * case an entire byte is shown.
+ *
+ * NB! the format on the wire is the target endianess
+ *
+ * The format of reg->value is little endian
+ *
+ */
void gdb_str_to_target(target_t *target, char *tstr, reg_t *reg)
{
int i;
for (i = 0; i < buf_len; i++)
{
- tstr[i*2] = DIGITS[(buf[i]>>4) & 0xf];
- tstr[i*2+1] = DIGITS[buf[i]&0xf];
+ int j = gdb_reg_pos(target, i, buf_len);
+ tstr[i*2] = DIGITS[(buf[j]>>4) & 0xf];
+ tstr[i*2+1] = DIGITS[buf[j]&0xf];
}
}
-void gdb_target_to_str(target_t *target, char *tstr, char *str)
+static int hextoint(char c)
{
- int str_len = strlen(tstr);
- int i;
+ if (c>='0'&&c<='9')
+ {
+ return c-'0';
+ }
+ c=toupper(c);
+ if (c>='A'&&c<='F')
+ {
+ return c-'A'+10;
+ }
+ LOG_ERROR("BUG: invalid register value %08x", c);
+ return 0;
+}
+/* copy over in register buffer */
+void gdb_target_to_reg(target_t *target, char *tstr, int str_len, u8 *bin)
+{
if (str_len % 2)
{
LOG_ERROR("BUG: gdb value with uneven number of characters encountered");
exit(-1);
}
+ int i;
for (i = 0; i < str_len; i+=2)
{
- str[str_len - i - 1] = tstr[i + 1];
- str[str_len - i - 2] = tstr[i];
+ u8 t = hextoint(tstr[i])<<4;
+ t |= hextoint(tstr[i]);
+
+ int j = gdb_reg_pos(target, i/2, str_len/2);
+ bin[j] = t;
}
}
for (i = 0; i < reg_list_size; i++)
{
u8 *bin_buf;
- char *hex_buf;
- reg_arch_type_t *arch_type;
+ int chars = (CEIL(reg_list[i]->size, 8) * 2);
- /* convert from GDB-string (target-endian) to hex-string (big-endian) */
- hex_buf = malloc(CEIL(reg_list[i]->size, 8) * 2);
- gdb_target_to_str(target, packet_p, hex_buf);
+ if (packet_p + chars > packet + packet_size)
+ {
+ LOG_ERROR("BUG: register packet is too small for registers");
+ }
- /* convert hex-string to binary buffer */
+ reg_arch_type_t *arch_type;
bin_buf = malloc(CEIL(reg_list[i]->size, 8));
- str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16);
+ gdb_target_to_reg(target, packet_p, chars, bin_buf);
/* get register arch_type, and call set method */
arch_type = register_get_arch_type(reg_list[i]->arch_type);
arch_type->set(reg_list[i], bin_buf);
/* advance packet pointer */
- packet_p += (CEIL(reg_list[i]->size, 8) * 2);
+ packet_p += chars;
+
free(bin_buf);
- free(hex_buf);
}
/* free reg_t *reg_list[] array allocated by get_gdb_reg_list */
int gdb_set_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
{
char *separator;
- char *hex_buf;
u8 *bin_buf;
int reg_num = strtoul(packet + 1, &separator, 16);
reg_t **reg_list;
}
/* convert from GDB-string (target-endian) to hex-string (big-endian) */
- hex_buf = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);
- gdb_target_to_str(target, separator + 1, hex_buf);
-
- /* convert hex-string to binary buffer */
bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8));
- str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16);
+ int chars = (CEIL(reg_list[reg_num]->size, 8) * 2);
- /* get register arch_type, and call set method */
+ /* fix!!! add some sanity checks on packet size here */
+
+ gdb_target_to_reg(target, separator + 1, chars, bin_buf);
+
+ /* get register arch_type, and call set method */
arch_type = register_get_arch_type(reg_list[reg_num]->arch_type);
arch_type->set(reg_list[reg_num], bin_buf);
gdb_put_packet(connection, "OK", 2);
free(bin_buf);
- free(hex_buf);
free(reg_list);
return ERROR_OK;