diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ada-lang.c | 115 | ||||
-rw-r--r-- | gdb/cli/cli-decode.h | 2 | ||||
-rw-r--r-- | gdb/dwarf2/read.c | 31 | ||||
-rw-r--r-- | gdb/testsuite/gdb.ada/scalar_storage.exp | 28 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c | 205 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp | 106 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/printcmds.exp | 7 | ||||
-rw-r--r-- | gdb/valops.c | 3 |
8 files changed, 413 insertions, 84 deletions
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 9d35440..3f5e707 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -36,7 +36,7 @@ #include "objfiles.h" #include "breakpoint.h" #include "gdbcore.h" -#include "hashtab.h" +#include "gdbsupport/unordered_set.h" #include "gdbsupport/gdb_obstack.h" #include "ada-lang.h" #include "completer.h" @@ -52,6 +52,7 @@ #include "namespace.h" #include "cli/cli-style.h" #include "cli/cli-decode.h" +#include "gdbsupport/string-set.h" #include "value.h" #include "mi/mi-common.h" @@ -349,56 +350,58 @@ struct cache_entry_search { const char *name; domain_search_flags domain; +}; + +/* Hash function for cache entry. */ + +struct cache_entry_hash +{ + using is_transparent = void; + using is_avalanching = void; - hashval_t hash () const + /* This implementation works for both cache_entry and + cache_entry_search. */ + template<typename T> + uint64_t operator() (const T &entry) const noexcept { - /* This must agree with hash_cache_entry, below. */ - return htab_hash_string (name); + return ankerl::unordered_dense::hash<std::string_view> () (entry.name); } }; -/* Hash function for cache_entry. */ +/* Equality function for cache entry. */ -static hashval_t -hash_cache_entry (const void *v) +struct cache_entry_eq { - const cache_entry *entry = (const cache_entry *) v; - return htab_hash_string (entry->name.c_str ()); -} - -/* Equality function for cache_entry. */ + using is_transparent = void; -static int -eq_cache_entry (const void *a, const void *b) -{ - const cache_entry *entrya = (const cache_entry *) a; - const cache_entry_search *entryb = (const cache_entry_search *) b; + /* This implementation works for both cache_entry and + cache_entry_search. */ + template<typename T> + bool operator() (const T &lhs, const cache_entry &rhs) const noexcept + { + return lhs.domain == rhs.domain && lhs.name == rhs.name; + } +}; - return entrya->domain == entryb->domain && entrya->name == entryb->name; -} +using cache_entry_set + = gdb::unordered_set<cache_entry, cache_entry_hash, cache_entry_eq>; /* Key to our per-program-space data. */ -static const registry<program_space>::key<htab, htab_deleter> +static const registry<program_space>::key<cache_entry_set> ada_pspace_data_handle; -/* Return this module's data for the given program space (PSPACE). - If not is found, add a zero'ed one now. - - This function always returns a valid object. */ +/* Return this module's data for the given program space (PSPACE). If + not is found, one is created. This function always returns a valid + object. */ -static htab_t +static cache_entry_set & get_ada_pspace_data (struct program_space *pspace) { - htab_t data = ada_pspace_data_handle.get (pspace); + cache_entry_set *data = ada_pspace_data_handle.get (pspace); if (data == nullptr) - { - data = htab_create_alloc (10, hash_cache_entry, eq_cache_entry, - htab_delete_entry<cache_entry>, - xcalloc, xfree); - ada_pspace_data_handle.set (pspace, data); - } + data = ada_pspace_data_handle.emplace (pspace); - return data; + return *data; } /* Utilities */ @@ -1603,7 +1606,7 @@ ada_decode_tests () storage leak, it should not be significant unless there are massive changes in the set of decoded names in successive versions of a symbol table loaded during a single session. */ -static struct htab *decoded_names_store; +static gdb::string_set decoded_names_store; /* Returns the decoded name of GSYMBOL, as for ada_decode, caching it in the language-specific part of GSYMBOL, if it has not been @@ -1637,13 +1640,7 @@ ada_decode_symbol (const struct general_symbol_info *arg) which case, we put the result on the heap. Since we only decode when needed, we hope this usually does not cause a significant memory leak (FIXME). */ - - char **slot = (char **) htab_find_slot (decoded_names_store, - decoded.c_str (), INSERT); - - if (*slot == NULL) - *slot = xstrdup (decoded.c_str ()); - *resultp = *slot; + *resultp = decoded_names_store.insert (decoded); } } @@ -3950,9 +3947,9 @@ ada_type_match (struct type *ftype, struct type *atype) atype = ada_check_typedef (atype); if (ftype->code () == TYPE_CODE_REF) - ftype = ftype->target_type (); + ftype = ada_check_typedef (ftype->target_type ()); if (atype->code () == TYPE_CODE_REF) - atype = atype->target_type (); + atype = ada_check_typedef (atype->target_type ()); switch (ftype->code ()) { @@ -4695,19 +4692,18 @@ static int lookup_cached_symbol (const char *name, domain_search_flags domain, struct symbol **sym, const struct block **block) { - htab_t tab = get_ada_pspace_data (current_program_space); + cache_entry_set &htab = get_ada_pspace_data (current_program_space); cache_entry_search search; search.name = name; search.domain = domain; - cache_entry *e = (cache_entry *) htab_find_with_hash (tab, &search, - search.hash ()); - if (e == nullptr) + auto iter = htab.find (search); + if (iter == htab.end ()) return 0; if (sym != nullptr) - *sym = e->sym; + *sym = iter->sym; if (block != nullptr) - *block = e->block; + *block = iter->block; return 1; } @@ -4735,21 +4731,8 @@ cache_symbol (const char *name, domain_search_flags domain, return; } - htab_t tab = get_ada_pspace_data (current_program_space); - cache_entry_search search; - search.name = name; - search.domain = domain; - - void **slot = htab_find_slot_with_hash (tab, &search, - search.hash (), INSERT); - - cache_entry *e = new cache_entry; - e->name = name; - e->domain = domain; - e->sym = sym; - e->block = block; - - *slot = e; + cache_entry_set &tab = get_ada_pspace_data (current_program_space); + tab.insert (cache_entry {name, domain, sym, block}); } /* Symbol Lookup */ @@ -14049,10 +14032,6 @@ When enabled, the debugger will stop using the DW_AT_GNAT_descriptive_type\n\ DWARF attribute."), NULL, NULL, &maint_set_ada_cmdlist, &maint_show_ada_cmdlist); - decoded_names_store = htab_create_alloc (256, htab_hash_string, - htab_eq_string, - NULL, xcalloc, xfree); - /* The ada-lang observers. */ gdb::observers::new_objfile.attach (ada_new_objfile_observer, "ada-lang"); gdb::observers::all_objfiles_removed.attach (ada_clear_symbol_cache, diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h index 217afbc..9be446f 100644 --- a/gdb/cli/cli-decode.h +++ b/gdb/cli/cli-decode.h @@ -62,6 +62,8 @@ struct cmd_list_element type (not_set_cmd), doc (doc_) { + gdb_assert (name != nullptr); + gdb_assert (doc != nullptr); memset (&function, 0, sizeof (function)); } diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 6e96afe..794c397 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -2383,14 +2383,14 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile, return (sect_offset) read_offset (abfd, info_ptr, offset_size); } -/* A helper for create_debug_types_hash_table. Read types from SECTION +/* A helper for create_dwo_debug_types_hash_table. Read types from SECTION and fill them into DWO_FILE's type unit hash table. It will process only type units, therefore DW_UT_type. */ static void -create_debug_type_hash_table (dwarf2_per_objfile *per_objfile, - dwo_file *dwo_file, dwarf2_section_info *section, - rcuh_kind section_kind) +create_dwo_debug_type_hash_table (dwarf2_per_objfile *per_objfile, + dwo_file *dwo_file, dwarf2_section_info *section, + rcuh_kind section_kind) { struct objfile *objfile = per_objfile->objfile; struct dwarf2_section_info *abbrev_section; @@ -2479,12 +2479,12 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile, Note: This function processes DWO files only, not DWP files. */ static void -create_debug_types_hash_table +create_dwo_debug_types_hash_table (dwarf2_per_objfile *per_objfile, dwo_file *dwo_file, gdb::array_view<dwarf2_section_info> type_sections) { for (dwarf2_section_info §ion : type_sections) - create_debug_type_hash_table (per_objfile, dwo_file, §ion, + create_dwo_debug_type_hash_table (per_objfile, dwo_file, §ion, rcuh_kind::TYPE); } @@ -6308,7 +6308,7 @@ lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name, Note: This function processes DWO files only, not DWP files. */ static void -create_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) +create_dwo_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) { dwarf2_per_objfile *per_objfile = cu->per_objfile; struct objfile *objfile = per_objfile->objfile; @@ -6342,6 +6342,12 @@ create_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) if (reader.is_dummy()) continue; + /* DWARF 5 .debug_info.dwo sections may contain some type units. Skip + everything that is not a compile unit. */ + if (const auto ut = reader.cu ()->header.unit_type; + ut != DW_UT_compile && ut != DW_UT_split_compile) + continue; + std::optional<ULONGEST> signature = lookup_dwo_id (reader.cu (), reader.top_level_die ()); if (!signature.has_value ()) @@ -7630,14 +7636,15 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, dwarf2_locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (), sec, &dwo_file->sections); - create_cus_hash_table (cu, *dwo_file); + create_dwo_cus_hash_table (cu, *dwo_file); if (cu->header.version < 5) - create_debug_types_hash_table (per_objfile, dwo_file.get (), - dwo_file->sections.types); + create_dwo_debug_types_hash_table (per_objfile, dwo_file.get (), + dwo_file->sections.types); else - create_debug_type_hash_table (per_objfile, dwo_file.get (), - &dwo_file->sections.info, rcuh_kind::COMPILE); + create_dwo_debug_type_hash_table (per_objfile, dwo_file.get (), + &dwo_file->sections.info, + rcuh_kind::COMPILE); dwarf_read_debug_printf ("DWO file found: %s", dwo_name); diff --git a/gdb/testsuite/gdb.ada/scalar_storage.exp b/gdb/testsuite/gdb.ada/scalar_storage.exp index 6b29226..52a85cd 100644 --- a/gdb/testsuite/gdb.ada/scalar_storage.exp +++ b/gdb/testsuite/gdb.ada/scalar_storage.exp @@ -45,10 +45,30 @@ if {![runto "storage.adb:$bp_location"]} { return } -gdb_test "print V_LE" "= \\(value => 126, another_value => 12, color => green\\)" +set re "value => 126, another_value => 12, color => green" # This requires a compiler fix that is in GCC 14. -if { ![gnat_version_compare >= 14] } { - setup_kfail "DW_AT_endianity on enum types" *-*-* +set have_xfail [expr ![gnat_version_compare >= 14]] +set re_color "(red|green|blue|$decimal)" +set re_xfail \ + "value => $decimal, another_value => $decimal, color => $re_color" + +set re_pre [string_to_regexp " = ("] +set re_post [string_to_regexp ")"] +set re $re_pre$re$re_post +set re_xfail $re_pre$re_xfail$re_post + +foreach var { V_LE V_BE } { + gdb_test_multiple "print $var" "" { + -re -wrap $re { + pass $gdb_test_name + } + -re -wrap $re_xfail { + if { $have_xfail } { + xfail $gdb_test_name + } else { + fail $gdb_test_name + } + } + } } -gdb_test "print V_BE" "= \\(value => 126, another_value => 12, color => green\\)" diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c new file mode 100644 index 0000000..c86beaf --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c @@ -0,0 +1,205 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025 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/>. */ + +/* Exercise unwinding AArch64's SVE registers from a signal frame. */ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <sys/prctl.h> +#include <unistd.h> + +static int second_vl = 0; + +static void +initialize_sve_state_main () +{ + __asm __volatile ("dup z0.b, -1"); + __asm __volatile ("dup z1.b, -1"); + __asm __volatile ("dup z2.b, -1"); + __asm __volatile ("dup z3.b, -1"); + __asm __volatile ("dup z4.b, -1"); + __asm __volatile ("dup z5.b, -1"); + __asm __volatile ("dup z6.b, -1"); + __asm __volatile ("dup z7.b, -1"); + __asm __volatile ("dup z8.b, -1"); + __asm __volatile ("dup z9.b, -1"); + __asm __volatile ("dup z10.b, -1"); + __asm __volatile ("dup z11.b, -1"); + __asm __volatile ("dup z12.b, -1"); + __asm __volatile ("dup z13.b, -1"); + __asm __volatile ("dup z14.b, -1"); + __asm __volatile ("dup z15.b, -1"); + __asm __volatile ("dup z16.b, -1"); + __asm __volatile ("dup z17.b, -1"); + __asm __volatile ("dup z18.b, -1"); + __asm __volatile ("dup z19.b, -1"); + __asm __volatile ("dup z20.b, -1"); + __asm __volatile ("dup z21.b, -1"); + __asm __volatile ("dup z22.b, -1"); + __asm __volatile ("dup z23.b, -1"); + __asm __volatile ("dup z24.b, -1"); + __asm __volatile ("dup z25.b, -1"); + __asm __volatile ("dup z26.b, -1"); + __asm __volatile ("dup z27.b, -1"); + __asm __volatile ("dup z28.b, -1"); + __asm __volatile ("dup z29.b, -1"); + __asm __volatile ("dup z30.b, -1"); + __asm __volatile ("dup z31.b, -1"); + __asm __volatile ("ptrue p0.d"); + __asm __volatile ("ptrue p1.d"); + __asm __volatile ("ptrue p2.d"); + __asm __volatile ("ptrue p3.d"); + __asm __volatile ("ptrue p4.d"); + __asm __volatile ("ptrue p5.d"); + __asm __volatile ("ptrue p6.d"); + __asm __volatile ("ptrue p7.d"); + __asm __volatile ("ptrue p8.d"); + __asm __volatile ("ptrue p9.d"); + __asm __volatile ("ptrue p10.d"); + __asm __volatile ("ptrue p11.d"); + __asm __volatile ("ptrue p12.d"); + __asm __volatile ("ptrue p13.d"); + __asm __volatile ("ptrue p14.d"); + __asm __volatile ("ptrue p15.d"); + __asm __volatile ("setffr"); +} + +static void +initialize_sve_state_sighandler () +{ + __asm __volatile ("dup z0.b, -2"); + __asm __volatile ("dup z1.b, -2"); + __asm __volatile ("dup z2.b, -2"); + __asm __volatile ("dup z3.b, -2"); + __asm __volatile ("dup z4.b, -2"); + __asm __volatile ("dup z5.b, -2"); + __asm __volatile ("dup z6.b, -2"); + __asm __volatile ("dup z7.b, -2"); + __asm __volatile ("dup z8.b, -2"); + __asm __volatile ("dup z9.b, -2"); + __asm __volatile ("dup z10.b, -2"); + __asm __volatile ("dup z11.b, -2"); + __asm __volatile ("dup z12.b, -2"); + __asm __volatile ("dup z13.b, -2"); + __asm __volatile ("dup z14.b, -2"); + __asm __volatile ("dup z15.b, -2"); + __asm __volatile ("dup z16.b, -2"); + __asm __volatile ("dup z17.b, -2"); + __asm __volatile ("dup z18.b, -2"); + __asm __volatile ("dup z19.b, -2"); + __asm __volatile ("dup z20.b, -2"); + __asm __volatile ("dup z21.b, -2"); + __asm __volatile ("dup z22.b, -2"); + __asm __volatile ("dup z23.b, -2"); + __asm __volatile ("dup z24.b, -2"); + __asm __volatile ("dup z25.b, -2"); + __asm __volatile ("dup z26.b, -2"); + __asm __volatile ("dup z27.b, -2"); + __asm __volatile ("dup z28.b, -2"); + __asm __volatile ("dup z29.b, -2"); + __asm __volatile ("dup z30.b, -2"); + __asm __volatile ("dup z31.b, -2"); + __asm __volatile ("pfalse p0.b"); + __asm __volatile ("pfalse p1.b"); + __asm __volatile ("pfalse p2.b"); + __asm __volatile ("pfalse p3.b"); + __asm __volatile ("pfalse p4.b"); + __asm __volatile ("pfalse p5.b"); + __asm __volatile ("pfalse p6.b"); + __asm __volatile ("pfalse p7.b"); + __asm __volatile ("pfalse p8.b"); + __asm __volatile ("pfalse p9.b"); + __asm __volatile ("pfalse p10.b"); + __asm __volatile ("pfalse p11.b"); + __asm __volatile ("pfalse p12.b"); + __asm __volatile ("pfalse p13.b"); + __asm __volatile ("pfalse p14.b"); + __asm __volatile ("pfalse p15.b"); + __asm __volatile ("setffr"); +} + +/* Set new value for the SVE vector length. + Return the value that was set. */ + +static int +set_vl (int vl) +{ + int rc; + + rc = prctl (PR_SVE_SET_VL, vl, 0, 0, 0); + if (rc < 0) + { + perror ("FAILED to PR_SVE_SET_VL"); + exit (EXIT_FAILURE); + } + + return rc & PR_SVE_VL_LEN_MASK; +} + +static void +sighandler (int sig, siginfo_t *info, void *ucontext) +{ + /* Set vector length to the second value. */ + second_vl = set_vl (second_vl); + initialize_sve_state_sighandler (); + printf ("sighandler: second_vl = %d\n", second_vl); /* Break here. */ +} + +int +main (int argc, char *argv[]) +{ + if (argc != 3) + { + fprintf (stderr, "Usage: %s <first vl> <second vl>\n", argv[0]); + return 1; + } + + int first_vl = atoi (argv[1]); + second_vl = atoi (argv[2]); + + if (first_vl == 0 || second_vl == 0) + { + fprintf (stderr, "Invalid vector length.\n"); + return 1; + } + + /* Set vector length to the first value. */ + first_vl = set_vl (first_vl); + + printf ("main: first_vl = %d\n", first_vl); + + unsigned char buf[256]; + + /* Use an SVE register to make the kernel start saving the SVE bank. */ + asm volatile ("mov z0.b, #255\n\t" + "str z0, %0" + : + : "m" (buf) + : "z0", "memory"); + + initialize_sve_state_main (); + + struct sigaction sigact; + sigact.sa_sigaction = sighandler; + sigact.sa_flags = SA_SIGINFO; + sigaction (SIGUSR1, &sigact, NULL); + + kill (getpid (), SIGUSR1); + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp new file mode 100644 index 0000000..32340bb --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp @@ -0,0 +1,106 @@ +# Copyright 2025 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/>. + +# Exercise unwinding AArch64's SVE registers from a signal frame. + +require allow_aarch64_sve_tests +# Remote targets can't communicate vector length changes to GDB via the RSP. +require !gdb_protocol_is_remote + +set first_vl 0 +set second_vl 0 + +# Find two valid VL values to use in the test. +# The minimum supported VL is 16 bytes, maximum is 256 bytes, and VL can change +# in increments of at least 16 bytes. +for {set i 16} {$i <= 256} {incr i 16} { + if {![aarch64_supports_sve_vl $i]} { + continue + } + + if {$first_vl == 0} { + set first_vl $i + } elseif {$second_vl == 0} { + set second_vl $i + break + } +} + +if {$first_vl == 0 || $second_vl == 0} { + untested "test needs to support at least two vector lengths" + return +} + +standard_testfile +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + [list debug additional_flags=-march=armv9-a]] } { + return +} + +# We want SIGUSR1 to be delivered normally. +gdb_test "handle SIGUSR1 nostop" \ + [multi_line {Signal Stop Print Pass to program Description} \ + {SIGUSR1 No Yes Yes User defined signal 1}] \ + "don't stop for SIGUSR1" + +set linespec ${srcfile}:[gdb_get_line_number "Break here."] +gdb_test_no_output "set args $first_vl $second_vl" + +if ![runto ${linespec}] { + return +} + +set first_vg [expr $first_vl/8] +set second_vg [expr $second_vl/8] + +gdb_test "print \$vg" ". = $second_vg" "vg was changed" + +for {set row 0} {$row < 32} {incr row} { + set register_name "\$z${row}\.b\.u" + gdb_test "print sizeof $register_name" " = $second_vl" \ + "size of $register_name in the signal handler" + gdb_test "print $register_name" ". = \\{254 <repeats $second_vl times>\\}" \ + "$register_name contents in signal handler" +} + +for {set row 0} {$row < 16} {incr row} { + set register_name "\$p${row}" + gdb_test "print $register_name" ". = \\{(0, ){[expr $second_vl/8 - 1]}0\\}" \ + "$register_name contents in signal handler" +} +gdb_test "print \$ffr" ". = \\{(255, ){[expr $second_vl/8 - 1]}255\\}" \ + "ffr contents in signal handler" + +gdb_test "frame function main" \ + [multi_line "#$decimal $hex in main \[^\r\n\]+" \ + "$decimal\[ \t\]+kill \\(getpid \\(\\), SIGUSR1\\);"] + +gdb_test "print \$vg" ". = $first_vg" "vg was correctly unwound" + +for {set row 0} {$row < 32} {incr row} { + set register_name "\$z${row}\.b\.u" + gdb_test "print sizeof $register_name" " = $first_vl" \ + "size of $register_name was correctly unwound" + gdb_test "print $register_name" ". = \\{255 <repeats $first_vl times>\\}" \ + "$register_name contents were correctly unwound" +} + +for {set row 0} {$row < 16} {incr row} { + set register_name "\$p${row}" + gdb_test "print $register_name" ". = \\{(1, ){[expr $first_vl/8 - 1]}1\\}" \ + "$register_name contents were correctly unwound" +} +gdb_test "print \$ffr" ". = \\{(255, ){[expr $first_vl/8 - 1]}255\\}" \ + "ffr contents were correctly unwound" diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index e1c996e..8634668 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -744,6 +744,12 @@ proc test_print_char_arrays {} { gdb_test_no_output "set print address off" "address off char arrays" } +proc test_print_arrays_negative {} { + # Check whether correct error messages are printed + gdb_test "p 1 == { }" "size of the array element must not be zero" + gdb_test "p 1 == { 1, 'a' }" "array elements must all be the same size" +} + proc test_print_nibbles {} { gdb_test_no_output "set print nibbles on" foreach lang_line { @@ -1235,6 +1241,7 @@ test_print_int_arrays test_print_typedef_arrays test_artificial_arrays test_print_char_arrays +test_print_arrays_negative test_print_nibbles # We used to do the runto main here. test_print_string_constants diff --git a/gdb/valops.c b/gdb/valops.c index 09af0ae..1b63343 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1695,6 +1695,9 @@ value_array (int lowbound, gdb::array_view<struct value *> elemvec) /* Validate that the bounds are reasonable and that each of the elements have the same size. */ + if (elemvec.empty ()) + error (_("size of the array element must not be zero")); + typelength = type_length_units (elemvec[0]->enclosing_type ()); for (struct value *other : elemvec.slice (1)) { |