Commit Graph

121406 Commits

Author SHA1 Message Date
Nick Alcock
003f19bfa7 libctf: make ctf_dynamic_type() the inverse of ctf_static_type()
They're meant to be inverses, which makes it unfortunate that
they check different bounds.  No visible effect yet, since
ctf_typemax and ctf_stypes currently cover the entire type ID
space, but will have an effect shortly.
2025-02-28 15:13:24 +00:00
Nick Alcock
b875301e74 libctf: drop LCTF_TYPE_ISPARENT/LCTF_TYPE_ISCHILD
Parent/child determination is about to become rather more complex, making a
macro impractical.  Use the ctf_type_isparent/ischild function calls
everywhere and remove the macro.  Make them more const-correct too, to
make them more widely usable.

While we're about it, change several places that hand-implemented
ctf_get_dict() to call it instead, and armour several functions against
the null returns that were always possible in this case (but previously
unprotected-against).
2025-02-28 15:13:24 +00:00
Nick Alcock
9835747b21 libctf: generalize the ref system
Despite the removal of the separate movable ref list, the ref system as
a whole is more than complex enough to be worth generalizing now that
we are adding different kinds of ref.

Refs now are lists of uint32_t * which can be updated through the
pointer for all entries in the list and moved to new sites for all
pointers in a given range: they are no longer references to string
offsets in particular and can be references to other uint32_t-sized
things instead (note that ctf_id_t is a typedef to a uint32_t).

ctf-string.c has been adjusted accordingly (the adjustments are tiny,
more or less just turning a bunch of references to atom into
&atom->csa_refs).
2025-02-28 15:13:24 +00:00
Nick Alcock
69d4f6d74c libctf, string: remove movable refs properly
Ever since pending refs were replaced with movable refs, we were failing
to remove movable ref backpointers properly on ctf_remove_ref.  I don't
see how this could cause any problem but a memory leak, but since we
do ultimately write down refs, leaking references to refs is still
risky: best to fix this.
2025-02-28 15:13:23 +00:00
Nick Alcock
21f748e1e3 libctf, string: delete separate movable ref storage again
This was added last year to let us maintain a backpointer to the movable
refs dynhash in movable ref atoms without spending space for the
backpointer on the majority of (non-movable) refs and also without
causing an atom which had some refs movable and some refs not movable to
dereference unallocated storage when freed.

The backpointer's only purpose was to let us locate the
ctf_str_movable_refs dynhash during item freeing, when we had nothing
but a pointer to the atom being freed.  Now we have a proper freeing
arg, we don't need the backpointer at all: we can just pass a pointer to
the dict in to the atoms dynhash as a freeing arg for the atom freeing
functions, and throw the whole backpointer and separate movable ref list
complexity away.
2025-02-28 15:13:23 +00:00
Nick Alcock
6a6a3cc9c2 libctf, hash: add support for freeing functions taking an arg
There are a bunch of places in libctf where the code is complicated
by the fact that freeing a hash key or value requires access to the
dict: more generally, they want an arg pointer to *something*.

But for the sake of being able to use free() as a freeing function,
we can't do this at all times.  We also don't want to bloat up the
hash itself with an arg value unless necessary (in the same way we
already avoid storing the key or value freeing functions unless at
least one of them is specified).

So from the outside this change is simple: add a new
ctf_dynhash_create_arg which takes a new sort of freeing function
which takes an argument.  Internally, we store the arg only when
the key or owner is set, and cast from the one freeing function
to the other iff the arg is non-NULL.  This means it's impossible
to pass a value that may or may not be NULL to the freeing
function, but that's harmless for all current uses, and allows
significant simplifications elsewhere.
2025-02-28 15:13:23 +00:00
Nick Alcock
d996ca5e85 libctf: move ctf_elf*_to_link_sym to ctf-link.c
Everything in ctf-util.c is in some way associated with data
structures in general in some way, except for the ctf_*_to_link_sym
functions, which are straight translators between the Elf*_Sym
type and the ctf_link_sym_t type used by ctf-link.c.

Move them into ctf-link.c where they belong.
2025-02-28 15:13:17 +00:00
Nick Alcock
4a7870a831 libctf: split up ctf-subr.c
This file is a bit of a grab-bag of dict-wide API functions like
ctf_set_open_errno or ctf_errwarning_next and portabilty functions and
wrappers like ctf_mmap or ctf_pread.

Split the latter out, and move other dict-wide functions that got
stuck in ctf-util.c (because it was so hard to tell the two files
apart) into ctf-api.c where they belong.
2025-02-28 15:12:02 +00:00
Nick Alcock
ac07bccf05 libctf: dedup: describe 'citer'
The distinction between the citer and citers variables in
ctf_dedup_rhash_type is somewhat opaque (it's a micro-optimization to avoid
having to allocate entire sets when we know in advance that we'll only have
to store one value).  Add a comment.

libctf/
	* ctf-dedup.c (ctf_dedup_rhash_type): Comment on citers variables.
2025-02-28 14:47:24 +00:00
Nick Alcock
06cefeee6b libctf: fix obsolete comment
Pending refs haven't been a thing for a while now.

libctf/
	* ctf-create.c (ctf_add_member_offset): Fix comment.
2025-02-28 14:47:24 +00:00
Nick Alcock
acf3236e6b libctf: a little string sharing test
It's actually quite hard to come up with simple tests that do *not* share
all their strings, but with enough ingenuity suitable cycles can be
concocted.

This test verifies that only and precisely those strings that are only used
in one child dict actually end up in its strtab.

ld/
	* testsuite/ld-ctf/unshared-strings*: New test.
2025-02-28 14:47:24 +00:00
Nick Alcock
4d2d5afa60 libctf: actually deduplicate the strtab
This commit finally implements strtab deduplication, putting together all
the pieces assembled in the earlier commits.

The magic is entirely localized to ctf_link_write, which preserializes all
the dicts (parent first), and calls ctf_dedup_strings on the parent.

(The error paths get tweaked a bit too.)

Calling ctf_dedup_strings has implications elsewhere: the lifetime rules for
the inputs versus outputs change a bit now that the child output dicts
contain references to the parent dict's atoms table.  We also pre-purge
movable refs from all the deduplicated strings before freeing any of this
because movable refs contain backreferences into the dict they came from,
which means the parent contains references to all the children!  Purging
the refs first makes those references go away so we can free the children
without creating any wild pointers, even temporarily.

There's a new testcase that identifies a regression whereby offset 0 (the
null string) and index 0 (in children now often the parent dict name,
".ctf") got mixed up, leading to anonymous structs and unions getting the
not entirely C-valid name ".ctf" instead.

May other testcases get adjusted to no longer depend on the precise layout
of the strtab.

