1# Copyright 2018-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 16load_lib gdb-python.exp 17 18# Test CLI output styling. 19 20standard_testfile 21 22# Compile the test executable. 23if {[build_executable "failed to build" $testfile $srcfile {debug macros}]} { 24 return -1 25} 26 27# The tests in this file are run multiple times with GDB's styles 28# disabled one at a time. This variable is the style that is 29# currently disabled. 30set currently_disabled_style "" 31 32# A wrapper around the 'style' function found in gdb-utils.exp, 33# filter out requests for the disabled style. 34proc limited_style { str style } { 35 global currently_disabled_style 36 37 if { $style != $currently_disabled_style } { 38 return [style $str $style] 39 } 40 41 return $str 42} 43 44# A wrapper around 'clean_restart' from gdb.exp, this performs the 45# normal clean_restart, but then disables the currently disabled 46# style. 47proc clean_restart_and_disable { prefix args } { 48 global currently_disabled_style 49 50 with_test_prefix "$prefix" { 51 eval "clean_restart $args" 52 53 if { $currently_disabled_style != "" } { 54 set st $currently_disabled_style 55 gdb_test_no_output "set style $st background none" 56 gdb_test_no_output "set style $st foreground none" 57 gdb_test_no_output "set style $st intensity normal" 58 } 59 } 60} 61 62# The core of this test script. Run some tests of different aspects 63# of GDB's styling. 64# 65# Within this proc always use LIMITED_STYLE instead of STYLE, and 66# CLEAN_RESTART_AND_DISABLE instead of CLEAN_RESTART, this ensures 67# that the test operates as expected as styles are disabled. 68proc run_style_tests { } { 69 global testfile srcfile hex binfile 70 global currently_disabled_style decimal hex 71 72 with_ansi_styling_terminal { 73 # Restart GDB with the correct TERM variable setting, this 74 # means that GDB will enable styling. 75 clean_restart_and_disable "restart 1" ${binfile} 76 77 set readnow [readnow] 78 79 if {![runto_main]} { 80 return 81 } 82 83 # Check that the source highlighter has not stripped away the 84 # leading newlines. 85 set main_line [gdb_get_line_number "break here"] 86 gdb_test "list $main_line,$main_line" "return.*some_called_function.*" 87 88 gdb_test_no_output "set style enabled off" 89 90 set argv "" 91 gdb_test_multiple "frame" "frame without styling" { 92 -re -wrap "main \\(argc=.*, (argv=$hex.*)\\).*style\\.c:\[0-9\].*" { 93 set argv $expect_out(1,string) 94 pass $gdb_test_name 95 } 96 } 97 98 gdb_test_no_output "set style enabled on" 99 100 set main_expr [limited_style main function] 101 set base_file_expr [limited_style ".*style\\.c" file] 102 set file_expr "$base_file_expr:\[0-9\]+" 103 set arg_expr [limited_style "arg." variable] 104 105 # On some embedded targets that don't fully support argc/argv, 106 # argv may print as "0x0" or as an address with a symbol name 107 # following, so use a regexp general enough to match that and 108 # do not make assumptions about how long the address string is. 109 gdb_test "frame" \ 110 [multi_line \ 111 "#0\\s+$main_expr\\s+\\($arg_expr=$decimal,\\s+$arg_expr=$hex.*\\)\\s+at\\s+$file_expr" \ 112 "\[0-9\]+\\s+.*return.* break here .*"] 113 gdb_test "info breakpoints" "$main_expr at $file_expr.*" 114 115 gdb_test_no_output "set style sources off" 116 gdb_test "frame" \ 117 "\r\n\[^\033\]*break here.*" \ 118 "frame without sources styling" 119 gdb_test_no_output "set style sources on" 120 121 gdb_test "break -q main" "file $base_file_expr.*" 122 123 gdb_test "print &main" " = .* [limited_style $hex address] <$main_expr>" 124 125 # Regression test for a bug where line-wrapping would occur at 126 # the wrong spot with styling. There were different bugs at 127 # different widths, so try two. 128 foreach width {20 30} { 129 set argv_len [string length $argv] 130 if { $argv_len == 0 } { 131 continue 132 } 133 134 # There was also a bug where the styling could be wrong in 135 # the line listing; this is why the words from the source 136 # code are spelled out in the final result line of the 137 # test. 138 set re0_styled \ 139 [multi_line \ 140 "#0\\s+$main_expr\\s+\\($arg_expr=$decimal,\\s+$arg_expr=$hex\\)" \ 141 "\\s+at\\s+$file_expr" \ 142 "\[0-9\]+\\s+.*return.* break here .*"] 143 set re1_styled \ 144 [multi_line \ 145 "#0\\s+$main_expr\\s+\\($arg_expr=$decimal,\\s+" \ 146 "\\s+$arg_expr=$hex.*\\)" \ 147 "\\s+at\\s+$file_expr" \ 148 "\[0-9\]+\\s+.*return.* break here .*"] 149 set re2_styled \ 150 [multi_line \ 151 "#0\\s+$main_expr\\s+\\($arg_expr=.*" \ 152 "\\s+$arg_expr=$hex.*\\)\\s+at\\s+$file_expr" \ 153 "\[0-9\]+\\s+.*return.* break here .*"] 154 155 # The length of the line containing argv containing: 156 # - 4 leading spaces 157 # - argv string 158 # - closing parenthesis 159 set line_len [expr 4 + $argv_len + 1] 160 161 if { $argv == "argv=0x0" && $width >= 27 } { 162 # Embedded target with no argv support. 163 # #0 main (argc=0, argv=0x0) 164 set re_styled $re0_styled 165 } elseif { $line_len > $width } { 166 # At on the next line. 167 set re_styled $re1_styled 168 } else { 169 # At on the same line as argv. 170 set re_styled $re2_styled 171 } 172 173 # Override width for the duration of the command, letting 174 # GDB reset back to 0. Doing this in the loop rather than 175 # after, avoids trying to do "set width 30" while width is 176 # 20, which causes horizontal scrolling in the case that 177 # the fallback stub-termcap.c is used: 178 # ^M<et width 30^M 179 # (gdb) FAIL: gdb.base/style.exp: all styles enabled: set width 30 180 gdb_test "with width $width -- frame" $re_styled \ 181 "frame when width=$width" 182 } 183 184 set macro_line [gdb_get_line_number "\#define SOME_MACRO"] 185 gdb_test "info macro SOME_MACRO" \ 186 "Defined at $base_file_expr:$macro_line\r\n#define SOME_MACRO 23" 187 188 gdb_test_no_output "set width 0" 189 190 # If disassembler styling is being done by the Python pygments 191 # module, then we can't be sure how the 'some_called_function' 192 # symbol will be styled. However, if pygments is not being 193 # used then we can know how the symbol name will be styled. 194 set main [limited_style main function] 195 if { $::python_disassembly_styling } { 196 set func "some_called_function" 197 } else { 198 set func [limited_style some_called_function function] 199 } 200 # Somewhere should see the call to the function. 201 gdb_test "disassemble main" \ 202 [concat "Dump of assembler code for function $main:.*" \ 203 "[limited_style $hex address].*$func.*"] 204 205 set ifield [limited_style int_field variable] 206 set sfield [limited_style string_field variable] 207 set efield [limited_style e_field variable] 208 set evalue [limited_style VALUE_TWO variable] 209 set lhs [limited_style "\\\$$decimal" variable] 210 gdb_test "print struct_value" \ 211 "$lhs = \{$ifield = 23,.*$sfield = .*,.*$efield = $evalue.*" 212 213 set ffield [limited_style field variable] 214 set cstart [string_to_regexp "/* XXX "] 215 set cend [string_to_regexp " */"] 216 set p1field [limited_style "$cstart.*$decimal.*-bit.*padding.*$cend" \ 217 highlight] 218 set p2field [limited_style "$cstart.*$decimal.*-byte.*padding.*$cend" \ 219 highlight] 220 221 gdb_test "ptype/o just_bitfield_value" \ 222 [multi_line \ 223 ".* type = struct just_bitfield {" \ 224 ".* unsigned int $ffield : 3;" \ 225 "$p1field" \ 226 "$p2field" \ 227 "" \ 228 ".* total size.*: *$decimal *$cend" \ 229 " *}.*"] 230 231 set address_style_expr [limited_style ".*\".*address.*\".*style.*" address] 232 set color "blue" 233 if { $currently_disabled_style == "address" } { 234 set color "none" 235 } 236 gdb_test "show style address foreground" \ 237 "The ${address_style_expr} foreground color is: ${color}" \ 238 "style name and style word styled using its own style in show style" 239 240 set aliases_expr [limited_style ".*aliases.*" title] 241 set breakpoints_expr [limited_style ".*breakpoints.*" title] 242 gdb_test "help" \ 243 [multi_line \ 244 "List of classes of commands:" \ 245 "" \ 246 "${aliases_expr} -- User-defined aliases of other commands\." \ 247 "${breakpoints_expr} -- Making program stop at certain points\." \ 248 ".*" \ 249 ] \ 250 "help classes of commands styled with title" 251 252 set taas_expr [limited_style ".*taas.*" title] 253 set tfaas_expr [limited_style ".*tfaas.*" title] 254 set cut_for_thre_expr [limited_style "cut for 'thre" highlight] 255 gdb_test "apropos -v cut for 'thre" \ 256 [multi_line \ 257 "" \ 258 "${taas_expr}" \ 259 "Apply a command to all .*" \ 260 "Usage:.*" \ 261 "short${cut_for_thre_expr}ad apply.*" \ 262 "" \ 263 "${tfaas_expr}" \ 264 "Apply a command to all .*" \ 265 "Usage:.*" \ 266 "short${cut_for_thre_expr}ad apply.*" \ 267 ] 268 269 clean_restart_and_disable "restart 2" 270 271 set quoted [string_to_regexp $binfile] 272 set pass_re "Reading symbols from [limited_style $quoted file]\.\.\." 273 if { $readnow } { 274 set pass_re \ 275 [multi_line \ 276 $pass_re \ 277 "Expanding full symbols from [limited_style $quoted file]\.\.\."] 278 } 279 gdb_test "file $binfile" \ 280 $pass_re \ 281 "filename is styled when loading symbol file" 282 283 gdb_test "pwd" "Working directory [limited_style .*? file].*" 284 285 gdb_test_no_output "set print repeat 3" 286 gdb_test "print {0,0,0,0,0,0,0,0}" \ 287 " = \\{0 [limited_style {<repeats.*8.*times>} metadata]\\}" 288 289 gdb_test "show logging file" \ 290 "The current logfile is \"[limited_style .*? file]\"\\..*" 291 292 # Check warnings are styled by setting a rubbish data 293 # directory. 294 gdb_test "set data-directory Makefile" \ 295 "warning: [limited_style .*? file] is not a directory\\..*" 296 gdb_test "show data-directory" \ 297 "GDB's data directory is \"[limited_style .*? file]\"\\..*" 298 299 # Check that deprecation styles command names. 300 gdb_test_no_output "maintenance deprecate p \"new_p\"" \ 301 "maintenance deprecate p \"new_p\" /1/" 302 gdb_test "p 5" \ 303 "Warning: '[limited_style p title]', an alias for the command '[limited_style print title]', is deprecated.*Use '[limited_style new_p title]'.*" \ 304 "p deprecated warning, with replacement" 305 306 # Check that the version string is styled in the output of 'show 307 # version', and that this styling can be disabled. 308 set vers [style "GNU gdb.*" version] 309 set url [limited_style "http:.*html" file] 310 gdb_test "show version" "${vers}.*<$url>.*" \ 311 "'show version' is styled" 312 } 313} 314 315# Check that disassembler styling can be disabled. The function that 316# we are disassembling has some minimal styling applied even if the 317# Python pygments module is not available, so, when we disable 318# disassembler styling, we should always see a change in output. 319proc test_disable_disassembler_styling { } { 320 save_vars { env(TERM) env(NO_COLOR) } { 321 # We need an ANSI-capable terminal to get the output. 322 setenv TERM ansi 323 setenv NO_COLOR "" 324 325 # Restart GDB with the correct TERM variable setting, this 326 # means that GDB will enable styling. 327 clean_restart_and_disable "restart 3" $::binfile 328 329 set styled_hex [limited_style $::hex address] 330 set main [limited_style main function] 331 332 foreach_with_prefix libopcodes { on off } { 333 334 set command_failed false 335 gdb_test_multiple "maint set libopcodes-styling enabled ${libopcodes}" "" { 336 -re "^maint set libopcodes-styling enabled ${libopcodes}\r\n" { 337 exp_continue 338 } 339 340 -re "Use of libopcodes styling not supported on architecture \[^\r\n\]+\r\n" { 341 set command_failed true 342 exp_continue 343 } 344 345 -re "^$::gdb_prompt $" { 346 gdb_assert { !$command_failed || [string equal $libopcodes "on"] } \ 347 $gdb_test_name 348 } 349 } 350 351 if { $libopcodes == "on" && $command_failed } { 352 # We tried to turn on libopcodes disassembler styling, 353 # but this is not supported on this architecture. 354 continue 355 } 356 357 foreach_with_prefix disasm_styling { on off } { 358 gdb_test_no_output "set style disassembler enabled ${disasm_styling}" 359 360 if { $libopcodes == "off" && $disasm_styling == "on" \ 361 && !$::python_disassembly_styling} { 362 # We have libopcodes based styling off, but 363 # disassembler styling turned on. We're expecting 364 # Python Pygments to be used to add styling. 365 # 366 # However, if we get here, then we don't have the 367 # Pygments module, so skip this test. 368 continue 369 } 370 371 set saw_header_line false 372 set saw_styled_output_line false 373 set saw_unstyled_output_line false 374 gdb_test_multiple "disassemble main" "" { 375 -re "disassemble main\r\n" { 376 exp_continue 377 } 378 -re "^Dump of assembler code for function $main:" { 379 set saw_header_line true 380 exp_continue 381 } 382 -re "^\\s+${styled_hex}\\s+<\[^>\]+>:\\s+\[^\r\n\033\]+\r\n" { 383 set saw_unstyled_output_line true 384 exp_continue 385 } 386 -re "^\\s+${styled_hex}\\s+<\[^>\]+>:\\s+\[^\r\n\]+\033\[^\r\n\]+\r\n" { 387 set saw_styled_output_line true 388 exp_continue 389 } 390 -re "^End of assembler dump\\.\r\n" { 391 exp_continue 392 } 393 -re "^$::gdb_prompt $" { 394 gdb_assert { $saw_header_line } 395 if { $disasm_styling } { 396 gdb_assert { $saw_styled_output_line } 397 gdb_assert { !$saw_unstyled_output_line } 398 } else { 399 gdb_assert { !$saw_styled_output_line } 400 gdb_assert { $saw_unstyled_output_line } 401 } 402 } 403 } 404 } 405 } 406 } 407} 408 409# Disassemble a single isntruction at the start of main, then strip 410# off the address and symbol information, returning just the 411# disassembled instruction part. 412proc get_single_disassembled_insn {} { 413 set disasm_line [capture_command_output "x/1i *main" ""] 414 regexp "^\[^:\]+:\\s*(.*)$" $disasm_line whole_match insn 415 return $insn 416} 417 418# Check that, if the user is using Python Pygments for disassembler 419# styling, then the styling correctly switches off when an error is 420# detected in the Python code. 421proc test_disassembler_error_handling { } { 422 423 # This test requires the Python Pygments module to be installed 424 # and used by GDB. 425 if { !$::python_disassembly_styling } { 426 return 427 } 428 429 save_vars { env(TERM) env(NO_COLOR) } { 430 # We need an ANSI-capable terminal to get the output. 431 setenv TERM ansi 432 setenv NO_COLOR "" 433 434 # Restart GDB with the correct TERM variable setting, this 435 # means that GDB will enable styling. 436 clean_restart_and_disable "restart 4" $::binfile 437 438 # Disable use of libopcodes for styling. As this function is 439 # only called when Python Pygments module is available, we 440 # should now be using that module to style the disassembler 441 # output. 442 gdb_test_no_output "maint set libopcodes-styling enabled off" 443 444 # Disassemble a single instruction and ensure that the output 445 # has styling markers in it. 446 set insn_before [get_single_disassembled_insn] 447 gdb_assert { [regexp "\033" $insn_before] } \ 448 "have style markers when Pygments is working fine" 449 450 # Now replace the standard function that colorizes the 451 # disassembler output, with a new function that always returns 452 # None, this should cause GDB to stop using the Pygments 453 # module for disassembler styling. 454 gdb_py_test_silent_cmd \ 455 [multi_line_input \ 456 "python" \ 457 "def replacement_colorize_disasm(content,gdbarch):" \ 458 " return None" \ 459 "gdb.styling.colorize_disasm = replacement_colorize_disasm" \ 460 "end"] \ 461 "setup replacement colorize_disasm function" \ 462 true 463 464 set insn_after [get_single_disassembled_insn] 465 gdb_assert { ![regexp "\033" $insn_after] } \ 466 "have no style markers when Pygments is broken" 467 } 468} 469 470# A separate test from the above as the styled text this checks can't 471# currently be disabled (the text is printed too early in GDB's 472# startup process). 473proc test_startup_version_string { } { 474 gdb_exit 475 476 save_vars { ::INTERNAL_GDBFLAGS } { 477 set ::INTERNAL_GDBFLAGS [string map {"-q" ""} $::INTERNAL_GDBFLAGS] 478 479 gdb_spawn 480 } 481 482 # Deliberate use of base STYLE proc here as the style of the 483 # startup version string can't (currently) be controlled. 484 set vers [style "GNU gdb.*" version] 485 gdb_test "" "${vers}.*" "version is styled at startup" 486} 487 488# Check to see if the Python styling of disassembler output is 489# expected or not, this styling requires Python support in GDB, and 490# the Python pygments module to be available. 491clean_restart ${binfile} 492if {[allow_python_tests] && [gdb_py_module_available "pygments"]} { 493 set python_disassembly_styling true 494} else { 495 set python_disassembly_styling false 496} 497 498# Run tests with all styles in their default state. 499with_test_prefix "all styles enabled" { 500 run_style_tests 501} 502 503# Now, for each style in turn. Disable that style only and run the 504# test again. Things in that style should NOT now be styled. 505foreach style { title file function highlight variable \ 506 address metadata } { 507 set currently_disabled_style $style 508 with_test_prefix "disable style $style" { 509 run_style_tests 510 } 511} 512 513# Check that the disassembler styling can be disabled. 514test_disable_disassembler_styling 515 516# Check that GDB handles an error in the Python Pygments disassembly 517# styling code. 518test_disassembler_error_handling 519 520# Finally, check the styling of the version string during startup. 521test_startup_version_string 522