Commit Graph

63 Commits

Author SHA1 Message Date
Nick Alcock
4a355ed5cb libctf: dedup: preserve non-root flag across normal links
The previous commits dropped preservation of the non-root flag in ctf_link
and arranged to use it somewhat differently to track conflicting types in
cu-mapped CUs when doing cu-mapped links.  This was necessary to prevent
entirely spuriously hidden types from appearing on the output of such links.

Bring it (and the test for it) back.  The problem with the previous design
was that it implicitly assumed that the non-root flag it saw on the input
was always meant to be preserved (when in the final phase of cu-mapped links
it merely means that conflicting types were found in intermediate links),
and also that it could figure out what the non-root flag on the input was by
sucking in the non-root flag of the input type corresponding to an output in
the output mapping (which maps type hashes to a corresponding type on some
input).

This method of getting properties of the input type *does* work *if* that
property was one of those hashed by the ctf_dedup_hash_type process.  In
that case, every type with a given hash will have the same value for all
hashed-in properties, so it doesn't matter which one is consulted (the
output mapping points at an arbitrary one of those input types).  But the
non-root flag is explicitly *not* hashed in: as a comment in
ctf_dedup_rhash_type notes, being non-root is not a property of a type, and
two types (one non-root, one not) can perfectly well be the same type even
though one is visible and one isn't.  So just copying the non-root flag from
the output mapping's idea of the input type will copy in a value that is not
stabilized by the hash, so is more-or-less random!

So we cannot do that.  We have to do something else, which means we have to
decide what to do if two identical types with different nonroot flag values
pop up.  The most sensible thing to do is probably to say that if all
instances of a type are non-root-visible, the linked output should also be
non-root-visible: any root-visible types in that set, and the output type is
root-visible again.

