1# Copyright (C) 2017-2020 Free Software Foundation, Inc. 2# 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 17if { ![istarget i?86-*-*] && ![istarget x86_64-*-* ] } { 18 untested "skipping x86 MPX tests." 19 return 20} 21 22standard_testfile 23 24if { ![supports_mpx_check_pointer_bounds] } { 25 return -1 26} 27 28set comp_flags "-mmpx -fcheck-pointer-bounds -I${srcdir}/../nat" 29 30if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ 31 [list debug additional_flags=${comp_flags}]] } { 32 return -1 33} 34 35if ![runto_main] { 36 untested "could not run to main" 37 return -1 38} 39 40set test "check whether processor supports MPX" 41gdb_test_multiple "print have_mpx ()" $test { 42 -re ".*= 1\r\n$gdb_prompt " { 43 pass $test 44 } 45 -re ".*= 0\r\n$gdb_prompt " { 46 pass $test 47 untested "processor does not support MPX; skipping tests" 48 return 49 } 50} 51 52# Convenience for returning from an inferior call that causes a BND violation. 53# 54gdb_test_no_output "set confirm off" 55 56# Convenience variable. 57# 58set bound_reg " = \\\{lbound = $hex, ubound = $hex\\\}.*" 59set int_braw_reg " = \\\{lbound = 0x0, ubound_raw = 0x0\\\}.*" 60set bndcfg_reg " = \\\{raw = $hex, config = \\\{base = $hex, reserved = $hex,\ 61 preserved = $hex, enabled = $hex\\\}\\\}" 62set bndstatus_reg " = \\\{raw = $hex, status = \\\{bde = $hex,\ 63 error = $hex\\\}\\\}" 64set u_fault [multi_line "Program received signal SIGSEGV, Segmentation fault" \ 65 "Upper bound violation while accessing address $hex" \ 66 "Bounds: \\\[lower = $hex, upper = $hex\\\]"] 67 68 69# Simplify the tests below. 70# 71proc sanity_check_bndregs {arglist} { 72 73 global int_braw_reg 74 75 foreach a $arglist { 76 gdb_test "p /x $a" "$int_braw_reg"\ 77 "$a" 78 } 79} 80 81# Set bnd register to have no access to memory. 82# 83proc remove_memory_access {reg} { 84 global hex 85 86 sanity_check_bndregs {"\$bnd0raw" "\$bnd1raw" "\$bnd2raw" "\$bnd3raw"} 87 88 gdb_test "p /x $reg.lbound = $reg.ubound" "= $hex"\ 89 "$reg lower bound set" 90 gdb_test "p /x $reg.ubound = 0" " = 0x0"\ 91 "$reg upper bound set" 92} 93 94 95# Prepare convenience variables for bndconfig and status 96# for posterior comparison. 97# 98proc prepare_bndcfg_bndstatus {} { 99 100 global bndcfg_reg 101 global bndstatus_reg 102 103 gdb_test "p /x \$temp_bndcfgu = \$bndcfgu" "$bndcfg_reg"\ 104 "bndcfgu should not change" 105 106 gdb_test "p /x \$temp_bndstatus = \$bndstatus" "$bndstatus_reg"\ 107 "bndstatus should not change" 108} 109 110# Compare values set for convenience variables and actual values of bndconfig 111# and bndstatus registers. 112# 113proc compare_bndstatus_with_convenience {} { 114 115 gdb_test "p \$temp_bndcfgu == \$bndcfgu" "= 1"\ 116 "bndcfgu compare before and after" 117 gdb_test "p \$temp_bndstatus == \$bndstatus" "= 1"\ 118 "bndstatus compare before and after" 119} 120 121# Perform an inferior call defined in func. 122# 123proc perform_a_call {func} { 124 125 global inf_call_stopped 126 global gdb_prompt 127 128 gdb_test "p /x $func" [multi_line "The program being debugged\ 129 stopped while in a function called from GDB." \ 130 "Evaluation of the expression containing the\ 131 function.*" \ 132 ] "inferior call stopped" 133} 134 135# Perform an inferior call defined in func. 136# 137proc check_bound_violation {parm parm_type is_positive} { 138 139 global u_fault 140 141 gdb_test "continue" "$u_fault.*" "continue to a bnd violation" 142 143 set message "access only one position" 144 if {$is_positive == 1} { 145 gdb_test "p (((void *)\$_siginfo._sifields._sigfault.si_addr\ 146 - (void*)$parm))/sizeof($parm_type) == 1"\ 147 " = 1" $message 148 } else { 149 gdb_test "p ((void*)$parm\ 150 - (void *)\$_siginfo._sifields._sigfault.si_addr)\ 151 /sizeof($parm_type) == 1"\ 152 " = 1" $message 153 } 154 gdb_test "return" "\\\#.*main.*i386-mpx-call\\\.c:.*" "return from the fault" 155} 156 157 158# Start testing! 159# 160 161# Set up for stopping in the middle of main for calling a function in the 162# inferior. 163# 164set break "bkpt 1." 165gdb_breakpoint [gdb_get_line_number "${break}"] 166gdb_continue_to_breakpoint "${break}" ".*${break}.*" 167 168 169# Consistency: 170# default run execution of call should succeed without violations. 171# 172with_test_prefix "default_run" { 173 174 gdb_test "p \$keep_bnd0_value=\$bnd0" $bound_reg\ 175 "store bnd0 register in a convenience variable" 176 177 gdb_test "p /x upper (a, b, c, d, 0)" " = $hex"\ 178 "default inferior call" 179 180 gdb_test "p ((\$bnd0.lbound==\$keep_bnd0_value.lbound) &&\ 181 (\$bnd0.ubound==\$keep_bnd0_value.ubound))" "= 1" \ 182 "bnd register value after and before call" 183} 184 185# Consistency: Examine bnd registers values before and after the call. 186# 187# 188with_test_prefix "verify_default_values" { 189 190 prepare_bndcfg_bndstatus 191 192 gdb_breakpoint "*upper" 193 perform_a_call "upper (a, b, c, d, 1)" 194 195 sanity_check_bndregs {"\$bnd0raw" "\$bnd1raw" "\$bnd2raw" "\$bnd3raw"} 196 197 compare_bndstatus_with_convenience 198 199 gdb_test_multiple "continue" "inferior call test" { 200 -re ".*Continuing.\r\n$gdb_prompt " { 201 pass "inferior call performed" 202 } 203 } 204} 205 206# Examine: Cause an upper bound violation changing BND0. 207# 208# 209with_test_prefix "upper_bnd0" { 210 211 prepare_bndcfg_bndstatus 212 213 gdb_breakpoint "*upper" 214 perform_a_call "upper (a, b, c, d, 1)" 215 216 remove_memory_access "\$bnd0" 217 218 compare_bndstatus_with_convenience 219 220 check_bound_violation "a" "int" 1 221} 222 223# Examine: Cause an upper bound violation changing BND1. 224# 225# 226with_test_prefix "upper_bnd1" { 227 228 prepare_bndcfg_bndstatus 229 230 gdb_breakpoint "*upper" 231 perform_a_call "upper (a, b, c, d, 1)" 232 233 remove_memory_access "\$bnd1" 234 235 compare_bndstatus_with_convenience 236 237 check_bound_violation "b" "int" 1 238} 239 240# Examine: Cause an upper bound violation changing BND2. 241# 242# 243with_test_prefix "upper_bnd2" { 244 245 prepare_bndcfg_bndstatus 246 247 gdb_breakpoint "*upper" 248 perform_a_call "upper (a, b, c, d, 1)" 249 250 remove_memory_access "\$bnd2" 251 252 compare_bndstatus_with_convenience 253 254 check_bound_violation "c" "int" 1 255} 256 257# Examine: Cause an upper bound violation changing BND3. 258# 259# 260with_test_prefix "upper_bnd3" { 261 prepare_bndcfg_bndstatus 262 263 gdb_breakpoint "*upper" 264 perform_a_call "upper (a, b, c, d, 1)" 265 266 remove_memory_access "\$bnd3" 267 268 compare_bndstatus_with_convenience 269 270 check_bound_violation "d" "int" 1 271} 272 273# Examine: Cause a lower bound violation changing BND0. 274# 275# 276with_test_prefix "lower_bnd0" { 277 278 prepare_bndcfg_bndstatus 279 280 gdb_breakpoint "*lower" 281 perform_a_call "lower (a, b, c, d, 1)" 282 283 remove_memory_access "\$bnd0" 284 285 compare_bndstatus_with_convenience 286 287 check_bound_violation "a" "int" 0 288} 289 290# Examine: Cause a lower bound violation changing BND1. 291# 292# 293with_test_prefix "lower_bnd1" { 294 295 prepare_bndcfg_bndstatus 296 297 gdb_breakpoint "*lower" 298 perform_a_call "lower (a, b, c, d, 1)" 299 300 remove_memory_access "\$bnd1" 301 302 compare_bndstatus_with_convenience 303 304 check_bound_violation "b" "int" 0 305} 306 307# Examine: Cause a lower bound violation changing BND2. 308# 309# 310with_test_prefix "lower_bnd2" { 311 312 prepare_bndcfg_bndstatus 313 314 gdb_breakpoint "*lower" 315 perform_a_call "lower (a, b, c, d, 1)" 316 317 remove_memory_access "\$bnd2" 318 319 compare_bndstatus_with_convenience 320 321 check_bound_violation "c" "int" 0 322} 323 324# Examine: Cause a lower bound violation changing BND3. 325# 326# 327with_test_prefix "lower_bnd3" { 328 329 prepare_bndcfg_bndstatus 330 331 gdb_breakpoint "*lower" 332 perform_a_call "lower (a, b, c, d, 1)" 333 334 remove_memory_access "\$bnd3" 335 336 compare_bndstatus_with_convenience 337 338 check_bound_violation "d" "int" 0 339} 340 341# Examine: String causing a upper bound violation changing BND0. 342# 343# 344with_test_prefix "chars_up" { 345 346 prepare_bndcfg_bndstatus 347 348 gdb_breakpoint "*char_upper" 349 perform_a_call "char_upper (hello, 1)" 350 351 remove_memory_access "\$bnd0" 352 353 compare_bndstatus_with_convenience 354 355 check_bound_violation "str" "char" 1 356} 357 358 359# Examine: String causing an lower bound violation changing BND0. 360# 361# 362with_test_prefix "chars_low" { 363 364 prepare_bndcfg_bndstatus 365 366 gdb_breakpoint "*char_lower" 367 perform_a_call "char_lower (hello, 1)" 368 369 remove_memory_access "\$bnd0" 370 371 compare_bndstatus_with_convenience 372 373 check_bound_violation "str" "char" 0 374} 375 376# Examine: String causing an lower bound violation changing BND0. 377# 378# 379with_test_prefix "chars_low_adhoc_parm" { 380 381 prepare_bndcfg_bndstatus 382 383 gdb_breakpoint "*char_lower" 384 perform_a_call "char_lower (\"tryme\", 1)" 385 386 remove_memory_access "\$bnd0" 387 388 compare_bndstatus_with_convenience 389 390 check_bound_violation "str" "char" 0 391} 392