[PATCH 00/59] Deduplicating CTF linker

classic Classic list List threaded Threaded
80 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

[PATCH 00/59] Deduplicating CTF linker

Sourceware - binutils list mailing list
So the deduplicating CTF linker is finally ready for review.  (Note: ready
for *review*, probably not yet quite ready for committing, since to speed
things up a bit I've posted before all non-Linux-arch tests are finished.
In particular, big-endian tests, Solaris tests, and tests on mingw and
cygwin will be done in parallel with this review.  Cross build-and-checks to
every supported arch, --enable-targets=all tests, and 64-bit and 32-bit
tests on x86-64 Linux and FreeBSD have been done already.)

Please read and review as you wish -- most of these are libctf-only changes,
but I'd be very happy for review of those too.  There are only a few dozen
lines of non-testsuite changes outside libctf.

Before the actual linker changes comes a lot of loosely-related stuff in
libctf.

First, there's new infrastructure, mostly used by the deduplicating linker
but also to improve interaction with the linker itself and other consumers,
like GDB:
 - proper textual error/warning reporting (adopted by all in-binutils
   consumers): libctf errors are no longer just an errno value and an error
   message swallowed up in the debug stream
 - adding new error codes only needs to be done in one place, and produces
   fewer relocs in the final binary
 - new API functions to get things we were concealing before, like the
   number of members in an enum, or to do things previously impossible,
   like bump the refcount on a ctf_file_t so you can hold it open for
   longer, and a bunch of new API functions for the dynhash
 - a new dynhash-like thing, the dynset (doesn't store a value, but is
   much more memory-efficient), still based on the libiberty hashtab
 - a whole new type of iterator, the *_next iterator family, much easier
   to use than the existing *_iter iterators that take a callback: I hope
   to move away from use of the old *_iter functions in most cases within
   libctf, and eventually reimplement *_iter in terms of *_next

Then there are a lot of bugfixes, and performance and memory-usage improvements,
again mostly triggered by the needs of the deduplicator.

