_CTF_ITEM (ECTF_NEEDSBFD, "This feature needs a libctf with BFD support.") \
_CTF_ITEM (ECTF_INCOMPLETE, "Type is not a complete type.") \
_CTF_ITEM (ECTF_NONAME, "Type name must not be empty.") \
- _CTF_ITEM (ECTF_BADFLAG, "Invalid CTF dict flag specified.")
+ _CTF_ITEM (ECTF_BADFLAG, "Invalid CTF dict flag specified.") \
+ _CTF_ITEM (ECTF_CTFVERS_NO_SERIALIZE, "CTFv1 dicts are too old to serialize.") \
+ _CTF_ITEM (ECTF_UNSTABLE, "Attempt to write unstable file format version: set I_KNOW_LIBCTF_IS_UNSTABLE in the environment.")
#define ECTF_BASE 1000 /* Base value for libctf errnos. */
#undef _CTF_FIRST
};
-#define ECTF_NERR (ECTF_BADFLAG - ECTF_BASE + 1) /* Count of CTF errors. */
+#define ECTF_NERR (ECTF_UNSTABLE - 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_MAX_SIZE_V1 0xfffe /* Max size of a type in bytes. */
# define CTF_LSIZE_SENT_V1 0xffff /* Sentinel for v1 ctt_size. */
- /* Start of actual data structure definitions.
+/* Start of actual data structure definitions.
- Every field in these structures must have corresponding code in the
- endianness-swapping machinery in libctf/ctf-open.c. */
+ Every field in these structures must have corresponding code in the
+ endianness-swapping machinery in libctf/ctf-open.c. */
+
+/* UPTODO: v4/BTF preamble in different order! at least the magic number is in the
+ same place. */
typedef struct ctf_preamble
{
uint32_t cth_strlen; /* Length of string section in bytes. */
} ctf_header_v2_t;
+typedef struct ctf_header_v3
+{
+ ctf_preamble_t cth_preamble;
+ uint32_t cth_parlabel; /* Ref to name of parent lbl uniq'd against. */
+ uint32_t cth_parname; /* Ref to basename of parent. */
+ uint32_t cth_cuname; /* Ref to CU name (may be 0). */
+ uint32_t cth_lbloff; /* Offset of label section. */
+ uint32_t cth_objtoff; /* Offset of object section. */
+ uint32_t cth_funcoff; /* Offset of function section. */
+ uint32_t cth_objtidxoff; /* Offset of object index section. */
+ uint32_t cth_funcidxoff; /* Offset of function index section. */
+ uint32_t cth_varoff; /* Offset of variable section. */
+ uint32_t cth_typeoff; /* Offset of type section. */
+ uint32_t cth_stroff; /* Offset of string section. */
+ uint32_t cth_strlen; /* Length of string section in bytes. */
+} ctf_header_v3_t;
+
typedef struct ctf_header
{
ctf_preamble_t cth_preamble;
writing the header from scratch, we would add a *pair* of version number
fields to allow for this, but this will do for now. (A flag will not do,
because we need to encode both the version we came from and the version we
- went to, not just "we were upgraded".) */
+ went to, not just "we were upgraded".)
-# define CTF_VERSION_1 1
-# define CTF_VERSION_1_UPGRADED_3 2
-# define CTF_VERSION_2 3
+ The same problem applies to v2 and v3 upgraded to v4, but here we can apply
+ some common sense and simply record the boundary in a new header field. */
+#define CTF_VERSION_1 1
+#define CTF_VERSION_1_UPGRADED_3 2
+#define CTF_VERSION_2 3
#define CTF_VERSION_3 4
-#define CTF_VERSION CTF_VERSION_3 /* Current version. */
+
+#define CTF_VERSION_4 5
+#define CTF_VERSION CTF_VERSION_4 /* Current version. */
+#define CTF_STABLE_VERSION 4
/* All of these flags bar CTF_F_COMPRESS and CTF_F_IDXSORTED are bug-workaround
flags and are valid only in format v3: in v2 and below they cannot occur and
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Variables:
digits_names -> .* \(kind 4\) char \*\[10\] .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Data object section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Type section: .* \(0x44 bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Data object section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Type section: .* \(0x6c bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: .ctf
Compilation unit name: .*/B.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: .ctf
Compilation unit name: .*/B-2.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0xac bytes\)
String section: .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: .*
Compilation unit name: .*/A.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: .*
Compilation unit name: .*/A-2.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0x94 bytes\)
String section: .* \(0x1d bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: .*
Compilation unit name: .*/C.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: .*
Compilation unit name: .*/C-2.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: 0x0 -- 0x57 \(0x58 bytes\)
String section: .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Types:
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Types:
0x1: .*int .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Labels:
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Labels:
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0x74 bytes\)
String section: .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0xa8 bytes\)
String section: .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0x6c bytes\)
String section: .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0x6c bytes\)
String section: .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0x6c bytes\)
String section: .*
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Data object section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Function info section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: \.ctf
Compilation unit name: .*/data-func-1\.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Data object section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Function info section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Parent name: \.ctf
Compilation unit name: .*/data-func-1\.c
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Data objects:
a -> 0x[0-9a-f]*: \(kind 6\) struct \(size 0x[0-9a-f]*\) \(aligned at 0x[0-9a-f]*\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Compilation unit name: \(\?\)
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Compilation unit name: .*A.c
Data object section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Variable section: 0x0 -- 0x17 \(0x18 bytes\)
Type section: 0x18 -- 0x83 \(0x6c bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0x48 bytes\)
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Compilation unit name: .*enums.c
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Type section: .* \(0x18 bytes\)
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Compilation unit name: .*function.c
Function info section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Types:
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Function objects:
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Types:
0x1: \(kind 8\) enum day_of_the_week \(size 0x[0-9a-f]*\) \(aligned at 0x[0-9a-f]*\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Types:
0x1: \(kind 8\) enum day_of_the_week \(size 0x[0-9a-f]*\) \(aligned at 0x[0-9a-f]*\)
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Compilation unit name: .*slice.c
#...
Header:
Magic number: 0xdff2
- Version: 4 \(CTF_VERSION_3\)
+ Version: 5 \(CTF_VERSION_4\)
#...
Compilation unit name: .*super-sub-cycles.c
#...
"CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
"boundaries)",
"CTF_VERSION_2",
- "CTF_VERSION_3", NULL
+ "CTF_VERSION_3",
+ "CTF_VERSION_4",
+ NULL
};
const char *verstr = NULL;
((fp)->ctf_dictops->ctfo_get_vbytes(fp, kind, size, vlen))
#define LCTF_CHILD 0x0001 /* CTF dict is a child. */
-#define LCTF_LINKING 0x0002 /* CTF link is underway: respect ctf_link_flags. */
#define LCTF_STRICT_NO_DUP_ENUMERATORS 0x0004 /* Duplicate enums prohibited. */
+#define LCTF_NO_SERIALIZE 0x0010 /* Serialization of this dict prohibited. */
extern ctf_dynhash_t *ctf_name_table (ctf_dict_t *, int);
extern const ctf_type_t *ctf_lookup_by_id (ctf_dict_t **, ctf_id_t);
{get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
/* CTF_VERSION_3, identical to 2: only new type kinds */
{get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
+ /* UPTODO: CTF_VERSION_4, identical to 3 at present (but not for long) */
+ {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
};
/* Initialize the symtab translation table as appropriate for its indexing
}
-/* Upgrade the header to CTF_VERSION_3. The upgrade is done in-place. */
+/* Upgrade the header to CTF_VERSION_4. The upgrade is done in-place,
+ end-to-start. */
static void
-upgrade_header (ctf_header_t *hp)
+upgrade_header_v2 (ctf_header_t *hp)
{
ctf_header_v2_t *oldhp = (ctf_header_v2_t *) hp;
hp->cth_cuname = 0; /* No CU name. */
}
+/* Ditto, for CTFv3. */
+static void
+upgrade_header_v3 (ctf_header_t *hp)
+{
+ ctf_header_v3_t *oldhp = (ctf_header_v3_t *) hp;
+
+ hp->cth_strlen = oldhp->cth_strlen;
+ hp->cth_stroff = oldhp->cth_stroff;
+ hp->cth_typeoff = oldhp->cth_typeoff;
+ hp->cth_varoff = oldhp->cth_varoff;
+ hp->cth_funcidxoff = oldhp->cth_funcidxoff;
+ hp->cth_objtidxoff = oldhp->cth_objtidxoff;
+ hp->cth_funcoff = oldhp->cth_funcoff;
+ hp->cth_objtoff = oldhp->cth_objtoff;
+ hp->cth_lbloff = oldhp->cth_lbloff;
+ hp->cth_cuname = oldhp->cth_cuname;
+ hp->cth_parname = oldhp->cth_parname;
+ hp->cth_parlabel = oldhp->cth_parlabel;
+}
+
/* Upgrade the type table to CTF_VERSION_3 (really CTF_VERSION_1_UPGRADED_3)
from CTF_VERSION_1.
case CTF_VERSION_1_UPGRADED_3:
fp->ctf_parmax = CTF_MAX_PTYPE_V1;
+ fp->ctf_flags |= LCTF_NO_SERIALIZE;
+ break;
+
+ /* v2 and v3 are currently just the same as v4 except for new types and
+ sections: no upgrading required.
- /* v2 is just the same as v3 except for new types and sections:
- no upgrading required. */
+ UPTODO: this is really going to change. */
case CTF_VERSION_2: ;
+ case CTF_VERSION_3: ;
/* FALLTHRU */
}
return 0;
int nlstructs = 0, nlunions = 0;
int err;
- if (_libctf_unlikely_ (fp->ctf_version == CTF_VERSION_1))
+ if (fp->ctf_version < CTF_VERSION_4)
{
int err;
if ((err = upgrade_types (fp, cth)) != 0)
}
if (_libctf_unlikely_ ((pp->ctp_version < CTF_VERSION_1)
- || (pp->ctp_version > CTF_VERSION_3)))
+ || (pp->ctp_version > CTF_VERSION_4)))
return (ctf_set_open_errno (errp, ECTF_CTFVERS));
if ((symsect != NULL) && (pp->ctp_version < CTF_VERSION_2))
return (ctf_set_open_errno (errp, ECTF_NOTSUP));
}
- if (pp->ctp_version < CTF_VERSION_3)
- hdrsz = sizeof (ctf_header_v2_t);
+ switch (pp->ctp_version)
+ {
+ case CTF_VERSION_1:
+ case CTF_VERSION_2:
+ hdrsz = sizeof (ctf_header_v2_t);
+ break;
+ case CTF_VERSION_1_UPGRADED_3:
+ case CTF_VERSION_3:
+ hdrsz = sizeof (ctf_header_v3_t);
+ break;
+ case CTF_VERSION_4:
+ hdrsz = sizeof (ctf_header_t);
+ break;
+ default:
+ ctf_err_warn (NULL, ECTF_INTERNAL, 0, "ctf_bufopen: CTF version %d "
+ "not handled in header-length switch", pp->ctp_version);
+ return (ctf_set_open_errno (errp, ECTF_INTERNAL));
+ }
if (_libctf_unlikely_ (pp->ctp_flags > CTF_F_MAX))
{
return (ctf_set_open_errno (errp, ECTF_FLAGS));
}
+ /* UPTODO: v4 flags: none valid, new header field likely needed. */
+
if (ctfsect->cts_size < hdrsz)
return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
hp = fp->ctf_header;
memcpy (hp, ctfsect->cts_data, hdrsz);
if (pp->ctp_version < CTF_VERSION_3)
- upgrade_header (hp);
+ upgrade_header_v2 (hp);
+ else if (pp->ctp_version < CTF_VERSION_4)
+ upgrade_header_v3 (hp);
+
+ /* UPTODO: header "upgrade" from BTF -> CTFv4. */
if (foreign_endian)
ctf_flip_header (hp);
return (ctf_set_open_errno (errp, ECTF_CORRUPT));
}
- /* This invariant will be lifted in v4, but for now it is true. */
+ /* This invariant may be lifted in v5, but for now it is true. */
if ((hp->cth_funcidxoff - hp->cth_objtidxoff != 0) &&
(hp->cth_funcidxoff - hp->cth_objtidxoff
/* Note: if this is a v1 buffer, it will be reallocated and expanded by
init_static_types(). */
+ /* UPTODO: may need to try unconditionally for BTF, and get flags from
+ somewhere else. */
+
if (hp->cth_flags & CTF_F_COMPRESS)
{
size_t srclen;
goto bad;
}
- fp->ctf_parmax = CTF_MAX_PTYPE;
+ fp->ctf_parmax = CTF_MAX_PTYPE; /* May be reset by upgrade_types. */
memcpy (&fp->ctf_data, ctfsect, sizeof (ctf_sect_t));
if (symsect != NULL)
emit_symtypetab_state_t symstate;
memset (&symstate, 0, sizeof (emit_symtypetab_state_t));
- /* Fill in an initial CTF header. We will leave the label, object,
- and function sections empty and only output a header, type section,
- and string table. The type section begins at a 4-byte aligned
+ /* Stop unstable file formats (subject to change) getting out into the
+ wild. */
+#if CTF_VERSION != CTF_STABLE_VERSION
+ if (!getenv ("I_KNOW_LIBCTF_IS_UNSTABLE"))
+ {
+ ctf_set_errno (fp, ECTF_UNSTABLE);
+ return NULL;
+ }
+#endif
+
+ /* Prohibit reserialization of dicts for which we have dynamic state inherited
+ from the upgrade process which we cannot record in the dict. Right now,
+ this applies only to CTFv1 dicts, which have a different parent/child type
+ offset to v2 and higher, and nowhere to record this in CTFv4. */
+
+ if (fp->ctf_flags & LCTF_NO_SERIALIZE)
+ {
+ ctf_set_errno (fp, ECTF_CTFVERS_NO_SERIALIZE);
+ return NULL;
+ }
+
+ /* Fill in an initial CTF header. The type section begins at a 4-byte aligned
boundary past the CTF header itself (at relative offset zero). The flag
indicating a new-style function info section (an array of CTF_K_FUNCTION
type IDs in the types section) is flipped on. */
/* This is a new-format func info section, and the symtab and strtab come out
of the dynsym and dynstr these days. */
+
+ /* UPTODO: remove. */
hdr.cth_flags = (CTF_F_NEWFUNCINFO | CTF_F_DYNSTR);
/* Propagate all symbols in the symtypetabs into the dynamic state, so that