From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7209 invoked by alias); 7 Feb 2011 14:28:10 -0000 Received: (qmail 6816 invoked by uid 22791); 7 Feb 2011 14:28:08 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 07 Feb 2011 14:28:01 +0000 Received: (qmail 24235 invoked from network); 7 Feb 2011 14:27:59 -0000 Received: from unknown (HELO scottsdale.localnet) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 7 Feb 2011 14:27:59 -0000 To: gdb-patches@sourceware.org Subject: [unavailable values part 1, 01/17] base support for unavailable value contents From: Pedro Alves Date: Mon, 07 Feb 2011 14:28:00 -0000 MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201102071427.55970.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-02/txt/msg00132.txt.bz2 This adds the base support for marking chunks of a given value's contents as unavailable. It then makes it so that it is an error to get at the contents of such values with value_contents() or value_contents_all(), similarly to how it is also an error to do the same to optimized out values. This in turn automaticaly makes it an error to use unavailable values in expression evaluation. Trying to print formatted or unformatted scalars (even if they're part of a compound) is also caught already by this patch, where we now print in place of "0" or some other garbage. This was made simple and centralized since the introduction of val_print_scalar_formatted in (yay for pieces falling in together!). Python pretty-printing does not yet know what to do to unavailable values, so this disables it. Does not mean someone can't add it later. Note that nothing is actually marking chunks of a value's contents as unavailable yet in this patch, so it's not testable yet. We give preference to printing rather than , since if a value had been optimized out at compile time, it can never be collected at run-time. -- Pedro Alves 2011-02-07 Pedro Alves Base support for value contents. gdb/ * value.h (value_bytes_available): Declare. (mark_value_bytes_unavailable): Declare. * value.c (struct range): New struct. (range_s): New typedef. (ranges_overlap): New function. (ranges_contain_p): New function. (ranges_copy): New function. (struct value) : New field. (value_bytes_available): New function. (mark_value_bytes_unavailable): New function. (require_not_optimized_out): Constify parameter. (require_available): New function. (value_contents_all, value_contents): Require all bytes be available. (value_free): Free `unavailable'. (value_copy): Copy `unavailable'. * valprint.h (val_print_unavailable): Declare. * valprint.c (valprint_check_validity): Rename `offset' parameter to `embedded_offset'. If printing a scalar, check whether the value chunk is available. (val_print_unavailable): New. (val_print_scalar_formatted): Check whether the value is available. * python/py-prettyprint.c (apply_val_pretty_printer): Refuse pretty-printing unavailable values. --- gdb/python/py-prettyprint.c | 5 + gdb/valprint.c | 22 +++++- gdb/valprint.h | 2 gdb/value.c | 156 +++++++++++++++++++++++++++++++++++++++++++- gdb/value.h | 14 +++ 5 files changed, 194 insertions(+), 5 deletions(-) Index: src/gdb/value.h =================================================================== --- src.orig/gdb/value.h 2011-02-07 11:31:36.446706000 +0000 +++ src/gdb/value.h 2011-02-07 11:31:37.986706000 +0000 @@ -360,6 +360,20 @@ extern int value_bits_valid (const struc extern int value_bits_synthetic_pointer (const struct value *value, int offset, int length); +/* Given a value, determine whether the contents bytes starting at + OFFSET and extending for LENGTH bytes are available. This returns + zero if all bytes in the given range are available, zero if any + byte is unavailable. */ + +extern int value_bytes_available (const struct value *value, + int offset, int length); + +/* Mark VALUE's content bytes starting at OFFSET and extending for + LENGTH bytes as unavailable. */ + +extern void mark_value_bytes_unavailable (struct value *value, + int offset, int length); + #include "symtab.h" Index: src/gdb/value.c =================================================================== --- src.orig/gdb/value.c 2011-02-07 11:31:36.446706000 +0000 +++ src/gdb/value.c 2011-02-07 11:31:37.996706001 +0000 @@ -63,6 +63,67 @@ struct internal_function void *cookie; }; +/* Defines an [OFFSET, OFFSET + LENGTH) range. */ + +struct range +{ + /* Lowest offset in the range. */ + int offset; + + /* Length of the range. */ + int length; +}; + +typedef struct range range_s; + +DEF_VEC_O(range_s); + +/* Returns true if the ranges defined by [offset1, offset1+len1) and + [offset2, offset2+len2) overlap. */ + +static int +ranges_overlap (int offset1, int len1, + int offset2, int len2) +{ + ULONGEST h, l; + + l = max (offset1, offset2); + h = min (offset1 + len1, offset2 + len2); + return (l < h); +} + +/* Returns true if RANGES contains any range that overlaps [OFFSET, + OFFSET+LENGTH). */ + +static int +ranges_contain_p (VEC(range_s) *ranges, int offset, int length) +{ + int i; + range_s *r; + + for (i = 0; VEC_iterate (range_s, ranges, i, r); i++) + if (ranges_overlap (r->offset, r->length, + offset, length)) + return 1; + + return 0; +} + +/* Returns a deep copy of RANGES. */ + +static VEC(range_s) * +ranges_copy (VEC(range_s) *ranges) +{ + int i; + range_s *r; + VEC(range_s) *copy = NULL; + + for (i = 0; VEC_iterate (range_s, ranges, i, r); i++) + VEC_safe_push (range_s, copy, r); + + return copy; +} + static struct cmd_list_element *functionlist; struct value @@ -206,6 +267,11 @@ struct value valid if lazy is nonzero. */ gdb_byte *contents; + /* Unavailable ranges in CONTENTS. We mark unavailable ranges, + rather than available, since the common and default case is for a + value to be available. This is filled in at value read time. */ + VEC(range_s) *unavailable; + /* The number of references to this value. When a value is created, the value chain holds a reference, so REFERENCE_COUNT is 1. If release_value is called, this value is removed from the chain but @@ -214,6 +280,83 @@ struct value int reference_count; }; +int +value_bytes_available (const struct value *value, int offset, int length) +{ + gdb_assert (!value->lazy); + + return !ranges_contain_p (value->unavailable, offset, length); +} + +void +mark_value_bytes_unavailable (struct value *value, int offset, int length) +{ + struct range *r; + int i; + + /* Insert the range sorted. If there's overlap or the new range + would be contiguous with an existing range, merge. */ + for (i = 0; VEC_iterate (range_s, value->unavailable, i, r); i++) + { + if (ranges_overlap (r->offset, r->length, offset, length)) + { + ULONGEST l = min (r->offset, offset); + ULONGEST h = max (r->offset + r->length, offset + length); + + r->offset = l; + r->length = h - l; + break; + } + else if (offset == r->offset + r->length) + { + r->length += length; + break; + } + else if (offset < r->offset) + { + struct range *nr; + + nr = VEC_safe_insert (range_s, value->unavailable, i, NULL); + nr->offset = offset; + nr->length = length; + break; + } + } + + /* Check whether the ranges following the one we've just added can + be folded in. */ + if (i < VEC_length (range_s, value->unavailable)) + { + /* Get the range we just touched. */ + struct range *t = VEC_index (range_s, value->unavailable, i); + int removed = 0; + + for (; VEC_iterate (range_s, value->unavailable, i, r); i++) + if (r->offset <= t->offset + t->length) + { + ULONGEST l, h; + + l = min (t->offset, r->offset); + h = max (t->offset + t->length, r->offset + r->length); + + t->offset = l; + t->length = h - l; + + removed++; + } + + if (removed != 0) + VEC_truncate (range_s, value->unavailable, + VEC_length (range_s, value->unavailable) - removed); + } + else + { + r = VEC_safe_push (range_s, value->unavailable, NULL); + r->offset = offset; + r->length = length; + } +} + /* Prototypes for local functions. */ static void show_values (char *, int); @@ -420,12 +563,19 @@ value_enclosing_type (struct value *valu } static void -require_not_optimized_out (struct value *value) +require_not_optimized_out (const struct value *value) { if (value->optimized_out) error (_("value has been optimized out")); } +static void +require_available (const struct value *value) +{ + if (!VEC_empty (range_s, value->unavailable)) + error (_("value is not available")); +} + const gdb_byte * value_contents_for_printing (struct value *value) { @@ -446,6 +596,7 @@ value_contents_all (struct value *value) { const gdb_byte *result = value_contents_for_printing (value); require_not_optimized_out (value); + require_available (value); return result; } @@ -478,6 +629,7 @@ value_contents (struct value *value) { const gdb_byte *result = value_contents_writeable (value); require_not_optimized_out (value); + require_available (value); return result; } @@ -703,6 +855,7 @@ value_free (struct value *val) } xfree (val->contents); + VEC_free (range_s, val->unavailable); } xfree (val); } @@ -833,6 +986,7 @@ value_copy (struct value *arg) TYPE_LENGTH (value_enclosing_type (arg))); } + val->unavailable = ranges_copy (arg->unavailable); val->parent = arg->parent; if (val->parent) value_incref (val->parent); Index: src/gdb/valprint.h =================================================================== --- src.orig/gdb/valprint.h 2011-02-07 11:31:36.446706000 +0000 +++ src/gdb/valprint.h 2011-02-07 11:31:37.996706001 +0000 @@ -154,4 +154,6 @@ int read_string (CORE_ADDR addr, int len extern void val_print_optimized_out (struct ui_file *stream); +extern void val_print_unavailable (struct ui_file *stream); + #endif Index: src/gdb/valprint.c =================================================================== --- src.orig/gdb/valprint.c 2011-02-07 11:31:36.446706000 +0000 +++ src/gdb/valprint.c 2011-02-07 11:31:37.996706001 +0000 @@ -260,7 +260,7 @@ scalar_type_p (struct type *type) static int valprint_check_validity (struct ui_file *stream, struct type *type, - int offset, + int embedded_offset, const struct value *val) { CHECK_TYPEDEF (type); @@ -269,19 +269,25 @@ valprint_check_validity (struct ui_file && TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_ARRAY) { - if (! value_bits_valid (val, TARGET_CHAR_BIT * offset, - TARGET_CHAR_BIT * TYPE_LENGTH (type))) + if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset, + TARGET_CHAR_BIT * TYPE_LENGTH (type))) { val_print_optimized_out (stream); return 0; } - if (value_bits_synthetic_pointer (val, TARGET_CHAR_BIT * offset, + if (value_bits_synthetic_pointer (val, TARGET_CHAR_BIT * embedded_offset, TARGET_CHAR_BIT * TYPE_LENGTH (type))) { fputs_filtered (_(""), stream); return 0; } + + if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type))) + { + val_print_unavailable (stream); + return 0; + } } return 1; @@ -293,6 +299,12 @@ val_print_optimized_out (struct ui_file fprintf_filtered (stream, _("")); } +void +val_print_unavailable (struct ui_file *stream) +{ + fprintf_filtered (stream, _("")); +} + /* Print using the given LANGUAGE the data of type TYPE located at VALADDR + EMBEDDED_OFFSET (within GDB), which came from the inferior at address ADDRESS + EMBEDDED_OFFSET, onto stdio stream @@ -560,6 +572,8 @@ val_print_scalar_formatted (struct type if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset, TARGET_CHAR_BIT * TYPE_LENGTH (type))) val_print_optimized_out (stream); + else if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type))) + val_print_unavailable (stream); else print_scalar_formatted (valaddr + embedded_offset, type, options, size, stream); Index: src/gdb/python/py-prettyprint.c =================================================================== --- src.orig/gdb/python/py-prettyprint.c 2011-02-07 11:31:36.446706000 +0000 +++ src/gdb/python/py-prettyprint.c 2011-02-07 11:31:37.996706001 +0000 @@ -690,6 +690,11 @@ apply_val_pretty_printer (struct type *t struct cleanup *cleanups; int result = 0; enum string_repr_result print_result; + + /* No pretty-printer support for unavailable values. */ + if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type))) + return 0; + cleanups = ensure_python_env (gdbarch, language); /* Instantiate the printer. */