From 5acfdbae5d2b0aaa2320ddfa3aa1f2cddce7b978 Mon Sep 17 00:00:00 2001 From: Sergio Durigan Junior Date: Sun, 12 Jan 2014 01:32:26 -0200 Subject: [PATCH] Split i386_stap_parse_special_token into smaller functions This patch reorganizes code on gdb/i386-tdep.c's SystemTap SDT probe support functions. Before it, the code to parse special operands on x86 lived in a single, big function. This patch creates 2 new functions that makes the code more organized and removes a few indentation levels (which is always good IMO). I haven't modified anything logical in the functions, i.e., there's still one latent bug on i386_stap_parse_special_token_triplet now. I will soon post a patch to fix this, and to also improve the readability of the two new functions. 2014-01-12 Sergio Durigan Junior * i386-tdep.c (i386_stap_parse_special_token_triplet): New function, with code from i386_stap_parse_special_token. (i386_stap_parse_special_token_three_arg_disp): Likewise. (i386_stap_parse_special_token): Move code to the two functions above; simplify it. --- gdb/ChangeLog | 8 + gdb/i386-tdep.c | 515 +++++++++++++++++++++++++++++--------------------------- 2 files changed, 279 insertions(+), 244 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 850709b..fd7aeee 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2014-01-12 Sergio Durigan Junior + + * i386-tdep.c (i386_stap_parse_special_token_triplet): New + function, with code from i386_stap_parse_special_token. + (i386_stap_parse_special_token_three_arg_disp): Likewise. + (i386_stap_parse_special_token): Move code to the two functions + above; simplify it. + 2014-01-09 Pedro Alves Hui Zhu diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index ce44ffd..9d1d9e0 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3605,311 +3605,338 @@ i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) || (*s == '%' && isalpha (s[1]))); /* Register access. */ } -/* Implementation of `gdbarch_stap_parse_special_token', as defined in - gdbarch.h. */ +/* Helper function for i386_stap_parse_special_token. -int -i386_stap_parse_special_token (struct gdbarch *gdbarch, - struct stap_parse_info *p) + This function parses operands of the form `-8+3+1(%rbp)', which + must be interpreted as `*(-8 + 3 - 1 + (void *) $eax)'. + + Return 1 if the operand was parsed successfully, zero + otherwise. */ + +static int +i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch, + struct stap_parse_info *p) { - /* In order to parse special tokens, we use a state-machine that go - through every known token and try to get a match. */ - enum + const char *s = p->arg; + + if (isdigit (*s) || *s == '-' || *s == '+') { - TRIPLET, - THREE_ARG_DISPLACEMENT, - DONE - } current_state; + int got_minus[3]; + int i; + long displacements[3]; + const char *start; + char *regname; + int len; + struct stoken str; + char *endp; + + got_minus[0] = 0; + if (*s == '+') + ++s; + else if (*s == '-') + { + ++s; + got_minus[0] = 1; + } - current_state = TRIPLET; + displacements[0] = strtol (s, &endp, 10); + s = endp; - /* The special tokens to be parsed here are: + if (*s != '+' && *s != '-') + { + /* We are not dealing with a triplet. */ + return 0; + } - - `register base + (register index * size) + offset', as represented - in `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'. + got_minus[1] = 0; + if (*s == '+') + ++s; + else + { + ++s; + got_minus[1] = 1; + } - - Operands of the form `-8+3+1(%rbp)', which must be interpreted as - `*(-8 + 3 - 1 + (void *) $eax)'. */ + displacements[1] = strtol (s, &endp, 10); + s = endp; - while (current_state != DONE) - { - const char *s = p->arg; + if (*s != '+' && *s != '-') + { + /* We are not dealing with a triplet. */ + return 0; + } - switch (current_state) + got_minus[2] = 0; + if (*s == '+') + ++s; + else { - case TRIPLET: - { - if (isdigit (*s) || *s == '-' || *s == '+') - { - int got_minus[3]; - int i; - long displacements[3]; - const char *start; - char *regname; - int len; - struct stoken str; - char *endp; - - got_minus[0] = 0; - if (*s == '+') - ++s; - else if (*s == '-') - { - ++s; - got_minus[0] = 1; - } + ++s; + got_minus[2] = 1; + } - displacements[0] = strtol (s, &endp, 10); - s = endp; + displacements[2] = strtol (s, &endp, 10); + s = endp; - if (*s != '+' && *s != '-') - { - /* We are not dealing with a triplet. */ - break; - } + if (*s != '(' || s[1] != '%') + return 0; - got_minus[1] = 0; - if (*s == '+') - ++s; - else - { - ++s; - got_minus[1] = 1; - } + s += 2; + start = s; - displacements[1] = strtol (s, &endp, 10); - s = endp; + while (isalnum (*s)) + ++s; - if (*s != '+' && *s != '-') - { - /* We are not dealing with a triplet. */ - break; - } + if (*s++ != ')') + return 0; - got_minus[2] = 0; - if (*s == '+') - ++s; - else - { - ++s; - got_minus[2] = 1; - } + len = s - start; + regname = alloca (len + 1); - displacements[2] = strtol (s, &endp, 10); - s = endp; + strncpy (regname, start, len); + regname[len] = '\0'; - if (*s != '(' || s[1] != '%') - break; + if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) + error (_("Invalid register name `%s' on expression `%s'."), + regname, p->saved_arg); - s += 2; - start = s; + for (i = 0; i < 3; i++) + { + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type (gdbarch)->builtin_long); + write_exp_elt_longcst (displacements[i]); + write_exp_elt_opcode (OP_LONG); + if (got_minus[i]) + write_exp_elt_opcode (UNOP_NEG); + } - while (isalnum (*s)) - ++s; + write_exp_elt_opcode (OP_REGISTER); + str.ptr = regname; + str.length = len; + write_exp_string (str); + write_exp_elt_opcode (OP_REGISTER); - if (*s++ != ')') - break; + write_exp_elt_opcode (UNOP_CAST); + write_exp_elt_type (builtin_type (gdbarch)->builtin_data_ptr); + write_exp_elt_opcode (UNOP_CAST); - len = s - start; - regname = alloca (len + 1); + write_exp_elt_opcode (BINOP_ADD); + write_exp_elt_opcode (BINOP_ADD); + write_exp_elt_opcode (BINOP_ADD); - strncpy (regname, start, len); - regname[len] = '\0'; + write_exp_elt_opcode (UNOP_CAST); + write_exp_elt_type (lookup_pointer_type (p->arg_type)); + write_exp_elt_opcode (UNOP_CAST); - if (user_reg_map_name_to_regnum (gdbarch, - regname, len) == -1) - error (_("Invalid register name `%s' " - "on expression `%s'."), - regname, p->saved_arg); + write_exp_elt_opcode (UNOP_IND); - for (i = 0; i < 3; i++) - { - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type - (builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (displacements[i]); - write_exp_elt_opcode (OP_LONG); - if (got_minus[i]) - write_exp_elt_opcode (UNOP_NEG); - } + p->arg = s; - write_exp_elt_opcode (OP_REGISTER); - str.ptr = regname; - str.length = len; - write_exp_string (str); - write_exp_elt_opcode (OP_REGISTER); + return 1; + } - write_exp_elt_opcode (UNOP_CAST); - write_exp_elt_type (builtin_type (gdbarch)->builtin_data_ptr); - write_exp_elt_opcode (UNOP_CAST); + return 0; +} - write_exp_elt_opcode (BINOP_ADD); - write_exp_elt_opcode (BINOP_ADD); - write_exp_elt_opcode (BINOP_ADD); +/* Helper function for i386_stap_parse_special_token. - write_exp_elt_opcode (UNOP_CAST); - write_exp_elt_type (lookup_pointer_type (p->arg_type)); - write_exp_elt_opcode (UNOP_CAST); + This function parses operands of the form `register base + + (register index * size) + offset', as represented in + `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'. - write_exp_elt_opcode (UNOP_IND); + Return 1 if the operand was parsed successfully, zero + otherwise. */ - p->arg = s; +static int +i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch, + struct stap_parse_info *p) +{ + const char *s = p->arg; - return 1; - } - break; - } - case THREE_ARG_DISPLACEMENT: - { - if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+') - { - int offset_minus = 0; - long offset = 0; - int size_minus = 0; - long size = 0; - const char *start; - char *base; - int len_base; - char *index; - int len_index; - struct stoken base_token, index_token; - - if (*s == '+') - ++s; - else if (*s == '-') - { - ++s; - offset_minus = 1; - } + if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+') + { + int offset_minus = 0; + long offset = 0; + int size_minus = 0; + long size = 0; + const char *start; + char *base; + int len_base; + char *index; + int len_index; + struct stoken base_token, index_token; + + if (*s == '+') + ++s; + else if (*s == '-') + { + ++s; + offset_minus = 1; + } - if (offset_minus && !isdigit (*s)) - break; + if (offset_minus && !isdigit (*s)) + return 0; - if (isdigit (*s)) - { - char *endp; + if (isdigit (*s)) + { + char *endp; - offset = strtol (s, &endp, 10); - s = endp; - } + offset = strtol (s, &endp, 10); + s = endp; + } - if (*s != '(' || s[1] != '%') - break; + if (*s != '(' || s[1] != '%') + return 0; - s += 2; - start = s; + s += 2; + start = s; - while (isalnum (*s)) - ++s; + while (isalnum (*s)) + ++s; - if (*s != ',' || s[1] != '%') - break; + if (*s != ',' || s[1] != '%') + return 0; - len_base = s - start; - base = alloca (len_base + 1); - strncpy (base, start, len_base); - base[len_base] = '\0'; + len_base = s - start; + base = alloca (len_base + 1); + strncpy (base, start, len_base); + base[len_base] = '\0'; - if (user_reg_map_name_to_regnum (gdbarch, - base, len_base) == -1) - error (_("Invalid register name `%s' " - "on expression `%s'."), - base, p->saved_arg); + if (user_reg_map_name_to_regnum (gdbarch, base, len_base) == -1) + error (_("Invalid register name `%s' on expression `%s'."), + base, p->saved_arg); - s += 2; - start = s; + s += 2; + start = s; - while (isalnum (*s)) - ++s; + while (isalnum (*s)) + ++s; - len_index = s - start; - index = alloca (len_index + 1); - strncpy (index, start, len_index); - index[len_index] = '\0'; + len_index = s - start; + index = alloca (len_index + 1); + strncpy (index, start, len_index); + index[len_index] = '\0'; - if (user_reg_map_name_to_regnum (gdbarch, - index, len_index) == -1) - error (_("Invalid register name `%s' " - "on expression `%s'."), - index, p->saved_arg); + if (user_reg_map_name_to_regnum (gdbarch, index, len_index) == -1) + error (_("Invalid register name `%s' on expression `%s'."), + index, p->saved_arg); - if (*s != ',' && *s != ')') - break; + if (*s != ',' && *s != ')') + return 0; - if (*s == ',') - { - char *endp; + if (*s == ',') + { + char *endp; - ++s; - if (*s == '+') - ++s; - else if (*s == '-') - { - ++s; - size_minus = 1; - } + ++s; + if (*s == '+') + ++s; + else if (*s == '-') + { + ++s; + size_minus = 1; + } - size = strtol (s, &endp, 10); - s = endp; + size = strtol (s, &endp, 10); + s = endp; - if (*s != ')') - break; - } + if (*s != ')') + return 0; + } - ++s; + ++s; - if (offset) - { - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type - (builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (offset); - write_exp_elt_opcode (OP_LONG); - if (offset_minus) - write_exp_elt_opcode (UNOP_NEG); - } + if (offset) + { + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type (gdbarch)->builtin_long); + write_exp_elt_longcst (offset); + write_exp_elt_opcode (OP_LONG); + if (offset_minus) + write_exp_elt_opcode (UNOP_NEG); + } - write_exp_elt_opcode (OP_REGISTER); - base_token.ptr = base; - base_token.length = len_base; - write_exp_string (base_token); - write_exp_elt_opcode (OP_REGISTER); + write_exp_elt_opcode (OP_REGISTER); + base_token.ptr = base; + base_token.length = len_base; + write_exp_string (base_token); + write_exp_elt_opcode (OP_REGISTER); - if (offset) - write_exp_elt_opcode (BINOP_ADD); + if (offset) + write_exp_elt_opcode (BINOP_ADD); - write_exp_elt_opcode (OP_REGISTER); - index_token.ptr = index; - index_token.length = len_index; - write_exp_string (index_token); - write_exp_elt_opcode (OP_REGISTER); + write_exp_elt_opcode (OP_REGISTER); + index_token.ptr = index; + index_token.length = len_index; + write_exp_string (index_token); + write_exp_elt_opcode (OP_REGISTER); - if (size) - { - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type - (builtin_type (gdbarch)->builtin_long); - write_exp_elt_longcst (size); - write_exp_elt_opcode (OP_LONG); - if (size_minus) - write_exp_elt_opcode (UNOP_NEG); - write_exp_elt_opcode (BINOP_MUL); - } + if (size) + { + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (builtin_type (gdbarch)->builtin_long); + write_exp_elt_longcst (size); + write_exp_elt_opcode (OP_LONG); + if (size_minus) + write_exp_elt_opcode (UNOP_NEG); + write_exp_elt_opcode (BINOP_MUL); + } - write_exp_elt_opcode (BINOP_ADD); + write_exp_elt_opcode (BINOP_ADD); - write_exp_elt_opcode (UNOP_CAST); - write_exp_elt_type (lookup_pointer_type (p->arg_type)); - write_exp_elt_opcode (UNOP_CAST); + write_exp_elt_opcode (UNOP_CAST); + write_exp_elt_type (lookup_pointer_type (p->arg_type)); + write_exp_elt_opcode (UNOP_CAST); - write_exp_elt_opcode (UNOP_IND); + write_exp_elt_opcode (UNOP_IND); - p->arg = s; + p->arg = s; - return 1; - } - break; - } + return 1; + } + + return 0; +} + +/* Implementation of `gdbarch_stap_parse_special_token', as defined in + gdbarch.h. */ + +int +i386_stap_parse_special_token (struct gdbarch *gdbarch, + struct stap_parse_info *p) +{ + /* In order to parse special tokens, we use a state-machine that go + through every known token and try to get a match. */ + enum + { + TRIPLET, + THREE_ARG_DISPLACEMENT, + DONE + } current_state; + + current_state = TRIPLET; + + /* The special tokens to be parsed here are: + + - `register base + (register index * size) + offset', as represented + in `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'. + + - Operands of the form `-8+3+1(%rbp)', which must be interpreted as + `*(-8 + 3 - 1 + (void *) $eax)'. */ + + while (current_state != DONE) + { + switch (current_state) + { + case TRIPLET: + if (i386_stap_parse_special_token_triplet (gdbarch, p)) + return 1; + break; + + case THREE_ARG_DISPLACEMENT: + if (i386_stap_parse_special_token_three_arg_disp (gdbarch, p)) + return 1; + break; } /* Advancing to the next state. */ -- 2.7.4