]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c
libctf, include: find types of symbols by name
[thirdparty/binutils-gdb.git] / libctf / testsuite / libctf-writable / symtypetab-nonlinker-writeout.c
1 /* Make sure that writing out a dict with a symtypetab without going via
2 ctf_link_write (as a compiler might do to generate input destined for a
3 linker) always writes out a complete indexed, sorted symtypetab, ignoring the
4 set of symbols reported (if any). Also a test of dynamic dict sym
5 iteration. */
6
7 #include <ctf-api.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 static int
13 report_sym (ctf_dict_t *fp, ctf_link_sym_t *sym, const char *name,
14 uint32_t idx, uint32_t st_type)
15 {
16 sym->st_name = name;
17 sym->st_symidx = idx;
18 sym->st_type = st_type;
19 return ctf_link_add_linker_symbol (fp, sym);
20 }
21
22 static void
23 try_maybe_reporting (int report)
24 {
25 ctf_dict_t *fp;
26 ctf_id_t func, func2, func3, base, base2, base3;
27 ctf_encoding_t e = { CTF_INT_SIGNED, 0, sizeof (long) };
28 ctf_id_t dummy;
29 ctf_funcinfo_t fi;
30 ctf_next_t *i = NULL;
31 ctf_id_t symtype;
32 const char *symname;
33 unsigned char *buf;
34 size_t bufsiz;
35 int err;
36
37 if ((fp = ctf_create (&err)) == NULL)
38 goto create_err;
39
40 /* Add a couple of sets of types to hang symbols off. We use multiple
41 identical types so we can distinguish between distinct func / data symbols
42 later on. */
43
44 if (((base = ctf_add_integer (fp, CTF_ADD_ROOT, "long int", &e)) == CTF_ERR) ||
45 ((base2 = ctf_add_integer (fp, CTF_ADD_ROOT, "long int", &e)) == CTF_ERR) ||
46 ((base3 = ctf_add_integer (fp, CTF_ADD_ROOT, "long int", &e)) == CTF_ERR))
47 goto create_types_err;
48
49 fi.ctc_return = base;
50 fi.ctc_argc = 0;
51 fi.ctc_flags = 0;
52 if (((func = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR) ||
53 ((func2 = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR) ||
54 ((func3 = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR))
55 goto create_types_err;
56
57 /* Add some function and data symbols. We intentionally add the symbols in
58 near-inverse order by symbol name, so that we can tell whether the
59 (necessarily indexed) section was sorted (since the sort is always in
60 lexicographical sort ordef by name). */
61 if ((ctf_add_objt_sym (fp, "data_c", base) < 0) ||
62 (ctf_add_objt_sym (fp, "data_a", base2) < 0) ||
63 (ctf_add_objt_sym (fp, "data_b", base3) < 0))
64 goto create_syms_err;
65
66 if ((ctf_add_func_sym (fp, "func_c", func) < 0) ||
67 (ctf_add_func_sym (fp, "func_a", func2) < 0) ||
68 (ctf_add_func_sym (fp, "func_b", func3) < 0))
69 goto create_syms_err;
70
71 /* Make sure we can iterate over them in a dynamic dict and that they have the
72 right types. We don't care about their order at this stage, which makes
73 the validation here a bit more verbose than it is below. */
74
75 while ((symtype = ctf_symbol_next (fp, &i, &symname, 0)) != CTF_ERR)
76 {
77 if (symtype == base && strcmp (symname, "data_c") == 0)
78 continue;
79 if (symtype == base2 && strcmp (symname, "data_a") == 0)
80 continue;
81 if (symtype == base3 && strcmp (symname, "data_b") == 0)
82 continue;
83 goto iter_compar_err;
84 }
85 if (ctf_errno (fp) != ECTF_NEXT_END)
86 goto iter_err;
87
88 while ((symtype = ctf_symbol_next (fp, &i, &symname, 1)) != CTF_ERR)
89 {
90 if (symtype == func && strcmp (symname, "func_c") == 0)
91 continue;
92 if (symtype == func2 && strcmp (symname, "func_a") == 0)
93 continue;
94 if (symtype == func3 && strcmp (symname, "func_b") == 0)
95 continue;
96 goto iter_compar_err;
97 }
98 if (ctf_errno (fp) != ECTF_NEXT_END)
99 goto iter_err;
100
101 /* Look up all the symbols by name and make sure that works. */
102
103 if (ctf_lookup_by_symbol_name (fp, "data_a") != base2)
104 goto lookup_syms_err;
105 if (ctf_lookup_by_symbol_name (fp, "data_b") != base3)
106 goto lookup_syms_err;
107 if (ctf_lookup_by_symbol_name (fp, "data_c") != base)
108 goto lookup_syms_err;
109 if (ctf_lookup_by_symbol_name (fp, "func_a") != func2)
110 goto lookup_syms_err;
111 if (ctf_lookup_by_symbol_name (fp, "func_b") != func3)
112 goto lookup_syms_err;
113 if (ctf_lookup_by_symbol_name (fp, "func_c") != func)
114 goto lookup_syms_err;
115
116 /* Possibly report some but not all of the symbols, as if we are a linker (no
117 real program would do this without using the ctf_link APIs, but it's not
118 *prohibited*, just useless, and if they do we don't want things to
119 break. In particular we want all the symbols written out, reported or no,
120 ignoring the reported symbol set entirely.) */
121 if (report)
122 {
123 ctf_link_sym_t sym;
124 sym.st_nameidx_set = 0;
125 sym.st_nameidx = 0;
126 sym.st_shndx = 404; /* Arbitrary, not SHN_UNDEF or SHN_EXTABS. */
127 sym.st_value = 404; /* Arbitrary, nonzero. */
128
129 /* STT_OBJECT: 1. Don't rely on the #define being visible: this may be a
130 non-ELF platform! */
131 if (report_sym (fp, &sym, "data_c", 2, 1) < 0 ||
132 report_sym (fp, &sym, "data_a", 3, 1) < 0)
133 goto report_err;
134
135 /* STT_FUNC: 2. */
136 if (report_sym (fp, &sym, "func_c", 4, 2) < 0 ||
137 report_sym (fp, &sym, "func_a", 5, 2) < 0)
138 goto report_err;
139
140 /* Look up all the symbols by name now we have reported symbols. */
141
142 if (ctf_lookup_by_symbol_name (fp, "data_a") != base2)
143 goto lookup_syms_err;
144 if (ctf_lookup_by_symbol_name (fp, "data_b") != base3)
145 goto lookup_syms_err;
146 if (ctf_lookup_by_symbol_name (fp, "data_c") != base)
147 goto lookup_syms_err;
148 if (ctf_lookup_by_symbol_name (fp, "func_a") != func2)
149 goto lookup_syms_err;
150 if (ctf_lookup_by_symbol_name (fp, "func_b") != func3)
151 goto lookup_syms_err;
152 if (ctf_lookup_by_symbol_name (fp, "func_c") != func)
153 goto lookup_syms_err;
154 }
155
156 /* Write out, to memory. */
157
158 if ((buf = ctf_write_mem (fp, &bufsiz, 4096)) == NULL)
159 goto write_err;
160 ctf_file_close (fp);
161
162 /* Read back in. */
163 if ((fp = ctf_simple_open ((const char *) buf, bufsiz, NULL, 0, 0, NULL,
164 0, &err)) == NULL)
165 goto open_err;
166
167 /* Verify symbol order against the order we expect if this dict is sorted and
168 indexed. */
169
170 struct ctf_symtype_expected
171 {
172 const char *name;
173 ctf_id_t id;
174 } *expected;
175 struct ctf_symtype_expected expected_obj[] = { { "data_a", base2 },
176 { "data_b", base3 },
177 { "data_c", base }, NULL };
178 struct ctf_symtype_expected expected_func[] = { { "func_a", func2 },
179 { "func_b", func3 },
180 { "func_c", func }, NULL };
181 expected = expected_obj;
182
183 while ((symtype = ctf_symbol_next (fp, &i, &symname, 0)) != CTF_ERR)
184 {
185 if (expected == NULL)
186 goto expected_overshoot_err;
187 if (symtype != expected->id || strcmp (symname, expected->name) != 0)
188 goto expected_compar_err;
189 printf ("Seen: %s\n", symname);
190 expected++;
191 }
192
193 expected = expected_func;
194 while ((symtype = ctf_symbol_next (fp, &i, &symname, 1)) != CTF_ERR)
195 {
196 if (expected == NULL)
197 goto expected_overshoot_err;
198 if (symtype != expected->id || strcmp (symname, expected->name) != 0)
199 goto expected_compar_err;
200 printf ("Seen: %s\n", symname);
201 expected++;
202 }
203
204 ctf_file_close (fp);
205
206 return;
207
208 create_err:
209 fprintf (stderr, "Creation failed: %s\n", ctf_errmsg (err));
210 exit (1);
211 open_err:
212 fprintf (stderr, "Reopen failed: %s\n", ctf_errmsg (err));
213 exit (1);
214 create_types_err:
215 fprintf (stderr, "Cannot create types: %s\n", ctf_errmsg (ctf_errno (fp)));
216 exit (1);
217 create_syms_err:
218 fprintf (stderr, "Cannot create syms: %s\n", ctf_errmsg (ctf_errno (fp)));
219 exit (1);
220 iter_compar_err:
221 fprintf (stderr, "Dynamic iteration comparison failure: %s "
222 "(reported type: %lx)\n", symname, symtype);
223 exit (1);
224 iter_err:
225 fprintf (stderr, "Cannot iterate: %s\n", ctf_errmsg (ctf_errno (fp)));
226 exit (1);
227 report_err:
228 fprintf (stderr, "Cannot report symbol: %s\n", ctf_errmsg (ctf_errno (fp)));
229 exit (1);
230 write_err:
231 fprintf (stderr, "Cannot write out: %s\n", ctf_errmsg (ctf_errno (fp)));
232 exit (1);
233 expected_overshoot_err:
234 fprintf (stderr, "Too many symbols in post-writeout comparison\n");
235 exit (1);
236 lookup_syms_err:
237 fprintf (stderr, "Explicit lookup of symbols by name failed: %s\n",
238 ctf_errmsg (ctf_errno (fp)));
239 exit (1);
240 expected_compar_err:
241 fprintf (stderr, "Non-dynamic iteration comparison failure: %s "
242 "(type %lx): expected %s (type %lx)\n", symname, symtype,
243 expected->name, expected->id);
244 exit (1);
245 }
246
247 int
248 main (int argc, char *argv[])
249 {
250 try_maybe_reporting (0);
251 try_maybe_reporting (1);
252 }