]> Git Repo - binutils.git/blob - libctf/ctf-link.c
libctf: add linking of the variable section
[binutils.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.067499 seconds and 4 git commands to generate.