1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-30 08:19:09 +00:00

ctf: Add v3 support to CTF tools, ctf{convert,dump,merge}

ctfdump handles v2 and v3.  ctfconvert now emits only CTFv3, whereas
ctfmerge can merge v2 and v3 containers into v3 containers.

MFC after:	1 month
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D34364
This commit is contained in:
Mark Johnston 2022-03-07 08:54:18 -05:00
parent a6fb869173
commit bdf290cd3e
4 changed files with 470 additions and 269 deletions

View File

@ -58,8 +58,7 @@ struct ctf_buf {
caddr_t ctb_end; /* pointer to end of buffer */
caddr_t ctb_ptr; /* pointer to empty buffer space */
size_t ctb_size; /* size of buffer */
int nptent; /* number of processed types */
int ntholes; /* number of type holes */
uint_t nptent; /* number of processed types */
};
/*
@ -165,10 +164,10 @@ write_label(void *arg1, void *arg2)
static void
write_objects(iidesc_t *idp, ctf_buf_t *b)
{
ushort_t id = (idp ? idp->ii_dtype->t_id : 0);
uint_t id = (idp ? idp->ii_dtype->t_id : 0);
if (target_requires_swap) {
SWAP_16(id);
SWAP_32(id);
}
ctf_buf_write(b, &id, sizeof (id));
@ -179,8 +178,8 @@ write_objects(iidesc_t *idp, ctf_buf_t *b)
static void
write_functions(iidesc_t *idp, ctf_buf_t *b)
{
ushort_t fdata[2];
ushort_t id;
uint_t fdata[2];
uint_t id;
int nargs;
int i;
@ -194,17 +193,17 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
nargs = idp->ii_nargs + (idp->ii_vargs != 0);
if (nargs > CTF_MAX_VLEN) {
if (nargs > CTF_V3_MAX_VLEN) {
terminate("function %s has too many args: %d > %d\n",
idp->ii_name, nargs, CTF_MAX_VLEN);
idp->ii_name, nargs, CTF_V3_MAX_VLEN);
}
fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
fdata[0] = CTF_V3_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
fdata[1] = idp->ii_dtype->t_id;
if (target_requires_swap) {
SWAP_16(fdata[0]);
SWAP_16(fdata[1]);
SWAP_32(fdata[0]);
SWAP_32(fdata[1]);
}
ctf_buf_write(b, fdata, sizeof (fdata));
@ -213,7 +212,7 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
id = idp->ii_args[i]->t_id;
if (target_requires_swap) {
SWAP_16(id);
SWAP_32(id);
}
ctf_buf_write(b, &id, sizeof (id));
@ -234,29 +233,29 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
* doesn't need to care.
*/
static void
write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
write_sized_type_rec(ctf_buf_t *b, struct ctf_type_v3 *ctt, size_t size)
{
if (size > CTF_MAX_SIZE) {
ctt->ctt_size = CTF_LSIZE_SENT;
if (size > CTF_V3_MAX_SIZE) {
ctt->ctt_size = CTF_V3_LSIZE_SENT;
ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
if (target_requires_swap) {
SWAP_32(ctt->ctt_name);
SWAP_16(ctt->ctt_info);
SWAP_16(ctt->ctt_size);
SWAP_32(ctt->ctt_info);
SWAP_32(ctt->ctt_size);
SWAP_32(ctt->ctt_lsizehi);
SWAP_32(ctt->ctt_lsizelo);
}
ctf_buf_write(b, ctt, sizeof (*ctt));
} else {
ctf_stype_t *cts = (ctf_stype_t *)ctt;
struct ctf_stype_v3 *cts = (struct ctf_stype_v3 *)ctt;
cts->ctt_size = (ushort_t)size;
cts->ctt_size = size;
if (target_requires_swap) {
SWAP_32(cts->ctt_name);
SWAP_16(cts->ctt_info);
SWAP_16(cts->ctt_size);
SWAP_32(cts->ctt_info);
SWAP_32(cts->ctt_size);
}
ctf_buf_write(b, cts, sizeof (*cts));
@ -264,14 +263,14 @@ write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
}
static void
write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt)
write_unsized_type_rec(ctf_buf_t *b, struct ctf_type_v3 *ctt)
{
ctf_stype_t *cts = (ctf_stype_t *)ctt;
struct ctf_stype_v3 *cts = (struct ctf_stype_v3 *)ctt;
if (target_requires_swap) {
SWAP_32(cts->ctt_name);
SWAP_16(cts->ctt_info);
SWAP_16(cts->ctt_size);
SWAP_32(cts->ctt_info);
SWAP_32(cts->ctt_size);
}
ctf_buf_write(b, cts, sizeof (*cts));
@ -292,14 +291,12 @@ write_type(void *arg1, void *arg2)
int isroot = tp->t_flags & TDESC_F_ISROOT;
int i;
ctf_type_t ctt;
ctf_array_t cta;
ctf_member_t ctm;
ctf_lmember_t ctlm;
ctf_enum_t cte;
ushort_t id;
ctlm.ctlm_pad = 0;
struct ctf_type_v3 ctt;
struct ctf_array_v3 cta;
struct ctf_member_v3 ctm;
struct ctf_lmember_v3 ctlm;
struct ctf_enum cte;
uint_t id;
/*
* There shouldn't be any holes in the type list (where a hole is
@ -308,13 +305,13 @@ write_type(void *arg1, void *arg2)
* fake entries to fill the holes, or we won't be able to reconstruct
* the tree from the written data.
*/
if (++b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
if (++b->nptent < CTF_V3_TYPE_TO_INDEX(tp->t_id)) {
debug(2, "genctf: type hole from %d < x < %d\n",
b->nptent - 1, CTF_TYPE_TO_INDEX(tp->t_id));
b->nptent - 1, CTF_V3_TYPE_TO_INDEX(tp->t_id));
ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0);
ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0);
while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
ctt.ctt_info = CTF_V3_TYPE_INFO(0, 0, 0);
while (b->nptent < CTF_V3_TYPE_TO_INDEX(tp->t_id)) {
write_sized_type_rec(b, &ctt, 0);
b->nptent++;
}
@ -327,10 +324,10 @@ write_type(void *arg1, void *arg2)
case INTRINSIC:
ip = tp->t_intr;
if (ip->intr_type == INTR_INT)
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_INTEGER,
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_INTEGER,
isroot, 1);
else
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FLOAT, isroot, 1);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FLOAT, isroot, 1);
write_sized_type_rec(b, &ctt, tp->t_size);
encoding = 0;
@ -355,21 +352,21 @@ write_type(void *arg1, void *arg2)
break;
case POINTER:
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_POINTER, isroot, 0);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_POINTER, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
case ARRAY:
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, isroot, 1);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_ARRAY, isroot, 1);
write_sized_type_rec(b, &ctt, tp->t_size);
cta.cta_contents = tp->t_ardef->ad_contents->t_id;
cta.cta_index = tp->t_ardef->ad_idxtype->t_id;
cta.cta_nelems = tp->t_ardef->ad_nelems;
if (target_requires_swap) {
SWAP_16(cta.cta_contents);
SWAP_16(cta.cta_index);
SWAP_32(cta.cta_contents);
SWAP_32(cta.cta_index);
SWAP_32(cta.cta_nelems);
}
ctf_buf_write(b, &cta, sizeof (cta));
@ -380,19 +377,19 @@ write_type(void *arg1, void *arg2)
for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next)
i++; /* count up struct or union members */
if (i > CTF_MAX_VLEN) {
if (i > CTF_V3_MAX_VLEN) {
terminate("sou %s has too many members: %d > %d\n",
tdesc_name(tp), i, CTF_MAX_VLEN);
tdesc_name(tp), i, CTF_V3_MAX_VLEN);
}
if (tp->t_type == STRUCT)
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, isroot, i);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_STRUCT, isroot, i);
else
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, isroot, i);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_UNION, isroot, i);
write_sized_type_rec(b, &ctt, tp->t_size);
if (tp->t_size < CTF_LSTRUCT_THRESH) {
if (tp->t_size < CTF_V3_LSTRUCT_THRESH) {
for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) {
offset = strtab_insert(&b->ctb_strtab,
mp->ml_name);
@ -403,8 +400,8 @@ write_type(void *arg1, void *arg2)
ctm.ctm_offset = mp->ml_offset;
if (target_requires_swap) {
SWAP_32(ctm.ctm_name);
SWAP_16(ctm.ctm_type);
SWAP_16(ctm.ctm_offset);
SWAP_32(ctm.ctm_type);
SWAP_32(ctm.ctm_offset);
}
ctf_buf_write(b, &ctm, sizeof (ctm));
}
@ -423,7 +420,7 @@ write_type(void *arg1, void *arg2)
if (target_requires_swap) {
SWAP_32(ctlm.ctlm_name);
SWAP_16(ctlm.ctlm_type);
SWAP_32(ctlm.ctlm_type);
SWAP_32(ctlm.ctlm_offsethi);
SWAP_32(ctlm.ctlm_offsetlo);
}
@ -437,11 +434,11 @@ write_type(void *arg1, void *arg2)
for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next)
i++; /* count up enum members */
if (i > CTF_MAX_VLEN) {
i = CTF_MAX_VLEN;
if (i > CTF_V3_MAX_VLEN) {
i = CTF_V3_MAX_VLEN;
}
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_ENUM, isroot, i);
write_sized_type_rec(b, &ctt, tp->t_size);
for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) {
@ -460,25 +457,25 @@ write_type(void *arg1, void *arg2)
break;
case FORWARD:
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, isroot, 0);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FORWARD, isroot, 0);
ctt.ctt_type = 0;
write_unsized_type_rec(b, &ctt);
break;
case TYPEDEF:
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
case VOLATILE:
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_VOLATILE, isroot, 0);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_VOLATILE, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
case CONST:
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_CONST, isroot, 0);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_CONST, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
@ -486,12 +483,12 @@ write_type(void *arg1, void *arg2)
case FUNCTION:
i = tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs;
if (i > CTF_MAX_VLEN) {
if (i > CTF_V3_MAX_VLEN) {
terminate("function %s has too many args: %d > %d\n",
tdesc_name(tp), i, CTF_MAX_VLEN);
tdesc_name(tp), i, CTF_V3_MAX_VLEN);
}
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, isroot, i);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FUNCTION, isroot, i);
ctt.ctt_type = tp->t_fndef->fn_ret->t_id;
write_unsized_type_rec(b, &ctt);
@ -499,7 +496,7 @@ write_type(void *arg1, void *arg2)
id = tp->t_fndef->fn_args[i]->t_id;
if (target_requires_swap) {
SWAP_16(id);
SWAP_32(id);
}
ctf_buf_write(b, &id, sizeof (id));
@ -511,14 +508,10 @@ write_type(void *arg1, void *arg2)
i++;
}
if (i & 1) {
id = 0;
ctf_buf_write(b, &id, sizeof (id));
}
break;
case RESTRICT:
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_RESTRICT, isroot, 0);
ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_RESTRICT, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
@ -704,7 +697,7 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
* integers; we pad these out to the next 4-byte boundary if needed.
*/
h.cth_magic = CTF_MAGIC;
h.cth_version = CTF_VERSION;
h.cth_version = CTF_VERSION_3;
h.cth_flags = do_compress ? CTF_F_COMPRESS : 0;
h.cth_parlabel = strtab_insert(&buf->ctb_strtab,
iiburst->iib_td->td_parlabel);
@ -761,14 +754,46 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
}
static void
get_ctt_size(ctf_type_t *ctt, size_t *sizep, size_t *incrementp)
get_ctt_info(ctf_header_t *h, void *v, uint_t *kind, uint_t *vlen, int *isroot)
{
if (ctt->ctt_size == CTF_LSIZE_SENT) {
*sizep = (size_t)CTF_TYPE_LSIZE(ctt);
*incrementp = sizeof (ctf_type_t);
if (h->cth_version == CTF_VERSION_2) {
struct ctf_type_v2 *ctt = v;
*kind = CTF_V2_INFO_KIND(ctt->ctt_info);
*vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
*isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
} else {
*sizep = ctt->ctt_size;
*incrementp = sizeof (ctf_stype_t);
struct ctf_type_v3 *ctt = v;
*kind = CTF_V3_INFO_KIND(ctt->ctt_info);
*vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
*isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
}
}
static void
get_ctt_size(ctf_header_t *h, void *v, size_t *sizep, size_t *incrementp)
{
if (h->cth_version == CTF_VERSION_2) {
struct ctf_type_v2 *ctt = v;
if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
*sizep = (size_t)CTF_TYPE_LSIZE(ctt);
*incrementp = sizeof (struct ctf_type_v2);
} else {
*sizep = ctt->ctt_size;
*incrementp = sizeof (struct ctf_stype_v2);
}
} else {
struct ctf_type_v3 *ctt = v;
if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
*sizep = (size_t)CTF_TYPE_LSIZE(ctt);
*incrementp = sizeof (struct ctf_type_v3);
} else {
*sizep = ctt->ctt_size;
*incrementp = sizeof (struct ctf_stype_v3);
}
}
}
@ -776,18 +801,22 @@ static int
count_types(ctf_header_t *h, caddr_t data)
{
caddr_t dptr = data + h->cth_typeoff;
uint_t version = h->cth_version;
size_t idwidth;
int count = 0;
idwidth = version == CTF_VERSION_2 ? 2 : 4;
dptr = data + h->cth_typeoff;
while (dptr < data + h->cth_stroff) {
void *v = (void *) dptr;
ctf_type_t *ctt = v;
size_t vlen = CTF_INFO_VLEN(ctt->ctt_info);
size_t size, increment;
uint_t vlen, kind;
int isroot;
get_ctt_size(ctt, &size, &increment);
get_ctt_info(h, v, &kind, &vlen, &isroot);
get_ctt_size(h, v, &size, &increment);
switch (CTF_INFO_KIND(ctt->ctt_info)) {
switch (kind) {
case CTF_K_INTEGER:
case CTF_K_FLOAT:
dptr += 4;
@ -799,17 +828,31 @@ count_types(ctf_header_t *h, caddr_t data)
case CTF_K_CONST:
case CTF_K_RESTRICT:
case CTF_K_FUNCTION:
dptr += sizeof (ushort_t) * (vlen + (vlen & 1));
dptr += idwidth * vlen;
break;
case CTF_K_ARRAY:
dptr += sizeof (ctf_array_t);
if (version == CTF_VERSION_2)
dptr += sizeof (struct ctf_array_v2);
else
dptr += sizeof (struct ctf_array_v3);
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
if (size < CTF_LSTRUCT_THRESH)
dptr += sizeof (ctf_member_t) * vlen;
else
dptr += sizeof (ctf_lmember_t) * vlen;
if (version == CTF_VERSION_2) {
if (size < CTF_V2_LSTRUCT_THRESH)
dptr += sizeof (struct ctf_member_v2) *
vlen;
else
dptr += sizeof (struct ctf_lmember_v2) *
vlen;
} else {
if (size < CTF_V3_LSTRUCT_THRESH)
dptr += sizeof (struct ctf_member_v3) *
vlen;
else
dptr += sizeof (struct ctf_lmember_v3) *
vlen;
}
break;
case CTF_K_ENUM:
dptr += sizeof (ctf_enum_t) * vlen;
@ -818,7 +861,7 @@ count_types(ctf_header_t *h, caddr_t data)
break;
default:
parseterminate("Unknown CTF type %d (#%d) at %#x",
CTF_INFO_KIND(ctt->ctt_info), count, dptr - data);
kind, count, dptr - data);
}
dptr += increment;
@ -895,11 +938,15 @@ resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
caddr_t buf = ctfdata + h->cth_objtoff;
size_t bufsz = h->cth_funcoff - h->cth_objtoff;
caddr_t dptr;
size_t idwidth;
idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4;
symit_reset(si);
for (dptr = buf; dptr < buf + bufsz; dptr += 2) {
void *v = (void *) dptr;
ushort_t id = *((ushort_t *)v);
for (dptr = buf; dptr < buf + bufsz; dptr += idwidth) {
uint32_t id = 0;
memcpy(&id, (void *) dptr, idwidth);
iidesc_t *ii;
GElf_Sym *sym;
@ -912,7 +959,7 @@ resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
if (id == 0) {
debug(3, "Skipping null object\n");
continue;
} else if (id >= tdsize) {
} else if (id >= (uint_t)tdsize) {
parseterminate("Reference to invalid type %d", id);
}
@ -937,18 +984,21 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
{
caddr_t buf = ctfdata + h->cth_funcoff;
size_t bufsz = h->cth_typeoff - h->cth_funcoff;
size_t idwidth;
caddr_t dptr = buf;
iidesc_t *ii;
ushort_t info;
ushort_t retid;
GElf_Sym *sym;
int i;
idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4;
symit_reset(si);
while (dptr < buf + bufsz) {
void *v = (void *) dptr;
info = *((ushort_t *)v);
dptr += 2;
uint32_t id, info, retid;
info = 0;
memcpy(&info, (void *) dptr, idwidth);
dptr += idwidth;
if (!(sym = symit_next(si, STT_FUNC)) && info != 0)
parseterminate("Unexpected end of function symbols");
@ -959,11 +1009,11 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
continue;
}
v = (void *) dptr;
retid = *((ushort_t *)v);
dptr += 2;
retid = 0;
memcpy(&retid, (void *) dptr, idwidth);
dptr += idwidth;
if (retid >= tdsize)
if (retid >= (uint_t)tdsize)
parseterminate("Reference to invalid type %d", retid);
ii = iidesc_new(symit_name(si));
@ -973,15 +1023,18 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
ii->ii_owner = xstrdup(symit_curfile(si));
} else
ii->ii_type = II_GFUN;
ii->ii_nargs = CTF_INFO_VLEN(info);
if (h->cth_version == CTF_VERSION_2)
ii->ii_nargs = CTF_V2_INFO_VLEN(info);
else
ii->ii_nargs = CTF_V3_INFO_VLEN(info);
if (ii->ii_nargs)
ii->ii_args =
xmalloc(sizeof (tdesc_t *) * ii->ii_nargs);
for (i = 0; i < ii->ii_nargs; i++, dptr += 2) {
v = (void *) dptr;
ushort_t id = *((ushort_t *)v);
if (id >= tdsize)
for (i = 0; i < ii->ii_nargs; i++, dptr += idwidth) {
id = 0;
memcpy(&id, (void *) dptr, idwidth);
if (id >= (uint_t)tdsize)
parseterminate("Reference to invalid type %d",
id);
ii->ii_args[i] = tdarr[id];
@ -1011,55 +1064,65 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
tdesc_t *tdp;
uint_t data;
uint_t encoding;
size_t size, increment;
size_t idwidth, size, increment;
int tcnt;
int iicnt = 0;
tid_t tid, argid;
int kind, vlen;
int i;
int isroot, kind, vlen;
int i, version;
elist_t **epp;
mlist_t **mpp;
intr_t *ip;
ctf_type_t *ctt;
ctf_array_t *cta;
ctf_enum_t *cte;
version = h->cth_version;
idwidth = version == CTF_VERSION_2 ? 2 : 4;
/*
* A maxid of zero indicates a request to resurrect all types, so reset
* maxid to the maximum type id.
*/
if (maxid == 0)
maxid = CTF_MAX_TYPE;
if (maxid == 0) {
maxid = version == CTF_VERSION_2 ?
CTF_V2_MAX_TYPE : CTF_V3_MAX_TYPE;
}
for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) {
ctf_enum_t *cte;
uint_t name, type;
void *v;
if (tid > maxid)
break;
if (tid >= tdsize)
parseterminate("Reference to invalid type %d", tid);
void *v = (void *) dptr;
ctt = v;
get_ctt_info(h, dptr, &kind, &vlen, &isroot);
get_ctt_size(h, dptr, &size, &increment);
if (version == CTF_VERSION_2) {
struct ctf_type_v2 *ctt = (void *) dptr;
get_ctt_size(ctt, &size, &increment);
name = ctt->ctt_name;
type = ctt->ctt_type;
} else {
struct ctf_type_v3 *ctt = (void *) dptr;
name = ctt->ctt_name;
type = ctt->ctt_type;
}
dptr += increment;
tdp = tdarr[tid];
if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0)
if (CTF_NAME_STID(name) != CTF_STRTAB_0)
parseterminate(
"Unable to cope with non-zero strtab id");
if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) {
tdp->t_name =
xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name));
if (CTF_NAME_OFFSET(name) != 0) {
tdp->t_name = xstrdup(sbuf + CTF_NAME_OFFSET(name));
} else
tdp->t_name = NULL;
kind = CTF_INFO_KIND(ctt->ctt_info);
vlen = CTF_INFO_VLEN(ctt->ctt_info);
switch (kind) {
case CTF_K_INTEGER:
tdp->t_type = INTRINSIC;
@ -1106,62 +1169,110 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
case CTF_K_POINTER:
tdp->t_type = POINTER;
tdp->t_tdesc = tdarr[ctt->ctt_type];
tdp->t_tdesc = tdarr[type];
break;
case CTF_K_ARRAY:
case CTF_K_ARRAY: {
uint_t contents, index, nelems;
tdp->t_type = ARRAY;
tdp->t_size = size;
v = (void *) dptr;
cta = v;
dptr += sizeof (ctf_array_t);
if (version == CTF_VERSION_2) {
struct ctf_array_v2 *cta = (void *) dptr;
contents = cta->cta_contents;
index = cta->cta_index;
nelems = cta->cta_nelems;
dptr += sizeof (*cta);
} else {
struct ctf_array_v3 *cta = (void *) dptr;
contents = cta->cta_contents;
index = cta->cta_index;
nelems = cta->cta_nelems;
dptr += sizeof (*cta);
}
tdp->t_ardef = xmalloc(sizeof (ardef_t));
tdp->t_ardef->ad_contents = tdarr[cta->cta_contents];
tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index];
tdp->t_ardef->ad_nelems = cta->cta_nelems;
tdp->t_ardef->ad_contents = tdarr[contents];
tdp->t_ardef->ad_idxtype = tdarr[index];
tdp->t_ardef->ad_nelems = nelems;
break;
}
case CTF_K_STRUCT:
case CTF_K_UNION:
case CTF_K_UNION: {
tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION);
tdp->t_size = size;
if (size < CTF_LSTRUCT_THRESH) {
for (i = 0, mpp = &tdp->t_members; i < vlen;
i++, mpp = &((*mpp)->ml_next)) {
v = (void *) dptr;
ctf_member_t *ctm = v;
dptr += sizeof (ctf_member_t);
if (version == CTF_VERSION_2) {
if (size < CTF_V2_LSTRUCT_THRESH) {
for (i = 0, mpp = &tdp->t_members; i < vlen;
i++, mpp = &((*mpp)->ml_next)) {
v = (void *) dptr;
struct ctf_member_v2 *ctm = v;
dptr += sizeof (struct ctf_member_v2);
*mpp = xmalloc(sizeof (mlist_t));
(*mpp)->ml_name = xstrdup(sbuf +
ctm->ctm_name);
(*mpp)->ml_type = tdarr[ctm->ctm_type];
(*mpp)->ml_offset = ctm->ctm_offset;
(*mpp)->ml_size = 0;
*mpp = xmalloc(sizeof (mlist_t));
(*mpp)->ml_name = xstrdup(sbuf +
ctm->ctm_name);
(*mpp)->ml_type = tdarr[ctm->ctm_type];
(*mpp)->ml_offset = ctm->ctm_offset;
(*mpp)->ml_size = 0;
}
} else {
for (i = 0, mpp = &tdp->t_members; i < vlen;
i++, mpp = &((*mpp)->ml_next)) {
v = (void *) dptr;
struct ctf_lmember_v2 *ctlm = v;
dptr += sizeof (struct ctf_lmember_v2);
*mpp = xmalloc(sizeof (mlist_t));
(*mpp)->ml_name = xstrdup(sbuf +
ctlm->ctlm_name);
(*mpp)->ml_type =
tdarr[ctlm->ctlm_type];
(*mpp)->ml_offset =
(int)CTF_LMEM_OFFSET(ctlm);
(*mpp)->ml_size = 0;
}
}
} else {
for (i = 0, mpp = &tdp->t_members; i < vlen;
i++, mpp = &((*mpp)->ml_next)) {
v = (void *) dptr;
ctf_lmember_t *ctlm = v;
dptr += sizeof (ctf_lmember_t);
if (size < CTF_V3_LSTRUCT_THRESH) {
for (i = 0, mpp = &tdp->t_members; i < vlen;
i++, mpp = &((*mpp)->ml_next)) {
v = (void *) dptr;
struct ctf_member_v3 *ctm = v;
dptr += sizeof (struct ctf_member_v3);
*mpp = xmalloc(sizeof (mlist_t));
(*mpp)->ml_name = xstrdup(sbuf +
ctlm->ctlm_name);
(*mpp)->ml_type =
tdarr[ctlm->ctlm_type];
(*mpp)->ml_offset =
(int)CTF_LMEM_OFFSET(ctlm);
(*mpp)->ml_size = 0;
*mpp = xmalloc(sizeof (mlist_t));
(*mpp)->ml_name = xstrdup(sbuf +
ctm->ctm_name);
(*mpp)->ml_type = tdarr[ctm->ctm_type];
(*mpp)->ml_offset = ctm->ctm_offset;
(*mpp)->ml_size = 0;
}
} else {
for (i = 0, mpp = &tdp->t_members; i < vlen;
i++, mpp = &((*mpp)->ml_next)) {
v = (void *) dptr;
struct ctf_lmember_v3 *ctlm = v;
dptr += sizeof (struct ctf_lmember_v3);
*mpp = xmalloc(sizeof (mlist_t));
(*mpp)->ml_name = xstrdup(sbuf +
ctlm->ctlm_name);
(*mpp)->ml_type =
tdarr[ctlm->ctlm_type];
(*mpp)->ml_offset =
(int)CTF_LMEM_OFFSET(ctlm);
(*mpp)->ml_size = 0;
}
}
}
*mpp = NULL;
break;
}
case CTF_K_ENUM:
tdp->t_type = ENUM;
@ -1187,26 +1298,26 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
case CTF_K_TYPEDEF:
tdp->t_type = TYPEDEF;
tdp->t_tdesc = tdarr[ctt->ctt_type];
tdp->t_tdesc = tdarr[type];
break;
case CTF_K_VOLATILE:
tdp->t_type = VOLATILE;
tdp->t_tdesc = tdarr[ctt->ctt_type];
tdp->t_tdesc = tdarr[type];
break;
case CTF_K_CONST:
tdp->t_type = CONST;
tdp->t_tdesc = tdarr[ctt->ctt_type];
tdp->t_tdesc = tdarr[type];
break;
case CTF_K_FUNCTION:
tdp->t_type = FUNCTION;
tdp->t_fndef = xcalloc(sizeof (fndef_t));
tdp->t_fndef->fn_ret = tdarr[ctt->ctt_type];
tdp->t_fndef->fn_ret = tdarr[type];
v = (void *) (dptr + (sizeof (ushort_t) * (vlen - 1)));
if (vlen > 0 && *(ushort_t *)v == 0)
v = (void *) (dptr + (idwidth * (vlen - 1)));
if (vlen > 0 && *(uint_t *)v == 0)
tdp->t_fndef->fn_vargs = 1;
tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs;
@ -1215,20 +1326,19 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
for (i = 0; i < vlen; i++) {
v = (void *) dptr;
argid = *(ushort_t *)v;
dptr += sizeof (ushort_t);
memcpy(&argid, v, idwidth);
dptr += idwidth;
if (argid != 0)
tdp->t_fndef->fn_args[i] = tdarr[argid];
}
if (vlen & 1)
dptr += sizeof (ushort_t);
dptr = roundup2(dptr, 4);
break;
case CTF_K_RESTRICT:
tdp->t_type = RESTRICT;
tdp->t_tdesc = tdarr[ctt->ctt_type];
tdp->t_tdesc = tdarr[type];
break;
case CTF_K_UNKNOWN:
@ -1238,7 +1348,7 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
warning("Can't parse unknown CTF type %d\n", kind);
}
if (CTF_INFO_ISROOT(ctt->ctt_info)) {
if (isroot) {
iidesc_t *ii = iidesc_new(tdp->t_name);
if (tdp->t_type == STRUCT || tdp->t_type == UNION ||
tdp->t_type == ENUM)
@ -1252,8 +1362,7 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
}
debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type,
(CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""),
tdesc_name(tdp), tdp->t_id);
(isroot ? "root " : ""), tdesc_name(tdp), tdp->t_id);
}
debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt);
@ -1353,7 +1462,7 @@ ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label)
if (h->cth_magic != CTF_MAGIC)
parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic);
if (h->cth_version != CTF_VERSION)
if (h->cth_version != CTF_VERSION_2 && h->cth_version != CTF_VERSION_3)
parseterminate("Unknown CTF version %d", h->cth_version);
ctfdatasz = h->cth_stroff + h->cth_strlen;

