Main index | Section 5 | Options |
#include <sys/ctf.h>
+-------------+ 0t0 +--------| Preamble | | +-------------+ 0t4 |+-------| Header | || +-------------+ 0t36 + cth_lbloff ||+------| Labels | ||| +-------------+ 0t36 + cth_objtoff |||+-----| Objects | |||| +-------------+ 0t36 + cth_funcoff ||||+----| Functions | ||||| +-------------+ 0t36 + cth_typeoff |||||+---| Types | |||||| +-------------+ 0t36 + cth_stroff ||||||+--| Strings | ||||||| +-------------+ 0t36 + cth_stroff + cth_strlen ||||||| ||||||| ||||||| ||||||| +-- magic - vers flags ||||||| | | | | ||||||| +------+------+------+------+ +---------| 0xcf | 0xf1 | 0x03 | 0x00 | |||||| +------+------+------+------+ |||||| 0 1 2 3 4 |||||| |||||| + parent label + objects |||||| | + parent name | + functions + strings |||||| | | + label | | + types | + strlen |||||| | | | | | | | | |||||| +------+------+------+------+------+-------+-------+-------+ +--------| 0x00 | 0x00 | 0x00 | 0x08 | 0x36 | 0x110 | 0x5f4 | 0x611 | ||||| +------+------+------+------+------+-------+-------+-------+ ||||| 0x04 0x08 0x0c 0x10 0x14 0x18 0x1c 0x20 0x24 ||||| ||||| + Label name ||||| | + Label type ||||| | | + Next label ||||| | | | ||||| +-------+------+-----+ +-----------| 0x01 | 0x42 | ... | |||| +-------+------+-----+ |||| cth_lbloff +0x4 +0x8 cth_objtoff |||| |||| |||| Symidx 0t15 0t43 0t44 |||| +------+------+------+-----+ +----------| 0x00 | 0x42 | 0x36 | ... | ||| +------+------+------+-----+ ||| cth_objtoff +0x4 +0x8 +0xc cth_funcoff ||| ||| + CTF_TYPE_INFO + CTF_TYPE_INFO ||| | + Return type | ||| | | + arg0 | ||| +--------+------+------+-----+ +---------| 0x2c10 | 0x08 | 0x0c | ... | || +--------+------+------+-----+ || cth_funcff +0x4 +0x8 +0xc cth_typeoff || || + ctf_stype_t for type 1 || | integer + integer encoding || | | + ctf_stype_t for type 2 || | | | || +--------------------+-----------+-----+ +--------| 0x19 * 0xc01 * 0x0 | 0x1000000 | ... | | +--------------------+-----------+-----+ | cth_typeoff +0x0c +0x10 cth_stroff | | +--- str 0 | | +--- str 1 + str 2 | | | | | v v v | +----+---+---+---+----+---+---+---+---+---+----+ +---| \0 | i | n | t | \0 | f | o | o | _ | t | \0 | +----+---+---+---+----+---+---+---+---+---+----+ 0 1 2 3 4 5 6 7 8 9 10 11
typedef struct ctf_preamble { uint16_t ctp_magic; /* magic number (CTF_MAGIC) */ uint8_t ctp_version; /* data format version number (CTF_VERSION) */ uint8_t ctp_flags; /* flags (see below) */ } ctf_preamble_t;
The preamble is four bytes long and must be four byte aligned. This preamble defines the version of the ctf file which defines the format of the rest of the header. While the header may change in subsequent versions, the preamble will not change across versions, though the interpretation of its flags may change from version to version. The ctp_magic member defines the magic number for the ctf file format. This must always be 0xcff1. If another value is encountered, then the file should not be treated as a ctf file. The ctp_version member defines the version of the ctf file. The current version is 3. It is possible to encounter an unsupported version. In that case, software should not try to parse the format, as it may have changed. Finally, the ctp_flags member describes aspects of the file which modify its interpretation. The following flags are currently defined:
#define CTF_F_COMPRESS 0x01
The flag
CTF_F_COMPRESS
indicates that the body of the
ctf
file, all the data following the
header,
has been compressed through the
zlib
library and its
deflate
algorithm.
If this flag is not present, then the body has not been compressed and no
special action is needed to interpret it.
All offsets into the data as described by
header,
always refer to the
uncompressed
data.
.Lp
In versions two and three of the
ctf
file format, the
header
denotes whether or not this
ctf
file is the child of another
ctf
file and also indicates the size of the remaining sections.
The structure for the
header
logically contains a copy of the
preamble
and the two have a combined size of 36 bytes.
typedef struct ctf_header { 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_lbloff; /* offset of label section */ uint32_t cth_objtoff; /* offset of object section */ uint32_t cth_funcoff; /* offset of function 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_t;
After the
preamble,
the next two members
cth_parlabel
and
cth_parname,
are used to identify the parent.
The value of both members are offsets into the
string
section which point to the start of a null-terminated string.
For more information on the encoding of strings, see the subsection on
String Identifiers.
If the value of either is zero, then there is no entry for that
member.
If the member
cth_parlabel
is set, then the
ctf_parname
member must be set, otherwise it will not be possible to find the
parent.
If
ctf_parname
is set, it is not necessary to define
cth_parlabel,
as the parent may not have a label.
For more information on labels and their interpretation, see
The Label Section.
.Lp
The remaining members (excepting
cth_strlen)
describe the beginning of the corresponding sections.
These offsets are relative to the end of the
header.
Therefore, something with an offset of 0 is at an offset of thirty-six
bytes relative to the start of the
ctf
file.
The difference between members indicates the size of the section itself.
Different offsets have different alignment requirements.
The start of the
cth_objtoff
and
cth_funcoff
must be two byte aligned, while the sections
cth_lbloff
and
cth_typeoff
must be four-byte aligned.
The section
cth_stroff
has no alignment requirements.
To calculate the size of a given section, excepting the
string
section, one should subtract the offset of the section from the following one.
For example, the size of the
types
section can be calculated by subtracting
cth_typeoff
from
cth_stroff.
.Lp
Finally, the member
cth_strlen
describes the length of the string section itself.
From it, you can also calculate the size of the entire
ctf
file by adding together the size of the
ctf_header_t,
the offset of the string section in
cth_stroff,
and the size of the string section in
cth_srlen.
#define CTF_K_UNKNOWN 0 #define CTF_K_INTEGER 1 #define CTF_K_FLOAT 2 #define CTF_K_POINTER 3 #define CTF_K_ARRAY 4 #define CTF_K_FUNCTION 5 #define CTF_K_STRUCT 6 #define CTF_K_UNION 7 #define CTF_K_ENUM 8 #define CTF_K_FORWARD 9 #define CTF_K_TYPEDEF 10 #define CTF_K_VOLATILE 11 #define CTF_K_CONST 12 #define CTF_K_RESTRICT 13
#define CTF_V3_MAX_VLEN 0x00ffffff #define CTF_V3_INFO_KIND(info) (((info) & 0xfc000000) >> 26) #define CTF_V3_INFO_ISROOT(info) (((info) & 0x02000000) >> 25) #define CTF_V3_INFO_VLEN(info) (((info) & CTF_V3_MAX_VLEN))
#define CTF_V3_TYPE_INFO(kind, isroot, vlen) \ (((kind) << 26) | (((isroot) ? 1 : 0) << 25) | ((vlen) & CTF_V3_MAX_VLEN))
typedef struct ctf_lblent { uint32_t ctl_label; /* ref to name of label */ uint32_t ctl_typeidx; /* last type associated with this label */ } ctf_lblent_t;
#include <gelf.h> #include <stdio.h>/* * Given the start of the object section in a CTFv3 file, the number of symbols, * and the ELF Data sections for the symbol table and the string table, this * prints the type identifiers that correspond to objects. Note, a more robust * implementation should ensure that they don't walk beyond the end of the CTF * object section. * * An implementation that handles CTFv2 must take into account the fact that * type identifiers are 16 bits wide rather than 32 bits wide. */ static int walk_symbols(uint32_t *objtoff, Elf_Data *symdata, Elf_Data *strdata, long nsyms) { long i; uintptr_t strbase = strdata->d_buf;
for (i = 1; i < nsyms; i++, objftoff++) { const char *name; GElf_Sym sym;
if (gelf_getsym(symdata, i, &sym) == NULL) return (1);
if (GELF_ST_TYPE(sym.st_info) != STT_OBJECT) continue; if (sym.st_shndx == SHN_UNDEF || sym.st_name == 0) continue; if (sym.st_shndx == SHN_ABS && sym.st_value == 0) continue; name = (const char *)(strbase + sym.st_name); if (strcmp(name, "_START_") == 0 || strcmp(name, "_END_") == 0) continue;
(void) printf("Symbol %d has type %d0, i, *objtoff); }
return (0); }
#define CTF_V3_MAX_SIZE 0xfffffffe /* max size of a type in bytes */ #define CTF_V3_LSIZE_SENT 0xffffffff /* sentinel for ctt_size */ #define CTF_V3_MAX_LSIZE UINT64_MAXstruct ctf_stype_v3 { uint32_t ctt_name; /* reference to name in string table */ uint32_t ctt_info; /* encoded kind, variant length */ union { uint32_t _size; /* size of entire type in bytes */ uint32_t _type; /* reference to another type */ } _u; };
struct ctf_type_v3 { uint32_t ctt_name; /* reference to name in string table */ uint32_t ctt_info; /* encoded kind, variant length */ union { uint32_t _size; /* always CTF_LSIZE_SENT */ uint32_t _type; /* do not use */ } _u; uint32_t ctt_lsizehi; /* high 32 bits of type size in bytes */ uint32_t ctt_lsizelo; /* low 32 bits of type size in bytes */ };
#define ctt_size _u._size /* for fundamental types that have a size */ #define ctt_type _u._type /* for types that reference another type */
Type sizes are stored in
bytes.
The basic small form uses a
uint32_t
to store the number of bytes.
If the number of bytes in a structure would exceed 0xfffffffe, then the
alternate form, the
struct ctf_type_v3,
is used instead.
To indicate that the larger form is being used, the member
ctt_size
is set to value of
CTF_V3_LSIZE_SENT
(0xffffffff).
In general, when going through the type section, consumers use the
struct ctf_type_v3
structure, but pay attention to the value of the member
ctt_size
to determine whether they should increment their scan by the size of
struct ctf_stype_v3
or
struct ctf_type_v3.
Not all kinds of types use
ctt_size.
Those which do not, will always use the
struct ctf_stype_v3
structure.
The individual sections for each kind have more information.
.Lp
Types are written out in order.
Therefore the first entry encountered has a type id of 0x1, or 0x8000 if a
child.
The member
ctt_name
is encoded as described in the section
String Identifiers.
The string that it points to is the name of the type.
If the identifier points to an empty string (one that consists solely of a null
terminator) then the type does not have a name, this is common with anonymous
structures and unions that only have a typedef to name them, as well as
pointers and qualifiers.
.Lp
The next member, the
ctt_info,
is encoded as described in the section
Type Encoding.
The type's kind tells us how to interpret the remaining data in the
struct ctf_type_v3
and any variable length data that may exist.
The rest of this section will be broken down into the interpretation of the
various kinds.
This encoding can be expressed through the following macros:
#define CTF_INT_ENCODING(data) (((data) & 0xff000000) >> 24) #define CTF_INT_OFFSET(data) (((data) & 0x00ff0000) >> 16) #define CTF_INT_BITS(data) (((data) & 0x0000ffff))#define CTF_INT_DATA(encoding, offset, bits) \ (((encoding) << 24) | ((offset) << 16) | (bits))
The following flags are defined for the encoding at this time:
#define CTF_INT_SIGNED 0x01 #define CTF_INT_CHAR 0x02 #define CTF_INT_BOOL 0x04 #define CTF_INT_VARARGS 0x08
#define CTF_FP_ENCODING(data) (((data) & 0xff000000) >> 24) #define CTF_FP_OFFSET(data) (((data) & 0x00ff0000) >> 16) #define CTF_FP_BITS(data) (((data) & 0x0000ffff))#define CTF_FP_DATA(encoding, offset, bits) \ (((encoding) << 24) | ((offset) << 16) | (bits))
#define CTF_FP_SINGLE 1 /* IEEE 32-bit float encoding */ #define CTF_FP_DOUBLE 2 /* IEEE 64-bit float encoding */ #define CTF_FP_CPLX 3 /* Complex encoding */ #define CTF_FP_DCPLX 4 /* Double complex encoding */ #define CTF_FP_LDCPLX 5 /* Long double complex encoding */ #define CTF_FP_LDOUBLE 6 /* Long double encoding */ #define CTF_FP_INTRVL 7 /* Interval (2x32-bit) encoding */ #define CTF_FP_DINTRVL 8 /* Double interval (2x64-bit) encoding */ #define CTF_FP_LDINTRVL 9 /* Long double interval (2x128-bit) encoding */ #define CTF_FP_IMAGRY 10 /* Imaginary (32-bit) encoding */ #define CTF_FP_DIMAGRY 11 /* Long imaginary (64-bit) encoding */ #define CTF_FP_LDIMAGRY 12 /* Long double imaginary (128-bit) encoding */
struct ctf_array_v3 { uint32_t cta_contents; /* reference to type of array contents */ uint32_t cta_index; /* reference to type of array index */ uint32_t cta_nelems; /* number of elements */ };
struct ctf_member_v3 { uint32_t ctm_name; /* reference to name in string table */ uint32_t ctm_type; /* reference to type of member */ uint32_t ctm_offset; /* offset of this member in bits */ };struct ctf_lmember_v3 { uint32_t ctlm_name; /* reference to name in string table */ uint32_t ctlm_type; /* reference to type of member */ uint32_t ctlm_offsethi; /* high 32 bits of member offset in bits */ uint32_t ctlm_offsetlo; /* low 32 bits of member offset in bits */ };
typedef struct ctf_enum { uint32_t cte_name; /* reference to name in string table */ int32_t cte_value; /* value associated with this name */ } ctf_enum_t;
The member cte_name refers to the name of the enumerator's value, it is encoded according to the rules in the section String Identifiers. The member cte_value contains the integer value of this enumerator.
CTF (5) | February 28, 2022 |
Main index | Section 5 | Options |
Please direct any comments about this manual page service to Ben Bullock. Privacy policy.
“ | There are 10 types of people in the world: those who understand binary, and those who don't. | ” |