libctf: adapt core dictops for v4 and prefix types

The heart of libctf's reading code is the ctf_dictops_t and the functions it
provides for reading various things no matter what the CTF version in use:
these are called via LCTF_*() macros that translate into calls into the
dictops.

The introduction of prefix types in v4 requires changes here: in particular,
we want the ability to get the type kind of whatever ctf_type_t we are
looking at (the 'unprefixed' kind), as well as the ability to get the type
kind taking prefixes into account: and more generally we want the ability
to both look at a given prefix and look at the type as a whole.  So several
ctf_dictops_t entries are added for this (ctfo_get_prefixed_kind,
ctfo_get_prefixed_vlen).

This means API changes (no callers yet adjusted, it'll happen as we go),
because the existing macros were mostly called with e.g. a ctt_info value
and returned a type kind, while now we need to be called with the actual
ctf_type_t itself, so we can possibly walk beyond it to find the real type
record.  ctfo_get_vbytes needs adjusting for this.

We also add names to most of the ctf_type_t parameters, because suddenly we
can have up to three of them: one relating to the first entry in the type
record (which may be a prefix, usually called 'prefix'), one relating to the
true type record (which may be a suffix, so usually called 'suffix'), and
one possibly relating to some intermediate record if we have multiple
prefixes (usually called 'tp').

There is one horrible special case in here: the vlen of the new
CTF_K_FUNC_LINKAGE kind (equivalent to BTF_KIND_FUNC) is always zero: it
reuses the vlen field to encode the linkage (!).  BTF is rife with ugly
hacks like this.
This commit is contained in:
Nick Alcock
2025-04-24 13:50:38 +01:00
parent ab3ad58be9
commit 6a4a485c7b
2 changed files with 258 additions and 60 deletions

View File

@@ -133,11 +133,13 @@ typedef struct ctf_lookup
typedef struct ctf_dictops
{
uint32_t (*ctfo_get_kind) (uint32_t);
uint32_t (*ctfo_get_prefixed_kind) (const ctf_type_t *tp);
uint32_t (*ctfo_get_root) (uint32_t);
uint32_t (*ctfo_get_vlen) (uint32_t);
ssize_t (*ctfo_get_ctt_size) (const ctf_dict_t *, const ctf_type_t *,
uint32_t (*ctfo_get_prefixed_vlen) (const ctf_type_t *tp);
ssize_t (*ctfo_get_ctt_size) (const ctf_dict_t *, const ctf_type_t *tp,
ssize_t *, ssize_t *);
ssize_t (*ctfo_get_vbytes) (ctf_dict_t *, unsigned short, ssize_t, size_t);
ssize_t (*ctfo_get_vbytes) (ctf_dict_t *, const ctf_type_t *, ssize_t);
} ctf_dictops_t;
typedef struct ctf_list
@@ -593,11 +595,24 @@ extern ctf_id_t ctf_index_to_type (const ctf_dict_t *, uint32_t);
&(ctf_dtd_lookup (fp, ctf_index_to_type (fp, i))->dtd_data) : \
(ctf_type_t *)((uintptr_t)(fp)->ctf_buf + (fp)->ctf_txlate[(i)]))
#define LCTF_INFO_KIND(fp, info) ((fp)->ctf_dictops->ctfo_get_kind(info))
/* The non *INFO variants of these macros acquire the relevant info from the
suffixed type, if the type is prefixed. (Internally to libctf, all types
that may ever take a prefix are prefixed until they are written out, so that
nothing special needs to be done to handle them should their size later
expand past the limit where prefixing is needed.) */
#define LCTF_INFO_UNPREFIXED_KIND(fp, info) ((fp)->ctf_dictops->ctfo_get_kind(info))
#define LCTF_KIND(fp, tp) ((fp)->ctf_dictops->ctfo_get_prefixed_kind(tp))
#define LCTF_INFO_ISROOT(fp, info) ((fp)->ctf_dictops->ctfo_get_root(info))
#define LCTF_INFO_VLEN(fp, info) ((fp)->ctf_dictops->ctfo_get_vlen(info))
#define LCTF_VBYTES(fp, kind, size, vlen) \
((fp)->ctf_dictops->ctfo_get_vbytes(fp, kind, size, vlen))
#define LCTF_VLEN(fp, tp) ((fp)->ctf_dictops->ctfo_get_prefixed_vlen(tp))
#define LCTF_INFO_UNPREFIXED_VLEN(fp, info) ((fp)->ctf_dictops->ctfo_get_vlen(info))
#define LCTF_VBYTES(fp, tp, size) \
((fp)->ctf_dictops->ctfo_get_vbytes (fp, tp, size))
#define LCTF_IS_PREFIXED_KIND(kind) (kind == CTF_K_BIG || kind == CTF_K_CONFLICTING)
#define LCTF_IS_PREFIXED_INFO(info) \
((CTF_INFO_KIND ((info)) == CTF_K_BIG) \
|| (CTF_INFO_KIND ((info)) == CTF_K_CONFLICTING))
#define LCTF_CHILD 0x0001 /* CTF dict is a child. */
#define LCTF_LINKING 0x0002 /* CTF link is underway: respect ctf_link_flags. */
@@ -807,6 +822,9 @@ extern ctf_link_sym_t *ctf_elf32_to_link_sym (ctf_dict_t *fp, ctf_link_sym_t *ds
extern ctf_link_sym_t *ctf_elf64_to_link_sym (ctf_dict_t *fp, ctf_link_sym_t *dst,
const Elf64_Sym *src, uint32_t symidx);
ssize_t get_ctt_size_v2_unconverted (const ctf_dict_t *, const ctf_type_t *,
ssize_t *sizep, ssize_t *incrementp);
/* Variables, all underscore-prepended. */
extern const char _CTF_SECTION[]; /* name of CTF ELF section */