diff --git a/include/ctf-api.h b/include/ctf-api.h index 5883c5321df..c0aa0db2fed 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -533,13 +533,38 @@ extern void *ctf_getspecific (ctf_dict_t *); extern int ctf_errno (ctf_dict_t *); extern const char *ctf_errmsg (int); -/* Return the version of CTF dicts written by writeout functions. The - argument must currently be zero. All dicts with versions below the value - returned by this function can be read by the library. CTF dicts written - by other non-GNU CTF libraries (e.g. that in FreeBSD) are not compatible - and cannot be read by this library. */ +/* BTF/CTF writeout version info. -extern int ctf_version (int); + ctf_btf_mode has three levels: + + - LIBCTF_BTM_ALWAYS writes out full-blown CTFv4 at all times + - LIBCTF_BTM_POSSIBLE writes out CTFv4 if needed to avoid information loss, + BTF otherwise. If compressing, the same as LIBCTF_BTM_ALWAYS. + - LIBCTF_BTM_BTF writes out BTF always, and errors otherwise. + + Note that no attempt is made to downgrade existing CTF dicts to BTF: if you + read in a CTF dict and turn on LIBCTF_BTM_POSSIBLE, you'll get a CTF dict; if + you turn on LIBCTF_BTM_BTF, you'll get an unconditional error. Thus, this is + really useful only when reading in BTF dicts or when creating new dicts. */ + +typedef enum ctf_btf_mode +{ + LIBCTF_BTM_BTF = 0, + LIBCTF_BTM_POSSIBLE = 1, + LIBCTF_BTM_ALWAYS = 2 +} ctf_btf_mode_t; + +/* Set the CTF library client version to the specified version: this is the + version of dicts written out by the ctf_write* functions. If version is + zero, we just return the default library version number. The BTF version + (for CTFv4 and above) is indicated via btf_hdr_len, also zero for "no + change". + + You can influence what type kinds are written out to a CTFv4 dict via the + ctf_write_suppress_kind() function. */ + +extern int ctf_version (int ctf_version_, size_t btf_hdr_len, + ctf_btf_mode_t btf_mode); /* Given a symbol table index corresponding to a function symbol, return info on the type of a given function's arguments or return value, or its parameter @@ -1057,13 +1082,17 @@ extern ctf_snapshot_id_t ctf_snapshot (ctf_dict_t *); extern int ctf_rollback (ctf_dict_t *, ctf_snapshot_id_t); extern int ctf_discard (ctf_dict_t *); -/* Dict writeout. +/* Dict writeout. See ctf_version(). ctf_write: write out an uncompressed dict to an fd. ctf_compress_write: write out a compressed dict to an fd (currently always gzip, but this may change in future). ctf_write_mem: write out a dict to a buffer and return it and its size, - compressing it if its uncompressed size is over THRESHOLD. */ + compressing it if its uncompressed size is over THRESHOLD. + + If the ctf_btf_mode is not LIBCTF_BTM_ALWAYS and the threshold is -1, + the resulting dict may be pure BTF. + */ extern int ctf_write (ctf_dict_t *, int); extern int ctf_compress_write (ctf_dict_t * fp, int fd); diff --git a/libctf/ctf-api.c b/libctf/ctf-api.c index 60a53f25fd0..466491d5bae 100644 --- a/libctf/ctf-api.c +++ b/libctf/ctf-api.c @@ -27,33 +27,63 @@ #define ENOTSUP ENOSYS #endif -int _libctf_version = CTF_VERSION; /* Library client version. */ -int _libctf_debug = 0; /* Debugging messages enabled. */ +static int _libctf_version = CTF_VERSION; /* Library client version. */ +static size_t _btf_hdr_len = sizeof (ctf_btf_header_t); +static int _libctf_debug = 0; /* Debugging messages enabled. */ -/* Set the CTF library client version to the specified version. If version is - zero, we just return the default library version number. */ +ctf_btf_mode_t _libctf_btf_mode = LIBCTF_BTM_POSSIBLE; /* BTF writeout mode. */ + +/* Set the CTF library client version to the specified version: this is the + version of dicts written out by the ctf_write* functions. If version is + zero, we just return the default library version number. The BTF version + (for CTFv4 and above) is indicated via btf_hdr_len, also zero for "no + change". + + btf_mode has three levels: + + - LIBCTF_BTM_ALWAYS writes out full-blown CTFv4 at all times + - LIBCTF_BTM_POSSIBLE writes out CTFv4 if needed to avoid + information loss, BTF otherwise (and always writes out CTFv4 + if compressing) + - LIBCTF_BTM_BTF writes out BTF always, and errors otherwise (e.g. + if compressing) + + You can influence what type kinds are written out to a CTFv4 dict via the + ctf_write_suppress_kind() function. */ int -ctf_version (int version) +ctf_version (int ctf_version_, size_t btf_hdr_len, ctf_btf_mode_t btf_mode) { - if (version < 0) + if (ctf_version_ < 0 || btf_mode < 0 || btf_mode > 2) { errno = EINVAL; return -1; } - if (version > 0) + if (ctf_version_ > 0) { /* Dynamic version switching is not presently supported. */ - if (version != CTF_VERSION) - { - errno = ENOTSUP; - return -1; - } - ctf_dprintf ("ctf_version: client using version %d\n", version); - _libctf_version = version; + if (ctf_version_ != _libctf_version) + goto err; + + ctf_dprintf ("ctf_version: client using version %i\n", ctf_version_); } - return _libctf_version; + if (btf_hdr_len > 0) + { + /* Dynamic version switching is not presently supported. */ + if (btf_hdr_len != _btf_hdr_len) + goto err; + + ctf_dprintf ("ctf_version: client using BTF header length %zi\n", btf_hdr_len); + } + + _libctf_btf_mode = btf_mode; + + return ctf_version_; + + err: + errno = ENOTSUP; + return -1; } /* Store the specified error code into errp if it is non-NULL, and then diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index df59a6107a8..752eca81ab4 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -858,9 +858,7 @@ ssize_t get_ctt_size_v2_unconverted (const ctf_dict_t *, const ctf_type_t *, extern const char _CTF_SECTION[]; /* name of CTF ELF section */ extern const char _CTF_NULLSTR[]; /* empty string */ - -extern int _libctf_version; /* library client version */ -extern int _libctf_debug; /* debugging messages enabled */ +extern ctf_btf_mode_t _libctf_btf_mode; /* BTF writeout mode. */ #include "ctf-inlines.h"