aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/remote-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/gdbserver/remote-utils.c')
-rw-r--r--gdb/gdbserver/remote-utils.c113
1 files changed, 107 insertions, 6 deletions
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 164ce6a..3dfd1c9 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -1127,7 +1127,7 @@ write_enn (char *buf)
}
void
-convert_int_to_ascii (unsigned char *from, char *to, int n)
+convert_int_to_ascii (const unsigned char *from, char *to, int n)
{
int nib;
int ch;
@@ -1144,7 +1144,7 @@ convert_int_to_ascii (unsigned char *from, char *to, int n)
void
-convert_ascii_to_int (char *from, unsigned char *to, int n)
+convert_ascii_to_int (const char *from, unsigned char *to, int n)
{
int nib1, nib2;
while (n--)
@@ -1354,7 +1354,7 @@ decode_m_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr)
void
decode_M_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr,
- unsigned char *to)
+ unsigned char **to_p)
{
int i = 0;
char ch;
@@ -1372,12 +1372,15 @@ decode_M_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr,
*len_ptr |= fromhex (ch) & 0x0f;
}
- convert_ascii_to_int (&from[i++], to, *len_ptr);
+ if (*to_p == NULL)
+ *to_p = xmalloc (*len_ptr);
+
+ convert_ascii_to_int (&from[i++], *to_p, *len_ptr);
}
int
decode_X_packet (char *from, int packet_len, CORE_ADDR *mem_addr_ptr,
- unsigned int *len_ptr, unsigned char *to)
+ unsigned int *len_ptr, unsigned char **to_p)
{
int i = 0;
char ch;
@@ -1395,8 +1398,11 @@ decode_X_packet (char *from, int packet_len, CORE_ADDR *mem_addr_ptr,
*len_ptr |= fromhex (ch) & 0x0f;
}
+ if (*to_p == NULL)
+ *to_p = xmalloc (*len_ptr);
+
if (remote_unescape_input ((const gdb_byte *) &from[i], packet_len - i,
- to, *len_ptr) != *len_ptr)
+ *to_p, *len_ptr) != *len_ptr)
return -1;
return 0;
@@ -1565,6 +1571,101 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb)
return 1;
}
+/* Relocate an instruction to execute at a different address. OLDLOC
+ is the address in the inferior memory where the instruction to
+ relocate is currently at. On input, TO points to the destination
+ where we want the instruction to be copied (and possibly adjusted)
+ to. On output, it points to one past the end of the resulting
+ instruction(s). The effect of executing the instruction at TO
+ shall be the same as if executing it at FROM. For example, call
+ instructions that implicitly push the return address on the stack
+ should be adjusted to return to the instruction after OLDLOC;
+ relative branches, and other PC-relative instructions need the
+ offset adjusted; etc. Returns 0 on success, -1 on failure. */
+
+int
+relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
+{
+ char own_buf[266];
+ int len;
+ ULONGEST written = 0;
+
+ /* Send the request. */
+ strcpy (own_buf, "qRelocInsn:");
+ sprintf (own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
+ paddress (*to));
+ if (putpkt (own_buf) < 0)
+ return -1;
+
+ /* FIXME: Eventually add buffer overflow checking (to getpkt?) */
+ len = getpkt (own_buf);
+ if (len < 0)
+ return -1;
+
+ /* We ought to handle pretty much any packet at this point while we
+ wait for the qRelocInsn "response". That requires re-entering
+ the main loop. For now, this is an adequate approximation; allow
+ GDB to access memory. */
+ while (own_buf[0] == 'm' || own_buf[0] == 'M' || own_buf[0] == 'X')
+ {
+ CORE_ADDR mem_addr;
+ unsigned char *mem_buf = NULL;
+ unsigned int mem_len;
+
+ if (own_buf[0] == 'm')
+ {
+ decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
+ mem_buf = xmalloc (mem_len);
+ if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
+ convert_int_to_ascii (mem_buf, own_buf, mem_len);
+ else
+ write_enn (own_buf);
+ }
+ else if (own_buf[0] == 'X')
+ {
+ if (decode_X_packet (&own_buf[1], len - 1, &mem_addr,
+ &mem_len, &mem_buf) < 0
+ || write_inferior_memory (mem_addr, mem_buf, mem_len) != 0)
+ write_enn (own_buf);
+ else
+ write_ok (own_buf);
+ }
+ else
+ {
+ decode_M_packet (&own_buf[1], &mem_addr, &mem_len, &mem_buf);
+ if (write_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
+ write_ok (own_buf);
+ else
+ write_enn (own_buf);
+ }
+ free (mem_buf);
+ if (putpkt (own_buf) < 0)
+ return -1;
+ len = getpkt (own_buf);
+ if (len < 0)
+ return -1;
+ }
+
+ if (own_buf[0] == 'E')
+ {
+ warning ("An error occurred while relocating an instruction: %s\n",
+ own_buf);
+ return -1;
+ }
+
+ if (strncmp (own_buf, "qRelocInsn:", strlen ("qRelocInsn:")) != 0)
+ {
+ warning ("Malformed response to qRelocInsn, ignoring: %s\n",
+ own_buf);
+ return -1;
+ }
+
+ unpack_varlen_hex (own_buf + strlen ("qRelocInsn:"), &written);
+
+ *to += written;
+ return 0;
+}
+
void
monitor_output (const char *msg)
{