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