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:
parent
a6fb869173
commit
bdf290cd3e
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user