]> git.ipfire.org Git - thirdparty/binutils-gdb.git/log
thirdparty/binutils-gdb.git
9 days agolibctf: serialize: type section sizing
Nick Alcock [Fri, 25 Apr 2025 13:17:36 +0000 (14:17 +0100)] 
libctf: serialize: type section sizing

This is made much simpler by the fact that the DTD representation
now tracks the size of each vlen, so we don't need per-type-kind
code to track it ourselves any more.  There's extra code to handle
type suppression, CTF_K_BIG elision, and prefixes.

9 days agolibctf: serialize: check the type section for BTF-incompatible types
Nick Alcock [Fri, 25 Apr 2025 12:01:21 +0000 (13:01 +0100)] 
libctf: serialize: check the type section for BTF-incompatible types

We add a new ctf_type_sect_is_btf function (internal to ctf-serialize.c) to
check the type section against the write prohibitions list and (after
write-suppression) against the set of types allowed in BTF, and determine
whether this type section contains any types BTF does not allow.

CTF-specific type kinds like CTF_K_FLOAT are obviously prohibited in BTF, as
are CTF-specific prefixes, except that CTF_K_BIG is allowed if and only if
both its ctt_size and vlen are still zero: in that case it will be elided by
type section writeout and will never appear in the BTF at all.

Structs are checked to make sure they don't use any nameless padding members
and that (if they are bitfields) all their offsets will still fit after
conversion from CTF_K_BIG gap-between-struct-members representation (if they
are not bitfields, we know they will fit, but for bitfields, they might be
too big).

9 days agolibctf: strings: no external strings in BTF
Nick Alcock [Fri, 25 Apr 2025 11:56:58 +0000 (12:56 +0100)] 
libctf: strings: no external strings in BTF

One of the things BTF doesn't have is the concept of external strings which
can be shared with the ELF strtab.  Therefore, even if the linker has
reported strings which the dict is reusing, when we generate the strtab for
a BTF dict we should emit those strings into it (and we should certainly
not cause the presence of external strings to prevent BTF emission!)

Note that since already-written strtab entries are never erased, writing a
dict as BTF and then CTF will cause external strings to be emitted even for
the CTF.  This sort of repeated writing in different formats seems to be
very rare: in any case, the problem can be avoided by simply doing the CTF
writeout first (the following BTF writeout will spot the missing external-
in-CTF strings and add them).

We also throw away the internal-only function ctf_strraw_explicit(), which
was used to add strings with a hardwired strtab: it was only ever used to
write out the variable section, which is gone in v4.

9 days agolibctf: serialize: kind suppression and prohibition
Nick Alcock [Fri, 25 Apr 2025 11:42:12 +0000 (12:42 +0100)] 
libctf: serialize: kind suppression and prohibition

The CTF serialization machinery decides whether to write out a dict as BTF
or CTF (or, in LIBCTF_BTM_BTF mode, whether to write out a dict or fail with
ECTF_NOTBTF) in part by looking at the type kinds in the dictionary.

