Nick Alcock [Thu, 24 Apr 2025 13:20:28 +0000 (14:20 +0100)]
libctf, include: debuggability improvements
When --enable-libctf-hash-debugging is on, make ctf_set_errno and
ctf_set_typed_errno into real functions, not inlines, so you can
drop breakpoints on them. Since we are breaking API, also move
ECTF_NEXT_END to the start of the _CTF_ERRORS array, so you can
check for real (non-ECTF_NEXT_END) errors in breakpooints on those
functions by checking for err > 1000.
Nick Alcock [Thu, 24 Apr 2025 13:17:19 +0000 (14:17 +0100)]
libctf: ctf-lookup: support prefixes in ctf_lookup_by_id
ctf_lookup_by_id now has a new optional suffix argument, which,
if set, returns the suffix of a prefixed type: the ctf_type_t it
returns remains (as ever) the first one in the type (i.e. it
may be a prefix type). This is most convenient because the prefix
is the ctf_type_t that LCTF_KIND and other LCTF functions taking
ctf_type_t's expect.
Nick Alcock [Thu, 3 Apr 2025 14:21:47 +0000 (15:21 +0100)]
libctf: simplify ctf_txlate
Before now, this critical internal structure was an array mapping from a
type ID to the type index of the type with that ID. This was critical for
the old world in which ctf_update() reserialized the entire dict, so things
moved around in memory all the time: but these days, a ctf_type_t * never
moves after creation, so we can just make ctf_txlate an array of ctf_type_t *
and be done with it.
This lets us point type indexes anywhere in memory, not just to entries
in the ctf_buf, which means we can have synthetic ones for various purposes.
And we will.
Nick Alcock [Thu, 24 Apr 2025 12:50:38 +0000 (13:50 +0100)]
libctf: adapt core dictops for v4 and prefix types
The heart of libctf's reading code is the ctf_dictops_t and the functions it
provides for reading various things no matter what the CTF version in use:
these are called via LCTF_*() macros that translate into calls into the
dictops.
The introduction of prefix types in v4 requires changes here: in particular,
we want the ability to get the type kind of whatever ctf_type_t we are
looking at (the 'unprefixed' kind), as well as the ability to get the type
kind taking prefixes into account: and more generally we want the ability
to both look at a given prefix and look at the type as a whole. So several
ctf_dictops_t entries are added for this (ctfo_get_prefixed_kind,
ctfo_get_prefixed_vlen).
This means API changes (no callers yet adjusted, it'll happen as we go),
because the existing macros were mostly called with e.g. a ctt_info value
and returned a type kind, while now we need to be called with the actual
ctf_type_t itself, so we can possibly walk beyond it to find the real type
record. ctfo_get_vbytes needs adjusting for this.
We also add names to most of the ctf_type_t parameters, because suddenly we
can have up to three of them: one relating to the first entry in the type
record (which may be a prefix, usually called 'prefix'), one relating to the
true type record (which may be a suffix, so usually called 'suffix'), and
one possibly relating to some intermediate record if we have multiple
prefixes (usually called 'tp').
There is one horrible special case in here: the vlen of the new
CTF_K_FUNC_LINKAGE kind (equivalent to BTF_KIND_FUNC) is always zero: it
reuses the vlen field to encode the linkage (!). BTF is rife with ugly
hacks like this.
Nick Alcock [Thu, 24 Apr 2025 12:46:08 +0000 (13:46 +0100)]
libctf: don't warn about unused fp in ctf_assert
When hash debugging is enabled and NDEBUG is not set, ctf_assert()
translates into a true assert(). Don't leave the fp parameter
unused in this case (which can cause compiler errors when -Werror
is also on).
Nick Alcock [Thu, 24 Apr 2025 12:44:36 +0000 (13:44 +0100)]
libctf: split out compatibility code
The compatibility-opening code is quite voluminous, and is stuck right in
the middle of ctf-open.c, rather interfering with maintenance. Split it
out into a new ctf-open-compat.c. (Since it is not yet upgraded to support
v4, the new file is not added to the build system yet: indeed, even the
calls to it haven't been diked out at this stage.)
Nick Alcock [Thu, 24 Apr 2025 12:32:57 +0000 (13:32 +0100)]
include, libctf, binutils: drop labels
These have never been implemented properly and don't work with the linker or
deduplicator: BTF has nothing like them, so the default assumption should be
that we drop them. If we need something like them in future, we can add
them back (which we do not expect).
Quite a bit of label detritus is left in libctf after this: it's tied up
with later changes so will be removed as part of later commits. (Because
the entire thing is disabled, the non-compilability of this intermediate
state is not a concern.)
Nick Alcock [Thu, 24 Apr 2025 12:20:53 +0000 (13:20 +0100)]
include, libctf: header and soname changes for CTFv4
These changes bump the current file format version to CTF_VERSION_4, and
introduce a new VERSION_5 identical with it to get the version integer and
the name identical again. A great many changes are made to account for
the changes to handle CTFv4 (which is a BTF superset).
libctf will not compile after these changes, which is why it's been diked
out of the build system and forced-off until the series is complete.
Because all the CTF_K constants have changed values, this is necessarily an
ABI break: add a #define to make picking up this break at compile time
obvious.
Note that the ABI has broken by bumping the soname (deriving it now from
libctf/libtool-version) and folding all newer symbols in the symbol version
file into a new LIBCTF_2.0 version, which is now the only exported version.
Nick Alcock [Wed, 5 Mar 2025 19:01:12 +0000 (19:01 +0000)]
libctf: don't include cv-quals or pointers in the name table
Even if these types have a name recorded against them, we should
ignore it. They don't have names, full stop.
libctf/ChangeLog:
* ctf-open.c (init_static_types): Drop nameless types when sizing
the name table.
(init_static_types_names_internal): Never pass in their name.
Nick Alcock [Thu, 27 Feb 2025 19:27:00 +0000 (19:27 +0000)]
types: add some more error checking
A few places with inadequate error checking have fallen out of the
ctf_id_t work:
- ctf_add_slice doesn't make sure that the type it is slicing
actually exists
- ctf_add_member_offset doesn't check that the type of the member
exists (though it will often fail if it doesn't, it doesn't
explicitly check, so if you're unlucky it can sometimes succeed,
giving you a corrupted dict)
- ctf_type_encoding doesn't check whether its slied type exists:
it should verify it so it can return a decent error, rather than
a thoroughly misleading one
- ctf_type_compat has the same problem with respect to both of its
arguments. It would definitely be nicer if we could call
ctf_type_compat and just get a boolean answer, but it's not
clear to me whether a type can be said to be compatible *or*
incompatible with a nonexistent one, and we should probably alert
the users to a likely bug regardless. C error checking, sigh...
Nick Alcock [Sun, 16 Feb 2025 19:55:11 +0000 (19:55 +0000)]
libctf: consecutive ctf_id_t assignment
This change modifies type ID assignment in CTF so that it works like BTF:
rather than flipping the high bit on for types in child dicts, types ascend
directly from IDs in the parent to IDs in the child, without interruption
(so type 0x4 in the parent is immediately followed by 0x5 in all children).
Doing this while retaining useful semantics for modification of parents is
challenging. By definition, child type IDs are not known until the parent
is written out, but we don't want to find ourselves constrained to adding
types to the parent in one go, followed by all child types: that would make
the deduplicator a nightmare and would frankly make the entire ctf_add*()
interface next to useless: all existing clients that add types at all
add types to both parents and children without regard for ordering, and
breaking that would probably necessitate redesigning all of them.
So we have to be a litle cleverer.
We approach this the same way as we approach strings in the recent refs
rework: if a parent has children attached (or has ever had them attached
since it was created or last read in), any new types created in the parent
are assigned provisional IDs starting at the very top of the type space and
working down. (Their indexes in the internal libctf arrays remain
unchanged, so we don't suddenly need multigigabyte indexes!). At writeout
(preserialization) time, we traverse the type table (and all other table
containing type IDs) and assign refs to every type ID in exactly the same
way we assign refs to every string offset (just a different set of refs --
we don't want to update type IDs with string offset values!).
For a parent dict with children, these refs are real entities in memory:
pointers to the memory locations where type IDs are stored, tracked in the
DTD of each type. As we traverse the type table, we assign real IDs to each
type (by simple incrementation), storing those IDs in a new dtd_final_type
field in the DTD for each type. Once the type table and all other tables
containing type IDs are fully traversed, we update all the refs and
overwrite the IDs currently residing in each with the final IDs for each
type.
That fixes up IDs in the parent dict itself (including forward references in
structs and the like: that's why the ref updates only happen at the end);
but what about child dicts' references, both to parent types and to their
own? We add armouring to enforce that parent dicts are always serialized
before their children (which ctf-link.c already does, because it's a
precondition for strtab deduplication), and then arrange that when a ref is
added to a type whose ID has been assigned (has a dtd_final_type), we just
immediately do an update rather than storing a ref for later updating.
Since the parent is already serialized, all parent type IDs have a
dtd_final_type by this point, and all parent IDs in the children are
properly updated. The child types can now be renumbered now we now the
number of types in the parent, and their refs updated identically to what
was just done with the parent.
One wrinkle: before the child refs are updated, while we are working over
the child's type section, the type IDs in the child start from 1 (or
something like that), which might seem to overlap the parent IDs. But this
is not the case: when you serialize the parent, the IDs written out to disk
are changed, but the only change to the representation in memory is that we
remember a dtd_final_type for each type (and use it to update all the child
type refs): its ID in memory is the same as it always was, a nonoverlapping
provisional ID higher than any other valid ID. We enforce all of this by
asserting that when you add a ref to a type, the memory location that is
modified must be in the buffer being serialized: the code will not let you
accidentally modify the actual DTDs in memory.
We track the number of types in the parent in a new CTFv4 (not BTF) header
field (the dumper is updated): we will also use this to open CTFv3 child
dicts without change by simply declaring for them that the parent dict has
2^31 types in it (or 2^15, for v2 and below): the IDs in the children then
naturally come out right with no other changes needed. (Right now, opening
CTFv3 child dicts requires extra compatibility code that has not been
written, but that code will no longer need to worry about type ID
differences.)
Various things are newly forbidden:
- you cannot ctf_import() a child into a parent if you already ctf_add()ed
types to the child, because all its IDs would change (and since you
already cannot ctf_add() types to a child that hasn't had its parent
imported, this in practice means only that ctf_create() must be followed
immediately by a ctf_import() if this is a new child, which all sane
clients were doing anyway).
- You cannot import a child into a parent which has the wrong number of
(non-provisional) types, again because all its IDs would be wrong:
because parents only add types in the provisional space if children are
attached to it, this would break the not unknown case of opening an
archive, adding types to the parent, and only then importing children
into it, so we add a special case: archive members which are not children
in an archive with more than one member always pretend to have at least
one child, so type additions in them are always provisional even before
you ctf_import anything. In practice, this does exactly what we want,
since all archives so far are created by the linker and have one parent
and N children of that parent.
Because this introduces huge gaps between index and type ID for provisional
types, some extra assertions are added to ensure that the internal
ctf_type_to_index() is only ever called on types in the current dict (never
a parent dict): before now, this was just taken on trust, and it was often
wrong (which at best led to wrong results, as wrong array indexes were used,
and at worst to a buffer overflow). When hash debugging is on (suggesting
that the user doesn't mind expensive checks), every ctf_type_to_index()
triggers a ctf_index_to_type() to make sure that the operations are proper
inverses.
Lots and lots of tests are added to verify that assignment works and that
updating of every type kind works fine -- existing tests suffice for
type IDs in the variable and symtypetab sections.
The ld-ctf tests get a bunch of largely display-based updates: various
tests refer to 0x8... type IDs, which no longer exist, and because the
IDs are shorter all the spacing and alignment has changed.
Nick Alcock [Sun, 16 Feb 2025 19:53:40 +0000 (19:53 +0000)]
libctf: fix ctf_type_pointer on parent dicts, etc
Before now, ctf_type_pointer was crippled: it returned some type (if any)
that was a pointer to the type passed in, but only if both types were in the
current dict: if either (or both) was in the parent dict, it said there was
no pointer though there was. This breaks real users: it's past time to lift
the restriction.
Nick Alcock [Sun, 16 Feb 2025 19:41:08 +0000 (19:41 +0000)]
libctf: don't call ctf_type_to_index with types in other dicts
ctf_type_to_index has never given meaningful results when called with dicts
in which the specified type does not reside: its only purpose is to return
the offset in various dict-internal arrays in which this type is located, so
doing so makes no sense.
Stop ctf_lookup_by_name and refresh_pptrtab (which it calls) from doing so.
As part of this, refactor ctf_lookup_by_name so that it's a bit less
repetitive and squirrelly.
Nick Alcock [Sun, 16 Feb 2025 19:39:41 +0000 (19:39 +0000)]
libctf: move string deduplication into ctf-archive
This means that any archive containing dicts can get its strings dedupped
together, rather than only those that are ctf_linked.
(For now, we are still constrained to ctf_linked archives, since fixing that
requires further changes to ctf_dedup_strings: but this gives us the first
half of what is necessary.)
libctf/
* ctf-link.c (ctf_link_write): Move string dedup into...
* ctf-archive.c (ctf_arc_preserialize): ... this new function.
(ctf_arc_write_fd): Call it.
Nick Alcock [Tue, 11 Feb 2025 15:33:51 +0000 (15:33 +0000)]
ld, testsuite, ctf: really test -gctf even if the compiler warns
Commit a12c988767e5bd6b6a15dd6ca5e3b277f5627c64 endeavoured to
improve the CTF-availability test by having it try to create
CTF even if the compiler appears not to be working, checking
for the presence of likely-valid generated assembler instead.
Unfortunately this commit didn't remove the actual call to
check_compiler_available, so it didn't really improve anything.
Remove that call to induce proper testing on platforms in which
the compiler emits warnings.
ld/
* testsuite/lib/ld-lib.exp (check_ctf_available): Don't
require a working compiler before testing.
Nick Alcock [Fri, 7 Feb 2025 17:06:36 +0000 (17:06 +0000)]
libctf: string: refs rework
This commit moves provisional (not-yet-serialized) string refs towards the
scheme to be used for CTF IDs in the future. In particular
- provisional string offsets now count downwards from just under the
external string offset space (all bits on but the high bit). This makes
it possible to detect an overflowing strtab, and also makes it trivial to
determine whether any string offset (ref) updates were missed -- where
before we might get a slightly corrupted or incorrect string, we now get
a huge high strtab offset corresponding to no string, and an error is
emitted at read time.
- refs are emitted at serialization time during the pass through the types.
They are strictly associated with the newly-written-out buffer: the
existing opened CTF dict is not changed, though it does still get the new
strtab so that new refs to the same string can just refer directly to it.
The provisional strtab hash table that contains these strings is not
deleted after serialization (because we might serialize again): instead,
we keep track in the parent of the lowest-yet-used ("latest") provisional
strtab offset, and any strtab offset above that, but not external
(high-bit-on) is considered provisional.
This is sort-of-enforced by moving most of the ref-addition function
declarations (including ctf_str_add_ref) to a new ctf-ref.h, which is
not included by ctf-create.c or ctf-open.c.
- because we don't add refs when adding types, we don't need to handle the
case where we add things to expanding vlens (enums, struct members) and
have to realloc() them. So the entire painful movable refs system can
just be deleted, along with the ability to remove refs piecemeal at all
(purging all of them is still possible). Strings added during type
addition are added via ctf_str_add(), which adds no refs: the strings are
picked up at serialization time and refs to their final, serialized
resting place added. The DTDs never have any refs in them, and their
provisional strtab offsets are never updated by the ref system.
This caused several bugs to fall out of the earlier work and get fixed.
In particular, attempts to look up a string in a child dict now search
the parent's provisional strtab too: we add some extra special casing
for the null string so we don't need to worry about deduplication
moving it somewhere other than offset zero.
Finally, the optimization that removes an unreferenced synthetic external
strtab (the record of the strings the linker has told us about, kept around
internally for lookup during late serialization) is faulty: references to a
strtab entry will only produce CTF-level refs if their value might change,
and an external string's offset won't change, so it produces no refs: worse
yet, even if we did get a ref (say, if the string was originally believed
to be internal and only later were we told that the linker knew about it
too), when we serialize a strtab, all its refs are dropped (since they've
been updated and can no longer change); so if we serialized it a second
time, its synthetic external strtab would be considered empty and dropped,
even though the same external strings as before still exist, referencing
it. We must keep the synthetic external strtab around as long as external
strings exist that reference it, i.e. for the life of the dict.
One benefit of all this: now we're emitting provisional string offsets at
a really high value, it's out of the way of the consecutive, deduplicated
string offsets in child dicts. So we can drop the constraint that you
cannot add strings to a dict with children, which allows us to add types
freely to parent dicts again. What you can't do is write that dict out
again: when we serialize, we currently update the dict being serialized
with the updated strtabs: when you write a dict out, its provisional
strings become real strings, and suddenly the offsets would overlap once
more. But opening a dict and its children, adding to it, and then
writing it out again is rare indeed, and we have a workaround: anyone
wanting to do this can just use ctf_link instead.
Nick Alcock [Thu, 6 Feb 2025 13:02:50 +0000 (13:02 +0000)]
libctf: create: fix vlen / vbytes confusion
The initial_vlen parameter to ctf_add_generic is misnamed: it's not the
initial vlen (the initial number of members of a struct, etc), but rather
the initial size of the vlen region. We have a term for that, vbytes: use
it.
Amazingly this doesn't seem to have caused any bugs to creep in.
Making these functions is unnecessary right now, but will become much
clearer shortly.
While we're at it, we can drop the third child argument to
LCTF_INDEX_TO_TYPE: it's only used for nontrivial purposes that aren't
literally the same as getting the result from the fp in one place,
in ctf_lookup_by_name_internal, and that place is easily fixed by just
looking in the right dictionary in the first place.
Nick Alcock [Wed, 29 Jan 2025 12:35:47 +0000 (12:35 +0000)]
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.
Nick Alcock [Wed, 29 Jan 2025 12:30:58 +0000 (12:30 +0000)]
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).
Nick Alcock [Mon, 13 Jan 2025 15:04:17 +0000 (15:04 +0000)]
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).
Nick Alcock [Mon, 13 Jan 2025 14:49:14 +0000 (14:49 +0000)]
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.
Nick Alcock [Mon, 13 Jan 2025 12:04:40 +0000 (12:04 +0000)]
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.
Nick Alcock [Mon, 13 Jan 2025 11:34:56 +0000 (11:34 +0000)]
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.
Nick Alcock [Mon, 13 Jan 2025 11:31:56 +0000 (11:31 +0000)]
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.
Nick Alcock [Mon, 13 Jan 2025 11:29:26 +0000 (11:29 +0000)]
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.
Nick Alcock [Tue, 1 Oct 2024 14:34:12 +0000 (15:34 +0100)]
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.
Nick Alcock [Tue, 16 Jul 2024 12:01:36 +0000 (13:01 +0100)]
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.
Nick Alcock [Mon, 15 Jul 2024 22:29:02 +0000 (23:29 +0100)]
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.
Nick Alcock [Mon, 15 Jul 2024 22:21:20 +0000 (23:21 +0100)]
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.
Nick Alcock [Mon, 15 Jul 2024 21:08:10 +0000 (22:08 +0100)]
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!
Nick Alcock [Mon, 15 Jul 2024 20:56:15 +0000 (21:56 +0100)]
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.
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.
Nick Alcock [Mon, 15 Jul 2024 20:11:40 +0000 (21:11 +0100)]
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.
Nick Alcock [Mon, 15 Jul 2024 20:01:40 +0000 (21:01 +0100)]
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.
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.
Nick Alcock [Mon, 15 Jul 2024 19:43:51 +0000 (20:43 +0100)]
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.
Nick Alcock [Mon, 15 Jul 2024 19:33:24 +0000 (20:33 +0100)]
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.
Nick Alcock [Mon, 15 Jul 2024 19:21:36 +0000 (20:21 +0100)]
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).
Jens Remus [Thu, 30 Oct 2025 13:39:59 +0000 (14:39 +0100)]
s390: Do not generate incomplete opcode table
The s390 opcode table s390-opc.tbl is generated from s390-opc.txt
using the s390-mkopc utility using output redirection. If s390-mkopc
fails with a non-zero return code, e.g. due to a warning or error, an
incomplete opcode table may be generated in the build directory. A
subsequent invocation of make then assumes that incomplete opcode
table to be up to date. Depending on the s390-mkopc issue the build
may then proceed without any follow-on warnings or errors, causing
the preceding error or warning to go unnoticed.
Generate the s390 opcode table into an intermediate temporary file
s390-opc.tbl.tmp in the build directory and only move it to the final
target s390-opc.tbl if the generation was successful.
Tested by appending an unsupported inline comment "# TEST" to one of
the instructions defined in s390-opc.txt.
opcodes/
* Makefile.am (s390-opc.tab): Use an intermediate temporary file
to prevent updating of the target on error/warning.
* Makefile.in: Regenerated.
Alan Modra [Thu, 30 Oct 2025 05:56:57 +0000 (16:26 +1030)]
Sanity check elf_sym_hashes indexing
I'm a little surprised we haven't already had fuzzing reports of
indexing off the end of sym_hashes. The idea here is to preempt such
bugs. One wrinkle is that ppc64 can't leave a zero symtab_hdr when
setting up sym_hashes for the fake stub bfd.
* elf-bfd.h (struct elf_reloc_cookie): Add "num_sym".
(_bfd_elf_get_link_hash_entry): Update declaration.
* elf-eh-frame.c (find_merged_cie): Sanity check reloc symbol
index.
* elf64-ppc.c (use_global_in_relocs): Fake up symtab_hdr for
stub bfd.
* elflink.c (_bfd_elf_get_link_hash_entry): Add "num_sym"
param. Check symndx against it. Update all calls.
(set_symbol_value): Add "num_sym" param and update all calls.
(elf_link_input_bfd): Add "num_syms" var and use for above.
(init_reloc_cookie): Set "cookie->num_syms".
* elf64-x86-64.c (elf_x86_64_scan_relocs): Pass symtab number
of entries to _bfd_elf_get_link_hash_entry.
* elfxx-x86.c (_bfd_x86_elf_check_relocs): Likewise.
(_bfd_x86_elf_link_relax_section): Likewise.
Alan Modra [Thu, 30 Oct 2025 05:56:50 +0000 (16:26 +1030)]
Don't read and cache local syms for gc-sections
Most places just need the local sym section, so reading and sometimes
caching the symbols is excessive. A symbol shndx can be stored in 4
bytes, an elf symbol internal form requires 32 bytes. When caching
the local symbols we went slightly crazy trying to avoid memory usage,
resulting in the symbols being freed then immediately read again for
the testcase in the PR33530.
To avoid this problem, this patch caches the local symbol section
indices in the bfd rather than in the reloc cookie. They are not
initialised until there is a need for them, so unlike elf_sym_hashes
for global syms you cannot rely on them being present.
One place that does need local syms is adjust_eh_frame_local_symbols,
but that is called once via bfd_discard_info so there is no problem
simply reading them. The other place that needs local syms is
ppc64_elf_gc_mark_hook for the old ELFv1 ABI when handling .opd.
bfd_sym_from_r_symndx should be sufficient for function pointer
references to static functions, which is how this code is triggered.
PR 33530
* elf-bfd.h (struct elf_reloc_cookie): Delete "locsyms",
"sym_hashes", "bad_symtab". Make "locsymcount" and
"extsymoff" unsigned int.
(struct elf_obj_tdata): Add loc_shndx.
(elf_loc_shndx): Define.
(_bfd_get_local_sym_section): Declare.
* elf-eh-frame.c (find_merged_cie): Use
_bfd_get_local_sym_section for local syms.
(adjust_eh_frame_local_symbols): Read local syms if any match
.eh_frame section. Return them if changed.
(_bfd_elf_discard_section_eh_frame): Adjust.
* elf64-ppc.c (ppc64_elf_gc_mark_hook): Use
_bfd_get_local_sym_section. Use bfd_sym_from_r_symndx when
reading opd local symbol.
* elflink.c (_bfd_get_local_sym_section): New function.
(_bfd_elf_section_for_symbol): Use it.
(elf_link_add_object_symbols): Remove unnecessary cast on
bfd_zalloc return.
(init_reloc_cookie): Remove "info" and "keep_memory" params.
Adjust all callers. Don't stash elf_sym_hashes and
elf_bad_symtab to cookie. Don't read local syms to cookie.
(fini_reloc_cookie): Do nothing.
(_bfd_elf_gc_mark_hook): Use _bfd_get_local_sym_section.
(elf_gc_mark_debug_section): Likewise.
(bfd_elf_reloc_symbol_deleted_p): Likewise. Update cookie use.
Alan Modra [Thu, 30 Oct 2025 05:56:44 +0000 (16:26 +1030)]
_bfd_elf_get_link_hash_entry tidy
Replace the "Elf_Internal_Shdr *symtab_hdr" parameter with
"unsigned int ext_sym_start", making it a duplicate of the existing
get_link_hash_entry function.
Also remove unnecessary checks from get_ext_sym_hash_from_cookie and
find_merged_cie. The sym_hashes and symbol index checks in
get_ext_sym_hash_from_cookie are duplicates of those done in
_bfd_elf_get_link_hash_entry, and there is no need to check for a
global symbol before calling _bfd_elf_get_link_hash_entry. When
bad_symtab, local symbols will have a NULL sym_hashes entry. Removing
these unnecessary checks gets rid of some cookie->locsyms references.
PR 33530
* elf-bfd.h (_bfd_elf_get_link_hash_entry): Update declaration.
* elflink.c (_bfd_elf_get_link_hash_entry): Rename from
get_link_hash_entry, adjusting all calls and deleting original
function.
(get_ext_sym_hash_from_cookie): Make "symndx" unsigned int.
Remove unnecessary check on sym_hashes, symbol index and
symbol binding.
* elf-eh-frame.c (find_merged_cie): Remove similar unnecessary
checks.
* elf64-x86-64.c (elf_x86_64_scan_relocs): Adjust.
* elfxx-x86.c (_bfd_x86_elf_check_relocs): Adjust.
(_bfd_x86_elf_link_relax_section): Adjust.
Alan Modra [Thu, 30 Oct 2025 05:56:27 +0000 (16:26 +1030)]
Pass cookie and symndx to gc_mark_hook
Replace the "sym" param with "cookie" and "symndx". This is in
preparation for the next patch. Also remove "rel" param since this is
available via "cookie", and is always set from cookie->rel.
Alon Bar-Lev [Wed, 29 Oct 2025 10:54:40 +0000 (12:54 +0200)]
objcopy: add option to specify custom prefix for symbol of binary input
When using --input-target=binary, objcopy currently derives symbol names
from a mangled version of the input file name. This approach can lead to
unpredictable results, as the generated symbols depend on the file path and
working directory.
This patch introduces a new option:
--binary-symbol-prefix <prefix> Use <prefix> as the base symbol name for
the input file (default: derived from
file name)
It allows specifying an explicit symbol prefix, while preserving the existing
behavior as a fallback.
Andrew Burgess [Fri, 24 Oct 2025 21:14:56 +0000 (22:14 +0100)]
gdb/testsuite: fix git repository check in gdb.src/pre-commit.exp
In the recently added gdb.src/pre-commit.exp test, we check if the
source directory is a git repository like this:
if {![file isdirectory $repodir/.git]} {
unsupported "Not in a git repository"
return
}
I make extensive use of git worktrees for development. In a worktree
.git is a file containing the location of the actual .git directory,
it is not itself a directory. As such, the above check fails,
claiming my source tree is not a git repository, when in fact, it is.
Fix this by relaxing the check to 'file exists $repodir/.git', which
will cover the directory and file case.
Haochen Jiang [Fri, 24 Oct 2025 05:49:20 +0000 (13:49 +0800)]
x86: Disable AMX-TRANSPOSE by default
In Binutils, we choose to keep the AMX-TRANSPOSE support for
now in case there are vendors want to utilize the instructions
although the feature itself is de-published. AMX-TRANSPOSE will
not show up on any Intel/AMD hardware. Also in foreseeable future,
no hardware will support AMX-TRANSPOSE, we will disable it by
default.
The patch (the removal) was done on the wrong assumption that
it was only the APX-promoted forms which would be dropped
because the APX spec was updated ahead of ISE and there was no
info that AMX-TRANSPOSE would be de-published at that time.
Given the current situation, since we will choose to disable
AMX-TRANSPOSE but not to remove the support in Binutils, we will
also not remove the APX support.
Simon Marchi [Mon, 27 Oct 2025 19:41:51 +0000 (15:41 -0400)]
gdb/solib-rocm: avoid expensive gdbarch_from_bfd call in rocm_solib_relocate_section_addresses
Loading a library containing a lot (> 100k) sections proved very slow
with whenever the support for ROCm was built into gdb. The culprit is
the gdbarch_from_bfd call in rocm_solib_relocate_section_addresses:
if (!is_amdgpu_arch (gdbarch_from_bfd (so.abfd.get ())))
This function gets called for every section, and gdbarch_from_bfd is
somewhat slow. It turns out that we can skip the gdbarch_from_bfd call,
since all is_amdgpu_arch needs is the bfd_architecture value, which we
can directly extract from the `bfd *`, without going through the
gdbarch.
Add an overload of is_amdgpu_arch that takes a `bfd *`, and use it in
rocm_solib_relocate_section_addresses.
Update a call site in rocm_solib_bfd_open to use the new overload as
well. That call site is not as much in a hot path, but there is no
point in paying the extra cost of looking up the gdbarch there. I
removed the other assert that checked that gdbarch_from_bfd returned a
non-nullptr value. If that was the case, something would be very wrong
with ROCgdb, and the problem would manifest very soon after anyway.
Change-Id: I55e9e68af59903b1b9727ff57388f9469d0e0002 Approved-by: Lancelot Six <lancelot.six@amd.com> (AMDGPU)
Tom Tromey [Wed, 22 Oct 2025 14:04:12 +0000 (08:04 -0600)]
Emit language and encoding names from dwarf-to-dwarf-assembler
This changes dwarf-to-dwarf-assembler to emit DW_LANG_* and DW_ATE_*
names when decoding the appropriate attributes. This makes the output
a little more readable and a little closer to something we'd check in.
Tom Tromey [Wed, 22 Oct 2025 13:33:35 +0000 (07:33 -0600)]
Fix formatting of attributes in dwarf-to-dwarf-assembler output
This updates dwarf-to-dwarf-assembler.py to reflect the changes made
to how attributes are parsed; see commit c44edec047d (Make location
expressions be code in DWARF assembler).
gdb: assign a valid section in convert_address_location_to_sals
The convert_address_location_to_sals function builds a symtab_and_line
from an explicit pc. Unless overlay debugging is enabled, the sal does not
contain a valid section (as find_pc_overlay will simply return nullptr).
While it is usually not a problem (as the sal users often recompute the
proper section, when needed), it may lead to the proper gdbarch not
being assigned when setting a breakpoint.
In code_breakpoint::add_location, gdb attempts to retrieve the gdbarch
through get_sal_arch by checking for the section or the symtab. However,
neither are currently set by cinvert_address_location_to_sals if the
debug symbols cannot be found. We then fall back to the current
architecture, which may cause errors in heterogeneous programs
(in ROCm, a breakpoint was not being hit since GDB was setting an
x86 int3 instruction instead of the architecture-appropriate s_trap 1).
This is a rework of a patch that was approved, but never merged
upstream (https://inbox.sourceware.org/gdb-patches/20241108195257.485488-2-lancelot.six@amd.com/).
The original change proposed to set the objfile field in the sal, and
check this field in get_sal_arch() if neither the section, nor the
symtab is defined. This patch makes GDB compute the section from the pc
instead of checking from the objfile in get_sal_arch, in accordance with
the rule of trying to set the section when creating the sal implemented
in this patch series. The test cases from the original patch are
included in this new one.
This should have minimal impact on other parts of GDB as users of this
section field would either (1) recompute it the same way (2) not use it
at all. In the case of overlay debugging, then the preceding call to
find_pc_overlay would likely assign a section.
Co-Authored-By: Lancelot SIX <lancelot.six@amd.com> Approved-By: Tom Tromey <tom@tromey.com>
Change-Id: I23cef6ad5a66f696536c7c49c885a074bfea9b23
gdb: pass minsym section to find_function_start_sal, when possible
We may rely on a minimal symbol to place a breakpoint on a function,
for instance when debug infos are unavailable. The minsym_found
function attempts to convert that minsym to a sal using either
find_function_start_sal or filling a sal manually from the minimal
symbol. This patch implements the decision to make it the responsibility
of the sal creation site to properly fill out the section field when
that is possible.
The function address may be updated when dealing with ifuncs, which
means the section from the minsym may be completely different from the
actual function address's section. A preceding change (6f7ad238 : gdb:
ensure bp_location::section is set correct to avoid an assert) has
proposed recomputing the section by calling find_pc_overlay. However,
this ends up setting the section to NULL in most cases. While the
section is often recomputed later on, I think it might be more
appropriate to set it once and for all when creating the sal.
The parent commit ensures that find_function_start_sal will return a
symtab_and_line with a section if possible. minsym_found can pass the
section if it can be trusted later on - it is in fact necessary to
ensure we get the proper pc/section with overlays. When dealing with
an ifunc that was resolved, then the section has to be recomputed
since the ifunc implementation may be in another section, or objfile.
This is now done in find_sal_for_pc_sect.
This change restores the section argument in
find_function_start_sal that was removed in a previous commit (6b0581fc
: gdb/symtab: remove section parameter from find_function_start_sal),
as it avoids an unnecessary lookup later in find_sal_for_pc_sect. The
function now sends the minsym's section if it corresponds to the actual
function, and not an ifunc.
This commit fixes a failure on gdb.rocm/displaced-stepping.exp. A new
test case is also provided to check that a breakpoint on a kernel is hit
without debug infos.
Approved-By: Tom Tromey <tom@tromey.com>
Change-Id: I7a502dc4565911cec92618f34be3d4bcbf8560c5
gdb: make find_sal_for_pc_sect attempt to fill sal section
The find_sal_for_pc_section function inconsistently fills the section
field from its output symtab_and_line, depending on whether a symtab is
present or not. In the case that we cannot find a symtab for the pc and
section, the function would construct a sal with a pc but no section,
even though it could be either forwarded from the arguments, or
computed from the pc.
With the proposed changes, the function attempts to set the section in
all code paths and performs a section lookup when it is not provided as
an argument. This change is part of a patch series to fix
inconsistencies in symtab_and_line constructions, making it the
responsibility of the sal creator to fill out the section field (when
possible).
This section may be passed from a minsym in an unmapped overlay section.
Leaving the section field empty would mean in most cases losing some
important context (e.g. which overlay section this pc corresponds to).
Approved-By: Tom Tromey <tom@tromey.com>
Change-Id: I818a08c4f61803b6d2cadd32ec106fe416af4c66
gdb: lookup minsym using section in find_sal_for_pc_sect
The find_sal_for_pc_sect function attempts to find the line that is
closest to a pc+section in the available symbols. One of the first thing
the function does is search for a bound minimal symbol corresponding to
that pc. In its original version, the lookup is performed by
lookup_minimal_symbol_by_pc, discarding the section. This is misleading
and may cause issues with overlay debugging if a second minsym with the
same pc (but a different section) can be found -- although this is only
in theory after inspecting the code, as I have no way to test this on a
system supporting overlays.
This should have no observable effects for the end user. One slight
benefit is that we can avoid a section lookup inside
lookup_minimal_symbol_by_pc_section if the caller does provide a
section.
Since the section is already passed as an argument to the function, the
proposed change forwards this section to the minsym lookup section.
Approved-By: Tom Tromey <tom@tromey.com>
Change-Id: I86a16bf397ea7167d3e9c7db79b8d7901fad1a97
Simon Marchi [Mon, 27 Oct 2025 19:12:24 +0000 (15:12 -0400)]
gdb/dwarf: make some fields of dwarf2_per_cu private
The comments on these fields mention that they should be private, but we
can't. I think this comes from the time where dwarf2_per_cu was and had
to remain POD. I don't think it's relevant anymore, there are other
private fields anyway. Make them private.
Change-Id: I1915ea531f42d685f68ff547833816906f79cd58 Approved-By: Tom Tromey <tom@tromey.com>
Guinevere Larsen [Fri, 24 Oct 2025 11:43:46 +0000 (08:43 -0300)]
gdb/help: Update help message for target record-core
Before this commit, the help message for target record-core is the same
as the help message for target record-full, which is the following:
Log program while executing and replay execution from log.
For one, having the same message is unhelpful, since it doesn't tell
users what the difference between the two is. But, more importantly,
that message seems to also be incorrect, since attempting to execute the
inferior forward from a restored file past the end of history will crash
GDB, since there isn't an actual live inferior to run.
To fix this, the help text is updated to the following:
Load a saved execution log, allowing replay of the last instructions
This message doesn't imply that future execution is supported, while it
shows that replaying within recorded instructions *is* supported.
The dot prefix used for R_PARISC_EPLT relocations causes issues
for symbol version support as no version section is defined for
these symbols. This causes the linker to exit with an error.
This change modifies the handling of EPLT relocations to use
offsets relative to a __text_seg base symbol. This symbol is
defined in the same way as the HP linker (a section symbol for
the .dynamic section).
This mostly fixes the symbol versioning support. There are
still issues caused by the munging of the value and section
of dynamic symbols. The value modifies the sorting of the
dynamic table by number. The section changes the type of
text symbols to data symbols. I don't think the section munging
is actually needed but that's an issue for another patch.
2025-10-26 John David Anglin <danglin@gcc.gnu.org>
bfd/ChangeLog:
* elf64-hppa.c (USE_DOT_ELPT_PREFIX): Define.
(struct elf_link_hash_entry): Add text_segment field.
(allocate_global_data_opd): Compute hppa_info.
Condition old dot prefix code on USE_DOT_ELPT_PREFIX.
Add new code to setup __text_seg hash table entry.
(elf64_hppa_finalize_opd): Check hh. Rework to output
relocation using __text_seg base.
(elf64_hppa_finish_dynamic_sections): Remove duplicate
comment.
(elf_hppa_final_link_relocate): Move code to initialize
the segment base values forward.
BFD: Fix function prototype breakage through stabs.c
Update function prototype templates through stabs.c according to commit eb92a17c47ea ("bfd: move sec_info from ELF to general section struct"),
which changed the generated prototypes in libbfd.h by hand rather than
by remaking them properly from sources, and causing the build to fail as
soon as libbfd.h has been regenerated.
While at it remove an extraneous character introduced by the same commit
to a comment for a new member of `struct bfd_section'.
Guinevere Larsen [Thu, 23 Oct 2025 18:05:33 +0000 (15:05 -0300)]
gdb/reverse: update error message for "reverse-" commands
Before this change, when a user tried to use a command that executes the
inferior in reverse, they would get the following error message:
Target multi-thread does not support this command.
As an end-user with no knowledge of the internals of GDB would have as a
best guess, that reverse execution as a whole would not be supported in
their system (verified by asking a couple new users).
This commit changes the message to avoid the internal terminology, and
to add a hint that the user may need to create a recording somehow to be
able to execute in reverse.
Tom Tromey [Tue, 14 Oct 2025 19:26:30 +0000 (13:26 -0600)]
Handle dynamic DW_AT_bit_size
gnat-llvm will sometimes emit a structure that that uses
DW_AT_bit_size with an expression to compute the bit size of a record.
I believe this is a DWARF extension. This patch implements support
for this in gdb.
Simon Marchi [Thu, 23 Oct 2025 16:34:23 +0000 (12:34 -0400)]
gdb: add gdb_rl_tilde_expand util
Add gdb_rl_tilde_expand, a wrapper around readline's tilde_expand that
returns a gdb::unique_xmalloc_ptr<char>. Change all callers of
tilde_expand to use gdb_rl_tilde_expand (even the couple of spots that
release it immediatly, for consistency). This simplifies a few callers.
The name gdb_tilde_expand is already taken by a home-made implementation
in gdbsupport/gdb_tilde_expand.{h.cc}. I wonder if we could just use
that one instead of readline's tilde_expand, but that's an orthogonal
question. I don't know how they differ, and I don't want to introduce
behavior changes in this patch.
Change-Id: I6d34eef19f86473226df4ae56d07dc01912e3131 Approved-By: Tom Tromey <tom@tromey.com>
Rainer Orth [Fri, 24 Oct 2025 13:57:24 +0000 (15:57 +0200)]
ld: testsuite: xfail ld-elf/compress1a etc. on Solaris/sparcv9 [PR25802]
A couple of tests FAIL on Solaris/sparcv9:
FAIL: ld-elf/compress1a
FAIL: ld-elf/compressed1a
FAIL: ld-elf/eh5
FAIL: --gc-sections with multiple debug sections for a function section
The symptom is always similar:
compress1.o:(.debug_info+0x10): relocation truncated to fit: R_SPARC_UA32 against `.text'
eh5.o:(.eh_frame+0x3e): relocation truncated to fit: R_SPARC_UA32 against symbol `my_personality_v0' defined in .text section in eh5.o
all-debug-sections.o: in function `debug_info_main':
(.debug_info.text.main+0x4): relocation truncated to fit: R_SPARC_32 against symbol `main' defined in .text.main section in all-debug-sections.o
With the default Solaris/sparcv9 text address of 0x100000000, the
relocations are out of the 32-bit range of R_SPARC_UA32 resp. R_SPARC_32,
so the "relocation truncated to fit" errors are benign.
One could avoid those by linking the affected tests with -Ttext=0x80000000,
matching Solaris /usr/lib/ld/map.below4G, but that doesn't reflect real
usage. Therefore this patch xfail's those tests.
Tested on sparcv9-sun-solaris2.11, sparc-sun-solaris2.11, and
x86_64-pc-linux-gnu.
On openSUSE Leap 15.6 x86_64 I ran into:
....
(gdb) file gdbindex-stabs^M
Reading symbols from gdbindex-stabs...^M
warning: stabs debug information is not supported.^M
(gdb) list stabs_function^M
(gdb) FAIL: gdb.base/gdbindex-stabs.exp: list stabs_function
...
H. Peter Anvin [Fri, 24 Oct 2025 13:12:39 +0000 (15:12 +0200)]
z80, gas: follow historical assemblers and allow "op A,x" and "op x"
For arithmetic ops, Z80 syntax wants "op A,x" for ADD, ADC and SBC and
"op x" for SUB, AND, OR, XOR, and CP. Many historical assemblers
simply treat them orthogonally; allowing but not requiring the "A,"
operand for any of these operations. This is widely used in legacy
source code, and there is no reason not to.
Jan Beulich [Fri, 24 Oct 2025 13:11:39 +0000 (15:11 +0200)]
bfd: replace _bfd_merge_sections() hook with simple boolean
There's no need for a hook; what needs doing is uniform, the question is
only whether to perform any merging (i.e. whether other parts of a backend
are capable of dealing with the effects).
Where _bfd_nolink_bfd_merge_sections() was used, false is hardcoded. For
ELF no real target override is permitted; true is hardcoded except for the
cases where bfd_generic_merge_sections() was used as the hook function
before.
Jan Beulich [Fri, 24 Oct 2025 13:11:11 +0000 (15:11 +0200)]
bfd: generalize _bfd_elf_merge_sections()
Except for the ELF class check, which isn't needed anymore when the
generic linker knows how to deal with SEC_MERGE sections, there isn't
anything substantially ELF-specific left in the function.
This also eliminates the need for the "remove_hook" callback.
As a result, section merging itself now works for mixed-class ELF input
objects (issues with dropping of symbols and relocations that were there
before for such cases remain present, though), i.e. the PR ld/19013
testcases need adjusting accordingly: Both now expect identical .rodata
contents. While making the change, add another line of expected output,
to properly match after "#...". Else a mismatch on the important line
isn't properly visible in ld.log.
In set_symbol_from_hash() additionally set BSF_GLOBAL when dealing with a
defined symbol. Without that the if() body ahead of the one being added to
default_indirect_link_order() would not be entered once previously
undefined symbols become defined (suggesting that there is a pre-existing
issue there).
... as well as that of _bfd_stab_section_offset(): As sec_info is now
hanging off of sec, there's no need for the extra 4th parameter anymore.
Along these line struct struct coff_section_tdata's stab_info member then
isn't needed anymore either.
Furthermore there also hasn't been a good reason to have the caller of
_bfd_link_section_stabs() set sec_info_type.
As sec_info is now hanging off of sec, there's no need for the extra 3rd
parameter anymore; all callers pass as 2nd argument the address of a
section pointer that sec_info can be fetched from.
As sec_info is now hanging off of sec, there's no need for the extra 4th /
3rd parameter anymore. Along these line struct sec_merge_sec_info's
psecinfo member then isn't needed anymore either.
Furthermore there also hasn't been a good reason to have the caller of
_bfd_add_merge_section() set sec_info_type.
Jan Beulich [Fri, 24 Oct 2025 13:09:11 +0000 (15:09 +0200)]
bfd: move sec_info from ELF to general section struct
This is in preparation of supporting section merging also when the output
isn't ELF (or not of the same class). Note that it's also more consistent
this way, as the related sec_info_type field also live in the same struct.
Tom Tromey [Fri, 24 Oct 2025 00:04:14 +0000 (18:04 -0600)]
Remove get_context_stack_depth
Nothing calls get_context_stack_depth, so this patch removes it.
I looked at also removing context_stack::depth but apparently this is
used in coffread.c, and I didn't want to figure out how to make it
local to just that code.