Commit Graph

53168 Commits

Author SHA1 Message Date
Guinevere Larsen
bb067ddfca gdb/MAINTAINERS: update my email address
Sync the maintainers file with my new email address
2024-09-19 13:13:42 -03:00
Guinevere Larsen
9162d24e61 gdb/testsuite: skip gdb.mi/dw2-ref-missing-frame.exp with clang
The test gdb.mi/dw2-ref-missing-frame.exp uses the old-school way to set
debug information by hand, using a .S file and assembly labels to get
addresses. Unfortunately, clang will always re-arrange the global labels
to be side by side, making high and low PC for CUs and functions be the
same, and thus they will all be empty ranges. This makes the test fail,
since we never technically enter the functions that we want to check.

This commit skips that test when using clang. If we ever port this test
to use the dwarf assembler, we can reenable it with clang.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-17 17:18:54 -03:00
Guinevere Larsen
4d91b71056 gdb/testsuite: fix gdb.mi/mi-var-cp.exp with clang
The inline tests in gdb.mi/mi-var-cp.cc were failing when using clang to
run the test. This happened because inline tests want to step past the C
statements and then run the TCL tests, but in mi-var-cp.cc the statement
to be stepped past is "return s2.i;". Since clang links the epilogue
information to the return statement, not the closing brace,
single-stepping past return had us exiting the function - which made the
expressions invalid.

This commit fixes this by making the function have 2 C statements, and
the return one be after all inline tests, so we know GDB won't leave the
function before running the create_varobj tests.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-17 17:18:47 -03:00
Guinevere Larsen
bd26cd1810 gdb/testsuite: fix gdb.mi/mi-catch-cpp-exceptions.exp with clang
Clang adds line table information for a try/catch block differently to
gcc. Instead of linking the instructions related to __cxa_begin_catch to
the line containing the "catch" statement in the source code, it links
to the closing brace of the try block.

This was causing gdb.mi/mi-catch-cpp-exceptions.exp to fail when tested
with clang. The test was updated to have the catch in the same line as
the closing brace so it passes with no additional modifications with
clang.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-17 17:18:36 -03:00
Tom Tromey
0f79c44dac Fix typo in py-arch.exp
I found a typo in a test name in py-arch.exp.
2024-09-16 08:11:54 -06:00
Simon Marchi
929b910f62 gdb: fix amd_dbgapi_target_breakpoint::re_set's signature
Following

        commit 6cce025114
        Date:   Fri Mar 3 19:03:15 2023 +0000

            gdb: only insert thread-specific breakpoints in the relevant inferior

... when building amd-dbgapi-target.c:

      CXX    amd-dbgapi-target.o
    /home/smarchi/src/binutils-gdb/gdb/amd-dbgapi-target.c:486:8: error: ‘void amd_dbgapi_target_breakpoint::re_set()’ marked ‘override’, but does not override
      486 |   void re_set () override;
          |        ^~~~~~

Update the signature to match the base.

Change-Id: Ie8bd71a63284917180f3e67eead58bea74bb0692
2024-09-15 09:31:09 +00:00
Tom de Vries
a2860473ef [gdb/symtab] Revert "Change handling of DW_TAG_enumeration_type in DWARF scanner"
After adding dwarf assembly to test-case gdb.dwarf2/enum-type.exp that adds
this debug info:
...
 <1><11f>: Abbrev Number: 3 (DW_TAG_enumeration_type)
    <120>   DW_AT_specification: <0x130>
 <2><124>: Abbrev Number: 4 (DW_TAG_enumerator)
    <125>   DW_AT_name        : val1
    <12a>   DW_AT_const_value : 1
 <2><12b>: Abbrev Number: 0
 <1><12c>: Abbrev Number: 5 (DW_TAG_namespace)
    <12d>   DW_AT_name        : ns
 <2><130>: Abbrev Number: 6 (DW_TAG_enumeration_type)
    <131>   DW_AT_name        : e
    <133>   DW_AT_type        : <0x118>
    <137>   DW_AT_declaration : 1
