static int membadd(const char *name, ctf_id_t type, ulong_t offset, void *arg) { ctf_bundle_t *ctb = arg; ctf_dmdef_t *dmd; char *s = NULL; if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) return (ctf_set_errno(ctb->ctb_file, EAGAIN)); if (name != NULL && (s = ctf_strdup(name)) == NULL) { ctf_free(dmd, sizeof (ctf_dmdef_t)); return (ctf_set_errno(ctb->ctb_file, EAGAIN)); } /* * For now, dmd_type is copied as the src_fp's type; it is reset to an * equivalent dst_fp type by a final loop in ctf_add_type(), below. */ dmd->dmd_name = s; dmd->dmd_type = type; dmd->dmd_offset = offset; dmd->dmd_value = -1; ctf_list_append(&ctb->ctb_dtd->dtd_u.dtu_members, dmd); if (s != NULL) ctb->ctb_file->ctf_dtstrlen += strlen(s) + 1; ctb->ctb_file->ctf_flags |= LCTF_DIRTY; return (0); }
void ctf_dtd_insert(ctf_file_t *fp, ctf_dtdef_t *dtd) { ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1); dtd->dtd_hash = fp->ctf_dthash[h]; fp->ctf_dthash[h] = dtd; ctf_list_append(&fp->ctf_dtdefs, dtd); }
int ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value) { ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, enid); ctf_dmdef_t *dmd; uint_t kind, vlen, root; char *s; if (name == NULL) return (ctf_set_errno(fp, EINVAL)); if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); if (dtd == NULL) return (ctf_set_errno(fp, ECTF_BADID)); kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info); vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info); if (kind != CTF_K_ENUM) return (ctf_set_errno(fp, ECTF_NOTENUM)); if (vlen == CTF_MAX_VLEN) return (ctf_set_errno(fp, ECTF_DTFULL)); for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); dmd != NULL; dmd = ctf_list_next(dmd)) { if (strcmp(dmd->dmd_name, name) == 0) return (ctf_set_errno(fp, ECTF_DUPMEMBER)); } if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) return (ctf_set_errno(fp, EAGAIN)); if ((s = ctf_strdup(name)) == NULL) { ctf_free(dmd, sizeof (ctf_dmdef_t)); return (ctf_set_errno(fp, EAGAIN)); } dmd->dmd_name = s; dmd->dmd_type = CTF_ERR; dmd->dmd_offset = 0; dmd->dmd_value = value; dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1); ctf_list_append(&dtd->dtd_u.dtu_members, dmd); fp->ctf_dtstrlen += strlen(s) + 1; fp->ctf_flags |= LCTF_DIRTY; return (0); }
int ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type) { ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid); ctf_dmdef_t *dmd; ssize_t msize, malign, ssize; uint_t kind, vlen, root; char *s = NULL; if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); if (dtd == NULL) return (ctf_set_errno(fp, ECTF_BADID)); kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info); root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info); vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info); if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) return (ctf_set_errno(fp, ECTF_NOTSOU)); if (vlen == CTF_MAX_VLEN) return (ctf_set_errno(fp, ECTF_DTFULL)); if (name != NULL) { for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); dmd != NULL; dmd = ctf_list_next(dmd)) { if (dmd->dmd_name != NULL && strcmp(dmd->dmd_name, name) == 0) return (ctf_set_errno(fp, ECTF_DUPMEMBER)); } } if ((msize = ctf_type_size(fp, type)) == CTF_ERR || (malign = ctf_type_align(fp, type)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL) return (ctf_set_errno(fp, EAGAIN)); if (name != NULL && (s = ctf_strdup(name)) == NULL) { ctf_free(dmd, sizeof (ctf_dmdef_t)); return (ctf_set_errno(fp, EAGAIN)); } dmd->dmd_name = s; dmd->dmd_type = type; dmd->dmd_value = -1; if (kind == CTF_K_STRUCT && vlen != 0) { ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members); ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type); size_t off = lmd->dmd_offset; ctf_encoding_t linfo; ssize_t lsize; if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR) off += linfo.cte_bits; else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR) off += lsize * NBBY; /* * Round up the offset of the end of the last member to the * next byte boundary, convert 'off' to bytes, and then round * it up again to the next multiple of the alignment required * by the new member. Finally, convert back to bits and store * the result in dmd_offset. Technically we could do more * efficient packing if the new member is a bit-field, but * we're the "compiler" and ANSI says we can do as we choose. */ off = roundup(off, NBBY) / NBBY; off = roundup(off, MAX(malign, 1)); dmd->dmd_offset = off * NBBY; ssize = off + msize; } else { dmd->dmd_offset = 0; ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL); ssize = MAX(ssize, msize); } if (ssize > CTF_MAX_SIZE) { dtd->dtd_data.ctt_size = CTF_LSIZE_SENT; dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize); dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize); } else dtd->dtd_data.ctt_size = (ushort_t)ssize; dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1); ctf_list_append(&dtd->dtd_u.dtu_members, dmd); if (s != NULL) fp->ctf_dtstrlen += strlen(s) + 1; ctf_ref_inc(fp, type); fp->ctf_flags |= LCTF_DIRTY; return (0); }
void ctf_decl_push(ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type) { ctf_decl_node_t *cdp; ctf_decl_prec_t prec; uint_t kind, n = 1; int is_qual = 0; const ctf_type_t *tp; ctf_arinfo_t ar; if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) { cd->cd_err = fp->ctf_errno; return; } switch (kind = LCTF_INFO_KIND(fp, tp->ctt_info)) { case CTF_K_ARRAY: (void) ctf_array_info(fp, type, &ar); ctf_decl_push(cd, fp, ar.ctr_contents); n = ar.ctr_nelems; prec = CTF_PREC_ARRAY; break; case CTF_K_TYPEDEF: if (ctf_strptr(fp, tp->ctt_name)[0] == '\0') { ctf_decl_push(cd, fp, tp->ctt_type); return; } prec = CTF_PREC_BASE; break; case CTF_K_FUNCTION: ctf_decl_push(cd, fp, tp->ctt_type); prec = CTF_PREC_FUNCTION; break; case CTF_K_POINTER: ctf_decl_push(cd, fp, tp->ctt_type); prec = CTF_PREC_POINTER; break; case CTF_K_VOLATILE: case CTF_K_CONST: case CTF_K_RESTRICT: ctf_decl_push(cd, fp, tp->ctt_type); prec = cd->cd_qualp; is_qual++; break; default: prec = CTF_PREC_BASE; } if ((cdp = ctf_alloc(sizeof (ctf_decl_node_t))) == NULL) { cd->cd_err = EAGAIN; return; } cdp->cd_type = type; cdp->cd_kind = kind; cdp->cd_n = n; if (ctf_list_next(&cd->cd_nodes[prec]) == NULL) cd->cd_order[prec] = cd->cd_ordp++; /* * Reset cd_qualp to the highest precedence level that we've seen so * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER). */ if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY) cd->cd_qualp = prec; /* * C array declarators are ordered inside out so prepend them. Also by * convention qualifiers of base types precede the type specifier (e.g. * const int vs. int const) even though the two forms are equivalent. */ if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE)) ctf_list_prepend(&cd->cd_nodes[prec], cdp); else ctf_list_append(&cd->cd_nodes[prec], cdp); }