Once those are past we have linker-related changes, starting on patch 43,
including one big commit (patch 50) containing the CTF deduplicator itself.
(I can cut this one up if you find it too big, but control roughly flows
from the top of the patch to the bottom anyway, so slicing it into pieces
doesn't really buy much in terms of readability.)

Nearly all the changes are in libctf: ld gets only a couple of new options
to control various new CTF linker settings and a better way of reporting
(arbitrarily many) libctf errors and warnings.  No changes are needed in
libbfd at all.

Most of the new work is in the new file libctf/ctf-dedup.c, which
deduplicates the types section of CTF dicts, taking a bunch of CTF dicts and
linking them together into a single output dict and possibly a set of child
dicts containing conflicting types and (link mode allowing) types that
appear in only one input dict.  This gets done by recursively hashing types
(terminating the recursion at tagged structures and unions so as not to get
caught in cycles), identifying types with ambiguous definitions (multiple
hash values for the same name), then emitting one type per deduplicated type
hash value into appropriate output dicts.  The algorithm used by ctf-dedup.c
is documented at the top of the file.

The changes in ctf-link.c tie that deduplicator into the rest of libctf, fix
bugs in the existing variable-section linking code, allow the variable
section to be omitted from the output, allow CTF dicts to be opened lazily
by libctf itself rather than requiring callers to do it, start using the new
err/warning infrastructure, and fix a bunch of bugs.

There is a new configure option which turns on debug output during the
initial type hashing phase: this generates so very much output that it
massively slows ld down even when LIBCTF_DEBUG is not set in the
environment.  So it's turned off by default.  When that configure flag is
not provided, CTF-related operations are not at all the slowest thing ld
does, even though the deduplicator is still serial (though deduplication can
still take a few seconds for bigger projects): see below for some example
timings, some of which are approximate because the timings are frankly in
the noise.  Deduplication *is* a bit memory-hungry, mostly due to hashtab
overhead, but again this is tolerable and will be reduced further in time.

ld gains new options to customize the link mode (share-unconflicted or
share-duplicated: see ld.texi for the meaning of this) and to emit the
variable section if desired.  (Normal links will not want a variable
section, because the things in there correspond to static variables that
have no symbol table entry and cannot be looked up in any useful fashion.)

There is also a new CTF ld testsuite, largely due to Egeyar Bagcioglu: it
tests linking of CTF sections (including conflicting type names in different
TUs landing in suitable child dicts) and operation on a bunch of invalid
inputs: binutils gets some formatting fixes and an enhancement to
run_dump_test to let it compile things before assembling them.
Unfortunately because the pseudos GCC generates to emit assembler output are
often nonportable, the testsuite works by compiling C into asm and then
assembling and linking that: so a compiler capable of CTF generation via -gt
is needed to run the new tests.  We hope to fix this in time, but it will
take GCC changes.

Finally there is an important bugfix: our trick to ensure that the output
has only one .ctf section broke sometime in the last six months or so of
upstream development, so we were getting outputs with huge numbers of empty
CTF sections in: the new approach should be more robust.


I am reasonably confident in the algorithm, though no doubt bugs will
emerge.  CTF file format changes should not require significant changes in
the deduplicator, because we try wherever possible to use the public libctf
API in the dedup code rather than digging into the guts of the file format.
Much of this is probably reusable when CTF is extended to handle other
languages, as well (e.g. we don't really depend on any particular detail of
the C type system to break cycles, only that there *is* some thing or set of
things which must be present in order for a cycle in the type graph to
exist).


Coverage analysis suggests that the tests now in the testsuite cover all of
ctf-dedup.c except for paths associated with ld -r (input dicts with
children), paths associated with types that CTF cannot represent, a couple
of lines associated with cu-mapped links, and paths associated with the
share-duplicated link mode: perhaps 80% of the total line count is covered.
More tests will be added later to cover the missing cases.


Some speed (cpu-user-time) and CTF size figures are below: they were taken
on my 2.4GHz x86-64 Linux workhorse box.  The GCC used was a GCC 10 snapshot
from mid-Feb plus CTF-generation patches: see
https://github.com/oracle/gcc.git oracle/ctf-gen (if you want to replicate
this but don't want to fetch from GitHub I have a git bundle from upstream
commit 7a775242ea296849a34ce27de179eaaec411e880 available at
<http://www.esperi.org.uk/~nix/bundles/gcc-ctf.bundle>).

We start with easy stuff and proceed to things with crazy numbers of types
or that do mad things in the build process as a bit of a regression test,
notes below.  Sorry this is over 80 chars wide: I hope it's readable anyway:

Program        DWARF size .ctf size                                         Time[3]
               [1]        Compressed Uncompressed              Largest  -gt    no -gt
                                                  (no strings) input TU
GNU ld         1150314    42479      146945       63623        142226   17.33  16.76
libbfd         2746704    71380      237445       129929       143970   43.25  41.61
ld (static)    4490908    86428      289947       170933       162226   59.72  58.0
gas            1063842    48537      161929       75643        148271   17.66  16.66
coreutils ls   164517     6455       19384        15673        18481    0.30   0.33
vim            4740693    111080     372398       281471       138455   176.21 175.46
libX11         9525236    45799      155109       125534       58964    300.11 298.40
emacs 26.3 [2] 8079794    86267      303306       225828       174808   938.52 933.78
GhostScript    18972151   2311683[4] 4828538      2726368      127543   265.73 252.41
Gtk 3.24.20    11895771   255101[5]  908719       717034       255101   1268   1245
CLISP[6]       2870363    49234      193162       124811       254536   160.90 151.42
X.org xserver  6718404    105955     369395       295470       257878   448    436

[1] .debug_info only: perhaps I should include .debug_str?  Really what we
    need is "type only" DWARF for comparison, but that requires compiler
    hacking I haven't looked at yet.
[2] times include all lisp compilation
[3] times do not include configury: a good few of them are in the noise.
    This at least shows that the deduplicator won't slow things down too
    badly.
[4] GhostScript is a worst case for huge numbers of types with identical
    names but distinct definitions in different TUs.  Format v4 gains the
    ability to share the definitions of such types between TUs, and will
    reduce this size back down to something more like the size of the main
    dict, 113983 bytes.  (The deduplicator will hardly need to change: the
    changes are elsewhere in libctf.)
[5] Slightly afflicted by the same things as GhostScript: the CTF size will
    probably halve in format v4.
[6] size of lisp.a's sole member: clisp is an oddball, and would probably
    require a specialized reader that knew something about the .mem dumping
    process.

Egeyar Bagcioglu (3):
  libctf, types: ensure the emission of ECTF_NOPARENT
  ld: Reformat CTF errors into warnings.
  ld: new CTF testsuite

Nick Alcock (56):
  include, libctf: typo fixes
  libctf: restructure error handling to reduce relocations
  libctf, create: support addition of references to the unimplemented
    type
  libctf, create: do not corrupt function types' arglists at insertion
    time
  libctf, create: add explicit casts for variables' and slices' types
  libctf, types: allow ctf_type_reference of dynamic slices
  libctf, open: drop unnecessary historical wart around forwards
  libctf, create: member names of "" and NULL should be the same
  libctf, create: fix addition of anonymous struct/union members
  libctf, create: empty dicts are dirty to start with
  libctf, types: support slices of anything terminating in an int
  libctf, types: ints, floats and typedefs with no name are invalid
  libctf, archive: stop ctf_arc_bufopen triggering crazy unmaps
  libctf: having debugging enabled is unlikely
  libctf: add ctf_type_name_raw
  libctf: add ctf_type_kind_forwarded
  libctf: add ctf_member_count
  libctf: add ctf_archive_count
  libctf: fix __extension__ with non-GNU C compilers
  libctf: add new dynhash functions
  libctf, hash: improve insertion of existing keys into dynhashes
  libctf, hash: save per-item space when no key/item freeing function
  libctf, hash: introduce the ctf_dynset
  libctf: move existing inlines into ctf-inlines.h
  libctf: add ctf_forwardable_kind
  libctf: add ctf_ref
  libctf, next: introduce new class of easier-to-use iterators
  libctf, next, hash: add dynhash and dynset _next iteration
  libctf: pass the thunk down properly when wrapping qsort_r
  libctf: error out on corrupt CTF with invalid header flags
  libctf, ld, binutils: add textual error/warning reporting for libctf
  libctf, types: enhance ctf_type_aname to print function arg types
  libctf, decl: avoid leaks of the formatted string on error
  libctf, dump: migrate towards dumping errors rather than truncation
  libctf, dump: fix slice dumping
  libctf, open: fix opening CTF in binaries with no symtab
  libctf, archive: fix bad error message
  libctf: check for vasprintf
  libctf: rename the type_mapping_key to type_key
  libctf: sort out potential refcount loops
  libctf: drop error-prone ctf_strerror
  libctf, link: add lazy linking: clean up input members: err/warn
    cleanup
  libctf, link: fix ctf_link_write fd leak
  libctf, link: redo cu-mapping handling
  ctf, link: fix spurious conflicts of variables in the variable section
  libctf, link: add the ability to filter out variables from the link
  libctf: add SHA-1 support for libctf
  libctf, dedup: add new configure option --enable-libctf-hash-debugging
  libctf, dedup: add deduplicator
  libctf, link: add CTF_LINK_OMIT_VARIABLES_SECTION
  libctf, link: tie in the deduplicating linker
  binutils: objdump: ctf: drop incorrect linefeeds
  ld: new options --ctf-variables and --ctf-share-types
  binutils, testsuite: allow compilation before doing run_dump_test
  ld, testsuite: only run CTF tests when ld and GCC support CTF
  ld: do not produce one empty output .ctf section for every input .ctf

 binutils/objdump.c                            |   25 +-
 binutils/readelf.c                            |   23 +-
 binutils/testsuite/lib/binutils-common.exp    |   58 +-
 include/ctf-api.h                             |  178 +-
 include/ctf.h                                 |    3 +-
 ld/Makefile.am                                |    7 +-
 ld/Makefile.in                                |    8 +-
 ld/NEWS                                       |   10 +
 ld/configure                                  |    6 +-
 ld/configure.ac                               |    1 +
 ld/ld.h                                       |    8 +
 ld/ld.texi                                    |   34 +
 ld/ldlang.c                                   |   63 +-
 ld/ldlex.h                                    |    3 +
 ld/lexsup.c                                   |   29 +
 ld/testsuite/ld-ctf/A-2.c                     |    6 +
 ld/testsuite/ld-ctf/A.c                       |    5 +
 ld/testsuite/ld-ctf/B-2.c                     |    5 +
 ld/testsuite/ld-ctf/B.c                       |    4 +
 ld/testsuite/ld-ctf/C-2.c                     |    5 +
 ld/testsuite/ld-ctf/C.c                       |    5 +
 ld/testsuite/ld-ctf/array-char.c              |    2 +
 ld/testsuite/ld-ctf/array-int.c               |    1 +
 ld/testsuite/ld-ctf/array.d                   |   34 +
 ld/testsuite/ld-ctf/child-float.c             |    4 +
 ld/testsuite/ld-ctf/child-int.c               |    4 +
 ld/testsuite/ld-ctf/conflicting-cycle-1.B-1.d |   40 +
 ld/testsuite/ld-ctf/conflicting-cycle-1.B-2.d |   41 +
 .../ld-ctf/conflicting-cycle-1.parent.d       |   38 +
 ld/testsuite/ld-ctf/conflicting-cycle-2.A-1.d |   40 +
 ld/testsuite/ld-ctf/conflicting-cycle-2.A-2.d |   41 +
 .../ld-ctf/conflicting-cycle-2.parent.d       |   40 +
 ld/testsuite/ld-ctf/conflicting-cycle-3.C-1.d |   39 +
 ld/testsuite/ld-ctf/conflicting-cycle-3.C-2.d |   40 +
 .../ld-ctf/conflicting-cycle-3.parent.d       |   37 +
 ld/testsuite/ld-ctf/conflicting-enums.d       |   35 +
 ld/testsuite/ld-ctf/conflicting-typedefs.d    |   33 +
 ld/testsuite/ld-ctf/cross-tu-1.c              |   12 +
 ld/testsuite/ld-ctf/cross-tu-2.c              |    8 +
 ld/testsuite/ld-ctf/cross-tu-conflicting-2.c  |    8 +
 ld/testsuite/ld-ctf/cross-tu-cyclic-1.c       |   14 +
 ld/testsuite/ld-ctf/cross-tu-cyclic-2.c       |   16 +
 ld/testsuite/ld-ctf/cross-tu-cyclic-3.c       |    3 +
 ld/testsuite/ld-ctf/cross-tu-cyclic-4.c       |    4 +
 .../ld-ctf/cross-tu-cyclic-conflicting.d      |   57 +
 .../ld-ctf/cross-tu-cyclic-nonconflicting.d   |   50 +
 ld/testsuite/ld-ctf/cross-tu-into-cycle.d     |   64 +
 ld/testsuite/ld-ctf/cross-tu-noncyclic.d      |   46 +
 ld/testsuite/ld-ctf/ctf.exp                   |   31 +
 ld/testsuite/ld-ctf/cycle-1.c                 |    7 +
 ld/testsuite/ld-ctf/cycle-1.d                 |   36 +
 ld/testsuite/ld-ctf/cycle-2.A.d               |   40 +
 ld/testsuite/ld-ctf/cycle-2.B.d               |   40 +
 ld/testsuite/ld-ctf/cycle-2.C.d               |   40 +
 ld/testsuite/ld-ctf/diag-ctf-version-0.d      |    5 +
 ld/testsuite/ld-ctf/diag-ctf-version-0.s      |   44 +
 .../diag-ctf-version-2-unsupported-feature.d  |    5 +
 .../diag-ctf-version-2-unsupported-feature.s  |   44 +
 ld/testsuite/ld-ctf/diag-ctf-version-f.d      |    5 +
 ld/testsuite/ld-ctf/diag-ctf-version-f.s      |   44 +
 ld/testsuite/ld-ctf/diag-cttname-invalid.d    |    5 +
 ld/testsuite/ld-ctf/diag-cttname-invalid.s    |   44 +
 ld/testsuite/ld-ctf/diag-cttname-null.d       |   24 +
 ld/testsuite/ld-ctf/diag-cttname-null.s       |   44 +
 ld/testsuite/ld-ctf/diag-cuname.d             |   39 +
 ld/testsuite/ld-ctf/diag-cuname.s             |   44 +
 .../ld-ctf/diag-decompression-failure.d       |    5 +
 .../ld-ctf/diag-decompression-failure.s       |   44 +
 ld/testsuite/ld-ctf/diag-parlabel.d           |   39 +
 ld/testsuite/ld-ctf/diag-parlabel.s           |   44 +
 ld/testsuite/ld-ctf/diag-parname.d            |    5 +
 ld/testsuite/ld-ctf/diag-parname.s            |   44 +
 ld/testsuite/ld-ctf/diag-unsupported-flag.d   |    5 +
 ld/testsuite/ld-ctf/diag-unsupported-flag.s   |   44 +
 .../ld-ctf/diag-wrong-magic-number-mixed.d    |   39 +
 ld/testsuite/ld-ctf/diag-wrong-magic-number.d |    5 +
 ld/testsuite/ld-ctf/diag-wrong-magic-number.s |   44 +
 ld/testsuite/ld-ctf/enum-2.c                  |    3 +
 ld/testsuite/ld-ctf/enum.c                    |    3 +
 ld/testsuite/ld-ctf/function.c                |    3 +
 ld/testsuite/ld-ctf/function.d                |   23 +
 ld/testsuite/ld-ctf/slice.c                   |    6 +
 ld/testsuite/ld-ctf/slice.d                   |   30 +
 ld/testsuite/ld-ctf/super-sub-cycles.c        |   10 +
 ld/testsuite/ld-ctf/super-sub-cycles.d        |   34 +
 ld/testsuite/ld-ctf/typedef-int.c             |    3 +
 ld/testsuite/ld-ctf/typedef-long.c            |    3 +
 ld/testsuite/ld-ctf/union-1.c                 |    4 +
 ld/testsuite/lib/ld-lib.exp                   |   52 +
 libctf/.gitignore                             |    1 +
 libctf/Makefile.am                            |   12 +-
 libctf/Makefile.in                            |  360 +-
 libctf/aclocal.m4                             |    1 +
 libctf/config.h.in                            |    7 +
 libctf/configure                              |   73 +-
 libctf/configure.ac                           |    8 +-
 libctf/ctf-archive.c                          |  147 +-
 libctf/ctf-create.c                           |  112 +-
 libctf/ctf-decl.c                             |    5 +-
 libctf/ctf-decls.h                            |    2 +-
 libctf/ctf-dedup.c                            | 3157 +++++++++++++++++
 libctf/ctf-dump.c                             |  199 +-
 libctf/ctf-error.c                            |  102 +-
 libctf/ctf-hash.c                             |  560 ++-
 libctf/ctf-impl.h                             |  305 +-
 libctf/ctf-inlines.h                          |   97 +
 libctf/ctf-link.c                             | 1191 ++++++-
 libctf/ctf-lookup.c                           |   19 +-
 libctf/ctf-open-bfd.c                         |   85 +-
 libctf/ctf-open.c                             |   91 +-
 libctf/ctf-sha1.c                             |   50 +
 libctf/ctf-sha1.h                             |   41 +
 libctf/ctf-subr.c                             |  101 +-
 libctf/ctf-types.c                            |  508 ++-
 libctf/ctf-util.c                             |   66 +
 libctf/libctf.ver                             |   18 +-
 libctf/mkerrors.sed                           |   28 +
 117 files changed, 8997 insertions(+), 619 deletions(-)
 create mode 100644 ld/testsuite/ld-ctf/A-2.c
 create mode 100644 ld/testsuite/ld-ctf/A.c
 create mode 100644 ld/testsuite/ld-ctf/B-2.c
 create mode 100644 ld/testsuite/ld-ctf/B.c
 create mode 100644 ld/testsuite/ld-ctf/C-2.c
 create mode 100644 ld/testsuite/ld-ctf/C.c
 create mode 100644 ld/testsuite/ld-ctf/array-char.c
 create mode 100644 ld/testsuite/ld-ctf/array-int.c
 create mode 100644 ld/testsuite/ld-ctf/array.d
 create mode 100644 ld/testsuite/ld-ctf/child-float.c
 create mode 100644 ld/testsuite/ld-ctf/child-int.c
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-1.B-1.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-1.B-2.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-1.parent.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-2.A-1.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-2.A-2.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-2.parent.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-3.C-1.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-3.C-2.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-cycle-3.parent.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-enums.d
 create mode 100644 ld/testsuite/ld-ctf/conflicting-typedefs.d
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-1.c
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-2.c
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-conflicting-2.c
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-cyclic-1.c
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-cyclic-2.c
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-cyclic-3.c
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-cyclic-4.c
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-cyclic-conflicting.d
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-cyclic-nonconflicting.d
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-into-cycle.d
 create mode 100644 ld/testsuite/ld-ctf/cross-tu-noncyclic.d
 create mode 100644 ld/testsuite/ld-ctf/ctf.exp
 create mode 100644 ld/testsuite/ld-ctf/cycle-1.c
 create mode 100644 ld/testsuite/ld-ctf/cycle-1.d
 create mode 100644 ld/testsuite/ld-ctf/cycle-2.A.d
 create mode 100644 ld/testsuite/ld-ctf/cycle-2.B.d
 create mode 100644 ld/testsuite/ld-ctf/cycle-2.C.d
 create mode 100644 ld/testsuite/ld-ctf/diag-ctf-version-0.d
 create mode 100644 ld/testsuite/ld-ctf/diag-ctf-version-0.s
 create mode 100644 ld/testsuite/ld-ctf/diag-ctf-version-2-unsupported-feature.d
 create mode 100644 ld/testsuite/ld-ctf/diag-ctf-version-2-unsupported-feature.s
 create mode 100644 ld/testsuite/ld-ctf/diag-ctf-version-f.d
 create mode 100644 ld/testsuite/ld-ctf/diag-ctf-version-f.s
 create mode 100644 ld/testsuite/ld-ctf/diag-cttname-invalid.d
 create mode 100644 ld/testsuite/ld-ctf/diag-cttname-invalid.s
 create mode 100644 ld/testsuite/ld-ctf/diag-cttname-null.d
 create mode 100644 ld/testsuite/ld-ctf/diag-cttname-null.s
 create mode 100644 ld/testsuite/ld-ctf/diag-cuname.d
 create mode 100644 ld/testsuite/ld-ctf/diag-cuname.s
 create mode 100644 ld/testsuite/ld-ctf/diag-decompression-failure.d
 create mode 100644 ld/testsuite/ld-ctf/diag-decompression-failure.s
 create mode 100644 ld/testsuite/ld-ctf/diag-parlabel.d
 create mode 100644 ld/testsuite/ld-ctf/diag-parlabel.s
 create mode 100644 ld/testsuite/ld-ctf/diag-parname.d
 create mode 100644 ld/testsuite/ld-ctf/diag-parname.s
 create mode 100644 ld/testsuite/ld-ctf/diag-unsupported-flag.d
 create mode 100644 ld/testsuite/ld-ctf/diag-unsupported-flag.s
 create mode 100644 ld/testsuite/ld-ctf/diag-wrong-magic-number-mixed.d
 create mode 100644 ld/testsuite/ld-ctf/diag-wrong-magic-number.d
 create mode 100644 ld/testsuite/ld-ctf/diag-wrong-magic-number.s
 create mode 100644 ld/testsuite/ld-ctf/enum-2.c
 create mode 100644 ld/testsuite/ld-ctf/enum.c
 create mode 100644 ld/testsuite/ld-ctf/function.c
 create mode 100644 ld/testsuite/ld-ctf/function.d
 create mode 100644 ld/testsuite/ld-ctf/slice.c
 create mode 100644 ld/testsuite/ld-ctf/slice.d
 create mode 100644 ld/testsuite/ld-ctf/super-sub-cycles.c
 create mode 100644 ld/testsuite/ld-ctf/super-sub-cycles.d
 create mode 100644 ld/testsuite/ld-ctf/typedef-int.c
 create mode 100644 ld/testsuite/ld-ctf/typedef-long.c
 create mode 100644 ld/testsuite/ld-ctf/union-1.c
 create mode 100644 libctf/.gitignore
 create mode 100644 libctf/ctf-dedup.c
 create mode 100644 libctf/ctf-inlines.h
 create mode 100644 libctf/ctf-sha1.c
 create mode 100644 libctf/ctf-sha1.h
 create mode 100644 libctf/mkerrors.sed

--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 01/59] include, libctf: typo fixes