TODO: add new tests to verify that strings are actually being deduplicated.

libctf/
	* ctf-link.c (ctf_link_write): Deduplicate strings.
	* ctf-open.c (ctf_dict_close): Free refs, then the link outputs,
        then the out cu_mapping, then the inputs, in that order.
        * ctf-string.c (ctf_str_purge_refs): Not static any more.
	* ctf-impl.h: Declare it.

ld/
	* testsuite/ld-ctf/conflicting-cycle-2.A-1.d: Don't depend on
        strtab contents.
	* testsuite/ld-ctf/conflicting-cycle-2.A-2.d: Likewise.
	* testsuite/ld-ctf/conflicting-cycle-2.parent.d: Likewise.
	* testsuite/ld-ctf/conflicting-cycle-3.C-1.d: Likewise.
	* testsuite/ld-ctf/conflicting-cycle-3.C-2.d: Likewise.
	* testsuite/ld-ctf/anonymous-conflicts*: New test.
2025-02-28 14:47:24 +00:00
Nick Alcock
9daceda796 libctf: dedup: add strtab deduplicator
This is a pretty simple two-phase process (count duplicates that are
actually going to end up in the strtab and aren't e.g. strings without refs,
strings with external refs etc, and move them into the parent) with one
wrinkle: we sorta-abuse the csa_external_offset field in the deduplicated
child atom (normally used to indicate that this string is located in the ELF
strtab) to indicate that this atom is in the *parent*.  If you think of
"external" as meaning simply "is in some other strtab, we don't care which
one", this still makes enough sense to not need to change the name, I hope.

This is still not called from anywhere, so strings are (still!) not
deduplicated, and none of the dedup machinery added in earlier commits does
anything yet.

libctf/
	* ctf-dedup.c (ctf_dedup_emit_struct_members): Note that strtab
	dedup happens (well) after struct member emission.
	(ctf_dedup_strings): New.
	* ctf-impl.h (ctf_dedup_strings): Declare.
2025-02-28 14:47:24 +00:00
Nick Alcock
ba66e0cc32 libctf: do not deduplicate strings in the header
It is unreasonable to expect users to ctf_import the parent before being
able to understand the header -- doubly so because the only string in the
header which is likely to be deduplicable is the parent name, which is the
same in every child, yet without the parent name being *available* in the
child's strtab you cannot call ctf_parent_name to figure out which parent
to import!

libctf/
	* ctf-serialize.c (ctf_preserialize): Prevent deduplication of header string
        fields.
	* ctf-open.c (ctf_set_base): Note this.
	* ctf-string.c (ctf_str_free_atom): Likewise.
2025-02-28 14:47:24 +00:00
Nick Alcock
3bec4f1f3c include, libctf: string lookup and writeout of a parent-shared strtab
The next stage of strtab sharing is actual lookup of strings in such
strtabs, interning of strings in such strtabs and writing out of
such strtabs (but not actually figuring out which strings should
be shared: that's next).

We introduce several new internal ctf_str_* API functions to augment the
existing rather large set: ctf_str_add_copy, which adds a string and always
makes a copy of it (used when deduplicating to stop dedupped strings holding
permanent references on the input dicts), and ctf_str_no_dedup_ref (which
adds a ref to a string while preventing it from ever being deduplicated,
used for header fields like the parent name, which is the same for almost
all child dicts but had still better not be stored in the parent!).

ctf_strraw_explicit, the ultimate underlying "look up a string" function
that backs ctf_strptr et al, gains the ability to automatically find strings
in the parent if the offset is < cth_parent_strlen, and generally make all
offsets parent-relative (so something at offset 1 in the child strlen will
need to be looked up at offset 257 if cth_parent_strlen is 256).  This
suffices to paste together the parent and child from the perspective
of lookup.

We do quite a lot of new checks in here, simply because it's called all over
the place and it's preferable to emit a nice error into the ctf_err_warning
stream if things go wrong.  Among other things this traps cases where you
accidentally added a string to the parent, throwing off all the offsets.
Completely invalid offsets also now add a message to the err_warning
stream.

Insertion of new atoms (the deduplicated entities underlying strings in a
given dict), already a flag-heavy operation, gains more flags, corresponding
to the new ctf_str_add_copy and ctf_str_no_dedup_ref functions: atom
addition also checks the ctf_max_children set by ctf_import and prevents
addition of new atoms to any dicts with ctf_imported children and an
already-serialized strtab.

strtab writeout gains more checks as well: you can't write out a strtab for
a child dict whose parent hasn't been serialized yet (and thus doesn't have
a serialized strtab itself); you can't write it out if the child already
depended on a shared parent strtab and that strtab has changed length.  The
null atom at offset 0 is only written to the parent strtab; and ref updating
changes to look up offsets in the parent's atoms table iff a new
CTF_STR_ATOM_IN_PARENT flag is set on the atom (this will be set by
deduplication to ensure that serializing a dict will update all its refs
properly even though a bunch of them have moved to the parent dict).

None of this actually has any *effect* yet because no string deduplication
is being carried out, and the cth_parent_strlen is still locked at 0.

include/
	* ctf-api.h (_CTF_ERRORS) [ECTF_NOTSERIALIZED]: New.
        (ECTF_NERR): Updated.

libctf/
	* ctf-impl.h (CTF_STR_ATOM_IN_PARENT): New.
	(CTF_STR_ATOM_NO_DEDUP): Likewise.
	(ctf_str_add_no_dedup_ref): New.
	(ctf_str_add_copy): New.
	* ctf-string.c (ctf_strraw_explicit): Look in parents if necessary:
        use parent-relative offsets.
	(ctf_strptr_validate): Avoid duplicating errors.
	(ctf_str_create_atoms): Update comment.
	(CTF_STR_COPY): New.
	(CTF_STR_NO_DEDUP): Likewise.
	(ctf_str_add_ref_internal): Use them, setting the corresponding
        csa_flags, prohibiting addition to serialized parents, and copying
        strings if so requested.
	(ctf_str_add): Turn into a wrapper around...
	(ctf_str_add_flagged): ... this new function.  The offset is now
        parent-relative.
	(ctf_str_add_ref): Likewise.
	(ctf_str_add_movable_ref): Likewise.
	(ctf_str_add_copy): New.
	(ctf_str_add_no_dedup_ref): New.
	(ctf_str_write_strtab): Prohibit writes when the parent has
        changed length or is not serialized.  Only write the null atom
        to parent strtabs.  Chase refs to the parent if necessary.
2025-02-28 14:47:24 +00:00
Nick Alcock
a14fb397b2 libctf: tear opening and serialization in two
The next stage in sharing the strtab involves tearing two core parts
of libctf into two pieces.

