# Copyright 1998, 2005, 2007, 2008, 2009, 2010, 2011 # 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 . load_lib "trace-support.exp" set testfile "unavailable" set srcfile ${testfile}.cc set executable $testfile set binfile $objdir/$subdir/$executable if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ executable {debug nowarnings c++}] != "" } { untested unavailable.exp return -1 } set ws "\[\r\n\t \]+" set cr "\[\r\n\]+" # # Utility procs # proc prepare_for_trace_test {} { global executable clean_restart $executable runto_main gdb_test "break begin" ".*" "" gdb_test "break end" ".*" "" } proc run_trace_experiment { test_func } { global gdb_prompt gdb_test "continue" \ ".*Breakpoint \[0-9\]+, begin .*" \ "advance to begin" gdb_test_no_output "tstart" "start trace experiment" gdb_test "continue" \ "Continuing.*Breakpoint \[0-9\]+, end.*" \ "run trace experiment" gdb_test "tstop" \ "\[\r\n\]+" \ "stop trace experiment" gdb_test "tfind start" \ "#0 $test_func .*" \ "tfind test frame" } # # Test procs # proc gdb_collect_globals_test { } { global ws global cr global gdb_prompt global hex global pf_prefix set old_pf_prefix $pf_prefix set pf_prefix "$pf_prefix collect globals:" prepare_for_trace_test set testline [gdb_get_line_number "set globals_test_func tracepoint here"] gdb_test "trace $testline" \ "Tracepoint \[0-9\]+ at .*" \ "set tracepoint" gdb_trace_setactions "define actions" \ "" \ "collect struct_b.struct_a.array\[2\]" "^$" \ "collect struct_b.struct_a.array\[100\]" "^$" \ \ "collect a" "^$" \ "collect c" "^$" \ \ "collect tarray\[0\].a" "^$" \ "collect tarray\[1\].a" "^$" \ "collect tarray\[3\].a" "^$" \ "collect tarray\[3\].b" "^$" \ "collect tarray\[4\].b" "^$" \ "collect tarray\[5\].b" "^$" \ \ "collect g_string_p" "^$" \ "collect g_string_partial\[1\]" "^$" \ "collect g_string_partial\[2\]" "^$" \ \ "collect g_structref_p" "^$" # Begin the test. run_trace_experiment globals_test_func gdb_test "print globalc" " = " gdb_test "print globali" " = " gdb_test "print globalf" " = " gdb_test "print globald" " = " gdb_test "print globalstruct.memberc" " = " gdb_test "print globalstruct.memberi" " = " gdb_test "print globalstruct.memberf" " = " gdb_test "print globalstruct.memberd" " = " gdb_test "print globalstruct" \ " = {memberc = , memberi = , memberf = , memberd = }" gdb_test "print globalp == &globalstruct" \ "value is not available" \ "can't compare using non collected global pointer" gdb_test "print globalarr\[1\]" " = " gdb_test "print globalarr\[2\]" " = " gdb_test "print globalarr\[3\]" " = " gdb_test "print struct_b" \ " = {d = , ef = , struct_a = {a = , b = , array = {, , -1431655766, , -1431655766, }, ptr = , bitfield = }, s = , static static_struct_a = {a = , b = , array = { }, ptr = , bitfield = }, string = }" gdb_test "print /x struct_b" \ " = {d = , ef = , struct_a = {a = , b = , array = {, , 0xaaaaaaaa, , 0xaaaaaaaa, }, ptr = , bitfield = }, s = , static static_struct_a = {a = , b = , array = { }, ptr = , bitfield = }, string = }" gdb_test "print /x struct_b.struct_a" \ " = {a = , b = , array = {, , 0xaaaaaaaa, , 0xaaaaaaaa, }, ptr = , bitfield = }" gdb_test "print /x struct_b.struct_a.array" \ " = {, , 0xaaaaaaaa, , 0xaaaaaaaa, }" gdb_test "print /x struct_b.struct_a.array\[0\]" " = " gdb_test "print /x struct_b.struct_a.array\[2\]" " = 0xaaaaaaaa" # Check the target doesn't overcollect. GDB used to merge memory # ranges to collect if they were close enough (collecting the hole # as well), but does not do that anymore. It's plausible that a # target may do this on its end, but as of this writing, no known # target does it. gdb_test "print {a, b, c}" \ " = \\{1, , 3\\}" \ "No overcollect of almost but not quite adjacent memory ranges" # Check isn't confused with 0 in array element repetitions gdb_test_no_output "set print repeat 1" gdb_test "print /x tarray" \ " = \{\{a = 0x0, b = \} , \{a = , b = \}, \{a = 0x0, b = 0x0\}, \{a = , b = 0x0\} , \{a = , b = \} \}" \ " is not the same as 0 in array element repetitions" gdb_test_no_output "set print repeat 10" # Check that value repeat handles unavailable-ness. gdb_test "print *tarray@3" " = \\{\\{a = 0, b = \\}, \\{a = 0, b = \\}, \\{a = , b = \\}\\}" # Static fields gdb_test "print struct_b.static_struct_a" \ " = {a = , b = , array = { }, ptr = , bitfield = }" # Bitfields gdb_test "print struct_b.struct_a.bitfield" " = " # References gdb_test "print g_int" " = " gdb_test "print g_ref" \ "\\(int &\\) @$hex: " \ "global reference shows address but not value" gdb_test "print *&g_ref" \ "\\$\[0-9\]+ = $cr" \ "referenced integer was not collected (taking address of reference)" gdb_test "print *g_structref_p" \ " = {d = , ref = }" # Strings # Const string is always available, even when not collected. gdb_test "print g_const_string" \ " = \"hello world\"$cr" \ "non collected const string is still printable" gdb_test "print g_string_p" \ " = $hex \"hello world\"" \ "printing constant string through collected pointer" gdb_test "print g_string_unavail" \ " = \{ \}" \ "printing non collected string" # Incomplete strings print as an array. gdb_test "print g_string_partial" \ "\\$\[0-9\]+ = \{, 101 'e', 108 'l', , , , , , , , , \}" \ "printing partially collected string" # It is important for this test that the last examined value is # , to exercise the case of the $__ convenience # variable being set to without error. set msg "examining partially collected object" gdb_test_multiple "x /10x &struct_b" "$msg" { -re "$hex :${ws}${ws}${ws}${ws}$cr$hex :${ws}${ws}${ws}0xaaaaaaaa${ws}$cr$hex :${ws}${ws}$cr$gdb_prompt $" { pass "$msg" } -re "value is not available" { fail "$msg" } } gdb_test "p \$__" " = " "last examined value was " # This tests that building the array does not require accessing # g_int's contents. gdb_test "print { 1, g_int, 3 }" \ " = \\{1, , 3\\}" \ "build array from unavailable value" # Note, depends on previous test. gdb_test "print \$\[1\]" \ " = " \ "subscript a non-memory rvalue array, accessing an unvailable element" # Access a field of a non-lazy value, making sure the # unavailable-ness is propagated. History values are easy # non-lazy values, so use those. The first test just sets up for # the second. gdb_test "print g_smallstruct" " = \\{member = \\}" gdb_test "print \$.member" " = " # Cast to baseclass, checking the unavailable-ness is propagated. gdb_test "print (small_struct) g_smallstruct_b" " = \\{member = \\}" # Same cast, but starting from a non-lazy, value. gdb_test "print g_smallstruct_b" " = \\{ = \\{member = \\}, \\}" gdb_test "print (small_struct) \$" " = \\{member = \\}" gdb_test_no_output "set print object on" # With print object on, printing a pointer may need to fetch the # pointed-to object, to check its run-time type. Make sure that # fails gracefully and transparently when the pointer itself is # unavailable. gdb_test "print virtualp" " = \\(Virtual \\*\\) " gdb_test_no_output "set print object off" gdb_test "tfind none" \ "#0 end .*" \ "cease trace debugging" set pf_prefix $old_pf_prefix } proc gdb_trace_collection_test {} { gdb_collect_globals_test } clean_restart $executable runto_main # We generously give ourselves one "pass" if we successfully # detect that this test cannot be run on this target! if { ![gdb_target_supports_trace] } then { pass "Current target does not support trace" return 1; } # Body of test encased in a proc so we can return prematurely. gdb_trace_collection_test # Finished! gdb_test "tfind none" ".*" ""