static void write_const(CTX *ctx, struct ir_const_val v) { char *s = const_unparse(NULL, v); if (TEST_UNION(IR_TYPE, tarray, &v.type)) { fprintf(ctx->f, "{%s}", s); } else if (type_is_integer(v.type)) { // Get rid of annoying-but-correct gcc warning. This happens because we // negate a value not representable in intmax_t, even though the result // is representable, i.e. the only case is INT64_MIN. if (type_equals(v.type, type_integer(true, 64)) && *GET_UNION(VALUE, vuint64, &v.value) == INT64_MIN) { fprintf(ctx->f, "INT64_MIN"); } else { fprintf(ctx->f, "%s(%s)", int_const(v.type), s); } } else if (TEST_UNION(IR_TYPE, tslice, &v.type)) { if (TEST_UNION0(VALUE, vempty, &v.value)) { fprintf(ctx->f, "{0}"); } else if (type_equals(v.type, TYPE_STRING)) { char *raw = *GET_UNION(VALUE, vstring, &v.value); fprintf(ctx->f, "{ %s, %zd }", s, raw ? strlen(raw) : 0); } else { assert(false); } } else { fprintf(ctx->f, "%s", s); } talloc_free(s); }
static int type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b) { size_t asz, bsz; int akind, bkind; mdb_ctf_arinfo_t aar, bar; /* * Resolve both types down to their fundamental types, and make * sure their sizes and kinds match. */ if (mdb_ctf_type_resolve(a, &a) != 0 || mdb_ctf_type_resolve(b, &b) != 0 || (asz = mdb_ctf_type_size(a)) == -1UL || (bsz = mdb_ctf_type_size(b)) == -1UL || (akind = mdb_ctf_type_kind(a)) == -1 || (bkind = mdb_ctf_type_kind(b)) == -1 || asz != bsz || akind != bkind) { return (0); } switch (akind) { case CTF_K_INTEGER: case CTF_K_FLOAT: case CTF_K_POINTER: /* * For pointers we could be a little stricter and require * both pointers to reference types which look vaguely * similar (for example, we could insist that the two types * have the same name). However, all we really care about * here is that the structure of the two types are the same, * and, in that regard, one pointer is as good as another. */ return (1); case CTF_K_UNION: case CTF_K_STRUCT: /* * The test for the number of members is only strictly * necessary for unions since we'll find other problems with * structs. However, the extra check will do no harm. */ return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) && mdb_ctf_member_iter(a, type_equals_cb, &b) == 0); case CTF_K_ARRAY: return (mdb_ctf_array_info(a, &aar) == 0 && mdb_ctf_array_info(b, &bar) == 0 && aar.mta_nelems == bar.mta_nelems && type_equals(aar.mta_index, bar.mta_index) && type_equals(aar.mta_contents, bar.mta_contents)); } return (0); }
bool type_equals(const struct type *a, const struct type *b) { if (a->val != b->val) return false; switch (a->val) { case TYPE_POINTER: return type_equals(a->next, b->next); case TYPE_ARRAY: return ( a->u.n_elems == b->u.n_elems && type_equals(a->next, b->next) ); case TYPE_FUNCTION: if (a->u.func.n_params != b->u.func.n_params) return false; /* check if parameters are not equal */ for (unsigned i = 0; i < a->u.func.n_params; ++i) { if (!type_equals( a->u.func.params[i], b->u.func.params[i] )) { return false; } } /* check if return is not equal */ if (!type_equals(a->next, b->next)) return false; /* check if both have the the same variadic value */ if (a->u.func.is_variadic != b->u.func.is_variadic) return false; return true; case TYPE_INT: case TYPE_UINT: return a->u.n_bits == b->u.n_bits; case TYPE_VOID: case TYPE_BOOL: case TYPE_HALF: case TYPE_FLOAT: case TYPE_DOUBLE: return true; default: ERROR_HERE; break; } }
static int type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data) { mdb_ctf_id_t b = *(mdb_ctf_id_t *)data; ulong_t boff; mdb_ctf_id_t bmem; /* * Look up the corresponding member in the other composite type. */ if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0) return (1); /* * We don't allow members to be shuffled around. */ if (aoff != boff) return (1); return (type_equals(amem, bmem) ? 0 : 1); }
static int vread_helper(mdb_ctf_id_t modid, char *modbuf, mdb_ctf_id_t tgtid, char *tgtbuf, uint_t flags) { size_t modsz, tgtsz; int modkind, tgtkind; member_t mbr; int ret; mdb_ctf_arinfo_t tar, mar; int i; /* * Resolve the types to their canonical form. */ (void) mdb_ctf_type_resolve(modid, &modid); (void) mdb_ctf_type_resolve(tgtid, &tgtid); if ((modkind = mdb_ctf_type_kind(modid)) == -1) return (-1); /* errno is set for us */ if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) return (-1); /* errno is set for us */ if (tgtkind != modkind) return (set_errno(EMDB_INCOMPAT)); switch (modkind) { case CTF_K_INTEGER: case CTF_K_FLOAT: case CTF_K_POINTER: if ((modsz = mdb_ctf_type_size(modid)) == -1UL) return (-1); /* errno is set for us */ if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) return (-1); /* errno is set for us */ /* * If the sizes don't match we need to be tricky to make * sure that the caller gets the correct data. */ if (modsz < tgtsz) { if (!(flags & MDB_CTF_VREAD_IGNORE_GROW)) return (set_errno(EMDB_INCOMPAT)); #ifdef _BIG_ENDIAN bcopy(tgtbuf + tgtsz - modsz, modbuf, modsz); #else bcopy(tgtbuf, modbuf, modsz); #endif } else if (modsz > tgtsz) { bzero(modbuf, modsz); #ifdef _BIG_ENDIAN bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz); #else bcopy(tgtbuf, modbuf, tgtsz); #endif } else { bcopy(tgtbuf, modbuf, modsz); } return (0); case CTF_K_STRUCT: mbr.m_modbuf = modbuf; mbr.m_tgtbuf = tgtbuf; mbr.m_tgtid = tgtid; mbr.m_flags = flags; return (mdb_ctf_member_iter(modid, member_cb, &mbr)); case CTF_K_UNION: /* * Unions are a little tricky. The only time it's truly * safe to read in a union is if no part of the union or * any of its component types have changed. We allow the * consumer to ignore unions. The correct use of this * feature is to read the containing structure, figure * out which component of the union is valid, compute * the location of that in the target and then read in * that part of the structure. */ if (flags & MDB_CTF_VREAD_IGNORE_UNIONS) return (0); if (!type_equals(modid, tgtid)) return (set_errno(EMDB_INCOMPAT)); modsz = mdb_ctf_type_size(modid); tgtsz = mdb_ctf_type_size(tgtid); ASSERT(modsz == tgtsz); bcopy(tgtbuf, modbuf, modsz); return (0); case CTF_K_ARRAY: if (mdb_ctf_array_info(tgtid, &tar) != 0) return (-1); /* errno is set for us */ if (mdb_ctf_array_info(modid, &mar) != 0) return (-1); /* errno is set for us */ if (tar.mta_nelems != mar.mta_nelems) return (set_errno(EMDB_INCOMPAT)); if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) return (-1); /* errno is set for us */ if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) return (-1); /* errno is set for us */ for (i = 0; i < tar.mta_nelems; i++) { ret = vread_helper(mar.mta_contents, modbuf + i * modsz, tar.mta_contents, tgtbuf + i * tgtsz, flags); if (ret != 0) return (ret); } return (0); } return (set_errno(EMDB_INCOMPAT)); }