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