xref: /netbsd-src/external/gpl3/gdb/dist/libctf/testsuite/libctf-writable/error-propagation.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
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