1 # Copyright 2022-2024 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 # Format hex value VAL for language LANG. 17 18 proc hex_for_lang { lang val } { 19 set neg_p [regexp ^- $val] 20 set val [regsub ^-?0x $val ""] 21 if { $lang == "modula-2" } { 22 set val 0[string toupper $val]H 23 } else { 24 set val 0x$val 25 } 26 if { $neg_p } { 27 return -$val 28 } else { 29 return $val 30 } 31 } 32 33 # Determine whether N fits in type with TYPE_BITS and TYPE_SIGNEDNESS. 34 35 proc fits_in_type { n type_bits type_signedness } { 36 if { $type_signedness == "s" } { 37 set type_signed_p 1 38 } elseif { $type_signedness == "u" } { 39 set type_signed_p 0 40 } else { 41 error "unreachable" 42 } 43 44 if { $n < 0 && !$type_signed_p } { 45 # Can't fit a negative number in an unsigned type. 46 return 0 47 } 48 49 if { $n < 0} { 50 set n_sign -1 51 set n [expr -$n] 52 } else { 53 set n_sign 1 54 } 55 56 set smax [expr 1 << ($type_bits - 1)]; 57 if { $n_sign == -1 } { 58 # Negative number, signed type. 59 return [expr ($n <= $smax)] 60 } elseif { $n_sign == 1 && $type_signed_p } { 61 # Positive number, signed type. 62 return [expr ($n < $smax)] 63 } elseif { $n_sign == 1 && !$type_signed_p } { 64 # Positive number, unsigned type. 65 return [expr ($n >> $type_bits) == 0] 66 } else { 67 error "unreachable" 68 } 69 } 70 71 # Return 1 if LANG is a c-like language, in the sense that it uses the same 72 # parser. 73 74 proc c_like { lang } { 75 set res 0 76 switch $lang { 77 c 78 - c++ 79 - asm 80 - objective-c 81 - opencl 82 - minimal {set res 1} 83 } 84 return $res 85 } 86 87 # Parse number N for LANG, and return a list of expected type and value. 88 89 proc parse_number { lang n } { 90 global re_overflow 91 92 set hex_p [regexp ^-?0x $n] 93 94 global hex decimal 95 if { $hex_p } { 96 set any $hex 97 } else { 98 set any $decimal 99 } 100 101 global sizeof_long_long sizeof_long sizeof_int 102 set long_long_bits [expr $sizeof_long_long * 8] 103 set long_bits [expr $sizeof_long * 8] 104 set int_bits [expr $sizeof_int * 8] 105 106 if { $lang == "rust" } { 107 if { [fits_in_type $n 32 s] } { 108 return [list "i32" $n] 109 } elseif { [fits_in_type $n 64 s] } { 110 return [list "i64" $n] 111 } elseif { [fits_in_type $n 128 u] } { 112 return [list "i128" $n] 113 } else { 114 # Overflow. 115 return [list $re_overflow $re_overflow] 116 } 117 } elseif { $lang == "d" } { 118 if { [fits_in_type $n 32 s] } { 119 return [list int $n] 120 } elseif { [fits_in_type $n 32 u] } { 121 if { $hex_p } { 122 return [list uint $n] 123 } else { 124 return [list long $n] 125 } 126 } elseif { [fits_in_type $n 64 s] } { 127 return [list long $n] 128 } elseif { [fits_in_type $n 64 u] } { 129 return [list ulong $n] 130 } else { 131 # Overflow. 132 return [list $re_overflow $re_overflow] 133 } 134 } elseif { $lang == "ada" } { 135 if { [fits_in_type $n $int_bits s] } { 136 return [list "<$sizeof_int-byte integer>" $n] 137 } elseif { [fits_in_type $n $long_bits s] } { 138 return [list "<$sizeof_long-byte integer>" $n] 139 } elseif { [fits_in_type $n $long_bits u] } { 140 return [list "<$sizeof_long-byte integer>" $n] 141 } elseif { [fits_in_type $n $long_long_bits s] } { 142 return [list "<$sizeof_long_long-byte integer>" $n] 143 } elseif { [fits_in_type $n $long_long_bits u] } { 144 # Note: Interprets ULLONG_MAX as -1. 145 return [list "<$sizeof_long_long-byte integer>" $n] 146 } elseif { [fits_in_type $n 128 u] } { 147 return [list "<16-byte integer>" $n] 148 } else { 149 # Overflow. 150 return [list $re_overflow $re_overflow] 151 } 152 } elseif { $lang == "modula-2" } { 153 if { [string equal $n -0] } { 154 # Note: 0 is CARDINAL, but -0 is an INTEGER. 155 return [list "INTEGER" 0] 156 } 157 if { $n < 0 && [fits_in_type $n $int_bits s] } { 158 return [list "INTEGER" $n] 159 } elseif { [fits_in_type $n $int_bits u] } { 160 return [list "CARDINAL" $n] 161 } else { 162 # Overflow. 163 return [list $re_overflow $re_overflow] 164 } 165 } elseif { $lang == "fortran" } { 166 if { [fits_in_type $n $int_bits s] } { 167 return [list int $n] 168 } elseif { [fits_in_type $n $int_bits u] } { 169 return [list "unsigned int" $n] 170 } elseif { [fits_in_type $n $long_bits s] } { 171 return [list long $n] 172 } elseif { [fits_in_type $n $long_bits u] } { 173 return [list "unsigned long" $n] 174 } else { 175 # Overflow. 176 return [list $re_overflow $re_overflow] 177 } 178 } else { 179 if { [c_like $lang] } { 180 if { $hex_p } { 181 # C Hex. 182 set have_unsigned 1 183 } else { 184 # C Decimal. Unsigned not allowed according. 185 if { [fits_in_type $n $long_long_bits s] } { 186 # Fits in largest signed type. 187 set have_unsigned 0 188 } else { 189 # Doesn't fit in largest signed type, so ill-formed, but 190 # allow unsigned as a convenience, as compilers do (though 191 # with a warning). 192 set have_unsigned 1 193 } 194 } 195 } else { 196 # Non-C. 197 set have_unsigned 1 198 } 199 200 if { [fits_in_type $n $int_bits s] } { 201 return [list int $n] 202 } elseif { $have_unsigned && [fits_in_type $n $int_bits u] } { 203 return [list "unsigned int" $n] 204 } elseif { [fits_in_type $n $long_bits s] } { 205 return [list long $n] 206 } elseif { $have_unsigned && [fits_in_type $n $long_bits u] } { 207 return [list "unsigned long" $n] 208 } elseif { [fits_in_type $n $long_long_bits s] } { 209 return [list "long long" $n] 210 } elseif { $have_unsigned && [fits_in_type $n $long_long_bits u] } { 211 return [list "unsigned long long" $n] 212 } else { 213 # Overflow. 214 return [list $re_overflow $re_overflow] 215 } 216 } 217 218 error "unreachable" 219 } 220 221 # Test parsing numbers. Several language parsers had the same bug 222 # around parsing large 64-bit numbers, hitting undefined behavior, and 223 # thus crashing a GDB built with UBSan. This testcase goes over all 224 # languages exercising printing the max 64-bit number, making sure 225 # that GDB doesn't crash. ARCH is the architecture to test with. 226 227 proc test_parse_numbers {arch} { 228 global full_arch_testing 229 global tested_archs 230 global verbose 231 232 set arch_re [string_to_regexp $arch] 233 gdb_test "set architecture $arch" "The target architecture is set to \"$arch_re\"." 234 235 gdb_test_no_output "set language c" 236 237 # Types have different sizes depending on the architecture. 238 # Figure out type sizes before matching patterns in the upcoming 239 # tests. 240 241 global sizeof_long_long sizeof_long sizeof_int sizeof_short 242 set sizeof_long_long [get_sizeof "long long" -1] 243 set sizeof_long [get_sizeof "long" -1] 244 set sizeof_int [get_sizeof "int" -1] 245 set sizeof_short [get_sizeof "short" -1] 246 247 if { ! $full_arch_testing } { 248 set arch_id \ 249 [list $sizeof_long_long $sizeof_long $sizeof_long $sizeof_int \ 250 $sizeof_short] 251 if { [lsearch $tested_archs $arch_id] == -1 } { 252 lappend tested_archs $arch_id 253 } else { 254 return 255 } 256 } 257 258 foreach_with_prefix lang $::all_languages { 259 if { $lang == "unknown" } { 260 # Tested outside $supported_archs loop. 261 continue 262 } elseif { $lang == "auto" || $lang == "local" } { 263 # Avoid duplicate testing. 264 continue 265 } 266 267 gdb_test_no_output "set language $lang" 268 269 global re_overflow 270 if { $lang == "modula-2" || $lang == "fortran" } { 271 set re_overflow "Overflow on numeric constant\\." 272 } elseif { $lang == "ada" } { 273 set re_overflow "Integer literal out of range" 274 } elseif { $lang == "rust" } { 275 set re_overflow "Integer literal is too large" 276 } else { 277 set re_overflow "Numeric constant too large\\." 278 } 279 280 set basevals { 281 0xffffffffffffffff 282 0x7fffffffffffffff 283 0xffffffff 284 0x7fffffff 285 0xffff 286 0x7fff 287 0xff 288 0x7f 289 0x0 290 } 291 292 if { $lang == "modula-2" } { 293 # Modula-2 is the only language that changes the type of an 294 # integral literal based on whether it's prefixed with "-", 295 # so test both scenarios. 296 set prefixes { "" "-" } 297 } else { 298 # For all the other languages, we'd just be testing the 299 # parsing twice, so just test the basic scenario of no prefix. 300 set prefixes { "" } 301 } 302 303 foreach_with_prefix prefix $prefixes { 304 foreach baseval $basevals { 305 foreach offset { -2 -1 0 1 2 } { 306 set dec_val [expr $baseval + $offset] 307 set hex_val [format "0x%llx" $dec_val] 308 if { $dec_val < 0 } { 309 continue 310 } 311 312 set dec_val $prefix$dec_val 313 lassign [parse_number $lang $dec_val] type out 314 if { $verbose >= 1 } { verbose -log "EXPECTED: $out" 2 } 315 if { $prefix == "" } { 316 gdb_test "p/u $dec_val" "$out" 317 } else { 318 gdb_test "p/d $dec_val" "$out" 319 } 320 if { $verbose >= 1 } { verbose -log "EXPECTED: $type" 2 } 321 gdb_test "ptype $dec_val" "$type" 322 323 if { $prefix == "-" } { 324 # Printing with /x below means negative numbers are 325 # converted to unsigned representation. We could 326 # support this by updating the expected patterns. 327 # Possibly, we could print with /u and /d instead of 328 # /x here as well (which would also require updating 329 # expected patterns). 330 # For now, this doesn't seem worth the trouble, 331 # so skip. 332 continue 333 } 334 335 set hex_val $prefix$hex_val 336 lassign [parse_number $lang $hex_val] type out 337 set hex_val [hex_for_lang $lang $hex_val] 338 if { $verbose >= 1 } { verbose -log "EXPECTED: $out" 2 } 339 gdb_test "p/x $hex_val" "$out" 340 if { $verbose >= 1 } { verbose -log "EXPECTED: $type" 2 } 341 gdb_test "ptype $hex_val" "$type" 342 } 343 } 344 } 345 } 346 } 347 348 clean_restart 349 350 set supported_archs [get_set_option_choices "set architecture"] 351 # There should be at least one more than "auto". 352 gdb_assert {[llength $supported_archs] > 1} "at least one architecture" 353 354 set all_languages [get_set_option_choices "set language"] 355 356 gdb_test_no_output "set language unknown" 357 gdb_test "p/x 0" \ 358 "expression parsing not implemented for language \"Unknown\"" 359 360 # If 1, test each arch. If 0, test one arch for each sizeof 361 # short/int/long/longlong configuration. 362 # For a build with --enable-targets=all, full_arch_testing == 0 takes 15s, 363 # while full_arch_testing == 1 takes 9m20s. 364 set full_arch_testing 0 365 366 set tested_archs {} 367 foreach_with_prefix arch $supported_archs { 368 if {$arch == "auto"} { 369 # Avoid duplicate testing. 370 continue 371 } 372 test_parse_numbers $arch 373 } 374