Large parts of init_static_types, called at open time, involve traversing
the types table and initializing the hashtabs used by the type name lookup
functions and the enumerator conflicting checks.  If the string table is
partly located in the parent dict, this is obviously not going to work: so
split out that code into a new init_static_types_names function (which
also means moving the wrapper around init_static_types that was used
to simplify the enumerator code into being a wrapper around
init_static_types_names instead) and call that from init_static_types
(for parent dicts, and < v4 dicts), and from ctf_import (for v4 dicts).

At the same time as doing this we arrange to set LCTF_NO_STR (recently
introduced) iff this is a v4 child dict with a nonzero cth_parent_strlen:
this then blocks more or less everything that involves string operations
until a ctf_import has actually imported the strtab it depends on.  (No
string oeprations that actually use this have been introduced yet, but
since no string deduplication is happening yet either this is harmless.)

For v4 dicts, at import time we also validate that the cth_parent_strlen has
the same value as the parent's strlen (zero is also a valid value,
indicating a non-shared strtab, as is commonplace in older dicts, dicts
emitted by the compiler, parent dicts etc).  This makes ctf_import more
complex, so we simplify things again by dropping all the repeated code in
the obscure used-only-by-ctf_link ctf_import_unref and turning both into
wrappers around an internal function.  We prohibit repeated ctf_imports
(except of NULL or the same dict repeatedly), and set up some new fields
which will be used later to prevent people from adding strings to parent
dicts with pre-existing serialized strtabs once they have children imported
into them (which would change their string length and corrupt all those
strtabs).

Serialization also needs to be torn in two.  The problem here is that
currently serialization does too much: it emits everything including the
strtab, does things that depend on the strtab being finalized (notably
variable table sorting), and then writes it out.  Much of this emission
itself involves strtab writes, so the strtab is not actually complete until
halfway through ctf_serialize.  But when deduplicating, we want to use
machinery in ctf-link and ctf-dedup to deduplicate the strtab after it is
complete, and only then write it out.

We could do this via having ctf_serialize call some sort of horrible
callback, but it seems much simpler to just cut ctf_serialize in two,
and introduce a new ctf_preserialize which can optionally be called to do
all this "everything but the strtab" work.  (If it's not called,
ctf_serialize calls it itself.)

This means pulling some internal variables out of ctf_serialize into the
ctf_dict_t, and slightly abusing LCTF_NO_STR to mean (in addition to its
"no, you can't do much between opening a child dict and importing its
parent" semantics), "no, you can't do much between calling ctf_preserialize
and ctf_serialize". The requirements of both are not quite identical -- you
definitely can do things that involve string lookups after ctf_preserialize
-- but it serves to stop callers from accidentally adding more types after
the types table has been written out, and that's good enough.
ctf_preserialize isn't public API anyway.

libctf/
	* ctf-impl.h (struct ctf_dict) [ctf_serializing_buf]: New.
        [ctf_serializing_buf_size]: Likewise.
        [ctf_serializing_vars]: Likewise.
        [ctf_serializing_nvars]: Likewise.
        [ctf_max_children]: Likewise.
	(LCTF_PRESERIALIZED): New.
	(ctf_preserialize): New.
	(ctf_depreserialize): New.
	* ctf-open.c (init_static_types): Rename to...
	(init_static_types_names): ... this, wrapping a different
        function.
        (init_static_types_internal): Rename to...
        (init_static_types): ... this, and set LCTF_NO_STR if neecessary.
        Tear out the name-lookup guts into...
	(init_static_types_names_internal): ... this new function. Fix a few
        comment typos.
	(ctf_bufopen): Emphasise that you cannot rely on looking up strings
        at any point in ctf_bufopen any more.
	(ctf_dict_close): Free ctf_serializing_buf.
	(ctf_import): Turn into a wrapper, calling...
	(ctf_import_internal): ... this.  Prohibit repeated ctf_imports of
        different parent dicts, or "unimporting" by setting it back to NULL
        again.  Validate the parent we do import using cth_parent_strlen.
        Call init_static_types_names if the strtab is shared with the
        parent.
	(ctf_import_unref): Turn into a wrapper.
	* ctf-serialize.c (ctf_serialize): Split out everything before
        strtab serialization into...
	(ctf_preserialize): ... this new function.
	(ctf_depreserialize): New, undo preserialization on error.
2025-02-28 14:47:24 +00:00
Nick Alcock
6c77689963 include, libctf: add cth_parent_strlen CTFv4 header field
The first format difference between v3 and v4 is a cth_parent_strlen header
field.  This field (obviously not present in BTF) is populated from the
string table length of the parent at serialization time (protection against
being serialized before the parent is will be added in a later commit in
this series), and will be used at open time to prohibit opening of dicts
with a different strlen (which would corrupt the child's string table
if it was shared with the parent).

For now, just add the field, populate it at serialization time when linking
(when not linking, no deduplication is done and the correct value remains
unchanged), and dump it.

include/
	* ctf.h (ctf_header) [cth_parent_strlen]: New.

libctf/
	* ctf-dump.c (ctf_dump_header_sizefield): New.
	(ctf_dump_header): Use to dump the cth_parent_strlen.
	* ctf-open.c (upgrade_header_v2): Populate cth_parent_strlen.
	(upgrade_header_v3): Likewise.
	(ctf_flip_header): Flip it.
	(ctf_bufopen): Drop unnecessary initialization.
	* ctf-serialize.c (ctf_serialize): Write it out when linking.

ld/
	* testsuite/ld-ctf/data-func-conflicted-vars.d: Skip the nwe dump output.
	* testsuite/ld-ctf/data-func-conflicted.d: Likewise.
2025-02-28 14:47:24 +00:00
Nick Alcock
70d05ab0b2 libctf: add mechanism to prohibit most operations without a strtab
We are about to add machinery that deduplicates a child dict's strtab
against its parent.  Obviously if you open such a dict but do not import its
parent, all strtab lookups must fail: so add an LCTF_NO_STR flag that is set
in that window and make most operations fail if it's not set.  (Two more
that will be set in future commits are serialization and string lookup
itself.)

Notably, not all symbol lookup is impossible in this window: you can still
look up by symbol index, as long as this dict is not using an indexed
strtypetab (which obviously requires string lookups to get the symbol name).

include/
	* ctf-api.h (_CTF_ERRORS) [ECTF_HASPARENT]: New.
        [ECTF_WRONGPARENT]: Likewise.
	(ECTF_NERR): Update.
        Update comments to note the new limitations on ctf_import et al.

