diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2015-12-11 17:37:49 +0000 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2016-02-01 18:05:35 +0000 |
commit | 5fdf6324fafd60f967e2e8323fdacf84b1bfcea3 (patch) | |
tree | b7fa72f4b96fccd13aa8fb068b5472bacc64c8bf /gdb/value.c | |
parent | b125bd17270aca2af4d945ce8477f981dbc27e7e (diff) | |
download | gdb-5fdf6324fafd60f967e2e8323fdacf84b1bfcea3.zip gdb-5fdf6324fafd60f967e2e8323fdacf84b1bfcea3.tar.gz gdb-5fdf6324fafd60f967e2e8323fdacf84b1bfcea3.tar.bz2 |
gdb: New set/show max-value-size command.
For languages with dynamic types, an incorrect program, or uninitialised
variables within a program, could result in an incorrect, overly large
type being associated with a value. Currently, attempting to print such
a variable will result in gdb trying to allocate an overly large buffer.
If this large memory allocation fails then the result can be gdb either
terminating, or (due to memory contention) becoming unresponsive for the
user.
A new user visible variable in gdb helps guard against such problems,
two new commands are available:
set max-value-size
show max-value-size
The 'max-value-size' is the maximum size of memory in bytes that gdb
will allocate for the contents of a value. Any attempt to allocate a
value with a size greater than this will result in an error. The
initial default for this limit is set at 64k, this is based on a similar
limit that exists within the ada specific code.
It is possible for the user to set max-value-size to unlimited, in which
case the old behaviour is restored.
gdb/ChangeLog:
* value.c (max_value_size): New variable.
(MIN_VALUE_FOR_MAX_VALUE_SIZE): New define.
(show_max_value_size): New function.
(check_type_length_before_alloc): New function.
(allocate_value_contents): Call check_type_length_before_alloc.
(set_value_enclosing_type): Likewise.
(_initialize_values): Add set/show handler for max-value-size.
* NEWS: Mention new set/show command.
gdb/doc/ChangeLog:
* gdb.texinfo (Value Sizes): New section.
(Data): Add the 'Value Sizes' node to the menu.
gdb/testsuite/ChangeLog:
* gdb.base/max-value-size.c: New file.
* gdb.base/max-value-size.exp: New file.
* gdb.base/huge.exp: Disable max-value-size for this test.
Diffstat (limited to 'gdb/value.c')
-rw-r--r-- | gdb/value.c | 97 |
1 files changed, 93 insertions, 4 deletions
diff --git a/gdb/value.c b/gdb/value.c index eeb2b7d..738b2b2 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -955,13 +955,86 @@ allocate_value_lazy (struct type *type) return val; } +/* The maximum size, in bytes, that GDB will try to allocate for a value. + The initial value of 64k was not selected for any specific reason, it is + just a reasonable starting point. */ + +static int max_value_size = 65536; /* 64k bytes */ + +/* It is critical that the MAX_VALUE_SIZE is at least as big as the size of + LONGEST, otherwise GDB will not be able to parse integer values from the + CLI; for example if the MAX_VALUE_SIZE could be set to 1 then GDB would + be unable to parse "set max-value-size 2". + + As we want a consistent GDB experience across hosts with different sizes + of LONGEST, this arbitrary minimum value was selected, so long as this + is bigger than LONGEST on all GDB supported hosts we're fine. */ + +#define MIN_VALUE_FOR_MAX_VALUE_SIZE 16 +gdb_static_assert (sizeof (LONGEST) <= MIN_VALUE_FOR_MAX_VALUE_SIZE); + +/* Implement the "set max-value-size" command. */ + +static void +set_max_value_size (char *args, int from_tty, + struct cmd_list_element *c) +{ + gdb_assert (max_value_size == -1 || max_value_size >= 0); + + if (max_value_size > -1 && max_value_size < MIN_VALUE_FOR_MAX_VALUE_SIZE) + { + max_value_size = MIN_VALUE_FOR_MAX_VALUE_SIZE; + error (_("max-value-size set too low, increasing to %d bytes"), + max_value_size); + } +} + +/* Implement the "show max-value-size" command. */ + +static void +show_max_value_size (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + if (max_value_size == -1) + fprintf_filtered (file, _("Maximum value size is unlimited.\n")); + else + fprintf_filtered (file, _("Maximum value size is %d bytes.\n"), + max_value_size); +} + +/* Called before we attempt to allocate or reallocate a buffer for the + contents of a value. TYPE is the type of the value for which we are + allocating the buffer. If the buffer is too large (based on the user + controllable setting) then throw an error. If this function returns + then we should attempt to allocate the buffer. */ + +static void +check_type_length_before_alloc (const struct type *type) +{ + unsigned int length = TYPE_LENGTH (type); + + if (max_value_size > -1 && length > max_value_size) + { + if (TYPE_NAME (type) != NULL) + error (_("value of type `%s' requires %u bytes, which is more " + "than max-value-size"), TYPE_NAME (type), length); + else + error (_("value requires %u bytes, which is more than " + "max-value-size"), length); + } +} + /* Allocate the contents of VAL if it has not been allocated yet. */ static void allocate_value_contents (struct value *val) { if (!val->contents) - val->contents = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type)); + { + check_type_length_before_alloc (val->enclosing_type); + val->contents + = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type)); + } } /* Allocate a value and its contents for type TYPE. */ @@ -2986,9 +3059,12 @@ value_static_field (struct type *type, int fieldno) void set_value_enclosing_type (struct value *val, struct type *new_encl_type) { - if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) - val->contents = - (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type)); + if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) + { + check_type_length_before_alloc (new_encl_type); + val->contents + = (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type)); + } val->enclosing_type = new_encl_type; } @@ -4013,4 +4089,17 @@ Check whether an expression is void.\n\ Usage: $_isvoid (expression)\n\ Return 1 if the expression is void, zero otherwise."), isvoid_internal_fn, NULL); + + add_setshow_zuinteger_unlimited_cmd ("max-value-size", + class_support, &max_value_size, _("\ +Set maximum sized value gdb will load from the inferior."), _("\ +Show maximum sized value gdb will load from the inferior."), _("\ +Use this to control the maximum size, in bytes, of a value that gdb\n\ +will load from the inferior. Setting this value to 'unlimited'\n\ +disables checking.\n\ +Setting this does not invalidate already allocated values, it only\n\ +prevents future values, larger than this size, from being allocated."), + set_max_value_size, + show_max_value_size, + &setlist, &showlist); } |