aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base
AgeCommit message (Collapse)AuthorFilesLines
11 hoursgdb: Update linkage name lookup function to allow mst_file_data/bss types.Ijaz, Abdul B2-3/+10
From the commit 667ed4b14ddaa9af196481f1757c0e517e80b6ed onward, instead of normal name GDB looks for the "jit_descriptor" linkage name in the JIT code initialization. Without this change, the function "lookup_minimal_symbol_linkage", only matches the non-static data. So in case jit_debugger is static type then setting up breakpoint in the JIT code fails. Issue is seen for the intel compilers, where jit_debug_descriptor has static type i.e. "mst_file_data". Hence lookup_minimal_symbol_linkage returns nullptr for it. So, in this case breakpoint does not hit in the JIT code. To resolve this, the commit introduces a new boolean argument to the lookup_minimal_symbol_linkage function. This argument allows the function to also match mst_file_data and mst_file_bss types when set to true. The function is called with this new argument set to true only from JIT code initialization handling, ensuring that the current behavior remains unchanged for other cases. Because handling of static types of data symbols for all cases result in regression for "gdb.base/print-file-var.exp" test. Example of minsym for the JIT code emitted by the intel compilers where lookup_minimal_symbol_linkage fails without this change because jit_debugger type is "mst_file_data". (top-gdb) p *msymbol $1 = {<general_symbol_info> = {m_name = 0x7fffcc77dc95 "__jit_debug_descriptor", m_value = {ivalue = 84325936, block = 0x506b630, bytes = 0x506b630 <error: Cannot access memory at address 0x506b630>, address = 0x506b630, unrel_addr = (unknown: 0x506b630), common_block = 0x506b630, chain = 0x506b630}, language_specific = {obstack = 0x0, demangled_name = 0x0}, m_language = language_unknown, ada_mangled = 0, m_section = 29}, m_size = 24, filename = 0x55555a751b70 "JITLoaderGDB.cpp", m_type = mst_file_data, created_by_gdb = 0, m_target_flag_1 = 0, m_target_flag_2 = 0, m_has_size = 1, name_set = 1, hash_next = 0x55555b86e4f0, demangled_hash_next = 0x0} Updated the test "jit-elf-so.exp" to test the static type of jit_descriptor object. Approved-By: Tom Tromey <tom@tromey.com>
5 daysgdb/testsuite: some cleanups in gdb.base/annota{1,3}.exp testsAndrew Burgess2-64/+32
Fedora GDB has, for years, carried an out of tree patch for the gdb.base/annota{1,3}.exp tests. The patch simply adds a call to 'set breakpoint pending off' near the start of each test. Normally GDB tests are written using gdb_test or gdb_test_multiple, with gdb_test being a wrapper around gdb_test_multiple. Inside gdb_test_multiple we add a test pattern which detects if GDB offers the user an interactive yes/no prompt and immediately fails the test. What this means is that if something goes wrong with a test like: gdb_test "break main" ".*" and GDB ends up offering this prompt: Make breakpoint pending on future shared library load? (y or [n]) then instead of hanging waiting for the test to timeout, DejaGNU will spot the interactive prompt and immediately fail the test. In the gdb.base/annota{1,3}.exp tests we turn on GDB's annotation mode, and many of the tests in these scripts are written using send_gdb and gdb_expect or gdb_expect_list. This is done because in the past, gdb_test_multiple and friends were hard-coded to use the "normal" GDB prompt, and these tests instead expect the annotated prompt. Specifically, gdb_test_multiple expects '$gdb_prompt $' as the full prompt, that is the value of $gdb_prompt followed by a single white space. The annotation tests do update the value of $gdb_prompt, but with annotations on there is no trailing whitespace, so gdb_test_multiple's default behaviour doesn't work, which is why the test scripts originally avoided using gdb_test_multiple. As a result none of the tests in these files would early exit if we got an interactive yes/no prompt, and instead we'd be relying on each test to timeout, which could take a while. However, gdb_test_multiple now accepts a -prompt argument, so we can modify the prompt we are looking for, which is neat. So, I started off by going through these tests an changing all of the tests that create a breakpoint to use gdb_test, passing the -prompt option to change the prompt. While doing that I noticed some other things that I could improve in these tests, I've cleaned up the use of standard_testfile, switched to use prepare_for_testing, and removed some redundant clean_restart and 'set height 0' calls (set height 0 is done within clean_restart, which is called by prepare_for_testing). I've updated some comments which said "we can't use gdb_test" to say "we can use gdb_test with -prompt option", and I've removed some commented out debug code (e.g. setting 'exp_internal'). Finally, I ran these two tests through check-all-boards, and spotted that annota1.exp failed when using a remote host. This is because one test checks for a full path to the binary in some output, and with a remote host the binary ends up being copied and the path is not as expected. I'm assuming that checking the full path is important, so I've disabled this test on remote host boards. After all these changes I checked using 'make check-all-boards' and there are no unexpected results on either of these tests. Tested-By: Tom de Vries <tdevries@suse.de> Acked-By: Tom de Vries <tdevries@suse.de>
5 daysgdb/readline: don't get stuck thinking an EOF arrivedAndrew Burgess2-0/+150
It was brought to my attention[1] that if a user makes use of Ctrl+d to quit from a secondary prompt (e.g. the prompt used to enter lines for the 'commands' command) then GDB will start displaying some unexpected blank lines. Here's an example: Reading symbols from /tmp/hello.x... (gdb) break main Breakpoint 1 at 0x401198: file hello.c, line 18. (gdb) commands Type commands for breakpoint(s) 1, one per line. End with a line saying just "end". >quit # <----------- Use Ctrl+d to quit here. (gdb) show architecture # <----------- This blank line is unexpected. The target architecture is set to "auto" (currently "i386:x86-64"). (gdb) I've marked up where I press 'Ctrl+d', and also the unexpected blank line. This issue will only happen if bracketed-paste-mode is in use. If this has been disabled (e.g. in ~/.inputrc) then this issue will not occur. The blank line is not just emitted for the 'show architecture' command. The blank line is actually caused by an extra '\n' character emitted by readline after it has gathered a complete line of input, and so will occur for any command. The problem is caused by readline getting "stuck" in a state where it thinks that an EOF has just been delivered. This state is set when the 'Ctrl+d' does deliver an EOF, but then this state is never fully reset. As a result, every time readline completes a line, it thinks that the line was completed due to an EOF and so adds an extra '\n' character. Obviously the real fix for this issue is to patch readline, and I do have a patch for that[2], however, version 8.2 of readline has been released, and contains this issue. As such, if GDB is linked against the system readline, and that system readline is 8.2, then we can expect to see this issue. There's a pretty simple, and cheap workaround that we can add to GDB that will mitigate this issue. I propose that we add this workaround to GDB. If/when the readline patch is accepted then I'll back-port this to our local readline copy, but retaining the workaround will be harmless, and will make GDB play nicer with system readline libraries (version 8.2). [1] https://inbox.sourceware.org/gdb-patches/34ef5438-8644-44cd-8537-5068e0e5e434@redhat.com [2] https://lists.gnu.org/archive/html/bug-readline/2024-10/msg00014.html Reviewed-By: Keith Seitz <keiths@redhat.com>
5 daysgdb/readline: add readline library version to 'show configuration'Andrew Burgess1-0/+3
When debugging readline issues I'd like an easy way to know (for sure) what version of readline GDB is using. This could also be useful when writing readline tests, knowing the precise readline version will allow us to know if we expect a test to pass or not. Add the readline library version to the output of the 'show configuration' command. Also include a suffix indicating if we are using the system readline, or the statically linked in readline. The information about static readline vs shared readline can be figured out from the configure command output, but having it repeated in the readline version line makes it super easy to grok within tests, and it's super cheap, so I don't see this as a problem.
6 daysgdb/testsuite: fix failure in gdb.base/info_sources.expAndrew Burgess1-10/+50
I ran into an unexpected failure in gdb.base/info_sources.exp. The test in question runs this command: (gdb) info sources -d -- -d That is, list all the source files whose directory name matches the regexp '-d'. The expectation is that no source files will be listed. Unfortunately, when I ran the test some source files are listed; the directory I am running in contains the pattern '-d', and so the test fails. As we cannot control where the developer is building and testing GDB, I propose that instead of just testing with '-d' we should search through all the letters a-z and find one that isn't present in the source file directory name. I'm still including the leading '-' character in the regexp. So now, unless GDB is being built in a directory that contains '-a', '-b', '-c', .... '-z', the test will find one letter which isn't present, and use that for the test. To avoid test names changing between runs in different directories I've had to tweak the test name to something more generic, but there should be no change in which parts of GDB are actually being tested. Approved-By: Tom Tromey <tom@tromey.com>
6 days[gdb/testsuite] Reduce quoting in gdb.base/annota1.expTom de Vries1-7/+11
Reduce quoting in gdb.base/annota1.exp, mostly using string_to_regexp. Tested on arm-linux and x86_64-linux.
6 days[gdb/testsuite] Fix gdb.base/annota1.exp on arm-linuxTom de Vries1-0/+2
On arm-linux, gdb.base/annota1.exp fails: ... PASS: gdb.base/annota1.exp: breakpoint info run^M ^M ^Z^Zpost-prompt^M Starting program: /home/linux/gdb/build/gdb/testsuite/outputs/gdb.base/annota1/annota1 ^M ^M ^Z^Zbreakpoints-invalid^M ^M ^Z^Zframes-invalid^M ^M ^Z^Zstarting^M ^M ^Z^Zframes-invalid^M [Thread debugging using libthread_db enabled]^M Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".^M ^M ^Z^Zbreakpoints-invalid^M ^M ^Z^Zbreakpoint 1^M ^M Breakpoint 1, ^M ^Z^Zframe-begin 0 0x40054a^M ^M ^Z^Zframe-function-name^M main^M ^Z^Zframe-args^M ()^M ^Z^Zframe-source-begin^M at ^M ^Z^Zframe-source-file^M /home/linux/gdb/src/gdb/testsuite/gdb.base/annota1.c^M ^Z^Zframe-source-file-end^M :^M ^Z^Zframe-source-line^M 15^M ^Z^Zframe-source-end^M ^M ^M ^Z^Zsource /home/linux/gdb/binutils-gdb.git/gdb/testsuite/gdb.base/annota1.c:15:103:beg:0x40054a^M ^M ^Z^Zframe-end^M ^M ^Z^Zstopped^M ^M ^Z^Zpre-prompt^M (gdb) ^M ^Z^Zprompt^M FAIL: gdb.base/annota1.exp: run until main breakpoint (timeout) ... because the regexp doesn't match the first frames-invalid annotation. Fix this by adding an optional frames-invalid annotation in the regexp. Tested on arm-linux and x86_64-linux.
6 daysAdd setting to control frame language mismatch warningTom Tromey2-4/+4
A customer noted that there is no way to prevent the "current language does not match this frame" warning. This patch adds a new setting to allow this warning to be suppressed. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Andrew Burgess <aburgess@redhat.com>
9 daysgdb/testsuite: fix gdb.base/basic-edit-cmd.exp testAndrew Burgess1-1/+4
In the recent commit: commit 31ada87f91b4c5306d81c8a896df9764c32941f3 Date: Wed Nov 6 22:18:55 2024 +0000 gdb: fixes and tests for the 'edit' command the new gdb.base/basic-edit-cmd.exp was added. The Linaro CI highlighted an issue with the test which I failed to address before pushing the above commit. Part of the test loads a file into GDB and then uses the 'edit' command with no arguments to edit the default location. This default location is expected to be the 'main' function. On my local machine the line reported is the opening '{' of main, and that is what the test checks for. The Linaro CI though appears to see the first code line of main. I think either result is fine as far as this test is concerned, so I've expanded the test regexp to check for either line number. This should make the CI testing happy again.
9 daysgdb: fixes and tests for the 'edit' commandAndrew Burgess2-0/+209
This commit was inspired by this mailing list post: https://inbox.sourceware.org/gdb-patches/osmtfvf5xe3yx4n7oirukidym4cik7lehhy4re5mxpset2qgwt@6qlboxhqiwgm When reviewing that patch, the first thing I wanted to do was add some tests for the 'edit' command because, as far as I can tell, there are no real tests right now. The approach I've taken for testing is to override the EDITOR environment variable, setting this to just 'echo'. Now when the 'edit' command is run, instead of entering an interactive editor, the shell instead echos back the arguments that GDB is trying to pass to the editor. The output might look like this: (gdb) edit +22 /tmp/gdb/testsuite/gdb.base/edit-cmd.c (gdb) We can then test this like any other normal command. I then wrote some basic tests covering a few situations like, using 'edit' before the inferior is started. Using 'edit' without any arguments, and using 'edit' with a line number argument. There are plenty of cases that are still not tested, for example, the test program only has a single source file for example. But we can always add more tests later. I then used these tests to validate the fix proposed in the above patch. The patch above does indeed fix some cases, specifically, when GDB stops at a location (e.g. a breakpoint location) and then the 'edit' command without any arguments is fixed. But using the 'list' command to show some other location, and then 'edit' to edit the just listed location broken before and after the above patch. I am instead proposing this alternative patch which I think fixes more cases. When GDB stops at a location then 'edit' with no arguments should correctly edit the current line. And using 'list XX' to list a specific location, followed by 'edit' should also now edit the just listed location. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17669 Co-Authored-By: LluĂ­s Batlle i Rossell <viric@viric.name> Approved-By: Tom Tromey <tom@tromey.com>
13 daysgdb: add filename option supportAndrew Burgess2-7/+95
This commit adds support for filename options to GDB's option sub-system (see cli/cli-option.{c,h}). The new filename options support quoted and escaped filenames, and tab completion is fully supported. This commit adds the new option, and adds these options to the 'maintenance test-options' command as '-filename', along with some tests that exercise this new option. I've split the -filename testing into two. In gdb.base/options.exp we use the -filename option with some arbitrary strings. This tests that GDB can correctly extract the value from a filename option, and that GDB can complete other options after a filename option. However, these tests don't actually pass real filenames, nor do they test filename completion. In gdb.base/filename-completion.exp I have added some tests that test the -filename option with real filenames, and exercise filename tab completion. This commit doesn't include any real uses of the new filename options, that will come in the next commit.
2024-10-26gdb/testsuite: fix test pattern after switch to -lbl matchingAndrew Burgess1-3/+3
After commit: commit a1ccc78ea7ba8cad3ff37cbde9b5d3bba0194796 Date: Fri Oct 25 06:14:03 2024 +0200 [gdb/testsuite] Fix some test-cases for check-read1 (-lbl) I notice that gdb.base/sect-cmd.exp would sometimes fail. The problem is that by switching to line by line matching we now need to ensure that the gdb_test_multiple patterns match up to the end of the line, but don't actually include the trailing \r\n (yeah, our line by line matching is weird). We need to be especially careful anywhere '.*' is used as this can potentially match content on a subsequent line. I have replaced '.*' with '\[^\r\n\]*(?=\r\n)', matching everything up to the end of the line, but not the end of line itself, and I've made use of '(?=\r\n)' in a couple of other places to ensure we match up to the end of the line, but don't match the line terminator itself.
2024-10-25[gdb/testsuite] Fix some test-cases for check-read1 (-lbl)Tom de Vries1-7/+14
I ran the testsuite in an environment simulating a stressed system in combination with check-read1. This exposes a few more FAILs. Fix some by using -lbl. Tested on x86_64-linux.
2024-10-25[gdb/testsuite] Fix some test-cases for check-read1 (pipe/grep)Tom de Vries5-13/+30
I ran the testsuite in an environment simulating a stressed system in combination with check-read1. This exposes a few more FAILs. Fix some by using pipe / grep to filter out unnecessary output. Tested on x86_64-linux.
2024-10-25[gdb/testsuite] Fix some test-cases for check-read1 (gdb_test_lines)Tom de Vries1-8/+6
I ran the testsuite in an environment simulating a stressed system in combination with check-read1. This exposes a few more FAILs. Fix some by using gdb_test_lines, as well as related gdb_get_lines. Tested on x86_64-linux.
2024-10-22[gdb/testsuite] Handle maint set dwarf synchronous off defaultTom de Vries1-1/+5
I ran the testsuite with a patch setting dwarf_synchronous to false by default, and ran into FAILs in test-cases gdb.dwarf2/dw2-inter-cu-error.exp and gdb.dwarf2/dw2-inter-cu-error-2.exp, because the expected DWARF errors did not show up as a result of the file command. Fix this by forcing "maint set dwarf synchronous on". Add the same in gdb.base/index-cache.exp, where this is also required. Tested on aarch64-linux.
2024-10-21[gdb/contrib] Handle dot in spellcheck.shTom de Vries3-3/+3
Add handling of '.' in gdb/contrib/spellcheck.sh. While we're at, simplify the sed invocation by using a single s command instead of 3 s commands. Also introduce sed_join and grep_join. Fix the following common misspellings: ... bandwith -> bandwidth emmitted -> emitted immediatly -> immediately suprize -> surprise thru -> through transfered -> transferred ... Verified with shellcheck.
2024-10-20gdb: fix 'maint info inline-frames' after 'stepi'Andrew Burgess1-0/+14
There is an invalid assumption within 'maint info inline-frames' which triggers an assert: (gdb) stepi 0x000000000040119d 18 printf ("Hello World\n"); (gdb) maintenance info inline-frames ../../src/gdb/inline-frame.c:554: internal-error: maintenance_info_inline_frames: Assertion `it != inline_states.end ()' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. ----- Backtrace ----- ... etc ... The problem is this assert: /* Stopped threads always have cached inline_state information. */ gdb_assert (it != inline_states.end ()); If you check out infrun.c and look in handle_signal_stop for the call to skip_inline_frames then you'll find a rather large comment that explains that we don't always compute the inline state information for performance reasons. So the assertion is not valid. I've updated the code so that if there is cached information we use that, but if there is not then we just create our own information for the current $pc of the current thread. This means that, if there is cached information, GDB still correctly shows which frame the inferior is in (it might not be in the inner most frame). If there is no cached information we will always display the inferior as being in the inner most frame, but that's OK, because if skip_inline_frames has not been called then GDB will have told the user they are in the inner most frame, so everything lines up. I've extended the test to check 'maint info inline-frames' after a stepi which would previously have triggered the assertion.
2024-10-10[gdb/breakpoints] Fix gdb.base/scope-hw-watch-disable.exp on arm-linuxTom de Vries1-0/+18
On arm-linux, with test-case gdb.base/scope-hw-watch-disable.exp I run into: ... (gdb) awatch a^M Can't set read/access watchpoint when hardware watchpoints are disabled.^M (gdb) PASS: $exp: unsuccessful attempt to create an access watchpoint rwatch b^M Can't set read/access watchpoint when hardware watchpoints are disabled.^M (gdb) PASS: $exp: unsuccessful attempt to create a read watchpoint continue^M Continuing.^M ^M Program received signal SIGSEGV, Segmentation fault.^M 0xf7ec82c8 in ?? () from /lib/arm-linux-gnueabihf/libc.so.6^M (gdb) FAIL: $exp: continue until exit ... Using "maint info break", we can see that the two failed attempts to set a watchpoint each left behind a stale "watchpoint scope" breakpoint: ... -5 watchpoint scope del y 0xf7ec569a inf 1 -5.1 y 0xf7ec569a inf 1 stop only in stack frame at 0xfffef4f8 -6 watchpoint scope del y 0xf7ec569a inf 1 -6.1 y 0xf7ec569a inf 1 stop only in stack frame at 0xfffef4f8 ... The SIGSEGV is a consequence of the stale "watchpoint scope" breakpoint: the same happens if we: - have can-use-hw-watchpoints == 1, - set one of the watchpoints, and - continue to exit. The problem is missing symbol info on libc which is supposed to tell which code is thumb. After doing "set arm fallback-mode thumb" the SIGSEGV disappears. Extend the test-case to check the "maint info break" command before and after the two failed attempts, to make sure that we catch the stale "watchpoint scope" breakpoints also on x86_64-linux. Fix this in watch_command_1 by moving creation of the "watchpoint scope" breakpoint after the call to update_watchpoint. Tested on x86_64-linux. PR breakpoints/31860 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31860
2024-10-09[gdb/testsuite] Fix gdb.base/reggroups.exp with check-read1Tom de Vries1-7/+21
On aarch64-linux, with make target check-read1, I run into: ... (gdb) info reg vector^M ... d19 {f = 0x0, u = 0x0, s = 0x0} {f =FAIL: gdb.base/reggroups.exp: fetch reggroup regs vector (timeout) 0, u = 0, s = 0}^M ... The problem is that while (as documented) the corresponding gdb_test_multiple doesn't work for vector registers, it doesn't skip them either. This causes the timeout, and it also causes the registers after a vector register not to be found. Fix this by using -lbl style matching. Make which reggroups and registers are found more explicit using verbose -log, which makes us notice that regnames with underscores are skipped, so fix that as well. While we're at it, this: ... set invalid_register_re "Invalid register .*" ... and this: ... -re $invalid_register_re { fail "$test (unexpected invalid register response)" } ... means that the prompt may or may not be consumed. Fix this by limiting the regexp to one line, and using exp_continue. While we're at it, improve readability of the complex regexp matching a single register by factoring out regexps. Tested on aarch64-linux and x86_64-linux.
2024-10-08Use ui-out tables in "maint print user-regs"Tom Tromey1-1/+1
This changes "maint print user-regs" to use ui-out tables rather than printfs. Approved-By: Andrew Burgess <aburgess@redhat.com>
2024-10-08[gdb/testsuite] Fix gdb.base/break-interp.exp with check-read1Tom de Vries1-17/+5
When running test-case gdb.base/break-interp.exp with check-read1, I run into: ... (gdb) info files^M ... 0x00007ffff7e75980 - 0x00007ffff7e796a0 @ 0x001f1970 is .bss in /data/vries/gdb/leap-15-5/build/gdb/testsuite/outputs/gdb.base/break-interp/break-interp-BINprelinkNOdebugNOFAIL: gdb.base/break-interp.exp: ldprelink=NO: ldsepdebug=NO: binprelink=NO: binsepdebug=NO: binpie=NO: INNER: symbol-less: info files (timeout) pieNO.d/libc.so.6^M ... The code has two adaptations to deal with the large output: - nested gdb_test_multiple, and - an exp_continue in the inner gdb_test_multiple. The former seems unnecessary, and the latter doesn't trigger often enough because of an incomplete hex number regexp, causing the timeout. Get rid of both of these, and use -lbl instead. Tested on x86_64-linux.
2024-10-06[gdb] Rerun spellcheck.shTom de Vries1-2/+2
Fix the following common misspellings: ... completetion -> completion inital -> initial ...
2024-10-06[gdb] Fix more common misspellingsTom de Vries1-1/+1
Fix the following common misspellings: ... addres -> address, adders behavour -> behavior, behaviour intented -> intended, indented ther -> there, their, the throught -> thought, through, throughout ... Tested on x86_64-linux.
2024-10-06[gdb] Fix common misspellingsTom de Vries15-16/+16
Fix the following common misspellings: ... accidently -> accidentally additonal -> additional addresing -> addressing adress -> address agaisnt -> against albiet -> albeit arbitary -> arbitrary artifical -> artificial auxillary -> auxiliary auxilliary -> auxiliary bcak -> back begining -> beginning cannonical -> canonical compatiblity -> compatibility completetion -> completion diferent -> different emited -> emitted emiting -> emitting emmitted -> emitted everytime -> every time excercise -> exercise existance -> existence fucntion -> function funtion -> function guarentee -> guarantee htis -> this immediatly -> immediately layed -> laid noone -> no one occurances -> occurrences occured -> occurred originaly -> originally preceeded -> preceded preceeds -> precedes propogate -> propagate publically -> publicly refering -> referring substract -> subtract substracting -> subtracting substraction -> subtraction taht -> that targetting -> targeting teh -> the thier -> their thru -> through transfered -> transferred transfering -> transferring upto -> up to vincinity -> vicinity whcih -> which whereever -> wherever wierd -> weird withing -> within writen -> written wtih -> with doesnt -> doesn't ... Tested on x86_64-linux.
2024-09-30Add line-number stylingTom Tromey2-7/+9
This patch adds separate styling for line numbers. That is, whenever gdb prints a source line number, it uses this style. v2 includes a change to ensure that %ps works in query. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-09-30gdb: fix filename completion in the middle of a lineAndrew Burgess1-0/+163
I noticed that filename completion in the middle of a line doesn't work as I would expect it too. For example, assuming '/tmp/filename' exists, and is the only file in '/tmp/' then when I do the following: (gdb) file "/tmp/filen<TAB> GDB completes to: (gdb) file "/tmp/filename" But, if I type this: (gdb) file "/tmp/filen "xxx" Then move the cursor to the end of '/tmp/filen' and press <TAB>, GDB will complete the line to: (gdb) file "/tmp/filename "xxx" But GDB will not insert the trailing double quote character. The reason for this is found in readline/readline/complete.c in the function append_to_match. This is the function that appends the trailing closing quote character, however, the closing quote is only inserted if the cursor (rl_point) is at the end (rl_end) of the line being completed. In this patch, what I do instead is add the closing quote in the function gdb_completer_file_name_quote, which is called from readline through the rl_filename_quoting_function hook. The docs for rl_filename_quoting_function say (see 'info readline'): "... The MATCH_TYPE is either 'SINGLE_MATCH', if there is only one completion match, or 'MULT_MATCH'. Some functions use this to decide whether or not to insert a closing quote character. ..." This is exactly what I'm doing in this patch, and clearly this is not an unusual choice. Now after completing a filename that is not at the end of the line GDB will add the closing quote character if appropriate. I have managed to write some tests for this. I send a line of text to GDB which includes a partial filename followed by a trailing string, I then send the escape sequence to move the cursor left, and finally I send the tab character. Obviously, expect doesn't actually see the complete output with the extra text "in place", instead expect sees the original line followed by some escape sequences to reflect the cursor movement, then an escape sequence to indicate that text is being inserted in the middle of a line, followed by the new characters ... it's a bit messy, but I think it holds together. Reviewed-By: Tom Tromey <tom@tromey.com>
2024-09-30gdb: fix for completing a second filename for a commandAndrew Burgess1-102/+120
After the recent filename completion changes I noticed that the following didn't work as expected: (gdb) file "/path/to/some/file" /path/to/so<TAB> Now, I know that the 'file' command doesn't actually take multiple filenames, but currently (and this was true before the recent filename completion changes too) the completion function doesn't know that the command only expects a single filename, and should complete any number of filenames. And indeed, this works: (gdb) file "/path/to/some/file" "/path/to/so<TAB> In this case I quoted the second path, and now GDB is happy to offer completions. It turns out that the problem in the first case is an off-by-one bug in gdb_completer_file_name_char_is_quoted. This function tells GDB if a character within the line being completed is escaped or not. An escaped character cannot be a word separator. The algorithm in gdb_completer_file_name_char_is_quoted is to scan forward through the line keeping track of whether we are inside double or single quotes, or if a character follows a backslash. When we find an opening quote we skip forward to the closing quote and then check to see if we skipped over the character we are looking for, if we did then the character is within the quoted string. The problem is that this "is character inside quoted string" check used '>=' instead if '>'. As a consequence a character immediately after a quoted string would be thought of as inside the quoted string. In our first example this means that the single white space character after the quoted string was thought to be quoted, and was not considered a word breaking character. As such, GDB would not try to complete the second path. And indeed, if we tried this: (gdb) file "/path/to/some/file" /path/to/so<TAB> That is, place multiple spaces after the first path, then GDB would consider the first space as quoted, but the second space is NOT quoted, and would be a word break. Now GDB does complete the second path. By changing '>=' to '>' in gdb_completer_file_name_char_is_quoted this bug is resolved, now the original example works and GDB will correctly complete the second path. For testing I've factored out the core of one testing proc, and I now run those tests multiple times, once with no initial path, once with an initial path in double quotes, once with an initial path in single quotes, and finally, with an unquoted initial path. Reviewed-By: Tom Tromey <tom@tromey.com>
2024-09-30gdb, testsuite: clean duplicate header includesGerlicher, Klaus1-1/+0
Some of the gdb and testsuite files double include some headers. While all headers use include guards, it helps a bit keeping the code base tidy. No functional change. Approved-by: Kevin Buettner <kevinb@redhat.com>
2024-09-24[gdb/cli] Show readline wrapping mode for maint info screenTom de Vries1-6/+22
With the same trigger patch adding "set horizontal-scroll-mode on" to INPUTRC as used in commit 250f1bbaf33 ("[gdb/testsuite] Fix gdb.tui/wrap-line.exp with wrapping disabled"), we can easily reproduce a failure in gdb.tui/wrap-line.exp mentioned in PR testsuite/31201: ... (gdb) 78901234567890123456789012345678901234567890123456789012345678901234567^M<890123456789012345678901234567890123456789012345678 ^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H^H9WFAIL: gdb.base/wrap-line.exp: term=ansi: width-hard-coded: wrap (timeout) ... The test-case expects wrapping, but that's disabled by horizontal-scroll-mode. Add a new line to "maint info screen", that describes the current readline wrapping mode, and use it in the test-case to handle the different cases. The reported values for the wrapping mode are as follows. Unsupported because of running in batch mode: ... $ gdb -q -batch -ex "maint info screen" Readline wrapping mode: unsupported (gdb batch mode). ... Unsupported because the terminal is not capable to move the cursor up: ... $ TERM=dumb gdb -q -ex "maint info screen" -ex q Readline wrapping mode: unsupported (terminal is not Cursor Up capable). ... Disabled by horizontal-scroll-mode: ... $ grep horizontal-scroll-mode ~/.inputrc set horizontal-scroll-mode on $ gdb -q -ex "maint info screen" -ex q Readline wrapping mode: disabled (horizontal-scroll-mode). ... Wrap done by readline because terminal is not auto wrap capable: ... $ TERM=ansi gdb -q -ex "maint info screen" -ex q Readline wrapping mode: readline (terminal is not auto wrap capable, last column reserved). ... Wrap done by terminal autowrap: ... $ TERM=xterm gdb -q -ex "maint info screen" -ex q Readline wrapping mode: terminal (terminal is auto wrap capable). ... Tested on x86_64-linux. Co-Authored-By: Bernd Edlinger <bernd.edlinger@hotmail.de> Approved-By: Tom Tromey <tom@tromey.com> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31201
2024-09-23[gdb/testsuite] Avoid large timeout in gdb.base/checkpoint.expTom de Vries1-18/+32
I ran the testsuite in an environment simulating a stressed system, and the only test-cases that timed out in gdb.base were gdb.base/checkpoint.exp and gdb.base/checkpoint-ns.exp (which includes gdb.base/checkpoints.exp). In test-case gdb.base/checkpoint.exp there's a part where the timeout is increased with 120 seconds (in the default case that's from 10 to 130), to accommodate for a single command creating 600+ checkpoints. Instead, rewrite the test to present a gdb prompt each time a checkpoint is created, for which the default timeout is sufficient. Also ensure that the amount of checkpoints added is exactly 600 rather than 600+. Tested on aarch64-linux. Approved-By: Tom Tromey <tom@tromey.com>
2024-09-23[gdb/testsuite] Fix gdb.base/return.exp on arm-linuxTom de Vries1-2/+2
After doing pre-commit testing of some patch on arm-linux, the Linaro CI reported: ... FAIL: 1 regressions: 1 improvements regressions.sum: === gdb tests === Running gdb:gdb.base/return.exp ... ERROR: no fileid for ccd235fdc9bf improvements.sum: === gdb tests === Running gdb:gdb.base/return.exp ... ERROR: no fileid for 017e9b314c5a ... The problem is the call to allow_float_test. It calls gdb_exit (for arm-linux only), and consequently kills the gdb instance setup by prepare_for_testing: ... if { [prepare_for_testing "failed to prepare" "return"] } { return -1 } set allow_float_test [allow_float_test] ... Fix this by moving the call to allow_float_test to before prepare_for_testing. Tested on arm-linux and x86_64-linux.
2024-09-23[gdb/testsuite] Make parse_args error out on remaining argsTom de Vries1-2/+1
I noticed that introducing a typo here in gdb.mi/mi-breakpoint-changed.exp: ... set bp_re [mi_make_breakpoint \ - -number $bp_nr \ + -nunber $bp_nr \ -type dprintf \ -func marker \ -script [string_to_regexp {["printf \"arg\" \""]}]] ... didn't make the test fail. Proc mi_make_breakpoint uses parse_args, but does not check the remaining args as parse_args suggests: ... proc parse_args { argset } { parse_list 2 args $argset "-" false # The remaining args should be checked to see that they match the # number of items expected to be passed into the procedure } ... We could add the missing check in mi_make_breakpoint, but I think the problem is likely to occur again because the name parse_args does not suggest that further action is required. Fix this instead by: - copying proc parse_args to new proc parse_some_args, - adding new proc check_no_args_left, and - calling check_no_args_left in parse_args. Also be more strict in a few places where we do lassign for remaining args: ... lassign $args a b ... There may be more arguments left in $args, so check that that's not the case using check_no_args_left: ... set args [lassign $args a b] check_no_args_left ... Fix a few test-cases that trigger on the stricter checking. Tested on x86_64-linux. Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com> PR testsuite/32129 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32129
2024-09-23[gdb/testsuite] Fix gdb.base/empty-host-env-vars.expTom de Vries1-23/+9
On aarch64-linux (debian testing) with test-case gdb.base/empty-host-env-vars.exp I ran into: ... (gdb) show index-cache directory^M The directory of the index cache is "/home/linux/.cache/gdb".^M (gdb) FAIL: $exp: env_var_name=HOME: show index-cache directory ... Without changing any environment variables, the value of the index-cache dir is: ... $ gdb -q -batch -ex "show index-cache directory" The directory of the index cache is "/home/linux/.cache/gdb". ... and the expectation of the test-case is that setting HOME to empty will produce an empty dir, but what it actually produces is: ... $ HOME= gdb -q -batch -ex "show index-cache directory" The directory of the index cache is "/home/linux/.cache/gdb". ... There's nothing wrong with that behaviour, the dir is simply constructed using XDG_CACHE_HOME which happens to be explictly set to its default value $HOME/.cache [1]: ... $ echo $XDG_CACHE_HOME /home/linux/.cache ... and indeed also setting that variable to empty gets us the expected empty dir: ... $ XDG_CACHE_HOME= HOME= gdb -q -batch -ex "show index-cache directory" gdb: warning: Couldn't determine a path for the index cache directory. The directory of the index cache is "". ... Furthermore, the test-case assumption that setting variables to empty either produces the original dir or an empty dir is incorrect. Say that XDG_CACHE_HOME has a non-default value: ... $ echo $XDG_CACHE_HOME /home/linux/my-xdg-cache-home $ gdb -q -batch -ex "show index-cache directory" The directory of the index cache is "/home/linux/my-xdg-cache-home/gdb". ... then setting that variable to empty: ... $ XDG_CACHE_HOME= gdb -q -batch -ex "show index-cache directory" The directory of the index cache is "/home/linux/.cache/gdb". ... does change the value of the dir. Fix this by making the test-case less specific. While we're at it, factor out regexps re_pre and re_post to make regexps more readable, and use string_to_regexp to reduce quoting. Tested on aarch64-linux. PR testsuite/32132 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32132 [1] https://specifications.freedesktop.org/basedir-spec/latest/index.html#variables
2024-09-23[gdb/testsuite] Fix gdb.base/attach-deleted-exec.exp with NFSTom de Vries1-3/+21
With test-case gdb.base/attach-deleted-exec.exp I ran into: ... (gdb) attach 121552^M Attaching to process 121552^M Reading symbols .../attach-deleted-exec/.nfs00000000044ff2ef00000086...^M Reading symbols from /lib64/libm.so.6...^M (No debugging symbols found in /lib64/libm.so.6)^M Reading symbols from /lib64/libc.so.6...^M (No debugging symbols found in /lib64/libc.so.6)^M Reading symbols from /lib64/ld64.so.2...^M (No debugging symbols found in /lib64/ld64.so.2)^M 0x00007fff947cc838 in clock_nanosleep@@GLIBC_2.17 () from /lib64/libc.so.6^M (gdb) FAIL: $exp: attach to process with deleted executable .... The .nfs file indicates: - that the file has been removed on the NFS server, and - that the file is still open on the NFS client. Fix this by detecting this situation, and declaring the test for filename /proc/PID/exe unsupported. Tested on: - x86_64-linux (setup without NFS) - ppc64le-linux (setup with NFS) PR testsuite/32130 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32130
2024-09-20gdb/testsuite: rework bp-cond-failure to not depend on inliningGuinevere Larsen2-20/+40
The test gdb.base/bp-cond-failure is implicitly expecting that the function foo will be inlined twice and gdb will be able to find 2 locations to place a breakpoint. When clang is used, gdb only finds one location which causes the test to fail. Since the test is not worried about handling breakpoints on inlined functions, but rather on the format of the message on a breakpoint condition fail, this seems like a false fail report. This commit reworks the test to be in c++, and uses function overloading to ensure that 2 locations will always be found. Empirical testing showed that, for clang, we will land on location 2 with the currest exp commands, no matter the order of the functions declared, whereas for gcc it depends on the order that functions were declared, so they are ordered to always land on the second location, this way we are able to hardcode it and check for it. Reviewed-by: Keith Seitz <keiths@redhat.com> Approved-By: Tom Tromey <tom@tromey.com>
2024-09-10gdb/testsuite: add return after a call to 'untested'Andrew Burgess1-3/+4
In gdb.base/corefile-buildid.exp, in the function do_corefile_buildid_tests, if we fail to find the build-id for the test binary then we call 'untested', but then push on with the test, which inevitably fails as the rest of the test depends on having found the build-id. I think we're missing a 'return' after the call to 'untested' which I've now added. Also I noticed that we call build_id_debug_filename_get and then manually remove '.debug' from the end. This is no longer necessary, we can just ask build_id_debug_filename_get to not add the suffix.
2024-09-07gdb: parse pending breakpoint thread/task immediatelyAndrew Burgess2-4/+83
The initial motivation for this commit was to allow thread or inferior specific breakpoints to only be inserted within the appropriate inferior's program-space. The benefit of this is that inferiors for which the breakpoint does not apply will no longer need to stop, and then resume, for such breakpoints. This commit does not make this change, but is a refactor to allow this to happen in a later commit. The problem we currently have is that when a thread-specific (or inferior-specific) breakpoint is created, the thread (or inferior) number is only parsed by calling find_condition_and_thread_for_sals. This function is only called for non-pending breakpoints, and requires that we know the locations at which the breakpoint will be placed (for expression checking in case the breakpoint is also conditional). A consequence of this is that by the time we figure out the breakpoint is thread-specific we have already looked up locations in all program spaces. This feels wasteful -- if we knew the thread-id earlier then we could reduce the work GDB does by only looking up locations within the program space for which the breakpoint applies. Another consequence of how find_condition_and_thread_for_sals is called is that pending breakpoints don't currently know they are thread-specific, nor even that they are conditional! Additionally, by delaying parsing the thread-id, pending breakpoints can be created for non-existent threads, this is different to how non-pending breakpoints are handled, so I can do this: $ gdb -q ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp Reading symbols from ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp... (gdb) break foo thread 99 Function "foo" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (foo thread 99) pending. (gdb) r Starting program: /tmp/gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Error in re-setting breakpoint 1: Unknown thread 99. [Inferior 1 (process 3329749) exited normally] (gdb) GDB only checked the validity of 'thread 99' at the point the 'foo' location became non-pending. In contrast, if I try this: $ gdb -q ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp Reading symbols from ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp... (gdb) break main thread 99 Unknown thread 99. (gdb) GDB immediately checks if 'thread 99' exists. I think inconsistencies like this are confusing, and should be fixed if possible. In this commit the create_breakpoint function is updated so that the extra_string, which contains the thread, inferior, task, and/or condition information, is parsed immediately, even for pending breakpoints. Obviously, the condition still can't be validated until the breakpoint becomes non-pending, but the thread, inferior, and task information can be pulled from the extra-string, and can be validated early on, even for pending breakpoints. The -force-condition flag is also parsed as part of this early parsing change. There are a couple of benefits to doing this: 1. Printing of breakpoints is more consistent now. Consider creating a conditional breakpoint before this commit: (gdb) set breakpoint pending on (gdb) break pendingfunc if (0) Function "pendingfunc" not defined. Breakpoint 1 (pendingfunc if (0)) pending. (gdb) break main if (0) Breakpoint 2 at 0x401198: file /tmp/hello.c, line 18. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <PENDING> pendingfunc if (0) 2 breakpoint keep y 0x0000000000401198 in main at /tmp/hello.c:18 stop only if (0) (gdb) And after this commit: (gdb) set breakpoint pending on (gdb) break pendingfunc if (0) Function "pendingfunc" not defined. Breakpoint 1 (pendingfunc) pending. (gdb) break main if (0) Breakpoint 2 at 0x401198: file /home/andrew/tmp/hello.c, line 18. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y <PENDING> pendingfunc stop only if (0) 2 breakpoint keep y 0x0000000000401198 in main at /home/andrew/tmp/hello.c:18 stop only if (0) (gdb) Notice that the display of the condition is now the same for the pending and non-pending breakpoints. The same is true for the thread, inferior, or task information in thread, inferior, or task specific breakpoints; this information is displayed on its own line rather than being part of the 'What' field. 2. We can check that the thread exists as soon as the pending breakpoint is created. Currently there is a weird difference between pending and non-pending breakpoints when creating a thread-specific breakpoint. A pending thread-specific breakpoint only checks its thread when it becomes non-pending, at which point the thread the breakpoint was intended for might have exited. Here's the behaviour before this commit: (gdb) set breakpoint pending on (gdb) break foo thread 2 Function "foo" not defined. Breakpoint 2 (foo thread 2) pending. (gdb) c Continuing. [Thread 0x7ffff7c56700 (LWP 2948835) exited] Error in re-setting breakpoint 2: Unknown thread 2. [Inferior 1 (process 2948832) exited normally] (gdb) Notice the 'Error in re-setting breakpoint 2: Unknown thread 2.' line, this was triggered when GDB tried to make the breakpoint non-pending, and GDB discovers that the thread no longer exists. Compare that to the behaviour after this commit: (gdb) set breakpoint pending on (gdb) break foo thread 2 Function "foo" not defined. Breakpoint 2 (foo) pending. (gdb) c Continuing. [Thread 0x7ffff7c56700 (LWP 2949243) exited] Thread-specific breakpoint 2 deleted - thread 2 no longer in the thread list. [Inferior 1 (process 2949240) exited normally] (gdb) Now the behaviour for pending breakpoints is identical to non-pending breakpoints, the thread specific breakpoint is removed as soon as the thread the breakpoint is associated with exits. There is an additional change; when the pending breakpoint is created prior to this patch we see this line: Breakpoint 2 (foo thread 2) pending. While after this patch we get this line: Breakpoint 2 (foo) pending. Notice that 'thread 2' has disappeared. This might look like a regression, but I don't think it is. That we said 'thread 2' before was just a consequence of the lazy parsing of the breakpoint specification, while with this patch GDB understands, and has parsed away the 'thread 2' bit of the spec. If folk think the old information was useful then this would be trivial to add back in code_breakpoint::say_where. As a result of this commit the breakpoints 'extra_string' field is now only used by bp_dprintf type breakpoints to hold the printf format and arguments. This string should always be empty for other breakpoint types. This allows some cleanup in print_breakpoint_location. In code_breakpoint::code_breakpoint I've changed an error case into an assert. This is because the error is now handled earlier in create_breakpoint. As a result we know that by this point, the extra_string will always be nullptr for anything other than a bp_dprintf style breakpoint. The find_condition_and_thread_for_sals function is now no longer needed, this was previously doing the delayed splitting of the extra string into thread, task, and condition, but this is now all done in create_breakpoint, so find_condition_and_thread_for_sals can be deleted, and the code that calls this in code_breakpoint::location_spec_to_sals can be removed. With this update this code would only ever be reached for bp_dprintf style breakpoints, and in these cases the extra_string should not contain anything other than format and args. The most interesting changes are all in create_breakpoint and in the new file break-cond-parse.c. We have a new block of code early on in create_breakpoint that is responsible for splitting the extra_string into its component parts by calling create_breakpoint_parse_arg_string a function in the new break-cond-parse.c file. This means that some of the later code can be simplified a little. The new break-cond-parse.c file implements the splitting up the extra_string and finding all the parts, as well as some self-tests for the new function. Finally, now we know all the breakpoint details, these can be stored within the breakpoint object if we end up creating a deferred breakpoint. Additionally, if we are creating a deferred bp_dprintf we can parse the extra_string to build the printf command. The implementation here aims to maintain backwards compatibility as much as possible, this means that: 1. We support abbreviations of 'thread', 'task', and 'inferior' in some places on the breakpoint line. The handling of abbreviations has (before this patch) been a little weird, so this works: (gdb) break *main th 1 And creates a breakpoint at '*main' for thread 1 only, while this does not work: (gdb) break main th 1 In this case GDB will try to find the symbol 'main th 1'. This weirdness exists before and after this patch. 2. The handling of '-force-condition' is odd, if this flag appears immediately after a condition then it will be treated as part of the condition, e.g.: (gdb) break main if 0 -force-condition No symbol "force" in current context. But we are fine with these alternatives: (gdb) break main if 0 thread 1 -force-condition (gdb) break main -force-condition if 0 Again, this is just a quirk of how the breakpoint line used to be parsed, but I've maintained this for backward compatibility. During review it was suggested that -force-condition should become an actual breakpoint flag (i.e. only valid after the 'break' command but before the function name), and I don't think that would be a terrible idea, however, that's not currently a trivial change, and I think should be done as a separate piece of work. For now, this patch just maintains the current behaviour. The implementation works by first splitting the breakpoint condition string (everything after the location specification) into a list of tokens, each token has a type and a value. (e.g. we have a THREAD token where the value is the thread-id string). The list of tokens is validated, and in some cases, tokens are merged. Then the values are extracted from the remaining token list. Consider this breakpoint command: (gdb) break main thread 1 if argc == 2 The condition string passed to create_breakpoint_parse_arg_string is going to be 'thread 1 if argc == 2', which is then split into the tokens: { THREAD: "1" } { CONDITION: "argc == 2" } The thread-id (1) and the condition string 'argc == 2' are extracted from these tokens and returns back to create_breakpoint. Now consider this breakpoint command: (gdb) break some_function if ( some_var == thread ) Here the user wants a breakpoint if 'some_var' is equal to the variable 'thread'. However, when this is initially parsed we will find these tokens: { CONDITION: "( some_var == " } { THREAD: ")" } This is a consequence of how we have to try and figure out the contents of the 'if' condition without actually parsing the expression; parsing the expression requires that we know the location in order to lookup the variables by name, and this can't be done for pending breakpoints (their location isn't known yet), and one of the points of this work is that we extract things like thread-id for pending breakpoints. And so, it is in this case that token merging takes place. We check if the value of a token appearing immediately after the CONDITION token looks valid. In this case, does ')' look like a valid thread-id. Clearly, in this case ')' does not, and so me merge the THREAD token into the condition token, giving: { CONDITION: "( some_var == thread )" } Which is what we want. I'm sure that we might still be able to come up with some edge cases where the parser makes the wrong choice. I think long term the best way to work around these would be to move the thread, inferior, task, and -force-condition flags to be "real" command options for the break command. I am looking into doing this, but can't guarantee if/when that work would be completed, so this patch should be reviewed assume that the work will never arrive (though I hope it will). Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-09-07gdb: 'target ...' commands now expect quoted/escaped filenamesAndrew Burgess2-4/+4
This commit changes the 'target ...' commands that accept a filename to take a quoted or escaped filename rather than a literal filename. What this means in practice is that if you are specifying a filename that contains no white space or quote characters, then nothing should change, e.g.: target exec /path/to/some/file works both before and after this commit. However, if a user wishes to specify a file containing white space then either the entire filename needs to be quoted, or the special white space needs to be escaped. Before this patch a user could write: target exec /path/to a file/containing spaces But after this commit the user would have to choose one of: target exec "/path/to a file/containing spaces" or target exec /path/to\ a\ file/containing\ spaces Obviously this is a potentially breaking change. The benefit of making this change is consistency. Commands that take multiple arguments (one of which is a filename) or in the future, commands that take filename options, will always need to use quoted/escaped filenames, so converting all unquoted filename commands to use quoting or escaping makes the UI more consistent. Additionally (though this is probably not a common problem), GDB strips trailing white space from commands that the user enters. As such it is not possible to reference any file that ends in white space unless the quoting / escaping style is used. Though I suspect very few users run into this problem! The downside obviously is that this is a UI breaking change. Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-09-07gdb: allow quoted filenames for commands that have custom completionAndrew Burgess1-2/+4
This commit changes how GDB processes command arguments for the following commands: compile file maint print c-tdesc save gdb-index After this commit these commands will now expect their single filename argument to be (optionally) quoted if it contains any special characters (e.g. whit space or quotes). If the filename does not contain any special characters then nothing changes. As an example: (gdb) save gdb-index /path/to/some/directory/ will work before and after this patch. However, if the directory name contains a white space then before this patch a user would write: (gdb) save gdb-index /path/to some/directory/ But this will now fail as GDB will consider this as two arguments, '/path/to' and 'some/directory/'. To pass this single directory name a user must now do one of these: (gdb) save gdb-index "/path/to some/directory/" (gdb) save gdb-index '/path/to some/directory/' (gdb) save gdb-index /path/to\ some/directory/ This brings these commands into line with commands like 'file' and 'symbol-file', which have supported quoted filenames for a while. The motivation for this change is to make handling of filename arguments consistent throughout GDB. We can't move to all commands taking non-quoted filenames as the non-quoted style only allows for a single argument. Additionally, the non-quoted style doesn't allow for filenames that end in white space (though this is probably pretty rare). So, if we want to have consistency the only choice is to move towards supporting quote filenames. Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-09-07gdb: add remove-symbol-file command completionAndrew Burgess2-119/+142
The 'remove-symbol-file' command doesn't currently offer command completion. This commit addresses this. The 'remove-symbol-file' uses gdb_argv to split its command arguments, this means that the filename the command expects can be quoted. However, the 'remove-symbol-file' command is a little weird in that it also has a '-a' option, if this option is passed then the command expects not a filename, but an address. Currently the remove_symbol_file_command function splits the command args using gdb_argv, checks for a '-a' flag by looking at the first argument value, and then expects the filename or address to occupy a single entry in the gdb_argv array. The first thing I do is handle the '-a' flag using GDB's option system. I model this option as a flag_option_def (a boolean option). I've dropped the use of gdb_argv and instead use the new(ish) function extract_single_filename_arg, which was added a couple of commits back, to parse the filename argument (when '-a' is not given). If '-a' is given the the remove-symbol-file command expects an address rather than a filename. As we previously split the arguments using gdb_argv this meant the address needed to appear as a single argument. So a user could write: (gdb) remove-symbol-file 0x1234 Or they could write: (gdb) remove-symbol-file some_function Both of these would work fine. But a user could not write: (gdb) remove-symbol-file some_function + 0x1000 As only the 'some_function' part would be processed. Now the user could do this: (gdb) remove-symbol-file "some_function + 0x1000" By enclosing the address expression in quotes this would be handled as a single argument. However, this is a little weird, that's not how commands like 'print' or 'x' work. Also this functionality was neither documented, or tested. And so, in this commit, by removing the use of gdb_argv I bring the 'remove-symbol-file' command inline with GDB's other commands that take an expression, the quotes are no longer needed. Usually in a completer we call 'complete_options', but don't actually capture the option values. But for remove-symbol-file I do. This allows me to spot when the '-a' option has been given, I can then complete the rest of the command line as either a filename or an expression. Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-09-07gdb: implement readline rl_directory_rewrite_hook callbackAndrew Burgess1-0/+12
Implement the readline rl_directory_rewrite_hook callback function, this is used when readline needs to offer completions from within a directory. The important thing is that this function should remove any escaping, this allows GDB to correctly offer completions in situations like this: (gdb) file /tmp/directory\ with\ spaces/<TAB><TAB> Note the escaping in 'directory\ with\ spaces'. Without the rl_directory_rewrite_hook callback readline will try to open a directory literally called '/tmp/directory\ with\ spaces' which obviously doesn't exist. There are tests added to cover this new functionality.
2024-09-07gdb: improve gdb_rl_find_completion_word for quoted wordsAndrew Burgess1-8/+4
The function gdb_rl_find_completion_word is very similar to the readline function _rl_find_completion_word, but was either an older version of that function, or was trimmed when copying to remove code which was considered unnecessary. We maintain this copy because the _rl_find_completion_word function is not part of the public readline API, and we need to replicate the functionality of that function as part of the 'complete' command. Within gdb_rl_find_completion_word when looking for the completion word, if we don't find a unclosed quoted string (which would become the completion word) then we scan backwards looking for a word break character. For example, given: (gdb) complete file /tmp/foo There is no unclosed quoted string so we end up scanning backwards from the end looking for a word break character. In this case the space after 'file' and before '/tmp/foo' is found, so '/tmp/foo' becomes the completion word. However, given this: (gdb) complete file /tmp/foo\" There is still no unclosed quoted string, however, when we can backwards the '"' (double quotes) are treated as a word break character, and so we end up using the empty string as the completion word. The readline function _rl_find_completion_word avoids this mistake by using the rl_char_is_quoted_p hook. This function will return true for the double quote character as it is preceded by a backslash. An earlier commit in this series supplied a rl_char_is_quoted_p function for the filename completion case, however, gdb_rl_find_completion_word doesn't call rl_char_is_quoted_p so this doesn't help for the 'complete' case. In this commit I've copied the code to call rl_char_is_quoted_p from _rl_find_completion_word into gdb_rl_find_completion_word. This half solves the problem. In the case: (gdb) complete file /tmp/foo\" We do now try to complete on the string '/tmp/foo\"', however, when we reach filename_completer we call back into readline to actually perform filename completion. However, at this point the WORD variable points to a string that still contains the backslash. The backslash isn't part of the actual filename, that's just an escape character. Our expectation is that readline will remove the backslash when looking for matching filenames. However, readline contains an optimisation to avoid unnecessary work trying to remove escape characters. The readline variable rl_completion_found_quote is set in the readline function gen_completion_matches before the generation of completion matches. This variable is set to true (non-zero) if there is (or might be) escape characters within the completion word. The function rl_filename_completion_function, which generates the filename matches, only removes escape characters when rl_completion_found_quote is true. When GDB generates completions through readline (e.g. tab completion) then rl_completion_found_quote is set correctly. But when we use the 'complete' command we don't pass through readline, and so gen_completion_matches is never called and rl_completion_found_quote is not set. In this case when we call rl_filename_completion_function readline doesn't remove the escapes from the completion word, and so in our case above, readline looks for completions of the exact filename '/tmp/foo\"', that is, the filename including the backslash. To work around this problem I've added a new flag to our function gdb_rl_find_completion_word which is set true when we find any quoting or escaping. This matches what readline does. Then in the 'complete' function we can set rl_completion_found_quote prior to generating completion matches. With this done the 'complete' command now works correctly when trying to complete filenames that contain escaped word break characters. The tests have been updated accordingly.
2024-09-07gdb: apply escaping to filenames in 'complete' resultsAndrew Burgess1-37/+63
Building on the mechanism added in the previous commit(s), this commit applies escaping to filenames in the 'complete' command output. Consider a file: /tmp/xxx/aa"bb -- that is a filename that contains a double quote, currently the 'complete' command output looks like this: (gdb) complete file /tmp/xxx/a file /tmp/xxx/aa"bb Notice that the double quote in the output is not escaped. If we passed this same output back to GDB then the double quote will be treated as the start of a string. After this commit then the output looks like this: (gdb) complete file /tmp/xxx/a file /tmp/xxx/aa\"bb The double quote is now escaped. If we feed this output back to GDB then GDB will treat this as a single filename that contains a double quote, exactly what we want. To achieve this I've done a little refactoring, splitting out the core of gdb_completer_file_name_quote, and then added a new call from the filename_match_formatter function. There are updates to the tests to cover this new functionality.
2024-09-07gdb: add match formatter mechanism for 'complete' command outputAndrew Burgess1-19/+49
This commit solves a problem that existed prior to the previous commit, but the previous commit made more common. When completing a filename with the 'complete' command GDB will always add a trailing quote character, even if the completion is a directory name, in which case it would be better if the trailing quote was not added. Consider: (gdb) complete file '/tmp/xx file '/tmp/xxx/' The completion offered here is really only a partial completion, we've completed up to the end of the next directory name, but, until we have a filename then the completion is not finished and the trailing quote should not be added. This would match the readline behaviour, e.g.: (gdb) file '/tmp/xx<TAB> (gdb) file '/tmp/xxx/ In this case readline completes the directory name, but doesn't add the trailing quote character. Remember that the 'complete' command is intended for tools like e.g. emacs in order that they can emulate GDB's standard readline completion when implementing a CLI of their own. As such, not adding the trailing quote in this case matches the readline behaviour, and seems like the right way to go. To achieve this, I've added a new function pointer member variable completion_result::m_match_formatter. This contains a pointer to a callback function which is used by the 'complete' command to format each result. The default behaviour of this callback function is to just append the quote character (the character from before the completion string) to the end of the completion result. This matches the current behaviour. However, for filename completion we override the default value of m_match_formatter, this new function checks if the completion result is a directory or not. If the completion result is a directory then the closing quote is not added, instead we add a trailing '/' character. The code to add a trailing '/' character already exists within the filename_completer function. This is no longer needed in this location, instead this code is moved into the formatter callback. Tests are updated to handle the changes in functionality, this removes an xfail added in the previous commit.
2024-09-07gdb: simplify completion_result::print_matchesAndrew Burgess1-2/+19
Simplify completion_result::print_matches by removing one of the code paths. Now, every time we call ::print_matches we always add the trailing quote. Previously, when using the 'complete' command, if there was only one result then trailing quote was added in ::build_completion_result, but when we had multiple results the trailing quote was added in ::print_matches. As a consequence, ::print_matches had to understand not to add the trailing quote for the single result case. After this commit we don't add the trailing quote in ::build_completion_result, instead ::print_matches always adds the trailing quote, which makes ::print_matches simpler. However, there is a slight problem. When completion is being driven by readline, and not by the 'complete' command, we still need to manually add the trailing quote in the single result case, and as the printing is done by readline we can't add the quote at the time of printing, and so, in ::build_completion_result, we still add the trailing quote, but only when completion is being done for readline. And this does cause a small problem. When completing a filename, if the completion results in a directory name then, when using the 'complete' command, GDB should not be adding a trailing quote. For example, if we have the file /tmp/xxx/foo.c, then what we should see is this: (gdb) complete file '/tmp/xx file 'tmp/xxx/ But what we actually see after this commit is this: (gdb) complete file '/tmp/xx file 'tmp/xxx/' Previously we didn't get the trailing quote in this case, as when there is only a single result, the quote was added in ::build_completion_result, and for filename completion, GDB didn't know what the quote character was in ::build_completion_result, so no quote was added. Now that the trailing quote is always added in ::print_matches, and GDB does know the quote character at this point, so we are now getting the trailing quote, which is not correct. This is a regression, but really, GDB is now broken in a consistent way, if we create the file /tmp/xxa/bar.c, then previously if we did this: (gdb) complete file '/tmp/xx file '/tmp/xxa/' file '/tmp/xxx/' Notice how we get the trailing quote in this case, this is the before patch behaviour, and is also wrong. A later commit will fix things so that the trailing quote is not added in this filename completion case, but for now I'm going to accept this small regression. This change in behaviour caused some failures in one of the completion tests, I've tweaked the test case to expect the trailing quote as part of this commit, but will revert this in a later commit in this series. I've also added an extra test for when the 'complete' command does complete to a single complete filename, in which case the trailing quote is expected.
2024-09-07gdb: improve escaping when completing filenamesAndrew Burgess1-0/+34
This improves quoting and escaping when completing filenames for commands that allow filenames to be quoted and escaped. I've struggled a bit trying to split this series into chunks. There's a lot of dependencies between different parts of the completion system, and trying to get this working correctly is pretty messy. This first step is really about implementing 3 readline hooks: rl_char_is_quoted_p - Is a particular character quoted within readline's input buffer? rl_filename_dequoting_function - Remove quoting characters from a filename. rl_filename_quoting_function - Add quoting characters to a filename. See 'info readline' for full details, but with these hooks connected up, readline (on behalf of GDB) should do a better job inserting backslash escapes when completing filenames. There's still a bunch of stuff that doesn't work after this commit, mostly around the 'complete' command which of course doesn't go through readline, so doesn't benefit from all of these new functions yet, I'll add some of this in a later commit. Tab completion is now slightly improved though, it is possible to tab-complete a filename that includes a double or single quote, either in an unquoted string or within a string surrounded by single or double quotes, backslash escaping is used when necessary. There are some additional tests to cover the new functionality.
2024-09-07gdb: split apart two different types of filename completionAndrew Burgess1-49/+160
Unfortunately we have two different types of filename completion in GDB. The majority of commands have what I call unquoted filename completion, this is for commands like 'set logging file ...', 'target core ...', and 'add-auto-load-safe-path ...'. For these commands everything after the command name (that is not a command option) is treated as a single filename. If the filename contains white space then this does not need to be escaped, nor does the filename need to be quoted. In fact, the filename argument is not de-quoted, and does not have any escaping removed, so if a user does try to add such things, they will be treated as part of the filename. As an example: (gdb) target core "/path/that contains/some white space" Will look for a directory calls '"' (double quotes) in the local directory. A small number of commands do de-quote and remove escapes from filename arguments. These command accept what I call quoted and escaped filenames. Right now these are the commands that specify the file for GDB to debug, so: file exec-file symbol-file add-symbol-file remove-symbol-file As an example of this in action: (gdb) file "/path/that contains/some white space" In this case GDB would load the file: /path/that contains/some white space Current filename completion always assumes that filenames can be quoted, though escaping doesn't work in completion right now. But the assumption that quoting is allowed is clearly wrong. This commit splits filename completion into two. The existing filename_completer is retained, and is used for unquoted filenames. A second filename_maybe_quoted_completer is added which can be used for completing quoted filenames. The filename completion test has been extended to cover more cases. As part of the extended testing I need to know the character that should be used to separate filenames within a path. For this TCL 8.6+ has $::tcl_platform(pathSeparator). To support older versions of TCL I've added some code to testsuite/lib/gdb.exp. You might notice that after this commit the completion for unquoted files is all done in the brkchars phase, that is the function filename_completer_handle_brkchars calculates the completions and marks the completion_tracker as using a custom word point. The reason for this is that we don't want to break on white space for this completion, but if we rely on readline to find the completion word, readline will consider the entire command line, and with no white space in the word break character set, readline will end up using the entire command line as the word to complete. For now at least, the completer for quoted filenames does generate its completions during the completion phase, though this is going to change in a later commit.
2024-09-07gdb: improve shared library build-id check for core-filesAndrew Burgess1-1/+5
When GDB opens a core file, in 'core_target::build_file_mappings ()', we collection information about the files that are mapped into the core file, specifically, the build-id and the DT_SONAME attribute for the file, which will be set for some shared libraries. We then cache the DT_SONAME to build-id information on the core file bfd object in the function set_cbfd_soname_build_id. Later, when we are loading the shared libraries for the core file, we can use the library's file name to look in the DT_SONAME to build-id map, and, if we find a matching entry, we can use the build-id to validate that we are loading the correct shared library. This works OK, but has some limitations: not every shared library will have a DT_SONAME attribute. Though it is good practice to add such an attribute, it's not required. A library without this attribute will not have its build-id checked, which can lead to GDB loading the wrong shared library. What I want to do in this commit is to improve GDB's ability to use the build-ids extracted in core_target::build_file_mappings to both validate the shared libraries being loaded, and then to use these build-ids to potentially find (via debuginfod) the shared library. To do this I propose making the following changes to GDB: (1) Rather than just recording the DT_SONAME to build-id mapping in set_cbfd_soname_build_id, we should also record, the full filename to build-id mapping, and also the memory ranges to build-id mapping for every memory range covered by every mapped file. (2) Add a new callback solib_ops::find_solib_addr. This callback takes a solib object and returns an (optional) address within the inferior that is part of this library. We can use this address to find a mapped file using the stored memory ranges which will increase the cases in which a match can be found. (3) Move the mapped file record keeping out of solib.c and into corelow.c. Future commits will make use of this information from other parts of GDB. This information was never solib specific, it lived in the solib.c file because that was the only user of the data, but really, the data is all about the core file, and should be stored in core_target, other parts of GDB can then query this data as needed. Now, when we load a shared library for a core file, we do the following lookups: 1. Is the exact filename of the shared library found in the filename to build-id map? If so then use this build-id for validation. 2. Find an address within the shared library using ::find_solib_addr and then look for an entry in the mapped address to build-id map. If an entry is found then use this build-id. 3. Finally, look in the soname to build-id map. If an entry is found then use this build-id. The addition of step #2 here means that GDB is now far more likely to find a suitable build-id for a shared library. Having acquired a build-id the existing code for using debuginfod to lookup a shared library object can trigger more often. On top of this, we also create a build-id to filename map. This is useful as often a shared library is implemented as a symbolic link to the actual shared library file. The mapped file information is stored based on the actual, real file name, while the shared library information holds the original symbolic link file name. If when loading the shared library, we find the symbolic link has disappeared, we can use the build-id to file name map to check if the actual file is still around, if it is (and if the build-id matches) then we can fall back to use that file. This is another way in which we can slightly increase the chances that GDB will find the required files when loading a core file. Adding all of the above required pretty much a full rewrite of the existing set_cbfd_soname_build_id function and the corresponding get_cbfd_soname_build_id function, so I have taken the opportunity to move the information caching out of solib.c and into corelow.c where it is now accessed through the function core_target_find_mapped_file. At this point the benefit of this move is not entirely obvious, though I don't think the new location is significantly worse than where it was originally. The benefit though is that the cached information is no longer tied to the shared library loading code. I already have a second set of patches (not in this series) that make use of this caching from elsewhere in GDB. I've not included those patches in this series as this series is already pretty big, but even if those follow up patches don't arrive, I think the new location is just as good as the original location. Rather that caching the information within the core file BFD via the registry mechanism, the information used for the mapped file lookup is now stored within the core_file target directly.
2024-09-07gdb/corefile: don't pretend unavailable sections are readableAndrew Burgess1-0/+39
When GDB opens a core file the bfd library processes the core file and creates sections within the bfd object to represent each of the segments within the core file. GDB then creates two target_section lists, m_core_section_table and m_core_file_mappings, these, along with m_core_unavailable_mappings, are used by GDB to implement core_target::xfer_partial; this is the function used when GDB tries to read memory from a core file inferior. The m_core_section_table list represents sections within the core file itself. The sections in this list can be split into two groups based on whether the section has the SEC_HAS_CONTENTS flag set or not. Sections (from the core file) that have the SEC_HAS_CONTENTS flag had their contents copied into the core file when the core file was created. These correspond to writable sections within the original inferior (the inferior for which the core file was created). Sections (from the core file) that do not have the SEC_HAS_CONTENTS flag will not have had their contents copied into the core file when it was created. These sections correspond to read-only sections mapped from a file (possibly the initial executable, or possibly some other file) in the original inferior. The expectation is that the contents of these sections can still be found by looking in the file that was originally mapped. The m_core_file_mappings list is created when GDB parses the mapped file list in the core file. Every mapped region will be covered by entries in the m_core_section_table list (see above), but for read-only mappings the entry in m_core_section_table will not have the SEC_HAS_CONTENTS flag set. As GDB parses the mapped file list, if the file that was originally mapped can be found, then GDB creates an entry in the m_core_file_mappings list which represents the region of the file that was mapped into the original inferior. However, GDB only creates entries in m_core_file_mappings if it is able to find the correct on-disk file to open. If the file can't be found then an entry is added to m_core_unavailable_mappings instead. If is the handling m_core_unavailable_mappings which I think is currently not completely correct. When a read lands within an m_core_unavailable_mappings region we currently forward the read to the exec file stratum. The reason for this is this: when GDB read the mapped file list, if the executable file could not be found at the expected path then mappings within the executable will end up in the m_core_unavailable_mappings list. However, the user might provide the executable to GDB from a different location. If this happens then forwarding the read to the exec file stratum might give a result. But, if the exec file stratum does not resolve the access then currently we continue through ::xfer_partial, the next step of which is to handle m_core_section_table entries that don't have the SEC_HAS_CONTENTS flag set. Every m_core_unavailable_mappings entry will naturally have an m_core_section_table without the SEC_HAS_CONTENTS flag set, and so we treat the unavailable mapping as zero initialised memory and return all zeros. It is this fall through behaviour that I think is wrong. If a read falls in an unavailable region, and the exec file stratum cannot help, then I think the access should fail. To achieve this goal I have removed the xfer_memory_via_mappings helper function and moved its content inline into ::xfer_partial. Now, if an access is within an m_core_unavailable_mappings region, and the exec file stratum doesn't help, we immediately return with an error. The reset of ::xfer_partial is unchanged, I've extended some comments in the area that I have changed to (I hope) explain better what's going on. There's a new test that covers the new functionality, an inferior maps a file and generates a core file. We then remove the mapped file, load the core file and try to read from the mapped region. The expectation is that GDB should give an error rather than claiming that the region is full of zeros.