static int r_print_format_struct(RPrint* p, ut64 seek, const ut8* b, int len, char *name, int slide, int mode, const char *setval, char *field) { const char *fmt; char namefmt[8]; if ((slide % STRUCTPTR) > NESTDEPTH || (slide%STRUCTFLAG)/STRUCTPTR > NESTDEPTH) { eprintf ("Too much nested struct, recursion too deep...\n"); return 0; } fmt = r_strht_get (p->formats, name); if (!fmt || !*fmt) { eprintf ("Undefined struct '%s'.\n", name); return 0; } if (MUSTSEE && !SEEVALUE) { snprintf (namefmt, sizeof (namefmt), "%%%ds", 10+6*slide%STRUCTPTR); if (fmt[0] == '0') p->cb_printf (namefmt, "union"); else p->cb_printf (namefmt, "struct"); p->cb_printf ("<%s>\n", name); } r_print_format (p, seek, b, len, fmt, mode, setval, field); return r_print_format_struct_size(fmt, p, mode); }
// XXX: this is very incomplete. must be updated to handle all format chars int r_print_format_struct_size(const char *f, RPrint *p, int mode) { char *o = strdup(f); char *end = strchr (o, ' '), *args, *fmt = o; int size = 0, tabsize=0, i, idx=0, biggest = 0; if (!end && !(end = strchr (o, '\0'))) return -1; if (*end) { *end = 0; args = strdup (end+1); } else { args = strdup (""); } if (fmt[0] == '0') { mode |= R_PRINT_UNIONMODE; fmt++; } else { mode &= ~R_PRINT_UNIONMODE; } r_str_word_set0 (args); for (i=0; i<strlen (fmt); i++) { if (fmt[i] == '[') { char *end = strchr (fmt+i,']'); if (end == NULL) { eprintf ("No end bracket.\n"); continue; } *end = '\0'; tabsize = r_num_math (NULL, fmt+i+1); *end = ']'; while (fmt[i++]!=']'); } else { tabsize = 1; } switch (fmt[i]) { case 'c': case 'b': case '.': size+=tabsize*1; break; case 'w': size += tabsize*2; break; case 'd': case 'o': case 'i': case 'x': case 'f': case 's': case 't': case ':': size += tabsize*4; break; case 'S': case 'q': size += tabsize*8; break; case 'z': case 'Z': size += tabsize; break; case '*': size += tabsize*4; i++; break; case 'B': case 'E': switch (tabsize) { case 1: size+=1; break; case 2: size+=2; break; case 4: size+=4; break; default: break; } break; case '?': { const char *format = NULL; char *endname = NULL, *structname = NULL; structname = strdup(r_str_word_get0 (args, idx)); if (*structname == '(') { endname = strchr (structname, ')'); } else { eprintf ("Struct name missing (%s)\n", structname); free(structname); break; } if (endname) *endname = '\0'; format = r_strht_get (p->formats, structname+1); free (structname); size += tabsize * r_print_format_struct_size (format, p, mode); } break; // TODO continue list default: break; } idx++; if (mode & R_PRINT_UNIONMODE) { if (size > biggest) biggest = size; size = 0; } } free (o); free (args); if (mode & R_PRINT_UNIONMODE) return biggest; else return size; }
static int cmd_meta_hsdmf(RCore *core, const char *input) { int n, type = input[0]; char *t = 0, *p, name[256]; int repeat = 1; ut64 addr_end = 0LL, addr = core->offset; switch (input[1]) { case '?': eprintf ("See C?\n"); break; case '-': switch (input[2]) { case '*': core->num->value = r_meta_del (core->anal, input[0], 0, UT64_MAX, NULL); break; case ' ': addr = r_num_math (core->num, input+3); /* fallthrough */ default: core->num->value = r_meta_del (core->anal, input[0], addr, 1, NULL); break; } break; case '*': r_meta_list (core->anal, input[0], 1); break; case '!': { char *out, *comment = r_meta_get_string ( core->anal, R_META_TYPE_COMMENT, addr); out = r_core_editor (core, NULL, comment); if (out) { //r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out); r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr); //r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL); r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, out); free (out); } free (comment); } break; case ' ': case '\0': if (type != 'z' && input[1] == '*') { r_meta_list (core->anal, type, 0); break; } if (type == 'z') { type = 's'; } if (strlen (input) > 2) { char *rep = strchr (input + 2, '['); if (!rep) rep = strchr (input + 2, ' '); if (rep) { repeat = r_num_get (core->num, rep + 1); } } int repcnt = 0; if (repeat < 1) { repeat = 1; } while (repcnt < repeat) { t = strdup (r_str_chop_ro (input + 1)); p = NULL; n = 0; strncpy (name, t, sizeof (name) - 1); if (type != 'C') { n = r_num_math (core->num, t); if (type == 'f') { // "Cf" p = strchr (t, ' '); if (p) { if (n < 1) { n = r_print_format_struct_size (p + 1, core->print, 0); if (n < 1) { eprintf ("Cannot resolve struct size\n"); n = 32; // } } int r = r_print_format (core->print, addr, core->block, n, p + 1, 0, NULL, NULL); if (r < 0) { n = -1; } } else { eprintf ("Usage: Cf [size] [pf-format-string]\n"); break; } } else if (type == 's') { //Cs char tmp[256] = {0}; int i, j, name_len = 0; (void)r_core_read_at (core, addr, (ut8*)tmp, sizeof (tmp) - 1); name_len = r_str_nlen_w (tmp, sizeof (tmp)); //handle wide strings for (i = 0, j = 0; i < sizeof (name); i++, j++) { name[i] = tmp[j]; if (!tmp[j]) { break; } if (!tmp[j + 1]) { if (j + 3 < sizeof (tmp)) { if (tmp[j + 3]) { break; } } j++; } } name[sizeof (name) - 1] = '\0'; if (n == 0) { n = name_len + 1; } else { if (n > 0 && n < name_len) { name[n] = 0; } } } if (n < 1) { /* invalid length, do not insert into db */ return false; } if (!*t || n > 0) { RFlagItem *fi; p = strchr (t, ' '); if (p) { *p = '\0'; strncpy (name, p + 1, sizeof (name)-1); } else { if (type != 's') { fi = r_flag_get_i (core->flags, addr); if (fi) strncpy (name, fi->name, sizeof (name)-1); } } } } if (!n) { n++; } addr_end = addr + n; r_meta_add (core->anal, type, addr, addr_end, name); free (t); repcnt ++; addr = addr_end; } //r_meta_cleanup (core->anal->meta, 0LL, UT64_MAX); break; default: eprintf ("Missing space after CC\n"); break; } return true; }