It is possible that you'd like to extend this check and ban specific type
kinds from the dictionary (possibly even if it's CTF); it's also possible
that you'd like to *not* fail even if a CTF-only kind is found, but rather
replace it with a still-valid stub (CTF_K_UNKNOWN / BTF_KIND_UNKNOWN) and
keep going.  (The kernel's btfarchive machinery does this to ensure that
the compiler and previous link stages have emitted only valid BTF type
kinds.)

ctf_write_suppress_kind supports both these use cases:

+int ctf_write_suppress_kind (ctf_dict_t *fp, int kind, int prohibited);

This commit adds only the core population code: the actual suppression is
spread across the serializer and will be added in the next commits.

9 days agolibctf: serialize: user control over BTF-versus-CTF writeout
Nick Alcock [Fri, 25 Apr 2025 11:35:07 +0000 (12:35 +0100)] 
libctf: serialize: user control over BTF-versus-CTF writeout

We need some way for users to declare that they want BTF or CTF in
particular to be written out when they ask for it, or that they don't mind
which.  Adding this to all the ctf_write functions (like the compression
threshold already is) would be a bit of a nightmare: there are a great many
of them and this doesn't seem like something people would want to change
on a per-dict basis (even if we did, we'd need to think about archives and
linking, which work on a higher level than single dicts).

So we repurpose an unused, vestigial existing function, ctf_version(), which
was originally intended to do some sort of rather unclear API switching at
runtime, to allow switching between different CTF file format versions (not
yet supported, you have to pass CTF_VERSION) and BTF writeout modes:

/* BTF/CTF writeout version info.

   ctf_btf_mode has three levels:

   - LIBCTF_BTM_ALWAYS writes out full-blown CTFv4 at all times
   - LIBCTF_BTM_POSSIBLE writes out CTFv4 if needed to avoid information loss,
     BTF otherwise.  If compressing, the same as LIBCTF_BTM_ALWAYS.
   - LIBCTF_BTM_BTF writes out BTF always, and errors otherwise.

   Note that no attempt is made to downgrade existing CTF dicts to BTF: if you
   read in a CTF dict and turn on LIBCTF_BTM_POSSIBLE, you'll get a CTF dict; if
   you turn on LIBCTF_BTM_BTF, you'll get an unconditional error.  Thus, this is
   really useful only when reading in BTF dicts or when creating new dicts.  */

typedef enum ctf_btf_mode
{
  LIBCTF_BTM_BTF = 0,
  LIBCTF_BTM_POSSIBLE = 1,
  LIBCTF_BTM_ALWAYS = 2
} ctf_btf_mode_t;

/* Set the CTF library client version to the specified version: this is the
   version of dicts written out by the ctf_write* functions.  If version is
   zero, we just return the default library version number.  The BTF version
   (for CTFv4 and above) is indicated via btf_hdr_len, also zero for "no
   change".

    You can influence what type kinds are written out to a CTFv4 dict via the
    ctf_write_suppress_kind() function.  */

extern int ctf_version (int ctf_version_, size_t btf_hdr_len,
ctf_btf_mode_t btf_mode);

(We retain the ctf_version_ stuff to leave space in the API to let the
library possibly do file format downgrades in future, since we've already
had requests for such things from users.)

9 days agolibctf, serialize: preparatory steps
Nick Alcock [Fri, 25 Apr 2025 11:20:36 +0000 (12:20 +0100)] 
libctf, serialize: preparatory steps

The new serializer is quite a lot more customizable than the old, because it
can write out BTF as well as CTF: you can ask to write out BTF or fail,
write out CTF if required to avoid information loss, otherwise BTF, or
always write out CTF.

Callers often need to find out whether a dict could be written out as BTF
before deciding how to write it out (because a dict can never be written out
as BTF if it is compressed, a caller might well want to ask if there is
anything else that prevents BTF writeout -- say, slices, conflicting types,
or CTF_K_BIG -- before deciding whether to compress it).  GNU ld will do
this whenever it is passed only BTF sections on the input.

Figuring out whether a dict can be written out as BTF is quite expensive: we
have to traverse all the types and check them, including every member of
every struct.  So we'd rather do that work only once.  This means making a
lot of state once private to ctf_preserialize public enough that another
function can initialize it; and since the whole API is available after
calling this function and before serializing, we should probably arrange
that if we do things we know will invalidate the results of all this
checking, we are forced to do it again.

This commit does that, moving all the existing serialization state into a
new ctf_serialize_t and adding to it.  Several functions grow force_ctf
arguments that allow the caller to force CTF emission even if the type
section looks BTFish: the writeout code and archive creation use this to
force CTF emission if we are compressing, and archive creation uses it
to force CTF emission if a CTF multi-member archive is in use, because
BTF doesn't support archives at all so there's no point maintaining
BTF compatibility in that case.  The ctf_write* functions gain support for
writing out BTF headers as well as CTF, depending on whether what was
ultimately written out was actually BTF or not.

Even more than most commits in this series, there is no way this is
going to compile right now: we're in the middle of a major transition,
completed in the next few commits.

9 days agolibctf: lookup, open: chase header field changes
Nick Alcock [Fri, 25 Apr 2025 10:54:28 +0000 (11:54 +0100)] 
libctf: lookup, open: chase header field changes

Nothing exciting here, just header fields slightly changing name
and a couple of new comments and indentation fixes.

9 days agolibctf, open: new API for getting the size of CTF/BTF file sections
Nick Alcock [Fri, 25 Apr 2025 10:51:04 +0000 (11:51 +0100)] 
libctf, open: new API for getting the size of CTF/BTF file sections

I wrote this for BTF type size querying programs, but it might be
of more general use and it's impossible to get this info in any
other way, so we might want to keep it.

New API:
+size_t ctf_sect_size (ctf_dict_t *, ctf_sect_names_t sect);

9 days agolibctf: types: access to raw type data
Nick Alcock [Fri, 25 Apr 2025 10:47:07 +0000 (11:47 +0100)] 
libctf: types: access to raw type data

This new API lets users ask for the raw type data associated with a type
(either the whole lot including prefixes, or just the suffix if this is not
a CTF_K_BIG type), and then they can manipulate it using ctf.h functions
or whatever else they like.  Doing this does not preclude using libctf
querying functions at the same time (just don't change the type!  It's
const for a reason).

New API:

+const ctf_type_t *ctf_type_data (ctf_dict_t *, ctf_id_t, int prefix);

This function was unimplementable before the DTD changes, because the
ctf_type_t and vlen were separated in memory: but now they're always stored
in a single buffer, it's reliable and simple, indeed trivial.

9 days agolibctf: types: recursive type visiting
Nick Alcock [Fri, 25 Apr 2025 10:44:19 +0000 (11:44 +0100)] 
libctf: types: recursive type visiting

ctf_type_visit and ctf_type_rvisit have to adapt to the internal
API changes, but also to the change in the representation of
structures.  The new code is quite a lot simpler than the old,
because we don't need to roll our own iterator but can just use
ctf_member_next.

API changes, the usual for the *_f typedefs and anything to do with
structures:

-typedef int ctf_visit_f (const char *name, ctf_id_t type, unsigned long offset,
-  int depth, void *arg);
+typedef int ctf_visit_f (ctf_dict_t *, const char *name, ctf_id_t type,
+  size_t offset, int bit_width, int depth,
   void *arg);

9 days agolibctf, create: the unknown type
Nick Alcock [Fri, 25 Apr 2025 10:43:26 +0000 (11:43 +0100)] 
libctf, create: the unknown type

Just as for typedefs, this is just catching up with API changes on the
type-addition side.

9 days agolibctf, create: typedefs
Nick Alcock [Fri, 25 Apr 2025 10:41:45 +0000 (11:41 +0100)] 
libctf, create: typedefs

Nothing here but adjustment to internal API changes.  Typedefs have no
special properties that need querying, so there are no changes to
ctf-types.c at all.

9 days agolibctf, create, types: slices
Nick Alcock [Fri, 25 Apr 2025 10:40:13 +0000 (11:40 +0100)] 
libctf, create, types: slices

Nothing difficult for this CTF-specific type kind, just the usual adjustment
to internal API changes.

9 days agolibctf: create, types: arrays
Nick Alcock [Fri, 25 Apr 2025 10:38:11 +0000 (11:38 +0100)] 
libctf: create, types: arrays

The same internal API changes for arrays.  There is one ABI change here,
to ctf_arinfo_t:

-  uint32_t ctr_nelems; /* Number of elements.  */
+  size_t ctr_nelems; /* Number of elements.  */

9 days agolibctf: create, types: reftypes and pointers
Nick Alcock [Fri, 25 Apr 2025 10:31:28 +0000 (11:31 +0100)] 
libctf: create, types: reftypes and pointers

This is pure adjustment for internal API changes, and a change to the
type-compatibility of pointers to type 0 now that it can be void as well as
"unrepresentable".

By now this dance should be quite familiar.

9 days agolibctf: create, types: conflicting types
Nick Alcock [Fri, 25 Apr 2025 10:23:46 +0000 (11:23 +0100)] 
libctf: create, types: conflicting types

The conflicting type kind is a CTF-specific prefix kind consisting purely of
an optional translation unit name.  It takes the place of the old hidden
bit: we have already seen it used to prefix types added with a
CTF_ADD_NONROOT flag.  The deduplicator will also use them to label
conflicting types from different TUs smushed into the same dict by the
CU-mapping mechanism: unlike the hidden bit, with this scheme users can tell
which CUs the conflicting types came from.

New API:

+int ctf_type_conflicting (ctf_dict_t *, ctf_id_t, const char **cuname);
+int ctf_set_conflicting (ctf_dict_t *, ctf_id_t, const char *);

(Frankly I expect ctf_set_conflicting to be used only by deduplicators and
things like that, but if we provide an option to query something we should
also provide an option to produce it...)

9 days agolibctf, create, types: type and decl tags
Nick Alcock [Fri, 25 Apr 2025 10:14:09 +0000 (11:14 +0100)] 
libctf, create, types: type and decl tags

These are a little more fiddly than previous kinds, because their
namespacing rules are odd: they have names (so presumably we want an API to
look them up by name), but the names are not unique (they don't need to be,
because they are not entities you can refer to from C), so many distinct
tags in the same TU can have the same name.  Type tags only refer to a type
ID: decl tags refer to a specific function parameter or structure member via
a zero-indexed "component index".

The name tables for these things are a hash of name to a set of type IDs;
rather different from all the other named entities in libctf.  As a
consequence, they can presently be looked up only using their own dedicated
functions, not using ctf_lookup_by_name et al.  (It's not clear if this
restriction could ever be lifted: ctf_lookup_by_name and friends return a
type ID, not a set of them.)

They are similar enough to each other that we can at least have one function
to look up both type and decl tags if you don't care about their
component_idx and only want a type ID: ctf_tag.  (And one to iterate over
them, ctf_tag_next).

(A caveat: because tags aren't widely used or generated yet, much of this is
more or less untested and/or supposition and will need testing later.)

New API, more or less the minimum needed because it's not entirely clear how
these things will be used:

+ctf_id_t ctf_tag (ctf_dict_t *, ctf_id_t tag);
+ctf_id_t ctf_decl_tag (ctf_dict_t *, ctf_id_t decl_tag,
+        int64_t *component_idx);
+ctf_id_t ctf_tag_next (ctf_dict_t *, const char *tag, ctf_next_t **);
+ctf_id_t ctf_add_type_tag (ctf_dict_t *, uint32_t, ctf_id_t, const char *);
+ctf_id_t ctf_add_decl_type_tag (ctf_dict_t *, uint32_t, ctf_id_t, const char *);
+ctf_id_t ctf_add_decl_tag (ctf_dict_t *, uint32_t, ctf_id_t, const char *,
+    int component_idx);

5 weeks agolibctf: create, types: functions, linkage, arg names (API ADVICE)
Nick Alcock [Fri, 25 Apr 2025 09:55:41 +0000 (10:55 +0100)] 
libctf: create, types: functions, linkage, arg names (API ADVICE)

Functions change in CTFv4 by growing argument names as well as argument
types; the representation changes into a two-element array of (type, string
offset) rather than a simple array of arg types.  Functions also gain an
explicit linkage in a different type kind (CTF_K_FUNC_LINKAGE, which
corresponds to BTF_KIND_FUNC).

New API:

 typedef struct ctf_funcinfo {
 /* ... */
-  uint32_t ctc_argc; /* Number of typed arguments to function.  */
+  size_t ctc_argc; /* Number of typed arguments to function.  */
};

int ctf_func_arg_names (ctf_dict_t *, unsigned long, uint32_t, const char **);
int ctf_func_type_arg_names (ctf_dict_t *, ctf_id_t, uint32_t,
      const char **names);
+extern int ctf_type_linkage (ctf_dict_t *, ctf_id_t);
-extern ctf_id_t ctf_add_function (ctf_dict_t *, uint32_t,
-   const ctf_funcinfo_t *, const ctf_id_t *);
+extern ctf_id_t ctf_add_function (ctf_dict_t *, uint32_t,
+   const ctf_funcinfo_t *, const ctf_id_t *,
+   const char **arg_names);
+extern ctf_id_t ctf_add_function_linkage (ctf_dict_t *, uint32_t,
+   ctf_id_t, const char *, int linkage);

Adding this is fairly straightforward; the only annoying part is the way the
callers need to allocate space for the arg name and type arrays.  Maybe we
should rethink these into something like ctf_type_aname(), allocating
space for the caller so the caller doesn't need to?  It would certainly
make all the callers in libctf much less complex...

While we're at it, adjust ctf_type_reference, ctf_type_align, and
ctf_type_size for the new internal API changes (they also all have
special-case code for functions).

5 weeks agolibctf, types: ctf_type_kind_{iter,next} et al
Nick Alcock [Thu, 24 Apr 2025 17:00:32 +0000 (18:00 +0100)] 
libctf, types: ctf_type_kind_{iter,next} et al

These new functions let you iterate over types by kind, letting you get all
variables, all enums, all datasecs, etc.  (This is amenable to future
optimization, and some is expected shortly.)

We also add new iternal functions ctf_type_kind_{forwarded_,unsliced_,}tp
which are like the corresponding non-_tp functions except that they
take a ctf_type_t rather than a type ID: doing this allows the deduplicator
to use these nearly-public functions more.  The public ctf_type_kind*
functions are reimplemented in terms of these.

This machinery is the principal place where the magic encoding of forwards
is encoded.

5 weeks agolibctf: create, types: variables and datasecs (REVIEW NEEDED)
Nick Alcock [Thu, 24 Apr 2025 16:42:16 +0000 (17:42 +0100)] 
libctf: create, types: variables and datasecs (REVIEW NEEDED)

This is an area of significant difference from CTFv3.  The API changes
significantly, with quite a few additions to allow creation and querying of
these new datasec entities:

-typedef int ctf_variable_f (const char *name, ctf_id_t type, void *arg);
+typedef int ctf_variable_f (ctf_dict_t *, const char *name, ctf_id_t type,
+     void *arg);
+typedef int ctf_datasec_var_f (ctf_dict_t *fp, ctf_id_t type, size_t offset,
+        size_t datasec_size, void *arg);

+/* Search a datasec for a variable covering a given offset.
+
+   Errors with ECTF_NODATASEC if not found.  */
+
+ctf_id_t ctf_datasec_var_offset (ctf_dict_t *fp, ctf_id_t datasec,
+  uint32_t offset);
+
+/* Return the datasec that a given variable appears in, or ECTF_NODATASEC if
+   none.  */
+
+ctf_id_t ctf_variable_datasec (ctf_dict_t *fp, ctf_id_t var);

+int ctf_datasec_var_iter (ctf_dict_t *, ctf_id_t, ctf_datasec_var_f *,
+   void *);
+ctf_id_t ctf_datasec_var_next (ctf_dict_t *, ctf_id_t, ctf_next_t **,
+        size_t *size, size_t *offset);

-int ctf_add_variable (ctf_dict_t *, const char *, ctf_id_t);
+/* ctf_add_variable adds variables to no datasec at all;
+   ctf_add_section_variable adds them to the given datasec, or to no datasec at
+   all if the datasec is NULL.  */
+
+ctf_id_t ctf_add_variable (ctf_dict_t *, const char *, int linkage, ctf_id_t);
+ctf_id_t ctf_add_section_variable (ctf_dict_t *, uint32_t,
+    const char *datasec, const char *name,
+    int linkage, ctf_id_t type,
+    size_t size, size_t offset);

We tie datasecs quite closely to variables at addition (and, as should
become clear later, dedup) time: you never create datasecs, you only create
variables *in* datasecs, and the datasec springs into existence when you do
so: datasecs are always found in the same dict as the variables they contain
(the variables are never in the parent if the datasec is in a child or
anything).  We keep track of the variable->datasec mapping in
ctf_var_datasecs (populating it at addition and open time), to allow
ctf_variable_datasec to work at reasonable speed.  (But, as yet, there are
no tests of this function at all.)

The datasecs are created unsorted (to avoid variable addition becoming
O(n^2)) and sorted at serialization time, and when ctf_datasec_var_offset is
invoked.

We reuse the natural-alignment code from struct addition to get a plausible
offset in datasecs if an alignment of -1 is specified: maybe this is
unnecessary now (it was originally added when ctf_add_variable added
variables to a "default datasec", while now it just leaves them out of
all datasecs, like externs are).

One constraint of this is that we currently prohibit the addition of
nonrepresentable-typed variables, because we can't tell what their natural
alignment is: if we dropped the whole "align" and just required everyone
adding a variable to a datasec to specify an offset, we could drop that
restriction. WDYT?

One additional caveat: right now, ctf_lookup_variable() looks up the type of
a variable (because when it was invented, variables were not entities in
themselves that you could look up).  This name is confusing as hell as a
result.  It might be less confusing to make it return the CTF_K_VAR, but
that would be awful to adapt callers to, since both are represented with
ctf_id_t's, so the compiler wouldn't warn about the needed change at all...
I've vacillated on this three or four times now.

6 weeks agolibctf: decl, types: revise ctf_decl*, ctf_type_*name
Nick Alcock [Fri, 25 Apr 2025 10:03:16 +0000 (11:03 +0100)] 
libctf: decl, types: revise ctf_decl*, ctf_type_*name

These all need fairly trivial revisions for prefix types.  While
we're at it, we can add explicit handling of nonrepresentable types,
returning CTF_K_UNKNOWN for such types rather than throwing an error,
so that type printing prints (nonrepresentable type) for such types
as it always intended to.

6 weeks agolibctf, create, types: encoding, BTF floats
Nick Alcock [Thu, 24 Apr 2025 16:28:34 +0000 (17:28 +0100)] 
libctf, create, types: encoding, BTF floats

This adds support for the nearly useless BTF_KIND_FLOAT, under the name
CTF_K_BTF_FLOAT.  At the same time we fix up the ctf_add_encoding and
ctf_type_encoding machinery for the new API changes.

I expect this to change a bit: Ali Bahrami reckons I've oversimplified the
CTFv4 encoding representation and need to reintroduce at least a width.

New API:

ctf_id_t ctf_add_btf_float (ctf_dict_t *, uint32_t,
                            const char *, const ctf_encoding_t *);

6 weeks agolibctf: create, types: enums and enum64s; type encoding
Nick Alcock [Thu, 24 Apr 2025 16:17:57 +0000 (17:17 +0100)] 
libctf: create, types: enums and enum64s; type encoding

This commit adapts most aspects of enum handling: querying and iteration,
enumerator querying and iteration, ctf_type_add, etc.  We have to adapt to
enum64s and to signed versus unsigned enums, to our vlen and DTD changes and
other internal API changes to handle prefix types etc, and fix the types of
things to allow for 64-bit enumerators.  We can also (finally!) get useful
info on enum size rather than being restricted to a value hardwired into
libctf.

We also adjust all the type-encoding functions for the internal API changes,
since enums are the first encodable entities we have covered.

API changes:

-typedef int ctf_enum_f (const char *name, int val, void *arg);
+typedef int ctf_enum_f (const char *name, int64_t val, void *arg);
+typedef int ctf_unsigned_enum_f (const char *name, uint64_t val, void *arg);

-extern const char *ctf_enum_name (ctf_dict_t *, ctf_id_t, int);
-extern int ctf_enum_value (ctf_dict_t *, ctf_id_t, const char *, int *);
+extern const char *ctf_enum_name (ctf_dict_t *, ctf_id_t, int64_t);
+extern int ctf_enum_value (ctf_dict_t *, ctf_id_t, const char *, int64_t *);
+extern int ctf_enum_unsigned_value (ctf_dict_t *, ctf_id_t, const char *, uint64_t *);
+
+/* Return 1 if this enum's contents are unsigned, so you can tell which of the
+   above functions to use.  */
+
+extern int ctf_enum_unsigned (ctf_dict_t *, ctf_id_t);

-/* Return all enumeration constants in a given enum type.  */
-extern int ctf_enum_iter (ctf_dict_t *, ctf_id_t, ctf_enum_f *, void *);
+/* Return all enumeration constants in a given enum type.  The return value, and
+   VAL argument, may need to be cast to uint64_t: see ctf_enum_unsigned().  */
+extern int64_t ctf_enum_iter (ctf_dict_t *, ctf_id_t, ctf_enum_f *, void *);
 extern const char *ctf_enum_next (ctf_dict_t *, ctf_id_t, ctf_next_t **,
-   int *);
+   int64_t *);
+
+/* enums are created signed by default.  If you want an unsigned enum,
+   use ctf_add_enum_encoded() with an encoding of 0 (CTF_INT_SIGNED and
+   everything else off).  This will not create a slice, unlike all other
+   uses of ctf_add_enum_encoded(), and the result is still representable
+   as BTF.  */
+
+extern ctf_id_t ctf_add_enum64_encoded (ctf_dict_t *, uint32_t, const char *,
+ const ctf_encoding_t *);
+extern ctf_id_t ctf_add_enum64 (ctf_dict_t *, uint32_t, const char *);

