libctf: add linking of the variable section
[deliverable/binutils-gdb.git] / libctf / ctf-link.c
1 /* CTF linking.
2 Copyright (C) 2019 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 <string.h>
22
23 /* Type tracking machinery. */
24
25 /* Record the correspondence between a source and ctf_add_type()-added
26 destination type: both types are translated into parent type IDs if need be,
27 so they relate to the actual container they are in. Outside controlled
28 circumstances (like linking) it is probably not useful to do more than
29 compare these pointers, since there is nothing stopping the user closing the
30 source container whenever they want to.
31
32 Our OOM handling here is just to not do anything, because this is called deep
33 enough in the call stack that doing anything useful is painfully difficult:
34 the worst consequence if we do OOM is a bit of type duplication anyway. */
35
36 void
37 ctf_add_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type,
38 ctf_file_t *dst_fp, ctf_id_t dst_type)
39 {
40 if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
41 src_fp = src_fp->ctf_parent;
42
43 src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
44
45 if (LCTF_TYPE_ISPARENT (dst_fp, dst_type) && dst_fp->ctf_parent)
46 dst_fp = dst_fp->ctf_parent;
47
48 dst_type = LCTF_TYPE_TO_INDEX(dst_fp, dst_type);
49
50 /* This dynhash is a bit tricky: it has a multivalued (structural) key, so we
51 need to use the sized-hash machinery to generate key hashing and equality
52 functions. */
53
54 if (dst_fp->ctf_link_type_mapping == NULL)
55 {
56 ctf_hash_fun f = ctf_hash_type_mapping_key;
57 ctf_hash_eq_fun e = ctf_hash_eq_type_mapping_key;
58
59 if ((dst_fp->ctf_link_type_mapping = ctf_dynhash_create (f, e, free,
60 NULL)) == NULL)
61 return;
62 }
63
64 ctf_link_type_mapping_key_t *key;
65 key = calloc (1, sizeof (struct ctf_link_type_mapping_key));
66 if (!key)
67 return;
68
69 key->cltm_fp = src_fp;
70 key->cltm_idx = src_type;
71
72 ctf_dynhash_insert (dst_fp->ctf_link_type_mapping, key,
73 (void *) (uintptr_t) dst_type);
74 }
75
76 /* Look up a type mapping: return 0 if none. The DST_FP is modified to point to
77 the parent if need be. The ID returned is from the dst_fp's perspective. */
78 ctf_id_t
79 ctf_type_mapping (ctf_file_t *src_fp, ctf_id_t src_type, ctf_file_t **dst_fp)
80 {
81 ctf_link_type_mapping_key_t key;
82 ctf_file_t *target_fp = *dst_fp;
83 ctf_id_t dst_type = 0;
84
85 if (LCTF_TYPE_ISPARENT (src_fp, src_type) && src_fp->ctf_parent)
86 src_fp = src_fp->ctf_parent;
87
88 src_type = LCTF_TYPE_TO_INDEX(src_fp, src_type);
89 key.cltm_fp = src_fp;
90 key.cltm_idx = src_type;
91
92 if (target_fp->ctf_link_type_mapping)
93 dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
94 &key);
95
96 if (dst_type != 0)
97 {
98 dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
99 target_fp->ctf_parent != NULL);
100 *dst_fp = target_fp;
101 return dst_type;
102 }
103
104 if (target_fp->ctf_parent)
105 target_fp = target_fp->ctf_parent;
106 else
107 return 0;
108
109 if (target_fp->ctf_link_type_mapping)
110 dst_type = (uintptr_t) ctf_dynhash_lookup (target_fp->ctf_link_type_mapping,
111 &key);
112
113 if (dst_type)
114 dst_type = LCTF_INDEX_TO_TYPE (target_fp, dst_type,
115 target_fp->ctf_parent != NULL);
116
117 *dst_fp = target_fp;
118 return dst_type;
119 }
120
121 /* Linker machinery.
122
123 CTF linking consists of adding CTF archives full of content to be merged into
124 this one to the current file (which must be writable) by calling
125 ctf_link_add_ctf(). Once this is done, a call to ctf_link() will merge the
126 type tables together, generating new CTF files as needed, with this one as a
127 parent, to contain types from the inputs which conflict.
128 ctf_link_add_strtab() takes a callback which provides string/offset pairs to
129 be added to the external symbol table and deduplicated from all CTF string
130 tables in the output link; ctf_link_shuffle_syms() takes a callback which
131 provides symtab entries in ascending order, and shuffles the function and
132 data sections to match; and ctf_link_write() emits a CTF file (if there are
133 no conflicts requiring per-compilation-unit sub-CTF files) or CTF archives
134 (otherwise) and returns it, suitable for addition in the .ctf section of the
135 output. */
136
137 /* Add a file to a link. */
138
139 static void ctf_arc_close_thunk (void *arc)
140 {
141 ctf_arc_close ((ctf_archive_t *) arc);
142 }
143
144 static void ctf_file_close_thunk (void *file)
145 {
146 ctf_file_close ((ctf_file_t *) file);
147 }
148
149 int
150 ctf_link_add_ctf (ctf_file_t *fp, ctf_archive_t *ctf, const char *name)
151 {
152 char *dupname = NULL;
153
154 if (fp->ctf_link_outputs)
155 return (ctf_set_errno (fp, ECTF_LINKADDEDLATE));
156 if (fp->ctf_link_inputs == NULL)
157 fp->ctf_link_inputs = ctf_dynhash_create (ctf_hash_string,
158 ctf_hash_eq_string, free,
159 ctf_arc_close_thunk);
160
161 if (fp->ctf_link_inputs == NULL)
162 goto oom;
163
164 if ((dupname = strdup (name)) == NULL)
165 goto oom;
166
167 if (ctf_dynhash_insert (fp->ctf_link_inputs, dupname, ctf) < 0)
168 goto oom;
169
170 return 0;
171 oom:
172 free (fp->ctf_link_inputs);
173 fp->ctf_link_inputs = NULL;
174 free (dupname);
175 return (ctf_set_errno (fp, ENOMEM));
176 }
177
178 /* Return a per-CU output CTF dictionary suitable for the given CU, creating and
179 interning it if need be. */
180
181 static ctf_file_t *
182 ctf_create_per_cu (ctf_file_t *fp, const char *filename, const char *cuname)
183 {
184 ctf_file_t *cu_fp;
185 char *dynname = NULL;
186
187 if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, filename)) == NULL)
188 {
189 int err;
190
191 if ((cu_fp = ctf_create (&err)) == NULL)
192 {
193 ctf_dprintf ("Cannot create per-CU CTF archive for CU %s from "
194 "input file %s: %s\n", cuname, filename,
195 ctf_errmsg (err));
196 ctf_set_errno (fp, err);
197 return NULL;
198 }
199
200 if ((dynname = strdup (filename)) == NULL)
201 goto oom;
202 if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, cu_fp) < 0)
203 goto oom;
204
205 ctf_import (cu_fp, fp);
206 ctf_cuname_set (cu_fp, cuname);
207 ctf_parent_name_set (cu_fp, _CTF_SECTION);
208 }
209 return cu_fp;
210
211 oom:
212 free (dynname);
213 ctf_file_close (cu_fp);
214 ctf_set_errno (fp, ENOMEM);
215 return NULL;
216 }
217
218 typedef struct ctf_link_in_member_cb_arg
219 {
220 ctf_file_t *out_fp;
221 const char *file_name;
222 ctf_file_t *in_fp;
223 ctf_file_t *main_input_fp;
224 const char *cu_name;
225 char *arcname;
226 int done_main_member;
227 int share_mode;
228 int in_input_cu_file;
229 } ctf_link_in_member_cb_arg_t;
230
231 /* Link one type into the link. We rely on ctf_add_type() to detect
232 duplicates. This is not terribly reliable yet (unnmamed types will be
233 mindlessly duplicated), but will improve shortly. */
234
235 static int
236 ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
237 {
238 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
239 ctf_file_t *per_cu_out_fp;
240 int err;
241
242 if (arg->share_mode != CTF_LINK_SHARE_UNCONFLICTED)
243 {
244 ctf_dprintf ("Share-duplicated mode not yet implemented.\n");
245 return ctf_set_errno (arg->out_fp, ECTF_NOTYET);
246 }
247
248 /* Simply call ctf_add_type: if it reports a conflict and we're adding to the
249 main CTF file, add to the per-CU archive member instead, creating it if
250 necessary. If we got this type from a per-CU archive member, add it
251 straight back to the corresponding member in the output. */
252
253 if (!arg->in_input_cu_file)
254 {
255 if (ctf_add_type (arg->out_fp, arg->in_fp, type) != CTF_ERR)
256 return 0;
257
258 err = ctf_errno (arg->out_fp);
259 if (err != ECTF_CONFLICT)
260 {
261 ctf_dprintf ("Cannot link type %lx from archive member %s, input file %s "
262 "into output link: %s\n", type, arg->arcname, arg->file_name,
263 ctf_errmsg (err));
264 return -1;
265 }
266 ctf_set_errno (arg->out_fp, 0);
267 }
268
269 if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->arcname,
270 arg->cu_name)) == NULL)
271 return -1; /* Errno is set for us. */
272
273 if (ctf_add_type (per_cu_out_fp, arg->in_fp, type) != CTF_ERR)
274 return 0;
275
276 err = ctf_errno (per_cu_out_fp);
277 if (err == ECTF_CONFLICT)
278 /* Conflicts are possible at this stage only if a non-ld user has combined
279 multiple TUs into a single output dictionary. Even in this case we do not
280 want to stop the link or propagate the error. */
281 ctf_set_errno (arg->out_fp, 0);
282
283 return 0; /* As above: do not lose types. */
284 }
285
286 /* Check if we can safely add a variable with the given type to this container. */
287
288 static int
289 check_variable (const char *name, ctf_file_t *fp, ctf_id_t type,
290 ctf_dvdef_t **out_dvd)
291 {
292 ctf_dvdef_t *dvd;
293
294 dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name);
295 *out_dvd = dvd;
296 if (!dvd)
297 return 1;
298
299 if (dvd->dvd_type != type)
300 {
301 /* Variable here. Wrong type: cannot add. Just skip it, because there is
302 no way to express this in CTF. (This might be the parent, in which
303 case we'll try adding in the child first, and only then give up.) */
304 ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name);
305 }
306
307 return 0; /* Already exists. */
308 }
309
310 /* Link one variable in. */
311
312 static int
313 ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
314 {
315 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
316 ctf_file_t *per_cu_out_fp;
317 ctf_id_t dst_type = 0;
318 ctf_file_t *check_fp;
319 ctf_dvdef_t *dvd;
320
321 /* In unconflicted link mode, if this type is mapped to a type in the parent
322 container, we want to try to add to that first: if it reports a duplicate,
323 or if the type is in a child already, add straight to the child. */
324
325 check_fp = arg->out_fp;
326
327 dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
328 if (dst_type != 0)
329 {
330 if (check_fp == arg->out_fp)
331 {
332 if (check_variable (name, check_fp, dst_type, &dvd))
333 {
334 /* No variable here: we can add it. */
335 if (ctf_add_variable (check_fp, name, dst_type) < 0)
336 return (ctf_set_errno (arg->out_fp, ctf_errno (check_fp)));
337 return 0;
338 }
339
340 /* Already present? Nothing to do. */
341 if (dvd && dvd->dvd_type == type)
342 return 0;
343 }
344 }
345
346 /* Can't add to the parent due to a name clash, or because it references a
347 type only present in the child. Try adding to the child, creating if need
348 be. */
349
350 if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->arcname,
351 arg->cu_name)) == NULL)
352 return -1; /* Errno is set for us. */
353
354 /* If the type was not found, check for it in the child too. */
355 if (dst_type == 0)
356 {
357 check_fp = per_cu_out_fp;
358 dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
359
360 if (dst_type == 0)
361 {
362 ctf_dprintf ("Type %lx for variable %s in input file %s not "
363 "found: skipped.\n", type, name, arg->file_name);
364 /* Do not terminate the link: just skip the variable. */
365 return 0;
366 }
367 }
368
369 if (check_variable (name, per_cu_out_fp, dst_type, &dvd))
370 if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0)
371 return (ctf_set_errno (arg->out_fp, ctf_errno (per_cu_out_fp)));
372 return 0;
373 }
374
375 /* Merge every type and variable in this archive member into the link, so we can
376 relink things that have already had ld run on them. We use the archive
377 member name, sans any leading '.ctf.', as the CU name for ambiguous types if
378 there is one and it's not the default: otherwise, we use the name of the
379 input file. */
380 static int
381 ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *arg_)
382 {
383 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
384 int err = 0;
385
386 if (strcmp (name, _CTF_SECTION) == 0)
387 {
388 /* This file is the default member of this archive, and has already been
389 explicitly processed.
390
391 In the default sharing mode of CTF_LINK_SHARE_UNCONFLICTED, it does no
392 harm to rescan an existing shared repo again: all the types will just
393 end up in the same place. But in CTF_LINK_SHARE_DUPLICATED mode, this
394 causes the system to erroneously conclude that all types are duplicated
395 and should be shared, even if they are not. */
396
397 if (arg->done_main_member)
398 return 0;
399 arg->arcname = strdup (".ctf.");
400 if (arg->arcname)
401 {
402 char *new_name;
403
404 new_name = ctf_str_append (arg->arcname, arg->file_name);
405 if (new_name)
406 arg->arcname = new_name;
407 else
408 free (arg->arcname);
409 }
410 }
411 else
412 {
413 arg->arcname = strdup (name);
414
415 /* Get ambiguous types from our parent. */
416 ctf_import (in_fp, arg->main_input_fp);
417 arg->in_input_cu_file = 1;
418 }
419
420 if (!arg->arcname)
421 return ctf_set_errno (in_fp, ENOMEM);
422
423 arg->cu_name = name;
424 if (strncmp (arg->cu_name, ".ctf.", strlen (".ctf.")) == 0)
425 arg->cu_name += strlen (".ctf.");
426 arg->in_fp = in_fp;
427
428 if ((err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg)) > -1)
429 err = ctf_variable_iter (in_fp, ctf_link_one_variable, arg);
430
431 arg->in_input_cu_file = 0;
432 free (arg->arcname);
433
434 if (err < 0)
435 return -1; /* Errno is set for us. */
436
437 return 0;
438 }
439
440 /* Dump the unnecessary link type mapping after one input file is processed. */
441 static void
442 empty_link_type_mapping (void *key _libctf_unused_, void *value,
443 void *arg _libctf_unused_)
444 {
445 ctf_file_t *fp = (ctf_file_t *) value;
446
447 if (fp->ctf_link_type_mapping)
448 ctf_dynhash_empty (fp->ctf_link_type_mapping);
449 }
450
451 /* Link one input file's types into the output file. */
452 static void
453 ctf_link_one_input_archive (void *key, void *value, void *arg_)
454 {
455 const char *file_name = (const char *) key;
456 ctf_archive_t *arc = (ctf_archive_t *) value;
457 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
458 int err;
459
460 arg->file_name = file_name;
461 arg->done_main_member = 0;
462 if ((arg->main_input_fp = ctf_arc_open_by_name (arc, NULL, &err)) == NULL)
463 if (err != ECTF_ARNNAME)
464 {
465 ctf_dprintf ("Cannot open main archive member in input file %s in the "
466 "link: skipping: %s.\n", arg->file_name,
467 ctf_errmsg (err));
468 return;
469 }
470
471 if (ctf_link_one_input_archive_member (arg->main_input_fp,
472 _CTF_SECTION, arg) < 0)
473 {
474 ctf_file_close (arg->main_input_fp);
475 return;
476 }
477 arg->done_main_member = 1;
478 if (ctf_archive_iter (arc, ctf_link_one_input_archive_member, arg) < 0)
479 ctf_dprintf ("Cannot traverse archive in input file %s: link "
480 "cannot continue: %s.\n", arg->file_name,
481 ctf_errmsg (ctf_errno (arg->out_fp)));
482 else
483 {
484 /* The only error indication to the caller is the errno: so ensure that it
485 is zero if there was no actual error from the caller. */
486 ctf_set_errno (arg->out_fp, 0);
487 }
488 ctf_file_close (arg->main_input_fp);
489
490 /* Discard the now-unnecessary mapping table data. */
491 if (arg->out_fp->ctf_link_type_mapping)
492 ctf_dynhash_empty (arg->out_fp->ctf_link_type_mapping);
493 ctf_dynhash_iter (arg->out_fp->ctf_link_outputs, empty_link_type_mapping, NULL);
494 }
495
496 /* Merge types and variable sections in all files added to the link
497 together. */
498 int
499 ctf_link (ctf_file_t *fp, int share_mode)
500 {
501 ctf_link_in_member_cb_arg_t arg;
502
503 memset (&arg, 0, sizeof (struct ctf_link_in_member_cb_arg));
504 arg.out_fp = fp;
505 arg.share_mode = share_mode;
506
507 if (fp->ctf_link_inputs == NULL)
508 return 0; /* Nothing to do. */
509
510 if (fp->ctf_link_outputs == NULL)
511 fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
512 ctf_hash_eq_string, free,
513 ctf_file_close_thunk);
514
515 if (fp->ctf_link_outputs == NULL)
516 return ctf_set_errno (fp, ENOMEM);
517
518 ctf_dynhash_iter (fp->ctf_link_inputs, ctf_link_one_input_archive,
519 &arg);
520
521 if (ctf_errno (fp) != 0)
522 return -1;
523 return 0;
524 }
525
526 typedef struct ctf_link_out_string_cb_arg
527 {
528 const char *str;
529 uint32_t offset;
530 int err;
531 } ctf_link_out_string_cb_arg_t;
532
533 /* Intern a string in the string table of an output per-CU CTF file. */
534 static void
535 ctf_link_intern_extern_string (void *key _libctf_unused_, void *value,
536 void *arg_)
537 {
538 ctf_file_t *fp = (ctf_file_t *) value;
539 ctf_link_out_string_cb_arg_t *arg = (ctf_link_out_string_cb_arg_t *) arg_;
540
541 fp->ctf_flags |= LCTF_DIRTY;
542 if (ctf_str_add_external (fp, arg->str, arg->offset) == NULL)
543 arg->err = ENOMEM;
544 }
545
546 /* Repeatedly call ADD_STRING to acquire strings from the external string table,
547 adding them to the atoms table for this CU and all subsidiary CUs.
548
549 If ctf_link() is also called, it must be called first if you want the new CTF
550 files ctf_link() can create to get their strings dedupped against the ELF
551 strtab properly. */
552 int
553 ctf_link_add_strtab (ctf_file_t *fp, ctf_link_strtab_string_f *add_string,
554 void *arg)
555 {
556 const char *str;
557 uint32_t offset;
558 int err = 0;
559
560 while ((str = add_string (&offset, arg)) != NULL)
561 {
562 ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 };
563
564 fp->ctf_flags |= LCTF_DIRTY;
565 if (ctf_str_add_external (fp, str, offset) == NULL)
566 err = ENOMEM;
567
568 ctf_dynhash_iter (fp->ctf_link_outputs, ctf_link_intern_extern_string,
569 &iter_arg);
570 if (iter_arg.err)
571 err = iter_arg.err;
572 }
573
574 return -err;
575 }
576
577 /* Not yet implemented. */
578 int
579 ctf_link_shuffle_syms (ctf_file_t *fp _libctf_unused_,
580 ctf_link_iter_symbol_f *add_sym _libctf_unused_,
581 void *arg _libctf_unused_)
582 {
583 return 0;
584 }
585
586 typedef struct ctf_name_list_accum_cb_arg
587 {
588 char **names;
589 ctf_file_t *fp;
590 ctf_file_t **files;
591 size_t i;
592 } ctf_name_list_accum_cb_arg_t;
593
594 /* Accumulate the names and a count of the names in the link output hash,
595 and run ctf_update() on them to generate them. */
596 static void
597 ctf_accumulate_archive_names (void *key, void *value, void *arg_)
598 {
599 const char *name = (const char *) key;
600 ctf_file_t *fp = (ctf_file_t *) value;
601 char **names;
602 ctf_file_t **files;
603 ctf_name_list_accum_cb_arg_t *arg = (ctf_name_list_accum_cb_arg_t *) arg_;
604 int err;
605
606 if ((err = ctf_update (fp)) < 0)
607 {
608 ctf_set_errno (arg->fp, ctf_errno (fp));
609 return;
610 }
611
612 if ((names = realloc (arg->names, sizeof (char *) * ++(arg->i))) == NULL)
613 {
614 (arg->i)--;
615 ctf_set_errno (arg->fp, ENOMEM);
616 return;
617 }
618
619 if ((files = realloc (arg->files, sizeof (ctf_file_t *) * arg->i)) == NULL)
620 {
621 (arg->i)--;
622 ctf_set_errno (arg->fp, ENOMEM);
623 return;
624 }
625 arg->names = names;
626 arg->names[(arg->i) - 1] = (char *) name;
627 arg->files = files;
628 arg->files[(arg->i) - 1] = fp;
629 }
630
631 /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file
632 (otherwise) into a new dynamically-allocated string, and return it.
633 Members with sizes above THRESHOLD are compressed. */
634 unsigned char *
635 ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
636 {
637 ctf_name_list_accum_cb_arg_t arg;
638 char **names;
639 ctf_file_t **files;
640 FILE *f = NULL;
641 int err;
642 long fsize;
643 const char *errloc;
644 unsigned char *buf = NULL;
645
646 memset (&arg, 0, sizeof (ctf_name_list_accum_cb_arg_t));
647 arg.fp = fp;
648
649 if (ctf_update (fp) < 0)
650 {
651 errloc = "CTF file construction";
652 goto err;
653 }
654
655 if (fp->ctf_link_outputs)
656 {
657 ctf_dynhash_iter (fp->ctf_link_outputs, ctf_accumulate_archive_names, &arg);
658 if (ctf_errno (fp) < 0)
659 {
660 errloc = "hash creation";
661 goto err;
662 }
663 }
664
665 /* No extra outputs? Just write a simple ctf_file_t. */
666 if (arg.i == 0)
667 return ctf_write_mem (fp, size, threshold);
668
669 /* Writing an archive. Stick ourselves (the shared repository, parent of all
670 other archives) on the front of it with the default name. */
671 if ((names = realloc (arg.names, sizeof (char *) * (arg.i + 1))) == NULL)
672 {
673 errloc = "name reallocation";
674 goto err_no;
675 }
676 arg.names = names;
677 memmove (&(arg.names[1]), arg.names, sizeof (char *) * (arg.i));
678 arg.names[0] = (char *) _CTF_SECTION;
679
680 if ((files = realloc (arg.files,
681 sizeof (struct ctf_file *) * (arg.i + 1))) == NULL)
682 {
683 errloc = "ctf_file reallocation";
684 goto err_no;
685 }
686 arg.files = files;
687 memmove (&(arg.files[1]), arg.files, sizeof (ctf_file_t *) * (arg.i));
688 arg.files[0] = fp;
689
690 if ((f = tmpfile ()) == NULL)
691 {
692 errloc = "tempfile creation";
693 goto err_no;
694 }
695
696 if ((err = ctf_arc_write_fd (fileno (f), arg.files, arg.i + 1,
697 (const char **) arg.names,
698 threshold)) < 0)
699 {
700 errloc = "archive writing";
701 ctf_set_errno (fp, err);
702 goto err;
703 }
704
705 if (fseek (f, 0, SEEK_END) < 0)
706 {
707 errloc = "seeking to end";
708 goto err_no;
709 }
710
711 if ((fsize = ftell (f)) < 0)
712 {
713 errloc = "filesize determination";
714 goto err_no;
715 }
716
717 if (fseek (f, 0, SEEK_SET) < 0)
718 {
719 errloc = "filepos resetting";
720 goto err_no;
721 }
722
723 if ((buf = malloc (fsize)) == NULL)
724 {
725 errloc = "CTF archive buffer allocation";
726 goto err_no;
727 }
728
729 while (!feof (f) && fread (buf, fsize, 1, f) == 0)
730 if (ferror (f))
731 {
732 errloc = "reading archive from temporary file";
733 goto err_no;
734 }
735
736 *size = fsize;
737 free (arg.names);
738 free (arg.files);
739 return buf;
740
741 err_no:
742 ctf_set_errno (fp, errno);
743 err:
744 free (buf);
745 if (f)
746 fclose (f);
747 free (arg.names);
748 free (arg.files);
749 ctf_dprintf ("Cannot write archive in link: %s failure: %s\n", errloc,
750 ctf_errmsg (ctf_errno (fp)));
751 return NULL;
752 }
This page took 0.073774 seconds and 5 git commands to generate.