/src/binutils-gdb/libctf/ctf-serialize.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* CTF dict creation. |
2 | | Copyright (C) 2019-2025 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of libctf. |
5 | | |
6 | | libctf is free software; you can redistribute it and/or modify it under |
7 | | the terms of the GNU General Public License as published by the Free |
8 | | Software Foundation; either version 3, or (at your option) any later |
9 | | version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, but |
12 | | WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
14 | | See the GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program; see the file COPYING. If not see |
18 | | <http://www.gnu.org/licenses/>. */ |
19 | | |
20 | | #include <ctf-impl.h> |
21 | | #include <assert.h> |
22 | | #include <string.h> |
23 | | #include <unistd.h> |
24 | | #include <zlib.h> |
25 | | |
26 | | #include <elf.h> |
27 | | #include "elf-bfd.h" |
28 | | |
29 | | /* Symtypetab sections. */ |
30 | | |
31 | | /* Symtypetab emission flags. */ |
32 | | |
33 | 0 | #define CTF_SYMTYPETAB_EMIT_FUNCTION 0x1 |
34 | 0 | #define CTF_SYMTYPETAB_EMIT_PAD 0x2 |
35 | 0 | #define CTF_SYMTYPETAB_FORCE_INDEXED 0x4 |
36 | | |
37 | | /* Properties of symtypetab emission, shared by symtypetab section |
38 | | sizing and symtypetab emission itself. */ |
39 | | |
40 | | typedef struct emit_symtypetab_state |
41 | | { |
42 | | /* True if linker-reported symbols are being filtered out. symfp is set if |
43 | | this is true: otherwise, indexing is forced and the symflags indicate as |
44 | | much. */ |
45 | | int filter_syms; |
46 | | |
47 | | /* True if symbols are being sorted. */ |
48 | | int sort_syms; |
49 | | |
50 | | /* Flags for symtypetab emission. */ |
51 | | int symflags; |
52 | | |
53 | | /* The dict to which the linker has reported symbols. */ |
54 | | ctf_dict_t *symfp; |
55 | | |
56 | | /* The maximum number of objects seen. */ |
57 | | size_t maxobjt; |
58 | | |
59 | | /* The maximum number of func info entris seen. */ |
60 | | size_t maxfunc; |
61 | | } emit_symtypetab_state_t; |
62 | | |
63 | | /* Determine if a symbol is "skippable" and should never appear in the |
64 | | symtypetab sections. */ |
65 | | |
66 | | int |
67 | | ctf_symtab_skippable (ctf_link_sym_t *sym) |
68 | 0 | { |
69 | | /* Never skip symbols whose name is not yet known. */ |
70 | 0 | if (sym->st_nameidx_set) |
71 | 0 | return 0; |
72 | | |
73 | 0 | return (sym->st_name == NULL || sym->st_name[0] == 0 |
74 | 0 | || sym->st_shndx == SHN_UNDEF |
75 | 0 | || strcmp (sym->st_name, "_START_") == 0 |
76 | 0 | || strcmp (sym->st_name, "_END_") == 0 |
77 | 0 | || (sym->st_type == STT_OBJECT && sym->st_shndx == SHN_EXTABS |
78 | 0 | && sym->st_value == 0)); |
79 | 0 | } |
80 | | |
81 | | /* Get the number of symbols in a symbol hash, the count of symbols, the maximum |
82 | | seen, the eventual size, without any padding elements, of the func/data and |
83 | | (if generated) index sections, and the size of accumulated padding elements. |
84 | | The linker-reported set of symbols is found in SYMFP: it may be NULL if |
85 | | symbol filtering is not desired, in which case CTF_SYMTYPETAB_FORCE_INDEXED |
86 | | will always be set in the flags. |
87 | | |
88 | | Also figure out if any symbols need to be moved to the variable section, and |
89 | | add them (if not already present). */ |
90 | | |
91 | | _libctf_nonnull_ ((1,3,4,5,6,7,8)) |
92 | | static int |
93 | | symtypetab_density (ctf_dict_t *fp, ctf_dict_t *symfp, ctf_dynhash_t *symhash, |
94 | | size_t *count, size_t *max, size_t *unpadsize, |
95 | | size_t *padsize, size_t *idxsize, int flags) |
96 | 0 | { |
97 | 0 | ctf_next_t *i = NULL; |
98 | 0 | const void *name; |
99 | 0 | const void *ctf_sym; |
100 | 0 | ctf_dynhash_t *linker_known = NULL; |
101 | 0 | int err; |
102 | 0 | int beyond_max = 0; |
103 | |
|
104 | 0 | *count = 0; |
105 | 0 | *max = 0; |
106 | 0 | *unpadsize = 0; |
107 | 0 | *idxsize = 0; |
108 | 0 | *padsize = 0; |
109 | |
|
110 | 0 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) |
111 | 0 | { |
112 | | /* Make a dynhash citing only symbols reported by the linker of the |
113 | | appropriate type, then traverse all potential-symbols we know the types |
114 | | of, removing them from linker_known as we go. Once this is done, the |
115 | | only symbols remaining in linker_known are symbols we don't know the |
116 | | types of: we must emit pads for those symbols that are below the |
117 | | maximum symbol we will emit (any beyond that are simply skipped). |
118 | | |
119 | | If there are none, this symtypetab will be empty: just report that. */ |
120 | |
|
121 | 0 | if (!symfp->ctf_dynsyms) |
122 | 0 | return 0; |
123 | | |
124 | 0 | if ((linker_known = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, |
125 | 0 | NULL, NULL)) == NULL) |
126 | 0 | return (ctf_set_errno (fp, ENOMEM)); |
127 | | |
128 | 0 | while ((err = ctf_dynhash_cnext (symfp->ctf_dynsyms, &i, |
129 | 0 | &name, &ctf_sym)) == 0) |
130 | 0 | { |
131 | 0 | ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym; |
132 | |
|
133 | 0 | if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
134 | 0 | && sym->st_type != STT_FUNC) |
135 | 0 | || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
136 | 0 | && sym->st_type != STT_OBJECT)) |
137 | 0 | continue; |
138 | | |
139 | 0 | if (ctf_symtab_skippable (sym)) |
140 | 0 | continue; |
141 | | |
142 | | /* This should only be true briefly before all the names are |
143 | | finalized, long before we get this far. */ |
144 | 0 | if (!ctf_assert (fp, !sym->st_nameidx_set)) |
145 | 0 | return -1; /* errno is set for us. */ |
146 | | |
147 | 0 | if (ctf_dynhash_cinsert (linker_known, name, ctf_sym) < 0) |
148 | 0 | { |
149 | 0 | ctf_dynhash_destroy (linker_known); |
150 | 0 | return (ctf_set_errno (fp, ENOMEM)); |
151 | 0 | } |
152 | 0 | } |
153 | 0 | if (err != ECTF_NEXT_END) |
154 | 0 | { |
155 | 0 | ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols during " |
156 | 0 | "serialization")); |
157 | 0 | ctf_dynhash_destroy (linker_known); |
158 | 0 | return (ctf_set_errno (fp, err)); |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | 0 | while ((err = ctf_dynhash_cnext (symhash, &i, &name, NULL)) == 0) |
163 | 0 | { |
164 | 0 | ctf_link_sym_t *sym; |
165 | |
|
166 | 0 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) |
167 | 0 | { |
168 | | /* Linker did not report symbol in symtab. Remove it from the |
169 | | set of known data symbols and continue. */ |
170 | 0 | if ((sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, name)) == NULL) |
171 | 0 | { |
172 | 0 | ctf_dynhash_remove (symhash, name); |
173 | 0 | continue; |
174 | 0 | } |
175 | | |
176 | | /* We don't remove skippable symbols from the symhash because we don't |
177 | | want them to be migrated into variables. */ |
178 | 0 | if (ctf_symtab_skippable (sym)) |
179 | 0 | continue; |
180 | | |
181 | 0 | if ((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
182 | 0 | && sym->st_type != STT_FUNC) |
183 | 0 | { |
184 | 0 | ctf_err_warn (fp, 1, 0, _("symbol %s (%x) added to CTF as a " |
185 | 0 | "function but is of type %x. " |
186 | 0 | "The symbol type lookup tables " |
187 | 0 | "are probably corrupted"), |
188 | 0 | sym->st_name, sym->st_symidx, sym->st_type); |
189 | 0 | ctf_dynhash_remove (symhash, name); |
190 | 0 | continue; |
191 | 0 | } |
192 | 0 | else if (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
193 | 0 | && sym->st_type != STT_OBJECT) |
194 | 0 | { |
195 | 0 | ctf_err_warn (fp, 1, 0, _("symbol %s (%x) added to CTF as a " |
196 | 0 | "data object but is of type %x. " |
197 | 0 | "The symbol type lookup tables " |
198 | 0 | "are probably corrupted"), |
199 | 0 | sym->st_name, sym->st_symidx, sym->st_type); |
200 | 0 | ctf_dynhash_remove (symhash, name); |
201 | 0 | continue; |
202 | 0 | } |
203 | | |
204 | 0 | ctf_dynhash_remove (linker_known, name); |
205 | |
|
206 | 0 | if (*max < sym->st_symidx) |
207 | 0 | *max = sym->st_symidx; |
208 | 0 | } |
209 | 0 | else |
210 | 0 | (*max)++; |
211 | | |
212 | 0 | *unpadsize += sizeof (uint32_t); |
213 | 0 | (*count)++; |
214 | 0 | } |
215 | 0 | if (err != ECTF_NEXT_END) |
216 | 0 | { |
217 | 0 | ctf_err_warn (fp, 0, err, _("iterating over CTF symtypetab during " |
218 | 0 | "serialization")); |
219 | 0 | ctf_dynhash_destroy (linker_known); |
220 | 0 | return (ctf_set_errno (fp, err)); |
221 | 0 | } |
222 | | |
223 | 0 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) |
224 | 0 | { |
225 | 0 | while ((err = ctf_dynhash_cnext (linker_known, &i, NULL, &ctf_sym)) == 0) |
226 | 0 | { |
227 | 0 | ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym; |
228 | |
|
229 | 0 | if (sym->st_symidx > *max) |
230 | 0 | beyond_max++; |
231 | 0 | } |
232 | 0 | if (err != ECTF_NEXT_END) |
233 | 0 | { |
234 | 0 | ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols " |
235 | 0 | "during CTF serialization")); |
236 | 0 | ctf_dynhash_destroy (linker_known); |
237 | 0 | return (ctf_set_errno (fp, err)); |
238 | 0 | } |
239 | 0 | } |
240 | | |
241 | 0 | *idxsize = *count * sizeof (uint32_t); |
242 | 0 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) |
243 | 0 | *padsize = (ctf_dynhash_elements (linker_known) - beyond_max) * sizeof (uint32_t); |
244 | |
|
245 | 0 | ctf_dynhash_destroy (linker_known); |
246 | 0 | return 0; |
247 | 0 | } |
248 | | |
249 | | /* Emit an objt or func symtypetab into DP in a particular order defined by an |
250 | | array of ctf_link_sym_t or symbol names passed in. The index has NIDX |
251 | | elements in it: unindexed output would terminate at symbol OUTMAX and is in |
252 | | any case no larger than SIZE bytes. Some index elements are expected to be |
253 | | skipped: see symtypetab_density. The linker-reported set of symbols (if any) |
254 | | is found in SYMFP. */ |
255 | | static int |
256 | | emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp, |
257 | | ctf_link_sym_t **idx, const char **nameidx, uint32_t nidx, |
258 | | uint32_t outmax, int size, int flags) |
259 | 0 | { |
260 | 0 | uint32_t i; |
261 | 0 | uint32_t *dpp = dp; |
262 | 0 | ctf_dynhash_t *symhash; |
263 | |
|
264 | 0 | ctf_dprintf ("Emitting table of size %i, outmax %u, %u symtypetab entries, " |
265 | 0 | "flags %i\n", size, outmax, nidx, flags); |
266 | | |
267 | | /* Empty table? Nothing to do. */ |
268 | 0 | if (size == 0) |
269 | 0 | return 0; |
270 | | |
271 | 0 | if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
272 | 0 | symhash = fp->ctf_funchash; |
273 | 0 | else |
274 | 0 | symhash = fp->ctf_objthash; |
275 | |
|
276 | 0 | for (i = 0; i < nidx; i++) |
277 | 0 | { |
278 | 0 | const char *sym_name; |
279 | 0 | void *type; |
280 | | |
281 | | /* If we have a linker-reported set of symbols, we may be given that set |
282 | | to work from, or a set of symbol names. In both cases we want to look |
283 | | at the corresponding linker-reported symbol (if any). */ |
284 | 0 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) |
285 | 0 | { |
286 | 0 | ctf_link_sym_t *this_link_sym; |
287 | |
|
288 | 0 | if (idx) |
289 | 0 | this_link_sym = idx[i]; |
290 | 0 | else |
291 | 0 | this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, nameidx[i]); |
292 | | |
293 | | /* Unreported symbol number. No pad, no nothing. */ |
294 | 0 | if (!this_link_sym) |
295 | 0 | continue; |
296 | | |
297 | | /* Symbol of the wrong type, or skippable? This symbol is not in this |
298 | | table. */ |
299 | 0 | if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
300 | 0 | && this_link_sym->st_type != STT_FUNC) |
301 | 0 | || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
302 | 0 | && this_link_sym->st_type != STT_OBJECT)) |
303 | 0 | continue; |
304 | | |
305 | 0 | if (ctf_symtab_skippable (this_link_sym)) |
306 | 0 | continue; |
307 | | |
308 | 0 | sym_name = this_link_sym->st_name; |
309 | | |
310 | | /* Linker reports symbol of a different type to the symbol we actually |
311 | | added? Skip the symbol. No pad, since the symbol doesn't actually |
312 | | belong in this table at all. (Warned about in |
313 | | symtypetab_density.) */ |
314 | 0 | if ((this_link_sym->st_type == STT_FUNC) |
315 | 0 | && (ctf_dynhash_lookup (fp->ctf_objthash, sym_name))) |
316 | 0 | continue; |
317 | | |
318 | 0 | if ((this_link_sym->st_type == STT_OBJECT) |
319 | 0 | && (ctf_dynhash_lookup (fp->ctf_funchash, sym_name))) |
320 | 0 | continue; |
321 | 0 | } |
322 | 0 | else |
323 | 0 | sym_name = nameidx[i]; |
324 | | |
325 | | /* Symbol in index but no type set? Silently skip and (optionally) |
326 | | pad. (In force-indexed mode, this is also where we track symbols of |
327 | | the wrong type for this round of insertion.) */ |
328 | 0 | if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL) |
329 | 0 | { |
330 | 0 | if (flags & CTF_SYMTYPETAB_EMIT_PAD) |
331 | 0 | *dpp++ = 0; |
332 | 0 | continue; |
333 | 0 | } |
334 | | |
335 | 0 | if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) < size)) |
336 | 0 | return -1; /* errno is set for us. */ |
337 | | |
338 | 0 | *dpp++ = (ctf_id_t) (uintptr_t) type; |
339 | | |
340 | | /* When emitting unindexed output, all later symbols are pads: stop |
341 | | early. */ |
342 | 0 | if ((flags & CTF_SYMTYPETAB_EMIT_PAD) && idx[i]->st_symidx == outmax) |
343 | 0 | break; |
344 | 0 | } |
345 | | |
346 | 0 | return 0; |
347 | 0 | } |
348 | | |
349 | | /* Emit an objt or func symtypetab index into DP in a paticular order defined by |
350 | | an array of symbol names passed in. Stop at NIDX. The linker-reported set |
351 | | of symbols (if any) is found in SYMFP. */ |
352 | | static int |
353 | | emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp, |
354 | | const char **idx, uint32_t nidx, int size, int flags) |
355 | 0 | { |
356 | 0 | uint32_t i; |
357 | 0 | uint32_t *dpp = dp; |
358 | 0 | ctf_dynhash_t *symhash; |
359 | |
|
360 | 0 | ctf_dprintf ("Emitting index of size %i, %u entries reported by linker, " |
361 | 0 | "flags %i\n", size, nidx, flags); |
362 | | |
363 | | /* Empty table? Nothing to do. */ |
364 | 0 | if (size == 0) |
365 | 0 | return 0; |
366 | | |
367 | 0 | if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
368 | 0 | symhash = fp->ctf_funchash; |
369 | 0 | else |
370 | 0 | symhash = fp->ctf_objthash; |
371 | | |
372 | | /* Indexes should always be unpadded. */ |
373 | 0 | if (!ctf_assert (fp, !(flags & CTF_SYMTYPETAB_EMIT_PAD))) |
374 | 0 | return -1; /* errno is set for us. */ |
375 | | |
376 | 0 | for (i = 0; i < nidx; i++) |
377 | 0 | { |
378 | 0 | const char *sym_name; |
379 | 0 | void *type; |
380 | |
|
381 | 0 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) |
382 | 0 | { |
383 | 0 | ctf_link_sym_t *this_link_sym; |
384 | |
|
385 | 0 | this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, idx[i]); |
386 | | |
387 | | /* This is an index: unreported symbols should never appear in it. */ |
388 | 0 | if (!ctf_assert (fp, this_link_sym != NULL)) |
389 | 0 | return -1; /* errno is set for us. */ |
390 | | |
391 | | /* Symbol of the wrong type, or skippable? This symbol is not in this |
392 | | table. */ |
393 | 0 | if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
394 | 0 | && this_link_sym->st_type != STT_FUNC) |
395 | 0 | || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) |
396 | 0 | && this_link_sym->st_type != STT_OBJECT)) |
397 | 0 | continue; |
398 | | |
399 | 0 | if (ctf_symtab_skippable (this_link_sym)) |
400 | 0 | continue; |
401 | | |
402 | 0 | sym_name = this_link_sym->st_name; |
403 | | |
404 | | /* Linker reports symbol of a different type to the symbol we actually |
405 | | added? Skip the symbol. */ |
406 | 0 | if ((this_link_sym->st_type == STT_FUNC) |
407 | 0 | && (ctf_dynhash_lookup (fp->ctf_objthash, sym_name))) |
408 | 0 | continue; |
409 | | |
410 | 0 | if ((this_link_sym->st_type == STT_OBJECT) |
411 | 0 | && (ctf_dynhash_lookup (fp->ctf_funchash, sym_name))) |
412 | 0 | continue; |
413 | 0 | } |
414 | 0 | else |
415 | 0 | sym_name = idx[i]; |
416 | | |
417 | | /* Symbol in index and reported by linker, but no type set? Silently skip |
418 | | and (optionally) pad. (In force-indexed mode, this is also where we |
419 | | track symbols of the wrong type for this round of insertion.) */ |
420 | 0 | if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL) |
421 | 0 | continue; |
422 | | |
423 | 0 | ctf_str_add_ref (fp, sym_name, dpp++); |
424 | |
|
425 | 0 | if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) <= size)) |
426 | 0 | return -1; /* errno is set for us. */ |
427 | 0 | } |
428 | | |
429 | 0 | return 0; |
430 | 0 | } |
431 | | |
432 | | /* Delete symbols that have been assigned names from the variable section. Must |
433 | | be called from within ctf_serialize, because that is the only place you can |
434 | | safely delete variables without messing up ctf_rollback. */ |
435 | | |
436 | | static int |
437 | | symtypetab_delete_nonstatics (ctf_dict_t *fp, ctf_dict_t *symfp) |
438 | 0 | { |
439 | 0 | ctf_dvdef_t *dvd, *nvd; |
440 | 0 | ctf_id_t type; |
441 | |
|
442 | 0 | for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd) |
443 | 0 | { |
444 | 0 | nvd = ctf_list_next (dvd); |
445 | |
|
446 | 0 | if ((((type = (ctf_id_t) (uintptr_t) |
447 | 0 | ctf_dynhash_lookup (fp->ctf_objthash, dvd->dvd_name)) > 0) |
448 | 0 | || (type = (ctf_id_t) (uintptr_t) |
449 | 0 | ctf_dynhash_lookup (fp->ctf_funchash, dvd->dvd_name)) > 0) |
450 | 0 | && ctf_dynhash_lookup (symfp->ctf_dynsyms, dvd->dvd_name) != NULL |
451 | 0 | && type == dvd->dvd_type) |
452 | 0 | ctf_dvd_delete (fp, dvd); |
453 | 0 | } |
454 | |
|
455 | 0 | return 0; |
456 | 0 | } |
457 | | |
458 | | /* Figure out the sizes of the symtypetab sections, their indexed state, |
459 | | etc. */ |
460 | | static int |
461 | | ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s, |
462 | | ctf_header_t *hdr, size_t *objt_size, |
463 | | size_t *func_size, size_t *objtidx_size, |
464 | | size_t *funcidx_size) |
465 | 0 | { |
466 | 0 | size_t nfuncs, nobjts; |
467 | 0 | size_t objt_unpadsize, func_unpadsize, objt_padsize, func_padsize; |
468 | | |
469 | | /* If doing a writeout as part of linking, and the link flags request it, |
470 | | filter out reported symbols from the variable section, and filter out all |
471 | | other symbols from the symtypetab sections. (If we are not linking, the |
472 | | symbols are sorted; if we are linking, don't bother sorting if we are not |
473 | | filtering out reported symbols: this is almost certainly an ld -r and only |
474 | | the linker is likely to consume these symtypetabs again. The linker |
475 | | doesn't care what order the symtypetab entries are in, since it only |
476 | | iterates over symbols and does not use the ctf_lookup_by_symbol* API.) */ |
477 | |
|
478 | 0 | s->sort_syms = 1; |
479 | 0 | if (fp->ctf_flags & LCTF_LINKING) |
480 | 0 | { |
481 | 0 | s->filter_syms = !(fp->ctf_link_flags & CTF_LINK_NO_FILTER_REPORTED_SYMS); |
482 | 0 | if (!s->filter_syms) |
483 | 0 | s->sort_syms = 0; |
484 | 0 | } |
485 | | |
486 | | /* Find the dict to which the linker has reported symbols, if any. */ |
487 | |
|
488 | 0 | if (s->filter_syms) |
489 | 0 | { |
490 | 0 | if (!fp->ctf_dynsyms && fp->ctf_parent && fp->ctf_parent->ctf_dynsyms) |
491 | 0 | s->symfp = fp->ctf_parent; |
492 | 0 | else |
493 | 0 | s->symfp = fp; |
494 | 0 | } |
495 | | |
496 | | /* If not filtering, keep all potential symbols in an unsorted, indexed |
497 | | dict. */ |
498 | 0 | if (!s->filter_syms) |
499 | 0 | s->symflags = CTF_SYMTYPETAB_FORCE_INDEXED; |
500 | 0 | else |
501 | 0 | hdr->cth_flags |= CTF_F_IDXSORTED; |
502 | |
|
503 | 0 | if (!ctf_assert (fp, (s->filter_syms && s->symfp) |
504 | 0 | || (!s->filter_syms && !s->symfp |
505 | 0 | && ((s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) != 0)))) |
506 | 0 | return -1; |
507 | | |
508 | | /* Work out the sizes of the object and function sections, and work out the |
509 | | number of pad (unassigned) symbols in each, and the overall size of the |
510 | | sections. */ |
511 | | |
512 | 0 | if (symtypetab_density (fp, s->symfp, fp->ctf_objthash, &nobjts, &s->maxobjt, |
513 | 0 | &objt_unpadsize, &objt_padsize, objtidx_size, |
514 | 0 | s->symflags) < 0) |
515 | 0 | return -1; /* errno is set for us. */ |
516 | | |
517 | 0 | ctf_dprintf ("Object symtypetab: %i objects, max %i, unpadded size %i, " |
518 | 0 | "%i bytes of pads, index size %i\n", (int) nobjts, |
519 | 0 | (int) s->maxobjt, (int) objt_unpadsize, (int) objt_padsize, |
520 | 0 | (int) *objtidx_size); |
521 | |
|
522 | 0 | if (symtypetab_density (fp, s->symfp, fp->ctf_funchash, &nfuncs, &s->maxfunc, |
523 | 0 | &func_unpadsize, &func_padsize, funcidx_size, |
524 | 0 | s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) |
525 | 0 | return -1; /* errno is set for us. */ |
526 | | |
527 | 0 | ctf_dprintf ("Function symtypetab: %i functions, max %i, unpadded size %i, " |
528 | 0 | "%i bytes of pads, index size %i\n", (int) nfuncs, |
529 | 0 | (int) s->maxfunc, (int) func_unpadsize, (int) func_padsize, |
530 | 0 | (int) *funcidx_size); |
531 | | |
532 | | /* It is worth indexing each section if it would save space to do so, due to |
533 | | reducing the number of pads sufficiently. A pad is the same size as a |
534 | | single index entry: but index sections compress relatively poorly compared |
535 | | to constant pads, so it takes a lot of contiguous padding to equal one |
536 | | index section entry. It would be nice to be able to *verify* whether we |
537 | | would save space after compression rather than guessing, but this seems |
538 | | difficult, since it would require complete reserialization. Regardless, if |
539 | | the linker has not reported any symbols (e.g. if this is not a final link |
540 | | but just an ld -r), we must emit things in indexed fashion just as the |
541 | | compiler does. */ |
542 | |
|
543 | 0 | *objt_size = objt_unpadsize; |
544 | 0 | if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) |
545 | 0 | && ((objt_padsize + objt_unpadsize) * CTF_INDEX_PAD_THRESHOLD |
546 | 0 | > objt_padsize)) |
547 | 0 | { |
548 | 0 | *objt_size += objt_padsize; |
549 | 0 | *objtidx_size = 0; |
550 | 0 | } |
551 | |
|
552 | 0 | *func_size = func_unpadsize; |
553 | 0 | if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) |
554 | 0 | && ((func_padsize + func_unpadsize) * CTF_INDEX_PAD_THRESHOLD |
555 | 0 | > func_padsize)) |
556 | 0 | { |
557 | 0 | *func_size += func_padsize; |
558 | 0 | *funcidx_size = 0; |
559 | 0 | } |
560 | | |
561 | | /* If we are filtering symbols out, those symbols that the linker has not |
562 | | reported have now been removed from the ctf_objthash and ctf_funchash. |
563 | | Delete entries from the variable section that duplicate newly-added |
564 | | symbols. There's no need to migrate new ones in: we do that (if necessary) |
565 | | in ctf_link_deduplicating_variables. */ |
566 | |
|
567 | 0 | if (s->filter_syms && s->symfp->ctf_dynsyms && |
568 | 0 | symtypetab_delete_nonstatics (fp, s->symfp) < 0) |
569 | 0 | return -1; |
570 | | |
571 | 0 | return 0; |
572 | 0 | } |
573 | | |
574 | | static int |
575 | | ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s, |
576 | | unsigned char **tptr, size_t objt_size, |
577 | | size_t func_size, size_t objtidx_size, |
578 | | size_t funcidx_size) |
579 | 0 | { |
580 | 0 | unsigned char *t = *tptr; |
581 | 0 | size_t nsymtypes = 0; |
582 | 0 | const char **sym_name_order = NULL; |
583 | 0 | int err; |
584 | | |
585 | | /* Sort the linker's symbols into name order if need be. */ |
586 | |
|
587 | 0 | if ((objtidx_size != 0) || (funcidx_size != 0)) |
588 | 0 | { |
589 | 0 | ctf_next_t *i = NULL; |
590 | 0 | void *symname; |
591 | 0 | const char **walk; |
592 | |
|
593 | 0 | if (s->filter_syms) |
594 | 0 | { |
595 | 0 | if (s->symfp->ctf_dynsyms) |
596 | 0 | nsymtypes = ctf_dynhash_elements (s->symfp->ctf_dynsyms); |
597 | 0 | else |
598 | 0 | nsymtypes = 0; |
599 | 0 | } |
600 | 0 | else |
601 | 0 | nsymtypes = ctf_dynhash_elements (fp->ctf_objthash) |
602 | 0 | + ctf_dynhash_elements (fp->ctf_funchash); |
603 | |
|
604 | 0 | if ((sym_name_order = calloc (nsymtypes, sizeof (const char *))) == NULL) |
605 | 0 | goto oom; |
606 | | |
607 | 0 | walk = sym_name_order; |
608 | |
|
609 | 0 | if (s->filter_syms) |
610 | 0 | { |
611 | 0 | if (s->symfp->ctf_dynsyms) |
612 | 0 | { |
613 | 0 | while ((err = ctf_dynhash_next_sorted (s->symfp->ctf_dynsyms, &i, |
614 | 0 | &symname, NULL, |
615 | 0 | ctf_dynhash_sort_by_name, |
616 | 0 | NULL)) == 0) |
617 | 0 | *walk++ = (const char *) symname; |
618 | 0 | if (err != ECTF_NEXT_END) |
619 | 0 | goto symerr; |
620 | 0 | } |
621 | 0 | } |
622 | 0 | else |
623 | 0 | { |
624 | 0 | ctf_hash_sort_f sort_fun = NULL; |
625 | | |
626 | | /* Since we partition the set of symbols back into objt and func, |
627 | | we can sort the two independently without harm. */ |
628 | 0 | if (s->sort_syms) |
629 | 0 | sort_fun = ctf_dynhash_sort_by_name; |
630 | |
|
631 | 0 | while ((err = ctf_dynhash_next_sorted (fp->ctf_objthash, &i, &symname, |
632 | 0 | NULL, sort_fun, NULL)) == 0) |
633 | 0 | *walk++ = (const char *) symname; |
634 | 0 | if (err != ECTF_NEXT_END) |
635 | 0 | goto symerr; |
636 | | |
637 | 0 | while ((err = ctf_dynhash_next_sorted (fp->ctf_funchash, &i, &symname, |
638 | 0 | NULL, sort_fun, NULL)) == 0) |
639 | 0 | *walk++ = (const char *) symname; |
640 | 0 | if (err != ECTF_NEXT_END) |
641 | 0 | goto symerr; |
642 | 0 | } |
643 | 0 | } |
644 | | |
645 | | /* Emit the object and function sections, and if necessary their indexes. |
646 | | Emission is done in symtab order if there is no index, and in index |
647 | | (name) order otherwise. */ |
648 | | |
649 | 0 | if ((objtidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx) |
650 | 0 | { |
651 | 0 | ctf_dprintf ("Emitting unindexed objt symtypetab\n"); |
652 | 0 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, |
653 | 0 | s->symfp->ctf_dynsymidx, NULL, |
654 | 0 | s->symfp->ctf_dynsymmax + 1, s->maxobjt, |
655 | 0 | objt_size, s->symflags | CTF_SYMTYPETAB_EMIT_PAD) < 0) |
656 | 0 | goto err; /* errno is set for us. */ |
657 | 0 | } |
658 | 0 | else |
659 | 0 | { |
660 | 0 | ctf_dprintf ("Emitting indexed objt symtypetab\n"); |
661 | 0 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, |
662 | 0 | sym_name_order, nsymtypes, s->maxobjt, |
663 | 0 | objt_size, s->symflags) < 0) |
664 | 0 | goto err; /* errno is set for us. */ |
665 | 0 | } |
666 | | |
667 | 0 | t += objt_size; |
668 | |
|
669 | 0 | if ((funcidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx) |
670 | 0 | { |
671 | 0 | ctf_dprintf ("Emitting unindexed func symtypetab\n"); |
672 | 0 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, |
673 | 0 | s->symfp->ctf_dynsymidx, NULL, |
674 | 0 | s->symfp->ctf_dynsymmax + 1, s->maxfunc, |
675 | 0 | func_size, s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION |
676 | 0 | | CTF_SYMTYPETAB_EMIT_PAD) < 0) |
677 | 0 | goto err; /* errno is set for us. */ |
678 | 0 | } |
679 | 0 | else |
680 | 0 | { |
681 | 0 | ctf_dprintf ("Emitting indexed func symtypetab\n"); |
682 | 0 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, sym_name_order, |
683 | 0 | nsymtypes, s->maxfunc, func_size, |
684 | 0 | s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) |
685 | 0 | goto err; /* errno is set for us. */ |
686 | 0 | } |
687 | | |
688 | 0 | t += func_size; |
689 | |
|
690 | 0 | if (objtidx_size > 0) |
691 | 0 | if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order, |
692 | 0 | nsymtypes, objtidx_size, s->symflags) < 0) |
693 | 0 | goto err; |
694 | | |
695 | 0 | t += objtidx_size; |
696 | |
|
697 | 0 | if (funcidx_size > 0) |
698 | 0 | if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order, |
699 | 0 | nsymtypes, funcidx_size, |
700 | 0 | s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) |
701 | 0 | goto err; |
702 | | |
703 | 0 | t += funcidx_size; |
704 | 0 | free (sym_name_order); |
705 | 0 | *tptr = t; |
706 | |
|
707 | 0 | return 0; |
708 | | |
709 | 0 | oom: |
710 | 0 | ctf_set_errno (fp, EAGAIN); |
711 | 0 | goto err; |
712 | 0 | symerr: |
713 | 0 | ctf_err_warn (fp, 0, err, _("error serializing symtypetabs")); |
714 | 0 | err: |
715 | 0 | free (sym_name_order); |
716 | 0 | return -1; |
717 | 0 | } |
718 | | |
719 | | /* Type section. */ |
720 | | |
721 | | /* Iterate through the static types and the dynamic type definition list and |
722 | | compute the size of the CTF type section. */ |
723 | | |
724 | | static size_t |
725 | | ctf_type_sect_size (ctf_dict_t *fp) |
726 | 0 | { |
727 | 0 | ctf_dtdef_t *dtd; |
728 | 0 | size_t type_size; |
729 | |
|
730 | 0 | for (type_size = 0, dtd = ctf_list_next (&fp->ctf_dtdefs); |
731 | 0 | dtd != NULL; dtd = ctf_list_next (dtd)) |
732 | 0 | { |
733 | 0 | uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); |
734 | 0 | uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info); |
735 | 0 | size_t type_ctt_size = dtd->dtd_data.ctt_size; |
736 | | |
737 | | /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t |
738 | | if possible. */ |
739 | |
|
740 | 0 | if (kind == CTF_K_STRUCT || kind == CTF_K_UNION) |
741 | 0 | { |
742 | 0 | size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data); |
743 | |
|
744 | 0 | if (lsize <= CTF_MAX_SIZE) |
745 | 0 | type_ctt_size = lsize; |
746 | 0 | } |
747 | |
|
748 | 0 | if (type_ctt_size != CTF_LSIZE_SENT) |
749 | 0 | type_size += sizeof (ctf_stype_t); |
750 | 0 | else |
751 | 0 | type_size += sizeof (ctf_type_t); |
752 | |
|
753 | 0 | switch (kind) |
754 | 0 | { |
755 | 0 | case CTF_K_INTEGER: |
756 | 0 | case CTF_K_FLOAT: |
757 | 0 | type_size += sizeof (uint32_t); |
758 | 0 | break; |
759 | 0 | case CTF_K_ARRAY: |
760 | 0 | type_size += sizeof (ctf_array_t); |
761 | 0 | break; |
762 | 0 | case CTF_K_SLICE: |
763 | 0 | type_size += sizeof (ctf_slice_t); |
764 | 0 | break; |
765 | 0 | case CTF_K_FUNCTION: |
766 | 0 | type_size += sizeof (uint32_t) * (vlen + (vlen & 1)); |
767 | 0 | break; |
768 | 0 | case CTF_K_STRUCT: |
769 | 0 | case CTF_K_UNION: |
770 | 0 | if (type_ctt_size < CTF_LSTRUCT_THRESH) |
771 | 0 | type_size += sizeof (ctf_member_t) * vlen; |
772 | 0 | else |
773 | 0 | type_size += sizeof (ctf_lmember_t) * vlen; |
774 | 0 | break; |
775 | 0 | case CTF_K_ENUM: |
776 | 0 | type_size += sizeof (ctf_enum_t) * vlen; |
777 | 0 | break; |
778 | 0 | } |
779 | 0 | } |
780 | | |
781 | 0 | return type_size + fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; |
782 | 0 | } |
783 | | |
784 | | /* Take a final lap through the dynamic type definition list and copy the |
785 | | appropriate type records to the output buffer, noting down the strings as |
786 | | we go. */ |
787 | | |
788 | | static void |
789 | | ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr) |
790 | 0 | { |
791 | 0 | unsigned char *t = *tptr; |
792 | 0 | ctf_dtdef_t *dtd; |
793 | |
|
794 | 0 | for (dtd = ctf_list_next (&fp->ctf_dtdefs); |
795 | 0 | dtd != NULL; dtd = ctf_list_next (dtd)) |
796 | 0 | { |
797 | 0 | uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); |
798 | 0 | uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info); |
799 | 0 | size_t type_ctt_size = dtd->dtd_data.ctt_size; |
800 | 0 | size_t len; |
801 | 0 | ctf_stype_t *copied; |
802 | 0 | const char *name; |
803 | 0 | size_t i; |
804 | | |
805 | | /* Shrink ctf_type_t-using types from a ctf_type_t to a ctf_stype_t |
806 | | if possible. */ |
807 | |
|
808 | 0 | if (kind == CTF_K_STRUCT || kind == CTF_K_UNION) |
809 | 0 | { |
810 | 0 | size_t lsize = CTF_TYPE_LSIZE (&dtd->dtd_data); |
811 | |
|
812 | 0 | if (lsize <= CTF_MAX_SIZE) |
813 | 0 | type_ctt_size = lsize; |
814 | 0 | } |
815 | |
|
816 | 0 | if (type_ctt_size != CTF_LSIZE_SENT) |
817 | 0 | len = sizeof (ctf_stype_t); |
818 | 0 | else |
819 | 0 | len = sizeof (ctf_type_t); |
820 | |
|
821 | 0 | memcpy (t, &dtd->dtd_data, len); |
822 | 0 | copied = (ctf_stype_t *) t; /* name is at the start: constant offset. */ |
823 | 0 | if (copied->ctt_name |
824 | 0 | && (name = ctf_strraw (fp, copied->ctt_name)) != NULL) |
825 | 0 | ctf_str_add_ref (fp, name, &copied->ctt_name); |
826 | 0 | copied->ctt_size = type_ctt_size; |
827 | 0 | t += len; |
828 | |
|
829 | 0 | switch (kind) |
830 | 0 | { |
831 | 0 | case CTF_K_INTEGER: |
832 | 0 | case CTF_K_FLOAT: |
833 | 0 | memcpy (t, dtd->dtd_vlen, sizeof (uint32_t)); |
834 | 0 | t += sizeof (uint32_t); |
835 | 0 | break; |
836 | | |
837 | 0 | case CTF_K_SLICE: |
838 | 0 | memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_slice)); |
839 | 0 | t += sizeof (struct ctf_slice); |
840 | 0 | break; |
841 | | |
842 | 0 | case CTF_K_ARRAY: |
843 | 0 | memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_array)); |
844 | 0 | t += sizeof (struct ctf_array); |
845 | 0 | break; |
846 | | |
847 | 0 | case CTF_K_FUNCTION: |
848 | | /* Functions with no args also have no vlen. */ |
849 | 0 | if (dtd->dtd_vlen) |
850 | 0 | memcpy (t, dtd->dtd_vlen, sizeof (uint32_t) * (vlen + (vlen & 1))); |
851 | 0 | t += sizeof (uint32_t) * (vlen + (vlen & 1)); |
852 | 0 | break; |
853 | | |
854 | | /* These need to be copied across element by element, depending on |
855 | | their ctt_size. */ |
856 | 0 | case CTF_K_STRUCT: |
857 | 0 | case CTF_K_UNION: |
858 | 0 | { |
859 | 0 | ctf_lmember_t *dtd_vlen = (ctf_lmember_t *) dtd->dtd_vlen; |
860 | 0 | ctf_lmember_t *t_lvlen = (ctf_lmember_t *) t; |
861 | 0 | ctf_member_t *t_vlen = (ctf_member_t *) t; |
862 | |
|
863 | 0 | for (i = 0; i < vlen; i++) |
864 | 0 | { |
865 | 0 | const char *name = ctf_strraw (fp, dtd_vlen[i].ctlm_name); |
866 | |
|
867 | 0 | ctf_str_add_ref (fp, name, &dtd_vlen[i].ctlm_name); |
868 | |
|
869 | 0 | if (type_ctt_size < CTF_LSTRUCT_THRESH) |
870 | 0 | { |
871 | 0 | t_vlen[i].ctm_name = dtd_vlen[i].ctlm_name; |
872 | 0 | t_vlen[i].ctm_type = dtd_vlen[i].ctlm_type; |
873 | 0 | t_vlen[i].ctm_offset = CTF_LMEM_OFFSET (&dtd_vlen[i]); |
874 | 0 | ctf_str_add_ref (fp, name, &t_vlen[i].ctm_name); |
875 | 0 | } |
876 | 0 | else |
877 | 0 | { |
878 | 0 | t_lvlen[i] = dtd_vlen[i]; |
879 | 0 | ctf_str_add_ref (fp, name, &t_lvlen[i].ctlm_name); |
880 | 0 | } |
881 | 0 | } |
882 | 0 | } |
883 | |
|
884 | 0 | if (type_ctt_size < CTF_LSTRUCT_THRESH) |
885 | 0 | t += sizeof (ctf_member_t) * vlen; |
886 | 0 | else |
887 | 0 | t += sizeof (ctf_lmember_t) * vlen; |
888 | 0 | break; |
889 | | |
890 | 0 | case CTF_K_ENUM: |
891 | 0 | { |
892 | 0 | ctf_enum_t *dtd_vlen = (struct ctf_enum *) dtd->dtd_vlen; |
893 | 0 | ctf_enum_t *t_vlen = (struct ctf_enum *) t; |
894 | |
|
895 | 0 | memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_enum) * vlen); |
896 | 0 | for (i = 0; i < vlen; i++) |
897 | 0 | { |
898 | 0 | const char *name = ctf_strraw (fp, dtd_vlen[i].cte_name); |
899 | |
|
900 | 0 | ctf_str_add_ref (fp, name, &t_vlen[i].cte_name); |
901 | 0 | ctf_str_add_ref (fp, name, &dtd_vlen[i].cte_name); |
902 | 0 | } |
903 | 0 | t += sizeof (struct ctf_enum) * vlen; |
904 | |
|
905 | 0 | break; |
906 | 0 | } |
907 | 0 | } |
908 | 0 | } |
909 | | |
910 | 0 | *tptr = t; |
911 | 0 | } |
912 | | |
913 | | /* Variable section. */ |
914 | | |
915 | | /* Sort a newly-constructed static variable array. */ |
916 | | |
917 | | typedef struct ctf_sort_var_arg_cb |
918 | | { |
919 | | ctf_dict_t *fp; |
920 | | ctf_strs_t *strtab; |
921 | | } ctf_sort_var_arg_cb_t; |
922 | | |
923 | | static int |
924 | | ctf_sort_var (const void *one_, const void *two_, void *arg_) |
925 | 0 | { |
926 | 0 | const ctf_varent_t *one = one_; |
927 | 0 | const ctf_varent_t *two = two_; |
928 | 0 | ctf_sort_var_arg_cb_t *arg = arg_; |
929 | |
|
930 | 0 | return (strcmp (ctf_strraw_explicit (arg->fp, one->ctv_name, arg->strtab), |
931 | 0 | ctf_strraw_explicit (arg->fp, two->ctv_name, arg->strtab))); |
932 | 0 | } |
933 | | |
934 | | /* Overall serialization. */ |
935 | | |
936 | | /* Emit a new CTF dict which is a serialized copy of this one: also reify |
937 | | the string table and update all offsets in the current dict suitably. |
938 | | (This simplifies ctf-string.c a little, at the cost of storing a second |
939 | | copy of the strtab if this dict was originally read in via ctf_open.) |
940 | | |
941 | | Other aspects of the existing dict are unchanged, although some |
942 | | static entries may be duplicated in the dynamic state (which should |
943 | | have no effect on visible operation). */ |
944 | | |
945 | | static unsigned char * |
946 | | ctf_serialize (ctf_dict_t *fp, size_t *bufsiz) |
947 | 0 | { |
948 | 0 | ctf_header_t hdr, *hdrp; |
949 | 0 | ctf_dvdef_t *dvd; |
950 | 0 | ctf_varent_t *dvarents; |
951 | 0 | const ctf_strs_writable_t *strtab; |
952 | 0 | int sym_functions = 0; |
953 | |
|
954 | 0 | unsigned char *t; |
955 | 0 | unsigned long i; |
956 | 0 | size_t buf_size, type_size, objt_size, func_size; |
957 | 0 | size_t funcidx_size, objtidx_size; |
958 | 0 | size_t nvars; |
959 | 0 | unsigned char *buf = NULL, *newbuf; |
960 | |
|
961 | 0 | emit_symtypetab_state_t symstate; |
962 | 0 | memset (&symstate, 0, sizeof (emit_symtypetab_state_t)); |
963 | | |
964 | | /* Fill in an initial CTF header. We will leave the label, object, |
965 | | and function sections empty and only output a header, type section, |
966 | | and string table. The type section begins at a 4-byte aligned |
967 | | boundary past the CTF header itself (at relative offset zero). The flag |
968 | | indicating a new-style function info section (an array of CTF_K_FUNCTION |
969 | | type IDs in the types section) is flipped on. */ |
970 | |
|
971 | 0 | memset (&hdr, 0, sizeof (hdr)); |
972 | 0 | hdr.cth_magic = CTF_MAGIC; |
973 | 0 | hdr.cth_version = CTF_VERSION; |
974 | | |
975 | | /* This is a new-format func info section, and the symtab and strtab come out |
976 | | of the dynsym and dynstr these days. */ |
977 | 0 | hdr.cth_flags = (CTF_F_NEWFUNCINFO | CTF_F_DYNSTR); |
978 | | |
979 | | /* Propagate all symbols in the symtypetabs into the dynamic state, so that |
980 | | we can put them back in the right order. Symbols already in the dynamic |
981 | | state, likely due to repeated serialization, are left unchanged. */ |
982 | 0 | do |
983 | 0 | { |
984 | 0 | ctf_next_t *it = NULL; |
985 | 0 | const char *sym_name; |
986 | 0 | ctf_id_t sym; |
987 | |
|
988 | 0 | while ((sym = ctf_symbol_next_static (fp, &it, &sym_name, |
989 | 0 | sym_functions)) != CTF_ERR) |
990 | 0 | if ((ctf_add_funcobjt_sym_forced (fp, sym_functions, sym_name, sym)) < 0) |
991 | 0 | if (ctf_errno (fp) != ECTF_DUPLICATE) |
992 | 0 | return NULL; /* errno is set for us. */ |
993 | | |
994 | 0 | if (ctf_errno (fp) != ECTF_NEXT_END) |
995 | 0 | return NULL; /* errno is set for us. */ |
996 | 0 | } while (sym_functions++ < 1); |
997 | | |
998 | | /* Figure out how big the symtypetabs are now. */ |
999 | | |
1000 | 0 | if (ctf_symtypetab_sect_sizes (fp, &symstate, &hdr, &objt_size, &func_size, |
1001 | 0 | &objtidx_size, &funcidx_size) < 0) |
1002 | 0 | return NULL; /* errno is set for us. */ |
1003 | | |
1004 | | /* Propagate all vars into the dynamic state, so we can put them back later. |
1005 | | Variables already in the dynamic state, likely due to repeated |
1006 | | serialization, are left unchanged. */ |
1007 | | |
1008 | 0 | for (i = 0; i < fp->ctf_nvars; i++) |
1009 | 0 | { |
1010 | 0 | const char *name = ctf_strptr (fp, fp->ctf_vars[i].ctv_name); |
1011 | |
|
1012 | 0 | if (name != NULL && !ctf_dvd_lookup (fp, name)) |
1013 | 0 | if (ctf_add_variable_forced (fp, name, fp->ctf_vars[i].ctv_type) < 0) |
1014 | 0 | return NULL; /* errno is set for us. */ |
1015 | 0 | } |
1016 | | |
1017 | 0 | for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); |
1018 | 0 | dvd != NULL; dvd = ctf_list_next (dvd), nvars++); |
1019 | |
|
1020 | 0 | type_size = ctf_type_sect_size (fp); |
1021 | | |
1022 | | /* Compute the size of the CTF buffer we need, sans only the string table, |
1023 | | then allocate a new buffer and memcpy the finished header to the start of |
1024 | | the buffer. (We will adjust this later with strtab length info.) */ |
1025 | |
|
1026 | 0 | hdr.cth_lbloff = hdr.cth_objtoff = 0; |
1027 | 0 | hdr.cth_funcoff = hdr.cth_objtoff + objt_size; |
1028 | 0 | hdr.cth_objtidxoff = hdr.cth_funcoff + func_size; |
1029 | 0 | hdr.cth_funcidxoff = hdr.cth_objtidxoff + objtidx_size; |
1030 | 0 | hdr.cth_varoff = hdr.cth_funcidxoff + funcidx_size; |
1031 | 0 | hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t)); |
1032 | 0 | hdr.cth_stroff = hdr.cth_typeoff + type_size; |
1033 | 0 | hdr.cth_strlen = 0; |
1034 | |
|
1035 | 0 | buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; |
1036 | |
|
1037 | 0 | if ((buf = malloc (buf_size)) == NULL) |
1038 | 0 | { |
1039 | 0 | ctf_set_errno (fp, EAGAIN); |
1040 | 0 | return NULL; |
1041 | 0 | } |
1042 | | |
1043 | 0 | memcpy (buf, &hdr, sizeof (ctf_header_t)); |
1044 | 0 | t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff; |
1045 | |
|
1046 | 0 | hdrp = (ctf_header_t *) buf; |
1047 | 0 | if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL)) |
1048 | 0 | ctf_str_add_ref (fp, fp->ctf_parname, &hdrp->cth_parname); |
1049 | 0 | if (fp->ctf_cuname != NULL) |
1050 | 0 | ctf_str_add_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname); |
1051 | |
|
1052 | 0 | if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size, |
1053 | 0 | objtidx_size, funcidx_size) < 0) |
1054 | 0 | goto err; |
1055 | | |
1056 | 0 | assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff); |
1057 | | |
1058 | | /* Work over the variable list, translating everything into ctf_varent_t's and |
1059 | | prepping the string table. */ |
1060 | | |
1061 | 0 | dvarents = (ctf_varent_t *) t; |
1062 | 0 | for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; |
1063 | 0 | dvd = ctf_list_next (dvd), i++) |
1064 | 0 | { |
1065 | 0 | ctf_varent_t *var = &dvarents[i]; |
1066 | |
|
1067 | 0 | ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name); |
1068 | 0 | var->ctv_type = (uint32_t) dvd->dvd_type; |
1069 | 0 | } |
1070 | 0 | assert (i == nvars); |
1071 | | |
1072 | 0 | t += sizeof (ctf_varent_t) * nvars; |
1073 | |
|
1074 | 0 | assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff); |
1075 | | |
1076 | | /* Copy in existing static types, then emit new dynamic types. */ |
1077 | | |
1078 | 0 | memcpy (t, fp->ctf_buf + fp->ctf_header->cth_typeoff, |
1079 | 0 | fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff); |
1080 | 0 | t += fp->ctf_header->cth_stroff - fp->ctf_header->cth_typeoff; |
1081 | 0 | ctf_emit_type_sect (fp, &t); |
1082 | |
|
1083 | 0 | assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff); |
1084 | | |
1085 | | /* Construct the final string table and fill out all the string refs with the |
1086 | | final offsets. */ |
1087 | | |
1088 | 0 | strtab = ctf_str_write_strtab (fp); |
1089 | |
|
1090 | 0 | if (strtab == NULL) |
1091 | 0 | goto oom; |
1092 | | |
1093 | | /* Now the string table is constructed, we can sort the buffer of |
1094 | | ctf_varent_t's. */ |
1095 | 0 | ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) strtab }; |
1096 | 0 | ctf_qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var, |
1097 | 0 | &sort_var_arg); |
1098 | |
|
1099 | 0 | if ((newbuf = realloc (buf, buf_size + strtab->cts_len)) == NULL) |
1100 | 0 | goto oom; |
1101 | | |
1102 | 0 | buf = newbuf; |
1103 | 0 | memcpy (buf + buf_size, strtab->cts_strs, strtab->cts_len); |
1104 | 0 | hdrp = (ctf_header_t *) buf; |
1105 | 0 | hdrp->cth_strlen = strtab->cts_len; |
1106 | 0 | buf_size += hdrp->cth_strlen; |
1107 | 0 | *bufsiz = buf_size; |
1108 | |
|
1109 | 0 | return buf; |
1110 | | |
1111 | 0 | oom: |
1112 | 0 | ctf_set_errno (fp, EAGAIN); |
1113 | 0 | err: |
1114 | 0 | free (buf); |
1115 | 0 | return NULL; /* errno is set for us. */ |
1116 | 0 | } |
1117 | | |
1118 | | /* File writing. */ |
1119 | | |
1120 | | /* Write the compressed CTF data stream to the specified gzFile descriptor. The |
1121 | | whole stream is compressed, and cannot be read by CTF opening functions in |
1122 | | this library until it is decompressed. (The functions below this one leave |
1123 | | the header uncompressed, and the CTF opening functions work on them without |
1124 | | manual decompression.) |
1125 | | |
1126 | | No support for (testing-only) endian-flipping. */ |
1127 | | int |
1128 | | ctf_gzwrite (ctf_dict_t *fp, gzFile fd) |
1129 | 0 | { |
1130 | 0 | unsigned char *buf; |
1131 | 0 | unsigned char *p; |
1132 | 0 | size_t bufsiz; |
1133 | 0 | size_t len, written = 0; |
1134 | |
|
1135 | 0 | if ((buf = ctf_serialize (fp, &bufsiz)) == NULL) |
1136 | 0 | return -1; /* errno is set for us. */ |
1137 | | |
1138 | 0 | p = buf; |
1139 | 0 | while (written < bufsiz) |
1140 | 0 | { |
1141 | 0 | if ((len = gzwrite (fd, p, bufsiz - written)) <= 0) |
1142 | 0 | { |
1143 | 0 | free (buf); |
1144 | 0 | return (ctf_set_errno (fp, errno)); |
1145 | 0 | } |
1146 | 0 | written += len; |
1147 | 0 | p += len; |
1148 | 0 | } |
1149 | | |
1150 | 0 | free (buf); |
1151 | 0 | return 0; |
1152 | 0 | } |
1153 | | |
1154 | | /* Optionally compress the specified CTF data stream and return it as a new |
1155 | | dynamically-allocated string. Possibly write it with reversed |
1156 | | endianness. */ |
1157 | | unsigned char * |
1158 | | ctf_write_mem (ctf_dict_t *fp, size_t *size, size_t threshold) |
1159 | 0 | { |
1160 | 0 | unsigned char *rawbuf; |
1161 | 0 | unsigned char *buf = NULL; |
1162 | 0 | unsigned char *bp; |
1163 | 0 | ctf_header_t *rawhp, *hp; |
1164 | 0 | unsigned char *src; |
1165 | 0 | size_t rawbufsiz; |
1166 | 0 | size_t alloc_len = 0; |
1167 | 0 | int uncompressed = 0; |
1168 | 0 | int flip_endian; |
1169 | 0 | int rc; |
1170 | |
|
1171 | 0 | flip_endian = getenv ("LIBCTF_WRITE_FOREIGN_ENDIAN") != NULL; |
1172 | |
|
1173 | 0 | if ((rawbuf = ctf_serialize (fp, &rawbufsiz)) == NULL) |
1174 | 0 | return NULL; /* errno is set for us. */ |
1175 | | |
1176 | 0 | if (!ctf_assert (fp, rawbufsiz >= sizeof (ctf_header_t))) |
1177 | 0 | goto err; |
1178 | | |
1179 | 0 | if (rawbufsiz >= threshold) |
1180 | 0 | alloc_len = compressBound (rawbufsiz - sizeof (ctf_header_t)) |
1181 | 0 | + sizeof (ctf_header_t); |
1182 | | |
1183 | | /* Trivial operation if the buffer is too small to bother compressing, and |
1184 | | we're not doing a forced write-time flip. */ |
1185 | |
|
1186 | 0 | if (rawbufsiz < threshold) |
1187 | 0 | { |
1188 | 0 | alloc_len = rawbufsiz; |
1189 | 0 | uncompressed = 1; |
1190 | 0 | } |
1191 | |
|
1192 | 0 | if (!flip_endian && uncompressed) |
1193 | 0 | { |
1194 | 0 | *size = rawbufsiz; |
1195 | 0 | return rawbuf; |
1196 | 0 | } |
1197 | | |
1198 | 0 | if ((buf = malloc (alloc_len)) == NULL) |
1199 | 0 | { |
1200 | 0 | ctf_set_errno (fp, ENOMEM); |
1201 | 0 | ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"), |
1202 | 0 | (unsigned long) (alloc_len)); |
1203 | 0 | goto err; |
1204 | 0 | } |
1205 | | |
1206 | 0 | rawhp = (ctf_header_t *) rawbuf; |
1207 | 0 | hp = (ctf_header_t *) buf; |
1208 | 0 | memcpy (hp, rawbuf, sizeof (ctf_header_t)); |
1209 | 0 | bp = buf + sizeof (ctf_header_t); |
1210 | 0 | *size = sizeof (ctf_header_t); |
1211 | |
|
1212 | 0 | if (!uncompressed) |
1213 | 0 | hp->cth_flags |= CTF_F_COMPRESS; |
1214 | |
|
1215 | 0 | src = rawbuf + sizeof (ctf_header_t); |
1216 | |
|
1217 | 0 | if (flip_endian) |
1218 | 0 | { |
1219 | 0 | ctf_flip_header (hp); |
1220 | 0 | if (ctf_flip (fp, rawhp, src, 1) < 0) |
1221 | 0 | goto err; /* errno is set for us. */ |
1222 | 0 | } |
1223 | | |
1224 | 0 | if (!uncompressed) |
1225 | 0 | { |
1226 | 0 | size_t compress_len = alloc_len - sizeof (ctf_header_t); |
1227 | |
|
1228 | 0 | if ((rc = compress (bp, (uLongf *) &compress_len, |
1229 | 0 | src, rawbufsiz - sizeof (ctf_header_t))) != Z_OK) |
1230 | 0 | { |
1231 | 0 | ctf_set_errno (fp, ECTF_COMPRESS); |
1232 | 0 | ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc)); |
1233 | 0 | goto err; |
1234 | 0 | } |
1235 | 0 | *size += compress_len; |
1236 | 0 | } |
1237 | 0 | else |
1238 | 0 | { |
1239 | 0 | memcpy (bp, src, rawbufsiz - sizeof (ctf_header_t)); |
1240 | 0 | *size += rawbufsiz - sizeof (ctf_header_t); |
1241 | 0 | } |
1242 | | |
1243 | 0 | free (rawbuf); |
1244 | 0 | return buf; |
1245 | 0 | err: |
1246 | 0 | free (buf); |
1247 | 0 | free (rawbuf); |
1248 | 0 | return NULL; |
1249 | 0 | } |
1250 | | |
1251 | | /* Write the compressed CTF data stream to the specified file descriptor, |
1252 | | possibly compressed. Internal only (for now). */ |
1253 | | int |
1254 | | ctf_write_thresholded (ctf_dict_t *fp, int fd, size_t threshold) |
1255 | 0 | { |
1256 | 0 | unsigned char *buf; |
1257 | 0 | unsigned char *bp; |
1258 | 0 | size_t tmp; |
1259 | 0 | ssize_t buf_len; |
1260 | 0 | ssize_t len; |
1261 | 0 | int err = 0; |
1262 | |
|
1263 | 0 | if ((buf = ctf_write_mem (fp, &tmp, threshold)) == NULL) |
1264 | 0 | return -1; /* errno is set for us. */ |
1265 | | |
1266 | 0 | buf_len = tmp; |
1267 | 0 | bp = buf; |
1268 | |
|
1269 | 0 | while (buf_len > 0) |
1270 | 0 | { |
1271 | 0 | if ((len = write (fd, bp, buf_len)) < 0) |
1272 | 0 | { |
1273 | 0 | err = ctf_set_errno (fp, errno); |
1274 | 0 | ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing")); |
1275 | 0 | goto ret; |
1276 | 0 | } |
1277 | 0 | buf_len -= len; |
1278 | 0 | bp += len; |
1279 | 0 | } |
1280 | | |
1281 | 0 | ret: |
1282 | 0 | free (buf); |
1283 | 0 | return err; |
1284 | 0 | } |
1285 | | |
1286 | | /* Compress the specified CTF data stream and write it to the specified file |
1287 | | descriptor. */ |
1288 | | int |
1289 | | ctf_compress_write (ctf_dict_t *fp, int fd) |
1290 | 0 | { |
1291 | 0 | return ctf_write_thresholded (fp, fd, 0); |
1292 | 0 | } |
1293 | | |
1294 | | /* Write the uncompressed CTF data stream to the specified file descriptor. */ |
1295 | | int |
1296 | | ctf_write (ctf_dict_t *fp, int fd) |
1297 | 0 | { |
1298 | 0 | return ctf_write_thresholded (fp, fd, (size_t) -1); |
1299 | 0 | } |