]> granicus.if.org Git - strace/commitdiff
gdbserver: readlink fixes
authorEugene Syromyatnikov <evgsyr@gmail.com>
Mon, 18 Feb 2019 01:33:30 +0000 (02:33 +0100)
committerEugene Syromyatnikov <evgsyr@gmail.com>
Wed, 27 Feb 2019 16:35:22 +0000 (17:35 +0100)
gdbserver/gdbserver.c
gdbserver/protocol.c
gdbserver/protocol.h

index 1df7e3db964b069bdbb486ec1ca03ad6d2a0e005..c9fc014df9d7da8e674e6111bd2eb266b7b9215c 100644 (file)
@@ -1142,22 +1142,50 @@ gdb_upoke(struct tcb *tcp, unsigned long off, kernel_ulong_t res)
        return gdb_write_mem(tcp->pid, off, current_wordsize, (char*)&buffer);
 }
 
-
+/**
+ * readlink(2) implementation.
+ *  - Returns amount of bytes written to buf or -1 on error.
+ *  - Doesn't write terminating null byte.
+ *  - If result is more than bufsize, bufsize bytes is returned (result
+ *    is truncated)
+ */
 int
-gdb_getfdpath(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
+gdb_readlink(struct tcb *tcp, const char *linkpath,
+       char *buf, size_t bufsize)
 {
-       if (!gdb || fd < 0)
+       char *parameters = gdb_encode_hex_string(linkpath);
+       if (!parameters) {
+               errno = ENAMETOOLONG;
                return -1;
+       }
 
-       /*
-        * As long as we assume a Linux target, we can peek at their procfs
-        * just like normal getfdpath does.  Maybe that won't always be true.
-        */
-       char linkpath[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
-       sprintf(linkpath, "/proc/%u/fd/%u", tcp->pid, fd);
-       return gdb_readlink(gdb, linkpath, buf, bufsize);
-}
+       struct vfile_response res = gdb_vfile(gdb, "readlink", parameters);
+       free(parameters);
+
+       int ret = -1;
 
+       if (res.result >= 0 && res.attachment != NULL &&
+           res.result == (int64_t) res.attachment_size) {
+               uint64_t data_len = res.attachment_size;
+
+               if (data_len >= bufsize)
+                       data_len = bufsize;
+               if (data_len > SSIZE_MAX)
+                       data_len = SSIZE_MAX;
+
+               if (gdb_decode_hex_buf(res.attachment, data_len << 1, buf))
+                       res.errnum = EIO;
+               else
+                       ret = data_len;
+       }
+
+       free(res.reply);
+
+       if (ret == -1)
+               errno = res.errnum;
+
+       return ret;
+}
 
 bool
 gdb_verify_args(const char *username, bool daemon, unsigned int *follow_fork)
@@ -1274,17 +1302,20 @@ const struct tracing_backend gdbserver_backend = {
 
        .next_event         = gdb_next_event,
        .handle_exec        = (0),
-       .handle_group_stop  = gdb_handle_group_stop,
-       .get_siginfo        = (0),
        .restart_process    = gdb_restart_process,
 
        .clear_regs         = (0),
        .get_regs           = gdb_get_registers,
        .get_scno           = gdb_get_scno,
        .set_scno           = gdb_set_scno,
-       .set_error          = ptrace_set_error,
-       .set_success        = ptrace_set_success,
-       .get_syscall_result = ptrace_get_syscall_result,
+
+       .set_error          = /* XXX */ ptrace_set_error,
+       .set_success        = /* XXX */ ptrace_set_success,
+
+       .get_instruction_pointer = generic_get_instruction_pointer,
+       .get_stack_pointer       = generic_get_stack_pointer,
+       .get_syscall_args        = /* XXX */ ptrace_get_syscall_args,
+       .get_syscall_result      = /* XXX */ ptrace_get_syscall_result,
 
        .umoven             = gdb_umoven,
        .umovestr           = gdb_umovestr,
@@ -1295,7 +1326,7 @@ const struct tracing_backend gdbserver_backend = {
        .open               = (0),
        .pread              = (0),
        .close              = (0),
-       .readlink           = (0),
+       .readlink           = gdb_tracee_readlink,
        .getxattr           = (0),
        .socket             = (0),
        .sendmsg            = (0),
index 97e5a77538af0010ee3435d61196dfaedb2381b6..e5f9a2fe08baa693c73c6d8165795f1467de146f 100644 (file)
@@ -695,14 +695,6 @@ gdb_xfer_read(struct gdb_conn *conn, const char *object, const char *annex,
        return NULL;
 }
 
-struct vfile_response {
-       char *reply;
-       int64_t result;
-       int64_t errnum; /* avoid 'errno' macros */
-       size_t attachment_size;
-       const char *attachment;
-};
-
 static struct vfile_response
 gdb_vfile(struct gdb_conn *conn, const char *operation, const char *parameters)
 {
@@ -711,7 +703,6 @@ gdb_vfile(struct gdb_conn *conn, const char *operation, const char *parameters)
        char *cmd;
        int cmd_size = asprintf(&cmd, "vFile:%s:%s", operation, parameters);
        if (cmd_size < 0)
-               /* XXX Returns automatic variable! */
                return res;
 
        gdb_send(conn, cmd, strlen(cmd));
@@ -730,39 +721,13 @@ gdb_vfile(struct gdb_conn *conn, const char *operation, const char *parameters)
                }
 
                const char *errnum = memchr(res.reply, ',', size - res.attachment_size);
+               /*
+                * XXX convert errno value
+                *     https://sourceware.org/gdb/onlinedocs/gdb/Errno-Values.html
+                */
                if (errnum)
                        res.errnum = gdb_decode_signed_hex_str(errnum + 1);
        }
-       /* XXX Returns automatic variable! */
-       return res;
-}
-
-int
-gdb_readlink(struct gdb_conn *conn, const char *linkpath,
-       char *buf, unsigned bufsize)
-{
-       char *parameters = gdb_encode_hex_string(linkpath);
-       if (!parameters)
-               return -1;
 
-       struct vfile_response res = gdb_vfile(conn, "readlink", parameters);
-       free(parameters);
-
-       int ret = -1;
-
-       if (res.result >= 0 && res.attachment != NULL &&
-           res.result == (int64_t) res.attachment_size) {
-               size_t data_len = res.attachment_size;
-
-               if (data_len >= bufsize)
-                       data_len = bufsize - 1; /* XXX truncate -- ok? */
-
-               memcpy(buf, res.attachment, data_len);
-               buf[data_len] = 0;
-               ret = data_len;
-       }
-
-       free(res.reply);
-
-       return ret;
+       return res;
 }
index 1ebf9e1d82bc7d119627e2515a88605ec70545e0..712a52041318b9400d2c9d083b93a3eaa556b1a4 100644 (file)
 
 struct gdb_conn;
 
+/**
+ * Structure containing response for vFile requests[1].
+ *
+ * [1] https://sourceware.org/gdb/onlinedocs/gdb/Host-I_002fO-Packets.html
+ */
+struct vfile_response {
+       /** The whole reply, callee-allocated. */
+       char *reply;
+       /** Result, returned from the target */
+       int64_t result;
+       /** Error number returned from the target */
+       int64_t errnum;
+       /** Size of attachment, in bytes */
+       uint64_t attachment_size;
+       /**
+        * Pointer to the attachment inside reply. The attachment is hex-encoded
+        * (should be subjected to gdb_decode_hex* before usage).
+        */
+       const char *attachment;
+};
+
 void gdb_encode_hex(uint8_t byte, char *out);
 uint16_t gdb_decode_hex(char msb, char lsb);
 uint64_t gdb_decode_hex_n(const char *bytes, size_t n);