-extern int ctf_add_enumerator (ctf_dict_t *, ctf_id_t, const char *, int);
+extern int ctf_add_enumerator (ctf_dict_t *, ctf_id_t, const char *, int64_t);

The only aspects of enums that are not now handled are forwards to enums,
dumping of enums, and deduplication of enums.

6 weeks agolibctf: types: add ctf_struct_bitfield (NEEDS REVIEW)
Nick Alcock [Thu, 24 Apr 2025 16:05:10 +0000 (17:05 +0100)] 
libctf: types: add ctf_struct_bitfield (NEEDS REVIEW)

This new public API function allows you to find out if a struct has the
bitfield flag set or not.  (There are no other properties specific to a
struct, so we needed a new function for it.  I am open to a
ctf_struct_info() function handing back a struct if people prefer.)

New API:

int ctf_struct_bitfield (ctf_dict_t *, ctf_id_t);

6 weeks agolibctf: create: ctf_add_type modifications
Nick Alcock [Thu, 24 Apr 2025 15:59:23 +0000 (16:59 +0100)] 
libctf: create: ctf_add_type modifications

This adapts ctf_add_type a little, adding support for prefix types, shifting
away from hardwired things towards API functions that can adapt to the CTFv4
changes, adapting to the structure/union API changes, and adding bitfielded
structures and structure members as needed.