Sourceware - binutils list mailing list
include/
        * ctf-api.h: Fix typos in comments.
libctf/
        * ctf-impl.h: Fix typos in comments.
---
 include/ctf-api.h | 6 +++---
 libctf/ctf-impl.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index d6b05bc71fe..bb1cf0f50eb 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -30,7 +30,7 @@
 
 #ifdef __cplusplus
 extern "C"
-  {
+{
 #endif
 
 /* Clients can open one or more CTF containers and obtain a pointer to an
@@ -80,7 +80,7 @@ typedef struct ctf_link_sym
 
 /* Indication of how to share types when linking.  */
 
-/* Share all types thare are not in conflict.  The default.  */
+/* Share all types that are not in conflict.  The default.  */
 #define CTF_LINK_SHARE_UNCONFLICTED 0x0
 
 /* Share only types that are used by multiple inputs.  Not implemented yet.  */
@@ -428,7 +428,7 @@ extern unsigned char *ctf_link_write (ctf_file_t *, size_t *size,
       size_t threshold);
 
 /* Specialist linker functions.  These functions are not used by ld, but can be
-   used by other prgorams making use of the linker machinery for other purposes
+   used by other programs making use of the linker machinery for other purposes
    to customize its output.  */
 extern int ctf_link_add_cu_mapping (ctf_file_t *, const char *from,
     const char *to);
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 133ca0ee6e2..b20a4f05a80 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -37,7 +37,7 @@
 
 #ifdef __cplusplus
 extern "C"
-  {
+{
 #endif
 
 /* Compiler attributes.  */
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 02/59] libctf: restructure error handling to reduce relocations

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
Jose Marchesi noted that the traditional-Unix error array in ctf-error.c
introduces one reloc per error to initialize the array: 58 so far.  We
can reduce this to zero using an array of carefully-sized individual
members which is used to construct a string table, that is then
referenced by the lookup functions: but doing this automatically is a
pain.

Bruno Haible wrote suitable code years ago: I got permission to reuse it
(Bruno says "... which I hereby put in the public domain"); I modified
it a tiny bit (similarly to what Ulrich Drepper did in the dsohowto
text, but I redid it from scratch), commented it up a bit, and shifted
the error table into that form, migrating it into the new file
ctf-error.h.

This has the advantage that it spotted both typos in the text of the
errors in the comments in ctf-api.h and typos in the error defines in
the comments in ctf-error.c, and places where the two were simply not
in sync.  All are now fixed.

One new constant exists in ctf-api.h: CTF_NERR, since the old method of
working out the number of errors in ctf-error.c was no longer usable,
and it seems that the number of CTF errors is something users might
reasonably want as well.  It should be pretty easy to keep up to date as
new errors are introduced.

include/
        * ctf-api.h (ECTF_*): Improve comments.
        (ECTF_NERR): New.

libctf/
        * ctf-error.c: Include <stddef.h>, for offsetof.
        (_ctf_errlist): Migrate to...
        (_ctf_errlist_t): ... this.
        (_ctf_erridx): New, indexes into _ctf_errlist_t.
        (_ctf_nerr): Remove.
        (ctf_errmsg): Adjust accordingly.
        * Makefile.am (BUILT_SOURCES): Note...
        (ctf-error.h): ... this new rule.
        * Makefile.in: Regenerate.
        * mkerrors.sed: New, process ctf-api.h to generate ctf-error.h.
        * .gitignore: New, ignore ctf-error.h.
---
 include/ctf-api.h   | 106 ++++++++++++++++++++++----------------------
 libctf/.gitignore   |   1 +
 libctf/Makefile.am  |   5 +++
 libctf/Makefile.in  |  15 +++++--
 libctf/ctf-error.c  |  99 +++++++++++++++++------------------------
 libctf/mkerrors.sed |  28 ++++++++++++
 6 files changed, 140 insertions(+), 114 deletions(-)
 create mode 100644 libctf/.gitignore
 create mode 100644 libctf/mkerrors.sed

diff --git a/include/ctf-api.h b/include/ctf-api.h
index bb1cf0f50eb..2e3e28b840c 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -153,60 +153,62 @@ typedef struct ctf_snapshot_id
 
 enum
   {
-   ECTF_FMT = ECTF_BASE, /* File is not in CTF or ELF format.  */
-   ECTF_BFDERR, /* BFD error.  */
-   ECTF_CTFVERS, /* CTF version is more recent than libctf.  */
-   ECTF_BFD_AMBIGUOUS, /* Ambiguous BFD target.  */
-   ECTF_SYMTAB, /* Symbol table uses invalid entry size.  */
-   ECTF_SYMBAD, /* Symbol table data buffer invalid.  */
-   ECTF_STRBAD, /* String table data buffer invalid.  */
-   ECTF_CORRUPT, /* File data corruption detected.  */
-   ECTF_NOCTFDATA, /* ELF file does not contain CTF data.  */
-   ECTF_NOCTFBUF, /* Buffer does not contain CTF data.  */
-   ECTF_NOSYMTAB, /* Symbol table data is not available.  */
-   ECTF_NOPARENT, /* Parent CTF container is not available.  */
-   ECTF_DMODEL, /* Data model mismatch.  */
-   ECTF_LINKADDEDLATE, /* File added to link too late.  */
-   ECTF_ZALLOC, /* Failed to allocate (de)compression buffer.  */
-   ECTF_DECOMPRESS, /* Failed to decompress CTF data.  */
-   ECTF_STRTAB, /* String table for this string is missing.  */
-   ECTF_BADNAME, /* String offset is corrupt w.r.t. strtab.  */
-   ECTF_BADID, /* Invalid type ID number.  */
-   ECTF_NOTSOU, /* Type is not a struct or union.  */
-   ECTF_NOTENUM, /* Type is not an enum.  */
-   ECTF_NOTSUE, /* Type is not a struct, union, or enum.  */
-   ECTF_NOTINTFP, /* Type is not an integer, float, or enum.  */
-   ECTF_NOTARRAY, /* Type is not an array.  */
-   ECTF_NOTREF, /* Type does not reference another type.  */
-   ECTF_NAMELEN, /* Buffer is too small to hold type name.  */
-   ECTF_NOTYPE, /* No type found corresponding to name.  */
-   ECTF_SYNTAX, /* Syntax error in type name.  */
-   ECTF_NOTFUNC, /* Symbol entry or type is not a function.  */
-   ECTF_NOFUNCDAT, /* No func info available for function.  */
-   ECTF_NOTDATA, /* Symtab entry does not refer to a data obj.  */
-   ECTF_NOTYPEDAT, /* No type info available for object.  */
-   ECTF_NOLABEL, /* No label found corresponding to name.  */
-   ECTF_NOLABELDATA, /* File does not contain any labels.  */
-   ECTF_NOTSUP, /* Feature not supported.  */
-   ECTF_NOENUMNAM, /* Enum element name not found.  */
-   ECTF_NOMEMBNAM, /* Member name not found.  */
-   ECTF_RDONLY, /* CTF container is read-only.  */
-   ECTF_DTFULL, /* CTF type is full (no more members allowed).  */
-   ECTF_FULL, /* CTF container is full.  */
-   ECTF_DUPLICATE, /* Duplicate member or variable name.  */
-   ECTF_CONFLICT, /* Conflicting type definition present.  */
-   ECTF_OVERROLLBACK, /* Attempt to roll back past a ctf_update.  */
-   ECTF_COMPRESS, /* Failed to compress CTF data.  */
-   ECTF_ARCREATE, /* Error creating CTF archive.  */
-   ECTF_ARNNAME, /* Name not found in CTF archive.  */
-   ECTF_SLICEOVERFLOW, /* Overflow of type bitness or offset in slice.  */
-   ECTF_DUMPSECTUNKNOWN, /* Unknown section number in dump.  */
-   ECTF_DUMPSECTCHANGED, /* Section changed in middle of dump.  */
-   ECTF_NOTYET, /* Feature not yet implemented.  */
-   ECTF_INTERNAL, /* Internal error in link.  */
-   ECTF_NONREPRESENTABLE /* Type not representable in CTF.  */
+   ECTF_FMT = ECTF_BASE, /* File is not in CTF or ELF format.  */
+   ECTF_BFDERR, /* BFD error.  */
+   ECTF_CTFVERS, /* CTF dict version is too new for libctf.  */
+   ECTF_BFD_AMBIGUOUS, /* Ambiguous BFD target.  */
+   ECTF_SYMTAB, /* Symbol table uses invalid entry size.  */
+   ECTF_SYMBAD, /* Symbol table data buffer is not valid.  */
+   ECTF_STRBAD, /* String table data buffer is not valid.  */
+   ECTF_CORRUPT, /* File data structure corruption detected.  */
+   ECTF_NOCTFDATA, /* File does not contain CTF data.  */
+   ECTF_NOCTFBUF, /* Buffer does not contain CTF data.  */
+   ECTF_NOSYMTAB, /* Symbol table information is not available.  */
+   ECTF_NOPARENT, /* The parent CTF dictionary is unavailable.  */
+   ECTF_DMODEL, /* Data model mismatch.  */
+   ECTF_LINKADDEDLATE, /* File added to link too late.  */
+   ECTF_ZALLOC, /* Failed to allocate (de)compression buffer.  */
+   ECTF_DECOMPRESS, /* Failed to decompress CTF data.  */
+   ECTF_STRTAB, /* External string table is not available.  */
+   ECTF_BADNAME, /* String name offset is corrupt.  */
+   ECTF_BADID, /* Invalid type identifier.  */
+   ECTF_NOTSOU, /* Type is not a struct or union.  */
+   ECTF_NOTENUM, /* Type is not an enum.  */
+   ECTF_NOTSUE, /* Type is not a struct, union, or enum.  */
+   ECTF_NOTINTFP, /* Type is not an integer, float, or enum.  */
+   ECTF_NOTARRAY, /* Type is not an array.  */
+   ECTF_NOTREF, /* Type does not reference another type.  */
+   ECTF_NAMELEN, /* Buffer is too small to hold type name.  */
+   ECTF_NOTYPE, /* No type found corresponding to name.  */
+   ECTF_SYNTAX, /* Syntax error in type name.  */
+   ECTF_NOTFUNC, /* Symbol table entry or type is not a function.  */
+   ECTF_NOFUNCDAT, /* No function information available for function.  */
+   ECTF_NOTDATA, /* Symbol table entry does not refer to a data object.  */
+   ECTF_NOTYPEDAT, /* No type information available for symbol.  */
+   ECTF_NOLABEL, /* No label found corresponding to name.  */
+   ECTF_NOLABELDATA, /* File does not contain any labels.  */
+   ECTF_NOTSUP, /* Feature not supported.  */
+   ECTF_NOENUMNAM, /* Enum element name not found.  */
+   ECTF_NOMEMBNAM, /* Member name not found.  */
+   ECTF_RDONLY, /* CTF container is read-only.  */
+   ECTF_DTFULL, /* CTF type is full (no more members allowed).  */
+   ECTF_FULL, /* CTF container is full.  */
+   ECTF_DUPLICATE, /* Duplicate member or variable name.  */
+   ECTF_CONFLICT, /* Conflicting type is already defined.  */
+   ECTF_OVERROLLBACK, /* Attempt to roll back past a ctf_update.  */
+   ECTF_COMPRESS, /* Failed to compress CTF data.  */
+   ECTF_ARCREATE, /* Error creating CTF archive.  */
+   ECTF_ARNNAME, /* Name not found in CTF archive.  */
+   ECTF_SLICEOVERFLOW, /* Overflow of type bitness or offset in slice.  */
+   ECTF_DUMPSECTUNKNOWN, /* Unknown section number in dump.  */
+   ECTF_DUMPSECTCHANGED, /* Section changed in middle of dump.  */
+   ECTF_NOTYET, /* Feature not yet implemented.  */
+   ECTF_INTERNAL, /* Internal error in link.  */
+   ECTF_NONREPRESENTABLE /* Type not representable in CTF.  */
   };
 
+#define ECTF_NERR (ECTF_NONREPRESENTABLE - ECTF_BASE + 1) /* Count of CTF errors.  */
+
 /* The CTF data model is inferred to be the caller's data model or the data
    model of the given object, unless ctf_setmodel() is explicitly called.  */
 #define CTF_MODEL_ILP32 1 /* Object data model is ILP32.  */
diff --git a/libctf/.gitignore b/libctf/.gitignore
new file mode 100644
index 00000000000..b95386e97d3
--- /dev/null
+++ b/libctf/.gitignore
@@ -0,0 +1 @@
+ctf-error.h
diff --git a/libctf/Makefile.am b/libctf/Makefile.am
index c672d07e142..cdd3a5c55d6 100644
--- a/libctf/Makefile.am
+++ b/libctf/Makefile.am
@@ -52,3 +52,8 @@ libctf_la_LIBADD = @BFD_LIBADD@ $(libctf_nobfd_la_LIBADD)
 libctf_la_DEPENDENCIES = @BFD_DEPENDENCIES@
 libctf_la_LDFLAGS = $(libctf_nobfd_la_LDFLAGS)
 libctf_la_SOURCES = $(libctf_nobfd_la_SOURCES) ctf-open-bfd.c
+
+BUILT_SOURCES = ctf-error.h
+
+ctf-error.h: $(srcdir)/mkerrors.sed $(srcdir)/../include/ctf-api.h
+ sed -nf $(srcdir)/mkerrors.sed < $(srcdir)/../include/ctf-api.h > $@
diff --git a/libctf/Makefile.in b/libctf/Makefile.in
index 9e6f2551a56..a26fa31da49 100644
--- a/libctf/Makefile.in
+++ b/libctf/Makefile.in
@@ -452,7 +452,8 @@ libctf_la_LIBADD = @BFD_LIBADD@ $(libctf_nobfd_la_LIBADD)
 libctf_la_DEPENDENCIES = @BFD_DEPENDENCIES@
 libctf_la_LDFLAGS = $(libctf_nobfd_la_LDFLAGS)
 libctf_la_SOURCES = $(libctf_nobfd_la_SOURCES) ctf-open-bfd.c
-all: config.h
+BUILT_SOURCES = ctf-error.h
+all: $(BUILT_SOURCES) config.h
  $(MAKE) $(AM_MAKEFLAGS) all-am
 
 .SUFFIXES:
@@ -855,13 +856,15 @@ distcleancheck: distclean
        $(distcleancheck_listfiles) ; \
        exit 1; } >&2
 check-am: all-am
-check: check-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
 all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h
 installdirs:
  for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
   test -z "$$dir" || $(MKDIR_P) "$$dir"; \
  done
-install: install-am
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
 install-exec: install-exec-am
 install-data: install-data-am
 uninstall: uninstall-am
@@ -891,6 +894,7 @@ distclean-generic:
 maintainer-clean-generic:
  @echo "This command is intended for maintainers to use"
  @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
 clean: clean-am
 
 clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
@@ -965,7 +969,7 @@ ps-am:
 
 uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
 
-.MAKE: all install-am install-strip
+.MAKE: all check install install-am install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
  clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \
@@ -989,6 +993,9 @@ uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
 .PRECIOUS: Makefile
 
 
+ctf-error.h: $(srcdir)/mkerrors.sed $(srcdir)/../include/ctf-api.h
+ sed -nf $(srcdir)/mkerrors.sed < $(srcdir)/../include/ctf-api.h > $@
+
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/libctf/ctf-error.c b/libctf/ctf-error.c
index c457aa0a29f..1e69672007a 100644
--- a/libctf/ctf-error.c
+++ b/libctf/ctf-error.c
@@ -18,71 +18,54 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <ctf-impl.h>
+#include <stddef.h>
 
-static const char *const _ctf_errlist[] = {
-  "File is not in CTF or ELF format",     /* ECTF_FMT */
-  "BFD error",     /* ECTF_BFDERR */
-  "File uses more recent CTF version than libctf",   /* ECTF_CTFVERS */
-  "Ambiguous BFD target",     /* ECTF_BFD_AMBIGUOUS */
-  "Symbol table uses invalid entry size",     /* ECTF_SYMTAB */
-  "Symbol table data buffer is not valid",     /* ECTF_SYMBAD */
-  "String table data buffer is not valid",     /* ECTF_STRBAD */
-  "File data structure corruption detected",     /* ECTF_CORRUPT */
-  "File does not contain CTF data",     /* ECTF_NOCTFDATA */
-  "Buffer does not contain CTF data",     /* ECTF_NOCTFBUF */
-  "Symbol table information is not available",     /* ECTF_NOSYMTAB */
-  "Type information is in parent and unavailable",   /* ECTF_NOPARENT */
-  "Cannot import types with different data model",   /* ECTF_DMODEL */
-  "File added to link too late",     /* ECTF_LINKADDEDLATE */
-  "Failed to allocate (de)compression buffer",     /* ECTF_ZALLOC */
-  "Failed to decompress CTF data",     /* ECTF_DECOMPRESS */
-  "External string table is not available",     /* ECTF_STRTAB */
-  "String name offset is corrupt",     /* ECTF_BADNAME */
-  "Invalid type identifier",     /* ECTF_BADID */
-  "Type is not a struct or union",     /* ECTF_NOTSOU */
-  "Type is not an enum",     /* ECTF_NOTENUM */
-  "Type is not a struct, union, or enum",     /* ECTF_NOTSUE */
-  "Type is not an integer, float, or enum",     /* ECTF_NOTINTFP */
-  "Type is not an array",     /* ECTF_NOTARRAY */
-  "Type does not reference another type",     /* ECTF_NOTREF */
-  "Input buffer is too small for type name",     /* ECTF_NAMELEN */
-  "No type information available for that name",     /* ECTF_NOTYPE */
-  "Syntax error in type name",     /* ECTF_SYNTAX */
-  "Symbol table entry or type is not a function",    /* ECTF_NOTFUNC */
-  "No function information available for symbol",    /* ECTF_NOFUNCDAT */
-  "Symbol table entry is not a data object",     /* ECTF_NOTDATA */
-  "No type information available for symbol",     /* ECTF_NOTYPEDAT */
-  "No label information available for that name",    /* ECTF_NOLABEL */
-  "File does not contain any labels",     /* ECTF_NOLABELDATA */
-  "Feature not supported",     /* ECTF_NOTSUP */
-  "Invalid enum element name",     /* ECTF_NOENUMNAM */
-  "Invalid member name",     /* ECTF_NOMEMBNAM */
-  "CTF container is read-only",     /* ECTF_RDONLY */
-  "Limit on number of dynamic type members reached", /* ECTF_DTFULL */
-  "Limit on number of dynamic types reached",     /* ECTF_FULL */
-  "Duplicate member or variable name",     /* ECTF_DUPLICATE */
-  "Conflicting type is already defined",     /* ECTF_CONFLICT */
-  "Attempt to roll back past a ctf_update",     /* ECTF_OVERROLLBACK */
-  "Failed to compress CTF data",     /* ECTF_COMPRESS */
-  "Failed to create CTF archive",     /* ECTF_ARCREATE */
-  "Name not found in CTF archive",     /* ECTF_ARNNAME */
-  "Overflow of type bitness or offset in slice",     /* ECTF_SLICEOVERFLOW */
-  "Unknown section number in dump",     /* ECTF_DUMPSECTUNKNOWN */
-  "Section changed in middle of dump",     /* ECTF_DUMPSECTCHANGED */
-  "Feature not yet implemented",     /* ECTF_NOTYET */
-  "Internal error in link",     /* ECTF_INTERNAL */
-  "Type not representable in CTF"     /* ECTF_NONREPRESENTABLE */
-};
-
-static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]);
+/* This construct is due to Bruno Haible: much thanks.  */
+
+/* Give each structure member a unique name.  The name does not matter, so we
+   use the line number in ctf-error.h to uniquify them.  */
+
+#define ERRSTRFIELD(line) ERRSTRFIELD1 (line)
+#define ERRSTRFIELD1(line) ctf_errstr##line
+
+/* The error message strings, each in a unique structure member precisely big
+   enough for that error, plus a str member to access them all as a string
+   table.  */
+
+static const union _ctf_errlist_t
+{
+  __extension__ struct
+  {
+#define _S(n, s) char ERRSTRFIELD (__LINE__) [sizeof (s)];
+#include "ctf-error.h"
+#undef _S
+  };
+  char str[1];
+} _ctf_errlist =
+  {
+   {
+#define _S(n, s) s,
+#include "ctf-error.h"
+#undef _S
+   }
+  };
+
+/* Offsets to each member in the string table, computed using offsetof.  */
+
+static const unsigned int _ctf_erridx[] =
+  {
+#define _S(n, s) [n - ECTF_BASE] = offsetof (union _ctf_errlist_t, ERRSTRFIELD (__LINE__)),
+#include "ctf-error.h"
+#undef _S
+  };
 
 const char *
 ctf_errmsg (int error)
 {
   const char *str;
 
-  if (error >= ECTF_BASE && (error - ECTF_BASE) < _ctf_nerr)
-    str = _ctf_errlist[error - ECTF_BASE];
+  if (error >= ECTF_BASE && (error - ECTF_BASE) < ECTF_NERR)
+    str = _ctf_errlist.str + _ctf_erridx[error - ECTF_BASE];
   else
     str = ctf_strerror (error);
 
diff --git a/libctf/mkerrors.sed b/libctf/mkerrors.sed
new file mode 100644
index 00000000000..146fd4abc1d
--- /dev/null
+++ b/libctf/mkerrors.sed
@@ -0,0 +1,28 @@
+#
+#   Copyright (C) 2020 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING.  If not see
+# <http://www.gnu.org/licenses/>.
+#
+
+# Only process lines in the error-define block
+/= ECTF_BASE/,/ECTF_NERR/ {
+    # Do not process non-errors (braces, ECTF_NERR, etc).
+    /^ *ECTF_/!n;
+    # Strip out the base initializer.
+    s, = ECTF_BASE,,;
+    # Transform errors into _S(...).
+    s@^ *\(ECTF_[^[:blank:],]*\),\{0,1\}[[:blank:]]*/\* \(.*\).  \*/$@_S (\1, "\2")@;
+    p;
+  }
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 03/59] libctf, create: support addition of references to the unimplemented type

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
The deduplicating linker adds types from the linker inputs to the output
via the same API everyone else does, so it's important that we can emit
everything that the compiler wants us to.  Unfortunately, the compiler
may represent the unimplemented type (used for compiler constructs that
CTF cannot currently encode) as type zero or as a type of kind
CTF_K_UNKNOWN, and we don't allow the addition of types that cite the
former.