libctf/
	* ctf-impl.h (LCTF_NO_STR): New.
	* ctf-create.c (ctf_rollback): Error out when LCTF_NO_STR.
	(ctf_add_generic): Likewise.
	(ctf_add_struct_sized): Likewise.
	(ctf_add_union_sized): Likewise.
	(ctf_add_enum): Likewise.
	(ctf_add_forward): Likewise.
	(ctf_add_unknown): Likewise.
	(ctf_add_enumerator): Likewise.
	(ctf_add_member_offset): Likewise.
	(ctf_add_variable): Likewise.
	(ctf_add_funcobjt_sym_forced): Likewise.
	(ctf_add_type): Likewise (on either dict).
	* ctf-dump.c (ctf_dump): Likewise.
	* ctf-lookup.c (ctf_lookup_by_name): Likewise.
	(ctf_lookup_variable): Likewise. Likewise.
	(ctf_lookup_enumerator): Likewise.
	(ctf_lookup_enumerator_next): Likewise.
	(ctf_symbol_next): Likewise.
	(ctf_lookup_by_sym_or_name): Likewise, if doing indexed lookups.
	* ctf-types.c (ctf_member_next): Likewise.
	(ctf_enum_next): Likewise.
	(ctf_type_aname): Likewise.
	(ctf_type_name_raw): Likewise.
	(ctf_type_compat): Likewise, for either dict.
	(ctf_member_info): Likewise.
	(ctf_enum_name): Likewise.
	(ctf_enum_value): Likewise.
	(ctf_type_rvisit): Likewise.
	(ctf_variable_next): Note that we don't need to test LCTF_NO_STR.
2025-02-28 14:47:24 +00:00
Nick Alcock
30cced0da6 libctf, archive, link: fix parent importing
We are about to move to a regime where there are very few things you can do
with most dicts before you ctf_import them.  So emit a warning if
ctf_archive_next()'s convenience ctf_import of parents fails.  Rip out the
buggy code in ctf_link_deduplicating_open_inputs which opened the parent by
hand (with a hardwired name), and instead rely on ctf_archive_next to do it
for us (which also means we don't end up opening it twice, once in
ctf_archive_next, once in ctf_link_deduplicating_open_inputs).

While we're there, arrange to close the inputs we already opened if opening
of some inputs fails, rather than leaking them.  (There are still some leaks
here, so add a comment to remind us to clean them up later.)

libctf/
	* ctf-archive.c (ctf_arc_import_parent): Emit a warning if importing
	fails.
	* ctf-link.c (ctf_link_deduplicating_open_inputs): Rely on the
        ctf_archive_next to open parent dicts.
2025-02-28 14:47:24 +00:00
Nick Alcock
9a74ab12c8 include, libctf: start work on libctf v4
This format is a superset of BTF, but for now we just do the minimum to
declare a new file format version, without actually introducing any format
changes.

From now on, we refuse to reserialize CTFv1 dicts: these have a distinct
parent/child boundary which obviously cannot change upon reserialization
(that would change the type IDs): instead, we encoded this by stuffing in
a unique CTF version for such dicts.  We can't do that now we have one
version for all CTFv4 dicts, and testing such old dicts is very hard these
days anyway, and is not automated: so just drop support for writing them out
entirely. (You still *can* write them out, but you have to do a full-blown
ctf_link, which generates an all-new fresh dict and recomputes type IDs as
part of deduplication.)

To prevent this extremely-not-ready format escaping into the wild, add a
new mechanism whereby any format version higher than the new #define
CTF_STABLE_VERSION cannot be serialized unless I_KNOW_LIBCTF_IS_UNSTABLE is
set in the environment.

include/
	* ctf-api.h (_CTF_ERRORS) [ECTF_CTFVERS_NO_SERIALIZE]: New.
        [ECTF_UNSTABLE]: New.
         (ECTF_NERR): Update.
	* ctf.h: Small comment improvements..
        (ctf_header_v3): New, copy of ctf_header.
	(CTF_VERSION_4): New.
	(CTF_VERSION): Now CTF_VERSION_4.
	(CTF_STABLE_VERSION): Still 4, CTF_VERSION_3.