We implement this with a new cd_nonroot_consistency dynhash, which maps type
hashes to the value 0 ("all instances root-visible"), 1 ("all instances
non-root-visible") or 2 ("inconsistent").  After hashing is over, we save a
bit of memory by deleting everything from this hashtab that doesn't have a
value of 1 ("non-root-visible"), then use this to decide whether to emit any
given type as non-root-visible or not.

However... that's not quite enough.  In cu-mapped links, we want to
disregard this whole thing because we just hide everything -- but in phase
2, when we take the smushed-together CUs resulting from phase 1 and
deduplicate them against each other, we want to do what the previous commits
implemented and ignore the non-root flag entirely, instead falling back to
preventing clashes by hiding anything that would be considered conflicting.
We extend the existing cu_mapped parameter to various bits of ctf_dedup so
that it is now tristate: 0 means a normal link, 1 means the smush-it-
together phase of cu-mapped links, and 2 means the final phase of cu-mapped
links.  We do the hide-conflicting stuff only in phase 2, meaning that
normal links by GNU ld can always respect the value of the nonroot flag put
on types in the input.

(One extra thing added as part of this: you can now efficiently delete the
last value returned by ctf_dynhash_next() by calling
ctf_dynhash_next_remove.)

We bring back the ctf-nonroot-linking test with one tweak: linking now works
on mingw as long as you're using the ucrt libc, so re-enable it for better
test coverage on that platform.

libctf/
	PR libctf/33047
	* ctf-hash.c (ctf_dynhash_next_remove): New.
	* ctf-impl.h (struct ctf_dedup) [cd_nonroot_consistency]: New.
	* ctf-link.c (ctf_link_deduplicating):  Differentiate between
	cu-mapped and non-cu-mapped links, even in the final phase.
	* ctf-dedup.c (ctf_dedup_hash_type): Callback prototype addition.
	Get the non-root flag and pass it down.
	(ctf_dedup_rhash_type): Callback prototype addition. Document
	restrictions on use of the nonroot flag.
	(ctf_dedup_populate_mappings): Populate cd_nonroot_consistency.
	(ctf_dedup_hash_type_fini): New function: delete now-unnecessary
	values from cd_nonroot_consistency.
	(ctf_dedup_init): Initialize it.
	(ctf_dedup_fini): Destroy it.
	(ctf_dedup): cu_mapping is now cu_mapping_phase.  Call
	ctf_dedup_hash_type_fini.
	(ctf_dedup_emit_type): Use cu_mapping_phase and
	cd_nonroot_consistency to propagate the non-root flag into outputs
	for normal links, and to do name-based conflict checking only for
	phase 2 of cu-mapped links.
	(ctf_dedup_emit): cu_mapping is now cu_mapping_phase.  Adjust
	assertion accordingly.
	* testsuite/libctf-writable/ctf-nonroot-linking.c: Bring back.
	* testsuite/libctf-writable/ctf-nonroot-linking.lk: Likewise.
2025-06-26 15:49:11 +01:00
Nick Alcock
13c3c2087a Revert "libctf: fix linking of non-root-visible types"
This reverts commit 87b2f67310.

It is based on a misconception, that hidden types in the deduplicator
input should always be hidden in the output.  For cu-mapped links,
and final links following cu-mapped links, this is not true: we want
to hide inputs if they were conflicting on the output and no more.

We will reintroduce the testcase once a better fix is found.

libctf/
	PR libctf/33047
	* ctf-dedup.c (ctf_dedup_emit_type): Don't respect the nonroot flag.
	* testsuite/libctf-writable/ctf-nonroot-linking.c: Removed.
	* testsuite/libctf-writable/ctf-nonroot-linking.lk: Removed.
2025-06-25 12:27:06 +01:00
Nick Alcock
4bdc7aed03 libctf: testsuite fixes for datasec size changes 2025-05-20 14:35:37 +01:00
Nick Alcock
a9f8ddc5ae libctf: archive, open: when opening, always set errp to something
ctf_arc_import_parent, called by the cached-opening machinery used by
ctf_archive_next and archive-wide lookup functions like
ctf_arc_lookup_symbol, has an err-pointer parameter like all other opening
functions.  Unfortunately it unconditionally initializes it whenever
provided, even if there was no error, which can lead to its being
initialized to an uninitialized value.  This is not technically an
API-contract violation, since we don't define what happens to the error
value except when an error happens, but it is still unpleasant.

Initialize it only when there is an actual error, so we never initialize it
to an uninitialized value.

While we're at it, improve all the opening pathways: on success, set errp to
0, rather than leaving it what it was, reducing the likelihood of
uninitialized error param returns in callers too.  (This is inconsistent
with the treatment of ctf_errno(), but the err value being a parameter
passed in from outside makes the divergence acceptable: in open functions,
you're never going to be overwriting some old error value someone might want
to keep around across multiple calls, some of which are successful and some
of which are not.)

Soup up existing tests to verify all this.

Thanks to Bruce McCulloch for the original patch, and Stephen Brennan for
the report.

libctf/
	PR libctf/32903
	* ctf-archive.c (ctf_arc_open_internal): Zero errp on success.
	(ctf_dict_open_sections): Zero errp at the start.
	(ctf_arc_import_parent): Intialize err.
	* ctf-open.c (ctf_bufopen): Zero errp at the start.
	* testsuite/libctf-lookup/add-to-opened.c: Make sure one-element
	archive opens update errp.
	* testsuite/libctf-writable/ctf-compressed.c: Make sure real archive
	opens update errp.
2025-05-20 14:34:55 +01:00
Nick Alcock
4a4fbfd42e libctf: by-kind tests
These tiny testcases test opening-and-dumping of single type kinds,
and also linking and then opening-and-dumping.
2025-04-25 21:50:14 +01:00
Nick Alcock
66bc737718 libctf: run_lookup_test: force BTF emission (NOT FOR UPSTREAMING)
Pro tem as a hack until GCC supports -gctf for v4, or v3 upgrading
is supported, or direct CTF-then-BTF tests are written, just emit
BTF for test purposes.

This breaks most of the tests: DO NOT UPSTREAM.
2025-04-25 21:49:22 +01:00
Nick Alcock
0ad8ddc8b4 libctf: run_lookup_test: support per-test options
This lets you say e.g.

    run_lookup_test [file rootname $ctf_test ] {link: on}

to turn on the {link: on} option for all tests, as if specified in every
test file.
2025-04-25 21:48:22 +01:00
Nick Alcock
b5d3790c66 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.
2025-03-16 15:25:27 +00:00
Nick Alcock
5a1d8eca5c libctf: fix slices of slices and of enums
Slices had a bunch of horrible usability problems.  In particular, while
towers of cv-quals are resolved away by functions that need to do it, towers
of cv-quals with slices in the middle are not resolved away by functions
like ctf_enum_value that can see through slices: resolving volatile -> slice
-> const -> enum will leave it with a 'const', which will error pointlessly,
annoying callers, who reasonably expect slices to be more invisible than
this.  (The user-callable ctf_type_resolve still does not resolve away
slices, because this is the only way users can see that the slices are there
at all.)

This is induced by a fix for another wart: ctf_add_enumerator does not
resolve anything away at all, so you can't even add enumerators to const or
volatile enums -- and more problematically, you can't add enumerators to
enums with an explicit encoding without resolving away the types by hand,
since ctf_add_enum_encoded works by returning a slice!  ctf_add_enumerator
now resolves away all of those, so any cvr-or-typedef-or-slice-qual
terminating in an enum can be added to, exactly as callers likely expect.

(New tests added.)

libctf/
	* ctf-create.c (ctf_add_enumerator): Resolve away cvr-qualness.
	* ctf-types.c (ctf_type_resolve_unsliced): Don't terminate at
	the first slice.
	* testsuite/libctf-writable/slice-of-slice.*: New test.
2025-02-28 15:13:24 +00:00
Nick Alcock
a480362d88 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.
2025-02-28 15:13:24 +00:00
Alan Modra
e8e7cf2abe Update year range in copyright notice of binutils files 2025-01-01 18:29:57 +10:30
Frank Ch. Eigler
4eb048d448 binutils testsuite: canonicalize subtest names in libctf
Previous code included the full $srcdir pathnames in the individual
subtest PASS/FAIL names, which makes it difficult to compute
comparisons or regressions between test runs on different machines.
This version switches to the basename only, which are common.

Signed-off-by: Frank Ch. Eigler <fche@redhat.com>
2024-09-24 21:50:41 -04:00
Nick Alcock
6da9267482 libctf, include: add ctf_dict_set_flag: less enum dup checking by default
The recent change to detect duplicate enum values and return ECTF_DUPLICATE
when found turns out to perturb a great many callers.  In particular, the
pahole-created kernel BTF has the same problem we historically did, and
gleefully emits duplicated enum constants in profusion.  Handling the
resulting duplicate errors from BTF -> CTF converters reasonably is
unreasonably difficult (it amounts to forcing them to skip some types or
reimplement the deduplicator).

So let's step back a bit.  What we care about mostly is that the
deduplicator treat enums with conflicting enumeration constants as
conflicting types: programs that want to look up enumeration constant ->
value mappings using the new APIs to do so might well want the same checks
to apply to any ctf_add_* operations they carry out (and since they're
*using* the new APIs, added at the same time as this restriction was
imposed, there is likely to be no negative consequence of this).

So we want some way to allow processes that know about duplicate detection
to opt into it, while allowing everyone else to stay clear of it: but we
want ctf_link to get this behaviour even if its caller has opted out.

So add a new concept to the API: dict-wide CTF flags, set via
ctf_dict_set_flag, obtained via ctf_dict_get_flag.  They are not bitflags
but simple arbitrary integers and an on/off value, stored in an unspecified
manner (the one current flag, we translate into an LCTF_* flag value in the
internal ctf_dict ctf_flags word). If you pass in an invalid flag or value
you get a new ECTF_BADFLAG error, so the caller can easily tell whether
flags added in future are valid with a particular libctf or not.

We check this flag in ctf_add_enumerator, and set it around the link
(including on child per-CU dicts).  The newish enumerator-iteration test is
souped up to check the semantics of the flag as well.

The fact that the flag can be set and unset at any time has curious
consequences. You can unset the flag, insert a pile of duplicates, then set
it and expect the new duplicates to be detected, not only by
ctf_add_enumerator but also by ctf_lookup_enumerator.  This means we now
have to maintain the ctf_names and conflicting_enums enum-duplication
tracking as new enums are added, not purely as the dict is opened.
Move that code out of init_static_types_internal and into a new
ctf_track_enumerator function that addition can also call.

(None of this affects the file format or serialization machinery, which has
to be able to handle duplicate enumeration constants no matter what.)

include/
	* ctf-api.h (CTF_ERRORS) [ECTF_BADFLAG]: New.
	(ECTF_NERR): Update.
	(CTF_STRICT_NO_DUP_ENUMERATORS): New flag.
	(ctf_dict_set_flag): New function.
	(ctf_dict_get_flag): Likewise.

libctf/
	* ctf-impl.h (LCTF_STRICT_NO_DUP_ENUMERATORS): New flag.
	(ctf_track_enumerator): Declare.
	* ctf-dedup.c (ctf_dedup_emit_type): Set it.
	* ctf-link.c (ctf_create_per_cu): Likewise.
	(ctf_link_deduplicating_per_cu): Likewise.
	(ctf_link): Likewise.
	(ctf_link_write): Likewise.
	* ctf-subr.c (ctf_dict_set_flag): New function.
	(ctf_dict_get_flag): New function.
	* ctf-open.c (init_static_types_internal): Move enum tracking to...
	* ctf-create.c (ctf_track_enumerator): ... this new function.
	(ctf_add_enumerator): Call it.
	* libctf.ver: Add the new functions.
	* testsuite/libctf-lookup/enumerator-iteration.c: Test them.
2024-07-31 21:02:05 +01:00
Nick Alcock
36c771b179 libctf: fix CTF dict compression
Commit 483546ce4f ("libctf: make ctf_serialize() actually serialize")
accidentally broke dict compression.  There were two bugs:

 - ctf_arc_write_one_ctf was still making its own decision about
   whether to compress the dict via direct ctf_size comparison, which is
   unfortunate because now that it no longer calls ctf_serialize itself,
   ctf_size is always zero when it does this: it should let the writing
   functions decide on the threshold, which they contain code to do which is
   simply not used for lack of one trivial wrapper to write to an fd and
   also provide a compression threshold

 - ctf_write_mem, the function underlying all writing as of the commit
   above, was calling zlib's compressBound and avoiding compression if this
   returned a value larger than the input.  Unfortunately compressBound does
   not do a trial compression and determine whether the result is
   compressible: it just adds zlib header sizes to the value passed in, so
   our test would *always* have concluded that the value was incompressible!
   Avoid by simply always compressing if the raw size is larger than the
   threshold: zlib is quite clever enough to avoid actually compressing
   if the data is incompressible.

Add a testcase for this.

libctf/
	* ctf-impl.h (ctf_write_thresholded): New...
	* ctf-serialize.c (ctf_write_thresholded): ... defined here,
        a wrapper around...
        (ctf_write_mem): ... this.  Don't check compressibility.
	(ctf_compress_write): Reimplement as a ctf_write_thresholded
        wrapper.
	(ctf_write): Likewise.
	* ctf-archive.c (arc_write_one_ctf): Just call
        ctf_write_thresholded rather than trying to work out whether
        to compress.
	* testsuite/libctf-writable/ctf-compressed.*: New test.
2024-07-31 21:02:05 +01:00
Nick Alcock
87b2f67310 libctf: fix linking of non-root-visible types
If you deduplicate non-root-visible types, the resulting type should still
be non-root-visible! We were promoting all such types to root-visible, and
re-demoting them only if their names collided (which might happen on
cu-mapped links if multiple compilation units with conflicting types are
fused into one child dict).

This "worked" before now, in that linking at least didn't fail (if you don't
mind having your non-root flag value destroyed if you're adding
non-root-visible types), but now that conflicting enumerators cause their
containing enums to become conflicted (enums which might have *different
names*), this caused the linker to crash when it hit two enumerators with
conflicting values.

Not testable in ld because cu-mapped links are not exposed to ld, but can be
tested via direct creation of libraries and calls to ctf_link directly.
(This also tests the ctf_dump non-root type printout, which before now
was untested.)

libctf/
	* ctf-dedup.c (ctf_dedup_emit_type): Non-root-visible input types
	should be emitted as non-root-visible output types.
	* testsuite/libctf-writable/ctf-nonroot-linking.c: New test.
	* testsuite/libctf-writable/ctf-nonroot-linking.lk: New test.
2024-07-31 21:02:05 +01:00
Nick Alcock
b84ffc176d libctf: fix testsuite bugs revealed by -Wall
Most of these are harmless, but some of the type confusions and especially
a missing ctf_strerror() on an error path were actual bugs that could
have resulted in test failures crashing rather than printing an error
message.

