# Copyright 2014-2024 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 compile-support.exp
standard_testfile .c compile-shlib.c compile-constvar.S compile-nodebug.c
require is_c_compiler_gcc
set options {additional_flags=-g3}
if { ![is_x86_64_m64_target] } {
verbose "Skipping x86_64 LOC_CONST test."
set srcfile3 ""
}
set srcfilesoptions [list ${srcfile} ${options}]
if { $srcfile3 != "" } {
lappend srcfilesoptions $srcfile3 ${options}
}
lappend srcfilesoptions $srcfile4 "nodebug"
if { [eval build_executable_from_specs ${testfile}.exp $testfile {$options} ${srcfilesoptions}] } {
return -1
}
clean_restart ${testfile}
#
# Test command without an running inferior.
#
gdb_test "compile code int i=2;" \
"The program must be running for the compile command to work.*" \
"test compile code command without running inferior"
gdb_test "compile int i=2;" \
"The program must be running for the compile command to work.*" \
"test compile command without running inferior"
gdb_test "compile file -r ${srcdir}/${subdir}/${testfile}-mod.c" \
"The program must be running for the compile command to work.*" \
"test compile file command without running inferior"
if ![runto_main] {
return -1
}
if {[skip_compile_feature_untested]} {
return -1
}
#
# Test delimiter for code, and arguments.
#
gdb_test_no_output "compile -- f = 10" \
"test abbreviations and code delimiter"
gdb_test "compile f = 10;" "^Junk after filename \"=\": 10;" \
"Test abbreviations and code collision"
gdb_test_no_output "compile -r -- void _gdb_expr(){int i = 5;}" \
"test delimiter with -r"
gdb_test_no_output "compile -raw -- void _gdb_expr(){int i = 5;}" \
"test delimiter with -raw"
gdb_test "compile -- -r void _gdb_expr(){int i = 5;}" \
".* error: 'r' undeclared \\(first use in this function\\).*" \
"test delimiter with -r after it"
gdb_test "p globalvar" " = 10" "expect 10"
gdb_test_no_output "compile code globalvar = 11" \
"set variable without trailing semicolon"
gdb_test "p globalvar" " = 11" "check variable without trailing semicolon"
gdb_test_no_output "compile code globalvar = SOME_MACRO;" \
"set variable from macro"
gdb_test "p globalvar" " = 23" "expect 23"
gdb_test_no_output "compile code globalvar = ARG_MACRO(0, 0);" \
"set variable from function-like macro"
gdb_test "p globalvar" " = -1" "expect -1"
gdb_test_no_output "compile code globalvar = 42;" "set variable"
gdb_test "p globalvar" " = 42" "expect 42"
gdb_test_no_output "compile code globalvar *= 2;" "modify variable"
gdb_test "p globalvar" " = 84" "expect 84"
gdb_test_multiple "compile code" "compile code multiline 1" { -re "\r\n>$" {} }
gdb_test_multiple "globalvar = 10;" "compile code multiline 2" { -re "\r\n>$" {} }
gdb_test_multiple "globalvar *= 2;" "compile code multiline 3" { -re "\r\n>$" {} }
gdb_test_no_output "end" "compile code multiline 4"
gdb_test "p globalvar" " = 20" "expect 20"
gdb_test_no_output "compile file -r ${srcdir}/${subdir}/${testfile}-mod.c" \
"use external source file"
gdb_test "p globalvar" " = 7" "expect 7"
gdb_test_no_output "compile code func_static (2);" "call static function"
gdb_test "p globalvar" " = 9" "expect 9"
gdb_test_no_output "compile code func_global (1);" "call global function"
gdb_test "p globalvar" " = 8" "expect 8"
gdb_test_no_output \
"compile code globalvar = (sizeof (ulonger) == sizeof (long))" \
"compute size of ulonger"
gdb_test "p globalvar" " = 1" "check size of ulonger"
gdb_test_no_output \
"compile code globalvar = (sizeof (longer) == sizeof (long))" \
"compute size of longer"
gdb_test "p globalvar" " = 1" "check size of longer"
gdb_test_no_output "compile code globalvar = MINUS_1"
gdb_test "p globalvar" " = -1" "check MINUS_1"
gdb_test_no_output "compile code globalvar = static_local"
gdb_test "p globalvar" " = 77000" "check static_local"
gdb_test_no_output "compile code static int staticvar = 5; intptr = &staticvar" \
"do not keep jit in memory"
gdb_test "p *intptr" "Cannot access memory at address 0x\[0-9a-f\]+" "expect no 5"
gdb_test "compile code func_doesnotexist ();" "warning: Could not find symbol \"func_doesnotexist\" for .*"
gdb_test "compile code *(volatile int *) 0 = 0;" \
"The program being debugged was signaled while in a function called from GDB\\.\r\nGDB remains in the frame where the signal was received\\.\r\n.*" \
"compile code segfault first"
gdb_test "bt" [multi_line \
"#0 ($hex in )?_gdb_expr .*" \
"#1 " \
"#2 .*" \
]
set test "p/x \$pc"
set infcall_pc 0
gdb_test_multiple $test $test {
-re " = (0x\[0-9a-f\]+)\r\n$gdb_prompt $" {
set infcall_pc $expect_out(1,string)
pass $test
}
}
gdb_test "info sym $infcall_pc" "\r\n_gdb_expr .*" "info sym found"
gdb_test "return" "\r\n#0 main .*" "return" \
"Make _gdb_expr return now\\? \\(y or n\\) " "y"
gdb_test "info sym $infcall_pc" "\r\nNo symbol matches .*" "info sym not found"
gdb_test_no_output "set unwind-on-signal on"
gdb_test "compile code *(volatile int *) 0 = 0;" \
[multi_line \
"The program being debugged received signal SIGSEGV, Segmentation fault" \
"while in a function called from GDB\\. GDB has restored the context" \
"to what it was before the call\\. To change this behavior use" \
"\"set unwind-on-signal off\"\\. Evaluation of the expression containing" \
"the function \\(_gdb_expr\\) will be abandoned\\."] \
"compile code segfault second"
gdb_breakpoint [gdb_get_line_number "break-here"]
gdb_continue_to_breakpoint "break-here" ".* break-here .*"
gdb_test "p localvar" " = 50" "expect localvar 50"
gdb_test_no_output "compile code localvar = 12;" "set localvar"
gdb_test "p localvar" " = 12" "expect 12"
gdb_test_no_output "compile code localvar *= 2;" "modify localvar"
gdb_test "p localvar" " = 24" "expect 24"
gdb_test_no_output "compile code localvar = shadowed" \
"test shadowing"
gdb_test "p localvar" " = 52" "expect 52"
gdb_test_no_output "compile code localvar = externed"
gdb_test "p localvar" " = 7" "test extern in inner scope"
gdb_test_no_output "compile code vla\[2\] = 7"
gdb_test "p vla\[2\]" " = 7"
gdb_test_no_output \
"compile code localvar = (sizeof (vla) == bound * sizeof (vla\[0\]))"
gdb_test "p localvar" " = 1"
#
# Test setting fields and also many different types.
#
set skip_struct_object 0
set test "compile code struct_object.selffield = &struct_object"
gdb_test_multiple $test $test {
-re "^$test\r\n$gdb_prompt $" {
pass "$test"
}
-re " error: Unexpected type id from GCC, check you use recent enough GCC\\.\r\n.*\r\n$gdb_prompt $" {
xfail "$test (PR compile/18202)"
# All following tests will break with the same error message.
set skip_struct_object 1
}
}
if {$skip_struct_object} {
untested "all struct_object tests"
} else {
gdb_test "print struct_object.selffield == &struct_object" " = 1"
gdb_test_no_output "compile code struct_object.charfield = 1"
gdb_test "print struct_object.charfield" " = 1 '\\\\001'"
gdb_test_no_output "compile code struct_object.ucharfield = 1"
gdb_test "print struct_object.ucharfield" " = 1 '\\\\001'"
foreach {field value} {
shortfield -5
ushortfield 5
intfield -7
uintfield 7
bitfield 2
longfield -9
ulongfield 9
enumfield ONE
floatfield 1
doublefield 2
} {
gdb_test_no_output "compile code struct_object.$field = $value"
gdb_test "print struct_object.$field" " = $value"
}
gdb_test_no_output "compile code struct_object.arrayfield\[2\] = 7"
gdb_test "print struct_object.arrayfield" \
" = \\{0, 0, 7, 0, 0\\}"
gdb_test_no_output "compile code struct_object.complexfield = 7 + 5i"
gdb_test "print struct_object.complexfield" " = 7 \\+ 5i"
gdb_test_no_output "compile code struct_object.boolfield = 1"
gdb_test "print struct_object.boolfield" " = true"
gdb_test_no_output "compile code struct_object.vectorfield\[2\] = 7"
gdb_test "print struct_object.vectorfield" \
" = \\{0, 0, 7, 0\\}"
}
gdb_test_no_output "compile code union_object.typedeffield = 7"
gdb_test "print union_object.typedeffield" " = 7"
gdb_test "print union_object.intfield" " = 7"
# LOC_UNRESOLVED tests.
gdb_test "print unresolved" " = 20"
gdb_test_no_output "compile code globalvar = unresolved;"
gdb_test "print globalvar" " = 20" "print unresolved value"
# Test shadowing with global and static variables.
gdb_test_no_output "compile code globalshadow += 1;"
gdb_test "print globalshadow" " = 101"
gdb_test_no_output "compile code extern int globalshadow; globalshadow += 5;"
gdb_test "print 'compile.c'::globalshadow" " = 15"
gdb_test "print globalshadow" " = 101" "print globalshadow second time"
gdb_test_no_output "compile code staticshadow += 2;"
gdb_test "print staticshadow" " = 202"
# "extern int staticshadow;" cannot access static variable.
# Raw code cannot refer to locals.
# As it references global variable we need the #pragma.
# For #pragma we need multiline input.
gdb_test_multiple "compile code -r" "compile code -r multiline 1" { -re "\r\n>$" {} }
gdb_test_multiple "#pragma GCC user_expression" "compile code -r multiline 2" { -re "\r\n>$" {} }
gdb_test_multiple "void _gdb_expr(void) { globalshadow = 77000; }" "compile code -r multiline 3" { -re "\r\n>$" {} }
gdb_test_no_output "end" "compile code -r multiline 4"
gdb_test "print 'compile.c'::globalshadow" " = 77000" \
"check globalshadow with -r"
# Test GOT vs. resolving jit function pointers.
gdb_test_no_output "compile -raw -- int func(){return 21;} void _gdb_expr(){ void abort (void); int (*funcp)()=func; if (funcp()!=21) abort(); }" \
"pointer to jit function"
#
# Test the case where the registers structure would not normally have
# any fields.
#
gdb_breakpoint [gdb_get_line_number "no_args_or_locals breakpoint"]
gdb_continue_to_breakpoint "no_args_or_locals"
gdb_test_no_output "compile code globalvar = 77;" "set variable to 77"
gdb_test "p globalvar" " = 77" "expect 77"
# Test reference to minimal_symbol, not (full) symbol.
gdb_test "compile code globalvar = func_nodebug (75);" \
"warning: function has unknown return type; assuming int" \
"call func_nodebug"
gdb_test "p globalvar" " = -75" "expect -75"
gdb_test \
"compile code int (*funcp) (int) = (int (*) (int)) func_nodebug; globalvar = funcp (76);" \
"warning: function has unknown return type; assuming int" \
"call func_nodebug indirectly"
gdb_test "p globalvar" " = -76" "expect -76"
# Test compiled module memory protection.
gdb_test_no_output "set debug compile on"
gdb_test "compile code static const int readonly = 1; *(int *) &readonly = 2;" \
[multi_line \
"The program being debugged received signal SIGSEGV, Segmentation fault" \
"while in a function called from GDB\\. GDB has restored the context" \
"to what it was before the call\\. To change this behavior use" \
"\"set unwind-on-signal off\"\\. Evaluation of the expression containing" \
"the function \\(_gdb_expr\\) will be abandoned\\."]
gdb_test_no_output "set debug compile off"
#
# Some simple coverage tests.
#
gdb_test "show debug compile" "Compile debugging is .*"
gdb_test "show compile-args" \
"Compile command command-line arguments are .*"
gdb_test "compile code -z" "Unrecognized option at: -z"
gdb_test "set lang rust" \
"Warning: the current language does not match this frame."
gdb_test "compile code globalvar" "No compiler support for language rust\\."
gdb_test_no_output "set lang auto"
gdb_test_no_output "compile code union union_type newdecl_u"
gdb_test_no_output "compile code struct struct_type newdecl_s"
gdb_test_no_output "compile code inttypedef newdecl_i"
gdb_test "compile file" \
"You must provide a filename for this command.*" \
"Test compile file without a filename"
gdb_test "compile file -r" \
"You must provide a filename for this command.*" \
"Test compile file and raw option without a filename"
gdb_test "compile file -z" \
"Unrecognized option at: -z" \
"test compile file with unknown option"
gdb_test "compile file -z --" \
"Unrecognized option at: -z --" \
"test compile file with unknown option plus --"
gdb_test "compile file -raw -- -raw" \
"/-raw: No such file or directory.*" \
"test compile file \"-raw\" file"
# LOC_CONST tests.
if { $srcfile3 != "" } {
gdb_test "p constvar" " = 3"
gdb_test "info addr constvar" {Symbol "constvar" is constant\.}
gdb_test_no_output "compile code globalvar = constvar;"
gdb_test "print globalvar" " = 3" "print constvar value"
} else {
untested "print constvar value"
}
# Shared library tests.
require allow_shlib_tests
set libbin [standard_output_file ${testfile}-shlib.so]
set binfile [standard_output_file ${testfile}-shlib]
if { [gdb_compile_shlib ${srcdir}/${subdir}/${srcfile2} $libbin {debug}] != ""
|| [gdb_compile ${srcdir}/${subdir}/${srcfile} $binfile executable \
[list debug shlib=$libbin]] == -1 } {
return -1
}
clean_restart $binfile
gdb_load_shlib $libbin
if ![runto_main] {
return -1
}
gdb_test_no_output "compile code shlib_func ();" "call shared library function"
gdb_test "p globalvar" " = 1" "expect 1"
gdb_test_no_output "compile code shlibvar += 5;" "modify shared library variable"
gdb_test "p shlibvar" " = 15" "expect 15"
# This used to fail due to alignment. PR compile/31397.
gdb_test_no_output "compile code swa.val\[0\] = 1"