ld/
	* testsuite/ld-ctf/*.d: Update to CTF_VERSION_4.

libctf/
	* ctf-impl.h (LCTF_NO_SERIALIZE): New.
	* ctf-dump.c (ctf_dump_header): Add CTF_VERSION_4.
	* ctf-open.c (ctf_dictops): Likewise.
        (upgrade_header): Rename to...
	(upgrade_header_v2): ... this.
	(upgrade_header_v3): New.
	(upgrade_types): Support upgrading from CTF_VERSION_3.
        Turn on LCTF_NO_SERIALIZE for CTFv1.
	(init_static_types_internal): Upgrade all types tables older than
	* CTF_VERSION_4.
	(ctf_bufopen): Support CTF_VERSION_4: error out if we forget to
	update this switch in future.  Add header upgrading from v3 and
	below.  Improve comments slightly.
	* ctf-serialize.c (ctf_serialize): Block serialization of unstable
	file formats, and of file formats for which LCTF_NO_SERIALIZE is
	turned on (v1).
2025-02-28 14:47:24 +00:00
Tom de Vries
8cdf110a11 [gdb/testsuite] Fix gdb.base/nostdlib.exp on aarch64
On aarch64-linux, in test-case gdb.base/nostdlib.exp I run into:
...
(gdb) continue^M
Continuing.^M
warning: Temporarily disabling breakpoints for unloaded shared library \
  "/lib/ld-linux-aarch64.so.1"^M
^M
Breakpoint 2, _start () at nostdlib.c:20^M
20      {^M
(gdb) FAIL: $exp: pie=pie: continue to marker
...

This happens as follows:
- the test-case sets a breakpoint on *_start,
- the breakpoint resolves to *_start in the executable,
- the executable is started, and the breakpoint resolves to *_start in the
  dynamic linker,
- execution stops at *_start in the dynamic linker,
- the test-case issues a continue, expecting to continue to the breakpoint on
  marker,
- while continuing, the dynamic linker is reported as unloaded,
- the breakpoint again resolves to *_start in the executable,
- execution stops at *_start in the executable, and
- the test-case concludes that it failed to "continue to marker".

This doesn't happen on x86_64-linux.  There, after the executable is started,
the breakpoint again resolves to *_start in the exec.

This is similar to what happens when printing _start.

On aarch64-linux, we print the _start in the dynamic linker:
...
$ gdb -q -batch outputs/gdb.base/nostdlib/nostdlib-pie \
    -ex "b _start" \
    -ex run \
    -ex "print _start" \
    -ex "info break"
Breakpoint 1 at 0x2bc: file nostdlib.c, line 23.

Breakpoint 1.2, _start () at ../sysdeps/aarch64/dl-start.S:22
22      ENTRY (_start)
$1 = {void (void)} 0xfffff7fd6ac0 <_start>
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   <MULTIPLE>
        breakpoint already hit 1 time
1.1                         y   0x0000aaaaaaaa02bc in _start at nostdlib.c:23
1.2                         y   0x0000fffff7fd6ac0 in _start at dl-start.S:22
...

On x86_64-linux, we print the _start in the exec:
...
Breakpoint 1 at 0x2c5: file nostdlib.c, line 23.

Breakpoint 1.2, 0x00007ffff7fe4f00 in _start () from \
  /lib64/ld-linux-x86-64.so.2
$1 = {void (void)} 0x5555555542c1 <_start>
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   <MULTIPLE>
	breakpoint already hit 1 time
1.1                         y   0x00005555555542c5 in _start at nostdlib.c:23
1.2                         y   0x00007ffff7fe4f00 <_start>
...

The difference may be down to the availability of debug info for the _start in
the dynamic linker.

Finally, the described scenario on aarch64-linux is not deterministic.  The
behavior depends on the dynamic linker being reported as unloaded, which has
been classified as a GLIBC bug, so that might get fixed.

Ideally this test-case would stop at both *_start in the executable and the
dynamic linker, but in absense of a way to specify this reliably (see PR32748),
fix this by making this a temporary breakpoint, ensuring that the breakpoint
will only trigger once.

Approved-by: Kevin Buettner <kevinb@redhat.com>

PR testsuite/32743
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32743
2025-02-28 14:13:02 +01:00
Simon Marchi
b6fb76ec6e gdb, gdbserver, gdbsupport: fix some namespace comment formatting
I noticed a

  // namespace selftests

comment, which doesn't follow our comment formatting convention.  I did
a find & replace to fix all the offenders.

Change-Id: Idf8fe9833caf1c3d99e15330db000e4bab4ec66c
2025-02-27 21:35:38 -05:00
GDB Administrator
f0e6467e10 Automatic date update in version.in 2025-02-28 00:00:12 +00:00
Simon Marchi
661a85884f gdb/dwarf: fix failed assertion in dwarf2_find_containing_comp_unit selftest
Commit 2f0521c0d6 ("gdb/dwarf: fix signature_type created with nullptr
section") added some asserts in the dwarf2_per_cu_data constructor to
verify that the passed dwarf2_per_bfd and dwarf2_section_info are not
nullptr.  However, the dummy dwarf2_per_cu_data objects created in the
dwarf2_find_containing_comp_unit selftests are passed nullptr for those
parameters.

I prefer to keep the asserts in place, as protection for the non-test
code and as self documentation, so fix this by passing some dummy
pointers in the test.

Change-Id: Ic7cdc1b976f7506041b651222234eefc998e473a
Reviewed-By: Tom de Vries <tdevries@suse.de>
2025-02-27 10:15:34 -05:00
Simon Marchi
39ee8c9285 gdb/dwarf: pass unit length to dwarf2_per_cu_data constructor
Most of the time, the length of a unit is known when constructing a
dwarf2_per_cu_data or signatured_type.  Add a construtor parameter for
it.  In the few cases where it isn't, pass 0, which leaves it unset.

Change-Id: I0c8b9683164d3e3f3823ed995f71689a4d17fd96
Reviewed-By: Tom de Vries <tdevries@suse.de>
2025-02-27 10:15:23 -05:00
Nick Clifton
1142f1b334 Updated translations for bfd and gold 2025-02-27 12:16:26 +00:00
H.J. Lu
c44400b6ad x86-64: Pass -z separate-code to ld for -z mark-plt tests
Pass -z separate-code to ld for -z mark-plt tests to fix:

FAIL: ld-x86-64/mark-plt-1a
FAIL: ld-x86-64/mark-plt-1b
FAIL: ld-x86-64/mark-plt-1c
FAIL: ld-x86-64/mark-plt-1d
FAIL: ld-x86-64/mark-plt-1a-x32
FAIL: ld-x86-64/mark-plt-1b-x32
FAIL: ld-x86-64/mark-plt-1c-x32
FAIL: ld-x86-64/mark-plt-1d-x32

when binutils is configured with --disable-separate-code.

	* ld-x86-64/mark-plt-1a-x32.d: Pass -z separate-code to ld.
	* ld-x86-64/mark-plt-1a.d: Likewise.
	* ld-x86-64/mark-plt-1b-x32.d: Likewise.
	* ld-x86-64/mark-plt-1b.d: Likewise.
	* ld-x86-64/mark-plt-1c-x32.d: Likewise.
	* ld-x86-64/mark-plt-1c.d: Likewise.
	* ld-x86-64/mark-plt-1d-x32.d: Likewise.
	* ld-x86-64/mark-plt-1d.d: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
2025-02-27 08:19:29 +08:00
GDB Administrator
2d1374a760 Automatic date update in version.in 2025-02-27 00:00:31 +00:00
Indu Bhagat
887373a45f gas: sframe: partially process DWARF unwind info in CFI_escape
CFI_escape is most commonly used to include DWARF expressions in the
unwind information.  One may also use CFI_escape to add OS-specific CFI
opcodes.  Up until now, SFrame generation process would skip generating
SFrame FDE at the mere sight of a CFI_escape opcode.

Fine tune the handling of CFI_escape for SFrame generation by explicitly
checking for few "harmless" (in context of SFrame generation)
CFI_escape DWARF info:
  - DW_CFA_expression affecting registers of no significance to SFrame
    stack trace info
  - DW_CFA_value_offset affecting registers of no significance to SFrame
    stack trace info

Expose the current cfi_escape_data structure in dw2gencfi.c to the
relevant header file to allow SFrame generation APIs to use it too.

Valid unwind info may be split across multiple .cfi_escape directives.
Conversely, it is also allowed to simply put multiple DWARF expressions
and/or operations in a single .cfi_escape directive.  Handling all of
these cases correctly will need parsing/processing that is not deemed
worth the effort in context of SFrame generation; We continue to skip
generating SFrame FDE for these cases and warn the user.

In future, SFrame stack trace format may support non-SP/FP as base
register (albeit in limited form).  Add an explicit check in
sframe_xlate_do_escape_expr (to test against the current CFA register)
to ensure the functionality continues to work.

Use differentiated warning text in sframe_xlate_do_val_offset to avoid
confusion to the user as the same function is used for handling
.cfi_val_offset and .cfi_escape DW_CFA_val_offset,...

Also, add a common test with DWARF reg 12 which is non SP / FP on x86_64
and aarch64 (and s390x too).

gas/
	* gas/dw2gencfi.c (struct cfi_escape_data): Move from ...
	* gas/dw2gencfi.h (struct cfi_escape_data): ... to.
	* gas/gen-sframe.c (sframe_xlate_do_val_offset): Include string
	for .cfi_escape conditionally.
	(sframe_xlate_do_escape_expr): New definition.
	(sframe_xlate_do_escape_val_offset): Likewise.
	(sframe_xlate_do_cfi_escape): Likewise.
	(sframe_do_cfi_insn): Handle CFI_escape explicitly.

gas/testsuite/
	* gas/cfi-sframe/cfi-sframe.exp: Add new tests.
	* gas/cfi-sframe/cfi-sframe-common-9.d: New test.
	* gas/cfi-sframe/cfi-sframe-common-9.s: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-1.d: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-1.s: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-2.d: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-2.s: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-3.d: New test.
	* gas/cfi-sframe/cfi-sframe-x86_64-empty-3.s: New test.
2025-02-26 13:50:49 -08:00
Charlie Jenkins
227a52fbbd RISC-V: Fix abort when displaying data and partial instructions
If data is encountered that is not a power of two, dump all of the data with
a .<N>byte directive.  The current largest support risc-v instruction length
is 22, so the data over 22 bytes will be displayed by,
.insn, 22, ... + .<N-22>byte.

Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
2025-02-26 23:12:17 +08:00
Clément Chigot
5e0032993a ld/testsuite: add -z separate-code to sframe x86_64 tests
Those tests were generated by a linker having "-z separate-code" on by
default. However, being controlled by a configure option, it can be off
by default. Forcing the option as part of the tests ensures clean
results in both cases.
2025-02-26 09:02:18 +01:00
Tom de Vries
6c6080171f [gdb/build] Fix unused var in dwarf2/read.c
On x86_64-linux, with gcc 7.5.0 I ran into a build breaker:
...
gdb/dwarf2/read.c: In function ‘void read_comp_units_from_section()’:
gdb/dwarf2/read.c:4297:31: error: unused variable ‘sig_type_it’ \
  [-Werror=unused-variable]
    auto [sig_type_it, inserted] = sig_types.emplace (sig_ptr);
                               ^
...

Fix this by dropping the unused variable.

Tested on x86_64-linux, by completing a build.
2025-02-26 07:46:40 +01:00
Simon Marchi
2f0521c0d6 gdb/dwarf: fix signature_type created with nullptr section
Commit c44ab627b0 ("gdb/dwarf: pass section to dwarf2_per_cu_data
constructor") introduced a regression when using dwp.  It can be
reproduced with:

    $ make check TESTS="gdb.base/ptype-offsets.exp" RUNTESTFLAGS="--target_board=fission-dwp"

Then, to investigate:

    $ ./gdb  -nx -q --data-directory=data-directory testsuite/outputs/gdb.base/ptype-offsets/ptype-offsets -ex 'ptype int'
    Reading symbols from testsuite/outputs/gdb.base/ptype-offsets/ptype-offsets...
    /home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:3195:38: runtime error: member call on null pointer of type 'struct dwarf2_section_info'

Commit c44ab627b0 removed the assignment of signatured_type::section
(dwarf2_per_cu_data::section, really) in
fill_in_sig_entry_from_dwo_entry with the justification that the section
was already set when constructing the signatured_type.  Well, that was
true except for one spot in lookup_dwp_signatured_type which passes a
nullptr section to add_type_unit.

Fix that by passing the section to add_type_unit in that one spot.  This
is the same section that would have been set by
fill_in_sig_entry_from_dwo_entry before.

Add some asserts in the dwarf2_per_cu_data constructor to verity that
the passed dwarf2_per_bfd and dwarf2_section_info are non-nullptr.

Change-Id: If27dae6b4727957c96defc058c7e4be31472005b
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32739
Co-Authored-By: Tom de Vries <tdevries@suse.de>
Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 22:43:49 -05:00
Simon Marchi
2b5a48b6a9 gdb/dwarf: convert dwarf2_per_bfd::signatured_types to a gdb::unordered_set
I'd like to add these asserts in dwarf2_per_cu_data's constructor:

    gdb_assert (per_bfd != nullptr);
    gdb_assert (section != nullptr);

However, these dummy instances of signatured_type, used as hash table
lookup keys, are in the way:

    signatured_type find_sig_entry (nullptr, nullptr, sect_offset {}, sig);

This motivated me to convert the dwarf2_per_bfd::signatured_types hash
table to a gdb::unordered_set.  This allows finding an entry by simply
passing the signature (an integer) and removes the need to create dummy
signatured_type objects.

There is one small unfortunate pessimization:
lookup_dwo_signatured_type, for instance, does a lookup by signature to
find an existing signatured_type.  If not found, it adds a new one by
calling add_type_unit.  The current code passes down the slot where to
put the new element, avoiding an extra hash when inserting the new
signatured_type.  With the new code, I don't see a way to do that.  This
is probably negligible, but it bugs me.  If we used a map of signature
-> signatured_type, I would see a way, but then it would waste space.

I see one change in behavior, that is not really important IMO.  In
read_comp_units_from_section, if duplicate signature type entries are
detected, the code prior to this patch overwrites the existing
signatured_type in the hash table with the new one.  With this patch,
the existing signatured_type is kept: the call to emplace does not
insert the value if an existing equal value exists.

Other than that, no behavior change expected.

Change-Id: I0bef1b49cc63dbdf4e32fa9d4ea37f83025efc3e
Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 22:43:49 -05:00
Simon Marchi
fb3511fc47 gdb/dwarf: change some per-objfile functions to be per-bfd
I identified the following functions that currently take a
dwarf2_per_objfile, but could take a less specific dwarf2_per_bfd.

 - try_open_dwop_file
 - open_dwo_file
 - open_dwp_file

The uses of the per-objfile object in try_open_dwop_file can be replaced
with equivalent per-bfd ones.

Change-Id: Ia31fa0b988375e86a715ee863d4ec3c572ce89c0
Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 22:35:24 -05:00
Simon Marchi
643a92ff41 gdb/dwarf: use dwz_file::filename in a few spots
I found a few spots where the existing dwz_file::filename method could
be used.

Change-Id: I0522b1e3abbfac2f392f9ec777c37b242ee236d8
Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 22:34:33 -05:00
Simon Marchi
00aa53dabc gdb: move "gdb:function_view" into quick-symbol.h typedefs
All users of these typedefs use them inside a gdb::function_view.  Move
the gdb::function_view in the typedefs themselves.  This shortens the
types in function signatures and helps with readability, IMO.

Rename them to remove the `_ftype` suffix: this suffix is not as
relevant in C++ as it was in C.  With function_view, the caller can pass
more than just a simple "function".  Anyway, I think it's clearer to
name them after the role the callback has (listener, matcher, etc).

Adjust some related comments.

Change-Id: Iaf9f8ede68b51ea9e4d954792e8eb90def8659a6
Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 22:22:52 -05:00
Simon Marchi
f563d6cc74 gdb/dwarf: initialize tu_stats fields
Initialize fields of tu_stats to 0, remove the explicit default
initialization of dwarf2_per_bfd::tu_stats.

Change-Id: I98b2d5c4171291a3df2569466559174fb7cf32b6
Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 22:20:43 -05:00
GDB Administrator
0ec9aa4ac3 Automatic date update in version.in 2025-02-26 00:00:12 +00:00
Tom Tromey
f1e96c08e7 Remove struct print_one_inferior_data
struct print_one_inferior_data is not used, so remove it.
2025-02-25 14:57:12 -07:00
Simon Marchi
60b9de2ec0 gdb/dwarf: remove unused include in read.c
This include is reported as unused by clangd.

Change-Id: I95b73f85607537551ef54e46551197d1371d621b
2025-02-25 15:23:13 -05:00
Simon Marchi
b9935b23e4 gdb/amd-dbgapi: add displaced stepping support
Implement the target_ops displaced stepping methods to add displaced
stepping support when debugging AMD GPU programs.  The knowledge of how
to prepare and finish displaced steps is provided by the amd-dbgapi
library, so the code here is relatively straightforward.  No need to
parse instructions or handle fixups, that is done by the lib  We just
need to remember, for each thread doing a displaced step, the displaced
stepping id given by the library.

Add a test to exercise the new functionality.  The compiler generates
DWARF that GDB doesn't understand yet [1], so trying to step over a
breakpoint with DWARF present gives:

    (gdb) si
    Unhandled dwarf expression opcode 0xe9

The test purposefully builds the binary without DWARF info to circumvent
this.

[1] https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html

Change-Id: I53f459221a42d4b02a6041eadb8cf554500e2162
Approved-By: Lancelot Six <lancelot.six@amd.com> (amdgpu)
2025-02-25 11:45:43 -05:00
Simon Marchi
7f7e6755c5 gdb: add target displaced stepping support
The amd-dbgapi library, used in the AMD GPU port, has the capability to
prepare and cleanup displaced step operations.  In order to use it, add
the following target_ops methods:

 - supports_displaced_step
 - displaced_step_prepare
 - displaced_step_finish
 - displaced_step_restore_all_in_ptid

Prior to this patch, displaced stepping preparation and cleanup is done
solely by gdbarches.  Update infrun to use these new target methods
instead of gdbarch hooks.  To keep the behavior for other architectures
unchanged, make the default implementations of the new target_ops method
forward to the thread's gdbarch.

displaced_step_restore_all_in_ptid won't be needed for the AMD GPU port,
but was added for completeness.  It would be weird for infrun displaced
stepping code to call target methods except for that one thing where it
calls a gdbarch method.

Since this patch only adds infrastructure, no behavior change is
expected.

Change-Id: I07c68dddb5759a55cd137a711d2679eedc0d9285
2025-02-25 11:35:16 -05:00
Simon Marchi
6997fbcd06 gdb/amd-dbgapi: use gdb::unordered_map
Since we have gdb::unordered_map, swap std::unordered_map for that.

Change-Id: If2ef652fe18c1a440a25cff6131d29e37091bdbe
Approved-By: Lancelot Six <lancelot.six@amd.com> (amdgpu)
2025-02-25 11:35:12 -05:00
Ciaran Woodward
f2cc668e2b Fix mkdir_recursive on windows when CWD is root
On windows, when creating a directory with an absolute path,
mkdir_recursive would start by trying to make 'C:'.

On windows, this has a special meaning, which is "the current
directory on the C drive". So the first thing it tries to do
is create the current directory.

Most of the time, this fails with EEXIST, so the function
continues as expected. However if the current directory is
C:/, trying to create that causes EPERM, which causes the
function to prematurely terminate.

(The same applies for any drive letter.)

This patch resolves this issue, by skipping the drive letter
so that it is never sent to the mkdir call.

Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 14:58:15 +00:00
Jens Remus
6693696a7d x86: SFrame FDE for PLT0 does not use repetition block size
The SFrame FDE for the PLT0 entry is of type PCINC, which does does not
make use of the type PCMASK repetition block size.  Therefore generate
the FDE with a repetition block size of zero.

bfd/
	* elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Use FDE
	repetition block size of zero for PLT0.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
2025-02-25 13:29:02 +01:00
Ciaran Woodward
bd217f6d05 gdb/remote: Set the thread of the remote before sending qRcmd.
GDB allows remotes to implement extension commands which can
be accessed using the 'monitor' command.

This allows remotes to implement functionality which does not
exist in GDB for whatever reason (doesn't make sense, too
specific to one target, etc.)

However, before this change, the remote would not necessarily know
which thread/inferior was currently selected on the GDB client.
This prevents the implementation of any 'monitor' commands which are
specific to a single inferior/thread on the remote.

This is because GDB informs the remote of the current thread
lazily - only when it is relevant to the RSP command next being
sent.

qRcmd is the underlying RSP command used for monitor commands, so
this change ensures that GDB will update the remote with the
'current' thread if it has changed since the remote was last
informed.

Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 11:27:18 +00:00
Andrew Burgess
a6bc00ff35 gdb/windows: remove disable_breakpoints_in_shlibs call
I noticed that the disable_breakpoints_in_shlibs function disables
breakpoints without calling notify_breakpoint_modified.  This commit
is one step towards fixing this issue.

There are currently only two uses of disable_breakpoints_in_shlibs,
one in clear_solib (in solib.c), and the other in
windows_nat_target::do_initial_windows_stuff (in windows-nat.c).

I believe that the call in windows-nat.c can be shown to be redundant,
and therefore can be removed.

windows_nat_target::do_initial_windows_stuff is called from two
places: windows_nat_target::attach and
windows_nat_target::create_inferior, these are the target_ops
functions used to attach to a running process, or for creating a new
process, and are only called from attach_command or run_command_1,
both in infcmd.c.

Both attach_command and run_command_1 call target_pre_inferior before
calling the relevant target_ops function.

In target_pre_inferior, so long as the target doesn't have a global
solist (and windows doesn't), we always call no_shared_libraries (from
solib.c), which calls clear_solib (also in solib.c), which in turn
calls disable_breakpoints_in_shlibs.

My claim then, is that, any time we reach the
disable_breakpoints_in_shlibs call in
windows_nat_target::do_initial_windows_stuff, we will have always have
called disable_breakpoints_in_shlibs already via clear_solib.

I think it should be safe to remove the disable_breakpoints_in_shlibs
call from windows_nat_target::do_initial_windows_stuff.  There should
be no user visible changes.

My ultimate goal, which I'll address in follow on commits, is to
delete disable_breakpoints_in_shlibs completely.  Removing this call
means that we only have one disable_breakpoints_in_shlibs call
remaining in GDB.

Testing for this change has been minimal.  My only Windows build
machine is not great, and I've never managed to get DejaGNU running in
that environment.  This commit builds, and a few basic, manual tests
seem fine, but beyond that, this change is untested.

Approved-By: Tom Tromey <tom@tromey.com>
2025-02-25 11:01:35 +00:00
Tom de Vries
1e9bd86ccd gdb: don't show incorrect source file in source window
Consider the test-case sources main.c and foo.c:

  $ cat main.c
  extern int foo (void);

  int
  main (void)
  {
    return foo ();
  }
  $ cat foo.c
  extern int foo (void);

  int
  foo (void)
  {
    return 0;
  }

and main.c compiled with debug info, and foo.c without:

  $ gcc -g main.c -c
  $ gcc foo.c -c
  $ gcc -g main.o foo.o

In TUI mode, if we run to foo:

  $ gdb -q a.out -tui -ex "b foo" -ex run

it gets us "[ No Source Available ]":

  ┌─main.c─────────────────────────────────────────┐
  │                                                │
  │                                                │
  │                                                │
  │            [ No Source Available ]             │
  │                                                │
  │                                                │
  └────────────────────────────────────────────────┘
  (src) In: foo                  L??   PC: 0x400566
  ...
  Breakpoint 1, 0x0000000000400566 in foo ()
  (gdb)

But after resizing (pressing ctrl-<minus> in the gnome-terminal), we
get instead the source for main.c:

  ┌─main.c─────────────────────────────────────────┐
  │        3 int                                   │
  │        4 main (void)                           │
  │        5 {                                     │
  │        6   return foo ();                      │
  │        7 }                                     │
  │                                                │
  │                                                │
  └────────────────────────────────────────────────┘
  (src) In: foo                   L??   PC: 0x400566
  ...
  Breakpoint 1, 0x0000000000400566 in foo ()
  (gdb)

which is inappropriate because we're stopped in function foo, which is
not in main.c.

The problem is that, when the window is resized, GDB ends up calling
tui_source_window_base::rerender.  The rerender function has three
cases, one for when the window already has some source code
content (which is not the case here), a case for when the inferior is
active, and we have a selected frame (which is the case that applies
here), and a final case for when the inferior is not running.

For the case which we end up in, the source code window has no
content, but the inferior is running, so we have a selected frame, GDB
calls the get_current_source_symtab_and_line() function to get the
symtab_and_line for the current location.

The get_current_source_symtab_and_line() will actually return the last
recorded symtab and line location, not the current symtab and line
location.

What this means, is that, if the current location has no debug
information, get_current_source_symtab_and_line() will return any
previously recorded location, or failing that, the default (main)
location.

This behaviour of get_current_source_symtab_and_line() also causes
problems for the 'list' command.  Consider this pure CLI session:

  (gdb) break foo
  Breakpoint 1 at 0x40110a
  (gdb) run
  Starting program: /tmp/a.out

  Breakpoint 1, 0x000000000040110a in foo ()
  (gdb) list
  1	extern int foo (void);
  2
  3	int
  4	main (void)
  5	{
  6	  return foo ();
  7	}
  (gdb) list .
  Insufficient debug info for showing source lines at current PC (0x40110a).
  (gdb)

However, if we look at how GDB's TUI updates the source window during
a normal stop, we see that GDB does a better job of displaying the
expected contents.  Going back to our original example, when we start
GDB with:

  $ gdb -q a.out -tui -ex "b foo" -ex run

we do get the "[ No Source Available ]" message as expected.  Why is
that?

The answer is that, in this case GDB uses tui_show_frame_info to
update the source window, tui_show_frame_info is called each time a
prompt is displayed, like this:

  #0  tui_show_frame_info (fi=...) at ../../src/gdb/tui/tui-status.c:269
  #1  0x0000000000f55975 in tui_refresh_frame_and_register_information () at ../../src/gdb/tui/tui-hooks.c:118
  #2  0x0000000000f55ae8 in tui_before_prompt (current_gdb_prompt=0x31ef930 <top_prompt+16> "(gdb) ") at ../../src/gdb/tui/tui-hooks.c:165
  #3  0x000000000090ea45 in std::_Function_handler<void(char const*), void (*)(char const*)>::_M_invoke (__functor=..., __args#0=@0x7ffc955106b0: 0x31ef930 <top_prompt+16> "(gdb) ") at /usr/include/c++/9/bits/std_function.h:300
  #4  0x00000000009020df in std::function<void(char const*)>::operator() (this=0x5281260, __args#0=0x31ef930 <top_prompt+16> "(gdb) ") at /usr/include/c++/9/bits/std_function.h:688
  #5  0x0000000000901c35 in gdb::observers::observable<char const*>::notify (this=0x31dda00 <gdb::observers::before_prompt>, args#0=0x31ef930 <top_prompt+16> "(gdb) ") at ../../src/gdb/../gdbsupport/observable.h:166
  #6  0x00000000008ffed8 in notify_before_prompt (prompt=0x31ef930 <top_prompt+16> "(gdb) ") at ../../src/gdb/event-top.c:518
  #7  0x00000000008fff08 in top_level_prompt () at ../../src/gdb/event-top.c:534
  #8  0x00000000008ffdeb in display_gdb_prompt (new_prompt=0x0) at ../../src/gdb/event-top.c:487

If we look at how tui_show_frame_info figures out what source to
display, it doesn't use get_current_source_symtab_and_line(), instead,
it finds a symtab_and_line directly from a frame_info_pt.  This means
we are not dependent on get_current_source_symtab_and_line() returning
the current location (which it does not).

I propose that we change tui_source_window_base::rerender() so that,
for the case we are discussing here (the inferior has a selected
frame, but the source window has no contents), we move away from using
get_current_source_symtab_and_line(), and instead use find_frame_sal
instead, like tui_show_frame_info does.

This means that we will always use the inferior's current location.

Tested on x86_64-linux.

Reviewed-By: Tom de Vries <tdevries@suse.de>
Reported-By: Andrew Burgess <aburgess@redhat.com>
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32614
2025-02-25 10:56:36 +00:00
Tom de Vries
f40b59b912 [libctf] Fix warning: @xref should not appear on @multitable line
When building gdb, I run into:
...
ctf-spec.texi:809: warning: @xref should not appear on @multitable line
...

The line in question is:
...
@multitable {Kind} {@code{CTF_K_VOLATILE}} {Indicates a type that cannot be represented in CTF, or that} {@xref{Pointers typedefs and cvr-quals}}
...
which defines a prototype row with 4 columns.

However, the table only has 3 colums:
...
@headitem Kind @tab Macro @tab Purpose
...

Fix the warning by removing the item in the prototype row representing a fourth column.

Tested on aarch64-linux.

PR libctf/32044
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32044
2025-02-25 08:29:19 +01:00