libctf/
	* testsuite/libctf-lookup/enumerator-iteration.c: Fix type
        confusion, signedness confusion and a missing ctf_errmsg().
	* testsuite/libctf-regression/libctf-repeat-cu-main.c: Return 0 from
        the test function.
	* testsuite/libctf-regression/open-error-free.c: Fix signedness
        confusion.
	* testsuite/libctf-regression/zrewrite.c: Remove unused label.
2024-06-19 15:51:24 +01:00
Nick Alcock
2fa4b6e6df libctf, include: new functions for looking up enumerators
Three new functions for looking up the enum type containing a given
enumeration constant, and optionally that constant's value.

The simplest, ctf_lookup_enumerator, looks up a root-visible enumerator by
name in one dict: if the dict contains multiple such constants (which is
possible for dicts created by older versions of the libctf deduplicator),
ECTF_DUPLICATE is returned.

The next simplest, ctf_lookup_enumerator_next, is an iterator which returns
all enumerators with a given name in a given dict, whether root-visible or
not.

The most elaborate, ctf_arc_lookup_enumerator_next, finds all
enumerators with a given name across all dicts in an entire CTF archive,
whether root-visible or not, starting looking in the shared parent dict;
opened dicts are cached (as with all other ctf_arc_*lookup functions) so
that repeated use does not incur repeated opening costs.

All three of these return enumerator values as int64_t: unfortunately, API
compatibility concerns prevent us from doing the same with the other older
enum-related functions, which all return enumerator constant values as ints.
We may be forced to add symbol-versioning compatibility aliases that fix the
other functions in due course, bumping the soname for platforms that do not
support such things.

ctf_arc_lookup_enumerator_next is implemented as a nested ctf_archive_next
iterator, and inside that, a nested ctf_lookup_enumerator_next iterator
within each dict.  To aid in this, add support to ctf_next_t iterators for
iterators that are implemented in terms of two simultaneous nested iterators
at once.  (It has always been possible for callers to use as many nested or
semi-overlapping ctf_next_t iterators as they need, which is one of the
advantages of this style over the _iter style that calls a function for each
thing iterated over: the iterator change here permits *ctf_next_t iterators
themselves* to be implemented by iterating using multiple other iterators as
part of their internal operation, transparently to the caller.)

Also add a testcase that tests all these functions (which is fairly easy
because ctf_arc_lookup_enumerator_next is implemented in terms of
ctf_lookup_enumerator_next) in addition to enumeration addition in
ctf_open()ed dicts, ctf_add_enumerator duplicate enumerator addition, and
conflicting enumerator constant deduplication.

include/
	* ctf-api.h (ctf_lookup_enumerator): New.
	(ctf_lookup_enumerator_next): Likewise.
	(ctf_arc_lookup_enumerator_next): Likewise.

libctf/
	* libctf.ver: Add them.
	* ctf-impl.h (ctf_next_t) <ctn_next_inner>: New.
	* ctf-util.c (ctf_next_copy): Copy it.
        (ctf_next_destroy): Destroy it.
	* ctf-lookup.c (ctf_lookup_enumerator): New.
	(ctf_lookup_enumerator_next): New.
	* ctf-archive.c (ctf_arc_lookup_enumerator_next): New.
	* testsuite/libctf-lookup/enumerator-iteration.*: New test.
	* testsuite/libctf-lookup/enum-ctf-2.c: New test CTF, used by the
	  above.
2024-06-18 13:20:32 +01:00
Nick Alcock
9f0fb75b8e libctf: suppress spurious failure of malloc-counting tests under valgrind
The libctf-regression/open-error-free.c test works by interposing malloc
and counting mallocs and frees across libctf operations.  This only
works under suitably-interposable mallocs on systems supporting
dlsym (RTLD_NEXT, ...), so its operation is restricted to glibc
systems for now, but also it interacts badly with valgrind, which
interposes malloc itself.  Detect a running valgrind and skip the test.

Add new facilities allowing libctf lookup tests to declare themselves
unsupported, by printing "UNSUPPORTED: " and then some meaningful
message instead of their normal output.

libctf/
	* configure.ac: Check for <valgrind/valgrind.h>.
	* config.h.in: Regenerate.
	* configure: Likewise.
	* testsuite/lib/ctf-lib.exp (run_lookup_test): Add support for
	UNSUPPORTED tests.
	* testsuite/libctf-regression/open-error-free.c: When running
	under valgrind, this test is unsupported.
2024-06-18 13:20:32 +01:00
A. Wilcox
7065d0a33f PR 31882 libctf: test suite incorrect format specifiers 2024-06-12 13:16:27 +09:30
Alan Modra
4ce8b69ddd libctf testsuite compilation failure
* testsuite/libctf-regression/open-error-free.c (main): Correct
	format length modifier.
2024-05-23 08:11:12 +09:30
Nick Alcock
37ed36fc8b libctf: fix leak of entire dict when dict opening fails
Ever since commit 1fa7a0c24e ("libctf: sort out potential refcount
loops") ctf_dict_close has only freed anything if the refcount on entry
to the function is precisely 1.  >1 obviously just decrements the
refcount, but the linker machinery can sometimes cause freeing to recurse
from a dict to another dict and then back to the first dict again, so
we interpret a refcount of 0 as an indication that this is a recursive call
and we should just return, because a caller is already freeing this dict.

Unfortunately there is one situation in which this is not true: the bad:
codepath in ctf_bufopen entered when opening fails.  Because the refcount is
bumped only at the very end of ctf_bufopen, any failure causes
ctf_dict_close to be entered with a refcount of zero, and it frees nothing
and we leak the entire dict.

The solution is to bump the refcount to 1 right before freeing... but this
codepath is clearly delicate enough that we need to properly validate it,
so we add a test that uses malloc interposition to count allocations and
frees, creates a dict, writes it out, intentionally corrupts it (by setting
a bunch of bytes after the header to a value high enough that it is
definitely not a valid CTF type kind), then tries to open it again and
counts the malloc/free pairs to make sure they're matched.  (Test run only
on *-linux-gnu, because malloc interposition is not a thing you can rely
upon working everywhere, and this test is not arch-dependent so if it
passes on one arch it can be assumed to pass on all of them.)

libctf/
	* ctf-open.c (ctf_bufopen): Bump the refcount on failure.
	* testsuite/libctf-regression/open-error-free.*: New test.
2024-05-17 12:58:18 +01:00
Nick Alcock
8c59ec7006 libctf: test: add wrapper
This .lk option lets you run the lookup program via a wrapper executable.
For example, to run under valgrind and check for leaks (albeit noisily
because of the libtool shell script wrapper):

libctf/
	* testsuite/lib/ctf-lib.exp (run_lookup_test): Add wrapper.
2024-05-17 12:58:18 +01:00
Nick Alcock
e449709833 libctf: test: add host
This .lk option lets you execute particular tests only on specific host
architectures.

libctf/
	* testsuite/lib/ctf-lib.exp (run_lookup_test): Add host.
2024-05-17 12:58:18 +01:00
Nick Alcock
26f0f80b6f libctf: test: add lookup_link
This .lk option lets you link the lookup program with extra libraries
in addition to -lctf.

libctf/
	* testsuite/lib/ctf-lib.exp (run_lookup_test): Add lookup_link.
2024-05-17 12:58:18 +01:00
Alan Modra
122f6f14b1 buffer overflow in libctf tests
* testsuite/libctf-regression/gzrewrite.c (main): Don't overflow
       "a" buffer in "after adding types" check.
       * testsuite/libctf-regression/zrewrite.c (main): Likewise.
2024-04-24 09:33:03 +09:30
Alan Modra
02fa4bbec1 Error compiling libctf-regression test
Seen on 64-bit targets.
ERROR: compilation of lookup program .../libctf-regression/gzrewrite.c failed

	* testsuite/libctf-regression/gzrewrite.c (main): Use %zu to
	print size_t values.
	* testsuite/libctf-regression/zrewrite.c (main): Likewise.
2024-04-20 10:36:37 +09:30
Nick Alcock
b5ac272b87 libctf: fix leak in test
This purely serves to make it easier to interpret valgrind output.
No functional effect.

libctf/
	* testsuite/libctf-lookup/conflicting-type-syms.c: Free everything.
