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],