1*c9055873Schristos /* Make sure that errors are propagated properly from parent dicts to children 2*c9055873Schristos when errors are encountered in child functions that can recurse to parents. 3*c9055873Schristos 4*c9055873Schristos We check specifically a subset of known-buggy functions. 5*c9055873Schristos Functions that require a buggy linker to expose, or that only fail on 6*c9055873Schristos assertion-failure-incurring corrupted dicts, are not tested. */ 7*c9055873Schristos 8*c9055873Schristos #include <ctf-api.h> 9*c9055873Schristos #include <stdio.h> 10*c9055873Schristos #include <stdlib.h> 11*c9055873Schristos #include <string.h> 12*c9055873Schristos 13*c9055873Schristos static const char *desc; 14*c9055873Schristos 15*c9055873Schristos static void 16*c9055873Schristos check_prop_err (ctf_dict_t *child, ctf_dict_t *parent, int expected) 17*c9055873Schristos { 18*c9055873Schristos if (ctf_errno (child) == expected) 19*c9055873Schristos return; 20*c9055873Schristos 21*c9055873Schristos if (ctf_errno (parent) == expected) 22*c9055873Schristos fprintf (stderr, "%s: error propagation failure: error \"%s\" not seen on child, " 23*c9055873Schristos "but instead on parent\n", desc, ctf_errmsg (ctf_errno (parent))); 24*c9055873Schristos else 25*c9055873Schristos fprintf (stderr, "%s: expected error is entirely lost: " 26*c9055873Schristos "\"%s\" seen on parent, \"%s\" on child\n", desc, 27*c9055873Schristos ctf_errmsg (ctf_errno (parent)), 28*c9055873Schristos ctf_errmsg (ctf_errno (child))); 29*c9055873Schristos } 30*c9055873Schristos 31*c9055873Schristos static void 32*c9055873Schristos no_prop_err (void) 33*c9055873Schristos { 34*c9055873Schristos fprintf (stderr, "%s: expected error return not observed.\n", desc); 35*c9055873Schristos } 36*c9055873Schristos 37*c9055873Schristos int main (void) 38*c9055873Schristos { 39*c9055873Schristos ctf_dict_t *parent; 40*c9055873Schristos ctf_dict_t *blank; 41*c9055873Schristos ctf_dict_t *child; 42*c9055873Schristos ctf_id_t void_id; 43*c9055873Schristos ctf_id_t base; 44*c9055873Schristos ctf_id_t slice; 45*c9055873Schristos ctf_id_t function; 46*c9055873Schristos ctf_encoding_t long_encoding = { CTF_INT_SIGNED, 0, sizeof (long) }; 47*c9055873Schristos ctf_encoding_t void_encoding = { CTF_INT_SIGNED, 0, 0 }; 48*c9055873Schristos ctf_encoding_t foo; 49*c9055873Schristos ctf_funcinfo_t fi; 50*c9055873Schristos ctf_id_t bar; 51*c9055873Schristos char *funcname; 52*c9055873Schristos int err; 53*c9055873Schristos 54*c9055873Schristos if ((parent = ctf_create (&err)) == NULL 55*c9055873Schristos || (child = ctf_create (&err)) == NULL 56*c9055873Schristos || (blank = ctf_create (&err)) == NULL) 57*c9055873Schristos { 58*c9055873Schristos fprintf (stderr, "Cannot create dicts: %s\n", ctf_errmsg (err)); 59*c9055873Schristos return 1; 60*c9055873Schristos } 61*c9055873Schristos 62*c9055873Schristos if ((ctf_import (child, parent)) < 0) 63*c9055873Schristos { 64*c9055873Schristos fprintf (stderr, "cannot import: %s\n", ctf_errmsg (ctf_errno (child))); 65*c9055873Schristos return 1; 66*c9055873Schristos } 67*c9055873Schristos 68*c9055873Schristos if ((void_id = ctf_add_integer (parent, CTF_ADD_ROOT, "void", &void_encoding)) 69*c9055873Schristos == CTF_ERR) 70*c9055873Schristos goto parent_err; 71*c9055873Schristos 72*c9055873Schristos if ((base = ctf_add_integer (parent, CTF_ADD_ROOT, "long int", &long_encoding)) 73*c9055873Schristos == CTF_ERR) 74*c9055873Schristos goto parent_err; 75*c9055873Schristos 76*c9055873Schristos foo.cte_format = 0; 77*c9055873Schristos foo.cte_bits = 4; 78*c9055873Schristos foo.cte_offset = 4; 79*c9055873Schristos if ((slice = ctf_add_slice (child, CTF_ADD_ROOT, base, &foo)) == CTF_ERR) 80*c9055873Schristos goto parent_err; 81*c9055873Schristos 82*c9055873Schristos if (ctf_add_variable (parent, "foo", base) < 0) 83*c9055873Schristos goto child_err; 84*c9055873Schristos 85*c9055873Schristos fi.ctc_return = void_id; 86*c9055873Schristos fi.ctc_argc = 0; 87*c9055873Schristos fi.ctc_flags = 0; 88*c9055873Schristos if ((function = ctf_add_function (child, CTF_ADD_ROOT, &fi, NULL)) == CTF_ERR) 89*c9055873Schristos goto child_err; 90*c9055873Schristos 91*c9055873Schristos desc = "func info lookup of non-function"; 92*c9055873Schristos if ((ctf_func_type_info (child, base, &fi)) != CTF_ERR) 93*c9055873Schristos no_prop_err (); 94*c9055873Schristos check_prop_err (child, parent, ECTF_NOTFUNC); 95*c9055873Schristos 96*c9055873Schristos desc = "func args lookup of non-function"; 97*c9055873Schristos if ((ctf_func_type_args (child, base, 0, &bar)) != CTF_ERR) 98*c9055873Schristos no_prop_err (); 99*c9055873Schristos check_prop_err (child, parent, ECTF_NOTFUNC); 100*c9055873Schristos 101*c9055873Schristos if ((ctf_import (child, blank)) < 0) 102*c9055873Schristos { 103*c9055873Schristos fprintf (stderr, "cannot reimport: %s\n", ctf_errmsg (ctf_errno (child))); 104*c9055873Schristos return 1; 105*c9055873Schristos } 106*c9055873Schristos 107*c9055873Schristos /* This is testing ctf_type_resolve_unsliced(), which is called by the enum 108*c9055873Schristos functions (which are not themselves buggy). This typea isn't an enum, but 109*c9055873Schristos that's OK: we're after an error, after all, and the type we're slicing is 110*c9055873Schristos not visible any longer, so nothing can tell it's not an enum. */ 111*c9055873Schristos 112*c9055873Schristos desc = "child slice resolution"; 113*c9055873Schristos if ((ctf_enum_value (child, slice, "foo", NULL)) != CTF_ERR) 114*c9055873Schristos no_prop_err (); 115*c9055873Schristos check_prop_err (child, parent, ECTF_BADID); 116*c9055873Schristos 117*c9055873Schristos desc = "child slice encoding lookup"; 118*c9055873Schristos if ((ctf_type_encoding (child, slice, &foo)) != CTF_ERR) 119*c9055873Schristos no_prop_err (); 120*c9055873Schristos check_prop_err (child, parent, ECTF_BADID); 121*c9055873Schristos 122*c9055873Schristos desc = "func info lookup of non-function"; 123*c9055873Schristos if ((ctf_func_type_info (child, base, &fi)) != CTF_ERR) 124*c9055873Schristos no_prop_err (); 125*c9055873Schristos check_prop_err (child, parent, ECTF_BADID); 126*c9055873Schristos 127*c9055873Schristos desc = "func args lookup of non-function"; 128*c9055873Schristos if ((ctf_func_type_args (child, base, 0, &bar)) != CTF_ERR) 129*c9055873Schristos no_prop_err (); 130*c9055873Schristos check_prop_err (child, parent, ECTF_BADID); 131*c9055873Schristos 132*c9055873Schristos desc = "child slice addition"; 133*c9055873Schristos if ((slice = ctf_add_slice (child, CTF_ADD_ROOT, base, &foo)) != CTF_ERR) 134*c9055873Schristos no_prop_err (); 135*c9055873Schristos check_prop_err (child, parent, ECTF_BADID); 136*c9055873Schristos 137*c9055873Schristos desc = "variable lookup"; 138*c9055873Schristos if (ctf_lookup_variable (child, "foo") != CTF_ERR) 139*c9055873Schristos no_prop_err (); 140*c9055873Schristos check_prop_err (child, parent, ECTF_NOTYPEDAT); 141*c9055873Schristos 142*c9055873Schristos desc = "function lookup via ctf_type_aname"; 143*c9055873Schristos if ((funcname = ctf_type_aname (child, function)) != NULL) 144*c9055873Schristos { 145*c9055873Schristos no_prop_err (); 146*c9055873Schristos free (funcname); 147*c9055873Schristos } 148*c9055873Schristos check_prop_err (child, parent, ECTF_BADID); 149*c9055873Schristos 150*c9055873Schristos ctf_dict_close (child); 151*c9055873Schristos ctf_dict_close (parent); 152*c9055873Schristos ctf_dict_close (blank); 153*c9055873Schristos fprintf (stderr, "All done.\n"); 154*c9055873Schristos return 0; 155*c9055873Schristos 156*c9055873Schristos parent_err: 157*c9055873Schristos fprintf (stderr, "cannot populate parent: %s\n", ctf_errmsg (ctf_errno (parent))); 158*c9055873Schristos return 1; 159*c9055873Schristos 160*c9055873Schristos child_err: 161*c9055873Schristos fprintf (stderr, "cannot populate child: %s\n", ctf_errmsg (ctf_errno (parent))); 162*c9055873Schristos return 1; 163*c9055873Schristos 164*c9055873Schristos } 165