2024-04-19 16:14:47 +01:00
Nick Alcock
3b5e2d0e8d libctf: add rewriting tests
Now there's a chance of it actually working, we can add more tests for
the long-broken dict read-and-rewrite cases.  This is the first ever
test for the (rarely-used, unpleasant, and until recently completely
broken) ctf_gzwrite function.

libctf/

	* testsuite/libctf-regression/gzrewrite*: New test.
	* testsuite/libctf-regression/zrewrite*: Likewise.
2024-04-19 16:14:47 +01:00
Nick Alcock
483546ce4f libctf: make ctf_serialize() actually serialize
ctf_serialize() evolved from the old ctf_update(), which mutated the
in-memory CTF dict to make all the dynamic in-memory types into static,
unchanging written-to-the-dict types (by deserializing and reserializing
it): back in the days when you could only do type lookups on static types,
this meant you could see all the types you added recently, at the small,
small cost of making it impossible to change those older types ever again
and inducing an amortized O(n^2) cost if you actually wanted to add
references to types you added at arbitrary times to later types.

It also reset things so that ctf_discard() would throw away only types you
added after the most recent ctf_update() call.

Some time ago this was all changed so that you could look up dynamic types
just as easily as static types: ctf_update() changed so that only its
visible side-effect of affecting ctf_discard() remained: the old
ctf_update() was renamed to ctf_serialize(), made internal to libctf, and
called from the various functions that wrote files out.

... but it was still working by serializing and deserializing the entire
dict, swapping out its guts with the newly-serialized copy in an invasive
and horrible fashion that coupled ctf_serialize() to almost every field in
the ctf_dict_t.  This is totally useless, and fixing it is easy: just rip
all that code out and have ctf_serialize return a serialized representation,
and let everything use that directly.  This simplifies most of its callers
significantly.

(It also points up another bug: ctf_gzwrite() failed to call ctf_serialize()
at all, so it would only ever work for a dict you just ctf_write_mem()ed
yourself, just for its invisible side-effect of serializing the dict!)

This lets us simplify away a bunch of internal-only open-side functionality
for overriding the syn_ext_strtab and some just-added functionality for
forcing in an existing atoms table, without loss of functionality, and lets
us lift the restriction on reserializing a dict that was ctf_open()ed rather
than being ctf_create()d: it's now perfectly OK to open a dict, modify it
(except for adding members to existing structs, unions, or enums, which
fails with -ECTF_RDONLY), and write it out again, just as one would expect.

libctf/

	* ctf-serialize.c (ctf_symtypetab_sect_sizes): Fix typos.
	(ctf_type_sect_size): Add static type sizes too.
	(ctf_serialize): Return the new dict rather than updating the
	existing dict.  No longer fail for dicts with static types;
	copy them onto the start of the new types table.
	(ctf_gzwrite): Actually serialize before gzwriting.
	(ctf_write_mem): Improve forced (test-mode) endian-flipping:
	flip dicts even if they are too small to be compressed.
	Improve confusing variable naming.
	* ctf-archive.c (arc_write_one_ctf): Don't bother to call
	ctf_serialize: both the functions we call do so.
	* ctf-string.c (ctf_str_create_atoms): Drop serializing case
	(atoms arg).
	* ctf-open.c (ctf_simple_open): Call ctf_bufopen directly.
	(ctf_simple_open_internal): Delete.
	(ctf_bufopen_internal): Delete/rename to ctf_bufopen: no
	longer bother with syn_ext_strtab or forced atoms table,
	serialization no longer needs them.
	* ctf-create.c (ctf_create): Call ctf_bufopen directly.
	* ctf-impl.h (ctf_str_create_atoms): Drop atoms arg.
	(ctf_simple_open_internal): Delete.
	(ctf_bufopen_internal): Likewise.
	(ctf_serialize): Adjust.
	* testsuite/libctf-lookup/add-to-opened.c: Adjust now that
	this is supposed to work.
2024-04-19 16:14:47 +01:00
Nick Alcock
8a60c93096 libctf: support addition of types to dicts read via ctf_open()
libctf has long declared deserialized dictionaries (out of files or ELF
sections or memory buffers or whatever) to be read-only: back in the
furthest prehistory this was not the case, in that you could add a
few sorts of type to such dicts, but attempting to do so often caused
horrible memory corruption, so I banned the lot.

But it turns out real consumers want it (notably DTrace, which
synthesises pointers to types that don't have them and adds them to the
ctf_open()ed dicts if it needs them). Let's bring it back again, but
without the memory corruption and without the massive code duplication
required in days of yore to distinguish between static and dynamic
types: the representation of both types has been identical for a few
years, with the only difference being that types as a whole are stored in
a big buffer for types read in via ctf_open and per-type hashtables for
newly-added types.

So we discard the internally-visible concept of "readonly dictionaries"
in favour of declaring the *range of types* that were already present
when the dict was read in to be read-only: you can't modify them (say,
by adding members to them if they're structs, or calling ctf_set_array
on them), but you can add more types and point to them.  (The API
remains the same, with calls sometimes returning ECTF_RDONLY, but now
they do so less often.)

This is a fairly invasive change, mostly because code written since the
ban was introduced didn't take the possibility of a static/dynamic split
into account.  Some of these irregularities were hard to define as
anything but bugs.

Notably:

 - The symbol handling was assuming that symbols only needed to be
   looked for in dynamic hashtabs or static linker-laid-out indexed/
   nonindexed layouts, but now we want to check both in case people
   added more symbols to a dict they opened.

 - The code that handles type additions wasn't checking to see if types
   with the same name existed *at all* (so you could do
   ctf_add_typedef (fp, "foo", bar) repeatedly without error).  This
   seems reasonable for types you just added, but we probably *do* want
   to ban addition of types with names that override names we already
   used in the ctf_open()ed portion, since that would probably corrupt
   existing type relationships.  (Doing things this way also avoids
   causing new errors for any existing code that was doing this sort of
   thing.)

 - ctf_lookup_variable entirely failed to work for variables just added
   by ctf_add_variable: you had to write the dict out and read it back
   in again before they appeared.

 - The symbol handling remembered what symbols you looked up but didn't
   remember their types, so you could look up an object symbol and then
   find it popping up when you asked for function symbols, which seems
   less than ideal.  Since we had to rejig things enough to be able to
   distinguish function and object symbols internally anyway (in order
   to give suitable errors if you try to add a symbol with a name that
   already existed in the ctf_open()ed dict), this bug suddenly became
   more visible and was easily fixed.

We do not (yet) support writing out dicts that have been previously read
in via ctf_open() or other deserializer (you can look things up in them,
but not write them out a second time).  This never worked, so there is
no incompatibility; if it is needed at a later date, the serializer is a
little bit closer to having it work now (the only table we don't deal
with is the types table, and that's because the upcoming CTFv4 changes
are likely to make major changes to the way that table is represented
internally, so adding more code that depends on its current form seems
like a bad idea).

There is a new testcase that tests much of this, in particular that
modification of existing types is still banned and that you can add new
ones and chase them without error.