...
I run into an assertion failure:
...
(gdb) file enum-type^M
Reading symbols from enum-type...^M
cooked-index.h:214: internal-error: get_parent: \
  Assertion `(flags & IS_PARENT_DEFERRED) == 0' failed.^M
...

This was reported in PR32160 comment 1.

This is a regression since commit 4e417d7bb1 ("Change handling of
DW_TAG_enumeration_type in DWARF scanner").

Fix this by reverting the commit.

[ Also drop the kfails for PR31900 and PR32158, which are regressions by that
same commit. ]

That allows us to look at the output of "maint print objfiles", and for val1
we get an entry without parent:
...
    [27] ((cooked_index_entry *) 0x7fbbb4002ef0)
    name:       val1
    canonical:  val1
    qualified:  val1
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0x124
    parent:     ((cooked_index_entry *) 0)
...
which is incorrect, as noted in that same comment, but an improvement over the
assertion failure, and I don't think that ever worked.  This is to be
addressed in a follow-up patch.

Reverting the commit begs the question: what was it trying to fix in the first
place, and do we need a different fix?  I've investigated this and filed
PR32160 to track this.

My guess is that the commit was based on a misunderstand of what we track
in cooked_indexer::m_die_range_map.

Each DIE has two types of parent DIEs:
- a DIE that is the parent as indicated by the tree structure in which DIEs
  occur, and
- a DIE that represent the parent scope.

In most cases, these two are the same, but some times they're not.

The debug info above demonstrates such a case.  The DIE at 0x11f:
- has a tree-parent: the DIE representing the CU, and
- has a scope-parent: DIE 0x12c representing namespace ns.

In cooked_indexer::m_die_range_map, we track scope-parents, and the commit
tried to add a tree-parent instead.

So, I don't think we need a different fix, and propose we backport the reversal
for gdb 15.2.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31900
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32158
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32160
2024-09-14 14:09:35 +02:00
Tom de Vries
93a20d956e [gdb/testsuite] Add regression test for PR32158
Consider test-case:
...
namespace ns {
  enum class ec {
    val2 = 2
  };
}

int main () {
  return (int)ns::ec::val2;
}
...
compiled with debug info:
...
$ g++ test.c -g
...

When looking at the cooked index entry for val2 using "maint print objfiles",
we get:
...
    [7] ((cooked_index_entry *) 0x7f8ecc002ef0)
    name:       val2
    canonical:  val2
    qualified:  ns::val2
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0xe9
    parent:     ((cooked_index_entry *) 0x7f8ecc002e90) [ns]
...
which is wrong, there is no source level entity ns::val2.

This is PR symtab/32158.

This is a regression since commit 4e417d7bb1 ("Change handling of
DW_TAG_enumeration_type in DWARF scanner").

Reverting the commit on current trunk fixes the problem, and gets us instead:
...
    [7] ((cooked_index_entry *) 0x7fba70002ef0)
    name:       val2
    canonical:  val2
    qualified:  ns::ec::val2
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0xe9
    parent:     ((cooked_index_entry *) 0x7fba70002ec0) [ec]
...

Add a regression test for this PR in test-case gdb.dwarf2/enum-type-c++.exp.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32158
2024-09-14 14:09:35 +02:00
Tom de Vries
2693187cc5 [gdb/testsuite] Add gdb.dwarf2/enum-type-c++.exp, regression test for PR31900.
Consider the following test-case:
...
$ cat a.h
namespace ns {

class A {
public:
  enum {
    val1 = 1
  };
};

}
$ cat main.c

ns::A a;

int
main (void)
{
  return 0;
}
$ cat val1.c

int u1 = ns::A::val1;
...
compiled with debug info:
...
$ g++ main.c val1.c -g
...

When trying to print ns::A::val with current trunk and gdb 15.1 we get:
...
$ gdb -q -batch a.out -ex "print ns::A::val1"
There is no field named val1
...

This PR c++/31900.

With gdb 14.2 we get the expected:
...
$ gdb -q -batch a.out -ex "print ns::A::val1"
$1 = ns::A::val1
...

This is a regression since commit 4e417d7bb1 ("Change handling of
DW_TAG_enumeration_type in DWARF scanner").

Reverting the commit on current trunk fixes the problem.

So how does this problem happen?

First, let's consider the current trunk, with the commit reverted.

Gdb looks for the entry ns::A::val1, and find this entry:
...
    [29] ((cooked_index_entry *) 0x7f7830002ef0)
    name:       val1
    canonical:  val1
    qualified:  ns::A::val1
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0x15a
    parent:     ((cooked_index_entry *) 0x7f7830002ec0) [A]
...
and expands the corresponding CU val1.c containing this debug info:
...
 <2><14a>: Abbrev Number: 3 (DW_TAG_class_type)
    <14b>   DW_AT_name        : A
    <14d>   DW_AT_byte_size   : 1
 <3><150>: Abbrev Number: 4 (DW_TAG_enumeration_type)
    <151>   DW_AT_encoding    : 7       (unsigned)
    <152>   DW_AT_byte_size   : 4
    <153>   DW_AT_type        : <0x163>
    <159>   DW_AT_accessibility: 1      (public)
 <4><15a>: Abbrev Number: 5 (DW_TAG_enumerator)
    <15b>   DW_AT_name        : val1
    <15f>   DW_AT_const_value : 1
 <4><160>: Abbrev Number: 0
 <3><161>: Abbrev Number: 0
 <2><162>: Abbrev Number: 0
...
after which it finds ns::A::val1 in the expanded symtabs.

Now let's consider the current trunk as is (so, with the commit present).

Gdb looks for the entry ns::A::val1, but doesn't find it because the val1
entry is missing its parent:
...
   [29] ((cooked_index_entry *) 0x7f5240002ef0)
    name:       val1
    canonical:  val1
    qualified:  val1
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0x15a
    parent:     ((cooked_index_entry *) 0)
...

Then gdb looks for the entry ns::A, and finds this entry:
...
   [3] ((cooked_index_entry *) 0x7f5248002ec0)
    name:       A
    canonical:  A
    qualified:  ns::A
    DWARF tag:  DW_TAG_class_type
    flags:      0x0 []
    DIE offset: 0xdd
    parent:     ((cooked_index_entry *) 0x7f5248002e90) [ns]
...
which corresponds to this debug info, which doesn't contain val1
due to -fno-eliminate-unused-debug-types:
...
 <2><dd>: Abbrev Number: 3 (DW_TAG_class_type)
    <de>   DW_AT_name        : A
    <e0>   DW_AT_byte_size   : 1
 <2><e3>: Abbrev Number: 0
...

Gdb expands the corresponding CU main.c, after which it doesn't find
ns::A::val1 in the expanded symtabs.

The root cause of the problem is the missing parent on the val1
cooked_index_entry, but this only becomes user-visible through the
elaborate scenario above.

Add a test-case gdb.dwarf2/enum-type-c++.exp that contains a regression test
for this problem that doesn't rely on expansion state or
-feliminate-unused-debug-types, but simply tests for the root cause by
grepping for ns::A::val1 in the output of "maint print objfile".

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31900
2024-09-14 14:09:35 +02:00
oltolm
1136616707 gdb dap: introduce stopOnEntry option
Approved-By: Tom Tromey <tom@tromey.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-09-13 14:19:34 -06:00
Tom Tromey
246119630a Update more types for section index change
Commit f89276a2f3 ("change type of `general_symbol_info::m_section`
to int") did what it says in the title -- changed the type of the
section index from short to int.  However, it seems incomplete, in
that there are uses of the section index that use the type 'short'.

This patch fixes the ones I found, first by searching for
"short.*sect" and then by looking at all the callers of section_index
(and then functions called with the resulting value) just to try to be
more sure.

Approved-by: Kevin Buettner <kevinb@redhat.com>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
2024-09-13 12:29:37 -06:00
Tom Tromey
24e5f97426 Fix quoting in gdb-add-index.sh
When the filename quoting change was merged into the AdaCore tree, we
saw a regression in a test setup that uses the DWARF 5 index (that is
running gdb-add-index), and a filename with a space in it.

Initially I thought this was a change in the 'file' command -- but
looking again, I found out that 'file' has worked this way for a
while, and our immediate error was caused by the (documented) change
to "save gdb-index".

While I'm not sure why this test was working previously, it seems to
me that gdb-add-index.sh requires a change to quote the arguments to
"file" and "save gdb-index".

While working on this, though, it seemed to me that multiple other
spots needed quoting for the script to work correctly.  And, I was
unable to get quoting working correctly in the objcopy calls, so I
split it into multiple different invocations.

Approved-by: Kevin Buettner <kevinb@redhat.com>
2024-09-13 10:16:29 -06:00
Tom Tromey
c7e57281af Add quoting to 'file' invocations in DAP
Oleg Tolmatcev noticed that DAP launch and attach requests don't
properly handle Windows filenames, because "file" doesn't handle the
backslash characters correctly.  This patch adds quoting to the
command in an attempt to fix this.
2024-09-13 09:34:50 -06:00
Simon Marchi
edb09798f2 gdb/solib: use owning_intrusive_list for solib list
Functions implementing `solib_ops::current_sos` return a list of solib
object, transferring the ownership to their callers.  However, the
return type, `intrusive_list<solib>`, does not reflect that.

Also, some of these functions build these lists incrementally, reading
this from the target for each solib.  If a target read were to throw,
for instance, the already created solibs would just be leaked.

Change `solib_ops::current_sos` to return an owning_intrusive_list to
address that.  Change `program_space::so_list` to be an
owning_intrusive_list as well.  This also saves us doing a few manual
deletes.

Change-Id: I6e4071d49744874491625075136c59cce8e608d4
Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-09-13 07:38:56 -04:00
Simon Marchi
8b8f98ad2b gdbsupport/intrusive-list: add owning_intrusive_list
It occured to me that `intrusive_list<solib>`, as returned by
`solib_ops::current_sos`, for instance, is not very safe.  The
current_sos method returns the ownership of the solib objects
(heap-allocated) to its caller, but the `intrusive_list<solib>` type
does not convey it.  If a function is building an
`intrusive_list<solib>` and something throws, the solibs won't
automatically be deleted.  Introduce owning_intrusive_list to fill this
gap.

Interface
---------

The interface of owning_intrusive_list is mostly equivalent to
intrusive_list, with the following differences:

 - When destroyed, owning_intrusive_list deletes all element objects.
   The clear method does so as well.

 - The erase method destroys the removed object.

 - The push_front, push_back and insert methods accept a `unique_ptr<T>`
   (compared to `T &` for intrusive_list), taking ownership of the
   object.

 - owning_intrusive_list has emplace_front, emplace_back and emplace
   methods, allowing to allocate and construct an object directly in the
   list.  This is really just a shorthand over std::make_unique and
   insert (or push_back / push_front if you don't care about the return
   value), but I think it is nicer to read:

     list.emplace (pos, "hello", 2);

   rather than

     list.insert (pos, std::make_unique<Foo> ("hello", 2));

   These methods are not `noexcept`, since the allocation or the
   constructor could throw.

 - owning_intrusive_list has a release method, allowing to remove an
   element without destroying it.  The release method returns a
   pair-like struct with an iterator to the next element in the list
   (like the erase method) and a unique pointer transferring the
   ownership of the released element to the caller.

 - owning_intrusive_list does not have a clear_and_dispose method, since
   that is typically used to manually free items.

Implementation
--------------

owning_intrusive_list privately inherits from intrusive_list, in order
to re-use the linked list machinery.  It adds ownership semantics around
it.

Testing
-------

Because of the subtle differences in the behavior in behavior and what
we want to test for each type of intrusive list, I didn't see how to
share the tests for the two implementations.  I chose to copy the
intrusive_list tests and adjust them for owning_intrusive_list.

The verify_items function was made common though, and it tries to
dereference the items in the list, to make sure they have not been
deleted by mistake (which would be caught by Valgrind / ASan).

Change-Id: Idbde09c1417b79992a0a9534d6907433e706f760
Co-Authored-By: Pedro Alves <pedro@palves.net>
Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-09-13 07:38:56 -04:00
Simon Marchi
d8ea57169c gdbsupport/intrusive-list: make insert return an iterator
Make the insert method return an iterator to the inserted element.  This
mimics what boost does [1] and what the standard library insert methods
generally do [2].

[1] https://www.boost.org/doc/libs/1_79_0/doc/html/boost/intrusive/list.html#idm33771-bb
[2] https://en.cppreference.com/w/cpp/container/vector/insert

Change-Id: I59082883492c60ee95e8bb29a18c9376283dd660
Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-09-13 07:38:56 -04:00
Stephan Rohr
a1371f3288 testsuite, trace: add guards if In-Process Agent library is not found
Several tests in gdb.trace trigger TCL errors if the In-Process Agent
library is not found, e.g.:

  Running gdb/testsuite/gdb.trace/change-loc.exp ...
  ERROR: tcl error sourcing gdb/testsuite/gdb.trace/change-loc.exp.
  ERROR: error copying "gdb/gdb/testsuite/../../gdbserver/libinproctrace.so":
	 no such file or directory
      while executing
  "file copy -force $fromfile $tofile"
      (procedure "gdb_remote_download" line 29)
      invoked from within
  "gdb_remote_download target $target_file"
      (procedure "gdb_download_shlib" line 6)
      invoked from within
  "gdb_download_shlib $file"
      (procedure "gdb_load_shlib" line 2)
      invoked from within
  "gdb_load_shlib $libipa"
      (file "gdb/testsuite/gdb.trace/change-loc.exp" line 354)
      invoked from within
  "source gdb/testsuite/gdb.trace/change-loc.exp"
      ("uplevel" body line 1)
      invoked from within
  "uplevel #0 source gdb/testsuite/gdb.trace/change-loc.exp"
      invoked from within
  "catch "uplevel #0 source $test_file_name""

Protect against this error by checking if the library is available.
2024-09-13 04:05:13 -07:00
Simon Marchi
f89276a2f3 gdb: change type of general_symbol_info::m_section to int
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-12 11:02:14 -04:00
Tom de Vries
e20c1e410b [gdb/testsuite] Simplify gdb.dwarf2/forward-spec.exp
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 8f258a6c97 ("[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-11 17:56:34 +02:00
Kyle Huey
1628e02267 gdb: Support DW_OP_constx (the standardized version of DW_OP_GNU_const_index).
Approved-By: Tom Tromey <tom@tromey.com>
2024-09-11 09:07:37 -06:00
Tom Tromey
ef54c7a94f Fix typo in Python TUI window text
I noticed a typo in the Python TUI window documentation.
2024-09-11 08:18:06 -06:00
Andrew Burgess
dbddec2a8e gdb/testsuite: fix argument order in example code within a comment
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-10 15:15:05 +01:00
Andrew Burgess
a80935397a gdb/testsuite: add return after a call to 'untested'
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-10 15:11:05 +01:00
Andrew Burgess
523b8f4f29 Revert "[gdb/testsuite] Handle missing curses in gdb.python/py-missing-debug.exp"
This reverts commit 29c7078711.

After the previous commit 29c7078711 should no longer be
needed as the curses dependency has been removed.
2024-09-10 14:07:11 +01:00
Andrew Burgess
5ddd0d7eef gdb/python: avoid depending on the curses library
The commit:

  commit 29c7078711
  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 14:07:11 +01:00
Tom de Vries
258c81da3c [gdb/testsuite] Fix gdb.xml/tdesc-regs.exp on riscv64
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 10:25:07 +02:00
Tom de Vries
bc13da1980 [gdb/build] Fix unused var in corelow.c
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-10 10:08:29 +02:00
Tom Tromey
2bf0419eea Move enum size check into ada_identical_enum_types_p
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-09 11:47:17 -06:00
Tom Tromey
511c6575b2 Minor cleanup to ada_identical_enum_types_p
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-09 11:47:17 -06:00
Tom Tromey
6b82623187 Boolify ada_identical_enum_types_p
This changes ada_identical_enum_types_p to return bool rather than
int.

Approved-By: Tom de Vries <tdevries@suse.de>
2024-09-09 11:47:17 -06:00
Tom Tromey
4f69c1b332 Fix some comments in dwarf2/cooked-index.h
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-09 11:42:34 -06:00
Tom Tromey
052736020a Refactor cooked_index_shard::handle_gnat_encoded_entry
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-09 11:37:35 -06:00
Tom Tromey
86d6495bd4 Ignore DW_TAG_padding in tag_is_type
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-09 11:32:40 -06:00
Andrew Burgess
b6900dc739 gdb/NEWS: group general news items together
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-09 11:29:33 +01:00
Andrew Burgess
da8730e8f9 gdb: fix use of out of scope temporary variable in break-cond-parse.c
The commit:

  commit c6b486755e
  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 21:17:55 +01:00
Tom de Vries
29c7078711 [gdb/testsuite] Handle missing curses in gdb.python/py-missing-debug.exp
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-08 07:46:09 +02:00
Andrew Burgess
6cce025114 gdb: only insert thread-specific breakpoints in the relevant inferior
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-07 21:48:35 +01:00
Andrew Burgess
85eb08c5f0 gdb: don't set breakpoint::pspace in create_breakpoint
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 cc72b2a2da
  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 f8eba3c616
  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 cc72b2a2da 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-07 21:48:35 +01:00
Andrew Burgess
c6b486755e gdb: parse pending breakpoint thread/task immediately
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-07 21:48:35 +01:00
Andrew Burgess
5a7cfbb424 gdb: create new is_thread_id helper function
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-07 21:48:34 +01:00
Andrew Burgess
4764e22161 gdb: make breakpoint_debug_printf global
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-07 21:48:34 +01:00
Tom Tromey
26d23d8e02 Remove tui_refresh_cmd_win
tui_refresh_cmd_win is no longer needed and can be replaced with a
call to the refresh_window method.
2024-09-07 14:23:04 -06:00
Tom Tromey
a35cc8ff85 Remove tui_wrefresh
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-07 14:23:04 -06:00
Tom Tromey
d3acf3d759 Rename tui_suppress_output
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-07 14:23:04 -06:00
Tom Tromey
8f934adf59 Clean up refreshing in TUI register window
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-07 14:23:04 -06:00
Andrew Burgess
03ad29c86c gdb: 'target ...' commands now expect quoted/escaped filenames
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-07 20:28:59 +01:00
Andrew Burgess
e454ae416a gdb: allow quoted filenames for commands that have custom completion
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-07 20:28:59 +01:00
Andrew Burgess
d552429eda gdb: add remove-symbol-file command completion
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-07 20:28:59 +01:00
Andrew Burgess
1be3b2e82f gdb: extend completion of quoted filenames to work in brkchars phase
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-07 20:28:59 +01:00
Andrew Burgess
1217ae6726 gdb: new extract_single_filename_arg helper function
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-07 20:28:58 +01:00