Files
binutils-gdb/gdb/testsuite/gdb.base/settings.exp
Andrew Burgess baab375361 gdb: building inferior strings from within GDB
History Of This Patch
=====================

This commit aims to address PR gdb/21699.  There have now been a
couple of attempts to fix this issue.  Simon originally posted two
patches back in 2021:

  https://sourceware.org/pipermail/gdb-patches/2021-July/180894.html
  https://sourceware.org/pipermail/gdb-patches/2021-July/180896.html

Before Pedro then posted a version of his own:

  https://sourceware.org/pipermail/gdb-patches/2021-July/180970.html

After this the conversation halted.  Then in 2023 I (Andrew) also took
a look at this bug and posted two versions:

  https://sourceware.org/pipermail/gdb-patches/2023-April/198570.html
  https://sourceware.org/pipermail/gdb-patches/2023-April/198680.html

The approach taken in my first patch was pretty similar to what Simon
originally posted back in 2021.  My second attempt was only a slight
variation on the first.

Pedro then pointed out his older patch, and so we arrive at this
patch.  The GDB changes here are mostly Pedro's work, but updated by
me (Andrew), any mistakes are mine.

The tests here are a combinations of everyone's work, and the commit
message is new, but copies bits from everyone's earlier work.

Problem Description
===================

Bug PR gdb/21699 makes the observation that using $_as_string with
GDB's printf can cause GDB to print unexpected data from the
inferior.  The reproducer is pretty simple:

  #include <stddef.h>
  static char arena[100];

  /* Override malloc() so value_coerce_to_target() gets a known
     pointer, and we know we"ll see an error if $_as_string() gives
     a string that isn't null terminated. */
  void
  *malloc (size_t size)
  {
      memset (arena, 'x', sizeof (arena));
      if (size > sizeof (arena))
          return NULL;
      return arena;
  }

  int
  main ()
  {
    return 0;
  }

And then in a GDB session:

  $ gdb -q test
  Reading symbols from /tmp/test...
  (gdb) start
  Temporary breakpoint 1 at 0x4004c8: file test.c, line 17.
  Starting program: /tmp/test

  Temporary breakpoint 1, main () at test.c:17
  17        return 0;
  (gdb) printf "%s\n", $_as_string("hello")
  "hello"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  (gdb) quit

The problem above is caused by how value_cstring is used within
py-value.c, but once we understand the issue then it turns out that
value_cstring is used in an unexpected way in many places within GDB.

Within py-value.c we have a null-terminated C-style string.  We then
pass a pointer to this string, along with the length of this
string (so not including the null-character) to value_cstring.

In value_cstring GDB allocates an array value of the given character
type, and copies in requested number of characters.  However
value_cstring does not add a null-character of its own.  This means
that the value created by calling value_cstring is only
null-terminated if the null-character is included in the passed in
length.  In py-value.c this is not the case, and indeed, in most uses
of value_cstring, this is not the case.

When GDB tries to print one of these strings the value contents are
pushed to the inferior, and then read back as a C-style string, that
is, GDB reads inferior memory until it finds a null-terminator.  For
the py-value.c case, no null-terminator is pushed into the inferior,
so GDB will continue reading inferior memory until a null-terminator
is found, with unpredictable results.

Patch Description
=================

The first thing this patch does is better define what the arguments
for the two function value_cstring and value_string should represent.
The comments in the header file are updated to describe whether the
length argument should, or should not, include a null-character.
Also, the data argument is changed to type gdb_byte.  The functions as
they currently exist will handle wide-characters, in which case more
than one 'char' would be needed for each character.  As such using
gdb_byte seems to make more sense.

To avoid adding casts throughout GDB, I've also added an overload that
still takes a 'char *', but asserts that the character type being used
is of size '1'.

The value_cstring function is now responsible for adding a null
character at the end of the string value it creates.

However, once we start looking at how value_cstring is used, we
realise there's another, related, problem.  Not every language's
strings are null terminated.  Fortran and Ada strings, for example,
are just an array of characters, GDB already has the function
value_string which can be used to create such values.

Consider this example using current GDB:

  (gdb) set language ada
  (gdb) p $_gdb_setting("arch")
  $1 = (97, 117, 116, 111)
  (gdb) ptype $
  type = array (1 .. 4) of char
  (gdb) p $_gdb_maint_setting("test-settings string")
  $2 = (0)
  (gdb) ptype $
  type = array (1 .. 1) of char

This shows two problems, first, the $_gdb_setting and
$_gdb_maint_setting functions are calling value_cstring using the
builtin_char character, rather than a language appropriate type.  In
the first call, the 'arch' case, the value_cstring call doesn't
include the null character, so the returned array only contains the
expected characters.  But, in the $_gdb_maint_setting example we do
end up including the null-character, even though this is not expected
for Ada strings.

This commit adds a new language method language_defn::value_string,
this function takes a pointer and length and creates a language
appropriate value that represents the string.  For C, C++, etc this
will be a null-terminated string (by calling value_cstring), and for
Fortran and Ada this can be a bounded array of characters with no null
terminator.  Additionally, this new language_defn::value_string
function is responsible for selecting a language appropriate character
type.

After this commit the only calls to value_cstring are from the C
expression evaluator and from the default language_defn::value_string.

And the only calls to value_string are from Fortan, Ada, and ObjectC
related code.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=21699

Co-Authored-By: Simon Marchi <simon.marchi@efficios.com>
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Co-Authored-By: Pedro Alves <pedro@palves.net>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-06-05 13:25:08 +01:00

669 lines
18 KiB
Plaintext

# This testcase is part of GDB, the GNU debugger.
# Copyright 2019-2023 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Test the set/show commands framework. The test uses the
# "maintenance test-settings set/show xxx" subcommands to exercise
# TAB-completion and setting processing.
load_lib completion-support.exp
standard_testfile .c
if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
return -1
}
clean_restart
if { ![readline_is_used] } {
untested "no tab completion support without readline"
return -1
}
# Test the show command SHOW_CMD. EXPECTED_RE is the expected output.
# Also verifies that $_gdb_maint_setting_str produces an equivalent output,
# matching it with EXPECTED_RE. EXPECTED_RE double quotes are escaped
# unless EXPECTED_RE_ESCAPED is true, indicating the quotes in EXPECTED_RE
# are already escaped.
# The value for the setting corresponding to SHOW_CMD is then reset
# to RESET_VALUE, then set again to the value given by $_gdb_maint_setting_str
# and $_gdb_maint_setting. The default value of RESET_VALUE (0) should work for
# most settings. Note that we do not check that RESET_VALUE differs from
# the expected value, as we assume different values will be verified.
# The setting value must still be the one in force before calling show_setting.
# In other words, this verifies that
# maint set test-settings <some_setting> $_gdb_maint_setting_str(<some_setting>)
# maint set test-settings <some_setting> $_gdb_maint_setting(<some_setting>)
# do not change the setting value.
# This procedure makes it easier to make the test
# name/message unique, since we test the "show" commands many times.
# EXPECTED_RE is made part of the test name.
proc show_setting {show_cmd expected_re {expected_re_escaped 0} {reset_value 0}} {
global gdb_prompt
with_test_prefix "$show_cmd $expected_re" {
gdb_test "$show_cmd" $expected_re "show"
# Remove the first two words (such as "maint show") to have the
# setting name to use for $_gdb_maint_setting_str.
regsub "\[^ \]+ +\[^ \]+ +\(.*\)" $show_cmd "\\1" maint_setting
if {$expected_re_escaped} {
set escaped_expected_re $expected_re
} else {
regsub -all "\"" $expected_re "\\\\\\\"" escaped_expected_re
}
set test "print \$_gdb_maint_setting_str"
set setting_str_value "xxxYYYxxx"
gdb_test_multiple "print \$_gdb_maint_setting_str(\"$maint_setting\")" $test {
-re " = \"\($escaped_expected_re\)\".*$gdb_prompt $" {
set setting_str_value $expect_out(1,string)
regsub -all "\\\\" $expect_out(1,string) "" setting_str_value
pass $test
}
}
# Change the setting value to RESET_VALUE, set it back to setting_str_value
# and check we still have the original value.
gdb_test_no_output "maintenance set $maint_setting $reset_value" "str reset $reset_value"
gdb_test_no_output "maintenance set $maint_setting $setting_str_value" "str set again"
gdb_test "$show_cmd" $expected_re "str show after reset+set again"
# Same test, but with value captured from $_gdb_maint_setting.
set test "print \$_gdb_maint_setting"
set setting_value "xxxYYYxxx"
gdb_test_multiple "print \$_gdb_maint_setting(\"$maint_setting\")" $test {
-re " = \"\(.*\)\".*$gdb_prompt $" {
set setting_value $expect_out(1,string)
regsub -all "\\\\" $expect_out(1,string) "" setting_value
pass $test
}
-re " = \(.*\)\r\n$gdb_prompt $" {
set setting_value $expect_out(1,string)
pass $test
}
}
gdb_test_no_output "maintenance set $maint_setting $reset_value" "reset $reset_value"
gdb_test_no_output "maintenance set $maint_setting $setting_value" "set again"
gdb_test "$show_cmd" $expected_re "show after reset+set again"
}
}
# Verifies that $_gdb_setting (SETTING) gives a value whose ptype matches EXPECTED.
proc check_type {setting expected} {
with_test_prefix "check_type $setting $expected" {
gdb_test "print \$_gdb_maint_setting(\"$setting\")"
gdb_test "ptype $" "$expected"
# Currently, GDB ptype <internal function> always tells it is type int.
# ptype should better report an error such as:
# "No type information for GDB functions"
# Test 'type int', so as to make it fail if ptype is changed.
gdb_test "ptype \$_gdb_maint_setting(\"$setting\")" \
"type = int"
}
}
# var_Xinteger tests. VARIANT determines which command/variant to
# exercise.
proc test-integer {variant} {
set set_cmd "maint set test-settings $variant"
set show_cmd "maint show test-settings $variant"
# A bogus value.
gdb_test "$set_cmd bogus" \
"No symbol table is loaded\\. Use the \"file\" command\\."
# Seemingly-valid but not quite valid value.
gdb_test "$set_cmd 1a" \
"Invalid number \"1a\"\\."
# Valid value followed by garbage.
gdb_test "$set_cmd 1 1" \
"A syntax error in expression, near `1'\\."
# Valid value followed by garbage.
gdb_test "$set_cmd 1 x" \
"A syntax error in expression, near `x'\\."
if {$variant == "zuinteger-unlimited"} {
# -1 means unlimited. Other negative values are rejected. -1
# -is tested further below, along the "unlimited" tests.
gdb_test "$set_cmd -2" "integer -2 out of range"
check_type "test-settings $variant" "type = int"
} elseif {$variant == "uinteger" || $variant == "zuinteger"} {
# Negative values are not accepted.
gdb_test "$set_cmd -1" "integer -1 out of range"
gdb_test "$set_cmd -2" "integer -2 out of range"
check_type "test-settings $variant" "type = unsigned int"
} else {
# Negative values are not accepted.
gdb_test_no_output "$set_cmd -1"
show_setting "$show_cmd" "-1"
gdb_test_no_output "$set_cmd -2"
show_setting "$show_cmd" "-2"
check_type "test-settings $variant" "type = int"
}
# Regular integer is accepted.
gdb_test_no_output "$set_cmd 999"
show_setting "$show_cmd" "999"
if {$variant == "zinteger" || $variant == "zuinteger"} {
# 0 means 0.
gdb_test_no_output "$set_cmd 0"
show_setting "$show_cmd" "0"
} else {
# Either 0 or -1 mean unlimited. Test both the number and
# "unlimited". For the latter, test both full name and
# abbreviations.
if {$variant == "zuinteger-unlimited"} {
gdb_test_no_output "$set_cmd -1"
} else {
gdb_test_no_output "$set_cmd 0"
}
show_setting "$show_cmd" "unlimited"
foreach_with_prefix value {
"u"
"un"
"unl"
"unli"
"unlim"
"unlimi"
"unlimit"
"unlimite"
"unlimited"
} {
# Alternate between integer and unlimited, to make sure the
# setting really took effect.
gdb_test_no_output "$set_cmd 1"
show_setting "$show_cmd" "1"
gdb_test_no_output "$set_cmd $value"
show_setting "$show_cmd" "unlimited"
}
}
if {$variant == "zuinteger"} {
test_gdb_complete_multiple "maint set test-settings " "zuinteger" "" {
"zuinteger"
"zuinteger-unlimited"
}
} else {
test_gdb_complete_unique \
"$set_cmd" \
"$set_cmd"
}
if {$variant == "zinteger" || $variant == "zuinteger"} {
test_gdb_complete_none \
"$set_cmd "
} else {
test_gdb_complete_multiple "$set_cmd " "" "" {
"NUMBER"
"unlimited"
}
test_gdb_complete_none \
"$set_cmd 1"
test_gdb_complete_unique \
"$set_cmd u" \
"$set_cmd unlimited"
}
# Check junk after "unlimited".
gdb_test "$set_cmd unlimitedu" "No symbol table is loaded.*"
if {$variant == "zinteger" || $variant == "zuinteger"} {
gdb_test "$set_cmd unlimited u" "No symbol table is loaded.*"
gdb_test "$set_cmd unlimited 1" "No symbol table is loaded.*"
gdb_test "$set_cmd unlimited -1" "No symbol table is loaded.*"
} else {
gdb_test "$set_cmd unlimited u" "Junk after \"unlimited\": u"
gdb_test "$set_cmd unlimited 1" "Junk after \"unlimited\": 1"
gdb_test "$set_cmd unlimited -1" "Junk after \"unlimited\": -1"
}
test_gdb_complete_none "$set_cmd unlimited "
test_gdb_complete_none "$set_cmd unlimitedu"
test_gdb_complete_none "$set_cmd unlimited u"
test_gdb_complete_none "$set_cmd unlimited 1"
test_gdb_complete_none "$set_cmd x"
test_gdb_complete_none "$set_cmd x "
test_gdb_complete_none "$set_cmd -1"
test_gdb_complete_none "$set_cmd -1 "
test_gdb_complete_none "$set_cmd 1 "
# Check show command completion.
if {$variant == "zuinteger"} {
test_gdb_complete_multiple "maintenance show test-settings " "zuinteger" "" {
"zuinteger"
"zuinteger-unlimited"
}
} else {
test_gdb_complete_unique \
"$show_cmd" \
"$show_cmd"
}
test_gdb_complete_none "$show_cmd "
}
# boolean tests.
proc_with_prefix test-boolean {} {
# Use these variables to make sure we don't call the wrong command
# by mistake.
set set_cmd "maint set test-settings boolean"
set show_cmd "maint show test-settings boolean"
# A bogus value.
gdb_test "$set_cmd bogus" \
"\"on\" or \"off\" expected\\."
# Seemingly-valid but not quite valid value.
gdb_test "$set_cmd on1" \
"\"on\" or \"off\" expected\\."
# Valid value followed by garbage.
gdb_test "$set_cmd on 1" \
"\"on\" or \"off\" expected\\."
# Unlike auto-bool settings, "-1" is not accepted.
gdb_test "$set_cmd -1" \
"\"on\" or \"off\" expected\\."
# Nor "auto".
gdb_test "$set_cmd auto" \
"\"on\" or \"off\" expected\\."
# "o" is ambiguous.
gdb_test "$set_cmd o" \
"\"on\" or \"off\" expected\\."
# Various valid values. Test both full value names and
# abbreviations.
# Note that unlike with auto-bool, empty value implies "on".
foreach_with_prefix value {
""
"on"
"1"
"y"
"ye"
"yes"
"e"
"en"
"ena"
"enab"
"enabl"
"enable"
} {
gdb_test_no_output "$set_cmd off"
show_setting "$show_cmd" "off"
gdb_test_no_output "$set_cmd $value"
show_setting "$show_cmd" "on"
}
check_type "test-settings boolean" "type = int"
foreach_with_prefix value {
"of"
"off"
"0"
"n"
"no"
"d"
"di"
"dis"
"disa"
"disab"
"disabl"
"disable"
} {
gdb_test_no_output "$set_cmd on"
show_setting "$show_cmd" "on"
gdb_test_no_output "$set_cmd $value"
show_setting "$show_cmd" "off"
}
test_gdb_complete_multiple "$set_cmd " "" "o" {
"off"
"on"
}
test_gdb_complete_unique \
"$set_cmd of" \
"$set_cmd off"
test_gdb_complete_none "$set_cmd x"
# Check that the show command doesn't complete anything.
test_gdb_complete_unique \
"$show_cmd" \
"$show_cmd"
test_gdb_complete_none "$show_cmd "
}
# auto-boolean tests.
proc_with_prefix test-auto-boolean {} {
# Use these variables to make sure we don't call the wrong command
# by mistake.
set set_cmd "maint set test-settings auto-boolean"
set show_cmd "maint show test-settings auto-boolean"
# A bogus value.
gdb_test "$set_cmd bogus" \
"\"on\", \"off\" or \"auto\" expected\\."
# Seemingly-valid but not quite valid value.
gdb_test "$set_cmd on1" \
"\"on\", \"off\" or \"auto\" expected\\."
# Valid value followed by garbage.
gdb_test "$set_cmd on 1" \
"\"on\", \"off\" or \"auto\" expected\\."
# "o" is ambiguous.
gdb_test "$set_cmd o" \
"\"on\", \"off\" or \"auto\" expected\\."
# Various valid values. Test both full value names and
# abbreviations.
foreach_with_prefix value {
"on"
"1"
"y"
"ye"
"yes"
"e"
"en"
"ena"
"enab"
"enabl"
"enable"
} {
gdb_test_no_output "$set_cmd off"
show_setting "$show_cmd" "off"
gdb_test_no_output "$set_cmd $value"
show_setting "$show_cmd" "on"
}
foreach_with_prefix value {
"of"
"off"
"0"
"n"
"no"
"d"
"di"
"dis"
"disa"
"disab"
"disabl"
"disable"
} {
gdb_test_no_output "$set_cmd on"
show_setting "$show_cmd" "on"
gdb_test_no_output "$set_cmd $value"
show_setting "$show_cmd" "off"
}
foreach_with_prefix value {
"a"
"au"
"aut"
"auto"
"-1"
} {
gdb_test_no_output "$set_cmd on"
show_setting "$show_cmd" "on"
gdb_test_no_output "$set_cmd $value"
show_setting "$show_cmd" "auto"
}
check_type "test-settings auto-boolean" "type = int"
# "-" is not accepted as abbreviation of "-1".
gdb_test "$set_cmd -" \
"\"on\", \"off\" or \"auto\" expected\\."
test_gdb_complete_multiple "$set_cmd " "" "" {
"auto"
"off"
"on"
}
test_gdb_complete_unique \
"$set_cmd of" \
"$set_cmd off"
test_gdb_complete_none "$set_cmd x"
# Check that the show command doesn't complete anything.
test_gdb_complete_unique \
"$show_cmd" \
"$show_cmd"
test_gdb_complete_none "$show_cmd "
}
# Enum option tests.
proc_with_prefix test-enum {} {
# Use these variables to make sure we don't call the wrong command
# by mistake.
set set_cmd "maint set test-settings enum"
set show_cmd "maint show test-settings enum"
# Missing value.
gdb_test "$set_cmd" \
"Requires an argument\\. Valid arguments are xxx, yyy, zzz\\."
# A bogus value.
gdb_test "$set_cmd bogus" \
"Undefined item: \"bogus\"."
# Seemingly-valid but not quite valid value.
gdb_test "$set_cmd xxx1" \
"Undefined item: \"xxx1\"."
# Valid value followed by garbage.
gdb_test "$set_cmd xxx 1" \
"Junk after item \"xxx\": 1"
# Valid value followed by garbage, with extra spaces.
gdb_test "$set_cmd xxx 1" \
"Junk after item \"xxx\": 1"
# Abbreviated value followed by garbage.
gdb_test "$set_cmd xx 1" \
"Junk after item \"xx\": 1"
# Various valid values. Test both full value names and
# abbreviations.
gdb_test_no_output "$set_cmd x"
show_setting "$show_cmd" "xxx" 0 "zzz"
gdb_test_no_output "$set_cmd yy"
show_setting "$show_cmd" "yyy" 0 "zzz"
gdb_test_no_output "$set_cmd zzz"
show_setting "$show_cmd" "zzz" 0 "yyy"
check_type "test-settings enum" "type = char \\\[4\\\]"
test_gdb_complete_multiple "$set_cmd " "" "" {
"xxx"
"yyy"
"zzz"
}
test_gdb_complete_unique \
"$set_cmd x" \
"$set_cmd xxx"
test_gdb_complete_none "$set_cmd a"
# Check that the show command doesn't complete anything.
test_gdb_complete_unique \
"$show_cmd" \
"$show_cmd"
test_gdb_complete_none "$show_cmd "
}
# string settings tests.
proc test-string {variant} {
global gdb_prompt
global srcfile binfile
# Load symbols for the completion test below.
clean_restart $binfile
# Use these variables to make sure we don't call the wrong command
# by mistake.
set set_cmd "maint set test-settings $variant"
set show_cmd "maint show test-settings $variant"
# Checks that gdb doesn't crash if we haven't set the string yet.
if {$variant != "filename"} {
# This odd expected output here is because we expect GDB to
# emit a single blank line as a result of this command.
gdb_test -nonl "$show_cmd" "^\r\n" "$show_cmd: show default"
} else {
gdb_test "$show_cmd" "/foo/bar" "$show_cmd: show default"
}
# A string value.
gdb_test_no_output "$set_cmd hello world"
show_setting "$show_cmd" "hello world"
check_type "test-settings $variant" "type = char \\\[\[1-9\]\[0-9\]*\\\]"
# A quoted string value.
if {$variant == "string"} {
gdb_test_no_output "$set_cmd \"hello world\""
show_setting "$show_cmd" "\\\\\"hello world\\\\\"" 1
} else {
gdb_test_no_output "$set_cmd \"hello world\""
show_setting "$show_cmd" "\"hello world\""
}
# Test clearing the string.
with_test_prefix "clear string" {
if {$variant == "filename"} {
gdb_test "$set_cmd" \
"Argument required \\(filename to set it to\\.\\)\\."
# Check the value didn't change.
show_setting "$show_cmd" "\"hello world\""
} else {
gdb_test_no_output "$set_cmd"
# This odd expected output here is because we expect GDB to
# emit a single blank line as a result of this command.
gdb_test -nonl "$show_cmd" "^\r\n" "$show_cmd: empty second time"
}
}
# Test completion.
if {$variant == "string" || $variant == "string-noescape" } {
# Make sure GDB doesn't try to complete on symbols, which
# doesn't make any sense.
test_gdb_complete_none "$set_cmd "
} else {
# Complete on filename.
# See comments in gdb.base/completion.exp.
# We `cd' to ${srcdir}, and then do the completion relative to
# the current directory.
# ${srcdir} may be a relative path. We want to make sure we
# end up in the right directory - so make sure we know where
# it is.
with_cwd $::srcdir {
set fullsrcdir [pwd]
}
gdb_test "cd ${fullsrcdir}" \
"Working directory [string_to_regexp ${fullsrcdir}].*" \
"cd to \${srcdir}"
set unique_file ../testsuite/gdb.base/comp-dir/subdir/dummy
test_gdb_complete_unique \
"$set_cmd ${unique_file}" \
"$set_cmd ${unique_file}.txt"
test_gdb_complete_none "$set_cmd ${unique_file}.abc"
}
# Check show command completion.
if {$variant == "string"} {
test_gdb_complete_multiple "maint show test-settings " "string" "" {
"string"
"string-noescape"
}
} else {
test_gdb_complete_unique \
"$show_cmd" \
"$show_cmd"
}
test_gdb_complete_none "$show_cmd "
}
# Check that $_gdb_setting & co report the correct error strings.
proc test-setting-error {} {
gdb_test {print $_gdb_setting("xxx")} \
"First argument of \\\$_gdb_setting must be a valid setting of the 'show' command\\."
gdb_test {print $_gdb_setting_str("xxx")} \
"First argument of \\\$_gdb_setting_str must be a valid setting of the 'show' command\\."
gdb_test {print $_gdb_maint_setting("xxx")} \
"First argument of \\\$_gdb_maint_setting must be a valid setting of the 'maintenance show' command\\."
gdb_test {print $_gdb_maint_setting_str("xxx")} \
"First argument of \\\$_gdb_maint_setting_str must be a valid setting of the 'maintenance show' command\\."
}
foreach variant {
uinteger
integer
zinteger
zuinteger
zuinteger-unlimited
} {
with_test_prefix "test-integer $variant" {
test-integer $variant
}
}
test-boolean
test-auto-boolean
test-enum
foreach variant {
string
string-noescape
optional-filename
filename
} {
with_test_prefix "test-string $variant" {
test-string $variant
}
}
test-setting-error