View File

@ -972,11 +972,11 @@ main(int argc, char **argv)
savetd = tdata_new();
if (CTF_TYPE_ISCHILD(reftd->td_nextid))
if (CTF_V3_TYPE_ISCHILD(reftd->td_nextid))
terminate("No room for additional types in master\n");
savetd->td_nextid = withfile ? reftd->td_nextid :
CTF_INDEX_TO_TYPE(1, TRUE);
CTF_V3_INDEX_TO_TYPE(1, TRUE);
merge_into_master(mstrtd, reftd, savetd, 0);
tdata_label_add(savetd, label, CTF_LABEL_LASTIDX);

View File

@ -97,6 +97,8 @@ typedef struct ctf_data {
caddr_t cd_ctfdata; /* Pointer to the CTF data */
size_t cd_ctflen; /* Length of CTF data */
size_t cd_idwidth; /* Size of a type ID, in bytes */
/*
* cd_symdata will be non-NULL if the CTF data is being retrieved from
* an ELF file with a symbol table. cd_strdata and cd_nsyms should be
@ -266,9 +268,8 @@ next_sym(const ctf_data_t *cd, const int symidx, const uchar_t matchtype,
static int
read_data(const ctf_header_t *hp, const ctf_data_t *cd)
{
void *v = (void *) (cd->cd_ctfdata + hp->cth_objtoff);
const ushort_t *idp = v;
ulong_t n = (hp->cth_funcoff - hp->cth_objtoff) / sizeof (ushort_t);
const char *v = (void *) (cd->cd_ctfdata + hp->cth_objtoff);
ulong_t n = (hp->cth_funcoff - hp->cth_objtoff) / cd->cd_idwidth;
if (flags != F_STATS)
print_line("- Data Objects ");
@ -287,6 +288,7 @@ read_data(const ctf_header_t *hp, const ctf_data_t *cd)
char *name = NULL;
for (symidx = -1, i = 0; i < (int) n; i++) {
uint32_t id = 0;
int nextsym;
if (cd->cd_symdata == NULL || (nextsym = next_sym(cd,
@ -295,7 +297,9 @@ read_data(const ctf_header_t *hp, const ctf_data_t *cd)
else
symidx = nextsym;
len = printf(" [%u] %u", i, *idp++);
memcpy(&id, v, cd->cd_idwidth);
v += cd->cd_idwidth;
len = printf(" [%u] %u", i, id);
if (name != NULL)
(void) printf("%*s%s (%u)", (15 - len), "",
name, symidx);
@ -310,11 +314,10 @@ read_data(const ctf_header_t *hp, const ctf_data_t *cd)
static int
read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
{
void *v = (void *) (cd->cd_ctfdata + hp->cth_funcoff);
const ushort_t *fp = v;
const char *v = (void *) (cd->cd_ctfdata + hp->cth_funcoff);
uint_t f = 0, info;
v = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
const ushort_t *end = v;
const char *end = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
ulong_t id;
int symidx;
@ -331,10 +334,14 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
if (hp->cth_funcoff > hp->cth_typeoff)
WARN("file is corrupt -- cth_funcoff > cth_typeoff\n");
for (symidx = -1, id = 0; fp < end; id++) {
ushort_t info = *fp++;
ushort_t kind = CTF_INFO_KIND(info);
ushort_t n = CTF_INFO_VLEN(info);
for (symidx = -1, id = 0; v < end; id++) {
info = 0;
memcpy(&info, v, cd->cd_idwidth);
v += cd->cd_idwidth;
ushort_t kind = hp->cth_version == CTF_VERSION_2 ?
CTF_V2_INFO_KIND(info) : CTF_V3_INFO_KIND(info);
ushort_t n = hp->cth_version == CTF_VERSION_2 ?
CTF_V2_INFO_VLEN(info) : CTF_V3_INFO_VLEN(info);
ushort_t i;
int nextsym;
char *name;
@ -354,7 +361,7 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
return (E_ERROR);
}
if (fp + n > end) {
if (v + n * cd->cd_idwidth > end) {
(void) printf(" [%lu] vlen %u extends past section "
"boundary\n", id, n);
return (E_ERROR);
@ -364,17 +371,24 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
(void) printf(" [%lu] FUNC ", id);
if (name != NULL)
(void) printf("(%s) ", name);
(void) printf("returns: %u args: (", *fp++);
memcpy(&f, v, cd->cd_idwidth);
v += cd->cd_idwidth;
(void) printf("returns: %u args: (", f);
if (n != 0) {
(void) printf("%u", *fp++);
for (i = 1; i < n; i++)
(void) printf(", %u", *fp++);
memcpy(&f, v, cd->cd_idwidth);
v += cd->cd_idwidth;
(void) printf("%u", f);
for (i = 1; i < n; i++) {
memcpy(&f, v, cd->cd_idwidth);
v += cd->cd_idwidth;
(void) printf(", %u", f);
}
}
(void) printf(")\n");
} else
fp += n + 1; /* skip to next function definition */
v += n * cd->cd_idwidth + 1; /* skip to next function definition */
stats.s_nfunc++;
stats.s_nargs += n;
@ -387,13 +401,10 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
static int
read_types(const ctf_header_t *hp, const ctf_data_t *cd)
{
void *v = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
const ctf_type_t *tp = v;
v = (void *) (cd->cd_ctfdata + hp->cth_stroff);
const ctf_type_t *end = v;
const char *v = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
const char *end = (void *) (cd->cd_ctfdata + hp->cth_stroff);
ulong_t id;
uint_t version;
if (flags != F_STATS)
print_line("- Types ");
@ -407,103 +418,158 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
if (hp->cth_typeoff > hp->cth_stroff)
WARN("file is corrupt -- cth_typeoff > cth_stroff\n");
version = hp->cth_version;
id = 1;
if (hp->cth_parlabel || hp->cth_parname)
id += 1 << CTF_PARENT_SHIFT;
id += 1ul << (hp->cth_version == CTF_VERSION_2 ?
CTF_V2_PARENT_SHIFT : CTF_V3_PARENT_SHIFT);
for (/* */; tp < end; id++) {
ulong_t i, n = CTF_INFO_VLEN(tp->ctt_info);
for (/* */; v < end; id++) {
struct ctf_type_v2 t2;
struct ctf_type_v3 t3;
ulong_t i, n;
size_t size, increment, vlen = 0;
int kind = CTF_INFO_KIND(tp->ctt_info);
uint_t isroot, name, type;
int kind;
if (version == CTF_VERSION_2) {
memcpy(&t2, v, sizeof(t2));
name = t2.ctt_name;
n = CTF_V2_INFO_VLEN(t2.ctt_info);
isroot = CTF_V2_INFO_ISROOT(t2.ctt_info);
kind = CTF_V2_INFO_KIND(t2.ctt_info);
type = t2.ctt_type;
if (t2.ctt_size == CTF_V2_LSIZE_SENT) {
increment = sizeof (struct ctf_type_v2);
size = (size_t)CTF_TYPE_LSIZE(&t2);
} else {
increment = sizeof (struct ctf_stype_v2);
size = t2.ctt_size;
}
} else {
memcpy(&t3, v, sizeof(t3));
name = t3.ctt_name;
n = CTF_V3_INFO_VLEN(t3.ctt_info);
isroot = CTF_V3_INFO_ISROOT(t3.ctt_info);
kind = CTF_V3_INFO_KIND(t3.ctt_info);
type = t3.ctt_type;
if (t3.ctt_size == CTF_V3_LSIZE_SENT) {
increment = sizeof (struct ctf_type_v3);
size = (size_t)CTF_TYPE_LSIZE(&t3);
} else {
increment = sizeof (struct ctf_stype_v3);
size = t3.ctt_size;
}
}
union {
const void *ptr;
ctf_array_t *ap;
const ctf_member_t *mp;
const ctf_lmember_t *lmp;
const char *ptr;
struct ctf_array_v2 *ap2;
struct ctf_array_v3 *ap3;
const struct ctf_member_v2 *mp2;
const struct ctf_member_v3 *mp3;
const struct ctf_lmember_v2 *lmp2;
const struct ctf_lmember_v3 *lmp3;
const ctf_enum_t *ep;
const ushort_t *argp;
} u;
u.ptr = v + increment;
if (flags != F_STATS) {
(void) printf(" %c%lu%c ",
"[<"[CTF_INFO_ISROOT(tp->ctt_info)], id,
"]>"[CTF_INFO_ISROOT(tp->ctt_info)]);
"[<"[isroot], id, "]>"[isroot]);
}
if (tp->ctt_size == CTF_LSIZE_SENT) {
increment = sizeof (ctf_type_t);
size = (size_t)CTF_TYPE_LSIZE(tp);
} else {
increment = sizeof (ctf_stype_t);
size = tp->ctt_size;
}
u.ptr = (const char *)tp + increment;
switch (kind) {
case CTF_K_INTEGER:
if (flags != F_STATS) {
uint_t encoding = *((const uint_t *)u.ptr);
uint_t encoding =
*((const uint_t *)(const void *)u.ptr);
(void) printf("INTEGER %s encoding=%s offset=%u"
" bits=%u", ref_to_str(tp->ctt_name, hp,
cd), int_encoding_to_str(
" bits=%u", ref_to_str(name, hp, cd),
int_encoding_to_str(
CTF_INT_ENCODING(encoding)),
CTF_INT_OFFSET(encoding),
CTF_INT_BITS(encoding));
}
vlen = sizeof (uint_t);
vlen = sizeof (uint32_t);
break;
case CTF_K_FLOAT:
if (flags != F_STATS) {
uint_t encoding = *((const uint_t *)u.ptr);
uint_t encoding =
*((const uint_t *)(const void *)u.ptr);
(void) printf("FLOAT %s encoding=%s offset=%u "
"bits=%u", ref_to_str(tp->ctt_name, hp,
cd), fp_encoding_to_str(
"bits=%u", ref_to_str(name, hp, cd),
fp_encoding_to_str(
CTF_FP_ENCODING(encoding)),
CTF_FP_OFFSET(encoding),
CTF_FP_BITS(encoding));
}
vlen = sizeof (uint_t);
vlen = sizeof (uint32_t);
break;
case CTF_K_POINTER:
if (flags != F_STATS) {
(void) printf("POINTER %s refers to %u",
ref_to_str(tp->ctt_name, hp, cd),
tp->ctt_type);
ref_to_str(name, hp, cd), type);
}
break;
case CTF_K_ARRAY:
case CTF_K_ARRAY: {
uint_t contents, index, nelems;
if (version == CTF_VERSION_2) {
contents = u.ap2->cta_contents;
index = u.ap2->cta_index;
nelems = u.ap2->cta_nelems;
} else {
contents = u.ap3->cta_contents;
index = u.ap3->cta_index;
nelems = u.ap3->cta_nelems;
}
if (flags != F_STATS) {
(void) printf("ARRAY %s content: %u index: %u "
"nelems: %u\n", ref_to_str(tp->ctt_name,
hp, cd), u.ap->cta_contents,
u.ap->cta_index, u.ap->cta_nelems);
"nelems: %u\n", ref_to_str(name, hp, cd),
contents, index, nelems);
}
vlen = sizeof (ctf_array_t);
if (version == 2)
vlen = sizeof (struct ctf_array_v2);
else
vlen = sizeof (struct ctf_array_v3);
break;
}
case CTF_K_FUNCTION: {
uint_t arg = 0;
case CTF_K_FUNCTION:
if (flags != F_STATS) {
(void) printf("FUNCTION %s returns: %u args: (",
ref_to_str(tp->ctt_name, hp, cd),
tp->ctt_type);
ref_to_str(name, hp, cd), type);
if (n != 0) {
(void) printf("%u", *u.argp++);
for (i = 1; i < n; i++, u.argp++)
(void) printf(", %u", *u.argp);
memcpy(&arg, u.ptr, cd->cd_idwidth);
u.ptr += cd->cd_idwidth;
(void) printf("%u", arg);
for (i = 1; i < n;
i++, u.ptr += cd->cd_idwidth) {
memcpy(&arg, u.ptr,
cd->cd_idwidth);
(void) printf(", %u", arg);
}
}
(void) printf(")");
}
vlen = sizeof (ushort_t) * (n + (n & 1));
vlen = roundup2(cd->cd_idwidth * n, 4);
break;
}
case CTF_K_STRUCT:
case CTF_K_UNION:
@ -527,36 +593,64 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
if (flags != F_STATS) {
(void) printf(" %s (%zd bytes)\n",
ref_to_str(tp->ctt_name, hp, cd), size);
ref_to_str(name, hp, cd), size);
if (size >= CTF_LSTRUCT_THRESH) {
for (i = 0; i < n; i++, u.lmp++) {
(void) printf(
"\t%s type=%u off=%llu\n",
ref_to_str(u.lmp->ctlm_name,
hp, cd), u.lmp->ctlm_type,
(unsigned long long)
CTF_LMEM_OFFSET(u.lmp));
if (version == CTF_VERSION_2) {
if (size >= CTF_V2_LSTRUCT_THRESH) {
for (i = 0; i < n; i++, u.lmp2++) {
(void) printf(
"\t%s type=%u off=%llu\n",
ref_to_str(u.lmp2->ctlm_name,
hp, cd), u.lmp2->ctlm_type,
(unsigned long long)
CTF_LMEM_OFFSET(u.lmp2));
}
} else {
for (i = 0; i < n; i++, u.mp2++) {
(void) printf(
"\t%s type=%u off=%u\n",
ref_to_str(u.mp2->ctm_name,
hp, cd), u.mp2->ctm_type,
u.mp2->ctm_offset);
}
}
} else {
for (i = 0; i < n; i++, u.mp++) {
(void) printf(
"\t%s type=%u off=%u\n",
ref_to_str(u.mp->ctm_name,
hp, cd), u.mp->ctm_type,
u.mp->ctm_offset);
if (size >= CTF_V3_LSTRUCT_THRESH) {
for (i = 0; i < n; i++, u.lmp3++) {
(void) printf(
"\t%s type=%u off=%llu\n",
ref_to_str(u.lmp3->ctlm_name,
hp, cd), u.lmp3->ctlm_type,
(unsigned long long)
CTF_LMEM_OFFSET(u.lmp3));
}
} else {
for (i = 0; i < n; i++, u.mp3++) {
(void) printf(
"\t%s type=%u off=%u\n",
ref_to_str(u.mp3->ctm_name,
hp, cd), u.mp3->ctm_type,
u.mp3->ctm_offset);
}
}
}
}
vlen = n * (size >= CTF_LSTRUCT_THRESH ?
sizeof (ctf_lmember_t) : sizeof (ctf_member_t));
if (version == CTF_VERSION_2) {
vlen = n * (size >= CTF_V2_LSTRUCT_THRESH ?
sizeof (struct ctf_lmember_v2) :
sizeof (struct ctf_member_v2));
} else {
vlen = n * (size >= CTF_V3_LSTRUCT_THRESH ?
sizeof (struct ctf_lmember_v3) :
sizeof (struct ctf_member_v3));
}
break;
case CTF_K_ENUM:
if (flags != F_STATS) {
(void) printf("ENUM %s\n",
ref_to_str(tp->ctt_name, hp, cd));
ref_to_str(name, hp, cd));
for (i = 0; i < n; i++, u.ep++) {
(void) printf("\t%s = %d\n",
@ -574,39 +668,35 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
case CTF_K_FORWARD:
if (flags != F_STATS) {
(void) printf("FORWARD %s",
ref_to_str(tp->ctt_name, hp, cd));
ref_to_str(name, hp, cd));
}
break;
case CTF_K_TYPEDEF:
if (flags != F_STATS) {
(void) printf("TYPEDEF %s refers to %u",
ref_to_str(tp->ctt_name, hp, cd),
tp->ctt_type);
ref_to_str(name, hp, cd), type);
}
break;
case CTF_K_VOLATILE:
if (flags != F_STATS) {
(void) printf("VOLATILE %s refers to %u",
ref_to_str(tp->ctt_name, hp, cd),
tp->ctt_type);
ref_to_str(name, hp, cd), type);
}
break;
case CTF_K_CONST:
if (flags != F_STATS) {
(void) printf("CONST %s refers to %u",
ref_to_str(tp->ctt_name, hp, cd),
tp->ctt_type);
ref_to_str(name, hp, cd), type);
}
break;
case CTF_K_RESTRICT:
if (flags != F_STATS) {
(void) printf("RESTRICT %s refers to %u",
ref_to_str(tp->ctt_name, hp, cd),
tp->ctt_type);
ref_to_str(name, hp, cd), type);
}
break;
@ -624,7 +714,7 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
stats.s_ntypes++;
stats.s_types[kind]++;
tp = (ctf_type_t *)((uintptr_t)tp + increment + vlen);
v += increment + vlen;
}
return (E_SUCCESS);
@ -935,14 +1025,16 @@ main(int argc, char *argv[])
if (pp->ctp_magic != CTF_MAGIC)
die("%s does not appear to contain CTF data\n", filename);
if (pp->ctp_version == CTF_VERSION) {
if (pp->ctp_version >= CTF_VERSION_2) {
v = (void *) cd.cd_ctfdata;
hp = v;
cd.cd_ctfdata = (caddr_t)cd.cd_ctfdata + sizeof (ctf_header_t);
cd.cd_idwidth = pp->ctp_version == CTF_VERSION_2 ? 2 : 4;
if (cd.cd_ctflen < sizeof (ctf_header_t)) {
die("%s does not contain a v%d CTF header\n", filename,
CTF_VERSION);
pp->ctp_version);
}
} else {

View File

@ -149,7 +149,7 @@ typedef struct ctf_enum {
} ctf_enum_t;
#define CTF_MAGIC 0xcff1
#define CTF_VERSION CTF_VERSION_2
#define CTF_VERSION CTF_VERSION_3
#define CTF_VERSION_3 3
#define CTF_VERSION_2 2
#define CTF_VERSION_1 1