libctf/

	* ctf-impl.h (struct ctf_dict.ctf_symhash): Split into...
	(ctf_dict.ctf_symhash_func): ... this and...
	(ctf_dict.ctf_symhash_objt): ... this.
	(ctf_dict.ctf_stypes): New, counts static types.
	(LCTF_INDEX_TO_TYPEPTR): Use it instead of CTF_RDWR.
	(LCTF_RDWR): Deleted.
	(LCTF_DIRTY): Renumbered.
	(LCTF_LINKING): Likewise.
	(ctf_lookup_variable_here): New.
	(ctf_lookup_by_sym_or_name): Likewise.
	(ctf_symbol_next_static): Likewise.
	(ctf_add_variable_forced): Likewise.
	(ctf_add_funcobjt_sym_forced): Likewise.
	(ctf_simple_open_internal): Adjust.
	(ctf_bufopen_internal): Likewise.
	* ctf-create.c (ctf_grow_ptrtab): Adjust a lot to start with.
	(ctf_create): Migrate a bunch of initializations into bufopen.
	Force recreation of name tables.  Do not forcibly override the
	model, let ctf_bufopen do it.
	(ctf_static_type): New.
	(ctf_update): Drop LCTF_RDWR check.
	(ctf_dynamic_type): Likewise.
	(ctf_add_function): Likewise.
	(ctf_add_type_internal): Likewise.
	(ctf_rollback): Check ctf_stypes, not LCTF_RDWR.
	(ctf_set_array): Likewise.
	(ctf_add_struct_sized): Likewise.
	(ctf_add_union_sized): Likewise.
	(ctf_add_enum): Likewise.
	(ctf_add_enumerator): Likewise (only on the target dict).
	(ctf_add_member_offset): Likewise.
	(ctf_add_generic): Drop LCTF_RDWR check.  Ban addition of types
	with colliding names.
	(ctf_add_forward): Note safety under the new rules.
	(ctf_add_variable): Split all but the existence check into...
	(ctf_add_variable_forced): ... this new function.
	(ctf_add_funcobjt_sym): Likewise...
	(ctf_add_funcobjt_sym_forced): ... for this new function.
	* ctf-link.c (ctf_link_add_linker_symbol): Ban calling on dicts
	with any stypes.
	(ctf_link_add_strtab): Likewise.
	(ctf_link_shuffle_syms): Likewise.
	(ctf_link_intern_extern_string): Note pre-existing prohibition.
	* ctf-lookup.c (ctf_lookup_by_id): Drop LCTF_RDWR check.
	(ctf_lookup_variable): Split out looking in a dict but not
	its parent into...
	(ctf_lookup_variable_here): ... this new function.
	(ctf_lookup_symbol_idx): Track whether looking up a function or
	object: cache them separately.
	(ctf_symbol_next): Split out looking in non-dynamic symtypetab
	entries to...
	(ctf_symbol_next_static): ... this new function.  Don't get confused
	by the simultaneous presence of static and dynamic symtypetab entries.
	(ctf_try_lookup_indexed):  Don't waste time looking up symbols by
	index before there can be any idea how symbols are numbered.
	(ctf_lookup_by_sym_or_name): Distinguish between function and
	data object lookups.  Drop LCTF_RDWR.
	(ctf_lookup_by_symbol): Adjust.
	(ctf_lookup_by_symbol_name): Likewise.
	* ctf-open.c (init_types): Rename to...
	(init_static_types): ... this.  Drop LCTF_RDWR.  Populate ctf_stypes.
	(ctf_simple_open): Drop writable arg.
	(ctf_simple_open_internal): Likewise.
	(ctf_bufopen): Likewise.
	(ctf_bufopen_internal): Populate fields only used for writable dicts.
	Drop LCTF_RDWR.
	(ctf_dict_close): Cater for symhash cache split.
	* ctf-serialize.c (ctf_serialize): Use ctf_stypes, not LCTF_RDWR.
	* ctf-types.c (ctf_variable_next): Drop LCTF_RDWR.
	* testsuite/libctf-lookup/add-to-opened*: New test.
2024-04-19 16:14:46 +01:00
Nick Alcock
2ba5ec13b2 libctf: fix name lookup in dicts containing base-type bitfields
The intent of the name lookup code was for lookups to yield non-bitfield
basic types except if none existed with a given name, and only then
return bitfield types with that name.  Unfortunately, the code as
written only does this if the base type has a type ID higher than all
bitfield types, which is most unlikely (the opposite is almost always
the case).

Adjust it so that what ends up in the name table is the highest-width
zero-offset type with a given name, if any such exist, and failing that
the first type with that name we see, no matter its offset.  (We don't
define *which* bitfield type you get, after all, so we might as well
just stuff in the first we find.)

Reported by Stephen Brennan <stephen.brennan@oracle.com>.

libctf/

	* ctf-open.c (init_types): Modify to allow some lookups during open;
	detect bitfield name reuse and prefer less bitfieldy types.
	* testsuite/libctf-writable/libctf-bitfield-name-lookup.*: New test.
2024-04-19 16:14:46 +01:00
Nick Alcock
9b9e262994 libctf: fix uninitialized variables in testsuite
Just because a path is an error path doesn't mean the program terminates
there if you don't ask it to.  And we don't want to -- but that means
we need to initialize the variables that are missed if an error happens to
*something*.  Type ID 0 (unimplemented) will do: it'll induce further
ECTF_BADID errors, but that's no bad thing.

libctf/ChangeLog:

	* testsuite/libctf-writable/libctf-errors.c: Initialize variables.
2024-03-11 17:16:12 +00:00
Alan Modra
fd67aa1129 Update year range in copyright notice of binutils files
Adds two new external authors to etc/update-copyright.py to cover
bfd/ax_tls.m4, and adds gprofng to dirs handled automatically, then
updates copyright messages as follows:

1) Update cgen/utils.scm emitted copyrights.
2) Run "etc/update-copyright.py --this-year" with an extra external
   author I haven't committed, 'Kalray SA.', to cover gas testsuite
   files (which should have their copyright message removed).
