Remove duplicate code where possible by using reusable functions.

Signed-off-by: Srikar Dronamraju <sri...@linux.vnet.ibm.com>
---
 kernel/utrace-gdb.c |  272 +++++++++++++++++++++++----------------------------
 1 files changed, 123 insertions(+), 149 deletions(-)

diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c
index f44b3c0..97811c2 100644
--- a/kernel/utrace-gdb.c
+++ b/kernel/utrace-gdb.c
@@ -793,6 +793,84 @@ static int gdb_remote_register_info(struct gdb_connection 
*p,
        return -ENOENT;
 }
 
+static inline int fetch_remote_register_info(struct gdb_connection *p,
+                                       struct task_struct *task,
+                                       int index,
+                                       unsigned *pos,
+                                       unsigned *count,
+                                       unsigned *bytes)
+{
+       int rsn;
+
+       rsn = gdb_remote_register_info(p, task, index, pos, count, bytes);
+       pr_debug("gdb register %u => rsn %d p%u c%u b%u\n", index, rsn,
+                                                       *pos, *count, *bytes);
+       if (rsn > 0) {
+               /*
+                * If we want to extract register data, make sure we're
+                * fetching at least that much.
+                */
+               BUG_ON(*count > 0 && *count < *bytes);
+               /* Assert reg_contents size is right. */
+               BUG_ON(MAX_REG_WIDTH < *bytes || MAX_REG_WIDTH < *count);
+       }
+       return rsn;
+}
+
+static inline int get_set_regset_view(struct task_struct *task,
+                       unsigned pos, unsigned count,
+                       unsigned char *reg_contents,
+                       int rsn, bool set)
+{
+       int rc;
+       const struct user_regset_view *rsv;
+       const struct user_regset *rs;
+
+       if (!count) {
+               if (!set)
+                       memset(reg_contents, 0, MAX_REG_WIDTH);
+               return 0;
+       }
+
+       /* real register */
+       if (set)
+               BUG_ON(count > MAX_REG_WIDTH);
+
+       rsv = task_user_regset_view(task);
+       BUG_ON(rsn >= rsv->n);
+       rs = &rsv->regsets[rsn];
+
+       /* Extract the register values into reg_contents[]. */
+       if (set)
+               rc = (rs->set)(task, rs, pos, count, reg_contents, NULL);
+       else
+               rc = (rs->get)(task, rs, pos, count, reg_contents, NULL);
+
+       return rc;
+}
+
+static inline void prepare_regset_set(struct gdb_connection *p,
+                               unsigned char *reg_contents,
+                               size_t *start, unsigned bytes)
+{
+       int j;
+
+       /*
+        * 0-fill the register copy.
+        * XXX initialize it from rs->get() instead?
+        */
+       memset(reg_contents, 0, MAX_REG_WIDTH);
+
+       /*
+        * Hex-unconvert all the bytes.
+        * XXX: endianness adjust for count != bytes
+        */
+       for (j = 0; j < bytes; j++)
+               reg_contents[j] = byteme(p->input_buf[*start + 2 * j],
+                                          p->input_buf[*start + 2 * j + 1]);
+       *start += 2 * bytes;
+}
+
 /*
  * Process an entire, checksum-confirmed $command# at the front of
  * p->input_buf[].  The input and output mutexes are being held.
@@ -880,50 +958,23 @@ static void handle_gdb_command_packet(struct 
gdb_connection *p,
                        unsigned rs_count;
                        unsigned rs_pos;
                        unsigned bytes;
-                       const struct user_regset_view *rsv;
-                       const struct user_regset *rs;
+                       int rsn;
                        unsigned char reg_contents[MAX_REG_WIDTH];
 
-                       int rsn = gdb_remote_register_info(p, task, i,
-                                                          &rs_pos, &rs_count,
-                                                          &bytes);
-
+                       rsn = fetch_remote_register_info(p, task, i,
+                                          &rs_pos, &rs_count, &bytes);
                        if (rsn < 0)
                                break;
 
-                       /*
-                        * If we want to extract register data, make sure
-                        * we're fetching at least that much.
-                        */
-                       BUG_ON(rs_count > 0 && rs_count < bytes);
-                       /* Assert reg_contents size is right. */
-                       BUG_ON(sizeof(reg_contents) < bytes ||
-                              sizeof(reg_contents) < rs_count);
-
-                       if (rs_count) { /* real register */
-                               rsv = task_user_regset_view(task);
-                               BUG_ON(rsn >= rsv->n);
-                               rs = &rsv->regsets[rsn];
-
-                               /*
-                                * Extract the register values into
-                                * reg_contents[].
-                                */
-                               rc = (rs->get)(task, rs, rs_pos, rs_count,
-                                               reg_contents, NULL);
-                               if (rc)
-                                       break;
-
-                       } else {        /* dummy value */
-                               memset(reg_contents, 0, sizeof(reg_contents));
-                       }
+                       rc = get_set_regset_view(task, rs_pos, rs_count,
+                                               reg_contents, rsn, false);
+                       if (rc)
+                               break;
 
                        /*
                         * Hex-dump it.
                         * XXX: endianness adjust for count != bytes
                         */
