From c8c1c22feaaf76ddd437776a3cdeaedf4695916a Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 14 Feb 2011 11:23:33 +0000 Subject: [PATCH] gdb/ * value.h (value_available_contents_eq): Declare. * value.c (find_first_range_overlap): New function. (value_available_contents_eq): New function. * valprint.c (val_print_array_elements): Use value_available_contents_eq. * ada-valprint.c (val_print_packed_array_elements): Use value_available_contents_eq. * jv-valprint.c (java_value_print): Use value_available_contents_eq. --- gdb/ChangeLog | 12 +++++++ gdb/ada-valprint.c | 4 ++- gdb/jv-valprint.c | 7 ++-- gdb/valprint.c | 8 +++-- gdb/value.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/value.h | 25 +++++++++++++ 6 files changed, 151 insertions(+), 6 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4440c09..92a6d4e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,17 @@ 2011-02-14 Pedro Alves + * value.h (value_available_contents_eq): Declare. + * value.c (find_first_range_overlap): New function. + (value_available_contents_eq): New function. + * valprint.c (val_print_array_elements): Use + value_available_contents_eq. + * ada-valprint.c (val_print_packed_array_elements): Use + value_available_contents_eq. + * jv-valprint.c (java_value_print): Use + value_available_contents_eq. + +2011-02-14 Pedro Alves + * target.c (target_read_live_memory): New function. (memory_xfer_live_readonly_partial): New. (memory_xfer_partial): If reading from a traceframe, fallback to diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c index bc3ea26..9381ecc 100644 --- a/gdb/ada-valprint.c +++ b/gdb/ada-valprint.c @@ -200,7 +200,9 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, (i * bitsize) / HOST_CHAR_BIT, (i * bitsize) % HOST_CHAR_BIT, bitsize, elttype); - if (memcmp (value_contents (v0), value_contents (v1), eltlen) != 0) + if (!value_available_contents_eq (v0, value_embedded_offset (v0), + v1, value_embedded_offset (v1), + eltlen)) break; } diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c index 0e5b97f..bed9b2f 100644 --- a/gdb/jv-valprint.c +++ b/gdb/jv-valprint.c @@ -179,8 +179,11 @@ java_value_print (struct value *val, struct ui_file *stream, set_value_lazy (next_v, 1); set_value_offset (next_v, value_offset (next_v) + TYPE_LENGTH (el_type)); - if (memcmp (value_contents (v), value_contents (next_v), - TYPE_LENGTH (el_type)) != 0) + value_fetch_lazy (next_v); + if (!(value_available_contents_eq + (v, value_embedded_offset (v), + next_v, value_embedded_offset (next_v), + TYPE_LENGTH (el_type)))) break; } diff --git a/gdb/valprint.c b/gdb/valprint.c index 64a4b05..fd573c2 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -1242,9 +1242,11 @@ val_print_array_elements (struct type *type, rep1 = i + 1; reps = 1; while (rep1 < len - && memcmp (valaddr + embedded_offset + i * eltlen, - valaddr + embedded_offset + rep1 * eltlen, - eltlen) == 0) + && value_available_contents_eq (val, + embedded_offset + i * eltlen, + val, + embedded_offset + rep1 * eltlen, + eltlen)) { ++reps; ++rep1; diff --git a/gdb/value.c b/gdb/value.c index 58190ea..a8be549 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -496,6 +496,107 @@ mark_value_bytes_unavailable (struct value *value, int offset, int length) } } +/* Find the first range in RANGES that overlaps the range defined by + OFFSET and LENGTH, starting at element POS in the RANGES vector, + Returns the index into RANGES where such overlapping range was + found, or -1 if none was found. */ + +static int +find_first_range_overlap (VEC(range_s) *ranges, int pos, + int offset, int length) +{ + range_s *r; + int i; + + for (i = pos; VEC_iterate (range_s, ranges, i, r); i++) + if (ranges_overlap (r->offset, r->length, offset, length)) + return i; + + return -1; +} + +int +value_available_contents_eq (const struct value *val1, int offset1, + const struct value *val2, int offset2, + int length) +{ + int org_len = length; + int org_offset1 = offset1; + int org_offset2 = offset2; + int idx1 = 0, idx2 = 0; + int prev_avail; + + /* This routine is used by printing routines, where we should + already have read the value. Note that we only know whether a + value chunk is available if we've tried to read it. */ + gdb_assert (!val1->lazy && !val2->lazy); + + /* The offset from either ORG_OFFSET1 or ORG_OFFSET2 where the + available contents we haven't compared yet start. */ + prev_avail = 0; + + while (length > 0) + { + range_s *r1, *r2; + ULONGEST l1, h1; + ULONGEST l2, h2; + + idx1 = find_first_range_overlap (val1->unavailable, idx1, + offset1, length); + idx2 = find_first_range_overlap (val2->unavailable, idx2, + offset2, length); + + /* The usual case is for both values to be completely available. */ + if (idx1 == -1 && idx2 == -1) + return (memcmp (val1->contents + org_offset1 + prev_avail, + val2->contents + org_offset2 + prev_avail, + org_len - prev_avail) == 0); + /* The contents only match equal if the available set matches as + well. */ + else if (idx1 == -1 || idx2 == -1) + return 0; + + gdb_assert (idx1 != -1 && idx2 != -1); + + r1 = VEC_index (range_s, val1->unavailable, idx1); + r2 = VEC_index (range_s, val2->unavailable, idx2); + + /* Get the unavailable windows intersected by the incoming + ranges. The first and last ranges that overlap the argument + range may be wider than said incoming arguments ranges. */ + l1 = max (offset1, r1->offset); + h1 = min (offset1 + length, r1->offset + r1->length); + + l2 = max (offset2, r2->offset); + h2 = min (offset2 + length, r2->offset + r2->length); + + /* Make them relative to the respective start offsets, so we can + compare them for equality. */ + l1 -= offset1; + h1 -= offset1; + + l2 -= offset2; + h2 -= offset2; + + /* Different availability, no match. */ + if (l1 != l2 || h1 != h2) + return 0; + + /* Compare the _available_ contents. */ + if (memcmp (val1->contents + org_offset1 + prev_avail, + val2->contents + org_offset2 + prev_avail, + l2 - prev_avail) != 0) + return 0; + + prev_avail += h1; + length -= h1; + offset1 += h1; + offset2 += h1; + } + + return 1; +} + /* Prototypes for local functions. */ static void show_values (char *, int); diff --git a/gdb/value.h b/gdb/value.h index d2eb091..0feb92f 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -374,6 +374,31 @@ extern int value_bytes_available (const struct value *value, extern void mark_value_bytes_unavailable (struct value *value, int offset, int length); +/* Compare LENGTH bytes of VAL1's contents starting at OFFSET1 with + LENGTH bytes of VAL2's contents starting at OFFSET2. Returns true + iff the set of available contents match. Unavailable contents + compare equal with unavailable contents, and different with any + available byte. For example, if 'x's represent an unavailable + byte, and 'V' and 'Z' represent different available bytes, in a + value with length 16: + + offset: 0 4 8 12 16 + contents: xxxxVVVVxxxxVVZZ + + then: + + value_available_contents_eq(val, 0, val, 8, 6) => 1 + value_available_contents_eq(val, 0, val, 4, 4) => 1 + value_available_contents_eq(val, 0, val, 8, 8) => 0 + value_available_contents_eq(val, 4, val, 12, 2) => 1 + value_available_contents_eq(val, 4, val, 12, 4) => 0 + value_available_contents_eq(val, 3, val, 4, 4) => 0 +*/ + +extern int value_available_contents_eq (const struct value *val1, int offset1, + const struct value *val2, int offset2, + int length); + /* Read LENGTH bytes of memory starting at MEMADDR into BUFFER, which is (or will be copied to) VAL's contents buffer offset by EMBEDDED_OFFSET (that is, to &VAL->contents[EMBEDDED_OFFSET]). -- 2.7.4