# Copyright (C) 2002 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Please email any bugs, comments, and/or additions to this file to: # bug-gdb@prep.ai.mit.edu # Test Apple local varobj features. # # Written by Jason Molenda (jmolenda@apple.com) # Initially, make use of the -stack-list-locals feature where # varobjs are created for all locals, and variables in a block # below the current block may not yet be in scope. if [target_info exists noobjc64] { verbose "Disable Objective-C tests on 64-bit PowerPC." return } load_lib mi-support.exp set MIFLAGS "-i=mi1" gdb_exit if [mi_gdb_start] { continue } set testfile "objc-prog" set srcfile ${testfile}.m set binfile ${objdir}/${subdir}/${testfile} if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DFAKEARGV\ -framework\ Foundation}] != "" } { gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." } mi_delete_breakpoints mi_gdb_reinitialize_dir $srcdir/$subdir mi_gdb_load ${binfile} send_gdb "100-break-insert randomFunc\n" gdb_expect { -re "100\\^done,bkpt=\{number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\".*randomFunc.*\",file=\".*$srcfile\",line=\"($decimal)\",shlib=\"$binfile\",times=\"0\"\}\[\r\n\]+$mi_gdb_prompt$" { set randomFunc_line_number $expect_out(1,string) pass "break-insert randomFunc operation" } -re ".*$mi_gdb_prompt$" { set randomFunc_line_number -1 fail "break-insert randomFunc operation" } timeout { fail "(timeout) break-insert randomFunc operation" } } send_gdb "200-break-insert blocky\n" gdb_expect { -re "200\\^done,bkpt=\{number=\"2\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"($hex)\",func=\"blocky\",file=\".*$srcfile\",line=\"($decimal)\",shlib=\"$binfile\",times=\"0\"\}\[\r\n\]+$mi_gdb_prompt$" { set blocky_address $expect_out(1,string) set blocky_line_number $expect_out(2,string) pass "break-insert blocky operation" } -re ".*$mi_gdb_prompt$" { set blocky_line_number -1 fail "break-insert blocky operation" } timeout { fail "(timeout) break-insert blocky operation" } } send_gdb "100-break-insert main\n" gdb_expect { -re "100\\^done,bkpt=\{number=\"3\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\"main\",file=\".*$srcfile\",line=\"($decimal)\",shlib=\"$binfile\",times=\"0\"\}\[\r\n\]+$mi_gdb_prompt$" { set main_line_number $expect_out(1,string) pass "break-insert main operation" } -re ".*$mi_gdb_prompt$" { set main_line_number -1 fail "break-insert main operation" } timeout { fail "(timeout) break-insert main operation" } } mi_run_cmd # The running part has been checked already by mi_run_cmd mi_get_bp_stopped "3" "\[01\]" "" "main" "$srcfile" ".*" "run to main" # Create a varobj for the currently uninitialized "object" variable. Then we will # make sure it's type change is picked up properly when we make it a MyClass, and # later when we make it a MyChild. mi_gdb_test "80-var-create objectVar * object" \ {80\^done,name="objectVar",numchild="1",type="(id|struct objc_object \*)",typecode="PTR",dynamic_type="",resolved_type="(id|struct objc_object \*)",in_scope="true",block_start_addr=".*",block_end_addr=".*"} \ "created varobj for uninitialized object - no dynamic type - no error" # Run to randomFunc twice, once as MyClass, once as MyChild, and make sure the dynamic # type and the ivars are correct. Each time, return to main to test that objectVar is okay. mi_continue_to 1 {-\[MyClass randomFunc\]} ".*" $srcfile $randomFunc_line_number "continue to randomFunc" mi_gdb_test "101-var-create firstSelf * self" \ {101\^done,name="firstSelf",numchild="3",type="MyClass \*",typecode="PTR",dynamic_type="MyClass \*",resolved_type="MyClass \*",in_scope="true",block_start_addr=".*",block_end_addr=".*"} "randomFunc called for MyClass object" mi_gdb_test "102-var-delete firstSelf" \ {102\^done,ndeleted="1"} "Delete firstSelf" mi_finish_to main ".*" "$srcfile" ".*" ".*" {\(struct objc_object \*\) 0x.*} "finished from randomFunc first time" mi_gdb_test "103-var-update objectVar" \ {103\^done,changelist=\[varobj={name="objectVar",in_scope="true",type_changed="true",new_type="(id|struct objc_object \*)",new_dynamic_type="MyClass \*",new_resolved_type="(id|struct objc_object \*)",new_typecode="PTR",new_num_children="3"}\]} \ "Update objectVar as MyClass" mi_gdb_test "104-var-list-children objectVar" \ {104\^done,numchild="3",children=\[child={name="objectVar.(isa|NSObject)",exp="(isa|NSObject)",numchild="(0|1)",type="(Class|NSObject|struct objc_class \*)",typecode="(PTR|STRUCT)",dynamic_type="",resolved_type="(Class|NSObject|struct objc_class \*)"},child={name="objectVar.object",exp="object",numchild="(1|3)",type="(id|NSObject|struct objc_object \*)",typecode="PTR",dynamic_type="(class NSConstantString|NSCFString) \*",resolved_type="(id|NSObject|struct objc_object \*)"},child={name="objectVar._object2",exp="_object2",numchild="(3|1)",type="(id|struct objc_object \*)",typecode="PTR",dynamic_type="(class NSConstantString|NSCFString) \*",resolved_type="(id|struct objc_object \*)"}\]} "List objectVar's children as MyClass" mi_continue_to 1 {-\[MyClass randomFunc\]} ".*" $srcfile $randomFunc_line_number "continue to randomFunc" mi_gdb_test "105-var-create secondSelf * self" \ {105\^done,name="secondSelf",numchild="2",type="MyClass \*",typecode="PTR",dynamic_type="MyChild \*",resolved_type="MyClass \*",in_scope="true",block_start_addr=".*",block_end_addr=".*"} "randomFunc called for MyChild object" mi_gdb_test "106-var-list-children secondSelf" \ {106\^done,numchild="2",children=\[child={name="secondSelf.MyClass",exp="MyClass",numchild="3",type="MyClass",typecode="STRUCT",dynamic_type="",resolved_type="MyClass"},child={name="secondSelf.some_val",exp="some_val",numchild="0",type="int",typecode="INT",dynamic_type="",resolved_type="int"}\]} "List secondSelf's children" mi_gdb_test "107-var-evaluate-expression secondSelf.some_val" \ {107\^done,value="5"} "secondSelf.some_value is 5" mi_gdb_test "108-var-delete secondSelf" \ {108\^done,ndeleted="3"} "Delete secondSelf" mi_finish_to main ".*" "$srcfile" ".*" ".*" {\(struct objc_object \*\) 0x.*} "finished from randomFunc second time" mi_gdb_test "109-var-update objectVar" \ {109\^done,changelist=\[varobj={name="objectVar",in_scope="true",type_changed="true",new_type="(id|struct objc_object \*)",new_dynamic_type="MyChild \*",new_resolved_type="(id|struct objc_object \*)",new_typecode="PTR",new_num_children="2"}\]} \ "Update objectVar as MyChild" mi_gdb_test "110-var-list-children objectVar" \ {110\^done,numchild="2",children=\[child={name="objectVar.MyClass",exp="MyClass",numchild="3",type="MyClass",typecode="STRUCT",dynamic_type="",resolved_type="MyClass"},child={name="objectVar.some_val",exp="some_val",numchild="0",type="int",typecode="INT",dynamic_type="",resolved_type="int"}\]} "List objectVar's children" mi_gdb_test "111-var-evaluate-expression objectVar.some_val" \ {111\^done,value="5"} "objectVar.some_value is 5" mi_gdb_test "112-var-delete objectVar" \ {112\^done,ndeleted="3"} "Delete objectVar" mi_continue_to "2" "blocky" ".*" "$srcfile" $blocky_line_number "continue to blocky" # Normal stack-list-locals behavior mi_gdb_test "120-stack-list-locals 0 0" "120\\^done,locals=\\\[\{name=\"outer\"\}\\\]" "normal stack-list-locals behavior" mi_gdb_test "121-stack-list-locals 0" "121\\^done,locals=\\\[\{name=\"outer\"\}\\\]" "normal stack-list-locals behavior #2" # Test local extension of -stack-list-locals which works over all blocks. mi_gdb_test "122-stack-list-locals 0 1" "122\\^done,locals=\\\[\{name=\"outer\"\},\{name=\"inner1\"\},\{name=\"inner2\"\},\{name=\"outer\"\},\{name=\"flooooo\"\},\{name=\"chhhhh\"\}\\\]" "list locals in all subblocks" mi_next "step forward" mi_next "step forward again" mi_gdb_test "123-stack-list-locals 0" "123\\^done,locals=\\\[\{name=\"inner1\"\},\{name=\"inner2\"\},\{name=\"outer\"\}\\\]" # Apple local behavior - -stack-list-locals's first arg can be '2', in which # case varobjs are created for all loals. mi_gdb_test "124-stack-list-locals 2" \ "124\\^done,locals=\\\[varobj=\{exp=\"inner1\",value=\"97 'a'\",name=\"var1\",numchild=\"0\",type=\"char\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"char\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"inner2\",value=\".*\",name=\"var2\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"outer\",value=\"5\",name=\"var3\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\\}\\\]" \ "create varobjs for all locals in current scope" # Note the importance of var7 - the second 'outer' variable -- its in_scope # value is 'false'. God help me, this may be the only test of that # functionality we have in the whole testsuite. mi_gdb_test "125-stack-list-locals 2 1" \ "125\\^done,locals=\\\[varobj=\{exp=\"outer\",value=\"5\",name=\"var4\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\\},varobj=\{exp=\"inner1\",value=\"97 'a'\",name=\"var5\",numchild=\"0\",type=\"char\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"char\",in_scope=\"true\"\,block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"inner2\",value=\".*\",name=\"var6\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\"\,block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"outer\",value=\".*\",name=\"var7\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"false\",block_start_addr=\".*\",block_end_addr=\".*\"\\},varobj=\{exp=\"flooooo\",value=\".*\",name=\"var8\",numchild=\"0\",type=\"float\",typecode=\"FLT\",dynamic_type=\"\",resolved_type=\"float\",in_scope=\"false\"\,block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"chhhhh\",value=\".*\",name=\"var9\",numchild=\"0\",type=\"char\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"char\",in_scope=\"false\",block_start_addr=\".*\",block_end_addr=\".*\"\\}\\\]" \ "create varobjs for all blocks visible" # The breakpoint on blocky() is on the first line of code in the func; # this second breakpoint should be about seven statements farther down - # on the line that reads "inner2 = 99". set second_blocky_bp [expr $blocky_line_number + 7] mi_gdb_test "130-break-insert $second_blocky_bp" \ "130\\^done,bkpt=\{number=\"4\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\"blocky\",file=\".*$srcfile\",line=\"$second_blocky_bp\",shlib=\"$binfile\",times=\"0\"\}" \ "break-insert operation 4" mi_continue_to "4" "blocky" ".*" "$srcfile" "$second_blocky_bp" "continue to line $second_blocky_bp" mi_gdb_test "131-var-update *" "131\\^done,changelist=\\\[varobj=\{name=\"var5\",in_scope=\"true\",type_changed=\"false\"\},varobj=\{name=\"var1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" "simple var-update change" # test variable scoping for -var-create - +XXXX # where XXXX can be: # address: +0x11223344 # file:line: +file.ext:12 set outer_line_number 1 mi_gdb_test "140-var-create outer_at_line_$outer_line_number +$srcfile:$outer_line_number outer" \ "140\\^done,name=\"outer_at_line_$outer_line_number\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"" \ "140 var-create for outer where file:line is $srcfile:$outer_line_number" mi_gdb_test "141-var-evaluate-expression outer_at_line_$outer_line_number" \ "141\\^done,value=\"15\"" \ "141 var-evaluate-expression for outer where file:line is $srcfile:$outer_line_number" set outer_line_number $blocky_line_number mi_gdb_test "142-var-create outer_at_line_$outer_line_number +$srcfile:$outer_line_number outer" \ "142\\^done,name=\"outer_at_line_$outer_line_number\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"" \ "142 var-create for outer where file:line is $srcfile:$outer_line_number" mi_gdb_test "143-var-evaluate-expression outer_at_line_$outer_line_number" \ "143\\^done,value=\"5\"" \ "143 var-evaluate-expression for outer where file:line is $srcfile:$outer_line_number" # test invalid line number of zero which should default to the global value mi_gdb_test "144-var-create outer0 +$srcfile:0 outer" \ "144\\^done,name=\"outer0\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\"no block\",block_end_addr=\"no block\"" \ "144 var-create for outer where file:line is $srcfile:0 (invalid line number of zero)" mi_gdb_test "145-var-evaluate-expression outer0" \ "145\\^done,value=\"15\"" \ "145 var-evaluate-expression for outer where file:line is $srcfile:0" # test invalid line number that is too large for the file which should default to the global value mi_gdb_test "146-var-create outer999999 +$srcfile:999999 outer" \ "146\\^done,name=\"outer999999\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\"no block\",block_end_addr=\"no block\"" \ "146 var-create for outer where file:line is $srcfile:999999 (invalid line number of 999999)" mi_gdb_test "147-var-evaluate-expression outer999999" \ "147\\^done,value=\"15\"" \ "147 var-evaluate-expression for outer where file:line is $srcfile:999999" # test using an invalid file which should end up just use the selected frame # to evaluate the variable mi_gdb_test "148-var-create invalid_file_var +invalid_file.c:33 outer" \ {148\^error,msg="mi_cmd_var_create: invalid file and line in block expression: \\"\+invalid_file.c:33\\""} \ "148 var-create for outer where file:line is invalid_file.c:33 (invalid file)" # test using the valid address for the block function which should pick up the first local value of 5 mi_gdb_test "149-var-create outer_addr$blocky_address +$blocky_address outer" \ "149\\^done,name=\"outer_addr$blocky_address\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"" \ "149 var-create for outer where address is $blocky_address (address of blocky function)" mi_gdb_test "150-var-evaluate-expression outer_addr$blocky_address" \ "150\\^done,value=\"5\"" \ "150 var-evaluate-expression for outer at address $blocky_address" # test using an invalid address for the block address which needs to fail gracefully mi_gdb_test "151-var-create outer_addr0xffffffff +0xffffffff outer" \ "151\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \ "151 var-create using +0xffffffff (invalid address)" mi_finish_to "main" ".*" "$srcfile" ".*" ".*" ".*" "back to main" # Now make sure all the varobj's went away - mi_gdb_test "132-var-update *" "132\\^done,changelist=\\\[varobj=\{name=\"outer_addr$blocky_address\",in_scope=\"false\"\},varobj=\{name=\"outer_at_line_122\",in_scope=\"false\"\},varobj=\{name=\"var6\",in_scope=\"false\"\},varobj=\{name=\"var5\",in_scope=\"false\"\},varobj=\{name=\"var4\",in_scope=\"false\"\},varobj=\{name=\"var3\",in_scope=\"false\"\},varobj=\{name=\"var2\",in_scope=\"false\"\},varobj=\{name=\"var1\",in_scope=\"false\"\}\\\]" "all varobjs go out of scope" mi_gdb_exit return 0