3) Build with --enable-maintainer-mode --enable-cgen-maint=yes.
4) Check out */po/*.pot which we don't update frequently.
2024-01-04 22:58:12 +10:30
Nick Alcock
cd4a8fc4f0 libctf: fix creation-time parent/child dict confusions
The fixes applied a few years ago to resolve confusions between parent and
child dicts at lookup time also apply in various forms to creation.  In
general, if you have a type in a parent dict ctf_imported into a child and
you do something to it, and the parent dict is writable (created via
ctf_create, not opened via ctf_open*) it should work just the same to make
changes to that type via a child dict as it does to make the change
to the parent dict directly -- and nothing you're prohibited from doing
to the parent dict when done directly should be allowed just because
you're doing it via a child.

Specifically, the following don't work when doing things from the child, but
should:

 - adding a member of a type in the parent to a struct or union in the
   parent via ctf_add_member or ctf_add_member_offset: this yields
   ECTF_BADID

 - adding a member of a type in the parent to a struct or union in the
   parent via ctf_add_member_encoded: this dumps core (!).

 - adding an enumerand to an enumerator in the parent: this yields
   ECTF_BADID

 - setting the properties of an array in the parent via ctf_set_array;
   this yields ECTF_BADID

Relatedly, some things work when doing things via a child that should fail,
yielding a CTF dictionary with invalid content (readable, but meaningless):
in particular, you can add a child type to a struct in the parent via
any of the ctf_add_member* family and nothing complains at all, even though
you should never be able to add references to children to parents (since any
given parent can be associated with many different children).

A family of tests is added to check each of these cases independently, since
some can result in coredumps and it would be nice to test the other cases
even if some dump core.  They use a common library to do all the actual
work.  The set of affected API calls was determined by code inspection
(auditing all calls to ctf_dtd_lookup): it's possible that I missed a few,
but I doubt it, since other cases use ctf_lookup* functions, which already
climb to the parent where appropriate.

libctf/ChangeLog:

	PR libctf/30985
	* ctf-create.c (ctf_dtd_lookup): Traverse to parents if necessary.
	(ctf_set_array): Likewise.  Report errors on the child; require
	both parent and child to be writable.
	(ctf_add_enumerator): Likewise.
	(ctf_add_member_offset): Likewise.  Prohibit addition of child types
	to structs in the parent.
	(ctf_add_member_encoded): Do not dereference a NULL dtd: report
	ECTF_BADID instead.
	* ctf-string.c (ctf_str_add_ref_internal): Report ENOMEM on the
	dict if addition of a string ref fails.
	* testsuite/libctf-writable/parent-child-dtd-crash-lib.c: New library.
	* testsuite/libctf-writable/parent-child-dtd-enum.*: New test.
	* testsuite/libctf-writable/parent-child-dtd-enumerator.*: New test.
	* testsuite/libctf-writable/parent-child-dtd-member-encoded.*: New test.
	* testsuite/libctf-writable/parent-child-dtd-member-offset.*: New test.
	* testsuite/libctf-writable/parent-child-dtd-set-array.*: New test.
	* testsuite/libctf-writable/parent-child-dtd-struct.*: New test.
	* testsuite/libctf-writable/parent-child-dtd-union.*: New test.
2023-10-20 18:09:54 +01:00
Nick Alcock
29736fc507 libctf: check for problems with error returns
We do this as a writable test because the only known-affected platforms
(with ssize_t longer than unsigned long) use PE, and we do not have support
for CTF linkage in the PE linker yet.

	PR libctf/30836
	* libctf/testsuite/libctf-writable/libctf-errors.*: New test.
2023-10-18 12:41:00 +01:00
Nick Alcock
d7474051e8 libctf: propagate errors from parents correctly
CTF dicts have per-dict errno values: as with other errno values these
are set on error and left unchanged on success.  This means that all
errors *must* set the CTF errno: if a call leaves it unchanged, the
caller is apt to find a previous, lingering error and misinterpret
it as the real error.

There are many places in libctf where we carry out operations on parent
dicts as a result of carrying out other user-requested operations on
child dicts (e.g. looking up information on a pointer to a type will
look up the type as well: the pointer might well be in a child and the
type it's a pointer to in the parent).  Those operations on the parent
might fail; if they do, the error must be correctly reflected on the
child that the user-visible operation was carried out on.  In many
places this was not happening.

So, audit and fix all those places.  Add tests for as many of those
cases as possible so they don't regress.

libctf/
	* ctf-create.c (ctf_add_slice): Use the original dict.
	* ctf-lookup.c (ctf_lookup_variable): Propagate errors.
	(ctf_lookup_symbol_idx): Likewise.
	* ctf-types.c (ctf_member_next): Likewise.
	(ctf_type_resolve_unsliced): Likewise.
	(ctf_type_aname): Likewise.
	(ctf_member_info): Likewise.
	(ctf_type_rvisit): Likewise.
	(ctf_func_type_info): Set the error on the right dict.
	(ctf_type_encoding): Use the original dict.
	* testsuite/libctf-writable/error-propagation.*: New test.
2023-04-08 16:07:17 +01:00
Nick Alcock
30a794e9f1 libctf, tests: do not assume host and target have identical field offsets
The newly-introduced libctf-lookup unnamed-field-info test checks
C compiler-observed field offsets against libctf-computed ones
by #including the testcase in the lookup runner as well as
generating CTF for it.  This only works if the host, on which
the lookup runner is compiled and executed, is the same architecture as
the target, for which the CTF is generated: when crossing, the trick
may fail.

So pass down an indication of whether this is a cross into the
testsuite, and add a new no_cross flag to .lk files that is used to
suppress test execution when a cross-compiler is being tested.

libctf/
	* Makefile.am (check_DEJAGNU): Pass down TEST_CROSS.
	* Makefile.in: Regenerated.
	* testsuite/lib/ctf-lib.exp (run_lookup_test): Use it to
	implement the new no_cross option.
	* testsuite/libctf-lookup/unnamed-field-info.lk: Mark as
	no_cross.
2023-04-08 16:07:17 +01:00
Nick Alcock
3672e32622 libctf: get the offsets of fields of unnamed structs/unions right
We were failing to add the offsets of the containing struct/union
in this case, leading to all offsets being relative to the unnamed
struct/union itself.

libctf/
	PR libctf/30264
	* ctf-types.c (ctf_member_info): Add the offset of the unnamed
	member of the current struct as necessary.
	* testsuite/libctf-lookup/unnamed-field-info*: New test.
2023-03-24 13:37:32 +00:00
Nick Alcock
e2dc08c6f0 libctf: skip the testsuite from inside dejagnu
The libctf testsuite uses Tcl try/catch to trap run_output errors.  This
is only supported in reasonably recent Tcls, so we detect the lack of
try/catch and suppress the testsuite via an Automake conditional in its
absence.

But this turns out not to work: Automake produces a check-DEJAGNU target
regardless of the value of this conditional and sticks it in an
unconditionally-executed part of the makefile, so the testsuite gets
executed anyway, and fails with a nasty-looking syntax error.  We can't
disable it by taking "dejagnu" out of AUTOMAKE_OPTIONS, because if you
do that Automake stops you using RUNTEST, RUNTESTFLAGS and other
variables users would expect to work.

So move to disabling the testsuite from inside the testsuite itself,
importing the value of the former Automake conditional as a Tcl variable
and exiting very early in default.exp if it's false.

	* configure.ac (TCL_TRY): No longer an Automake conditional.
	Rename to...
	(HAVE_TCL_TRY): ... this.
	* Makefile.am: Drop TCL_TRY.
	(development.exp): Set have_tcl_try.
	* testsuite/config/default.exp: Exit if have_tcl_try is false.

	* configure: Regenerated.
	* Makefile.in: Likewise.
2023-01-12 14:40:47 +00:00
Alan Modra
d87bef3a7b Update year range in copyright notice of binutils files
The newer update-copyright.py fixes file encoding too, removing cr/lf
on binutils/bfdtest2.c and ld/testsuite/ld-cygwin/exe-export.exp, and
embedded cr in binutils/testsuite/binutils-all/ar.exp string match.
2023-01-01 21:50:11 +10:30
Nick Alcock
6a8829ebb2 libctf: tests: prune warnings from compiler output
We were failing to call prune_warnings appropriately, leading to
false-positive test failures on some platforms (observed on
sparclinux).

libctf/ChangeLog:

	* testsuite/lib/ctf-lib.exp: Prune warnings from compiler and
	linker output.
	* testsuite/libctf-regression/libctf-repeat-cu.exp: Likewise,
	and ar output too.
2022-06-21 19:27:15 +01:00
Nick Alcock
6bd2318f32 libctf: fix linking together multiple objects derived from the same source
Right now, if you compile the same .c input repeatedly with CTF enabled
and different compilation flags, then arrange to link all of these
together, then things misbehave in various ways.  libctf may conflate
either inputs (if the .o files have the same name, say if they are
stored in different .a archives), or per-CU outputs when conflicting
types are found: the latter can lead to entirely spurious errors when
it tries to produce multiple per-CU outputs with the same name
(discarding all but the last, but then looking for types in the earlier
ones which have just been thrown away).

Fixing this is multi-pronged.  Both inputs and outputs need to be
differentiated in the hashtables libctf keeps them in: inputs with the
same cuname and filename need to be considered distinct as long as they
have different associated CTF dicts, and per-CU outputs need to be
considered distinct as long as they have different associated input
dicts.  Right now there is nothing tying the two together other than the
CU name: fix this by introducing a new field in the ctf_dict_t named
ctf_link_in_out, which (for input dicts) points to the associated per-CU
output dict (if any), and for output dicts points to the associated
input dict.  At creation time the name used is completely arbitrary:
it's only important that it be distinct if CTF dicts are distinct.  So,
when a clash is found, adjust the CU name by sticking the number of
elements in the input on the end.  At output time, the CU name will
appear in the linked object, so it matters a little more that it look
slightly less ugly: in conflicting cases, append an incrementing
integer, starting at 0.

This naming scheme is not very helpful, but it's hard to see what else
we can do.  The input .o name may be the same.  The input .a name is not
even visible to ctf_link, and even *that* might be the same, because
.a's can contain many members with the same name, all of which
participate in the link.  All we really know is that the two have
distinct dictionaries with distinct types in them, and at least this way
they are all represented, any any symbols, variables etc referring to
those types are accurately stored.

(As a side-effect this also fixes a use-after-free and double-free when
errors are found during variable or symbol emission.)

Use the opportunity to prevent a couple of sources of problems, to wit
changing the active CU mappings when a link has already been done
(no effect on ld, which doesn't use CU mappings at all), and causing
multiple consecutive ctf_link's to have the same net effect as just
doing the last one (no effect on ld, which only ever does one
ctf_link) rather than having the links be a sort of half-incremental
not-really-intended mess.

libctf/ChangeLog:

	PR libctf/29242
	* ctf-impl.h (struct ctf_dict) [ctf_link_in_out]: New.
	* ctf-dedup.c (ctf_dedup_emit_type): Set it.
	* ctf-link.c (ctf_link_add_ctf_internal): Set the input
	CU name uniquely when clashes are found.
	(ctf_link_add): Document what repeated additions do.
	(ctf_new_per_cu_name): New, come up with a consistent
	name for a new per-CU dict.
	(ctf_link_deduplicating): Use it.
	(ctf_create_per_cu): Use it, and ctf_link_in_out, and set
	ctf_link_in_out properly.  Don't overwrite per-CU dicts with
	per-CU dicts relating to different inputs.
	(ctf_link_add_cu_mapping): Prevent per-CU mappings being set up
	if we already have per-CU outputs.
	(ctf_link_one_variable): Adjust ctf_link_per_cu call.
	(ctf_link_deduplicating_one_symtypetab): Likewise.
	(ctf_link_empty_outputs): New, delete all the ctf_link_outputs
	and blank out ctf_link_in_out on the corresponding inputs.
	(ctf_link): Clarify the effect of multiple ctf_link calls.
	Empty ctf_link_outputs if it already exists rather than
	having the old output leak into the new link.  Fix a variable
	name.
	* testsuite/config/default.exp (AR): Add.
	(OBJDUMP): Likewise.
	* testsuite/libctf-regression/libctf-repeat-cu.exp: New test.
	* testsuite/libctf-regression/libctf-repeat-cu*: Main program,
	library, and expected results for the test.
2022-06-21 19:27:15 +01:00
Alan Modra
a2c5833233 Update year range in copyright notice of binutils files
The result of running etc/update-copyright.py --this-year, fixing all
the files whose mode is changed by the script, plus a build with
--enable-maintainer-mode --enable-cgen-maint=yes, then checking
out */po/*.pot which we don't update frequently.

The copy of cgen was with commit d1dd5fcc38ead reverted as that commit
breaks building of bfp opcodes files.
2022-01-02 12:04:28 +10:30
Nick Alcock
6ab5b6d0f3 libctf, lookup: fix bounds of pptrtab lookup
An off-by-one bug in the check for pptrtab lookup meant that we could
access the pptrtab past its bounds (*well* past its bounds),
particularly if we called ctf_lookup_by_name in a child dict with "*foo"
where "foo" is a type that exists in the parent but not the child and no
previous lookups by name have been carried out.  (Note that "*foo" is
not even a valid thing to call ctf_lookup_by_name with: foo * is.
Nonetheless, users sometimes do call ctf_lookup_by_name with invalid
content, and it should return ECTF_NOTYPE, not crash.)

ctf_pptrtab_len, as its name suggests (and as other tests of it in
ctf-lookup.c confirm), is one higher than the maximum valid permissible
index, so the comparison is wrong.

(Test added, which should fail pretty reliably in the presence of this
bug on any machine with 4KiB pages.)

libctf/ChangeLog
2021-09-27  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-lookup.c (ctf_lookup_by_name_internal): Fix pptrtab bounds.
	* testsuite/libctf-writable/pptrtab-writable-page-deep-lookup.*:
	New test.
2021-09-27 20:31:26 +01:00
Nick Alcock
e695879142 libctf, testsuite: fix various warnings in tests
These warnings are all off by default, but if they do fire you get
spurious ERRORs when running make check-libctf.

libctf/ChangeLog
2021-09-27  Nick Alcock  <nick.alcock@oracle.com>

	* testsuite/libctf-lookup/enum-symbol.c: Remove unused label.
	* testsuite/libctf-lookup/conflicting-type-syms.c: Remove unused
	variables.
	* testsuite/libctf-regression/pptrtab.c: Likewise.
	* testsuite/libctf-regression/type-add-unnamed-struct.c: Likewise.
	* testsuite/libctf-writable/pptrtab.c: Likewise.
	* testsuite/libctf-writable/reserialize-strtab-corruption.c:
	Likewise.
	* testsuite/libctf-regression/nonstatic-var-section-ld-r.c: Fix
	format string.
	* testsuite/libctf-regression/nonstatic-var-section-ld.c:
	Likewise.
	* testsuite/libctf-regression/nonstatic-var-section-ld.lk: Adjust.
	* testsuite/libctf-writable/symtypetab-nonlinker-writeout.c: Fix
	initializer.
2021-09-27 20:31:26 +01:00
Alan Modra
ad77db1c02 CC_FOR_TARGET et al
The top level Makefile, the ld Makefile and others, define
CC_FOR_TARGET to be a compiler for the binutils target machine.  This
is the compiler that should be used for almost all tests with C
source.  There are _FOR_TARGET versions of CFLAGS, CXX, and CXXFLAGS
too.  This was all supposed to work with the testsuite .exp files
using CC for the target compiler, and CC_FOR_HOST for the host
compiler, with the makefiles passing CC=$CC_FOR_TARGET and
CC_FOR_HOST=$CC to the runtest invocation.

One exception to the rule of using CC_FOR_TARGET is the native-only ld
bootstrap test, which uses the newly built ld to link a copy of
itself.  Since the files being linked were created with the host
compiler, the boostrap test should use CC and CFLAGS, in case some
host compiler option provides needed libraries automatically.
However, bootstrap.exp used CC where it should have used CC_FOR_HOST.
I set about fixing that problem, then decided that playing games in
the makefiles with CC was a bad idea.  Not only is it confusing, but
other dejagnu code knows about CC_FOR_TARGET.  See dejagnu/target.exp.

So this patch gets rid of the makefile variable renaming and changes
all the .exp files to use the correct _FOR_TARGET variables.
CC_FOR_HOST and CFLAGS_FOR_HOST disappear.  A followup patch will
correct bootstrap.exp to use CFLAGS, and a number of other things I
noticed.

binutils/
	* testsuite/lib/binutils-common.exp (run_dump_test): Use
	CC_FOR_TARGET and CFLAGS_FOR_TARGET rather than CC and CFLAGS.
ld/
	* Makefile.am (check-DEJAGNU): Don't set CC to CC_FOR_TARGET
	and similar.  Pass variables with unchanged names.  Don't set
	CC_FOR_HOST or CFLAGS_FOR_HOST.
	* Makefile.in: Regenerate.
	* testsuite/config/default.exp: Update default CC and similar.
	(compiler_supports, plug_opt): Use CC_FOR_TARGET.
	* testsuite/ld-cdtest/cdtest.exp: Replace all uses of CC with
	CC_FOR_TARGET, and similarly for CFLAGS, CXX and CXXFLAGS.
	* testsuite/ld-auto-import/auto-import.exp: Likewise.
	* testsuite/ld-cygwin/exe-export.exp: Likewise.
	* testsuite/ld-elf/dwarf.exp: Likewise.
	* testsuite/ld-elf/indirect.exp: Likewise.
	* testsuite/ld-elf/shared.exp: Likewise.
	* testsuite/ld-elfcomm/elfcomm.exp: Likewise.
	* testsuite/ld-elfvers/vers.exp: Likewise.
	* testsuite/ld-elfvsb/elfvsb.exp: Likewise.
	* testsuite/ld-elfweak/elfweak.exp: Likewise.
	* testsuite/ld-gc/gc.exp: Likewise.
	* testsuite/ld-ifunc/ifunc.exp: Likewise.
	* testsuite/ld-mn10300/mn10300.exp: Likewise.
	* testsuite/ld-pe/pe-compile.exp: Likewise.
	* testsuite/ld-pe/pe-run.exp: Likewise.
	* testsuite/ld-pe/pe-run2.exp: Likewise.
	* testsuite/ld-pie/pie.exp: Likewise.
	* testsuite/ld-plugin/lto.exp: Likewise.
	* testsuite/ld-plugin/plugin.exp: Likewise.
	* testsuite/ld-scripts/crossref.exp: Likewise.
	* testsuite/ld-selective/selective.exp: Likewise.
	* testsuite/ld-sh/sh.exp: Likewise.
	* testsuite/ld-shared/shared.exp: Likewise.
	* testsuite/ld-srec/srec.exp: Likewise.
	* testsuite/ld-undefined/undefined.exp: Likewise.
	* testsuite/ld-unique/unique.exp: Likewise.
	* testsuite/ld-x86-64/tls.exp: Likewise.
	* testsuite/lib/ld-lib.exp: Likewise.
libctf/
	* Makefile.am (check-DEJAGNU): Don't set CC to CC_FOR_TARGET.
	Pass CC and CC_FOR_TARGET.  Don't set CC_FOR_HOST.
	* Makefile.in: Regenerate.
	* testsuite/config/default.exp: Update default CC and similar.
	* testsuite/lib/ctf-lib.exp (run_native_host_cmd): Use CC rather
	than CC_FOR_HOST.
	(run_lookup_test): Use CC_FOR_TARGET and CFLAGS_FOR_TARGET.
2021-09-03 16:26:09 +09:30
Nick Alcock
ae064303ef libctf, ld: fix test results for upstream GCC
The tests currently in binutils are aimed at the original GCC-based
implementation of CTF, which emitted CTF directly from GCC's internal
representation.  The approach now under review emits CTF from DWARF,
with an eye to eventually doing this for all non-DWARF debuginfo-like
formats GCC supports.  It also uses a different flag to enable
CTF emission (-gctf rather than -gt).

Adjust the testsuite accordingly.

Given that the ld testsuite results are dependent on type ordering,
which we do not guarantee at all, it's amazing how little changes. We
see a few type ordering differences, slices change because the old GCC
was buggy (slices were emitted "backwards", from the wrong end of the
machine word) and its expected results were wrong, and GCC now emits the
underlying integral type for enumerated types, though CTF has no way to
record this yet (coming in v4).

GCC also now emits even hidden symbols into the symtab (and thus
symtypetab), so one symtypetab test changes its expected results
slightly to compensate.

Also add tests for the CTF_K_UNKNOWN nonrepresentable type: this
couldn't be done before now since the only GCC that emits CTF_K_UNKNOWN
for nonrepresentable types is the new one.

ld/ChangeLog
2021-05-06  Nick Alcock  <nick.alcock@oracle.com>

	* testsuite/ld-ctf/ctf.exp: Use -gctf, not -gt.
	* testsuite/lib/ld-lib.exp: Likewise.
	* testsuite/ld-ctf/nonrepresentable-1.c: New test for nonrepresentable types.
	* testsuite/ld-ctf/nonrepresentable-2.c: Likewise.
	* testsuite/ld-ctf/nonrepresentable.d: Likewise.
	* testsuite/ld-ctf/array.d: Larger type section.
	* testsuite/ld-ctf/data-func-conflicted.d: Likewise.
	* testsuite/ld-ctf/enums.d: Likewise.
	* testsuite/ld-ctf/conflicting-enums.d: Don't compare types.
	* testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Changed type order.
	* testsuite/ld-ctf/cross-tu-noncyclic.d: Likewise.
	* testsuite/ld-ctf/slice.d: Adjust for improved slice emission.

libctf/ChangeLog
2021-05-06  Nick Alcock  <nick.alcock@oracle.com>

	* testsuite/lib/ctf-lib.exp: Use -gctf, not -gt.
	* testsuite/libctf-regression/nonstatic-var-section-ld-r.lk:
	Hidden symbols now get into the symtypetab anyway.
2021-05-06 09:31:31 +01:00
Nick Alcock
15131809c2 libctf: fix memory leak in a test
Harmless, but causes noise that makes it harder to spot other leaks.

libctf/ChangeLog
2021-03-25  Nick Alcock  <nick.alcock@oracle.com>

	* testsuite/libctf-writable/symtypetab-nonlinker-writeout.c: Don't
	leak buf.
2021-03-25 16:32:50 +00:00
Nick Alcock
08c428aff4 libctf: eliminate dtd_u, part 5: structs / unions
Eliminate the dynamic member storage for structs and unions as we have
for other dynamic types.  This is much like the previous enum
elimination, except that structs and unions are the only types for which
a full-sized ctf_type_t might be needed.  Up to now, this decision has
been made in the individual ctf_add_{struct,union}_sized functions and
duplicated in ctf_add_member_offset.  The vlen machinery lets us
simplify this, always allocating a ctf_lmember_t and setting the
dtd_data's ctt_size to CTF_LSIZE_SENT: we figure out whether this is
really justified and (almost always) repack things down into a
ctf_stype_t at ctf_serialize time.

This allows us to eliminate the dynamic member paths from the iterators and
query functions in ctf-types.c in favour of always using the large-structure
vlen stuff for dynamic types (the diff is ugly but that's just because of the
volume of reindentation this calls for).  This also means the large-structure
vlen stuff gets more heavily tested, which is nice because it was an almost
totally unused code path before now (it only kicked in for structures of size
>4GiB, and how often do you see those?)

The only extra complexity here is ctf_add_type.  Back in the days of the
nondeduplicating linker this was called a ridiculous number of times for
countless identical copies of structures: eschewing the repeated lookups of the
dtd in ctf_add_member_offset and adding the members directly saved an amazing
amount of time.  Now the nondeduplicating linker is gone, this is extreme
overoptimization: we can rip out the direct addition and use ctf_member_next and
ctf_add_member_offset, just like ctf_dedup_emit does.

We augment a ctf_add_type test to try adding a self-referential struct, the only
thing the ctf_add_type part of this change really perturbs.

This completes the elimination of dtd_u.

libctf/ChangeLog
2021-03-18  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-impl.h (ctf_dtdef_t) <dtu_members>: Remove.
	<dtd_u>: Likewise.
	(ctf_dmdef_t): Remove.
	(struct ctf_next) <u.ctn_dmd>: Remove.
	* ctf-create.c (INITIAL_VLEN): New, more-or-less arbitrary initial
	vlen size.
	(ctf_add_enum): Use it.
	(ctf_dtd_delete): Do not free the (removed) dmd; remove string
	refs from the vlen on struct deletion.
	(ctf_add_struct_sized): Populate the vlen: do it by hand if
	promoting forwards.  Always populate the full-size
	lsizehi/lsizelo members.
	(ctf_add_union_sized): Likewise.
	(ctf_add_member_offset): Set up the vlen rather than the dmd.
	Expand it as needed, repointing string refs via
	ctf_str_move_pending. Add the member names as pending strings.
	Always populate the full-size lsizehi/lsizelo members.
	(membadd): Remove, folding back into...
	(ctf_add_type_internal): ... here, adding via an ordinary
	ctf_add_struct_sized and _next iteration rather than doing
	everything by hand.
	* ctf-serialize.c (ctf_copy_smembers): Remove this...
	(ctf_copy_lmembers): ... and this...
	(ctf_emit_type_sect): ... folding into here. Figure out if a
	ctf_stype_t is needed here, not in ctf_add_*_sized.
	(ctf_type_sect_size): Figure out the ctf_stype_t stuff the same
	way here.
	* ctf-types.c (ctf_member_next): Remove the dmd path and always
	use the vlen.  Force large-structure usage for dynamic types.
	(ctf_type_align): Likewise.
	(ctf_member_info): Likewise.
	(ctf_type_rvisit): Likewise.
	* testsuite/libctf-regression/type-add-unnamed-struct-ctf.c: Add a
	self-referential type to this test.
	* testsuite/libctf-regression/type-add-unnamed-struct.c: Adjusted
	accordingly.
	* testsuite/libctf-regression/type-add-unnamed-struct.lk: Likewise.
2021-03-18 12:40:40 +00:00
Nick Alcock
77d724a7ec libctf: eliminate dtd_u, part 4: enums
This is the first tricky one, the first complex multi-entry vlen
containing strings.  To handle this in vlen form, we have to handle
pending refs moving around on realloc.

We grow vlen regions using a new ctf_grow_vlen function, and iterate
through the existing enums every time a grow happens, telling the string
machinery the distance between the old and new vlen region and letting
it adjust the pending refs accordingly.  (This avoids traversing all
outstanding refs to find the refs that need adjusting, at the cost of
having to traverse one enum: an obvious major performance win.)

Addition of enums themselves (and also structs/unions later) is a bit
trickier than earlier forms, because the type might be being promoted
from a forward, and forwards have no vlen: so we have to spot that and
create it if needed.

Serialization of enums simplifies down to just telling the string
machinery about the string refs; all the enum type-lookup code loses all
its dynamic member lookup complexity entirely.

A new test is added that iterates over (and gets values of) an enum with
enough members to force a round of vlen growth.

libctf/ChangeLog
2021-03-18  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-impl.h (ctf_dtdef_t) <dtd_vlen_alloc>: New.
	(ctf_str_move_pending): Declare.
	* ctf-string.c (ctf_str_add_ref_internal): Fix error return.
	(ctf_str_move_pending): New.
	* ctf-create.c (ctf_grow_vlen): New.
	(ctf_dtd_delete): Zero out the vlen_alloc after free.  Free the
	vlen later: iterate over it and free enum name refs first.
	(ctf_add_generic): Populate dtd_vlen_alloc from vlen.
	(ctf_add_enum): populate the vlen; do it by hand if promoting
	forwards.
	(ctf_add_enumerator): Set up the vlen rather than the dmd.  Expand
	it as needed, repointing string refs via ctf_str_move_pending. Add
	the enumerand names as pending strings.
	* ctf-serialize.c (ctf_copy_emembers): Remove.
	(ctf_emit_type_sect): Copy the vlen into place and ref the
	strings.
	* ctf-types.c (ctf_enum_next): The dynamic portion now uses
	the same code as the non-dynamic.
	(ctf_enum_name): Likewise.
	(ctf_enum_value): Likewise.
	* testsuite/libctf-lookup/enum-many-ctf.c: New test.
	* testsuite/libctf-lookup/enum-many.lk: New test.
2021-03-18 12:40:40 +00:00