6 weeks agolibctf: types: ctf_type_resolve_nonrepresentable
Nick Alcock [Thu, 24 Apr 2025 15:55:20 +0000 (16:55 +0100)] 
libctf: types: ctf_type_resolve_nonrepresentable

This new internal function allows us to say "resolve a type to its base
type, but treat type 0 like BTF, returning 0 if it is found rather than
erroring with ECTF_NONREPRESENTABLE".  Used in the next commit.

6 weeks agolibctf: create: structure and union member addition
Nick Alcock [Thu, 24 Apr 2025 15:47:14 +0000 (16:47 +0100)] 
libctf: create: structure and union member addition

There is one API addition here:

int ctf_add_member_bitfield (ctf_dict_t *, ctf_id_t souid,
                             const char *, ctf_id_t type,
                             unsigned long bit_offset,
                             int bit_width);

SoU addition handles the representational changes for bitfields and for
CTF_K_BIG structs (i.e. all structs you can add members to), errors out if
you add bitfields to structs that aren't created with the
CTF_ADD_STRUCT_BITFIELDS flag, and arranges to add padding as needed if
there is too much of a gap for the offsets to encode in one hop (that
part is still untested).

6 weeks agolibctf: create: struct/union addition
Nick Alcock [Thu, 24 Apr 2025 15:28:26 +0000 (16:28 +0100)] 
libctf: create: struct/union addition

There's one API addition here: the existing CTF_ADD_ROOT / CTF_ADD_NONROOT
flags can have a new flag ORed with them, CTF_ADD_STRUCT_BITFIELDS,
indicating that the newly-added struct/union is capable of having bitfields
added to it via the new ctf_add_member_bitfield function (see a later
commit).

Without this, you can only add bitfields via the deprecated slice or base
type encoding representations (the former will force CTF output).