Adding this support adds a tiny bit of extra complexity: additions of
structure members immediately following a member of the unimplemented
type must be via ctf_add_member_offset or ctf_add_member_encoded, since
we have no idea how big members of the unimplemented type are.
(Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other
attempts to do forbidden things with the unimplemented type.)

Even slices of the unimplemented type are permitted: this is the only
case in which you can slice a type that terminates in a non-integral
type, on the grounds that it was likely integral in the source code,
it's just that we can't represent that sort of integral type properly
yet.

libctf/
        * ctf-create.c (ctf_add_reftype): Support refs to type zero.
        (ctf_add_array): Support array contents of type zero.
        (ctf_add_function): Support arguments and return types of
        type zero.
        (ctf_add_typedef): Support typedefs to type zero.
        (ctf_add_member_offset): Support members of type zero,
        unless added at unspecified (naturally-aligned) offset.
---
 libctf/ctf-create.c | 42 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 808da372de8..67a3f199a96 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -900,7 +900,7 @@ ctf_add_reftype (ctf_file_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
   if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
     return (ctf_set_errno (fp, EINVAL));
 
-  if (ctf_lookup_by_id (&tmp, ref) == NULL)
+  if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
     return CTF_ERR; /* errno is set for us.  */
 
   if ((type = ctf_add_generic (fp, flag, NULL, kind, &dtd)) == CTF_ERR)
@@ -957,12 +957,13 @@ ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
   if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
     return (ctf_set_errno (fp, EINVAL));
 
-  if ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL)
+  if (ref != 0 && ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL))
     return CTF_ERR; /* errno is set for us.  */
 
   kind = ctf_type_kind_unsliced (tmp, ref);
   if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) &&
