aboutsummaryrefslogtreecommitdiff
path: root/gdb
AgeCommit message (Collapse)AuthorFilesLines
2024-09-13gdb, btrace, infrun: per-inferior run-controlusers/mmetzger/pr19340Markus Metzger4-28/+44
While recording is already per inferior, run-control isn't. As soon as any thread in any inferior is replaying, no other inferior can be resumed. This is controlled by many calls to record_is_replaying(minus_one_ptid). Instead of minus_one_ptid, pass the ptid of the inferior to be checked.
2024-09-13gdb, infrun: fix silent inferior switch in do_target_wait()Markus Metzger3-13/+72
In do_target_wait(), we iterate over inferiors and call do_target_wait_1(), which eventually calls target_wait() per inferior. Each time, we wait for minus_one_ptid. In some cases, e.g. gdb.threads/detach-step-over.exp, we ask to wait for one inferior, and get an event from a different inferior back without noticing the inferior switch. Wait for a single inferior, instead. Since we iterate over all inferiors, we still cover everything. This exposes another bug with STOP_QUIETLY_NO_SIGSTOP handling. After attaching, we interrupt all threads in the new inferior, then call do_target_wait() to receive the stopped events. This randomly selects an inferior to start waiting for and iterates over all inferiors starting from there. The initial stop event for the main thread is already queued up, so we wouldn't actually wait() if we had started with the new inferior. Or if we had waited for minus_one_ptid, which would then have silently switched inferiors. Since we no longer allow that, we may actually wait() for the new inferior and find other events to report, out of which we randomly select one. If we selected an event for another thread, e.g. one that had been interrupted as part of non-stop attach, STOP_QUIETLY_NO_SIGSTOP would be applied to that thread (unnecessarily), leaving the main thread with a SIGSTOP event but last_resume_kind = 0 (resume_continue). When the main thread is later selected, SIGSTOP is reported to the user. Normally, linux-nat's wait() turns the SIGSTOP it uses for interrupting threads into GDB_SIGNAL_0. This is based on last_resume_kind, which is set to 2 (resume_stop) when sending SIGSTOP to interrupt a thread. We do this for all threads of the new inferior when interrupting them as part of non-stop attach. Except for the main thread, which we expect to be reported before the first wait(). Set last_resume_kind to resume_stop for the main thread after attaching.
2024-09-13gdb, remote: adjust debug printingMarkus Metzger1-7/+5
remote::wait () may get called rather frequently, polluting the logging output with tons of [remote] wait: enter [remote] wait: exit messages. Similarly, remote_target::remote_notif_remove_queued_reply () will print the debug message even if nothing was actually removed. Change that to only print a debug message if a stop reply was removed.
2024-09-13gdb, btrace: set wait status to ignore if nothing is movingMarkus Metzger1-4/+4
When record_btrace::wait() is called and no threads are moving, we set the wait status to no_resumed. Change that to ignore. This helps with enabling per-inferior run-control for the record btrace target as it avoids breaking out of do_target_wait() too early with no_resumed when there would have been an event on another thread.
2024-09-13gdb, btrace: remove record_btrace_target::supports_*()Markus Metzger1-27/+0
Let's not introduce support for breakpoint types the target beneath does not support, even though we could while replaying. Otherwise, users may set breakpoints during replay that then couldn't be inserted into the target when switching back to recording.
2024-09-13gdb, btrace: simplify gdb.btrace/multi-inferior.expMarkus Metzger1-21/+3
We don't really need three inferiors to test multi-inferior recording. We don't really need to start recording on the second inferior first. We don't really need to check info record before starting recording. If we were recording, there would be output, causing a fail. This just complicates the test when there is something to debug.
2024-09-13gdb, btrace: fix pr19340Markus Metzger2-7/+32
GDB fails with an assertion when stopping recording on a replaying thread and then resuming that thread. Stopping recording left the thread replaying but the record target is gone. Stop replaying all threads in the selected inferior before stopping recording. If the selected thread had been replaying, print the (potentially updated) location. I had to change the stepping test slightly to account for different compilers generating slightly different debug information, so when stepping the 'return 0' after 'record stop' I would end up in a different location depending on which compiler I used. The test still covers all stepping commands. Fixes PR gdb/19340.
2024-09-12gdb: change type of `general_symbol_info::m_section` to intSimon Marchi1-3/+3
The binary provided with bug 32165 [1] has 36139 ELF sections. GDB crashes on it with (note that my GDB is build with -D_GLIBCXX_DEBUG=1: $ ./gdb -nx -q --data-directory=data-directory ./vmlinux Reading symbols from ./vmlinux... (No debugging symbols found in ./vmlinux) (gdb) info func /usr/include/c++/14.2.1/debug/vector:508: In function: std::debug::vector<_Tp, _Allocator>::reference std::debug::vector<_Tp, _Allocator>::operator[](size_type) [with _Tp = long unsigned int; _Allocator = std::allocator<long unsigned int>; reference = long unsigned int&; size_type = long unsigned int] Error: attempt to subscript container with out-of-bounds index -29445, but container only holds 36110 elements. Objects involved in the operation: sequence "this" @ 0x514000007340 { type = std::debug::vector<unsigned long, std::allocator<unsigned long> >; } The crash occurs here: #3 0x00007ffff5e334c3 in __GI_abort () at abort.c:79 #4 0x00007ffff689afc4 in __gnu_debug::_Error_formatter::_M_error (this=<optimized out>) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/debug.cc:1320 #5 0x0000555561119a16 in std::__debug::vector<unsigned long, std::allocator<unsigned long> >::operator[] (this=0x514000007340, __n=18446744073709522171) at /usr/include/c++/14.2.1/debug/vector:508 #6 0x0000555562e288e8 in minimal_symbol::value_address (this=0x5190000bb698, objfile=0x514000007240) at /home/smarchi/src/binutils-gdb/gdb/symtab.c:517 #7 0x0000555562e5a131 in global_symbol_searcher::expand_symtabs (this=0x7ffff0f5c340, objfile=0x514000007240, preg=std::optional [no contained value]) at /home/smarchi/src/binutils-gdb/gdb/symtab.c:4983 #8 0x0000555562e5d2ed in global_symbol_searcher::search (this=0x7ffff0f5c340) at /home/smarchi/src/binutils-gdb/gdb/symtab.c:5189 #9 0x0000555562e5ffa4 in symtab_symbol_info (quiet=false, exclude_minsyms=false, regexp=0x0, kind=FUNCTION_DOMAIN, t_regexp=0x0, from_tty=1) at /home/smarchi/src/binutils-gdb/gdb/symtab.c:5361 #10 0x0000555562e6131b in info_functions_command (args=0x0, from_tty=1) at /home/smarchi/src/binutils-gdb/gdb/symtab.c:5525 That is, at this line of `minimal_symbol::value_address`, where `objfile->section_offsets` is an `std::vector`: return (CORE_ADDR (this->unrelocated_address ()) + objfile->section_offsets[this->section_index ()]); A section index of -29445 is suspicious. The minimal_symbol at play here is: (top-gdb) p m_name $1 = 0x521001de10af "_sinittext" So I restarted debugging, breaking on: (top-gdb) b general_symbol_info::set_section_index if $_streq("_sinittext", m_name) And I see that weird -29445 value: (top-gdb) frame #0 general_symbol_info::set_section_index (this=0x525000082390, idx=-29445) at /home/smarchi/src/binutils-gdb/gdb/symtab.h:611 611 { m_section = idx; } But going up one frame, the section index is 36091: (top-gdb) frame #1 0x0000555562426526 in minimal_symbol_reader::record_full (this=0x7ffff0ead560, name="_sinittext", copy_name=false, address=-2111475712, ms_type=mst_text, section=36091) at /home/smarchi/src/binutils-gdb/gdb/minsyms.c:1228 1228 msymbol->set_section_index (section); It seems like the problem is just that the type used for the section index (short) is not big enough. Change from short to int. If somebody insists, we could even go long long / int64_t, but I doubt it's necessary. With that fixed, I get: (gdb) info func All defined functions: Non-debugging symbols: 0xffffffff81000000 _stext 0xffffffff82257000 _sinittext 0xffffffff822b4ebb _einittext [1] https://sourceware.org/bugzilla/show_bug.cgi?id=32165 Change-Id: Icb1c3de9474ff5adef7e0bbbf5e0b67b279dee04 Reviewed-By: Tom de Vries <tdevries@suse.de> Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-09-11[gdb/testsuite] Simplify gdb.dwarf2/forward-spec.expTom de Vries1-28/+12
Test-case gdb.dwarf2/forward-spec.exp contains a non-trivial gdb_test_multiple to parse this cooked_index_entry: ... [5] ((cooked_index_entry *) 0x7f01f0004040)^M name: v^M canonical: v^M qualified: ns::v^M DWARF tag: DW_TAG_variable^M flags: 0x2 [IS_STATIC]^M DIE offset: 0xcb^M parent: ((cooked_index_entry *) 0x7f01f00040a0) [ns]^M ... which allows us to verify that the entry has a parent. After commit 8f258a6c979 ("[gdb/symtab] Dump qualified name of cooked_index_entry") that's no longer necessary. Simplify this by checking for ns::v instead. While we're at it, also fix the test-case for target boards readnow, cc-with-gdb-index and cc-with-debug-names. Tested on x86_64-linux.
2024-09-11gdb: Support DW_OP_constx (the standardized version of DW_OP_GNU_const_index).Kyle Huey3-3/+10
Approved-By: Tom Tromey <tom@tromey.com>
2024-09-11Fix typo in Python TUI window textTom Tromey1-1/+1
I noticed a typo in the Python TUI window documentation.
2024-09-10gdb/testsuite: fix argument order in example code within a commentAndrew Burgess1-1/+1
Small typo in some example code inside a comment; the arguments were in the wrong order. There's no functional change after this commit.
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-10Revert "[gdb/testsuite] Handle missing curses in ↵Andrew Burgess1-15/+2
gdb.python/py-missing-debug.exp" This reverts commit 29c70787112e01cd52b53bf14bdcacb0a11e0725. After the previous commit 29c70787112e01cd52 should no longer be needed as the curses dependency has been removed.
2024-09-10gdb/python: avoid depending on the curses libraryAndrew Burgess1-3/+27
The commit: commit 29c70787112e01cd52b53bf14bdcacb0a11e0725 Date: Sun Sep 8 07:46:09 2024 +0200 [gdb/testsuite] Handle missing curses in gdb.python/py-missing-debug.exp Highlighted that in some cases we might be running on a system with an older version of Python (earlier than 3.7), and on a system for which the curses library has not been installed. In these circumstances the gdb.missing_debug module will not load as it uses curses to provide isalnum() and isascii() functions. To avoid this problem I propose that we copy the isalnum() and isascii() from the Python curses library. These functions are basically trivial and removing the curses dependency means GDB will work in more cases without increasing its dependencies. I did consider keeping the uses of curses and only having the function definitions be a fallback for when the curses library failed to load, but this felt like overkill. The function definitions are both tiny and I think "obvious" given their specifications, so I figure we might as well just use our own definitions if they are not available as builtin methods on the str class. For testing I changed this line: if sys.version_info >= (3, 7): to if sys.version_info >= (3, 7) and False: then reran gdb.python/py-missing-debug.exp, there were no failures. Approved-By: Tom de Vries <tdevries@suse.de>
2024-09-10[gdb/testsuite] Fix gdb.xml/tdesc-regs.exp on riscv64Tom de Vries1-9/+26
When running test-case gdb.xml/tdesc-regs.exp on riscv64-linux, I get: ... (gdb) set tdesc file single-reg.xml^M warning: Architecture rejected target-supplied description^M (gdb) FAIL: gdb.xml/tdesc-regs.exp: set tdesc file single-reg.xml UNSUPPORTED: gdb.xml/tdesc-regs.exp: register tests ... The FAIL and UNSUPPORTED are produced here: ... # If no core registers were specified, assume this target does not # support target-defined registers. Verify that we get a warning if # we try to use them. This not only tests the warning, but also # reminds maintainers to add test support when they add the feature. if {[string equal ${core-regs} ""]} { gdb_test "set tdesc file $single_reg_xml" \ "warning: Target-supplied registers are not supported.*" \ "set tdesc file single-reg.xml" unsupported "register tests" return 0 } ... The test-case contains target-specific setting of the core-regs variable, and adding this for riscv64 bypasses this code and makes the test-case pass. However, without that change, the test-case shouldn't produce a FAIL since gdb isn't doing anything wrong. Fix this by producing instead: ... PASS: $exp: set tdesc file single-reg.xml UNSUPPORTED: $exp: register tests (missing architecture-specific core-regs setting) ... Tested on riscv64-linux.
2024-09-10[gdb/build] Fix unused var in corelow.cTom de Vries1-2/+2
On x86_64-linux, with gcc 7.5.0 and CFLAGS/CXXFLAGS="-O0 -g -Wall" I ran into a build breaker: ... gdb/corelow.c: In member function ‘void mapped_file_info::add(const char*, const char*, const char*, std::vector<mem_range>&&, const bfd_build_id*)’: gdb/corelow.c:1822:27: error: unused variable ‘it’ [-Werror=unused-variable] const auto [it, inserted] ^ ... Fix this by dropping the variable it. Tested on x86_64-linux. Reviewed-By: Lancelot Six<lancelot.six@amd.com>
2024-09-09Move enum size check into ada_identical_enum_types_pTom Tromey1-10/+4
Currently, the callers of ada_identical_enum_types_p must check that both enum types have the same number of members. In another series I'm working on, it was convenient to move this check into the callee instead; and I broke this patch out to make that series a little simpler. Approved-By: Tom de Vries <tdevries@suse.de>
2024-09-09Minor cleanup to ada_identical_enum_types_pTom Tromey1-4/+2
This moves the declaration of 'i' into the 'for' loops in ada_identical_enum_types_p. This is just a trivial cleanup. Approved-By: Tom de Vries <tdevries@suse.de>
2024-09-09Boolify ada_identical_enum_types_pTom Tromey1-6/+7
This changes ada_identical_enum_types_p to return bool rather than int. Approved-By: Tom de Vries <tdevries@suse.de>
2024-09-09Fix some comments in dwarf2/cooked-index.hTom Tromey1-4/+4
This fixes a couple of comments in dwarf2/cooked-index.h. The comment by cooked_index_entry::canonical mentions C++, but this field can also be different from 'name' in other situations. Rather than enumerate the cases here (which doesn't seem important), make the text a little less specific. Also, cooked_index_entry::write_scope doesn't document its "for_main" parameter -- and it is misnamed in the prototype as well. Reviewed-By: Tom de Vries <tdevries@suse.de>
2024-09-09Refactor cooked_index_shard::handle_gnat_encoded_entryTom Tromey2-17/+11
This changes cooked_index_shard::handle_gnat_encoded_entry to modify the incoming entry itself, and to return void rather than a new name. this simplifies the caller a little, which is convenient for a different series I am working on. Approved-By: Tom de Vries <tdevries@suse.de>
2024-09-09Ignore DW_TAG_padding in tag_is_typeTom Tromey1-1/+0
DW_TAG_padding isn't a real tag -- it doesn't appear in the DWARF standard, only in include/dwarf2.def as a placeholder. So, remove it from dwarf2/tag.h:tag_is_type. Reviewed-By: Tom de Vries <tdevries@suse.de>
2024-09-09gdb/NEWS: group general news items togetherAndrew Burgess1-14/+14
I noticed that the list of general NEWS items seemed to have gotten mixed up a bit in the NEWS file. This commit just moves things around so that the general items all appear at the start of the 'Changes since GDB 15' section. I've not changed any of the actual content.
2024-09-08gdb: fix use of out of scope temporary variable in break-cond-parse.cAndrew Burgess1-7/+4
The commit: commit c6b486755e020095710c7494d029577ca967a13a Date: Thu Mar 30 19:21:22 2023 +0100 gdb: parse pending breakpoint thread/task immediately Introduce a use bug where the value of a temporary variable was being used after it had gone out of scope. This was picked up by the address sanitizer and would result in this error: (gdb) maintenance selftest create_breakpoint_parse_arg_string Running selftest create_breakpoint_parse_arg_string. ================================================================= ==2265825==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fbb08046511 at pc 0x000001632230 bp 0x7fff7c2fb770 sp 0x7fff7c2fb768 READ of size 1 at 0x7fbb08046511 thread T0 #0 0x163222f in create_breakpoint_parse_arg_string(char const*, std::unique_ptr<char, gdb::xfree_deleter<char> >*, int*, int*, int*, std::unique_ptr<char, gdb::xfree_deleter<char> >*, bool*) ../../src/gdb/break-cond-parse.c:496 #1 0x1633026 in test ../../src/gdb/break-cond-parse.c:582 #2 0x163391b in create_breakpoint_parse_arg_string_tests ../../src/gdb/break-cond-parse.c:649 #3 0x12cfebc in void std::__invoke_impl<void, void (*&)()>(std::__invoke_other, void (*&)()) /usr/include/c++/13/bits/invoke.h:61 #4 0x12cc8ee in std::enable_if<is_invocable_r_v<void, void (*&)()>, void>::type std::__invoke_r<void, void (*&)()>(void (*&)()) /usr/include/c++/13/bits/invoke.h:111 #5 0x12c81e5 in std::_Function_handler<void (), void (*)()>::_M_invoke(std::_Any_data const&) /usr/include/c++/13/bits/std_function.h:290 #6 0x18bb51d in std::function<void ()>::operator()() const /usr/include/c++/13/bits/std_function.h:591 #7 0x4193ef9 in selftests::run_tests(gdb::array_view<char const* const>, bool) ../../src/gdbsupport/selftest.cc:100 #8 0x21c2206 in maintenance_selftest ../../src/gdb/maint.c:1172 ... etc ... The problem was caused by three lines like this one: thread_info *thr = parse_thread_id (std::string (t.get_value ()).c_str (), &tmptok); After parsing the thread-id TMPTOK would be left pointing into the temporary string which had been created on this line. When on the next line we did this: gdb_assert (*tmptok == '\0'); The value of *TMPTOK is undefined. Fix this by creating the std::string earlier in the scope. Now the contents of the string will remain valid when we check *TMPTOK. The address sanitizer issue is now resolved.
2024-09-08[gdb/testsuite] Handle missing curses in gdb.python/py-missing-debug.expTom de Vries1-2/+15
On a system with python 3.6, module gdb.missing_debug imports module curses, so when running test-case gdb.python/py-missing-debug.exp on a system without that module installed, we run into: ... (gdb) source py-missing-debug.py^M Python Exception <class 'ImportError'>: Module 'curses' is not installed.^M Use:^M sudo zypper install python36-curses^M to install it.^M Error occurred in Python: Module 'curses' is not installed.^M Use:^M sudo zypper install python36-curses^M to install it.^M (gdb) FAIL: gdb.python/py-missing-debug.exp: source python script ... Fix this by issuing UNSUPPORTED instead, and bailing out. Tested on x86_64-linux. Approved-by: Kevin Buettner <kevinb@redhat.com> PR testsuite/31576 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31576
2024-09-07gdb: only insert thread-specific breakpoints in the relevant inferiorAndrew Burgess14-111/+497
This commit updates GDB so that thread or inferior specific breakpoints are only inserted into the program space in which the specific thread or inferior is running. In terms of implementation, getting this basically working is easy enough, now that a breakpoint's thread or inferior field is setup prior to GDB looking for locations, we can easily use this information to find a suitable program_space and pass this to as a filter when creating the sals. Or we could if breakpoint_ops::create_sals_from_location_spec allowed us to pass in a filter program_space. So, this commit extends breakpoint_ops::create_sals_from_location_spec to take a program_space argument, and uses this to filter the set of returned sals. This accounts for about half the change in this patch. The second set of changes starts from breakpoint_set_thread and breakpoint_set_inferior, this is called when the thread or inferior for a breakpoint changes, e.g. from the Python API. Previously this call would never result in the locations of a breakpoint changing, after all, locations were inserted in every program space, and we just use the thread or inferior variable to decide when we should stop. Now though, changing a breakpoint's thread or inferior can mean we need to figure out a new set of breakpoint locations. To support this I've added a new breakpoint_re_set_one function, which is like breakpoint_re_set, but takes a single breakpoint, and just updates the locations for that one breakpoint. We only need to call this function if the program_space in which a breakpoint's thread (or inferior) is running actually changes. If the program_space does change then we call the new breakpoint_re_set_one function passing in the program_space which should be used to filter the new locations (or nullptr to indicate we should set locations in all program spaces). This filter program_space needs to propagate down to all the re_set methods, this accounts for the remaining half of the changes in this patch. There were a couple of existing tests that created thread or inferior specific breakpoints and then checked the 'info breakpoints' output, these needed updating. These were: gdb.mi/user-selected-context-sync.exp gdb.multi/bp-thread-specific.exp gdb.multi/multi-target-continue.exp gdb.multi/multi-target-ping-pong-next.exp gdb.multi/tids.exp gdb.mi/new-ui-bp-deleted.exp gdb.multi/inferior-specific-bp.exp gdb.multi/pending-bp-del-inferior.exp I've also added some additional tests to: gdb.multi/pending-bp.exp I've updated the documentation and added a NEWS entry. Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-09-07gdb: don't set breakpoint::pspace in create_breakpointAndrew Burgess4-6/+259
I spotted this code within create_breakpoint: if ((type_wanted != bp_breakpoint && type_wanted != bp_hardware_breakpoint) || thread != -1) b->pspace = current_program_space; this code is only executed when creating a pending breakpoint, and sets the breakpoint::pspace member variable. The above code gained the 'thread != -1' clause with this commit: commit cc72b2a2da6d6372cbdb1d14639a5fce84e1a325 Date: Fri Dec 23 17:06:16 2011 +0000 Introduce gdb.FinishBreakpoint in Python While the type_wanted checks were added with this commit: commit f8eba3c61629b3c03ac1f33853eab4d8507adb9c Date: Tue Dec 6 18:54:43 2011 +0000 the "ambiguous linespec" series Before this breakpoint::pspace was set unconditionally. If we look at how breakpoint::pspace is used today, some breakpoint types specifically set this field, either in their constructors, or in a wrapper function that calls the constructor. So, the watchpoint type and its sub-class set this variable, as does the catchpoint type, and all it's sub-classes. However, code_breakpoint doesn't specifically set this field within its constructor, though some sub-classes of code_breakpoint (ada_catchpoint, exception_catchpoint, internal_breakpoint, and momentary_breakpoint) do set this field. When I examine all the places that breakpoint::pspace is used, I believe that in every place where it is expected that this field is set, the breakpoint type will be one that specifically sets this field. Next, I observe two problems with the existing code. First, the above code is only hit for pending breakpoints, there's no equivalent code for non-pending breakpoints. This opens up the possibility of GDB entering non-consistent states; if a breakpoint is first created pending and then later gets a location, the pspace field will be set, while if the breakpoint is immediately non-pending, then the pspace field will never be set. Second, if we look at how breakpoint::pspace is used in the function breakpoint_program_space_exit, we see that when a program space is removed, any breakpoint with breakpoint::pspace set to the removed program space, will be deleted. This makes sense, but does mean we need to ensure breakpoint::pspace is only set for breakpoints that apply to a single program space. So, if I create a pending dprintf breakpoint (type bp_dprintf) then the breakpoint::pspace variable will be set even though the dprintf is not really tied to that one program space. As a result, when the matching program space is removed the dprintf is incorrectly removed. Also, if I create a thread specific breakpoint, then, thanks to the 'thread != -1' clause the wrong program space will be stored in breakpoint::pspace (the current program space is always used, which might not be the program space that corresponds to the selected thread), as a result, the thread specific breakpoint will be deleted when the matching program space is removed. If we look at commit cc72b2a2da6d which added the 'thread != -1' clause, we can see this change was entirely redundant, the breakpoint::pspace is also set in bpfinishpy_init after create_breakpoint has been called. As such, I think we can safely drop the 'thread != -1' clause. For the other problems, I'm proposing to be pretty aggressive - I'd like to drop the breakpoint::pspace assignment completely from create_breakpoint. Having looked at how this variable is used, I believe that it is already set elsewhere in all the cases that it is needed. Maybe this code was needed at one time, but I can't see how it's needed any more. There's tests to expose the issues I've spotted with this code, and there's no regressions in testing.
2024-09-07gdb: parse pending breakpoint thread/task immediatelyAndrew Burgess15-307/+1152
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: create new is_thread_id helper functionAndrew Burgess2-20/+70
This is a refactoring commit that splits the existing parse_thread_id function into two parts, and then adds a new is_thread_id function. The core of parse_thread_id is split into parse_thread_id_1, which is responsible for actually parsing a thread-id. Then parse_thread_id is responsible for taking a parsed thread-id and validating that it references an actually existing inferior thread. The new is_thread_id function also uses parse_thread_id_1, but doesn't actually check that the inferior thread exists, instead, this new function simply checks that a string looks like a thread-id. This commit does not add a use for is_thread_id, this will be added in the next commit. This is a refactoring commit, there should be no user visible changes after this commit.
2024-09-07gdb: make breakpoint_debug_printf globalAndrew Burgess2-7/+10
This commit makes breakpoint_debug_printf available outside of breakpoint.c. In a later commit I'll want to use this macro from another file. This is just a refactor, there should be no user visible changes after this commit.
2024-09-07Remove tui_refresh_cmd_winTom Tromey3-14/+3
tui_refresh_cmd_win is no longer needed and can be replaced with a call to the refresh_window method.
2024-09-07Remove tui_wrefreshTom Tromey6-29/+5
This removes tui_wrefresh, moving the code into refresh_window. We remove tui_norefresh_window as well, because now the command window's refresh_window has to do what tui_wrefresh previously did.
2024-09-07Rename tui_suppress_outputTom Tromey9-36/+32
This patch renames tui_suppress_output to the more descriptive tui_batch_rendering. This code was never really correct, and was based on a misunderstanding of the curses API. The updated comments describe the intended use of this class. This also removes the erroneous tui_win_info::no_refresh. wnoutrefresh does not prevent any output; rather, it copies from one curses buffer to another but (unlike woutrefresh) without then flushing to the screen. tui_batch_rendering now works in the correct way: calling doupdate in the destructor of the outermost instance, thus batching all screen output until that point. The patch adds instantiations of tui_batch_rendering to various spots, to make sure it is active when refreshing.
2024-09-07Clean up refreshing in TUI register windowTom Tromey2-24/+19
This patch rearranges the TUI register window code a bit, removing a call to tui_wrefresh and hoisting the calls to refresh_window to "more outer" spots. Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
2024-09-07gdb: 'target ...' commands now expect quoted/escaped filenamesAndrew Burgess8-30/+48
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 Burgess7-27/+43
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 Burgess5-148/+238
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: extend completion of quoted filenames to work in brkchars phaseAndrew Burgess2-15/+91
Up to this point filename completion for possibly quoted filenames has always been handled during the second (non-brkchars) phase of completion. This works fine for commands that only want to complete on a single filename argument. In a later commit though I need to perform completion of a quoted filename argument during the first (brkchars) phase of completion. This will allow me to add a custom completer that completes both command options and arguments for a command (remove-symbol-file) that takes a possibly quoted filename argument. This commit doesn't add the remove-symbol-file completer, this commit is just about putting support for that in place. To achieve this I've added the new function advance_to_filename_maybe_quoted_complete_word_point, which is unused in this commit. I've then had to extend some other functions in order to extract the quoting state during the brkchars phase. As this commit doesn't use the new functionality, the important thing at this point is that I've not regressed the existing filename completion (or any of the other completion). The next commit in this series will make use of the new functionality, and will include tests. There should be no user visible changes after this commit.
2024-09-07gdb: new extract_single_filename_arg helper functionAndrew Burgess2-0/+32
This commit is in preparation for the next few commits, this commit adds a new function extract_single_filename_arg. This new function will be used to convert GDB commands that expect a single filename argument to have these commands take a possibly quoted or escaped string. There's no use of the new function in this commit, for that see the following commits.
2024-09-07gdb: implement readline rl_directory_rewrite_hook callbackAndrew Burgess2-0/+33
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 Burgess2-18/+56
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 Burgess2-54/+144
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 Burgess3-51/+158
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 Burgess2-33/+50
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: move display of completion results into completion_result classAndrew Burgess3-25/+47
This commit moves the printing of the 'complete' command results out of the 'complete_command' function. The printing is now done in a new member function 'completion_result::print_matches'. At this point, this is entirely a refactor. The motivation for this refactor is how 'complete' should print the completion of filename arguments. In some cases the filename results need to have escaping added to the output. This escaping needs to be done immediately prior to printing the result as adding too early will result in multiple 'complete' results potentially being sorted incorrectly. See the subsequent commits for more details. There should be no user visible changes after this commit. Approved-By: Tom Tromey <tom@tromey.com>
2024-09-07gdb: improve escaping when completing filenamesAndrew Burgess2-3/+199
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: deprecated filename_completer and associated functionsAndrew Burgess23-59/+62
Following on from the previous commit, this commit marks the old unquoted filename completion related functions as deprecated. The aim of doing this is to make it more obvious to someone adding a new command that they should not be using the older unquoted style filename argument handling. I split this change from the previous to make for an easier review. This commit touches more files, but is _just_ function renaming. Check out gdb/completer.{c,h} for what has been renamed. All the other files have just been updated to use the new names. There should be no user visible changes after this commit.
2024-09-07gdb: split apart two different types of filename completionAndrew Burgess8-72/+269
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: unify build-id to objfile lookup codeAndrew Burgess7-55/+136
There are 3 places where we currently call debuginfod_exec_query to lookup an objfile for a given build-id. In one of these places we first call build_id_to_exec_bfd which also looks up an objfile given a build-id, but this function looks on disk for a symlink in the .build-id/ sub-directory (within the debug-file-directory). I can't think of any reason why we shouldn't call build_id_to_exec_bfd before every call to debuginfod_exec_query. So, in this commit I have added a new function in build-id.c, find_objfile_by_build_id, this function calls build_id_to_exec_bfd, and if that fails, then calls debuginfod_exec_query. Everywhere we call debuginfod_exec_query is updated to call the new function, and in locate_exec_from_corefile_build_id, the existing call to build_id_to_exec_bfd is removed as calling find_objfile_by_build_id does this for us. One slight weird thing is in core_target::build_file_mappings, here we call find_objfile_by_build_id which returns a gdb_bfd_ref_ptr for the opened file, however we immediately reopen the file as "binary". The reason for this is that all the bfds opened in ::build_file_mappings need to be opened as "binary" (see the function comments for why). I did consider passing a target type into find_objfile_by_build_id, which could then be forwarded to build_id_to_exec_bfd and used to open the BFD as "binary", however, if you follow the call chain you'll end up in build_id_to_debug_bfd_1, where we actually open the bfd. Notice in here that we call build_id_verify to double check the build-id of the file we found, this requires that the bfd not be opened as "binary". What this means is that we always have to first open the bfd using the gnutarget target type (for the build-id check), and then we would have to reopen it as "binary". There seems little point pushing the reopen logic into find_objfile_by_build_id, so we just do this in the ::build_file_mappings function. I've extended the tests to cover the two cases which actually changed in this commit.