-                       /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u (",
-                                       i, rsn, rs_pos, rs_count, bytes); */
                        for (j = 0; j < bytes; j++) {
                                /* pr_debug("%02x", reg_contents[j]); */
                                push_output_hex(p, reg_contents[j]);
@@ -937,66 +988,27 @@ static void handle_gdb_command_packet(struct 
gdb_connection *p,
                i = 0;
                op_start = 2;   /* use as input pointer, past $G in command */
                while (p->input_buf[op_start] != '#' &&
-                      op_start < p->input_buf_size) {
+                                      op_start < p->input_buf_size) {
                        unsigned rs_count;
                        unsigned rs_pos;
                        unsigned bytes;
-                       const struct user_regset_view *rsv;
-                       const struct user_regset *rs;
+                       int rsn;
                        unsigned char reg_contents[MAX_REG_WIDTH];
 
-                       int rsn = gdb_remote_register_info(p, task, i,
-                                                          &rs_pos, &rs_count,
-                                                          &bytes);
-                       /* pr_debug ("gdb register %d => rsn %d p%u c%u b%u\n",
-                                       i, rsn, rs_pos, rs_count, bytes); */
-
+                       rsn = fetch_remote_register_info(p, task, i,
+                                          &rs_pos, &rs_count, &bytes);
                        if (rsn < 0)
                                break;
 
-                       /*
-                        * If we want to extract register data, make sure
-                        * we're fetching at least that much.
-                        */
-                       BUG_ON(rs_count > 0 && rs_count < bytes);
-                       /* Assert reg_contents size is right. */
-                       BUG_ON(sizeof(reg_contents) < bytes ||
-                              sizeof(reg_contents) < rs_count);
-
                        /* Remaining packet too short? */
                        if ((op_start + 2 * bytes + 3) < p->input_buf_size)
                                break;
 
-                       /*
-                        * 0-fill the register copy.  XXX initialize
-                        * it from rs->get() instead?
-                        */
-                       memset(reg_contents, 0, sizeof(reg_contents));
-
-                       /*
-                        * Hex-unconvert all the bytes.
-                        * XXX: endianness adjust for count != bytes
-                        */
-                       for (j = 0; j < bytes; j++)
-                               reg_contents[j] =
-                                   byteme(p->input_buf[op_start + 2 * j],
-                                          p->input_buf[op_start + 2 * j + 1]);
-                       op_start += 2 * bytes;
-
-                       if (rs_count) { /* real register */
-                               BUG_ON(rs_count > sizeof(reg_contents));
-                               rsv = task_user_regset_view(task);
-                               BUG_ON(rsn >= rsv->n);
-                               rs = &rsv->regsets[rsn];
-
-                               /* Set register values from reg_contents[]. */
-                               rc = (rs->set) (task, rs, rs_pos, rs_count,
-                                               reg_contents, NULL);
-                               if (rc)
-                                       break;
-                       } else {        /* dummy register */
-                               ;
-                       }
+                       prepare_regset_set(p, reg_contents, &op_start, bytes);
+                       rc = get_set_regset_view(task, rs_pos, rs_count,
+                                               reg_contents, rsn, true);
+                       if (rc)
+                               break;
                }
                if (p->input_buf[op_start] == '#' && rc == 0)
                        push_output_packet(p, "OK");
@@ -1017,59 +1029,22 @@ static void handle_gdb_command_packet(struct 
gdb_connection *p,
                        unsigned rs_count;
                        unsigned rs_pos;
                        unsigned bytes;
-                       const struct user_regset_view *rsv;
-                       const struct user_regset *rs;
+                       int rsn;
                        unsigned char reg_contents[MAX_REG_WIDTH];
 
-                       int rsn = gdb_remote_register_info(p, task, arg1,
-                                                          &rs_pos, &rs_count,
-                                                          &bytes);
-                       pr_debug("gdb register %lu => rsn %d p%u c%u b%u\n",
-                                arg1, rsn, rs_pos, rs_count, bytes);
-
+                       rsn = fetch_remote_register_info(p, task, arg1,
+                                          &rs_pos, &rs_count, &bytes);
                        if (rsn < 0)
                                break;
 
-                       /*
-                        * If we want to extract register data, make sure
-                        * we're fetching at least that much.
-                        */
-                       BUG_ON(rs_count > 0 && rs_count < bytes);
-                       /* Assert reg_contents size is right. */
-                       BUG_ON(sizeof(reg_contents) < bytes ||
-                              sizeof(reg_contents) < rs_count);
-
                        /* Remaining packet too short? */
                        if ((op_start + 2 * bytes + 3) < p->input_buf_size)
                                break;
 
-                       /*
-                        * 0-fill the register copy.
-                        * XXX initialize it from rs->get() instead?
-                        */
-                       memset(reg_contents, 0, sizeof(reg_contents));
-
-                       /*
-                        * Hex-unconvert all the bytes.
-                        * XXX: endianness adjust for count != bytes
-                        */
-                       for (j = 0; j < bytes; j++)
-                               reg_contents[j] =
-                                   byteme(p->input_buf[op_start + 2 * j],
-                                          p->input_buf[op_start + 2 * j + 1]);
-                       op_start += 2 * bytes;
-
-                       if (rs_count) { /* real register */
-                               BUG_ON(rs_count > sizeof(reg_contents));
-                               rsv = task_user_regset_view(task);
-                               BUG_ON(rsn >= rsv->n);
-                               rs = &rsv->regsets[rsn];
-
-                               /* Set register values from reg_contents[]. */
-                               rc = (rs->set) (task, rs, rs_pos, rs_count,
-                                               reg_contents, NULL);
-                               WARN_ON(rc);
-                       }
+                       prepare_regset_set(p, reg_contents, &op_start, bytes);
+                       rc = get_set_regset_view(task, rs_pos, rs_count,
+                                               reg_contents, rsn, true);
+                       WARN_ON(rc);
                        if (p->input_buf[op_start] == '#' && rc == 0)
                                push_output_packet(p, "OK");
                        else
@@ -1238,7 +1213,8 @@ static int proc_gdb_open(struct inode *inode, struct file 
*filp)
 
        mutex_lock(&gdb_connections_mutex);
 
-       /* Reject if a connection exists for the thread group
+       /*
+        * Reject if a connection exists for the thread group
         * leader.
         */
        list_for_each_entry(p, &gdb_connections, link) {
@@ -1519,29 +1495,27 @@ again:
                } else if (p->input_buf[0] == '$') {    /* command packet */
                        int j;
                        unsigned char checksum = 0;
+                       unsigned char checksum2;
                        for (j = 1; j < p->input_buf_size - 2; j++) {
-                               if (p->input_buf[j] == '#') {
-                                       unsigned char checksum2;
-                                       checksum2 = byteme(p->input_buf[j + 1],
-                                                          p->input_buf[j + 2]);
-                                       pr_debug("received gdb packet %.*s\n",
-                                                j + 3, &p->input_buf[0]);
-                                       if (checksum == checksum2) {
-                                               push_output(p, '+');
-                                               handle_gdb_command_packet(p,
-                                                                         task);
-                                       } else {
-                                               push_output(p, '-');
-                                       }
-                                       /* Consume the whole packet. */
-                                       p->input_buf_size -= (j + 3);
-                                       memmove(&p->input_buf[0],
-                                               &p->input_buf[j + 3],
-                                               p->input_buf_size);
-                                       break;
-                               } else {
+                               if (p->input_buf[j] != '#') {
                                        checksum += p->input_buf[j];
+                                       continue;
                                }
+                               checksum2 = byteme(p->input_buf[j + 1],
+                                                  p->input_buf[j + 2]);
+                               pr_debug("received gdb packet %.*s\n",
+                                                j + 3, &p->input_buf[0]);
+                               if (checksum == checksum2) {
+                                       push_output(p, '+');
+                                       handle_gdb_command_packet(p, task);
+                               } else
+                                       push_output(p, '-');
+
+                               /* Consume the whole packet. */
+                               p->input_buf_size -= (j + 3);
+                               memmove(&p->input_buf[0], &p->input_buf[j + 3],
+                                                       p->input_buf_size);
+                               break;
                        }       /* End searching for end of packet */
 
                        /*
@@ -1556,8 +1530,8 @@ again:
                         * we'll iterate one more time in this loop.
                         */
                } else {        /* junk character */
-                       printk(KERN_WARNING "Unexpected character (%x) received"
-                              " on /proc/%d/gdb connection.\n",
+                       printk(KERN_WARNING "Unexpected character (%x) "
+                              "received on /proc/%d/gdb connection.\n",
                               (int)p->input_buf[0], task_pid_nr(task));
                        /* Consume the input. */
                        memmove(&p->input_buf[0], &p->input_buf[1],

Reply via email to