-      (kind != CTF_K_ENUM))
+      (kind != CTF_K_ENUM)
+      && (ref != 0))
     return (ctf_set_errno (fp, ECTF_NOTINTFP));
 
   if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_SLICE, &dtd)) == CTF_ERR)
@@ -1008,7 +1009,8 @@ ctf_add_array (ctf_file_t *fp, uint32_t flag, const ctf_arinfo_t *arp)
   if (arp == NULL)
     return (ctf_set_errno (fp, EINVAL));
 
-  if (ctf_lookup_by_id (&tmp, arp->ctr_contents) == NULL)
+  if (arp->ctr_contents != 0
+      && ctf_lookup_by_id (&tmp, arp->ctr_contents) == NULL)
     return CTF_ERR; /* errno is set for us.  */
 
   tmp = fp;
@@ -1062,13 +1064,14 @@ ctf_add_function (ctf_file_t *fp, uint32_t flag,
   if (ctc->ctc_flags & CTF_FUNC_VARARG)
     vlen++;       /* Add trailing zero to indicate varargs (see below).  */
 
-  if (ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
+  if (ctc->ctc_return != 0
+      && ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
     return CTF_ERR; /* errno is set for us.  */
 
   for (i = 0; i < ctc->ctc_argc; i++)
     {
       tmp = fp;
-      if (ctf_lookup_by_id (&tmp, argv[i]) == NULL)
+      if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
  return CTF_ERR; /* errno is set for us.  */
     }
 
@@ -1259,7 +1262,7 @@ ctf_add_typedef (ctf_file_t *fp, uint32_t flag, const char *name,
   if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
     return (ctf_set_errno (fp, EINVAL));
 
-  if (ctf_lookup_by_id (&tmp, ref) == NULL)
+  if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
     return CTF_ERR; /* errno is set for us.  */
 
   if ((type = ctf_add_generic (fp, flag, name, CTF_K_TYPEDEF,
@@ -1387,7 +1390,20 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
 
   if ((msize = ctf_type_size (fp, type)) < 0 ||
       (malign = ctf_type_align (fp, type)) < 0)
-    return -1; /* errno is set for us.  */
+    {
+      /* The unimplemented type, and any type that resolves to it, has no size
+ and no alignment: it can correspond to any number of compiler-inserted
+ types.  */
+
+      if (ctf_errno (fp) == ECTF_NONREPRESENTABLE)
+ {
+  msize = 0;
+  malign = 0;
+  ctf_set_errno (fp, 0);
+ }
+      else
+ return -1; /* errno is set for us.  */
+    }
 
   if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
     return (ctf_set_errno (fp, EAGAIN));
@@ -1415,6 +1431,16 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
   ctf_encoding_t linfo;
   ssize_t lsize;
 
+  /* Propagate any error from ctf_type_resolve.  If the last member was
+     of unimplemented type, this may be -ECTF_NONREPRESENTABLE: we
+     cannot insert right after such a member without explicit offset
+     specification, because its alignment and size is not known.  */
+  if (ltype == CTF_ERR)
+    {
+      free (dmd);
+      return -1; /* errno is set for us.  */
+    }
+
   if (ctf_type_encoding (fp, ltype, &linfo) == 0)
     off += linfo.cte_bits;
   else if ((lsize = ctf_type_size (fp, ltype)) > 0)
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 04/59] libctf, create: do not corrupt function types' arglists at insertion time

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
ctf_add_function assumes that function types' arglists are of type
ctf_id_t.  Since they are CTF IDs, they are 32 bits wide, a uint32_t:
unfortunately ctf_id_t is a forward-compatible user-facing 64 bits wide,
and should never ever reach the CTF storage level.

All the CTF code other than ctf_add_function correctly assumes that
function arglists outside dynamic containers are 32 bits wide, so the
serialization machinery ends up cutting off half the arglist, corrupting
all args but the first (a good sign is a bunch of args of ID 0, the
unimplemented type, popping up).

Fix this by copying the arglist into place item by item, casting it
properly, at the same time as we validate the arg types.  Fix the type
of the dtu_argv in the dynamic container and drop the now-unnecessary
cast in the serializer.

libctf/
        * ctf-impl.h (ctf_dtdef_t) <dtu_argv>: Fix type.
        * ctf-create.c (ctf_add_function): Check for unimplemented type
        and populate at the same time.  Populate one-by-one, not via
        memcpy.
        (ctf_serialize): Remove unnecessary cast.
        * ctf-types.c (ctf_func_type_info): Likewise.
        (ctf_func_type_args): Likewise.  Fix comment typo.
---
 libctf/ctf-create.c | 23 +++++++++++++----------
 libctf/ctf-impl.h   |  2 +-
 libctf/ctf-types.c  |  6 +++---
 3 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 67a3f199a96..f91da6ea159 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -448,7 +448,7 @@ ctf_serialize (ctf_file_t *fp)
     uint32_t argc;
 
     for (argc = 0; argc < vlen; argc++)
-      *argv++ = (uint32_t) dtd->dtd_u.dtu_argv[argc];
+      *argv++ = dtd->dtd_u.dtu_argv[argc];
 
     if (vlen & 1)
       *argv++ = 0; /* Pad to 4-byte boundary.  */
@@ -1052,7 +1052,7 @@ ctf_add_function (ctf_file_t *fp, uint32_t flag,
   ctf_dtdef_t *dtd;
   ctf_id_t type;
   uint32_t vlen;
-  ctf_id_t *vdat = NULL;
+  uint32_t *vdat = NULL;
   ctf_file_t *tmp = fp;
   size_t i;
 
@@ -1068,19 +1068,23 @@ ctf_add_function (ctf_file_t *fp, uint32_t flag,
       && ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
     return CTF_ERR; /* errno is set for us.  */
 
-  for (i = 0; i < ctc->ctc_argc; i++)
-    {
-      tmp = fp;
-      if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
- return CTF_ERR; /* errno is set for us.  */
-    }
-
   if (vlen > CTF_MAX_VLEN)
     return (ctf_set_errno (fp, EOVERFLOW));
 
   if (vlen != 0 && (vdat = malloc (sizeof (ctf_id_t) * vlen)) == NULL)
     return (ctf_set_errno (fp, EAGAIN));
 
+  for (i = 0; i < ctc->ctc_argc; i++)
+    {
+      tmp = fp;
+      if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
+ {
+  free (vdat);
+  return CTF_ERR;   /* errno is set for us.  */
+ }
+      vdat[i] = (uint32_t) argv[i];
+    }
+
   if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_FUNCTION,
        &dtd)) == CTF_ERR)
     {
@@ -1091,7 +1095,6 @@ ctf_add_function (ctf_file_t *fp, uint32_t flag,
   dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
   dtd->dtd_data.ctt_type = (uint32_t) ctc->ctc_return;
 
-  memcpy (vdat, argv, sizeof (ctf_id_t) * ctc->ctc_argc);
   if (ctc->ctc_flags & CTF_FUNC_VARARG)
     vdat[vlen - 1] = 0;   /* Add trailing zero to indicate varargs.  */
   dtd->dtd_u.dtu_argv = vdat;
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index b20a4f05a80..fdd48f0d331 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -172,7 +172,7 @@ typedef struct ctf_dtdef
     ctf_list_t dtu_members; /* struct, union, or enum */
     ctf_arinfo_t dtu_arr; /* array */
     ctf_encoding_t dtu_enc; /* integer or float */
-    ctf_id_t *dtu_argv; /* function */
+    uint32_t *dtu_argv; /* function */
     ctf_slice_t dtu_slice; /* slice */
   } dtd_u;
 } ctf_dtdef_t;
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index cd910434ea4..35253cb3cbc 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -1163,7 +1163,7 @@ ctf_func_type_info (ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
   if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
     args = (uint32_t *) ((uintptr_t) tp + increment);
   else
-    args = (uint32_t *) dtd->dtd_u.dtu_argv;
+    args = dtd->dtd_u.dtu_argv;
 
   if (fip->ctc_argc != 0 && args[fip->ctc_argc - 1] == 0)
     {
@@ -1174,7 +1174,7 @@ ctf_func_type_info (ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
   return 0;
 }
 
-/* Given a type ID relating to a function type,, return the arguments for the
+/* Given a type ID relating to a function type, return the arguments for the
    function.  */
 
 int
@@ -1200,7 +1200,7 @@ ctf_func_type_args (ctf_file_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv
   if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
     args = (uint32_t *) ((uintptr_t) tp + increment);
   else
-    args = (uint32_t *) dtd->dtd_u.dtu_argv;
+    args = dtd->dtd_u.dtu_argv;
 
   for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
     *argv++ = *args++;
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 05/59] libctf, create: add explicit casts for variables' and slices' types

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
This is technically unnecessary -- the compiler is quite capable of
doing the range reduction for us -- but it does mean that all
assignments of a ctf_id_t to its final uint32_t representation now have
appropriate explicit casts.

libctf/
        * ctf-create.c (ctf_serialize): Add cast.
        (ctf_add_slice): Likewise.
---
 libctf/ctf-create.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index f91da6ea159..bc0ad802dd2 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -373,7 +373,7 @@ ctf_serialize (ctf_file_t *fp)
       ctf_varent_t *var = &dvarents[i];
 
       ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name);
-      var->ctv_type = dvd->dvd_type;
+      var->ctv_type = (uint32_t) dvd->dvd_type;
     }
   assert (i == nvars);
 
@@ -972,7 +972,7 @@ ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
   dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
   dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
  / CHAR_BIT);
-  dtd->dtd_u.dtu_slice.cts_type = ref;
+  dtd->dtd_u.dtu_slice.cts_type = (uint32_t) ref;
   dtd->dtd_u.dtu_slice.cts_bits = ep->cte_bits;
   dtd->dtd_u.dtu_slice.cts_offset = ep->cte_offset;
 
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 06/59] libctf, types: allow ctf_type_reference of dynamic slices

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
One spot was missed when we rejigged ctf_update into ctf_serialize and
allowed all operations on dynamic containers: ctf_type_reference of
slices.  A dynamic slice's vlen state is stored in the dtu_slice member,
so fetch it from there.

libctf/
        * ctf-types.c (ctf_type_reference): Add support for dynamic slices.
---
 libctf/ctf-types.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index 35253cb3cbc..9c10905ea11 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -680,10 +680,19 @@ ctf_type_reference (ctf_file_t *fp, ctf_id_t type)
       /* Slices store their type in an unusual place.  */
     case CTF_K_SLICE:
       {
+ ctf_dtdef_t *dtd;
  const ctf_slice_t *sp;
- ssize_t increment;
- (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
- sp = (const ctf_slice_t *) ((uintptr_t) tp + increment);
+
+ if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
+  {
+    ssize_t increment;
+
+    (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
+    sp = (const ctf_slice_t *) ((uintptr_t) tp + increment);
+  }
+ else
+  sp = &dtd->dtd_u.dtu_slice;
+
  return sp->cts_type;
       }
     default:
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 07/59] libctf, open: drop unnecessary historical wart around forwards

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
When opening, we consider a forward with a kind above the maximum
allowable set of kinds and a forward of kind CTF_K_UNKNOWN to be a
forward to a struct.  Whatever CTF version it was that produced
forwards with no associated kind, it predates anything we can read:
remove this wart.

libctf/
        * ctf-open.c (init_types): Remove typeless CTF_K_FORWARD
        special-casing.
---
 libctf/ctf-open.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index 4daa1e45351..05672f36498 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -692,17 +692,11 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
       if (vbytes < 0)
  return ECTF_CORRUPT;
 
+      /* For forward declarations, ctt_type is the CTF_K_* kind for the tag,
+ so bump that population count too.  */
       if (kind == CTF_K_FORWARD)
- {
-  /* For forward declarations, ctt_type is the CTF_K_* kind for the tag,
-     so bump that population count too.  If ctt_type is unknown, treat
-     the tag as a struct.  */
+ pop[tp->ctt_type]++;
 
-  if (tp->ctt_type == CTF_K_UNKNOWN || tp->ctt_type >= CTF_K_MAX)
-    pop[CTF_K_STRUCT]++;
-  else
-    pop[tp->ctt_type]++;
- }
       tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
       pop[kind]++;
     }
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 08/59] libctf, create: member names of "" and NULL should be the same

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
This matters for the case of unnamed bitfields, whose names are the null
string.  These are special in that they are the only members whose
"names" are allowed to be duplicated in a single struct, but we were
only handling this for the case where name == NULL.  Translate "" to
NULL to help callers.

libctf/
        * ctf-create.c (ctf_add_member_offset): Support names of ""
        as if they were the null pointer.
---
 libctf/ctf-create.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index bc0ad802dd2..848e725ef24 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -1371,6 +1371,9 @@ ctf_add_member_offset (ctf_file_t *fp, ctf_id_t souid, const char *name,
   if (dtd == NULL)
     return (ctf_set_errno (fp, ECTF_BADID));
 
+  if (name != NULL && name[0] == '\0')
+    name = NULL;
+
   kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
   root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
   vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 09/59] libctf, create: fix addition of anonymous struct/union members

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
A Solaris-era bug causes us to check the offsets of types with no names
against the first such type when ctf_add_type()ing members to a struct
or union.  Members with no names (i.e. anonymous struct/union members)
can appear as many times as you like in a struct/union, so this check
should be skipped in this case.

libctf/
        * ctf-create.c (membcmp)  Skip nameless members.
---
 libctf/ctf-create.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 848e725ef24..5cbcfe0a702 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -1602,6 +1602,11 @@ membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
   ctf_bundle_t *ctb = arg;
   ctf_membinfo_t ctm;
 
+  /* Don't check nameless members (e.g. anonymous structs/unions) against each
+     other.  */
+  if (name[0] == 0)
+    return 0;
+
   if (ctf_member_info (ctb->ctb_file, ctb->ctb_type, name, &ctm) < 0)
     {
       ctf_dprintf ("Conflict due to member %s iteration error: %s.\n", name,
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 10/59] libctf, create: empty dicts are dirty to start with

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
Without this, an empty dict that is written out immediately never gets
any content at all: even the header is left empty.

libctf/
        * ctf-create.c (ctf_create): Mark dirty.
---
 libctf/ctf-create.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 5cbcfe0a702..1416d187fd9 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -126,6 +126,7 @@ ctf_create (int *errp)
   fp->ctf_dtoldid = 0;
   fp->ctf_snapshots = 1;
   fp->ctf_snapshot_lu = 0;
+  fp->ctf_flags |= LCTF_DIRTY;
 
   ctf_set_ctl_hashes (fp);
   ctf_setmodel (fp, CTF_MODEL_NATIVE);
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 11/59] libctf, types: support slices of anything terminating in an int

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
It is perfectly valid C to say e.g.

typedef u64 int;
struct foo_t
  {
    const volatile u64 wibble:2;
  };

i.e. bitfields have to be integral types, but they can be cv-qualified
integral types or typedefs of same, etc.

This is easy to fix: do a ctf_type_resolve_unsliced() at creation time
to ensure the ultimate type is integral, and ctf_type_resolve() at
lookup time so that if you somehow have e.g. a slice of a typedef of a
slice of a cv-qualified int, we pull the encoding that the topmost slice
is based on out of the subsidiary slice (and then modify it), not out of
the underlying int.  (This last bit is rather academic right now, since
all slices override exactly the same properties of the underlying type,
but it's still the right thing to do.)

libctf/
        * ctf-create.c (ctf_add_slice): Support slices of any kind that
        resolves to an integral type.
        * ctf-types.c (ctf_type_encoding): Resolve the type before
        fishing its encoding out.
---
 libctf/ctf-create.c | 9 ++++++++-
 libctf/ctf-types.c  | 9 +++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 1416d187fd9..c13b83d4d3b 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -944,6 +944,7 @@ ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
        const ctf_encoding_t *ep)
 {
   ctf_dtdef_t *dtd;
+  ctf_id_t resolved_ref = ref;
   ctf_id_t type;
   int kind;
   const ctf_type_t *tp;
@@ -961,7 +962,13 @@ ctf_add_slice (ctf_file_t *fp, uint32_t flag, ctf_id_t ref,
   if (ref != 0 && ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL))
     return CTF_ERR; /* errno is set for us.  */
 
-  kind = ctf_type_kind_unsliced (tmp, ref);
+  /* Make sure we ultimately point to an integral type.  We also allow slices to
+     point to the unimplemented type, for now, because the compiler can emit
+     such slices, though they're not very much use.  */
+
+  resolved_ref = ctf_type_resolve_unsliced (tmp, ref);
+  kind = ctf_type_kind_unsliced (tmp, resolved_ref);
+
   if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) &&
       (kind != CTF_K_ENUM)
       && (ref != 0))
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index 9c10905ea11..f5a1fc0ae12 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -758,9 +758,12 @@ ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
   {
     const ctf_slice_t *slice;
     ctf_encoding_t underlying_en;
+    ctf_id_t underlying;
+
     slice = &dtd->dtd_u.dtu_slice;
+    underlying = ctf_type_resolve (fp, slice->cts_type);
+    data = ctf_type_encoding (fp, underlying, &underlying_en);
 
-    data = ctf_type_encoding (fp, slice->cts_type, &underlying_en);
     ep->cte_format = underlying_en.cte_format;
     ep->cte_offset = slice->cts_offset;
     ep->cte_bits = slice->cts_bits;
@@ -792,9 +795,11 @@ ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
       {
  const ctf_slice_t *slice;
  ctf_encoding_t underlying_en;
+ ctf_id_t underlying;
 
  slice = (ctf_slice_t *) ((uintptr_t) tp + increment);
- data = ctf_type_encoding (fp, slice->cts_type, &underlying_en);
+ underlying = ctf_type_resolve (fp, slice->cts_type);
+ data = ctf_type_encoding (fp, underlying, &underlying_en);
 
  ep->cte_format = underlying_en.cte_format;
  ep->cte_offset = slice->cts_offset;
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 12/59] libctf, types: ints, floats and typedefs with no name are invalid

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
Report them as such, rather than letting ctf_decl_sprintf wrongly
conclude that the printing of zero characters means we are out of
memory.

libctf/
        * ctf-types.c (ctf_type_aname): Return ECTF_CORRUPT if
        ints, floats or typedefs have no name.  Fix comment typo.
---
 libctf/ctf-types.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index f5a1fc0ae12..db42b9e8a90 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -316,7 +316,7 @@ ctf_id_t ctf_lookup_by_rawhash (ctf_file_t *fp, ctf_names_t *np, const char *nam
   return id;
 }
 
-/* Lookup the given type ID and return its name as a new dynamcally-allocated
+/* Lookup the given type ID and return its name as a new dynamically-allocated
    string.  */
 
 char *
@@ -379,6 +379,15 @@ ctf_type_aname (ctf_file_t *fp, ctf_id_t type)
     case CTF_K_INTEGER:
     case CTF_K_FLOAT:
     case CTF_K_TYPEDEF:
+      /* Integers, floats, and typedefs must always be named types.  */
+
+      if (name[0] == '\0')
+ {
+  ctf_set_errno (fp, ECTF_CORRUPT);
+  ctf_decl_fini (&cd);
+  return NULL;
+ }
+
       ctf_decl_sprintf (&cd, "%s", name);
       break;
     case CTF_K_POINTER:
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 13/59] libctf, archive: stop ctf_arc_bufopen triggering crazy unmaps

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
The archive machinery mmap()s its archives when possible: so it arranges
to do appropriately-sized unmaps by recording the unmap length in the
ctfa_magic value and unmapping that.

This brilliant (horrible) trick works less well when ctf_arc_bufopen is
called with an existing buffer (which might be a readonly mapping).
ctf_arc_bufopen always returns a ctf_archive_t wrapper, so record in
there the necessity to not unmap anything when a bufopen'ed archive is
closed again.

libctf/
        * ctf-impl.h (struct ctf_archive_internal)
        <ctfi_unmap_on_close>: New.
        (ctf_new_archive_internal): Adjust.
        * ctf-archive.c (ctf_new_archive_internal): Likewise.
        Initialize ctfi_unmap_on_close.  Adjust error path.
        (ctf_arc_bufopen): Adjust ctf_new_archive_internal call
        (unmap_on_close is 0).
        (ctf_arc_close): Only unmap if ctfi_unmap_on_close.
        * ctf-open-bfd.c (ctf_fdopen): Adjust.
---
 libctf/ctf-archive.c  | 26 ++++++++++++++++++++------
 libctf/ctf-impl.h     | 10 ++++++----
 libctf/ctf-open-bfd.c |  4 ++--
 3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index ac13d6dd5e9..303c94d97a4 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -343,10 +343,11 @@ search_modent_by_name (const void *key, const void *ent, void *arg)
 
 /* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
    ctf_file.  Closes ARC and/or FP on error.  Arrange to free the SYMSECT or
-   STRSECT, as needed, on close.  */
+   STRSECT, as needed, on close.  Possibly do not unmap on close.  */
 
 struct ctf_archive_internal *
-ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
+ctf_new_archive_internal (int is_archive, int unmap_on_close,
+  struct ctf_archive *arc,
   ctf_file_t *fp, const ctf_sect_t *symsect,
   const ctf_sect_t *strsect,
   int *errp)
@@ -356,7 +357,10 @@ ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
   if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL)
     {
       if (is_archive)
- ctf_arc_close_internal (arc);
+ {
+  if (unmap_on_close)
+    ctf_arc_close_internal (arc);
+ }
       else
  ctf_file_close (fp);
       return (ctf_set_open_errno (errp, errno));
@@ -371,6 +375,7 @@ ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
   if (strsect)
      memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
   arci->ctfi_free_symsect = 0;
+  arci->ctfi_unmap_on_close = unmap_on_close;
 
   return arci;
 }