Implementation notes: structs and unions are always added with a CTF_K_BIG
prefix: if promoting from a forward, one is added.  These are elided at
serialization time if they are not needed to encode this size of struct /
this number of members.  (This means you don't have to figure out in advance
if your struct will be too big for BTF: you can just add members to it,
and libctf will figure it out and upgrade the dict as needed, or tell you
it can't if you've forbidden such things.)

We take advantage of this to merge a couple of very similar functions,
saving a bit of code.

6 weeks agolibctf: create: DTD addition and deletion; ctf_rollback
Nick Alcock [Thu, 24 Apr 2025 15:11:53 +0000 (16:11 +0100)] 
libctf: create: DTD addition and deletion; ctf_rollback

DTD deletion changes mostly relate to the changes to the ctf_dtdef_t, but
also we no longer nede to have special handling for forwards (we can just
use ctf_type_kind_forwarded like everyone else).

Rollback no longer needs to delete things by hand (it hasn't needed to for
years): it can just call ctf_dtd_delete.

ctf_add_generic changes substantially, mostly to allow for the ctf_dtdef_t
changes.  Rather than returning a type ID it now returns the DTD it just
allocated: it can also be asked to add some prefixes, and return the first
prefix added (which may not be the first prefix in the type, because if it
is asked to add a non-root-visible type it will additionally allocate a
CTF_K_CONFLICTING prefix to encode that).

Finally, duplicate name detection is suppressed for type and decl tags.

6 weeks agolibctf: create, lookup: delete DVDs; ctf_lookup_by_kind
Nick Alcock [Thu, 24 Apr 2025 14:58:12 +0000 (15:58 +0100)] 
libctf: create, lookup: delete DVDs; ctf_lookup_by_kind

Variable handling in BTF and CTFv4 works quite differently from in CTFv3.
Rather than a separate section containing sorted, bsearchable variables,
they are simply named entities like types, stored in CTF_K_VARs.

As a first stage towards migrating to this, delete most references to
the ctf_varent_t and ctf_dvdef_t, including the DVD lookup code, all
the linking code, and quite a lot of the serialization code.

Note: CTF_LINK_OMIT_VARIABLES_SECTION, and the whole "delete variables that
already exist in the symtypetabs section" stuff, has yet to be
reimplemented.  We can implement CTF_LINK_OMIT_VARIABLES_SECTION by simply
excising all CTF_K_VARs at deduplication time if requested.  (Note:
symtypetabs should still point directly at the type, not at the CTF_K_VAR.)

(Symtypetabs in general need a bit more thought -- perhaps we can now store
them in a separate .ctf.symtypetab section with its own little four-entry
header for the symtypetabs and their indexes, making .ctf even more like
.BTF; the only difference would then be that .ctf could include prefix
types, CTF_K_FLOAT, and external string refs.  For later discussion.)

We also add ctf_lookup_by_kind() at this stage (because it is hopelessly
diff-entangled with ctf_lookup_variable): this looks up a type of a
particular kind, without needing a per-kind lookup function for it,
nor needing to hack around adding string prefixes (so you can do
ctf_lookup_by_kind (fp, CTF_K_STRUCT, "foo") rather than having to
do ctf_lookup_by_name (fp, "struct foo"): often this is more convenient, and
anything that reduces string buffer manipulation in C is good.)

6 weeks agolibctf: create: vlen growth and prefix addition (NEEDS REVIEW)
Nick Alcock [Thu, 24 Apr 2025 14:48:16 +0000 (15:48 +0100)] 
libctf: create: vlen growth and prefix addition (NEEDS REVIEW)

This commit modifies ctf_grow_vlen to account for the recent changes to
ctf_dtdef_t, and adds a new ctf_add_prefix function to add a prefix to an
existing type, moving the dtd_data and dtd_vlen up accordinly.

It deserves close review, since this is probably the single greatest bug
cluster in libctf: the number of times I added to a variable of type
ctf_type_t and assumed it would move it in bytes rather than ctf_type_t
units is hard to believe.

6 weeks agolibctf: types: struct/union member querying and iteration
Nick Alcock [Thu, 24 Apr 2025 14:43:57 +0000 (15:43 +0100)] 
libctf: types: struct/union member querying and iteration

This commit revises ctf_member_next, ctf_member_iter, ctf_member_count, and
ctf_member_info for the new CTFv4 world.  This also pulls in a bunch of
infrastructure used by most of the type querying functions, and fundamental
changes to the way DTD records are represented in libctf (ctf-create not yet
adjusted).  Other type querying functions affected by changes in struct
representation are also changed.

There are some API changes here: new bit-width fields in ctf_member_f,
ctf_membinfo_t and ctf_member_next, and a fix to the type of the offset in
ctf_member_f, ctf_membinfo_t and and ctf_member_count.  (ctf_member_next got
the offset type right already.)

ctf_member_f also gets a new ctf_dict_t arg so that you can actually use
the member type it passes in without having to package up and pass in the
dict type yourself (a frequent need).  This change is later echoed in most
of the rest of the *_f typedefs.

 typedef struct ctf_membinfo
 {
   ctf_id_t ctm_type; /* Type of struct or union member.  */
-  unsigned long ctm_offset; /* Offset of member in bits.  */
+  size_t ctm_offset; /* Offset of member in bits.  */
+  int ctm_bit_width; /* Width of member in bits: -1: not bitfield */
 } ctf_membinfo_t;

-typedef int ctf_member_f (const char *name, ctf_id_t membtype,
-   unsigned long offset, void *arg);
+typedef int ctf_member_f (ctf_dict_t *, const char *name, ctf_id_t membtype,
+   size_t offset, int bit_width, void *arg);

 extern ssize_t ctf_member_next (ctf_dict_t *, ctf_id_t, ctf_next_t **,
  const char **name, ctf_id_t *membtype,
- int flags);
+ int *bit_width, int flags);

-int ctf_member_count (ctf_dict_t *, ctf_id_t);
+ssize_t ctf_member_count (ctf_dict_t *, ctf_id_t);

The DTD changes are that where before the ctf_dtdef_t had a dtd_data which
was the ctf_type_t type node for a type, and a separate dtd_vlen which was
the vlen buffer which (in the final serialized representation) would
directly follow that type, now it has one single buffer, dtd_buf, which
consists of a stream of one or more ctf_type_t nodes, followed by a vlen,
as it will appear in the final serialized form.  This buffer has internal
pointers into it: dtd_data is a pointer to the last ctf_type_t in the stream
(the true type node, after all prefixes), and dtd_vlen is a pointer to the
vlen (precisely one ctf_type_t after the dtd_data).  This representation is
nice because it means there is even less distinction between a dynamic type
added by ctf_add_*() and a static one read directly out of a dict: you can
traverse the entire type without caring where it came from, simplifying
most of the type querying functions.

(There are a few more things in there which will be useful mostly when
adding new types: their uses will be seen later.)

