📄 valprint.c
字号:
/* Bitfields require special handling, especially due to byte order problems. */ v = value_from_longest (TYPE_FIELD_TYPE (type, i), unpack_field_as_long (type, valaddr, i)); val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, stream, format, 0, recurse + 1, pretty); } else { val_print (TYPE_FIELD_TYPE (type, i), valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0, stream, format, 0, recurse + 1, pretty); } } if (pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); } } fprintf_filtered (stream, "}");}/* Special val_print routine to avoid printing multiple copies of virtual baseclasses. */static voidcplus_val_print (type, valaddr, stream, format, recurse, pretty, dont_print) struct type *type; char *valaddr; FILE *stream; int format; int recurse; enum val_prettyprint pretty; struct type **dont_print;{ struct obstack tmp_obstack; struct type **last_dont_print = (struct type **)obstack_next_free (&dont_print_obstack); int i, n_baseclasses = TYPE_N_BASECLASSES (type); if (dont_print == 0) { /* If we're at top level, carve out a completely fresh chunk of the obstack and use that until this particular invocation returns. */ tmp_obstack = dont_print_obstack; /* Bump up the high-water mark. Now alpha is omega. */ obstack_finish (&dont_print_obstack); } for (i = 0; i < n_baseclasses; i++) { char *baddr; int err; if (BASETYPE_VIA_VIRTUAL (type, i)) { struct type **first_dont_print = (struct type **)obstack_base (&dont_print_obstack); int j = (struct type **)obstack_next_free (&dont_print_obstack) - first_dont_print; while (--j >= 0) if (TYPE_BASECLASS (type, i) == first_dont_print[j]) goto flush_it; obstack_ptr_grow (&dont_print_obstack, TYPE_BASECLASS (type, i)); } /* Fix to use baseclass_offset instead. FIXME */ baddr = baseclass_addr (type, i, valaddr, 0, &err); if (err == 0 && baddr == 0) error ("could not find virtual baseclass `%s'\n", type_name_no_tag (TYPE_BASECLASS (type, i))); if (pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); } fputs_filtered ("<", stream); fputs_filtered (type_name_no_tag (TYPE_BASECLASS (type, i)), stream); fputs_filtered ("> = ", stream); if (err != 0) fprintf_filtered (stream, "<invalid address 0x%x>", baddr); else val_print_fields (TYPE_BASECLASS (type, i), baddr, stream, format, recurse, pretty, (struct type **)obstack_base (&dont_print_obstack)); fputs_filtered (", ", stream); flush_it: ; } if (dont_print == 0) { /* Free the space used to deal with the printing of this type from top level. */ obstack_free (&dont_print_obstack, last_dont_print); /* Reset watermark so that we can continue protecting ourselves from whatever we were protecting ourselves. */ dont_print_obstack = tmp_obstack; }}static voidprint_class_member (valaddr, domain, stream, prefix) char *valaddr; struct type *domain; FILE *stream; char *prefix;{ /* VAL is a byte offset into the structure type DOMAIN. Find the name of the field for that offset and print it. */ int extra = 0; int bits = 0; register unsigned int i; unsigned len = TYPE_NFIELDS (domain); /* @@ Make VAL into bit offset */ LONGEST val = unpack_long (builtin_type_int, valaddr) << 3; for (i = TYPE_N_BASECLASSES (domain); i < len; i++) { int bitpos = TYPE_FIELD_BITPOS (domain, i); QUIT; if (val == bitpos) break; if (val < bitpos && i != 0) { /* Somehow pointing into a field. */ i -= 1; extra = (val - TYPE_FIELD_BITPOS (domain, i)); if (extra & 0x7) bits = 1; else extra >>= 3; break; } } if (i < len) { char *name; fprintf_filtered (stream, prefix); name = type_name_no_tag (domain); if (name) fputs_filtered (name, stream); else type_print_base (domain, stream, 0, 0); fprintf_filtered (stream, "::"); fputs_filtered (TYPE_FIELD_NAME (domain, i), stream); if (extra) fprintf_filtered (stream, " + %d bytes", extra); if (bits) fprintf_filtered (stream, " (offset in bits)"); } else fprintf_filtered (stream, "%d", val >> 3);}/* Print data of type TYPE located at VALADDR (within GDB), which came from the inferior at address ADDRESS, onto stdio stream STREAM according to FORMAT (a letter or 0 for natural format). The data at VALADDR is in target byte order. If the data are a string pointer, returns the number of sting characters printed. if DEREF_REF is nonzero, then dereference references, otherwise just print them like pointers. The PRETTY parameter controls prettyprinting. */intval_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; CORE_ADDR address; FILE *stream; int format; int deref_ref; int recurse; enum val_prettyprint pretty;{ register unsigned int i; unsigned len; struct type *elttype; unsigned eltlen; LONGEST val; unsigned char c; if (pretty == Val_pretty_default) { pretty = prettyprint ? Val_prettyprint : Val_no_prettyprint; } QUIT; check_stub_type (type); if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) { fprintf_filtered (stream, "<unknown struct>"); fflush (stream); return 0; } switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) { elttype = TYPE_TARGET_TYPE (type); eltlen = TYPE_LENGTH (elttype); len = TYPE_LENGTH (type) / eltlen; if (arrayprint) print_spaces_filtered (2 + 2 * recurse, stream); fprintf_filtered (stream, "{"); /* For an array of chars, print with string syntax. */ if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT && (format == 0 || format == 's') ) print_string (stream, valaddr, len, 0); else { unsigned int things_printed = 0; /* If this is a virtual function table, print the 0th entry specially, and the rest of the members normally. */ if (is_vtbl_ptr_type (elttype)) { fprintf_filtered (stream, "%d vtable entries", len-1); i = 1; } else i = 0; for (; i < len && things_printed < print_max; i++) { /* Position of the array element we are examining to see whether it is repeated. */ unsigned int rep1; /* Number of repetitions we have detected so far. */ unsigned int reps; if (i != 0) if (arrayprint) { fprintf_filtered (stream, ",\n"); print_spaces_filtered (2 + 2 * recurse, stream); } else fprintf_filtered (stream, ", "); wrap_here (n_spaces (2 + 2 * recurse)); rep1 = i + 1; reps = 1; while (rep1 < len && !memcmp (valaddr + i * eltlen, valaddr + rep1 * eltlen, eltlen)) { ++reps; ++rep1; } if (reps > REPEAT_COUNT_THRESHOLD) { val_print (elttype, valaddr + i * eltlen, 0, stream, format, deref_ref, recurse + 1, pretty); fprintf_filtered (stream, " <repeats %u times>", reps); i = rep1 - 1; things_printed += REPEAT_COUNT_THRESHOLD; } else { val_print (elttype, valaddr + i * eltlen, 0, stream, format, deref_ref, recurse + 1, pretty); things_printed++; } } if (i < len) fprintf_filtered (stream, "..."); } fprintf_filtered (stream, "}"); break; } /* Array of unspecified length: treat like pointer to first elt. */ valaddr = (char *) &address; case TYPE_CODE_PTR: if (format && format != 's') { print_scalar_formatted (valaddr, type, format, 0, stream); break; } if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD) { struct type *domain, *ttype; struct fn_field *f; int j, len2; char *kind = ""; CORE_ADDR addr; ttype = TYPE_TARGET_TYPE (type); if (ttype == 0 || (domain = TYPE_DOMAIN_TYPE(ttype)) == 0) { printf("<bug workaround: can't print ptr to method>\n"); break; } addr = unpack_pointer (lookup_pointer_type (builtin_type_void), valaddr); if (METHOD_PTR_IS_VIRTUAL(addr)) { int offset = METHOD_PTR_TO_VOFFSET(addr); len = TYPE_NFN_FIELDS (domain); for (i = 0; i < len; i++) { f = TYPE_FN_FIELDLIST1 (domain, i); len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); for (j = 0; j < len2; j++) { QUIT; if (TYPE_FN_FIELD_VOFFSET (f, j) == offset) { kind = "virtual "; goto common; } } } } else { struct symbol *sym = find_pc_function (addr); if (sym == 0) error ("invalid pointer to member function"); len = TYPE_NFN_FIELDS (domain); for (i = 0; i < len; i++) { f = TYPE_FN_FIELDLIST1 (domain, i); len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); for (j = 0; j < len2; j++) { QUIT; if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) goto common; } } } common: if (i < len) { fprintf_filtered (stream, "&"); type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); fprintf (stream, kind); if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER) type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream); else type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "", TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream); break; } fprintf_filtered (stream, "("); type_print (type, "", stream, -1); fprintf_filtered (stream, ") %d", (int) addr >> 3); } else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) { print_class_member (valaddr, TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)), stream, "&"); } else { CORE_ADDR addr = unpack_pointer (type, valaddr); elttype = TYPE_TARGET_TYPE (type); if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) { /* Try to print what function it points to. */ print_address_demangle (addr, stream, demangle); /* Return value is irrelevant except for string pointers. */ return 0; } if (addressprint && format != 's') fprintf_filtered (stream, "0x%x", addr); /* For a pointer to char or unsigned char, also print the string pointed to, unless pointer is null. */ i = 0; /* Number of characters printed. */ if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT && (format == 0 || format == 's') && addr != 0 /* If print_max is UINT_MAX, the alloca below will fail. In that case don't try to print the string. */ && print_max < UINT_MAX) { int first_addr_err = 0; int errcode = 0; /* Get first character. */ errcode = target_read_memory (addr, (char *)&c, 1); if (errcode != 0) { /* First address out of bounds. */ first_addr_err = 1; } else { /* A real string. */ char *string = (char *) alloca (print_max); /* If the loop ends by us hitting print_max characters, we need to have elipses at the end. */ int force_ellipses = 1; /* This loop always fetches print_max characters, even though print_string might want to print more or fewer (with repeated characters). This is so that we don't spend forever fetching if we print a long string consisting of the same character repeated. Also so we can do it all in one memory operation, which is faster. However, this will be slower if print_max is set high, e.g. if you set print_max to 1000, not only will it take a long time to fetch short strings, but if you are near the end of the address space, it might not work. */ QUIT; errcode = target_read_memory (addr, string, print_max); if (errcode != 0) { /* Try reading just one character. If that succeeds, assume we hit the end of the address space, but the initial part of the string is probably safe. */ char x[1]; errcode = target_read_memory (addr, x, 1); } if (errcode != 0) force_ellipses = 0; else for (i = 0; i < print_max; i++) if (string[i] == '\0') { force_ellipses = 0; break; } QUIT; if (addressprint) fputs_filtered (" ", stream); print_string (stream, string, i, force_ellipses); } if (errcode != 0) { if (errcode == EIO) { fprintf_filtered (stream, (" <Address 0x%x out of bounds>" + first_addr_err), addr + i); } else { error ("Error reading memory address 0x%x: %s.", addr + i, safe_strerror (errcode)); } } fflush (stream); } else /* print vtbl's nicely */ if (is_vtbl_member(type)) { CORE_ADDR vt_address = unpack_pointer (type, valaddr); struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (vt_address); if ((msymbol != NULL) && (vt_address == msymbol -> address)) { fputs_filtered (" <", stream); fputs_demangled (msymbol -> name, stream, DMGL_ANSI | DMGL_PARAMS); fputs_filtered (">", stream); } if (vtblprint) { value vt_val; vt_val = value_at (TYPE_TARGET_TYPE (type), vt_address); val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), VALUE_ADDRESS (vt_val), stream, format, deref_ref, recurse + 1, pretty); if (pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 + 2 * recurse, stream); } } } /* Return number of characters printed, plus one for the terminating null if we have "reached the end". */ return i + (print_max && i != print_max); } break; case TYPE_CODE_MEMBER: error ("not implemented: member type in val_print"); break; case TYPE_CODE_REF: { CORE_ADDR addr = unpack_long (builtin_type_int, valaddr); if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) { print_class_member (valaddr, TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)), stream, ""); break; } if (addressprint) { fprintf_filtered (stream, "@0x%lx", addr); if (deref_ref) fputs_filtered (": ", stream); } /* De-reference the reference. */ if (deref_ref) { if (target_read_memory(addr, (char *)&c, 1)) { fprintf_filtered (stream, "<Address out of bounds>"); break; } if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) { value deref_val = value_at (TYPE_TARGET_TYPE (type), addr); val_print (VALUE_TYPE (deref_val), VALUE_CONTENTS (deref_val), VALUE_ADDRESS (deref_val), stream, format, deref_ref, recurse + 1, pretty); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -