Changeset View
Changeset View
Standalone View
Standalone View
cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
#define RES_BUF_CHUNK_SIZE (64 * 1024) | #define RES_BUF_CHUNK_SIZE (64 * 1024) | ||||
struct ctf_buf { | struct ctf_buf { | ||||
strtab_t ctb_strtab; /* string table */ | strtab_t ctb_strtab; /* string table */ | ||||
caddr_t ctb_base; /* pointer to base of buffer */ | caddr_t ctb_base; /* pointer to base of buffer */ | ||||
caddr_t ctb_end; /* pointer to end of buffer */ | caddr_t ctb_end; /* pointer to end of buffer */ | ||||
caddr_t ctb_ptr; /* pointer to empty buffer space */ | caddr_t ctb_ptr; /* pointer to empty buffer space */ | ||||
size_t ctb_size; /* size of buffer */ | size_t ctb_size; /* size of buffer */ | ||||
int nptent; /* number of processed types */ | uint_t nptent; /* number of processed types */ | ||||
int ntholes; /* number of type holes */ | |||||
}; | }; | ||||
/* | /* | ||||
* Macros to reverse byte order | * Macros to reverse byte order | ||||
*/ | */ | ||||
#define BSWAP_8(x) ((x) & 0xff) | #define BSWAP_8(x) ((x) & 0xff) | ||||
#define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) | #define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) | ||||
#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) | #define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | write_label(void *arg1, void *arg2) | ||||
ctf_buf_write(b, &ctl, sizeof (ctl)); | ctf_buf_write(b, &ctl, sizeof (ctl)); | ||||
return (1); | return (1); | ||||
} | } | ||||
static void | static void | ||||
write_objects(iidesc_t *idp, ctf_buf_t *b) | 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) { | if (target_requires_swap) { | ||||
SWAP_16(id); | SWAP_32(id); | ||||
} | } | ||||
ctf_buf_write(b, &id, sizeof (id)); | ctf_buf_write(b, &id, sizeof (id)); | ||||
debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id); | debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id); | ||||
} | } | ||||
static void | static void | ||||
write_functions(iidesc_t *idp, ctf_buf_t *b) | write_functions(iidesc_t *idp, ctf_buf_t *b) | ||||
{ | { | ||||
ushort_t fdata[2]; | uint_t fdata[2]; | ||||
ushort_t id; | uint_t id; | ||||
int nargs; | int nargs; | ||||
int i; | int i; | ||||
if (!idp) { | if (!idp) { | ||||
fdata[0] = 0; | fdata[0] = 0; | ||||
ctf_buf_write(b, &fdata[0], sizeof (fdata[0])); | ctf_buf_write(b, &fdata[0], sizeof (fdata[0])); | ||||
debug(3, "Wrote function (null)\n"); | debug(3, "Wrote function (null)\n"); | ||||
return; | return; | ||||
} | } | ||||
nargs = idp->ii_nargs + (idp->ii_vargs != 0); | 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", | 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; | fdata[1] = idp->ii_dtype->t_id; | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_16(fdata[0]); | SWAP_32(fdata[0]); | ||||
SWAP_16(fdata[1]); | SWAP_32(fdata[1]); | ||||
} | } | ||||
ctf_buf_write(b, fdata, sizeof (fdata)); | ctf_buf_write(b, fdata, sizeof (fdata)); | ||||
for (i = 0; i < idp->ii_nargs; i++) { | for (i = 0; i < idp->ii_nargs; i++) { | ||||
id = idp->ii_args[i]->t_id; | id = idp->ii_args[i]->t_id; | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_16(id); | SWAP_32(id); | ||||
} | } | ||||
ctf_buf_write(b, &id, sizeof (id)); | ctf_buf_write(b, &id, sizeof (id)); | ||||
} | } | ||||
if (idp->ii_vargs) { | if (idp->ii_vargs) { | ||||
id = 0; | id = 0; | ||||
ctf_buf_write(b, &id, sizeof (id)); | ctf_buf_write(b, &id, sizeof (id)); | ||||
} | } | ||||
debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs); | debug(3, "Wrote function %s (%d args)\n", idp->ii_name, nargs); | ||||
} | } | ||||
/* | /* | ||||
* Depending on the size of the type being described, either a ctf_stype_t (for | * Depending on the size of the type being described, either a ctf_stype_t (for | ||||
* types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be | * types with size < CTF_LSTRUCT_THRESH) or a ctf_type_t (all others) will be | ||||
* written. We isolate the determination here so the rest of the writer code | * written. We isolate the determination here so the rest of the writer code | ||||
* doesn't need to care. | * doesn't need to care. | ||||
*/ | */ | ||||
static void | 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) { | if (size > CTF_V3_MAX_SIZE) { | ||||
ctt->ctt_size = CTF_LSIZE_SENT; | ctt->ctt_size = CTF_V3_LSIZE_SENT; | ||||
ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); | ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); | ||||
ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); | ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_32(ctt->ctt_name); | SWAP_32(ctt->ctt_name); | ||||
SWAP_16(ctt->ctt_info); | SWAP_32(ctt->ctt_info); | ||||
SWAP_16(ctt->ctt_size); | SWAP_32(ctt->ctt_size); | ||||
SWAP_32(ctt->ctt_lsizehi); | SWAP_32(ctt->ctt_lsizehi); | ||||
SWAP_32(ctt->ctt_lsizelo); | SWAP_32(ctt->ctt_lsizelo); | ||||
} | } | ||||
ctf_buf_write(b, ctt, sizeof (*ctt)); | ctf_buf_write(b, ctt, sizeof (*ctt)); | ||||
} else { | } 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) { | if (target_requires_swap) { | ||||
SWAP_32(cts->ctt_name); | SWAP_32(cts->ctt_name); | ||||
SWAP_16(cts->ctt_info); | SWAP_32(cts->ctt_info); | ||||
SWAP_16(cts->ctt_size); | SWAP_32(cts->ctt_size); | ||||
} | } | ||||
ctf_buf_write(b, cts, sizeof (*cts)); | ctf_buf_write(b, cts, sizeof (*cts)); | ||||
} | } | ||||
} | } | ||||
static void | 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) { | if (target_requires_swap) { | ||||
SWAP_32(cts->ctt_name); | SWAP_32(cts->ctt_name); | ||||
SWAP_16(cts->ctt_info); | SWAP_32(cts->ctt_info); | ||||
SWAP_16(cts->ctt_size); | SWAP_32(cts->ctt_size); | ||||
} | } | ||||
ctf_buf_write(b, cts, sizeof (*cts)); | ctf_buf_write(b, cts, sizeof (*cts)); | ||||
} | } | ||||
static int | static int | ||||
write_type(void *arg1, void *arg2) | write_type(void *arg1, void *arg2) | ||||
{ | { | ||||
tdesc_t *tp = arg1; | tdesc_t *tp = arg1; | ||||
ctf_buf_t *b = arg2; | ctf_buf_t *b = arg2; | ||||
elist_t *ep; | elist_t *ep; | ||||
mlist_t *mp; | mlist_t *mp; | ||||
intr_t *ip; | intr_t *ip; | ||||
size_t offset; | size_t offset; | ||||
uint_t encoding; | uint_t encoding; | ||||
uint_t data; | uint_t data; | ||||
int isroot = tp->t_flags & TDESC_F_ISROOT; | int isroot = tp->t_flags & TDESC_F_ISROOT; | ||||
int i; | int i; | ||||
ctf_type_t ctt; | struct ctf_type_v3 ctt; | ||||
ctf_array_t cta; | struct ctf_array_v3 cta; | ||||
ctf_member_t ctm; | struct ctf_member_v3 ctm; | ||||
ctf_lmember_t ctlm; | struct ctf_lmember_v3 ctlm; | ||||
ctf_enum_t cte; | struct ctf_enum cte; | ||||
ushort_t id; | uint_t id; | ||||
ctlm.ctlm_pad = 0; | |||||
/* | /* | ||||
* There shouldn't be any holes in the type list (where a hole is | * There shouldn't be any holes in the type list (where a hole is | ||||
* defined as two consecutive tdescs without consecutive ids), but | * defined as two consecutive tdescs without consecutive ids), but | ||||
* check for them just in case. If we do find holes, we need to make | * check for them just in case. If we do find holes, we need to make | ||||
* fake entries to fill the holes, or we won't be able to reconstruct | * fake entries to fill the holes, or we won't be able to reconstruct | ||||
* the tree from the written data. | * 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", | 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_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0); | ||||
ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0); | ctt.ctt_info = CTF_V3_TYPE_INFO(0, 0, 0); | ||||
while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) { | while (b->nptent < CTF_V3_TYPE_TO_INDEX(tp->t_id)) { | ||||
write_sized_type_rec(b, &ctt, 0); | write_sized_type_rec(b, &ctt, 0); | ||||
b->nptent++; | b->nptent++; | ||||
} | } | ||||
} | } | ||||
offset = strtab_insert(&b->ctb_strtab, tp->t_name); | offset = strtab_insert(&b->ctb_strtab, tp->t_name); | ||||
ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); | ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); | ||||
switch (tp->t_type) { | switch (tp->t_type) { | ||||
case INTRINSIC: | case INTRINSIC: | ||||
ip = tp->t_intr; | ip = tp->t_intr; | ||||
if (ip->intr_type == INTR_INT) | 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); | isroot, 1); | ||||
else | 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); | write_sized_type_rec(b, &ctt, tp->t_size); | ||||
encoding = 0; | encoding = 0; | ||||
if (ip->intr_type == INTR_INT) { | if (ip->intr_type == INTR_INT) { | ||||
if (ip->intr_signed) | if (ip->intr_signed) | ||||
encoding |= CTF_INT_SIGNED; | encoding |= CTF_INT_SIGNED; | ||||
if (ip->intr_iformat == 'c') | if (ip->intr_iformat == 'c') | ||||
encoding |= CTF_INT_CHAR; | encoding |= CTF_INT_CHAR; | ||||
else if (ip->intr_iformat == 'b') | else if (ip->intr_iformat == 'b') | ||||
encoding |= CTF_INT_BOOL; | encoding |= CTF_INT_BOOL; | ||||
else if (ip->intr_iformat == 'v') | else if (ip->intr_iformat == 'v') | ||||
encoding |= CTF_INT_VARARGS; | encoding |= CTF_INT_VARARGS; | ||||
} else | } else | ||||
encoding = ip->intr_fformat; | encoding = ip->intr_fformat; | ||||
data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits); | data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits); | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_32(data); | SWAP_32(data); | ||||
} | } | ||||
ctf_buf_write(b, &data, sizeof (data)); | ctf_buf_write(b, &data, sizeof (data)); | ||||
break; | break; | ||||
case POINTER: | 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; | ctt.ctt_type = tp->t_tdesc->t_id; | ||||
write_unsized_type_rec(b, &ctt); | write_unsized_type_rec(b, &ctt); | ||||
break; | break; | ||||
case ARRAY: | 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); | write_sized_type_rec(b, &ctt, tp->t_size); | ||||
cta.cta_contents = tp->t_ardef->ad_contents->t_id; | cta.cta_contents = tp->t_ardef->ad_contents->t_id; | ||||
cta.cta_index = tp->t_ardef->ad_idxtype->t_id; | cta.cta_index = tp->t_ardef->ad_idxtype->t_id; | ||||
cta.cta_nelems = tp->t_ardef->ad_nelems; | cta.cta_nelems = tp->t_ardef->ad_nelems; | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_16(cta.cta_contents); | SWAP_32(cta.cta_contents); | ||||
SWAP_16(cta.cta_index); | SWAP_32(cta.cta_index); | ||||
SWAP_32(cta.cta_nelems); | SWAP_32(cta.cta_nelems); | ||||
} | } | ||||
ctf_buf_write(b, &cta, sizeof (cta)); | ctf_buf_write(b, &cta, sizeof (cta)); | ||||
break; | break; | ||||
case STRUCT: | case STRUCT: | ||||
case UNION: | case UNION: | ||||
for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next) | for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next) | ||||
i++; /* count up struct or union members */ | 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", | 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) | 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 | 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); | 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) { | for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { | ||||
offset = strtab_insert(&b->ctb_strtab, | offset = strtab_insert(&b->ctb_strtab, | ||||
mp->ml_name); | mp->ml_name); | ||||
ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0, | ctm.ctm_name = CTF_TYPE_NAME(CTF_STRTAB_0, | ||||
offset); | offset); | ||||
ctm.ctm_type = mp->ml_type->t_id; | ctm.ctm_type = mp->ml_type->t_id; | ||||
ctm.ctm_offset = mp->ml_offset; | ctm.ctm_offset = mp->ml_offset; | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_32(ctm.ctm_name); | SWAP_32(ctm.ctm_name); | ||||
SWAP_16(ctm.ctm_type); | SWAP_32(ctm.ctm_type); | ||||
SWAP_16(ctm.ctm_offset); | SWAP_32(ctm.ctm_offset); | ||||
} | } | ||||
ctf_buf_write(b, &ctm, sizeof (ctm)); | ctf_buf_write(b, &ctm, sizeof (ctm)); | ||||
} | } | ||||
} else { | } else { | ||||
for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { | for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) { | ||||
offset = strtab_insert(&b->ctb_strtab, | offset = strtab_insert(&b->ctb_strtab, | ||||
mp->ml_name); | mp->ml_name); | ||||
ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0, | ctlm.ctlm_name = CTF_TYPE_NAME(CTF_STRTAB_0, | ||||
offset); | offset); | ||||
ctlm.ctlm_type = mp->ml_type->t_id; | ctlm.ctlm_type = mp->ml_type->t_id; | ||||
ctlm.ctlm_offsethi = | ctlm.ctlm_offsethi = | ||||
CTF_OFFSET_TO_LMEMHI(mp->ml_offset); | CTF_OFFSET_TO_LMEMHI(mp->ml_offset); | ||||
ctlm.ctlm_offsetlo = | ctlm.ctlm_offsetlo = | ||||
CTF_OFFSET_TO_LMEMLO(mp->ml_offset); | CTF_OFFSET_TO_LMEMLO(mp->ml_offset); | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_32(ctlm.ctlm_name); | SWAP_32(ctlm.ctlm_name); | ||||
SWAP_16(ctlm.ctlm_type); | SWAP_32(ctlm.ctlm_type); | ||||
SWAP_32(ctlm.ctlm_offsethi); | SWAP_32(ctlm.ctlm_offsethi); | ||||
SWAP_32(ctlm.ctlm_offsetlo); | SWAP_32(ctlm.ctlm_offsetlo); | ||||
} | } | ||||
ctf_buf_write(b, &ctlm, sizeof (ctlm)); | ctf_buf_write(b, &ctlm, sizeof (ctlm)); | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case ENUM: | case ENUM: | ||||
for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next) | for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next) | ||||
i++; /* count up enum members */ | i++; /* count up enum members */ | ||||
if (i > CTF_MAX_VLEN) { | if (i > CTF_V3_MAX_VLEN) { | ||||
i = CTF_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); | write_sized_type_rec(b, &ctt, tp->t_size); | ||||
for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) { | for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) { | ||||
offset = strtab_insert(&b->ctb_strtab, ep->el_name); | offset = strtab_insert(&b->ctb_strtab, ep->el_name); | ||||
cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); | cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); | ||||
cte.cte_value = ep->el_number; | cte.cte_value = ep->el_number; | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_32(cte.cte_name); | SWAP_32(cte.cte_name); | ||||
SWAP_32(cte.cte_value); | SWAP_32(cte.cte_value); | ||||
} | } | ||||
ctf_buf_write(b, &cte, sizeof (cte)); | ctf_buf_write(b, &cte, sizeof (cte)); | ||||
i--; | i--; | ||||
} | } | ||||
break; | break; | ||||
case FORWARD: | 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; | ctt.ctt_type = 0; | ||||
write_unsized_type_rec(b, &ctt); | write_unsized_type_rec(b, &ctt); | ||||
break; | break; | ||||
case TYPEDEF: | 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; | ctt.ctt_type = tp->t_tdesc->t_id; | ||||
write_unsized_type_rec(b, &ctt); | write_unsized_type_rec(b, &ctt); | ||||
break; | break; | ||||
case VOLATILE: | 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; | ctt.ctt_type = tp->t_tdesc->t_id; | ||||
write_unsized_type_rec(b, &ctt); | write_unsized_type_rec(b, &ctt); | ||||
break; | break; | ||||
case CONST: | 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; | ctt.ctt_type = tp->t_tdesc->t_id; | ||||
write_unsized_type_rec(b, &ctt); | write_unsized_type_rec(b, &ctt); | ||||
break; | break; | ||||
case FUNCTION: | case FUNCTION: | ||||
i = tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs; | 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", | 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; | ctt.ctt_type = tp->t_fndef->fn_ret->t_id; | ||||
write_unsized_type_rec(b, &ctt); | write_unsized_type_rec(b, &ctt); | ||||
for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) { | for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) { | ||||
id = tp->t_fndef->fn_args[i]->t_id; | id = tp->t_fndef->fn_args[i]->t_id; | ||||
if (target_requires_swap) { | if (target_requires_swap) { | ||||
SWAP_16(id); | SWAP_32(id); | ||||
} | } | ||||
ctf_buf_write(b, &id, sizeof (id)); | ctf_buf_write(b, &id, sizeof (id)); | ||||
} | } | ||||
if (tp->t_fndef->fn_vargs) { | if (tp->t_fndef->fn_vargs) { | ||||
id = 0; | id = 0; | ||||
ctf_buf_write(b, &id, sizeof (id)); | ctf_buf_write(b, &id, sizeof (id)); | ||||
i++; | i++; | ||||
} | } | ||||
if (i & 1) { | |||||
id = 0; | |||||
ctf_buf_write(b, &id, sizeof (id)); | |||||
} | |||||
break; | break; | ||||
case RESTRICT: | 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; | ctt.ctt_type = tp->t_tdesc->t_id; | ||||
write_unsized_type_rec(b, &ctt); | write_unsized_type_rec(b, &ctt); | ||||
break; | break; | ||||
default: | default: | ||||
warning("Can't write unknown type %d\n", tp->t_type); | warning("Can't write unknown type %d\n", tp->t_type); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress) | ||||
do_compress &= ~CTF_SWAP_BYTES; | do_compress &= ~CTF_SWAP_BYTES; | ||||
/* | /* | ||||
* Prepare the header, and create the CTF output buffers. The data | * Prepare the header, and create the CTF output buffers. The data | ||||
* object section and function section are both lists of 2-byte | * object section and function section are both lists of 2-byte | ||||
* integers; we pad these out to the next 4-byte boundary if needed. | * integers; we pad these out to the next 4-byte boundary if needed. | ||||
*/ | */ | ||||
h.cth_magic = CTF_MAGIC; | 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_flags = do_compress ? CTF_F_COMPRESS : 0; | ||||
h.cth_parlabel = strtab_insert(&buf->ctb_strtab, | h.cth_parlabel = strtab_insert(&buf->ctb_strtab, | ||||
iiburst->iib_td->td_parlabel); | iiburst->iib_td->td_parlabel); | ||||
h.cth_parname = strtab_insert(&buf->ctb_strtab, | h.cth_parname = strtab_insert(&buf->ctb_strtab, | ||||
iiburst->iib_td->td_parname); | iiburst->iib_td->td_parname); | ||||
h.cth_lbloff = 0; | h.cth_lbloff = 0; | ||||
(void) list_iter(iiburst->iib_td->td_labels, write_label, | (void) list_iter(iiburst->iib_td->td_labels, write_label, | ||||
Show All 40 Lines | ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress) | ||||
else | else | ||||
outbuf = write_buffer(&h, buf, resszp); | outbuf = write_buffer(&h, buf, resszp); | ||||
ctf_buf_free(buf); | ctf_buf_free(buf); | ||||
return (outbuf); | return (outbuf); | ||||
} | } | ||||
static void | 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) { | 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 { | |||||
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); | *sizep = (size_t)CTF_TYPE_LSIZE(ctt); | ||||
*incrementp = sizeof (ctf_type_t); | *incrementp = sizeof (struct ctf_type_v2); | ||||
} else { | } else { | ||||
*sizep = ctt->ctt_size; | *sizep = ctt->ctt_size; | ||||
*incrementp = sizeof (ctf_stype_t); | *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); | |||||
} | } | ||||
} | |||||
} | |||||
static int | static int | ||||
count_types(ctf_header_t *h, caddr_t data) | count_types(ctf_header_t *h, caddr_t data) | ||||
{ | { | ||||
caddr_t dptr = data + h->cth_typeoff; | caddr_t dptr = data + h->cth_typeoff; | ||||
uint_t version = h->cth_version; | |||||
size_t idwidth; | |||||
int count = 0; | int count = 0; | ||||
idwidth = version == CTF_VERSION_2 ? 2 : 4; | |||||
dptr = data + h->cth_typeoff; | dptr = data + h->cth_typeoff; | ||||
while (dptr < data + h->cth_stroff) { | while (dptr < data + h->cth_stroff) { | ||||
void *v = (void *) dptr; | void *v = (void *) dptr; | ||||
ctf_type_t *ctt = v; | |||||
size_t vlen = CTF_INFO_VLEN(ctt->ctt_info); | |||||
size_t size, increment; | 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_INTEGER: | ||||
case CTF_K_FLOAT: | case CTF_K_FLOAT: | ||||
dptr += 4; | dptr += 4; | ||||
break; | break; | ||||
case CTF_K_POINTER: | case CTF_K_POINTER: | ||||
case CTF_K_FORWARD: | case CTF_K_FORWARD: | ||||
case CTF_K_TYPEDEF: | case CTF_K_TYPEDEF: | ||||
case CTF_K_VOLATILE: | case CTF_K_VOLATILE: | ||||
case CTF_K_CONST: | case CTF_K_CONST: | ||||
case CTF_K_RESTRICT: | case CTF_K_RESTRICT: | ||||
case CTF_K_FUNCTION: | case CTF_K_FUNCTION: | ||||
dptr += sizeof (ushort_t) * (vlen + (vlen & 1)); | dptr += idwidth * vlen; | ||||
break; | break; | ||||
case CTF_K_ARRAY: | 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; | break; | ||||
case CTF_K_STRUCT: | case CTF_K_STRUCT: | ||||
case CTF_K_UNION: | case CTF_K_UNION: | ||||
if (size < CTF_LSTRUCT_THRESH) | if (version == CTF_VERSION_2) { | ||||
dptr += sizeof (ctf_member_t) * vlen; | if (size < CTF_V2_LSTRUCT_THRESH) | ||||
dptr += sizeof (struct ctf_member_v2) * | |||||
vlen; | |||||
else | else | ||||
dptr += sizeof (ctf_lmember_t) * vlen; | 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; | break; | ||||
case CTF_K_ENUM: | case CTF_K_ENUM: | ||||
dptr += sizeof (ctf_enum_t) * vlen; | dptr += sizeof (ctf_enum_t) * vlen; | ||||
break; | break; | ||||
case CTF_K_UNKNOWN: | case CTF_K_UNKNOWN: | ||||
break; | break; | ||||
default: | default: | ||||
parseterminate("Unknown CTF type %d (#%d) at %#x", | parseterminate("Unknown CTF type %d (#%d) at %#x", | ||||
CTF_INFO_KIND(ctt->ctt_info), count, dptr - data); | kind, count, dptr - data); | ||||
} | } | ||||
dptr += increment; | dptr += increment; | ||||
count++; | count++; | ||||
} | } | ||||
debug(3, "CTF read %d types\n", count); | debug(3, "CTF read %d types\n", count); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, | resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, | ||||
caddr_t ctfdata, symit_data_t *si) | caddr_t ctfdata, symit_data_t *si) | ||||
{ | { | ||||
caddr_t buf = ctfdata + h->cth_objtoff; | caddr_t buf = ctfdata + h->cth_objtoff; | ||||
size_t bufsz = h->cth_funcoff - h->cth_objtoff; | size_t bufsz = h->cth_funcoff - h->cth_objtoff; | ||||
caddr_t dptr; | caddr_t dptr; | ||||
size_t idwidth; | |||||
idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4; | |||||
symit_reset(si); | symit_reset(si); | ||||
for (dptr = buf; dptr < buf + bufsz; dptr += 2) { | for (dptr = buf; dptr < buf + bufsz; dptr += idwidth) { | ||||
void *v = (void *) dptr; | uint32_t id = 0; | ||||
ushort_t id = *((ushort_t *)v); | |||||
memcpy(&id, (void *) dptr, idwidth); | |||||
iidesc_t *ii; | iidesc_t *ii; | ||||
GElf_Sym *sym; | GElf_Sym *sym; | ||||
if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) { | if (!(sym = symit_next(si, STT_OBJECT)) && id != 0) { | ||||
parseterminate( | parseterminate( | ||||
"Unexpected end of object symbols at %x of %x", | "Unexpected end of object symbols at %x of %x", | ||||
dptr - buf, bufsz); | dptr - buf, bufsz); | ||||
} | } | ||||
if (id == 0) { | if (id == 0) { | ||||
debug(3, "Skipping null object\n"); | debug(3, "Skipping null object\n"); | ||||
continue; | continue; | ||||
} else if (id >= tdsize) { | } else if (id >= (uint_t)tdsize) { | ||||
parseterminate("Reference to invalid type %d", id); | parseterminate("Reference to invalid type %d", id); | ||||
} | } | ||||
ii = iidesc_new(symit_name(si)); | ii = iidesc_new(symit_name(si)); | ||||
ii->ii_dtype = tdarr[id]; | ii->ii_dtype = tdarr[id]; | ||||
if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { | if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { | ||||
ii->ii_type = II_SVAR; | ii->ii_type = II_SVAR; | ||||
ii->ii_owner = xstrdup(symit_curfile(si)); | ii->ii_owner = xstrdup(symit_curfile(si)); | ||||
} else | } else | ||||
ii->ii_type = II_GVAR; | ii->ii_type = II_GVAR; | ||||
hash_add(td->td_iihash, ii); | hash_add(td->td_iihash, ii); | ||||
debug(3, "Resurrected %s object %s (%d) from %s\n", | debug(3, "Resurrected %s object %s (%d) from %s\n", | ||||
(ii->ii_type == II_GVAR ? "global" : "static"), | (ii->ii_type == II_GVAR ? "global" : "static"), | ||||
ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)")); | ii->ii_name, id, (ii->ii_owner ? ii->ii_owner : "(none)")); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, | resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize, | ||||
caddr_t ctfdata, symit_data_t *si) | caddr_t ctfdata, symit_data_t *si) | ||||
{ | { | ||||
caddr_t buf = ctfdata + h->cth_funcoff; | caddr_t buf = ctfdata + h->cth_funcoff; | ||||
size_t bufsz = h->cth_typeoff - h->cth_funcoff; | size_t bufsz = h->cth_typeoff - h->cth_funcoff; | ||||
size_t idwidth; | |||||
caddr_t dptr = buf; | caddr_t dptr = buf; | ||||
iidesc_t *ii; | iidesc_t *ii; | ||||
ushort_t info; | |||||
ushort_t retid; | |||||
GElf_Sym *sym; | GElf_Sym *sym; | ||||
int i; | int i; | ||||
idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4; | |||||
symit_reset(si); | symit_reset(si); | ||||
while (dptr < buf + bufsz) { | while (dptr < buf + bufsz) { | ||||
void *v = (void *) dptr; | uint32_t id, info, retid; | ||||
info = *((ushort_t *)v); | |||||
dptr += 2; | |||||
info = 0; | |||||
memcpy(&info, (void *) dptr, idwidth); | |||||
dptr += idwidth; | |||||
if (!(sym = symit_next(si, STT_FUNC)) && info != 0) | if (!(sym = symit_next(si, STT_FUNC)) && info != 0) | ||||
parseterminate("Unexpected end of function symbols"); | parseterminate("Unexpected end of function symbols"); | ||||
if (info == 0) { | if (info == 0) { | ||||
debug(3, "Skipping null function (%s)\n", | debug(3, "Skipping null function (%s)\n", | ||||
symit_name(si)); | symit_name(si)); | ||||
continue; | continue; | ||||
} | } | ||||
v = (void *) dptr; | retid = 0; | ||||
retid = *((ushort_t *)v); | memcpy(&retid, (void *) dptr, idwidth); | ||||
dptr += 2; | dptr += idwidth; | ||||
if (retid >= tdsize) | if (retid >= (uint_t)tdsize) | ||||
parseterminate("Reference to invalid type %d", retid); | parseterminate("Reference to invalid type %d", retid); | ||||
ii = iidesc_new(symit_name(si)); | ii = iidesc_new(symit_name(si)); | ||||
ii->ii_dtype = tdarr[retid]; | ii->ii_dtype = tdarr[retid]; | ||||
if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { | if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) { | ||||
ii->ii_type = II_SFUN; | ii->ii_type = II_SFUN; | ||||
ii->ii_owner = xstrdup(symit_curfile(si)); | ii->ii_owner = xstrdup(symit_curfile(si)); | ||||
} else | } else | ||||
ii->ii_type = II_GFUN; | 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) | if (ii->ii_nargs) | ||||
ii->ii_args = | ii->ii_args = | ||||
xmalloc(sizeof (tdesc_t *) * ii->ii_nargs); | xmalloc(sizeof (tdesc_t *) * ii->ii_nargs); | ||||
for (i = 0; i < ii->ii_nargs; i++, dptr += 2) { | for (i = 0; i < ii->ii_nargs; i++, dptr += idwidth) { | ||||
v = (void *) dptr; | id = 0; | ||||
ushort_t id = *((ushort_t *)v); | memcpy(&id, (void *) dptr, idwidth); | ||||
if (id >= tdsize) | if (id >= (uint_t)tdsize) | ||||
parseterminate("Reference to invalid type %d", | parseterminate("Reference to invalid type %d", | ||||
id); | id); | ||||
ii->ii_args[i] = tdarr[id]; | ii->ii_args[i] = tdarr[id]; | ||||
} | } | ||||
if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) { | if (ii->ii_nargs && ii->ii_args[ii->ii_nargs - 1] == NULL) { | ||||
ii->ii_nargs--; | ii->ii_nargs--; | ||||
ii->ii_vargs = 1; | ii->ii_vargs = 1; | ||||
Show All 13 Lines | |||||
{ | { | ||||
caddr_t buf = ctfdata + h->cth_typeoff; | caddr_t buf = ctfdata + h->cth_typeoff; | ||||
size_t bufsz = h->cth_stroff - h->cth_typeoff; | size_t bufsz = h->cth_stroff - h->cth_typeoff; | ||||
caddr_t sbuf = ctfdata + h->cth_stroff; | caddr_t sbuf = ctfdata + h->cth_stroff; | ||||
caddr_t dptr = buf; | caddr_t dptr = buf; | ||||
tdesc_t *tdp; | tdesc_t *tdp; | ||||
uint_t data; | uint_t data; | ||||
uint_t encoding; | uint_t encoding; | ||||
size_t size, increment; | size_t idwidth, size, increment; | ||||
int tcnt; | int tcnt; | ||||
int iicnt = 0; | int iicnt = 0; | ||||
tid_t tid, argid; | tid_t tid, argid; | ||||
int kind, vlen; | int isroot, kind, vlen; | ||||
int i; | int i, version; | ||||
elist_t **epp; | elist_t **epp; | ||||
mlist_t **mpp; | mlist_t **mpp; | ||||
intr_t *ip; | intr_t *ip; | ||||
ctf_type_t *ctt; | version = h->cth_version; | ||||
ctf_array_t *cta; | idwidth = version == CTF_VERSION_2 ? 2 : 4; | ||||
ctf_enum_t *cte; | |||||
/* | /* | ||||
* A maxid of zero indicates a request to resurrect all types, so reset | * A maxid of zero indicates a request to resurrect all types, so reset | ||||
* maxid to the maximum type id. | * maxid to the maximum type id. | ||||
*/ | */ | ||||
if (maxid == 0) | if (maxid == 0) { | ||||
maxid = CTF_MAX_TYPE; | 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++) { | 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) | if (tid > maxid) | ||||
break; | break; | ||||
if (tid >= tdsize) | if (tid >= tdsize) | ||||
parseterminate("Reference to invalid type %d", tid); | parseterminate("Reference to invalid type %d", tid); | ||||
void *v = (void *) dptr; | get_ctt_info(h, dptr, &kind, &vlen, &isroot); | ||||
ctt = v; | 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; | dptr += increment; | ||||
tdp = tdarr[tid]; | tdp = tdarr[tid]; | ||||
if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0) | if (CTF_NAME_STID(name) != CTF_STRTAB_0) | ||||
parseterminate( | parseterminate( | ||||
"Unable to cope with non-zero strtab id"); | "Unable to cope with non-zero strtab id"); | ||||
if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) { | if (CTF_NAME_OFFSET(name) != 0) { | ||||
tdp->t_name = | tdp->t_name = xstrdup(sbuf + CTF_NAME_OFFSET(name)); | ||||
xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name)); | |||||
} else | } else | ||||
tdp->t_name = NULL; | tdp->t_name = NULL; | ||||
kind = CTF_INFO_KIND(ctt->ctt_info); | |||||
vlen = CTF_INFO_VLEN(ctt->ctt_info); | |||||
switch (kind) { | switch (kind) { | ||||
case CTF_K_INTEGER: | case CTF_K_INTEGER: | ||||
tdp->t_type = INTRINSIC; | tdp->t_type = INTRINSIC; | ||||
tdp->t_size = size; | tdp->t_size = size; | ||||
v = (void *) dptr; | v = (void *) dptr; | ||||
data = *((uint_t *)v); | data = *((uint_t *)v); | ||||
dptr += sizeof (uint_t); | dptr += sizeof (uint_t); | ||||
Show All 30 Lines | case CTF_K_FLOAT: | ||||
ip->intr_fformat = CTF_FP_ENCODING(data); | ip->intr_fformat = CTF_FP_ENCODING(data); | ||||
ip->intr_offset = CTF_FP_OFFSET(data); | ip->intr_offset = CTF_FP_OFFSET(data); | ||||
ip->intr_nbits = CTF_FP_BITS(data); | ip->intr_nbits = CTF_FP_BITS(data); | ||||
tdp->t_intr = ip; | tdp->t_intr = ip; | ||||
break; | break; | ||||
case CTF_K_POINTER: | case CTF_K_POINTER: | ||||
tdp->t_type = POINTER; | tdp->t_type = POINTER; | ||||
tdp->t_tdesc = tdarr[ctt->ctt_type]; | tdp->t_tdesc = tdarr[type]; | ||||
break; | break; | ||||
case CTF_K_ARRAY: | case CTF_K_ARRAY: { | ||||
uint_t contents, index, nelems; | |||||
tdp->t_type = ARRAY; | tdp->t_type = ARRAY; | ||||
tdp->t_size = size; | tdp->t_size = size; | ||||
v = (void *) dptr; | if (version == CTF_VERSION_2) { | ||||
cta = v; | struct ctf_array_v2 *cta = (void *) dptr; | ||||
dptr += sizeof (ctf_array_t); | 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 = xmalloc(sizeof (ardef_t)); | ||||
tdp->t_ardef->ad_contents = tdarr[cta->cta_contents]; | tdp->t_ardef->ad_contents = tdarr[contents]; | ||||
tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index]; | tdp->t_ardef->ad_idxtype = tdarr[index]; | ||||
tdp->t_ardef->ad_nelems = cta->cta_nelems; | tdp->t_ardef->ad_nelems = nelems; | ||||
break; | break; | ||||
} | |||||
case CTF_K_STRUCT: | case CTF_K_STRUCT: | ||||
case CTF_K_UNION: | case CTF_K_UNION: { | ||||
tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION); | tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION); | ||||
tdp->t_size = size; | tdp->t_size = size; | ||||
if (size < CTF_LSTRUCT_THRESH) { | if (version == CTF_VERSION_2) { | ||||
if (size < CTF_V2_LSTRUCT_THRESH) { | |||||
for (i = 0, mpp = &tdp->t_members; i < vlen; | for (i = 0, mpp = &tdp->t_members; i < vlen; | ||||
i++, mpp = &((*mpp)->ml_next)) { | i++, mpp = &((*mpp)->ml_next)) { | ||||
v = (void *) dptr; | v = (void *) dptr; | ||||
ctf_member_t *ctm = v; | struct ctf_member_v2 *ctm = v; | ||||
dptr += sizeof (ctf_member_t); | dptr += sizeof (struct ctf_member_v2); | ||||
*mpp = xmalloc(sizeof (mlist_t)); | *mpp = xmalloc(sizeof (mlist_t)); | ||||
(*mpp)->ml_name = xstrdup(sbuf + | (*mpp)->ml_name = xstrdup(sbuf + | ||||
ctm->ctm_name); | ctm->ctm_name); | ||||
(*mpp)->ml_type = tdarr[ctm->ctm_type]; | (*mpp)->ml_type = tdarr[ctm->ctm_type]; | ||||
(*mpp)->ml_offset = ctm->ctm_offset; | (*mpp)->ml_offset = ctm->ctm_offset; | ||||
(*mpp)->ml_size = 0; | (*mpp)->ml_size = 0; | ||||
} | } | ||||
} else { | } else { | ||||
for (i = 0, mpp = &tdp->t_members; i < vlen; | for (i = 0, mpp = &tdp->t_members; i < vlen; | ||||
i++, mpp = &((*mpp)->ml_next)) { | i++, mpp = &((*mpp)->ml_next)) { | ||||
v = (void *) dptr; | v = (void *) dptr; | ||||
ctf_lmember_t *ctlm = v; | struct ctf_lmember_v2 *ctlm = v; | ||||
dptr += sizeof (ctf_lmember_t); | dptr += sizeof (struct ctf_lmember_v2); | ||||
*mpp = xmalloc(sizeof (mlist_t)); | *mpp = xmalloc(sizeof (mlist_t)); | ||||
(*mpp)->ml_name = xstrdup(sbuf + | (*mpp)->ml_name = xstrdup(sbuf + | ||||
ctlm->ctlm_name); | ctlm->ctlm_name); | ||||
(*mpp)->ml_type = | (*mpp)->ml_type = | ||||
tdarr[ctlm->ctlm_type]; | tdarr[ctlm->ctlm_type]; | ||||
(*mpp)->ml_offset = | (*mpp)->ml_offset = | ||||
(int)CTF_LMEM_OFFSET(ctlm); | (int)CTF_LMEM_OFFSET(ctlm); | ||||
(*mpp)->ml_size = 0; | (*mpp)->ml_size = 0; | ||||
} | } | ||||
} | } | ||||
} else { | |||||
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 + | |||||
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; | *mpp = NULL; | ||||
break; | break; | ||||
} | |||||
case CTF_K_ENUM: | case CTF_K_ENUM: | ||||
tdp->t_type = ENUM; | tdp->t_type = ENUM; | ||||
tdp->t_size = size; | tdp->t_size = size; | ||||
for (i = 0, epp = &tdp->t_emem; i < vlen; | for (i = 0, epp = &tdp->t_emem; i < vlen; | ||||
i++, epp = &((*epp)->el_next)) { | i++, epp = &((*epp)->el_next)) { | ||||
v = (void *) dptr; | v = (void *) dptr; | ||||
Show All 9 Lines | for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) { | ||||
case CTF_K_FORWARD: | case CTF_K_FORWARD: | ||||
tdp->t_type = FORWARD; | tdp->t_type = FORWARD; | ||||
list_add(&td->td_fwdlist, tdp); | list_add(&td->td_fwdlist, tdp); | ||||
break; | break; | ||||
case CTF_K_TYPEDEF: | case CTF_K_TYPEDEF: | ||||
tdp->t_type = TYPEDEF; | tdp->t_type = TYPEDEF; | ||||
tdp->t_tdesc = tdarr[ctt->ctt_type]; | tdp->t_tdesc = tdarr[type]; | ||||
break; | break; | ||||
case CTF_K_VOLATILE: | case CTF_K_VOLATILE: | ||||
tdp->t_type = VOLATILE; | tdp->t_type = VOLATILE; | ||||
tdp->t_tdesc = tdarr[ctt->ctt_type]; | tdp->t_tdesc = tdarr[type]; | ||||
break; | break; | ||||
case CTF_K_CONST: | case CTF_K_CONST: | ||||
tdp->t_type = CONST; | tdp->t_type = CONST; | ||||
tdp->t_tdesc = tdarr[ctt->ctt_type]; | tdp->t_tdesc = tdarr[type]; | ||||
break; | break; | ||||
case CTF_K_FUNCTION: | case CTF_K_FUNCTION: | ||||
tdp->t_type = FUNCTION; | tdp->t_type = FUNCTION; | ||||
tdp->t_fndef = xcalloc(sizeof (fndef_t)); | 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))); | v = (void *) (dptr + (idwidth * (vlen - 1))); | ||||
if (vlen > 0 && *(ushort_t *)v == 0) | if (vlen > 0 && *(uint_t *)v == 0) | ||||
tdp->t_fndef->fn_vargs = 1; | tdp->t_fndef->fn_vargs = 1; | ||||
tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs; | tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs; | ||||
tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) * | tdp->t_fndef->fn_args = xcalloc(sizeof (tdesc_t) * | ||||
vlen - tdp->t_fndef->fn_vargs); | vlen - tdp->t_fndef->fn_vargs); | ||||
for (i = 0; i < vlen; i++) { | for (i = 0; i < vlen; i++) { | ||||
v = (void *) dptr; | v = (void *) dptr; | ||||
argid = *(ushort_t *)v; | memcpy(&argid, v, idwidth); | ||||
dptr += sizeof (ushort_t); | dptr += idwidth; | ||||
if (argid != 0) | if (argid != 0) | ||||
tdp->t_fndef->fn_args[i] = tdarr[argid]; | tdp->t_fndef->fn_args[i] = tdarr[argid]; | ||||
} | } | ||||
if (vlen & 1) | dptr = roundup2(dptr, 4); | ||||
dptr += sizeof (ushort_t); | |||||
break; | break; | ||||
case CTF_K_RESTRICT: | case CTF_K_RESTRICT: | ||||
tdp->t_type = RESTRICT; | tdp->t_type = RESTRICT; | ||||
tdp->t_tdesc = tdarr[ctt->ctt_type]; | tdp->t_tdesc = tdarr[type]; | ||||
break; | break; | ||||
case CTF_K_UNKNOWN: | case CTF_K_UNKNOWN: | ||||
break; | break; | ||||
default: | default: | ||||
warning("Can't parse unknown CTF type %d\n", kind); | 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); | iidesc_t *ii = iidesc_new(tdp->t_name); | ||||
if (tdp->t_type == STRUCT || tdp->t_type == UNION || | if (tdp->t_type == STRUCT || tdp->t_type == UNION || | ||||
tdp->t_type == ENUM) | tdp->t_type == ENUM) | ||||
ii->ii_type = II_SOU; | ii->ii_type = II_SOU; | ||||
else | else | ||||
ii->ii_type = II_TYPE; | ii->ii_type = II_TYPE; | ||||
ii->ii_dtype = tdp; | ii->ii_dtype = tdp; | ||||
hash_add(td->td_iihash, ii); | hash_add(td->td_iihash, ii); | ||||
iicnt++; | iicnt++; | ||||
} | } | ||||
debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type, | debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type, | ||||
(CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""), | (isroot ? "root " : ""), tdesc_name(tdp), tdp->t_id); | ||||
tdesc_name(tdp), tdp->t_id); | |||||
} | } | ||||
debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt); | debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt); | ||||
} | } | ||||
/* | /* | ||||
* For lack of other inspiration, we're going to take the boring route. We | * For lack of other inspiration, we're going to take the boring route. We | ||||
* count the number of types. This lets us malloc that many tdesc structs | * count the number of types. This lets us malloc that many tdesc structs | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label) | ||||
void *v = (void *) buf; | void *v = (void *) buf; | ||||
h = v; | h = v; | ||||
buf += sizeof (ctf_header_t); | buf += sizeof (ctf_header_t); | ||||
bufsz -= sizeof (ctf_header_t); | bufsz -= sizeof (ctf_header_t); | ||||
if (h->cth_magic != CTF_MAGIC) | if (h->cth_magic != CTF_MAGIC) | ||||
parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_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); | parseterminate("Unknown CTF version %d", h->cth_version); | ||||
ctfdatasz = h->cth_stroff + h->cth_strlen; | ctfdatasz = h->cth_stroff + h->cth_strlen; | ||||
if (h->cth_flags & CTF_F_COMPRESS) { | if (h->cth_flags & CTF_F_COMPRESS) { | ||||
size_t actual; | size_t actual; | ||||
ctfdata = xmalloc(ctfdatasz); | ctfdata = xmalloc(ctfdatasz); | ||||
if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) != | if ((actual = decompress_ctf(buf, bufsz, ctfdata, ctfdatasz)) != | ||||
Show All 18 Lines |