Two new nontrivial functions exist (one of which is annoyingly tangled up in
the diff, sorry about that): ctf_find_prefix, which hunts down a given
prefix (if it exists) among the possibly many that may exist on a type (so
you can ask it to find the CTF_K_BIG prefix for a type if it exists, and
it'll return you a pointer to its ctf_type_t record), and ctf_vlen, which
you hand a type ID and its ctf_type_t *, and it gives you back a pointer to
its vlen and tells you how long it is.  (This is one of only two places left
in ctf-types.c which cares whether a type is dynamic or not.  The other has
yet to be added).  Almost every function in ctf-types.c will end up calling
ctf_lookup_by_id and ctf_vlen in turn.

ctf_next_t has changed significantly: the ctn_type member is split in two so
that we can tell whether a given iterator works using types or indexes, and
we gain the ability to iterate over enum64s, DTDs themselves, and datasecs
(most of this will only be used in later commits).

The old internal function ctf_struct_member, which handled the distinction
between ctf_member_t and ctf_lmember_t, is gone.  Instead we have new code
that handles the different representation of bitfield versus non-bitfield
structs and unions, and more code to handle the different representation of
CTF_K_BIG structs and unions (their offsets are the distance from the last
offset, rather than the distance from the start of the structure).

7 weeks agolibctf: CTFv4: type opening
Nick Alcock [Thu, 24 Apr 2025 13:58:50 +0000 (14:58 +0100)] 
libctf: CTFv4: type opening

The majority of this commit rejigs the core type table opening
code for CTFv4: there are a few ancillary bits it drags in,
indicated below.

The internal definition of a child dict (that may not have type or string
lookups performed in it until ctf_open time) used to be 'has a
cth_parent_name', but since BTF doesn't have one of those at all, we add
an additional check: a dict the first byte of whose strtab is not 0 must
be a child.  (If *either* is true, this is a child dict, which allows for
the possibility of CTF dicts with non-deduplicated strtabs -- thus with
leading \0's -- to exist in future.)

The initial sweep through the type table in init_static_types (to size
the name-table lookup hashes) also now checks for various types which
indicate that this must be a CTF dict, in addition to being adjusted
to cater for new CTFv4 representations of things like forwards.  (At
this early stage, we cannot rely on the functions in ctf-type.c to
abstract over this for us.)

We make some new hashtables for new namespace-like things: datasecs
and type and decl tags.

The main name-population loop in init_static_types_names_internal
takes prefixes into account, looking for the name on the suffix type
(where the name is always found).  LSTRUCT handling is removed (they
no longer exist); ENUM64s, enum forwards, VARs, datasecs, and type
and decl tags get their names suitably populated.  Some buggy code
which tried to populate the name tables for cvr-quals (which are
nameless) was dropped.

We add an extra pass which traverses all datasecs and keeps track of which
datasec each var is instantiated in (if any) in a new ctf_var_datasecs hash
table.  (This uses a number of type-querying functions which don't yet
exist: they'll be added in the upcoming commits.)

We handle the type 0 == void case by pointing the first element of
ctf_txlate at a type read in named "void" (making type 0 an alias to it),
or, if one doesn't exist, creating a new one (outside the type table and dtd
arrays), and pointing type 0 at that.  Since it is numbered 0 and not in the
type table or dtd arrays, it will never be written out at serialization
time, but since it is *present*, libctf consumers who expect the void type
to have an integral definition rather than being a magic number will get
what they expect.

7 weeks agolibctf: CTFv4: core opening (other than the type table)
Nick Alcock [Thu, 24 Apr 2025 13:44:12 +0000 (14:44 +0100)] 
libctf: CTFv4: core opening (other than the type table)

This commit modifies the core opening code to handle opening CTFv4 and BTF.
Much of the back-compatibility side is left for later and is currently
untested, as is the type table side of things.

We keep the v3 header (if any) stashed away in ctf_dict_t.ctf_v3_header, for
the sake of the CTF dumper; we "upgrade" the BTF header to CTF (so that the
rest of the code can ignore the distinction, and so that you can do CTFish
things like adding symtypetab entries even to things opened as BTF), but
keep note of the fact that it was opened as BTF in ctf_dict_t.ctf_opened_btf,
so that things like ctf_import can allow for the absence of the various
parent-length fields.

A couple of ctf_dict_t fields are renamed for consistency with the headers'
names for them (ctf_parname becomes ctf_parent_name; ctf_dynparname becomes
ctf_dyn_parent_name; ctf_cuname becomes ctf_cu_name).  Not all users are yet
adjusted.

7 weeks agolibctf: adjust foreign-endian byteswapping for v4
Nick Alcock [Thu, 24 Apr 2025 13:27:48 +0000 (14:27 +0100)] 
libctf: adjust foreign-endian byteswapping for v4

Split into a separate commit because it's not yet really tested.

Callers not yet adjusted.

7 weeks agolibctf, include: debuggability improvements
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.

7 weeks agolibctf: ctf-lookup: support prefixes in ctf_lookup_by_id
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.

Callers not yet adjusted.

7 weeks agolibctf: simplify ctf_txlate
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.

7 weeks agolibctf: dynhash/dynset: a bit of const-correctness
Nick Alcock [Thu, 24 Apr 2025 13:06:38 +0000 (14:06 +0100)] 
libctf: dynhash/dynset: a bit of const-correctness

A pile of dynhash and dynset functions were requiring non-const hashes/sets
unnecessarily.  Fix them.

7 weeks agolibctf: ctf_next_t.ctn_size: make a size_t
Nick Alcock [Thu, 24 Apr 2025 13:04:39 +0000 (14:04 +0100)] 
libctf: ctf_next_t.ctn_size: make a size_t

Literally every single user would rather this is a size_t, rather
than an ssize_t.  Change it.

7 weeks agolibctf: adapt core dictops for v4 and prefix types
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.

7 weeks agolibctf: don't warn about unused fp in ctf_assert
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).

7 weeks agolibctf: split out compatibility code
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.)

7 weeks agoinclude, libctf, binutils: drop labels
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.)

7 weeks agoinclude, libctf: header and soname changes for CTFv4
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.

7 weeks agolibctf: don't include cv-quals or pointers in the name table
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.

7 weeks agotypes: add some more error checking
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...

7 weeks agoTiny stylistic spacing and comment tweaks
Nick Alcock [Thu, 27 Feb 2025 19:24:10 +0000 (19:24 +0000)] 
Tiny stylistic spacing and comment tweaks

7 weeks agolibctf: consecutive ctf_id_t assignment
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.

7 weeks agolibctf: fix ctf_type_pointer on parent dicts, etc
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.

WIP (complete, but not yet tested).

7 weeks agolibctf: don't call ctf_type_to_index with types in other dicts
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.

7 weeks agolibctf: move string deduplication into ctf-archive
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.

7 weeks agolibctf: document parameters to ctf_import
Nick Alcock [Sun, 16 Feb 2025 19:37:54 +0000 (19:37 +0000)] 
libctf: document parameters to ctf_import

One is a parent dict, one is a child: you shouldn't have to look at the
source to tell which is which.

include/
* ctf-api.h (ctf_import): Name parameters.

7 weeks agold, testsuite, ctf: really test -gctf even if the compiler warns
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.

7 weeks agolibctf: string: refs rework
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.

7 weeks agolibctf: create: fix vlen / vbytes confusion
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.

7 weeks agolibctf: de-macroize LCTF_TYPE_TO_INDEX / LCTF_INDEX_TO_TYPE
Nick Alcock [Tue, 4 Feb 2025 12:57:17 +0000 (12:57 +0000)] 
libctf: de-macroize LCTF_TYPE_TO_INDEX / LCTF_INDEX_TO_TYPE

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.

