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