@@ -389,7 +394,13 @@ ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
   if (ctfsect->cts_size > sizeof (uint64_t) &&
       ((*(uint64_t *) ctfsect->cts_data) == CTFA_MAGIC))
     {
-      /* The archive is mmappable, so this operation is trivial.  */
+      /* The archive is mmappable, so this operation is trivial.
+
+ This buffer is nonmodifiable, so the trick involving mmapping only part
+ of it and storing the length in the magic number is not applicable: so
+ record this fact in the archive-wrapper header.  (We cannot record it
+ in the archive, because the archive may very well be a read-only
+ mapping.)  */
 
       is_archive = 1;
       arc = (struct ctf_archive *) ctfsect->cts_data;
@@ -404,7 +415,7 @@ ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
   return NULL;
  }
     }
-  return ctf_new_archive_internal (is_archive, arc, fp, symsect, strsect,
+  return ctf_new_archive_internal (is_archive, 0, arc, fp, symsect, strsect,
    errp);
 }
 
@@ -481,7 +492,10 @@ ctf_arc_close (ctf_archive_t *arc)
     return;
 
   if (arc->ctfi_is_archive)
-    ctf_arc_close_internal (arc->ctfi_archive);
+    {
+      if (arc->ctfi_unmap_on_close)
+ ctf_arc_close_internal (arc->ctfi_archive);
+    }
   else
     ctf_file_close (arc->ctfi_file);
   if (arc->ctfi_free_symsect)
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index fdd48f0d331..4661aa8c7a9 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -312,6 +312,7 @@ struct ctf_file
 struct ctf_archive_internal
 {
   int ctfi_is_archive;
+  int ctfi_unmap_on_close;
   ctf_file_t *ctfi_file;
   struct ctf_archive *ctfi_archive;
   ctf_sect_t ctfi_symsect;
@@ -443,10 +444,11 @@ extern void ctf_str_rollback (ctf_file_t *, ctf_snapshot_id_t);
 extern void ctf_str_purge_refs (ctf_file_t *);
 extern ctf_strs_writable_t ctf_str_write_strtab (ctf_file_t *);
 
-extern struct ctf_archive_internal *ctf_new_archive_internal
- (int is_archive, struct ctf_archive *arc,
- ctf_file_t *fp, const ctf_sect_t *symsect,
- const ctf_sect_t *strsect, int *errp);
+extern struct ctf_archive_internal *
+ctf_new_archive_internal (int is_archive, int unmap_on_close,
+  struct ctf_archive *, ctf_file_t *,
+  const ctf_sect_t *symsect,
+  const ctf_sect_t *strsect, int *errp);
 extern struct ctf_archive *ctf_arc_open_internal (const char *, int *);
 extern void ctf_arc_close_internal (struct ctf_archive *);
 extern void *ctf_set_open_errno (int *, int);
diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c
index dafa265f9d8..2d2d572c88f 100644
--- a/libctf/ctf-open-bfd.c
+++ b/libctf/ctf-open-bfd.c
@@ -230,7 +230,7 @@ ctf_fdopen (int fd, const char *filename, const char *target, int *errp)
       fp->ctf_data_mmapped = data;
       fp->ctf_data_mmapped_len = (size_t) st.st_size;
 
-      return ctf_new_archive_internal (0, NULL, fp, NULL, NULL, errp);
+      return ctf_new_archive_internal (0, 1, NULL, fp, NULL, NULL, errp);
     }
 
   if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0)
