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
report_sym(ctf_dict_t * fp,ctf_link_sym_t * sym,const char * name,uint32_t idx,uint32_t st_type)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
try_maybe_reporting(int report)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   free (buf);
206 
207   return;
208 
209  create_err:
210   fprintf (stderr, "Creation failed: %s\n", ctf_errmsg (err));
211   exit (1);
212  open_err:
213   fprintf (stderr, "Reopen failed: %s\n", ctf_errmsg (err));
214   exit (1);
215  create_types_err:
216   fprintf (stderr, "Cannot create types: %s\n", ctf_errmsg (ctf_errno (fp)));
217   exit (1);
218  create_syms_err:
219   fprintf (stderr, "Cannot create syms: %s\n", ctf_errmsg (ctf_errno (fp)));
220   exit (1);
221  iter_compar_err:
222   fprintf (stderr, "Dynamic iteration comparison failure: %s "
223 	   "(reported type: %lx)\n", symname, symtype);
224   exit (1);
225  iter_err:
226   fprintf (stderr, "Cannot iterate: %s\n", ctf_errmsg (ctf_errno (fp)));
227   exit (1);
228  report_err:
229   fprintf (stderr, "Cannot report symbol: %s\n", ctf_errmsg (ctf_errno (fp)));
230   exit (1);
231  write_err:
232   fprintf (stderr, "Cannot write out: %s\n", ctf_errmsg (ctf_errno (fp)));
233   exit (1);
234  expected_overshoot_err:
235   fprintf (stderr, "Too many symbols in post-writeout comparison\n");
236   exit (1);
237  lookup_syms_err:
238   fprintf (stderr, "Explicit lookup of symbols by name failed: %s\n",
239 	   ctf_errmsg (ctf_errno (fp)));
240   exit (1);
241  expected_compar_err:
242   fprintf (stderr, "Non-dynamic iteration comparison failure: %s "
243 	   "(type %lx): expected %s (type %lx)\n", symname, symtype,
244 	   expected->name, expected->id);
245   exit (1);
246 }
247 
248 int
main(int argc,char * argv[])249 main (int argc, char *argv[])
250 {
251   try_maybe_reporting (0);
252   try_maybe_reporting (1);
253 }
254