From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1256) id B79EF3858D32; Fri, 10 Feb 2023 23:50:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B79EF3858D32 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1676073024; bh=byYrA0STpTVUqD+HehcqjFn6fbtLPTKbdvt3oSzEWgw=; h=From:To:Subject:Date:From; b=N8qMpiklNI5ZuuEbjO9iCHIXW7cQ2Fnufh0m2LyOml6JenHkQxuhSbCw2UE1Z9lPz xHlata5xZJpF1pub/IsrvYwOmgdTHssqOa+ZJbVTKG2osPQKncgpfIq29ZZHJRsSDA A7ALFiBaRhDCvHmgATBxD3azCrFXzVIJ1j/APO6s= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Maciej W. Rozycki To: gdb-cvs@sourceware.org Subject: [binutils-gdb] GDB: Fix the mess with value byte/bit range types X-Act-Checkin: binutils-gdb X-Git-Author: Maciej W. Rozycki X-Git-Refname: refs/heads/master X-Git-Oldrev: bae19789c0a2d4e88b5b441acebe4d9e1522cd67 X-Git-Newrev: 4f82620cc9fd1ef630b6b732a9d939d4e529a07f Message-Id: <20230210235024.B79EF3858D32@sourceware.org> Date: Fri, 10 Feb 2023 23:50:24 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D4f82620cc9fd= 1ef630b6b732a9d939d4e529a07f commit 4f82620cc9fd1ef630b6b732a9d939d4e529a07f Author: Maciej W. Rozycki Date: Fri Feb 10 23:49:19 2023 +0000 GDB: Fix the mess with value byte/bit range types =20 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.: =20 (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) =20 Previously such accesses would be let through with unpredictable results produced. Diff: --- 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; =20 /* Length of the range. */ - LONGEST length; + ULONGEST length; =20 /* 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. */ =20 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; =20 l =3D std::max (offset1, offset2); h =3D std::min (offset1 + len1, offset2 + len2); @@ -112,7 +112,7 @@ ranges_overlap (LONGEST offset1, LONGEST len1, =20 static int ranges_contain (const std::vector &ranges, LONGEST offset, - LONGEST length) + ULONGEST length) { range what; =20 @@ -380,7 +380,8 @@ get_value_arch (const struct value *value) } =20 int -value_bits_available (const struct value *value, LONGEST offset, LONGEST l= ength) +value_bits_available (const struct value *value, + LONGEST offset, ULONGEST length) { gdb_assert (!value->lazy); =20 @@ -389,8 +390,16 @@ value_bits_available (const struct value *value, LONGE= ST offset, LONGEST length) =20 int value_bytes_available (const struct value *value, - LONGEST offset, LONGEST length) + LONGEST offset, ULONGEST length) { + ULONGEST sign =3D (1ULL << (sizeof (ULONGEST) * 8 - 1)) / TARGET_CHAR_BI= T; + ULONGEST mask =3D (sign << 1) - 1; + + if (offset !=3D ((offset & mask) ^ sign) - sign + || length !=3D ((length & mask) ^ sign) - sign + || (length > 0 && (~offset & (offset + length - 1) & sign) !=3D 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) =20 static void insert_into_bit_range_vector (std::vector *vectorp, - LONGEST offset, LONGEST length) + LONGEST offset, ULONGEST length) { range newr; =20 @@ -558,8 +567,8 @@ insert_into_bit_range_vector (std::vector *vecto= rp, if (ranges_overlap (bef.offset, bef.length, offset, length)) { /* #1 */ - ULONGEST l =3D std::min (bef.offset, offset); - ULONGEST h =3D std::max (bef.offset + bef.length, offset + length); + LONGEST l =3D std::min (bef.offset, offset); + LONGEST h =3D std::max (bef.offset + bef.length, offset + length); =20 bef.offset =3D l; bef.length =3D h - l; @@ -600,7 +609,7 @@ insert_into_bit_range_vector (std::vector *vecto= rp, struct range &r =3D *i; if (r.offset <=3D t.offset + t.length) { - ULONGEST l, h; + LONGEST l, h; =20 l =3D std::min (t.offset, r.offset); h =3D std::max (t.offset + t.length, r.offset + r.length); @@ -626,14 +635,14 @@ insert_into_bit_range_vector (std::vector *vec= torp, =20 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); } =20 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 =3D 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; =20 l =3D std::max (r.offset, (LONGEST) src_bit_offset); - h =3D std::min (r.offset + r.length, + h =3D std::min ((LONGEST) (r.offset + r.length), (LONGEST) src_bit_offset + bit_length); =20 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 v= alue *value, byte is unavailable. */ =20 extern int value_bytes_available (const struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); =20 /* 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 *v= alue, bit is unavailable. */ =20 extern int value_bits_available (const struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); =20 /* 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. */ =20 extern void mark_value_bytes_unavailable (struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); =20 /* Mark VALUE's content bits starting at OFFSET and extending for LENGTH bits as unavailable. */ =20 extern void mark_value_bits_unavailable (struct value *value, - LONGEST offset, LONGEST length); + LONGEST offset, ULONGEST length); =20 /* Compare LENGTH bytes of VAL1's contents starting at OFFSET1 with LENGTH bytes of VAL2's contents starting at OFFSET2.