@@ -243,7 +243,7 @@ ctf_fdopen (int fd, const char *filename, const char *target, int *errp)
       if ((arc = ctf_arc_open_internal (filename, errp)) == NULL)
  return NULL; /* errno is set for us.  */
 
-      return ctf_new_archive_internal (1, arc, NULL, NULL, NULL, errp);
+      return ctf_new_archive_internal (1, 1, arc, NULL, NULL, NULL, errp);
     }
 
   /* Attempt to open the file with BFD.  We must dup the fd first, since bfd
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 14/59] libctf: having debugging enabled is unlikely

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
The deduplicator can emit enormous amounts of debugging output,
so much so that a later commit will introduce a new configure flag
that configures most of it out (and configures it out by default).

It became clear that when this configure flag is on, but debugging is
not enabled via the LIBCTF_DEBUG environment variable, up to 10% of
runtime can be spent on branch mispredictions checking the _libctf_debug
variable.  Mark it unlikely to be set (when it is set, performance is
likely to be the least of your concerns).

libctf/
        * ctf-subr.c (ctf_dprintf): _libctf_debug is unlikely to be set.
---
 libctf/ctf-subr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libctf/ctf-subr.c b/libctf/ctf-subr.c
index 114df843212..a5cde9d6f20 100644
--- a/libctf/ctf-subr.c
+++ b/libctf/ctf-subr.c
@@ -183,7 +183,7 @@ int ctf_getdebug (void)
 _libctf_printflike_ (1, 2)
 void ctf_dprintf (const char *format, ...)
 {
-  if (_libctf_debug)
+  if (_libctf_unlikely_ (_libctf_debug))
     {
       va_list alist;
 
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 15/59] libctf: add ctf_type_name_raw

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
We already have a function ctf_type_aname_raw, which returns the raw
name of a type with no decoration for structures or arrays or anything
like that: just the underlying name of whatever it is that's being
ultimately pointed at.

But this can be inconvenient to use, becauswe it always allocates new
storage for the string and copies it in, so it can potentially fail.
Add ctf_type_name_raw, which just returns the string directly out of
libctf's guts: it will live until the ctf_file_t is closed (if we later
gain the ability to remove types from writable dicts, it will live as
long as the type lives).

Reimplement ctf_type_aname_raw in terms of it.

include/
        * ctf-api.c (ctf_type_name_raw): New.

libctf/
        * ctf-types.c (ctf_type_name_raw): New.
        (ctf_type_aname_raw): Reimplement accordingly.
---
 include/ctf-api.h  |  1 +
 libctf/ctf-types.c | 23 +++++++++++++++++------
 libctf/libctf.ver  |  1 +
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 2e3e28b840c..363b5c258ca 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -324,6 +324,7 @@ extern char *ctf_type_aname (ctf_file_t *, ctf_id_t);
 extern char *ctf_type_aname_raw (ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_lname (ctf_file_t *, ctf_id_t, char *, size_t);
 extern char *ctf_type_name (ctf_file_t *, ctf_id_t, char *, size_t);
+extern const char *ctf_type_name_raw (ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_size (ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_align (ctf_file_t *, ctf_id_t);
 extern int ctf_type_kind (ctf_file_t *, ctf_id_t);
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index db42b9e8a90..ce3890c33a6 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -472,19 +472,30 @@ ctf_type_name (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
   return (rv >= 0 && (size_t) rv < len ? buf : NULL);
 }
 
-/* Lookup the given type ID and return its raw, unadorned, undecorated name as a
-   new dynamcally-allocated string.  */
+/* Lookup the given type ID and return its raw, unadorned, undecorated name.
+   The name will live as long as its ctf_file_t does.  */
 