7 weeks agolibctf: make ctf_dynamic_type() the inverse of ctf_static_type()
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.

7 weeks agolibctf: drop LCTF_TYPE_ISPARENT/LCTF_TYPE_ISCHILD
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).

7 weeks agolibctf: generalize the ref system
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).

7 weeks agolibctf, string: remove movable refs properly
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.

7 weeks agolibctf, string: delete separate movable ref storage again
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.

7 weeks agolibctf, hash: add support for freeing functions taking an arg
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.

7 weeks agolibctf: move ctf_elf*_to_link_sym to ctf-link.c
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.

Move them into ctf-link.c where they belong.

7 weeks agolibctf: split up ctf-subr.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.

7 weeks agolibctf: dedup: describe 'citer'
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.

7 weeks agolibctf: fix obsolete comment
Nick Alcock [Mon, 5 Aug 2024 13:40:05 +0000 (14:40 +0100)] 
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.

7 weeks agolibctf: a little string sharing test
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.

7 weeks agolibctf: actually deduplicate the strtab
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.

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.

7 weeks agolibctf: dedup: add strtab deduplicator
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.

7 weeks agolibctf: do not deduplicate strings in the header
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!

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.

7 weeks agoinclude, libctf: string lookup and writeout of a parent-shared strtab
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.

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.

7 weeks agolibctf: tear opening and serialization in two
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.

7 weeks agoinclude, libctf: add cth_parent_strlen CTFv4 header field
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.

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.

7 weeks agolibctf: add mechanism to prohibit most operations without a strtab
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.

7 weeks agolibctf, archive, link: fix parent importing
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.

7 weeks agoinclude, libctf: start work on libctf v4
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).

7 weeks agos390: Do not generate incomplete opcode table
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.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
7 weeks agoSanity check elf_sym_hashes indexing
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.

7 weeks agoDon't read and cache local syms for gc-sections
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.

7 weeks ago_bfd_elf_get_link_hash_entry tidy
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.

7 weeks agoPass cookie and symndx to gc_mark_hook
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.

PR 33530
* elf-m10300.c (mn10300_elf_gc_mark_hook): Replace "rel" and "sym"
params with "cookie" and "symndx".  Adjust to suit.
* elf32-arm.c (elf32_arm_gc_mark_hook): Likewise.
* elf32-bfin.c (bfin_gc_mark_hook): Likewise.
* elf32-cris.c (cris_elf_gc_mark_hook): Likewise.
* elf32-csky.c (csky_elf_gc_mark_hook): Likewise.
* elf32-d10v.c (elf32_d10v_gc_mark_hook): Likewise.
* elf32-fr30.c (fr30_elf_gc_mark_hook): Likewise.
* elf32-frv.c (elf32_frv_gc_mark_hook): Likewise.
* elf32-hppa.c (elf32_hppa_gc_mark_hook): Likewise.
* elf32-iq2000.c (iq2000_elf_gc_mark_hook): Likewise.
* elf32-lm32.c (lm32_elf_gc_mark_hook): Likewise.
* elf32-m32r.c (m32r_elf_gc_mark_hook): Likewise.
* elf32-m68k.c (elf_m68k_gc_mark_hook): Likewise.
* elf32-mcore.c (mcore_elf_gc_mark_hook): Likewise.
* elf32-metag.c (elf_metag_gc_mark_hook): Likewise.
* elf32-microblaze.c (microblaze_elf_gc_mark_hook): Likewise.
* elf32-nds32.c (nds32_elf_gc_mark_hook): Likewise.
* elf32-or1k.c (or1k_elf_gc_mark_hook): Likewise.
* elf32-ppc.c (ppc_elf_gc_mark_hook): Likewise.
* elf32-s390.c (elf_s390_gc_mark_hook): Likewise.
* elf32-score.c (s3_bfd_score_elf_gc_mark_hook): Likewise.
(_bfd_score_elf_gc_mark_hook): Likewise.
* elf32-score7.c (s7_bfd_score_elf_gc_mark_hook): Likewise.
* elf32-sh.c (sh_elf_gc_mark_hook): Likewise.
* elf32-tilepro.c (tilepro_elf_gc_mark_hook): Likewise.
* elf32-v850.c (v850_elf_gc_mark_hook): Likewise.
* elf32-vax.c (elf_vax_gc_mark_hook): Likewise.
* elf32-visium.c (visium_elf_gc_mark_hook): Likewise.
* elf32-xstormy16.c (xstormy16_elf_gc_mark_hook): Likewise.
* elf32-xtensa.c (elf_xtensa_gc_mark_hook): Likewise.
* elf64-alpha.c (elf64_alpha_gc_mark_hook): Likewise.
* elf64-mmix.c (mmix_elf_gc_mark_hook): Likewise.
* elf64-ppc.c (ppc64_elf_gc_mark_hook): Likewise.
* elf64-s390.c (elf_s390_gc_mark_hook): Likewise.
* elfnn-loongarch.c (loongarch_elf_gc_mark_hook): Likewise.
* elfxx-mips.c (_bfd_mips_elf_gc_mark_hook): Likewise.
* elfxx-sparc.c (_bfd_sparc_elf_gc_mark_hook): Likewise.
* elfxx-tilegx.c (tilegx_elf_gc_mark_hook): Likewise.
* elfxx-x86.c (_bfd_x86_elf_gc_mark_hook): Likewise.
* elflink.c (_bfd_elf_gc_mark_hook): Likewise.
(elf_gc_mark_debug_section): Likewise.
(_bfd_elf_gc_mark_rsec): Adjust gc_mark_hook calls.
* elf32-cr16.c (elf32_cr16_gc_mark_hook): Delete.
(elf_backend_gc_mark_hook): Don't define.
* elf32-moxie.c (moxie_elf_gc_mark_hook): Delete.
(elf_backend_gc_mark_hook): Don't define.
* elf-bfd.h (elf_gc_mark_hook_fn, _bfd_elf_gc_mark_hook): Update
declarations.
* elf32-score.h (s7_bfd_score_elf_gc_mark_hook): Likewise.
* elfxx-mips.h (_bfd_mips_elf_gc_mark_hook): Likewise.
* elfxx-sparc.h (_bfd_sparc_elf_gc_mark_hook): Likewise.
* elfxx-tilegx.h (tilegx_elf_gc_mark_hook): Likewise.
* elfxx-x86.h (_bfd_x86_elf_gc_mark_hook): Likewise.

7 weeks agoobjcopy: add option to specify custom prefix for symbol of binary input
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.

Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
7 weeks agoAutomatic date update in version.in
GDB Administrator [Thu, 30 Oct 2025 00:00:15 +0000 (00:00 +0000)] 
Automatic date update in version.in

7 weeks agogdb/testsuite: fix git repository check in gdb.src/pre-commit.exp
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.

Approved-By: Kevin Buettner <kevinb@redhat.com>
7 weeks agox86: Disable AMX-TRANSPOSE by default
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.

gas/ChangeLog:

* testsuite/gas/i386/x86-64-amx-movrs-intel.d:
Move AMX-TRANSPOSE part to AMX-TRANSPOSE test.
* testsuite/gas/i386/x86-64-amx-movrs.d: Ditto.
* testsuite/gas/i386/x86-64-amx-movrs.s: Ditto.
* testsuite/gas/i386/x86-64-amx-tf32-bad.d: Ditto.
* testsuite/gas/i386/x86-64-amx-tf32-bad.s: Ditto.
* testsuite/gas/i386/x86-64-amx-tf32-intel.d: Ditto.
* testsuite/gas/i386/x86-64-amx-tf32-inval.l: Ditto.
* testsuite/gas/i386/x86-64-amx-tf32-inval.s: Ditto.
* testsuite/gas/i386/x86-64-amx-tf32.d: Ditto.
* testsuite/gas/i386/x86-64-amx-tf32.s: Ditto.
* testsuite/gas/i386/x86-64-apx-evex-promoted-intel.d: Ditto.
* testsuite/gas/i386/x86-64-apx-evex-promoted-wig.d: Ditto.
* testsuite/gas/i386/x86-64-apx-evex-promoted.d: Ditto.
* testsuite/gas/i386/x86-64-apx-evex-promoted.s: Ditto.
* testsuite/gas/i386/x86-64-amx-movrs-inval.l: Move
AMX-TRANSPOSE part to AMX-TRANSPOSE file. Remove
noamx_transpose test.
* testsuite/gas/i386/x86-64-amx-movrs-inval.s: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose-bad.d:
Add AMX-MOVRS and AMX-TF32 related test.
* testsuite/gas/i386/x86-64-amx-transpose-bad.s: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose-intel.d: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose-inval.l: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose-inval.s: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose.d: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose.s: Ditto.
* testsuite/gas/i386/x86-64.exp: Remove AMX-MOVRS invalid test.
* testsuite/gas/i386/x86-64-amx-transpose-apx-intel.d:
New test originally comes from APX_F test.
* testsuite/gas/i386/x86-64-amx-transpose-apx-wig.d: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose-apx.d: Ditto.
* testsuite/gas/i386/x86-64-amx-transpose-apx.s: Ditto.

opcodes/ChangeLog:

* i386-gen.c: Disable AMX-TRANSPOSE by default.
* i386-init.h: Regenerated.

7 weeks agoRevert "x86/APX: drop AMX-TRANSPOSE promoted insns"
Haochen Jiang [Fri, 24 Oct 2025 02:53:21 +0000 (10:53 +0800)] 
Revert "x86/APX: drop AMX-TRANSPOSE promoted insns"

This reverts commit bafcf0823c1ae4c2201670225c9cf14ccf2abc67.

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.

7 weeks agoAutomatic date update in version.in
GDB Administrator [Wed, 29 Oct 2025 00:00:41 +0000 (00:00 +0000)] 
Automatic date update in version.in

7 weeks agogdb/solib-rocm: avoid expensive gdbarch_from_bfd call in rocm_solib_relocate_section_...
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)
7 weeks agoFix typo in break-kernel-no-debug-info.exp
Tom Tromey [Tue, 28 Oct 2025 15:53:17 +0000 (09:53 -0600)] 
Fix typo in break-kernel-no-debug-info.exp

pre-commit / codespell pointed out a typo in
break-kernel-no-debug-info.exp.  This patch fixes it.

7 weeks agoEmit language and encoding names from dwarf-to-dwarf-assembler
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.

Approved-By: Andrew Burgess <aburgess@redhat.com>
7 weeks agoUpdate "usage" line in dwarf-to-dwarf-assembler
Tom Tromey [Wed, 22 Oct 2025 13:37:01 +0000 (07:37 -0600)] 
Update "usage" line in dwarf-to-dwarf-assembler

This changes the "usage" text in dwarf-to-dwarf-assembler to be a bit
more GNU-like.  It also fixes the name used in the message.

Approved-By: Andrew Burgess <aburgess@redhat.com>
7 weeks agoFix formatting of attributes in dwarf-to-dwarf-assembler output
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).

Approved-By: Andrew Burgess <aburgess@redhat.com>
7 weeks agogdb: assign a valid section in convert_address_location_to_sals
Sébastien Darche [Thu, 16 Oct 2025 21:01:10 +0000 (17:01 -0400)] 
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

7 weeks agogdb: pass minsym section to find_function_start_sal, when possible
Sébastien Darche [Fri, 3 Oct 2025 13:18:30 +0000 (09:18 -0400)] 
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

7 weeks agogdb: make find_sal_for_pc_sect attempt to fill sal section
Sébastien Darche [Fri, 3 Oct 2025 12:47:55 +0000 (08:47 -0400)] 
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

7 weeks agogdb: lookup minsym using section in find_sal_for_pc_sect
Sébastien Darche [Mon, 20 Oct 2025 19:07:33 +0000 (15:07 -0400)] 
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

7 weeks agoPowerPC: Support for Load/Store VSX Vector Paired Byte*32 Indexed (RFC02678)
Abhay Kandpal [Tue, 28 Oct 2025 12:33:01 +0000 (07:33 -0500)] 
PowerPC: Support for Load/Store VSX Vector Paired Byte*32 Indexed (RFC02678)

opcodes/
* ppc-opc.c (powerpc_opcodes): Add lxvpb32x, stxvpb32x.

gas/
* testsuite/gas/ppc/future.s: New test.
* testsuite/gas/ppc/future.d: Likewise.

7 weeks agoaarch64: gas: Allow movprfx with fmmla and bfscale [PR gas/33562]
Alfie Richards [Thu, 23 Oct 2025 09:45:22 +0000 (09:45 +0000)] 
aarch64: gas: Allow movprfx with fmmla and bfscale [PR gas/33562]

These instructions were previously incorrectly marked as not accepting
movprfx.  Fix this and add tests.

PR gas/33562

opcodes:
* aarch64-tbl.h: Update widening fmmmla and bfscale instructions.
gas:
* testsuite/gas/aarch64/f8f16mm_sve2-bad.l: Update test with movprfx.
* testsuite/gas/aarch64/f8f16mm_sve2.d: Ditto.
* testsuite/gas/aarch64/f8f16mm_sve2.s: Ditto.
* testsuite/gas/aarch64/f8f32mm_sve2-bad.l: Ditto.
* testsuite/gas/aarch64/f8f32mm_sve2.d: Ditto.
* testsuite/gas/aarch64/f8f32mm_sve2.s: Ditto.
* testsuite/gas/aarch64/sve-f16f32mm-bad.l: Ditto.
* testsuite/gas/aarch64/sve-f16f32mm.d: Ditto.
* testsuite/gas/aarch64/sve-f16f32mm.s: Ditto.
* testsuite/gas/aarch64/sve-bfscale-sve2.s: Ditto.
* testsuite/gas/aarch64/sve-bfscale-sve2.d: Ditto.

Approved-By: Alice Carlotti <alice.carlotti@arm.com>
7 weeks agoAutomatic date update in version.in
GDB Administrator [Tue, 28 Oct 2025 00:01:01 +0000 (00:01 +0000)] 
Automatic date update in version.in