Commit | Line | Data |
---|---|---|
bf4c3185 NA |
1 | /* CTF dict creation. |
2 | Copyright (C) 2019-2021 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 | ||
b9a96431 | 29 | /* Symtypetab sections. */ |
bf4c3185 | 30 | |
b9a96431 NA |
31 | /* Symtypetab emission flags. */ |
32 | ||
33 | #define CTF_SYMTYPETAB_EMIT_FUNCTION 0x1 | |
34 | #define CTF_SYMTYPETAB_EMIT_PAD 0x2 | |
35 | #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 | |
bf4c3185 | 41 | { |
b9a96431 NA |
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; | |
bf4c3185 | 46 | |
b9a96431 NA |
47 | /* True if symbols are being sorted. */ |
48 | int sort_syms; | |
bf4c3185 | 49 | |
b9a96431 NA |
50 | /* Flags for symtypetab emission. */ |
51 | int symflags; | |
bf4c3185 | 52 | |
b9a96431 NA |
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; | |
bf4c3185 NA |
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 | { | |
69 | /* Never skip symbols whose name is not yet known. */ | |
70 | if (sym->st_nameidx_set) | |
71 | return 0; | |
72 | ||
73 | return (sym->st_name == NULL || sym->st_name[0] == 0 | |
74 | || sym->st_shndx == SHN_UNDEF | |
75 | || strcmp (sym->st_name, "_START_") == 0 | |
76 | || strcmp (sym->st_name, "_END_") == 0 | |
77 | || (sym->st_type == STT_OBJECT && sym->st_shndx == SHN_EXTABS | |
78 | && sym->st_value == 0)); | |
79 | } | |
80 | ||
bf4c3185 NA |
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 | { | |
97 | ctf_next_t *i = NULL; | |
98 | const void *name; | |
99 | const void *ctf_sym; | |
100 | ctf_dynhash_t *linker_known = NULL; | |
101 | int err; | |
102 | int beyond_max = 0; | |
103 | ||
104 | *count = 0; | |
105 | *max = 0; | |
106 | *unpadsize = 0; | |
107 | *idxsize = 0; | |
108 | *padsize = 0; | |
109 | ||
110 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) | |
111 | { | |
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 | if (!symfp->ctf_dynsyms) | |
122 | return 0; | |
123 | ||
124 | if ((linker_known = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, | |
125 | NULL, NULL)) == NULL) | |
126 | return (ctf_set_errno (fp, ENOMEM)); | |
127 | ||
128 | while ((err = ctf_dynhash_cnext (symfp->ctf_dynsyms, &i, | |
129 | &name, &ctf_sym)) == 0) | |
130 | { | |
131 | ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym; | |
132 | ||
133 | if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
134 | && sym->st_type != STT_FUNC) | |
135 | || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
136 | && sym->st_type != STT_OBJECT)) | |
137 | continue; | |
138 | ||
139 | if (ctf_symtab_skippable (sym)) | |
140 | continue; | |
141 | ||
142 | /* This should only be true briefly before all the names are | |
143 | finalized, long before we get this far. */ | |
144 | if (!ctf_assert (fp, !sym->st_nameidx_set)) | |
145 | return -1; /* errno is set for us. */ | |
146 | ||
147 | if (ctf_dynhash_cinsert (linker_known, name, ctf_sym) < 0) | |
148 | { | |
149 | ctf_dynhash_destroy (linker_known); | |
150 | return (ctf_set_errno (fp, ENOMEM)); | |
151 | } | |
152 | } | |
153 | if (err != ECTF_NEXT_END) | |
154 | { | |
155 | ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols during " | |
156 | "serialization")); | |
157 | ctf_dynhash_destroy (linker_known); | |
158 | return (ctf_set_errno (fp, err)); | |
159 | } | |
160 | } | |
161 | ||
162 | while ((err = ctf_dynhash_cnext (symhash, &i, &name, NULL)) == 0) | |
163 | { | |
164 | ctf_link_sym_t *sym; | |
165 | ||
166 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) | |
167 | { | |
168 | /* Linker did not report symbol in symtab. Remove it from the | |
169 | set of known data symbols and continue. */ | |
170 | if ((sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, name)) == NULL) | |
171 | { | |
172 | ctf_dynhash_remove (symhash, name); | |
173 | continue; | |
174 | } | |
175 | ||
176 | /* We don't remove skippable symbols from the symhash because we don't | |
177 | want them to be migrated into variables. */ | |
178 | if (ctf_symtab_skippable (sym)) | |
179 | continue; | |
180 | ||
181 | if ((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
182 | && sym->st_type != STT_FUNC) | |
183 | { | |
184 | ctf_err_warn (fp, 1, 0, _("symbol %s (%x) added to CTF as a " | |
185 | "function but is of type %x. " | |
186 | "The symbol type lookup tables " | |
187 | "are probably corrupted"), | |
188 | sym->st_name, sym->st_symidx, sym->st_type); | |
189 | ctf_dynhash_remove (symhash, name); | |
190 | continue; | |
191 | } | |
192 | else if (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
193 | && sym->st_type != STT_OBJECT) | |
194 | { | |
195 | ctf_err_warn (fp, 1, 0, _("symbol %s (%x) added to CTF as a " | |
196 | "data object but is of type %x. " | |
197 | "The symbol type lookup tables " | |
198 | "are probably corrupted"), | |
199 | sym->st_name, sym->st_symidx, sym->st_type); | |
200 | ctf_dynhash_remove (symhash, name); | |
201 | continue; | |
202 | } | |
203 | ||
204 | ctf_dynhash_remove (linker_known, name); | |
205 | } | |
206 | *unpadsize += sizeof (uint32_t); | |
207 | (*count)++; | |
208 | ||
209 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) | |
210 | { | |
211 | if (*max < sym->st_symidx) | |
212 | *max = sym->st_symidx; | |
213 | } | |
214 | else | |
215 | (*max)++; | |
216 | } | |
217 | if (err != ECTF_NEXT_END) | |
218 | { | |
219 | ctf_err_warn (fp, 0, err, _("iterating over CTF symtypetab during " | |
220 | "serialization")); | |
221 | ctf_dynhash_destroy (linker_known); | |
222 | return (ctf_set_errno (fp, err)); | |
223 | } | |
224 | ||
225 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) | |
226 | { | |
227 | while ((err = ctf_dynhash_cnext (linker_known, &i, NULL, &ctf_sym)) == 0) | |
228 | { | |
229 | ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym; | |
230 | ||
231 | if (sym->st_symidx > *max) | |
232 | beyond_max++; | |
233 | } | |
234 | if (err != ECTF_NEXT_END) | |
235 | { | |
236 | ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols " | |
237 | "during CTF serialization")); | |
238 | ctf_dynhash_destroy (linker_known); | |
239 | return (ctf_set_errno (fp, err)); | |
240 | } | |
241 | } | |
242 | ||
243 | *idxsize = *count * sizeof (uint32_t); | |
244 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) | |
245 | *padsize = (ctf_dynhash_elements (linker_known) - beyond_max) * sizeof (uint32_t); | |
246 | ||
247 | ctf_dynhash_destroy (linker_known); | |
248 | return 0; | |
249 | } | |
250 | ||
251 | /* Emit an objt or func symtypetab into DP in a particular order defined by an | |
252 | array of ctf_link_sym_t or symbol names passed in. The index has NIDX | |
253 | elements in it: unindexed output would terminate at symbol OUTMAX and is in | |
254 | any case no larger than SIZE bytes. Some index elements are expected to be | |
255 | skipped: see symtypetab_density. The linker-reported set of symbols (if any) | |
256 | is found in SYMFP. */ | |
257 | static int | |
258 | emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp, | |
259 | ctf_link_sym_t **idx, const char **nameidx, uint32_t nidx, | |
260 | uint32_t outmax, int size, int flags) | |
261 | { | |
262 | uint32_t i; | |
263 | uint32_t *dpp = dp; | |
264 | ctf_dynhash_t *symhash; | |
265 | ||
266 | ctf_dprintf ("Emitting table of size %i, outmax %u, %u symtypetab entries, " | |
267 | "flags %i\n", size, outmax, nidx, flags); | |
268 | ||
269 | /* Empty table? Nothing to do. */ | |
270 | if (size == 0) | |
271 | return 0; | |
272 | ||
273 | if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
274 | symhash = fp->ctf_funchash; | |
275 | else | |
276 | symhash = fp->ctf_objthash; | |
277 | ||
278 | for (i = 0; i < nidx; i++) | |
279 | { | |
280 | const char *sym_name; | |
281 | void *type; | |
282 | ||
283 | /* If we have a linker-reported set of symbols, we may be given that set | |
284 | to work from, or a set of symbol names. In both cases we want to look | |
285 | at the corresponding linker-reported symbol (if any). */ | |
286 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) | |
287 | { | |
288 | ctf_link_sym_t *this_link_sym; | |
289 | ||
290 | if (idx) | |
291 | this_link_sym = idx[i]; | |
292 | else | |
293 | this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, nameidx[i]); | |
294 | ||
295 | /* Unreported symbol number. No pad, no nothing. */ | |
296 | if (!this_link_sym) | |
297 | continue; | |
298 | ||
299 | /* Symbol of the wrong type, or skippable? This symbol is not in this | |
300 | table. */ | |
301 | if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
302 | && this_link_sym->st_type != STT_FUNC) | |
303 | || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
304 | && this_link_sym->st_type != STT_OBJECT)) | |
305 | continue; | |
306 | ||
307 | if (ctf_symtab_skippable (this_link_sym)) | |
308 | continue; | |
309 | ||
310 | sym_name = this_link_sym->st_name; | |
311 | ||
312 | /* Linker reports symbol of a different type to the symbol we actually | |
313 | added? Skip the symbol. No pad, since the symbol doesn't actually | |
314 | belong in this table at all. (Warned about in | |
315 | symtypetab_density.) */ | |
316 | if ((this_link_sym->st_type == STT_FUNC) | |
317 | && (ctf_dynhash_lookup (fp->ctf_objthash, sym_name))) | |
318 | continue; | |
319 | ||
320 | if ((this_link_sym->st_type == STT_OBJECT) | |
321 | && (ctf_dynhash_lookup (fp->ctf_funchash, sym_name))) | |
322 | continue; | |
323 | } | |
324 | else | |
325 | sym_name = nameidx[i]; | |
326 | ||
327 | /* Symbol in index but no type set? Silently skip and (optionally) | |
328 | pad. (In force-indexed mode, this is also where we track symbols of | |
329 | the wrong type for this round of insertion.) */ | |
330 | if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL) | |
331 | { | |
332 | if (flags & CTF_SYMTYPETAB_EMIT_PAD) | |
333 | *dpp++ = 0; | |
334 | continue; | |
335 | } | |
336 | ||
337 | if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) < size)) | |
338 | return -1; /* errno is set for us. */ | |
339 | ||
340 | *dpp++ = (ctf_id_t) (uintptr_t) type; | |
341 | ||
342 | /* When emitting unindexed output, all later symbols are pads: stop | |
343 | early. */ | |
344 | if ((flags & CTF_SYMTYPETAB_EMIT_PAD) && idx[i]->st_symidx == outmax) | |
345 | break; | |
346 | } | |
347 | ||
348 | return 0; | |
349 | } | |
350 | ||
351 | /* Emit an objt or func symtypetab index into DP in a paticular order defined by | |
352 | an array of symbol names passed in. Stop at NIDX. The linker-reported set | |
353 | of symbols (if any) is found in SYMFP. */ | |
354 | static int | |
355 | emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp, | |
356 | const char **idx, uint32_t nidx, int size, int flags) | |
357 | { | |
358 | uint32_t i; | |
359 | uint32_t *dpp = dp; | |
360 | ctf_dynhash_t *symhash; | |
361 | ||
362 | ctf_dprintf ("Emitting index of size %i, %u entries reported by linker, " | |
363 | "flags %i\n", size, nidx, flags); | |
364 | ||
365 | /* Empty table? Nothing to do. */ | |
366 | if (size == 0) | |
367 | return 0; | |
368 | ||
369 | if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
370 | symhash = fp->ctf_funchash; | |
371 | else | |
372 | symhash = fp->ctf_objthash; | |
373 | ||
374 | /* Indexes should always be unpadded. */ | |
375 | if (!ctf_assert (fp, !(flags & CTF_SYMTYPETAB_EMIT_PAD))) | |
376 | return -1; /* errno is set for us. */ | |
377 | ||
378 | for (i = 0; i < nidx; i++) | |
379 | { | |
380 | const char *sym_name; | |
381 | void *type; | |
382 | ||
383 | if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED)) | |
384 | { | |
385 | ctf_link_sym_t *this_link_sym; | |
386 | ||
387 | this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, idx[i]); | |
388 | ||
389 | /* This is an index: unreported symbols should never appear in it. */ | |
390 | if (!ctf_assert (fp, this_link_sym != NULL)) | |
391 | return -1; /* errno is set for us. */ | |
392 | ||
393 | /* Symbol of the wrong type, or skippable? This symbol is not in this | |
394 | table. */ | |
395 | if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
396 | && this_link_sym->st_type != STT_FUNC) | |
397 | || (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION) | |
398 | && this_link_sym->st_type != STT_OBJECT)) | |
399 | continue; | |
400 | ||
401 | if (ctf_symtab_skippable (this_link_sym)) | |
402 | continue; | |
403 | ||
404 | sym_name = this_link_sym->st_name; | |
405 | ||
406 | /* Linker reports symbol of a different type to the symbol we actually | |
407 | added? Skip the symbol. */ | |
408 | if ((this_link_sym->st_type == STT_FUNC) | |
409 | && (ctf_dynhash_lookup (fp->ctf_objthash, sym_name))) | |
410 | continue; | |
411 | ||
412 | if ((this_link_sym->st_type == STT_OBJECT) | |
413 | && (ctf_dynhash_lookup (fp->ctf_funchash, sym_name))) | |
414 | continue; | |
415 | } | |
416 | else | |
417 | sym_name = idx[i]; | |
418 | ||
419 | /* Symbol in index and reported by linker, but no type set? Silently skip | |
420 | and (optionally) pad. (In force-indexed mode, this is also where we | |
421 | track symbols of the wrong type for this round of insertion.) */ | |
422 | if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL) | |
423 | continue; | |
424 | ||
425 | ctf_str_add_ref (fp, sym_name, dpp++); | |
426 | ||
427 | if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) <= size)) | |
428 | return -1; /* errno is set for us. */ | |
429 | } | |
430 | ||
431 | return 0; | |
432 | } | |
433 | ||
b9a96431 NA |
434 | /* Delete data symbols that have been assigned names from the variable section. |
435 | Must be called from within ctf_serialize, because that is the only place | |
436 | you can safely delete variables without messing up ctf_rollback. */ | |
bf4c3185 | 437 | |
b9a96431 NA |
438 | static int |
439 | symtypetab_delete_nonstatic_vars (ctf_dict_t *fp, ctf_dict_t *symfp) | |
bf4c3185 | 440 | { |
b9a96431 NA |
441 | ctf_dvdef_t *dvd, *nvd; |
442 | ctf_id_t type; | |
bf4c3185 | 443 | |
b9a96431 | 444 | for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd) |
bf4c3185 | 445 | { |
b9a96431 | 446 | nvd = ctf_list_next (dvd); |
bf4c3185 | 447 | |
b9a96431 NA |
448 | if (((type = (ctf_id_t) (uintptr_t) |
449 | ctf_dynhash_lookup (fp->ctf_objthash, dvd->dvd_name)) > 0) | |
450 | && ctf_dynhash_lookup (symfp->ctf_dynsyms, dvd->dvd_name) != NULL | |
451 | && type == dvd->dvd_type) | |
452 | ctf_dvd_delete (fp, dvd); | |
bf4c3185 NA |
453 | } |
454 | ||
b9a96431 | 455 | return 0; |
bf4c3185 NA |
456 | } |
457 | ||
b9a96431 NA |
458 | /* Figure out the sizes of the symtypetab sections, their indexed state, |
459 | etc. */ | |
bf4c3185 | 460 | static int |
b9a96431 NA |
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) | |
bf4c3185 | 465 | { |
b9a96431 | 466 | size_t nfuncs, nobjts; |
bf4c3185 | 467 | size_t objt_unpadsize, func_unpadsize, objt_padsize, func_padsize; |
bf4c3185 NA |
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 certaily 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 is in, since it only | |
476 | iterates over symbols and does not use the ctf_lookup_by_symbol* API.) */ | |
477 | ||
b9a96431 | 478 | s->sort_syms = 1; |
bf4c3185 NA |
479 | if (fp->ctf_flags & LCTF_LINKING) |
480 | { | |
b9a96431 NA |
481 | s->filter_syms = !(fp->ctf_link_flags & CTF_LINK_NO_FILTER_REPORTED_SYMS); |
482 | if (!s->filter_syms) | |
483 | s->sort_syms = 0; | |
bf4c3185 NA |
484 | } |
485 | ||
486 | /* Find the dict to which the linker has reported symbols, if any. */ | |
487 | ||
b9a96431 | 488 | if (s->filter_syms) |
bf4c3185 NA |
489 | { |
490 | if (!fp->ctf_dynsyms && fp->ctf_parent && fp->ctf_parent->ctf_dynsyms) | |
b9a96431 | 491 | s->symfp = fp->ctf_parent; |
bf4c3185 | 492 | else |
b9a96431 | 493 | s->symfp = fp; |
bf4c3185 NA |
494 | } |
495 | ||
496 | /* If not filtering, keep all potential symbols in an unsorted, indexed | |
497 | dict. */ | |
b9a96431 NA |
498 | if (!s->filter_syms) |
499 | s->symflags = CTF_SYMTYPETAB_FORCE_INDEXED; | |
bf4c3185 | 500 | else |
b9a96431 | 501 | hdr->cth_flags |= CTF_F_IDXSORTED; |
bf4c3185 | 502 | |
b9a96431 NA |
503 | if (!ctf_assert (fp, (s->filter_syms && s->symfp) |
504 | || (!s->filter_syms && !s->symfp | |
505 | && ((s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) != 0)))) | |
bf4c3185 NA |
506 | 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 | ||
b9a96431 NA |
512 | if (symtypetab_density (fp, s->symfp, fp->ctf_objthash, &nobjts, &s->maxobjt, |
513 | &objt_unpadsize, &objt_padsize, objtidx_size, | |
514 | s->symflags) < 0) | |
bf4c3185 NA |
515 | return -1; /* errno is set for us. */ |
516 | ||
517 | ctf_dprintf ("Object symtypetab: %i objects, max %i, unpadded size %i, " | |
b9a96431 NA |
518 | "%i bytes of pads, index size %i\n", (int) nobjts, |
519 | (int) s->maxobjt, (int) objt_unpadsize, (int) objt_padsize, | |
520 | (int) *objtidx_size); | |
bf4c3185 | 521 | |
b9a96431 NA |
522 | if (symtypetab_density (fp, s->symfp, fp->ctf_funchash, &nfuncs, &s->maxfunc, |
523 | &func_unpadsize, &func_padsize, funcidx_size, | |
524 | s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) | |
bf4c3185 NA |
525 | return -1; /* errno is set for us. */ |
526 | ||
527 | ctf_dprintf ("Function symtypetab: %i functions, max %i, unpadded size %i, " | |
b9a96431 NA |
528 | "%i bytes of pads, index size %i\n", (int) nfuncs, |
529 | (int) s->maxfunc, (int) func_unpadsize, (int) func_padsize, | |
530 | (int) *funcidx_size); | |
bf4c3185 NA |
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 | ||
b9a96431 NA |
543 | *objt_size = objt_unpadsize; |
544 | if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) | |
bf4c3185 NA |
545 | && ((objt_padsize + objt_unpadsize) * CTF_INDEX_PAD_THRESHOLD |
546 | > objt_padsize)) | |
547 | { | |
b9a96431 NA |
548 | *objt_size += objt_padsize; |
549 | *objtidx_size = 0; | |
bf4c3185 NA |
550 | } |
551 | ||
b9a96431 NA |
552 | *func_size = func_unpadsize; |
553 | if (!(s->symflags & CTF_SYMTYPETAB_FORCE_INDEXED) | |
bf4c3185 NA |
554 | && ((func_padsize + func_unpadsize) * CTF_INDEX_PAD_THRESHOLD |
555 | > func_padsize)) | |
556 | { | |
b9a96431 NA |
557 | *func_size += func_padsize; |
558 | *funcidx_size = 0; | |
bf4c3185 NA |
559 | } |
560 | ||
b9a96431 NA |
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 data | |
564 | symbols. There's no need to migrate new ones in, because the compiler | |
565 | always emits both a variable and a data symbol simultaneously, and | |
566 | filtering only happens at final link time. */ | |
bf4c3185 | 567 | |
b9a96431 NA |
568 | if (s->filter_syms && s->symfp->ctf_dynsyms && |
569 | symtypetab_delete_nonstatic_vars (fp, s->symfp) < 0) | |
570 | return -1; | |
bf4c3185 | 571 | |
b9a96431 NA |
572 | return 0; |
573 | } | |
bf4c3185 | 574 | |
b9a96431 NA |
575 | static int |
576 | ctf_emit_symtypetab_sects (ctf_dict_t *fp, emit_symtypetab_state_t *s, | |
577 | unsigned char **tptr, size_t objt_size, | |
578 | size_t func_size, size_t objtidx_size, | |
579 | size_t funcidx_size) | |
580 | { | |
581 | unsigned char *t = *tptr; | |
582 | size_t nsymtypes = 0; | |
583 | const char **sym_name_order = NULL; | |
584 | int err; | |
bf4c3185 | 585 | |
b9a96431 | 586 | /* Sort the linker's symbols into name order if need be. */ |
bf4c3185 NA |
587 | |
588 | if ((objtidx_size != 0) || (funcidx_size != 0)) | |
589 | { | |
590 | ctf_next_t *i = NULL; | |
591 | void *symname; | |
592 | const char **walk; | |
593 | ||
b9a96431 | 594 | if (s->filter_syms) |
bf4c3185 | 595 | { |
b9a96431 NA |
596 | if (s->symfp->ctf_dynsyms) |
597 | nsymtypes = ctf_dynhash_elements (s->symfp->ctf_dynsyms); | |
bf4c3185 NA |
598 | else |
599 | nsymtypes = 0; | |
600 | } | |
601 | else | |
602 | nsymtypes = ctf_dynhash_elements (fp->ctf_objthash) | |
603 | + ctf_dynhash_elements (fp->ctf_funchash); | |
604 | ||
605 | if ((sym_name_order = calloc (nsymtypes, sizeof (const char *))) == NULL) | |
606 | goto oom; | |
607 | ||
608 | walk = sym_name_order; | |
609 | ||
b9a96431 | 610 | if (s->filter_syms) |
bf4c3185 | 611 | { |
b9a96431 | 612 | if (s->symfp->ctf_dynsyms) |
bf4c3185 | 613 | { |
b9a96431 | 614 | while ((err = ctf_dynhash_next_sorted (s->symfp->ctf_dynsyms, &i, |
bf4c3185 NA |
615 | &symname, NULL, |
616 | ctf_dynhash_sort_by_name, | |
617 | NULL)) == 0) | |
618 | *walk++ = (const char *) symname; | |
619 | if (err != ECTF_NEXT_END) | |
620 | goto symerr; | |
621 | } | |
622 | } | |
623 | else | |
624 | { | |
625 | ctf_hash_sort_f sort_fun = NULL; | |
626 | ||
627 | /* Since we partition the set of symbols back into objt and func, | |
628 | we can sort the two independently without harm. */ | |
b9a96431 | 629 | if (s->sort_syms) |
bf4c3185 NA |
630 | sort_fun = ctf_dynhash_sort_by_name; |
631 | ||
632 | while ((err = ctf_dynhash_next_sorted (fp->ctf_objthash, &i, &symname, | |
633 | NULL, sort_fun, NULL)) == 0) | |
634 | *walk++ = (const char *) symname; | |
635 | if (err != ECTF_NEXT_END) | |
636 | goto symerr; | |
637 | ||
638 | while ((err = ctf_dynhash_next_sorted (fp->ctf_funchash, &i, &symname, | |
639 | NULL, sort_fun, NULL)) == 0) | |
640 | *walk++ = (const char *) symname; | |
641 | if (err != ECTF_NEXT_END) | |
642 | goto symerr; | |
643 | } | |
644 | } | |
645 | ||
646 | /* Emit the object and function sections, and if necessary their indexes. | |
647 | Emission is done in symtab order if there is no index, and in index | |
648 | (name) order otherwise. */ | |
649 | ||
b9a96431 | 650 | if ((objtidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx) |
bf4c3185 NA |
651 | { |
652 | ctf_dprintf ("Emitting unindexed objt symtypetab\n"); | |
b9a96431 NA |
653 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, |
654 | s->symfp->ctf_dynsymidx, NULL, | |
655 | s->symfp->ctf_dynsymmax + 1, s->maxobjt, | |
656 | objt_size, s->symflags | CTF_SYMTYPETAB_EMIT_PAD) < 0) | |
bf4c3185 NA |
657 | goto err; /* errno is set for us. */ |
658 | } | |
659 | else | |
660 | { | |
661 | ctf_dprintf ("Emitting indexed objt symtypetab\n"); | |
b9a96431 NA |
662 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, |
663 | sym_name_order, nsymtypes, s->maxobjt, | |
664 | objt_size, s->symflags) < 0) | |
bf4c3185 NA |
665 | goto err; /* errno is set for us. */ |
666 | } | |
667 | ||
668 | t += objt_size; | |
669 | ||
b9a96431 | 670 | if ((funcidx_size == 0) && s->symfp && s->symfp->ctf_dynsymidx) |
bf4c3185 NA |
671 | { |
672 | ctf_dprintf ("Emitting unindexed func symtypetab\n"); | |
b9a96431 NA |
673 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, |
674 | s->symfp->ctf_dynsymidx, NULL, | |
675 | s->symfp->ctf_dynsymmax + 1, s->maxfunc, | |
676 | func_size, s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION | |
bf4c3185 NA |
677 | | CTF_SYMTYPETAB_EMIT_PAD) < 0) |
678 | goto err; /* errno is set for us. */ | |
679 | } | |
680 | else | |
681 | { | |
682 | ctf_dprintf ("Emitting indexed func symtypetab\n"); | |
b9a96431 NA |
683 | if (emit_symtypetab (fp, s->symfp, (uint32_t *) t, NULL, sym_name_order, |
684 | nsymtypes, s->maxfunc, func_size, | |
685 | s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) | |
bf4c3185 NA |
686 | goto err; /* errno is set for us. */ |
687 | } | |
688 | ||
689 | t += func_size; | |
690 | ||
691 | if (objtidx_size > 0) | |
b9a96431 NA |
692 | if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order, |
693 | nsymtypes, objtidx_size, s->symflags) < 0) | |
bf4c3185 NA |
694 | goto err; |
695 | ||
696 | t += objtidx_size; | |
697 | ||
698 | if (funcidx_size > 0) | |
b9a96431 | 699 | if (emit_symtypetab_index (fp, s->symfp, (uint32_t *) t, sym_name_order, |
bf4c3185 | 700 | nsymtypes, funcidx_size, |
b9a96431 | 701 | s->symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0) |
bf4c3185 NA |
702 | goto err; |
703 | ||
704 | t += funcidx_size; | |
705 | free (sym_name_order); | |
b9a96431 | 706 | *tptr = t; |
bf4c3185 | 707 | |
b9a96431 | 708 | return 0; |
bf4c3185 | 709 | |
b9a96431 NA |
710 | oom: |
711 | ctf_set_errno (fp, EAGAIN); | |
712 | goto err; | |
713 | symerr: | |
714 | ctf_err_warn (fp, 0, err, _("error serializing symtypetabs")); | |
715 | err: | |
716 | free (sym_name_order); | |
717 | return -1; | |
718 | } | |
719 | ||
720 | /* Type section. */ | |
721 | ||
722 | static unsigned char * | |
723 | ctf_copy_smembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t) | |
724 | { | |
725 | ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members); | |
726 | ctf_member_t ctm; | |
727 | ||
728 | for (; dmd != NULL; dmd = ctf_list_next (dmd)) | |
bf4c3185 | 729 | { |
b9a96431 | 730 | ctf_member_t *copied; |
bf4c3185 | 731 | |
b9a96431 NA |
732 | ctm.ctm_name = 0; |
733 | ctm.ctm_type = (uint32_t) dmd->dmd_type; | |
734 | ctm.ctm_offset = (uint32_t) dmd->dmd_offset; | |
735 | ||
736 | memcpy (t, &ctm, sizeof (ctm)); | |
737 | copied = (ctf_member_t *) t; | |
738 | if (dmd->dmd_name) | |
739 | ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctm_name); | |
740 | ||
741 | t += sizeof (ctm); | |
bf4c3185 | 742 | } |
bf4c3185 | 743 | |
b9a96431 NA |
744 | return t; |
745 | } | |
bf4c3185 | 746 | |
b9a96431 NA |
747 | static unsigned char * |
748 | ctf_copy_lmembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t) | |
749 | { | |
750 | ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members); | |
751 | ctf_lmember_t ctlm; | |
752 | ||
753 | for (; dmd != NULL; dmd = ctf_list_next (dmd)) | |
754 | { | |
755 | ctf_lmember_t *copied; | |
756 | ||
757 | ctlm.ctlm_name = 0; | |
758 | ctlm.ctlm_type = (uint32_t) dmd->dmd_type; | |
759 | ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset); | |
760 | ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset); | |
761 | ||
762 | memcpy (t, &ctlm, sizeof (ctlm)); | |
763 | copied = (ctf_lmember_t *) t; | |
764 | if (dmd->dmd_name) | |
765 | ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctlm_name); | |
766 | ||
767 | t += sizeof (ctlm); | |
768 | } | |
769 | ||
770 | return t; | |
771 | } | |
772 | ||
773 | static unsigned char * | |
774 | ctf_copy_emembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t) | |
775 | { | |
776 | ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members); | |
777 | ctf_enum_t cte; | |
778 | ||
779 | for (; dmd != NULL; dmd = ctf_list_next (dmd)) | |
780 | { | |
781 | ctf_enum_t *copied; | |
782 | ||
783 | cte.cte_value = dmd->dmd_value; | |
784 | memcpy (t, &cte, sizeof (cte)); | |
785 | copied = (ctf_enum_t *) t; | |
786 | ctf_str_add_ref (fp, dmd->dmd_name, &copied->cte_name); | |
787 | t += sizeof (cte); | |
788 | } | |
789 | ||
790 | return t; | |
791 | } | |
792 | ||
793 | /* Iterate through the dynamic type definition list and compute the | |
794 | size of the CTF type section. */ | |
795 | ||
796 | static size_t | |
797 | ctf_type_sect_size (ctf_dict_t *fp) | |
798 | { | |
799 | ctf_dtdef_t *dtd; | |
800 | size_t type_size; | |
801 | ||
802 | for (type_size = 0, dtd = ctf_list_next (&fp->ctf_dtdefs); | |
803 | dtd != NULL; dtd = ctf_list_next (dtd)) | |
804 | { | |
805 | uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); | |
806 | uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info); | |
807 | ||
808 | if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT) | |
809 | type_size += sizeof (ctf_stype_t); | |
810 | else | |
811 | type_size += sizeof (ctf_type_t); | |
812 | ||
813 | switch (kind) | |
814 | { | |
815 | case CTF_K_INTEGER: | |
816 | case CTF_K_FLOAT: | |
817 | type_size += sizeof (uint32_t); | |
818 | break; | |
819 | case CTF_K_ARRAY: | |
820 | type_size += sizeof (ctf_array_t); | |
821 | break; | |
822 | case CTF_K_SLICE: | |
823 | type_size += sizeof (ctf_slice_t); | |
824 | break; | |
825 | case CTF_K_FUNCTION: | |
826 | type_size += sizeof (uint32_t) * (vlen + (vlen & 1)); | |
827 | break; | |
828 | case CTF_K_STRUCT: | |
829 | case CTF_K_UNION: | |
830 | if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH) | |
831 | type_size += sizeof (ctf_member_t) * vlen; | |
832 | else | |
833 | type_size += sizeof (ctf_lmember_t) * vlen; | |
834 | break; | |
835 | case CTF_K_ENUM: | |
836 | type_size += sizeof (ctf_enum_t) * vlen; | |
837 | break; | |
838 | } | |
839 | } | |
bf4c3185 | 840 | |
b9a96431 NA |
841 | return type_size; |
842 | } | |
843 | ||
844 | /* Take a final lap through the dynamic type definition list and copy the | |
845 | appropriate type records to the output buffer, noting down the strings as | |
846 | we go. */ | |
847 | ||
848 | static void | |
849 | ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr) | |
850 | { | |
851 | unsigned char *t = *tptr; | |
852 | ctf_dtdef_t *dtd; | |
bf4c3185 NA |
853 | |
854 | for (dtd = ctf_list_next (&fp->ctf_dtdefs); | |
855 | dtd != NULL; dtd = ctf_list_next (dtd)) | |
856 | { | |
857 | uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); | |
858 | uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info); | |
859 | ||
bf4c3185 NA |
860 | size_t len; |
861 | ctf_stype_t *copied; | |
862 | const char *name; | |
863 | ||
864 | if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT) | |
865 | len = sizeof (ctf_stype_t); | |
866 | else | |
867 | len = sizeof (ctf_type_t); | |
868 | ||
869 | memcpy (t, &dtd->dtd_data, len); | |
870 | copied = (ctf_stype_t *) t; /* name is at the start: constant offset. */ | |
871 | if (copied->ctt_name | |
872 | && (name = ctf_strraw (fp, copied->ctt_name)) != NULL) | |
873 | ctf_str_add_ref (fp, name, &copied->ctt_name); | |
874 | t += len; | |
875 | ||
876 | switch (kind) | |
877 | { | |
878 | case CTF_K_INTEGER: | |
879 | case CTF_K_FLOAT: | |
7879dd88 NA |
880 | memcpy (t, dtd->dtd_vlen, sizeof (uint32_t)); |
881 | t += sizeof (uint32_t); | |
bf4c3185 NA |
882 | break; |
883 | ||
884 | case CTF_K_SLICE: | |
7879dd88 | 885 | memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_slice)); |
bf4c3185 NA |
886 | t += sizeof (struct ctf_slice); |
887 | break; | |
888 | ||
889 | case CTF_K_ARRAY: | |
534444b1 NA |
890 | memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_array)); |
891 | t += sizeof (struct ctf_array); | |
bf4c3185 NA |
892 | break; |
893 | ||
894 | case CTF_K_FUNCTION: | |
81982d20 NA |
895 | memcpy (t, dtd->dtd_vlen, sizeof (uint32_t) * (vlen + (vlen & 1))); |
896 | t += sizeof (uint32_t) * (vlen + (vlen & 1)); | |
897 | break; | |
bf4c3185 NA |
898 | |
899 | case CTF_K_STRUCT: | |
900 | case CTF_K_UNION: | |
901 | if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH) | |
902 | t = ctf_copy_smembers (fp, dtd, t); | |
903 | else | |
904 | t = ctf_copy_lmembers (fp, dtd, t); | |
905 | break; | |
906 | ||
907 | case CTF_K_ENUM: | |
908 | t = ctf_copy_emembers (fp, dtd, t); | |
909 | break; | |
910 | } | |
911 | } | |
b9a96431 NA |
912 | |
913 | *tptr = t; | |
914 | } | |
915 | ||
916 | /* Variable section. */ | |
917 | ||
918 | /* Sort a newly-constructed static variable array. */ | |
919 | ||
920 | typedef struct ctf_sort_var_arg_cb | |
921 | { | |
922 | ctf_dict_t *fp; | |
923 | ctf_strs_t *strtab; | |
924 | } ctf_sort_var_arg_cb_t; | |
925 | ||
926 | static int | |
927 | ctf_sort_var (const void *one_, const void *two_, void *arg_) | |
928 | { | |
929 | const ctf_varent_t *one = one_; | |
930 | const ctf_varent_t *two = two_; | |
931 | ctf_sort_var_arg_cb_t *arg = arg_; | |
932 | ||
933 | return (strcmp (ctf_strraw_explicit (arg->fp, one->ctv_name, arg->strtab), | |
934 | ctf_strraw_explicit (arg->fp, two->ctv_name, arg->strtab))); | |
935 | } | |
936 | ||
937 | /* Overall serialization. */ | |
938 | ||
939 | /* If the specified CTF dict is writable and has been modified, reload this dict | |
940 | with the updated type definitions, ready for serialization. In order to make | |
941 | this code and the rest of libctf as simple as possible, we perform updates by | |
942 | taking the dynamic type definitions and creating an in-memory CTF dict | |
943 | containing the definitions, and then call ctf_simple_open_internal() on it. | |
944 | We perform one extra trick here for the benefit of callers and to keep our | |
945 | code simple: ctf_simple_open_internal() will return a new ctf_dict_t, but we | |
946 | want to keep the fp constant for the caller, so after | |
947 | ctf_simple_open_internal() returns, we use memcpy to swap the interior of the | |
948 | old and new ctf_dict_t's, and then free the old. */ | |
949 | int | |
950 | ctf_serialize (ctf_dict_t *fp) | |
951 | { | |
952 | ctf_dict_t ofp, *nfp; | |
953 | ctf_header_t hdr, *hdrp; | |
954 | ctf_dvdef_t *dvd; | |
955 | ctf_varent_t *dvarents; | |
956 | ctf_strs_writable_t strtab; | |
957 | int err; | |
958 | ||
959 | unsigned char *t; | |
960 | unsigned long i; | |
961 | size_t buf_size, type_size, objt_size, func_size; | |
962 | size_t funcidx_size, objtidx_size; | |
963 | size_t nvars; | |
964 | unsigned char *buf = NULL, *newbuf; | |
965 | ||
966 | emit_symtypetab_state_t symstate; | |
967 | memset (&symstate, 0, sizeof (emit_symtypetab_state_t)); | |
968 | ||
969 | if (!(fp->ctf_flags & LCTF_RDWR)) | |
970 | return (ctf_set_errno (fp, ECTF_RDONLY)); | |
971 | ||
972 | /* Update required? */ | |
973 | if (!(fp->ctf_flags & LCTF_DIRTY)) | |
974 | return 0; | |
975 | ||
976 | /* Fill in an initial CTF header. We will leave the label, object, | |
977 | and function sections empty and only output a header, type section, | |
978 | and string table. The type section begins at a 4-byte aligned | |
979 | boundary past the CTF header itself (at relative offset zero). The flag | |
980 | indicating a new-style function info section (an array of CTF_K_FUNCTION | |
981 | type IDs in the types section) is flipped on. */ | |
982 | ||
983 | memset (&hdr, 0, sizeof (hdr)); | |
984 | hdr.cth_magic = CTF_MAGIC; | |
985 | hdr.cth_version = CTF_VERSION; | |
986 | ||
987 | /* This is a new-format func info section, and the symtab and strtab come out | |
988 | of the dynsym and dynstr these days. */ | |
989 | hdr.cth_flags = (CTF_F_NEWFUNCINFO | CTF_F_DYNSTR); | |
990 | ||
991 | if (ctf_symtypetab_sect_sizes (fp, &symstate, &hdr, &objt_size, &func_size, | |
992 | &objtidx_size, &funcidx_size) < 0) | |
993 | return -1; /* errno is set for us. */ | |
994 | ||
995 | for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); | |
996 | dvd != NULL; dvd = ctf_list_next (dvd), nvars++); | |
997 | ||
998 | type_size = ctf_type_sect_size (fp); | |
999 | ||
1000 | /* Compute the size of the CTF buffer we need, sans only the string table, | |
1001 | then allocate a new buffer and memcpy the finished header to the start of | |
1002 | the buffer. (We will adjust this later with strtab length info.) */ | |
1003 | ||
1004 | hdr.cth_lbloff = hdr.cth_objtoff = 0; | |
1005 | hdr.cth_funcoff = hdr.cth_objtoff + objt_size; | |
1006 | hdr.cth_objtidxoff = hdr.cth_funcoff + func_size; | |
1007 | hdr.cth_funcidxoff = hdr.cth_objtidxoff + objtidx_size; | |
1008 | hdr.cth_varoff = hdr.cth_funcidxoff + funcidx_size; | |
1009 | hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t)); | |
1010 | hdr.cth_stroff = hdr.cth_typeoff + type_size; | |
1011 | hdr.cth_strlen = 0; | |
1012 | ||
1013 | buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen; | |
1014 | ||
1015 | if ((buf = malloc (buf_size)) == NULL) | |
1016 | return (ctf_set_errno (fp, EAGAIN)); | |
1017 | ||
1018 | memcpy (buf, &hdr, sizeof (ctf_header_t)); | |
1019 | t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff; | |
1020 | ||
1021 | hdrp = (ctf_header_t *) buf; | |
1022 | if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL)) | |
1023 | ctf_str_add_ref (fp, fp->ctf_parname, &hdrp->cth_parname); | |
1024 | if (fp->ctf_cuname != NULL) | |
1025 | ctf_str_add_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname); | |
1026 | ||
1027 | if (ctf_emit_symtypetab_sects (fp, &symstate, &t, objt_size, func_size, | |
1028 | objtidx_size, funcidx_size) < 0) | |
1029 | goto err; | |
1030 | ||
1031 | assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_varoff); | |
1032 | ||
1033 | /* Work over the variable list, translating everything into ctf_varent_t's and | |
1034 | prepping the string table. */ | |
1035 | ||
1036 | dvarents = (ctf_varent_t *) t; | |
1037 | for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; | |
1038 | dvd = ctf_list_next (dvd), i++) | |
1039 | { | |
1040 | ctf_varent_t *var = &dvarents[i]; | |
1041 | ||
1042 | ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name); | |
1043 | var->ctv_type = (uint32_t) dvd->dvd_type; | |
1044 | } | |
1045 | assert (i == nvars); | |
1046 | ||
1047 | t += sizeof (ctf_varent_t) * nvars; | |
1048 | ||
1049 | assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff); | |
1050 | ||
1051 | ctf_emit_type_sect (fp, &t); | |
1052 | ||
bf4c3185 NA |
1053 | assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff); |
1054 | ||
1055 | /* Construct the final string table and fill out all the string refs with the | |
1056 | final offsets. Then purge the refs list, because we're about to move this | |
1057 | strtab onto the end of the buf, invalidating all the offsets. */ | |
1058 | strtab = ctf_str_write_strtab (fp); | |
1059 | ctf_str_purge_refs (fp); | |
1060 | ||
1061 | if (strtab.cts_strs == NULL) | |
1062 | goto oom; | |
1063 | ||
1064 | /* Now the string table is constructed, we can sort the buffer of | |
1065 | ctf_varent_t's. */ | |
1066 | ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) &strtab }; | |
1067 | ctf_qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var, | |
1068 | &sort_var_arg); | |
1069 | ||
1070 | if ((newbuf = ctf_realloc (fp, buf, buf_size + strtab.cts_len)) == NULL) | |
1071 | { | |
1072 | free (strtab.cts_strs); | |
1073 | goto oom; | |
1074 | } | |
1075 | buf = newbuf; | |
1076 | memcpy (buf + buf_size, strtab.cts_strs, strtab.cts_len); | |
1077 | hdrp = (ctf_header_t *) buf; | |
1078 | hdrp->cth_strlen = strtab.cts_len; | |
1079 | buf_size += hdrp->cth_strlen; | |
1080 | free (strtab.cts_strs); | |
1081 | ||
1082 | /* Finally, we are ready to ctf_simple_open() the new dict. If this is | |
1083 | successful, we then switch nfp and fp and free the old dict. */ | |
1084 | ||
1085 | if ((nfp = ctf_simple_open_internal ((char *) buf, buf_size, NULL, 0, | |
1086 | 0, NULL, 0, fp->ctf_syn_ext_strtab, | |
1087 | 1, &err)) == NULL) | |
1088 | { | |
1089 | free (buf); | |
1090 | return (ctf_set_errno (fp, err)); | |
1091 | } | |
1092 | ||
1093 | (void) ctf_setmodel (nfp, ctf_getmodel (fp)); | |
1094 | ||
1095 | nfp->ctf_parent = fp->ctf_parent; | |
1096 | nfp->ctf_parent_unreffed = fp->ctf_parent_unreffed; | |
1097 | nfp->ctf_refcnt = fp->ctf_refcnt; | |
1098 | nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY; | |
1099 | if (nfp->ctf_dynbase == NULL) | |
1100 | nfp->ctf_dynbase = buf; /* Make sure buf is freed on close. */ | |
1101 | nfp->ctf_dthash = fp->ctf_dthash; | |
1102 | nfp->ctf_dtdefs = fp->ctf_dtdefs; | |
1103 | nfp->ctf_dvhash = fp->ctf_dvhash; | |
1104 | nfp->ctf_dvdefs = fp->ctf_dvdefs; | |
1105 | nfp->ctf_dtoldid = fp->ctf_dtoldid; | |
1106 | nfp->ctf_add_processing = fp->ctf_add_processing; | |
1107 | nfp->ctf_snapshots = fp->ctf_snapshots + 1; | |
1108 | nfp->ctf_specific = fp->ctf_specific; | |
1109 | nfp->ctf_nfuncidx = fp->ctf_nfuncidx; | |
1110 | nfp->ctf_nobjtidx = fp->ctf_nobjtidx; | |
1111 | nfp->ctf_objthash = fp->ctf_objthash; | |
1112 | nfp->ctf_funchash = fp->ctf_funchash; | |
1113 | nfp->ctf_dynsyms = fp->ctf_dynsyms; | |
1114 | nfp->ctf_ptrtab = fp->ctf_ptrtab; | |
1115 | nfp->ctf_pptrtab = fp->ctf_pptrtab; | |
1116 | nfp->ctf_dynsymidx = fp->ctf_dynsymidx; | |
1117 | nfp->ctf_dynsymmax = fp->ctf_dynsymmax; | |
1118 | nfp->ctf_ptrtab_len = fp->ctf_ptrtab_len; | |
1119 | nfp->ctf_pptrtab_len = fp->ctf_pptrtab_len; | |
1120 | nfp->ctf_link_inputs = fp->ctf_link_inputs; | |
1121 | nfp->ctf_link_outputs = fp->ctf_link_outputs; | |
1122 | nfp->ctf_errs_warnings = fp->ctf_errs_warnings; | |
1123 | nfp->ctf_funcidx_names = fp->ctf_funcidx_names; | |
1124 | nfp->ctf_objtidx_names = fp->ctf_objtidx_names; | |
1125 | nfp->ctf_funcidx_sxlate = fp->ctf_funcidx_sxlate; | |
1126 | nfp->ctf_objtidx_sxlate = fp->ctf_objtidx_sxlate; | |
1127 | nfp->ctf_str_prov_offset = fp->ctf_str_prov_offset; | |
1128 | nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab; | |
1129 | nfp->ctf_pptrtab_typemax = fp->ctf_pptrtab_typemax; | |
1130 | nfp->ctf_in_flight_dynsyms = fp->ctf_in_flight_dynsyms; | |
1131 | nfp->ctf_link_in_cu_mapping = fp->ctf_link_in_cu_mapping; | |
1132 | nfp->ctf_link_out_cu_mapping = fp->ctf_link_out_cu_mapping; | |
1133 | nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping; | |
1134 | nfp->ctf_link_memb_name_changer = fp->ctf_link_memb_name_changer; | |
1135 | nfp->ctf_link_memb_name_changer_arg = fp->ctf_link_memb_name_changer_arg; | |
1136 | nfp->ctf_link_variable_filter = fp->ctf_link_variable_filter; | |
1137 | nfp->ctf_link_variable_filter_arg = fp->ctf_link_variable_filter_arg; | |
1138 | nfp->ctf_symsect_little_endian = fp->ctf_symsect_little_endian; | |
1139 | nfp->ctf_link_flags = fp->ctf_link_flags; | |
1140 | nfp->ctf_dedup_atoms = fp->ctf_dedup_atoms; | |
1141 | nfp->ctf_dedup_atoms_alloc = fp->ctf_dedup_atoms_alloc; | |
1142 | memcpy (&nfp->ctf_dedup, &fp->ctf_dedup, sizeof (fp->ctf_dedup)); | |
1143 | ||
1144 | nfp->ctf_snapshot_lu = fp->ctf_snapshots; | |
1145 | ||
1146 | memcpy (&nfp->ctf_lookups, fp->ctf_lookups, sizeof (fp->ctf_lookups)); | |
1147 | nfp->ctf_structs = fp->ctf_structs; | |
1148 | nfp->ctf_unions = fp->ctf_unions; | |
1149 | nfp->ctf_enums = fp->ctf_enums; | |
1150 | nfp->ctf_names = fp->ctf_names; | |
1151 | ||
1152 | fp->ctf_dthash = NULL; | |
1153 | ctf_str_free_atoms (nfp); | |
1154 | nfp->ctf_str_atoms = fp->ctf_str_atoms; | |
1155 | nfp->ctf_prov_strtab = fp->ctf_prov_strtab; | |
1156 | fp->ctf_str_atoms = NULL; | |
1157 | fp->ctf_prov_strtab = NULL; | |
1158 | memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t)); | |
1159 | memset (&fp->ctf_errs_warnings, 0, sizeof (ctf_list_t)); | |
1160 | fp->ctf_add_processing = NULL; | |
1161 | fp->ctf_ptrtab = NULL; | |
1162 | fp->ctf_pptrtab = NULL; | |
1163 | fp->ctf_funcidx_names = NULL; | |
1164 | fp->ctf_objtidx_names = NULL; | |
1165 | fp->ctf_funcidx_sxlate = NULL; | |
1166 | fp->ctf_objtidx_sxlate = NULL; | |
1167 | fp->ctf_objthash = NULL; | |
1168 | fp->ctf_funchash = NULL; | |
1169 | fp->ctf_dynsyms = NULL; | |
1170 | fp->ctf_dynsymidx = NULL; | |
1171 | fp->ctf_link_inputs = NULL; | |
1172 | fp->ctf_link_outputs = NULL; | |
1173 | fp->ctf_syn_ext_strtab = NULL; | |
1174 | fp->ctf_link_in_cu_mapping = NULL; | |
1175 | fp->ctf_link_out_cu_mapping = NULL; | |
1176 | fp->ctf_link_type_mapping = NULL; | |
1177 | fp->ctf_dedup_atoms = NULL; | |
1178 | fp->ctf_dedup_atoms_alloc = NULL; | |
1179 | fp->ctf_parent_unreffed = 1; | |
1180 | ||
1181 | fp->ctf_dvhash = NULL; | |
1182 | memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t)); | |
1183 | memset (fp->ctf_lookups, 0, sizeof (fp->ctf_lookups)); | |
1184 | memset (&fp->ctf_in_flight_dynsyms, 0, sizeof (fp->ctf_in_flight_dynsyms)); | |
1185 | memset (&fp->ctf_dedup, 0, sizeof (fp->ctf_dedup)); | |
1186 | fp->ctf_structs.ctn_writable = NULL; | |
1187 | fp->ctf_unions.ctn_writable = NULL; | |
1188 | fp->ctf_enums.ctn_writable = NULL; | |
1189 | fp->ctf_names.ctn_writable = NULL; | |
1190 | ||
1191 | memcpy (&ofp, fp, sizeof (ctf_dict_t)); | |
1192 | memcpy (fp, nfp, sizeof (ctf_dict_t)); | |
1193 | memcpy (nfp, &ofp, sizeof (ctf_dict_t)); | |
1194 | ||
1195 | nfp->ctf_refcnt = 1; /* Force nfp to be freed. */ | |
1196 | ctf_dict_close (nfp); | |
1197 | ||
1198 | return 0; | |
1199 | ||
bf4c3185 NA |
1200 | oom: |
1201 | free (buf); | |
bf4c3185 NA |
1202 | return (ctf_set_errno (fp, EAGAIN)); |
1203 | err: | |
1204 | free (buf); | |
bf4c3185 NA |
1205 | return -1; /* errno is set for us. */ |
1206 | } | |
1207 | ||
b9a96431 | 1208 | /* File writing. */ |
bf4c3185 NA |
1209 | |
1210 | /* Write the compressed CTF data stream to the specified gzFile descriptor. */ | |
1211 | int | |
1212 | ctf_gzwrite (ctf_dict_t *fp, gzFile fd) | |
1213 | { | |
1214 | const unsigned char *buf; | |
1215 | ssize_t resid; | |
1216 | ssize_t len; | |
1217 | ||
1218 | resid = sizeof (ctf_header_t); | |
1219 | buf = (unsigned char *) fp->ctf_header; | |
1220 | while (resid != 0) | |
1221 | { | |
1222 | if ((len = gzwrite (fd, buf, resid)) <= 0) | |
1223 | return (ctf_set_errno (fp, errno)); | |
1224 | resid -= len; | |
1225 | buf += len; | |
1226 | } | |
1227 | ||
1228 | resid = fp->ctf_size; | |
1229 | buf = fp->ctf_buf; | |
1230 | while (resid != 0) | |
1231 | { | |
1232 | if ((len = gzwrite (fd, buf, resid)) <= 0) | |
1233 | return (ctf_set_errno (fp, errno)); | |
1234 | resid -= len; | |
1235 | buf += len; | |
1236 | } | |
1237 | ||
1238 | return 0; | |
1239 | } | |
1240 | ||
1241 | /* Compress the specified CTF data stream and write it to the specified file | |
1242 | descriptor. */ | |
1243 | int | |
1244 | ctf_compress_write (ctf_dict_t *fp, int fd) | |
1245 | { | |
1246 | unsigned char *buf; | |
1247 | unsigned char *bp; | |
1248 | ctf_header_t h; | |
1249 | ctf_header_t *hp = &h; | |
1250 | ssize_t header_len = sizeof (ctf_header_t); | |
1251 | ssize_t compress_len; | |
1252 | ssize_t len; | |
1253 | int rc; | |
1254 | int err = 0; | |
1255 | ||
1256 | if (ctf_serialize (fp) < 0) | |
1257 | return -1; /* errno is set for us. */ | |
1258 | ||
1259 | memcpy (hp, fp->ctf_header, header_len); | |
1260 | hp->cth_flags |= CTF_F_COMPRESS; | |
1261 | compress_len = compressBound (fp->ctf_size); | |
1262 | ||
1263 | if ((buf = malloc (compress_len)) == NULL) | |
1264 | { | |
1265 | ctf_err_warn (fp, 0, 0, _("ctf_compress_write: cannot allocate %li bytes"), | |
1266 | (unsigned long) compress_len); | |
1267 | return (ctf_set_errno (fp, ECTF_ZALLOC)); | |
1268 | } | |
1269 | ||
1270 | if ((rc = compress (buf, (uLongf *) &compress_len, | |
1271 | fp->ctf_buf, fp->ctf_size)) != Z_OK) | |
1272 | { | |
1273 | err = ctf_set_errno (fp, ECTF_COMPRESS); | |
1274 | ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc)); | |
1275 | goto ret; | |
1276 | } | |
1277 | ||
1278 | while (header_len > 0) | |
1279 | { | |
1280 | if ((len = write (fd, hp, header_len)) < 0) | |
1281 | { | |
1282 | err = ctf_set_errno (fp, errno); | |
1283 | ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing header")); | |
1284 | goto ret; | |
1285 | } | |
1286 | header_len -= len; | |
1287 | hp += len; | |
1288 | } | |
1289 | ||
1290 | bp = buf; | |
1291 | while (compress_len > 0) | |
1292 | { | |
1293 | if ((len = write (fd, bp, compress_len)) < 0) | |
1294 | { | |
1295 | err = ctf_set_errno (fp, errno); | |
1296 | ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing")); | |
1297 | goto ret; | |
1298 | } | |
1299 | compress_len -= len; | |
1300 | bp += len; | |
1301 | } | |
1302 | ||
1303 | ret: | |
1304 | free (buf); | |
1305 | return err; | |
1306 | } | |
1307 | ||
1308 | /* Optionally compress the specified CTF data stream and return it as a new | |
1309 | dynamically-allocated string. */ | |
1310 | unsigned char * | |
1311 | ctf_write_mem (ctf_dict_t *fp, size_t *size, size_t threshold) | |
1312 | { | |
1313 | unsigned char *buf; | |
1314 | unsigned char *bp; | |
1315 | ctf_header_t *hp; | |
1316 | ssize_t header_len = sizeof (ctf_header_t); | |
1317 | ssize_t compress_len; | |
1318 | int rc; | |
1319 | ||
1320 | if (ctf_serialize (fp) < 0) | |
1321 | return NULL; /* errno is set for us. */ | |
1322 | ||
1323 | compress_len = compressBound (fp->ctf_size); | |
1324 | if (fp->ctf_size < threshold) | |
1325 | compress_len = fp->ctf_size; | |
1326 | if ((buf = malloc (compress_len | |
1327 | + sizeof (struct ctf_header))) == NULL) | |
1328 | { | |
1329 | ctf_set_errno (fp, ENOMEM); | |
1330 | ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"), | |
1331 | (unsigned long) (compress_len + sizeof (struct ctf_header))); | |
1332 | return NULL; | |
1333 | } | |
1334 | ||
1335 | hp = (ctf_header_t *) buf; | |
1336 | memcpy (hp, fp->ctf_header, header_len); | |
1337 | bp = buf + sizeof (struct ctf_header); | |
1338 | *size = sizeof (struct ctf_header); | |
1339 | ||
1340 | if (fp->ctf_size < threshold) | |
1341 | { | |
1342 | hp->cth_flags &= ~CTF_F_COMPRESS; | |
1343 | memcpy (bp, fp->ctf_buf, fp->ctf_size); | |
1344 | *size += fp->ctf_size; | |
1345 | } | |
1346 | else | |
1347 | { | |
1348 | hp->cth_flags |= CTF_F_COMPRESS; | |
1349 | if ((rc = compress (bp, (uLongf *) &compress_len, | |
1350 | fp->ctf_buf, fp->ctf_size)) != Z_OK) | |
1351 | { | |
1352 | ctf_set_errno (fp, ECTF_COMPRESS); | |
1353 | ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc)); | |
1354 | free (buf); | |
1355 | return NULL; | |
1356 | } | |
1357 | *size += compress_len; | |
1358 | } | |
1359 | return buf; | |
1360 | } | |
1361 | ||
1362 | /* Write the uncompressed CTF data stream to the specified file descriptor. */ | |
1363 | int | |
1364 | ctf_write (ctf_dict_t *fp, int fd) | |
1365 | { | |
1366 | const unsigned char *buf; | |
1367 | ssize_t resid; | |
1368 | ssize_t len; | |
1369 | ||
1370 | if (ctf_serialize (fp) < 0) | |
1371 | return -1; /* errno is set for us. */ | |
1372 | ||
1373 | resid = sizeof (ctf_header_t); | |
1374 | buf = (unsigned char *) fp->ctf_header; | |
1375 | while (resid != 0) | |
1376 | { | |
1377 | if ((len = write (fd, buf, resid)) <= 0) | |
1378 | { | |
1379 | ctf_err_warn (fp, 0, errno, _("ctf_write: error writing header")); | |
1380 | return (ctf_set_errno (fp, errno)); | |
1381 | } | |
1382 | resid -= len; | |
1383 | buf += len; | |
1384 | } | |
1385 | ||
1386 | resid = fp->ctf_size; | |
1387 | buf = fp->ctf_buf; | |
1388 | while (resid != 0) | |
1389 | { | |
1390 | if ((len = write (fd, buf, resid)) <= 0) | |
1391 | { | |
1392 | ctf_err_warn (fp, 0, errno, _("ctf_write: error writing")); | |
1393 | return (ctf_set_errno (fp, errno)); | |
1394 | } | |
1395 | resid -= len; | |
1396 | buf += len; | |
1397 | } | |
1398 | ||
1399 | return 0; | |
1400 | } |