-char *
-ctf_type_aname_raw (ctf_file_t *fp, ctf_id_t type)
+const char *
+ctf_type_name_raw (ctf_file_t *fp, ctf_id_t type)
 {
   const ctf_type_t *tp;
 
   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
     return NULL; /* errno is set for us.  */
 
-  if (ctf_strraw (fp, tp->ctt_name) != NULL)
-    return strdup (ctf_strraw (fp, tp->ctt_name));
+  return ctf_strraw (fp, tp->ctt_name);
+}
+
+/* Lookup the given type ID and return its raw, unadorned, undecorated name as a
+   new dynamically-allocated string.  */
+
+char *
+ctf_type_aname_raw (ctf_file_t *fp, ctf_id_t type)
+{
+  const char *name = ctf_type_name_raw (fp, type);
+
+  if (name != NULL)
+    return strdup (name);
 
   return NULL;
 }
diff --git a/libctf/libctf.ver b/libctf/libctf.ver
index aad304bc0d9..30a0b087bd6 100644
--- a/libctf/libctf.ver
+++ b/libctf/libctf.ver
@@ -57,6 +57,7 @@ LIBCTF_1.0 {
  ctf_type_resolve;
  ctf_type_lname;
  ctf_type_name;
+ ctf_type_name_raw;
  ctf_type_aname;
  ctf_type_aname_raw;
  ctf_type_size;
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 16/59] libctf: add ctf_type_kind_forwarded

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
This is just like ctf_type_kind, except that forwards get the
type of the thing being pointed to rather than CTF_K_FORWARD.

include/
        * ctf-api.h (ctf_type_kind_forwarded): New.
libctf/
        * ctf-types.c (ctf_type_kind_forwarded): New.
---
 include/ctf-api.h  |  1 +
 libctf/ctf-types.c | 20 ++++++++++++++++++++
 libctf/libctf.ver  |  1 +
 3 files changed, 22 insertions(+)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 363b5c258ca..87446a5f7d1 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -328,6 +328,7 @@ extern const char *ctf_type_name_raw (ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_size (ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_align (ctf_file_t *, ctf_id_t);
 extern int ctf_type_kind (ctf_file_t *, ctf_id_t);
+extern int ctf_type_kind_forwarded (ctf_file_t *, ctf_id_t);
 extern ctf_id_t ctf_type_reference (ctf_file_t *, ctf_id_t);
 extern ctf_id_t ctf_type_pointer (ctf_file_t *, ctf_id_t);
 extern int ctf_type_encoding (ctf_file_t *, ctf_id_t, ctf_encoding_t *);
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index ce3890c33a6..d8f848cf893 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -677,6 +677,26 @@ ctf_type_kind (ctf_file_t *fp, ctf_id_t type)
   return kind;
 }
 
+/* Return the kind of this type, except, for forwards, return the kind of thing
+   this is a forward to.  */
+int
+ctf_type_kind_forwarded (ctf_file_t *fp, ctf_id_t type)
+{
+  int kind;
+  const ctf_type_t *tp;
+
+  if ((kind = ctf_type_kind (fp, type)) < 0)
+    return -1; /* errno is set for us.  */
+
+  if (kind != CTF_K_FORWARD)
+    return kind;
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return -1; /* errno is set for us.  */
+
+  return tp->ctt_type;
+}
+
 /* If the type is one that directly references another type (such as POINTER),
    then return the ID of the type to which it refers.  */
 
diff --git a/libctf/libctf.ver b/libctf/libctf.ver
index 30a0b087bd6..b8c5133d3f9 100644
--- a/libctf/libctf.ver
+++ b/libctf/libctf.ver
@@ -63,6 +63,7 @@ LIBCTF_1.0 {
  ctf_type_size;
  ctf_type_align;
  ctf_type_kind;
+ ctf_type_kind_forwarded;
  ctf_type_reference;
  ctf_type_pointer;
  ctf_type_encoding;
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 17/59] libctf: add ctf_member_count

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
This returns the number of members in a struct or union, or the number
of enumerations in an enum.  (This was only available before now by
iterating across every member, but it can be returned much faster than
that.)

include/
        * ctf-api.h (ctf_member_count): New.

libctf/
        * ctf-types.c (ctf_member_count): New.
        * libctf.ver: New public function.
---
 include/ctf-api.h  |  1 +
 libctf/ctf-types.c | 24 ++++++++++++++++++++++++
 libctf/libctf.ver  |  1 +
 3 files changed, 26 insertions(+)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 87446a5f7d1..7cdf4a56235 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -349,6 +349,7 @@ extern const char *ctf_label_get (ctf_file_t *);
 extern const char *ctf_label_topmost (ctf_file_t *);
 extern int ctf_label_info (ctf_file_t *, const char *, ctf_lblinfo_t *);
 
+extern int ctf_member_count (ctf_file_t *, ctf_id_t);
 extern int ctf_member_iter (ctf_file_t *, ctf_id_t, ctf_member_f *, void *);
 extern int ctf_enum_iter (ctf_file_t *, ctf_id_t, ctf_enum_f *, void *);
 extern int ctf_type_iter (ctf_file_t *, ctf_type_f *, void *);
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index d8f848cf893..93967c6aa8d 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -963,6 +963,30 @@ ctf_type_compat (ctf_file_t *lfp, ctf_id_t ltype,
     }
 }
 
+/* Return the number of members in a STRUCT or UNION, or the number of
+   enumerators in an ENUM.  */
+
+int
+ctf_member_count (ctf_file_t *fp, ctf_id_t type)
+{
+  ctf_file_t *ofp = fp;
+  const ctf_type_t *tp;
+  uint32_t kind;
+
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return -1; /* errno is set for us.  */
+
+  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+    return -1; /* errno is set for us.  */
+
+  kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+
+  if (kind != CTF_K_STRUCT && kind != CTF_K_UNION && kind != CTF_K_ENUM)
+    return (ctf_set_errno (ofp, ECTF_NOTSUE));
+
+  return LCTF_INFO_VLEN (fp, tp->ctt_info);
+}
+
 /* Return the type and offset for a given member of a STRUCT or UNION.  */
 
 int
diff --git a/libctf/libctf.ver b/libctf/libctf.ver
index b8c5133d3f9..77b380ca991 100644
--- a/libctf/libctf.ver
+++ b/libctf/libctf.ver
@@ -73,6 +73,7 @@ LIBCTF_1.0 {
 
  ctf_member_info;
  ctf_array_info;
+ ctf_member_count;
 
  ctf_enum_name;
  ctf_enum_value;
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 18/59] libctf: add ctf_archive_count

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
Another count that was otherwise unavailable without doing expensive
operations.

include/
        * ctf-api.h (ctf_archive_count): New.

libctf/
        * ctf-archive.c (ctf_archive_count): New.
        * libctf.ver: New public function.
---
 include/ctf-api.h    |  1 +
 libctf/ctf-archive.c | 10 ++++++++++
 libctf/libctf.ver    |  1 +
 3 files changed, 12 insertions(+)

diff --git a/include/ctf-api.h b/include/ctf-api.h
index 7cdf4a56235..fb797a3346d 100644
--- a/include/ctf-api.h
+++ b/include/ctf-api.h
@@ -276,6 +276,7 @@ extern ctf_file_t *ctf_arc_open_by_name_sections (const ctf_archive_t *,
   const ctf_sect_t *,
   const ctf_sect_t *,
   const char *, int *);
+extern size_t ctf_archive_count (const ctf_archive_t *);
 
 /* The next functions return or close real CTF files, or write out CTF archives,
    not opaque containers around either.  */
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index 303c94d97a4..1cfe40f6e3a 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -624,6 +624,16 @@ ctf_arc_open_by_offset (const struct ctf_archive *arc,
   return fp;
 }
 
+/* Return the number of members in an archive.  */
+size_t
+ctf_archive_count (const ctf_archive_t *wrapper)
+{
+  if (!wrapper->ctfi_is_archive)
+    return 1;
+
+  return wrapper->ctfi_archive->ctfa_nfiles;
+}
+
 /* Raw iteration over all CTF files in an archive.  We pass the raw data for all
    CTF files in turn to the specified callback function.  */
 static int
diff --git a/libctf/libctf.ver b/libctf/libctf.ver
index 77b380ca991..375dee8fc77 100644
--- a/libctf/libctf.ver
+++ b/libctf/libctf.ver
@@ -135,6 +135,7 @@ LIBCTF_1.0 {
  ctf_arc_close;
  ctf_arc_open_by_name;
  ctf_arc_open_by_name_sections;
+ ctf_archive_count;
  ctf_archive_iter;
  ctf_archive_raw_iter;
  ctf_get_arc;
--
2.27.0.247.g3dff7de930

Reply | Threaded
Open this post in threaded view
|

[PATCH 19/59] libctf: fix __extension__ with non-GNU C compilers

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
We forgot to #define __extension__ to nothing in this case.

libctf/
        * ctf-impl.h [!__GNUC__] (__extension__): Define to nothing.
---
 libctf/ctf-impl.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 4661aa8c7a9..f832c71b97c 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -65,6 +65,7 @@ extern "C"
 #define _libctf_unlikely_(x) (x)
 #define _libctf_unused_
 #define _libctf_malloc_
+#define __extension__
 
 #endif
 
--
2.27.0.247.g3dff7de930

1234