From 4f82620cc9fd1ef630b6b732a9d939d4e529a07f Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 10 Feb 2023 23:49:19 +0000 Subject: [PATCH] GDB: Fix the mess with value byte/bit range types Consistently use the LONGEST and ULONGEST types for value byte/bit offsets and lengths respectively, avoiding silent truncation for ranges exceeding the 32-bit span, which may cause incorrect matching. Also report a conversion overflow on byte ranges that cannot be expressed in terms of bits with these data types, e.g.: (gdb) print one_hundred[1LL << 58] Integer overflow in data location calculation (gdb) print one_hundred[(-1LL << 58) - 1] Integer overflow in data location calculation (gdb) Previously such accesses would be let through with unpredictable results produced. --- gdb/value.c | 43 ++++++++++++++++++++++++++----------------- gdb/value.h | 8 ++++---- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/gdb/value.c b/gdb/value.c index 09e10b9a8b1..57625b005ac 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -74,7 +74,7 @@ struct range LONGEST offset; /* Length of the range. */ - LONGEST length; + ULONGEST length; /* Returns true if THIS is strictly less than OTHER, useful for searching. We keep ranges sorted by offset and coalesce @@ -97,10 +97,10 @@ struct range [offset2, offset2+len2) overlap. */ static int -ranges_overlap (LONGEST offset1, LONGEST len1, - LONGEST offset2, LONGEST len2) +ranges_overlap (LONGEST offset1, ULONGEST len1, + LONGEST offset2, ULONGEST len2) { - ULONGEST h, l; + LONGEST h, l; l = std::max (offset1, offset2); h = std::min (offset1 + len1, offset2 + len2); @@ -112,7 +112,7 @@ ranges_overlap (LONGEST offset1, LONGEST len1, static int ranges_contain (const std::vector &ranges, LONGEST offset, - LONGEST length) + ULONGEST length) { range what; @@ -380,7 +380,8 @@ get_value_arch (const struct value *value) } int -value_bits_available (const struct value *value, LONGEST offset, LONGEST length) +value_bits_available (const struct value *value, + LONGEST offset, ULONGEST length) { gdb_assert (!value->lazy); @@ -389,8 +390,16 @@ value_bits_available (const struct value *value, LONGEST offset, LONGEST length) int value_bytes_available (const struct value *value, - LONGEST offset, LONGEST length) + LONGEST offset, ULONGEST length) { + ULONGEST sign = (1ULL << (sizeof (ULONGEST) * 8 - 1)) / TARGET_CHAR_BIT; + ULONGEST mask = (sign << 1) - 1; + + if (offset != ((offset & mask) ^ sign) - sign + || length != ((length & mask) ^ sign) - sign + || (length > 0 && (~offset & (offset + length - 1) & sign) != 0)) + error (_("Integer overflow in data location calculation")); + return value_bits_available (value, offset * TARGET_CHAR_BIT, length * TARGET_CHAR_BIT); @@ -460,7 +469,7 @@ value_entirely_optimized_out (struct value *value) static void insert_into_bit_range_vector (std::vector *vectorp, - LONGEST offset, LONGEST length) + LONGEST offset, ULONGEST length) { range newr; @@ -558,8 +567,8 @@ insert_into_bit_range_vector (std::vector *vectorp, if (ranges_overlap (bef.offset, bef.length, offset, length)) { /* #1 */ - ULONGEST l = std::min (bef.offset, offset); - ULONGEST h = std::max (bef.offset + bef.length, offset + length); + LONGEST l = std::min (bef.offset, offset); + LONGEST h = std::max (bef.offset + bef.length, offset + length); bef.offset = l; bef.length = h - l; @@ -600,7 +609,7 @@ insert_into_bit_range_vector (std::vector *vectorp, struct range &r = *i; if (r.offset <= t.offset + t.length) { - ULONGEST l, h; + LONGEST l, h; l = std::min (t.offset, r.offset); h = std::max (t.offset + t.length, r.offset + r.length); @@ -626,14 +635,14 @@ insert_into_bit_range_vector (std::vector *vectorp, void mark_value_bits_unavailable (struct value *value, - LONGEST offset, LONGEST length) + LONGEST offset, ULONGEST length) { insert_into_bit_range_vector (&value->unavailable, offset, length); } void mark_value_bytes_unavailable (struct value *value, - LONGEST offset, LONGEST length) + LONGEST offset, ULONGEST length) { mark_value_bits_unavailable (value, offset * TARGET_CHAR_BIT, @@ -786,7 +795,7 @@ static int find_first_range_overlap_and_match (struct ranges_and_idx *rp1, struct ranges_and_idx *rp2, LONGEST offset1, LONGEST offset2, - LONGEST length, ULONGEST *l, ULONGEST *h) + ULONGEST length, ULONGEST *l, ULONGEST *h) { rp1->idx = find_first_range_overlap (rp1->ranges, rp1->idx, offset1, length); @@ -1306,14 +1315,14 @@ value_contents_all (struct value *value) static void ranges_copy_adjusted (std::vector *dst_range, int dst_bit_offset, const std::vector &src_range, int src_bit_offset, - int bit_length) + unsigned int bit_length) { for (const range &r : src_range) { - ULONGEST h, l; + LONGEST h, l; l = std::max (r.offset, (LONGEST) src_bit_offset); - h = std::min (r.offset + r.length, + h = std::min ((LONGEST) (r.offset + r.length), (LONGEST) src_bit_offset + bit_length); if (l < h) diff --git a/gdb/value.h b/gdb/value.h index f022510ded1..80f92597d07 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -505,7 +505,7 @@ extern int value_bits_synthetic_pointer (const struct value *value, byte is unavailable. */ extern int value_bytes_available (const struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); /* Given a value, determine whether the contents bits starting at OFFSET and extending for LENGTH bits are available. This returns @@ -513,7 +513,7 @@ extern int value_bytes_available (const struct value *value, bit is unavailable. */ extern int value_bits_available (const struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); /* Like value_bytes_available, but return false if any byte in the whole object is unavailable. */ @@ -527,13 +527,13 @@ extern int value_entirely_unavailable (struct value *value); LENGTH bytes as unavailable. */ extern void mark_value_bytes_unavailable (struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); /* Mark VALUE's content bits starting at OFFSET and extending for LENGTH bits as unavailable. */ extern void mark_value_bits_unavailable (struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); /* Compare LENGTH bytes of VAL1's contents starting at OFFSET1 with LENGTH bytes of VAL2's contents starting at OFFSET2. -- 2.30.2