]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c
libctf, ld: fix symtypetab and var section population under ld -r
[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 /* Possibly report some but not all of the symbols, as if we are a linker (no
102 real program would do this without using the ctf_link APIs, but it's not
103 *prohibited*, just useless, and if they do we don't want things to
104 break. In particular we want all the symbols written out, reported or no,
105 ignoring the reported symbol set entirely.) */
106 if (report)
107 {
108 ctf_link_sym_t sym;
109 sym.st_nameidx_set = 0;
110 sym.st_nameidx = 0;
111 sym.st_shndx = 404; /* Arbitrary, not SHN_UNDEF or SHN_EXTABS. */
112 sym.st_value = 404; /* Arbitrary, nonzero. */
113
114 /* STT_OBJECT: 1. Don't rely on the #define being visible: this may be a
115 non-ELF platform! */
116 if (report_sym (fp, &sym, "data_c", 2, 1) < 0 ||
117 report_sym (fp, &sym, "data_a", 3, 1) < 0)
118 goto report_err;
119
120 /* STT_FUNC: 2. */
121 if (report_sym (fp, &sym, "func_c", 4, 2) < 0 ||
122 report_sym (fp, &sym, "func_a", 5, 2) < 0)
123 goto report_err;
124 }
125
126 /* Write out, to memory. */
127
128 if ((buf = ctf_write_mem (fp, &bufsiz, 4096)) == NULL)
129 goto write_err;
130 ctf_file_close (fp);
131
132 /* Read back in. */
133 if ((fp = ctf_simple_open ((const char *) buf, bufsiz, NULL, 0, 0, NULL,
134 0, &err)) == NULL)
135 goto open_err;
136
137 /* Verify symbol order against the order we expect if this dict is sorted and
138 indexed. */
139
140 struct ctf_symtype_expected
141 {
142 const char *name;
143 ctf_id_t id;
144 } *expected;
145 struct ctf_symtype_expected expected_obj[] = { { "data_a", base2 },
146 { "data_b", base3 },
147 { "data_c", base }, NULL };
148 struct ctf_symtype_expected expected_func[] = { { "func_a", func2 },
149 { "func_b", func3 },
150 { "func_c", func }, NULL };
151 expected = expected_obj;
152
153 while ((symtype = ctf_symbol_next (fp, &i, &symname, 0)) != CTF_ERR)
154 {
155 if (expected == NULL)
156 goto expected_overshoot_err;
157 if (symtype != expected->id || strcmp (symname, expected->name) != 0)
158 goto expected_compar_err;
159 printf ("Seen: %s\n", symname);
160 expected++;
161 }
162
163 expected = expected_func;
164 while ((symtype = ctf_symbol_next (fp, &i, &symname, 1)) != CTF_ERR)
165 {
166 if (expected == NULL)
167 goto expected_overshoot_err;
168 if (symtype != expected->id || strcmp (symname, expected->name) != 0)
169 goto expected_compar_err;
170 printf ("Seen: %s\n", symname);
171 expected++;
172 }
173
174 ctf_file_close (fp);
175
176 return;
177
178 create_err:
179 fprintf (stderr, "Creation failed: %s\n", ctf_errmsg (err));
180 exit (1);
181 open_err:
182 fprintf (stderr, "Reopen failed: %s\n", ctf_errmsg (err));
183 exit (1);
184 create_types_err:
185 fprintf (stderr, "Cannot create types: %s\n", ctf_errmsg (ctf_errno (fp)));
186 exit (1);
187 create_syms_err:
188 fprintf (stderr, "Cannot create syms: %s\n", ctf_errmsg (ctf_errno (fp)));
189 exit (1);
190 iter_compar_err:
191 fprintf (stderr, "Dynamic iteration comparison failure: %s "
192 "(reported type: %lx)\n", symname, symtype);
193 exit (1);
194 iter_err:
195 fprintf (stderr, "Cannot iterate: %s\n", ctf_errmsg (ctf_errno (fp)));
196 exit (1);
197 report_err:
198 fprintf (stderr, "Cannot report symbol: %s\n", ctf_errmsg (ctf_errno (fp)));
199 exit (1);
200 write_err:
201 fprintf (stderr, "Cannot write out: %s\n", ctf_errmsg (ctf_errno (fp)));
202 exit (1);
203 expected_overshoot_err:
204 fprintf (stderr, "Too many symbols in post-writeout comparison\n");
205 exit (1);
206 expected_compar_err:
207 fprintf (stderr, "Non-dynamic iteration comparison failure: %s "
208 "(type %lx): expected %s (type %lx)\n", symname, symtype,
209 expected->name, expected->id);
210 exit (1);
211 }
212
213 int
214 main (int argc, char *argv[])
215 {
216 try_maybe_reporting (0);
217 try_maybe_reporting (1);
218 }