libctf: add CU-mapping machinery
[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 const char *ctf_name = NULL;
186 char *dynname = NULL;
187
188 /* First, check the mapping table and translate the per-CU name we use
189 accordingly. We check both the input filename and the CU name. Only if
190 neither are set do we fall back to the input filename as the per-CU
191 dictionary name. We prefer the filename because this is easier for likely
192 callers to determine. */
193
194 if (fp->ctf_link_cu_mapping)
195 {
196 if (((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, filename)) == NULL) &&
197 ((ctf_name = ctf_dynhash_lookup (fp->ctf_link_cu_mapping, cuname)) == NULL))
198 ctf_name = filename;
199 }
200
201 if (ctf_name == NULL)
202 ctf_name = filename;
203
204 if ((cu_fp = ctf_dynhash_lookup (fp->ctf_link_outputs, ctf_name)) == NULL)
205 {
206 int err;
207
208 if ((cu_fp = ctf_create (&err)) == NULL)
209 {
210 ctf_dprintf ("Cannot create per-CU CTF archive for CU %s from "
211 "input file %s: %s\n", cuname, filename,
212 ctf_errmsg (err));
213 ctf_set_errno (fp, err);
214 return NULL;
215 }
216
217 if ((dynname = strdup (ctf_name)) == NULL)
218 goto oom;
219 if (ctf_dynhash_insert (fp->ctf_link_outputs, dynname, cu_fp) < 0)
220 goto oom;
221
222 ctf_import (cu_fp, fp);
223 ctf_cuname_set (cu_fp, cuname);
224 ctf_parent_name_set (cu_fp, _CTF_SECTION);
225 }
226 return cu_fp;
227
228 oom:
229 free (dynname);
230 ctf_file_close (cu_fp);
231 ctf_set_errno (fp, ENOMEM);
232 return NULL;
233 }
234
235 /* Add a mapping directing that the CU named FROM should have its
236 conflicting/non-duplicate types (depending on link mode) go into a container
237 named TO. Many FROMs can share a TO: in this case, the effect on conflicting
238 types is not yet defined (but in time an auto-renaming algorithm will be
239 added: ugly, but there is really no right thing one can do in this
240 situation).
241
242 We forcibly add a container named TO in every case, even though it may well
243 wind up empty, because clients that use this facility usually expect to find
244 every TO container present, even if empty, and malfunction otherwise. */
245
246 int
247 ctf_link_add_cu_mapping (ctf_file_t *fp, const char *from, const char *to)
248 {
249 int err;
250 char *f, *t;
251
252 if (fp->ctf_link_cu_mapping == NULL)
253 fp->ctf_link_cu_mapping = ctf_dynhash_create (ctf_hash_string,
254 ctf_hash_eq_string, free,
255 free);
256 if (fp->ctf_link_cu_mapping == NULL)
257 return ctf_set_errno (fp, ENOMEM);
258
259 if (fp->ctf_link_outputs == NULL)
260 fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
261 ctf_hash_eq_string, free,
262 ctf_file_close_thunk);
263
264 if (fp->ctf_link_outputs == NULL)
265 return ctf_set_errno (fp, ENOMEM);
266
267 f = strdup (from);
268 t = strdup (to);
269 if (!f || !t)
270 goto oom;
271
272 if (ctf_create_per_cu (fp, t, t) == NULL)
273 goto oom_noerrno; /* Errno is set for us. */
274
275 err = ctf_dynhash_insert (fp->ctf_link_cu_mapping, f, t);
276 if (err)
277 {
278 ctf_set_errno (fp, err);
279 goto oom_noerrno;
280 }
281
282 return 0;
283
284 oom:
285 ctf_set_errno (fp, errno);
286 oom_noerrno:
287 free (f);
288 free (t);
289 return -1;
290 }
291
292 /* Set a function which is called to transform the names of archive members.
293 This is useful for applying regular transformations to many names, where
294 ctf_link_add_cu_mapping applies arbitrarily irregular changes to single
295 names. The member name changer is applied at ctf_link_write time, so it
296 cannot conflate multiple CUs into one the way ctf_link_add_cu_mapping can.
297 The changer function accepts a name and should return a new
298 dynamically-allocated name, or NULL if the name should be left unchanged. */
299 void
300 ctf_link_set_memb_name_changer (ctf_file_t *fp,
301 ctf_link_memb_name_changer_f *changer,
302 void *arg)
303 {
304 fp->ctf_link_memb_name_changer = changer;
305 fp->ctf_link_memb_name_changer_arg = arg;
306 }
307
308 typedef struct ctf_link_in_member_cb_arg
309 {
310 ctf_file_t *out_fp;
311 const char *file_name;
312 ctf_file_t *in_fp;
313 ctf_file_t *main_input_fp;
314 const char *cu_name;
315 char *arcname;
316 int done_main_member;
317 int share_mode;
318 int in_input_cu_file;
319 } ctf_link_in_member_cb_arg_t;
320
321 /* Link one type into the link. We rely on ctf_add_type() to detect
322 duplicates. This is not terribly reliable yet (unnmamed types will be
323 mindlessly duplicated), but will improve shortly. */
324
325 static int
326 ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
327 {
328 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
329 ctf_file_t *per_cu_out_fp;
330 int err;
331
332 if (arg->share_mode != CTF_LINK_SHARE_UNCONFLICTED)
333 {
334 ctf_dprintf ("Share-duplicated mode not yet implemented.\n");
335 return ctf_set_errno (arg->out_fp, ECTF_NOTYET);
336 }
337
338 /* Simply call ctf_add_type: if it reports a conflict and we're adding to the
339 main CTF file, add to the per-CU archive member instead, creating it if
340 necessary. If we got this type from a per-CU archive member, add it
341 straight back to the corresponding member in the output. */
342
343 if (!arg->in_input_cu_file)
344 {
345 if (ctf_add_type (arg->out_fp, arg->in_fp, type) != CTF_ERR)
346 return 0;
347
348 err = ctf_errno (arg->out_fp);
349 if (err != ECTF_CONFLICT)
350 {
351 ctf_dprintf ("Cannot link type %lx from archive member %s, input file %s "
352 "into output link: %s\n", type, arg->arcname, arg->file_name,
353 ctf_errmsg (err));
354 return -1;
355 }
356 ctf_set_errno (arg->out_fp, 0);
357 }
358
359 if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->file_name,
360 arg->cu_name)) == NULL)
361 return -1; /* Errno is set for us. */
362
363 if (ctf_add_type (per_cu_out_fp, arg->in_fp, type) != CTF_ERR)
364 return 0;
365
366 err = ctf_errno (per_cu_out_fp);
367 if (err == ECTF_CONFLICT)
368 /* Conflicts are possible at this stage only if a non-ld user has combined
369 multiple TUs into a single output dictionary. Even in this case we do not
370 want to stop the link or propagate the error. */
371 ctf_set_errno (arg->out_fp, 0);
372
373 return 0; /* As above: do not lose types. */
374 }
375
376 /* Check if we can safely add a variable with the given type to this container. */
377
378 static int
379 check_variable (const char *name, ctf_file_t *fp, ctf_id_t type,
380 ctf_dvdef_t **out_dvd)
381 {
382 ctf_dvdef_t *dvd;
383
384 dvd = ctf_dynhash_lookup (fp->ctf_dvhash, name);
385 *out_dvd = dvd;
386 if (!dvd)
387 return 1;
388
389 if (dvd->dvd_type != type)
390 {
391 /* Variable here. Wrong type: cannot add. Just skip it, because there is
392 no way to express this in CTF. (This might be the parent, in which
393 case we'll try adding in the child first, and only then give up.) */
394 ctf_dprintf ("Inexpressible duplicate variable %s skipped.\n", name);
395 }
396
397 return 0; /* Already exists. */
398 }
399
400 /* Link one variable in. */
401
402 static int
403 ctf_link_one_variable (const char *name, ctf_id_t type, void *arg_)
404 {
405 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
406 ctf_file_t *per_cu_out_fp;
407 ctf_id_t dst_type = 0;
408 ctf_file_t *check_fp;
409 ctf_dvdef_t *dvd;
410
411 /* In unconflicted link mode, if this type is mapped to a type in the parent
412 container, we want to try to add to that first: if it reports a duplicate,
413 or if the type is in a child already, add straight to the child. */
414
415 check_fp = arg->out_fp;
416
417 dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
418 if (dst_type != 0)
419 {
420 if (check_fp == arg->out_fp)
421 {
422 if (check_variable (name, check_fp, dst_type, &dvd))
423 {
424 /* No variable here: we can add it. */
425 if (ctf_add_variable (check_fp, name, dst_type) < 0)
426 return (ctf_set_errno (arg->out_fp, ctf_errno (check_fp)));
427 return 0;
428 }
429
430 /* Already present? Nothing to do. */
431 if (dvd && dvd->dvd_type == type)
432 return 0;
433 }
434 }
435
436 /* Can't add to the parent due to a name clash, or because it references a
437 type only present in the child. Try adding to the child, creating if need
438 be. */
439
440 if ((per_cu_out_fp = ctf_create_per_cu (arg->out_fp, arg->file_name,
441 arg->cu_name)) == NULL)
442 return -1; /* Errno is set for us. */
443
444 /* If the type was not found, check for it in the child too. */
445 if (dst_type == 0)
446 {
447 check_fp = per_cu_out_fp;
448 dst_type = ctf_type_mapping (arg->in_fp, type, &check_fp);
449
450 if (dst_type == 0)
451 {
452 ctf_dprintf ("Type %lx for variable %s in input file %s not "
453 "found: skipped.\n", type, name, arg->file_name);
454 /* Do not terminate the link: just skip the variable. */
455 return 0;
456 }
457 }
458
459 if (check_variable (name, per_cu_out_fp, dst_type, &dvd))
460 if (ctf_add_variable (per_cu_out_fp, name, dst_type) < 0)
461 return (ctf_set_errno (arg->out_fp, ctf_errno (per_cu_out_fp)));
462 return 0;
463 }
464
465 /* Merge every type and variable in this archive member into the link, so we can
466 relink things that have already had ld run on them. We use the archive
467 member name, sans any leading '.ctf.', as the CU name for ambiguous types if
468 there is one and it's not the default: otherwise, we use the name of the
469 input file. */
470 static int
471 ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *arg_)
472 {
473 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
474 int err = 0;
475
476 if (strcmp (name, _CTF_SECTION) == 0)
477 {
478 /* This file is the default member of this archive, and has already been
479 explicitly processed.
480
481 In the default sharing mode of CTF_LINK_SHARE_UNCONFLICTED, it does no
482 harm to rescan an existing shared repo again: all the types will just
483 end up in the same place. But in CTF_LINK_SHARE_DUPLICATED mode, this
484 causes the system to erroneously conclude that all types are duplicated
485 and should be shared, even if they are not. */
486
487 if (arg->done_main_member)
488 return 0;
489 arg->arcname = strdup (".ctf.");
490 if (arg->arcname)
491 {
492 char *new_name;
493
494 new_name = ctf_str_append (arg->arcname, arg->file_name);
495 if (new_name)
496 arg->arcname = new_name;
497 else
498 free (arg->arcname);
499 }
500 }
501 else
502 {
503 arg->arcname = strdup (name);
504
505 /* Get ambiguous types from our parent. */
506 ctf_import (in_fp, arg->main_input_fp);
507 arg->in_input_cu_file = 1;
508 }
509
510 if (!arg->arcname)
511 return ctf_set_errno (in_fp, ENOMEM);
512
513 arg->cu_name = name;
514 if (strncmp (arg->cu_name, ".ctf.", strlen (".ctf.")) == 0)
515 arg->cu_name += strlen (".ctf.");
516 arg->in_fp = in_fp;
517
518 if ((err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg)) > -1)
519 err = ctf_variable_iter (in_fp, ctf_link_one_variable, arg);
520
521 arg->in_input_cu_file = 0;
522 free (arg->arcname);
523
524 if (err < 0)
525 return -1; /* Errno is set for us. */
526
527 return 0;
528 }
529
530 /* Dump the unnecessary link type mapping after one input file is processed. */
531 static void
532 empty_link_type_mapping (void *key _libctf_unused_, void *value,
533 void *arg _libctf_unused_)
534 {
535 ctf_file_t *fp = (ctf_file_t *) value;
536
537 if (fp->ctf_link_type_mapping)
538 ctf_dynhash_empty (fp->ctf_link_type_mapping);
539 }
540
541 /* Link one input file's types into the output file. */
542 static void
543 ctf_link_one_input_archive (void *key, void *value, void *arg_)
544 {
545 const char *file_name = (const char *) key;
546 ctf_archive_t *arc = (ctf_archive_t *) value;
547 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
548 int err;
549
550 arg->file_name = file_name;
551 arg->done_main_member = 0;
552 if ((arg->main_input_fp = ctf_arc_open_by_name (arc, NULL, &err)) == NULL)
553 if (err != ECTF_ARNNAME)
554 {
555 ctf_dprintf ("Cannot open main archive member in input file %s in the "
556 "link: skipping: %s.\n", arg->file_name,
557 ctf_errmsg (err));
558 return;
559 }
560
561 if (ctf_link_one_input_archive_member (arg->main_input_fp,
562 _CTF_SECTION, arg) < 0)
563 {
564 ctf_file_close (arg->main_input_fp);
565 return;
566 }
567 arg->done_main_member = 1;
568 if (ctf_archive_iter (arc, ctf_link_one_input_archive_member, arg) < 0)
569 ctf_dprintf ("Cannot traverse archive in input file %s: link "
570 "cannot continue: %s.\n", arg->file_name,
571 ctf_errmsg (ctf_errno (arg->out_fp)));
572 else
573 {
574 /* The only error indication to the caller is the errno: so ensure that it
575 is zero if there was no actual error from the caller. */
576 ctf_set_errno (arg->out_fp, 0);
577 }
578 ctf_file_close (arg->main_input_fp);
579
580 /* Discard the now-unnecessary mapping table data. */
581 if (arg->out_fp->ctf_link_type_mapping)
582 ctf_dynhash_empty (arg->out_fp->ctf_link_type_mapping);
583 ctf_dynhash_iter (arg->out_fp->ctf_link_outputs, empty_link_type_mapping, NULL);
584 }
585
586 /* Merge types and variable sections in all files added to the link
587 together. */
588 int
589 ctf_link (ctf_file_t *fp, int share_mode)
590 {
591 ctf_link_in_member_cb_arg_t arg;
592
593 memset (&arg, 0, sizeof (struct ctf_link_in_member_cb_arg));
594 arg.out_fp = fp;
595 arg.share_mode = share_mode;
596
597 if (fp->ctf_link_inputs == NULL)
598 return 0; /* Nothing to do. */
599
600 if (fp->ctf_link_outputs == NULL)
601 fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
602 ctf_hash_eq_string, free,
603 ctf_file_close_thunk);
604
605 if (fp->ctf_link_outputs == NULL)
606 return ctf_set_errno (fp, ENOMEM);
607
608 ctf_dynhash_iter (fp->ctf_link_inputs, ctf_link_one_input_archive,
609 &arg);
610
611 if (ctf_errno (fp) != 0)
612 return -1;
613 return 0;
614 }
615
616 typedef struct ctf_link_out_string_cb_arg
617 {
618 const char *str;
619 uint32_t offset;
620 int err;
621 } ctf_link_out_string_cb_arg_t;
622
623 /* Intern a string in the string table of an output per-CU CTF file. */
624 static void
625 ctf_link_intern_extern_string (void *key _libctf_unused_, void *value,
626 void *arg_)
627 {
628 ctf_file_t *fp = (ctf_file_t *) value;
629 ctf_link_out_string_cb_arg_t *arg = (ctf_link_out_string_cb_arg_t *) arg_;
630
631 fp->ctf_flags |= LCTF_DIRTY;
632 if (ctf_str_add_external (fp, arg->str, arg->offset) == NULL)
633 arg->err = ENOMEM;
634 }
635
636 /* Repeatedly call ADD_STRING to acquire strings from the external string table,
637 adding them to the atoms table for this CU and all subsidiary CUs.
638
639 If ctf_link() is also called, it must be called first if you want the new CTF
640 files ctf_link() can create to get their strings dedupped against the ELF
641 strtab properly. */
642 int
643 ctf_link_add_strtab (ctf_file_t *fp, ctf_link_strtab_string_f *add_string,
644 void *arg)
645 {
646 const char *str;
647 uint32_t offset;
648 int err = 0;
649
650 while ((str = add_string (&offset, arg)) != NULL)
651 {
652 ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 };
653
654 fp->ctf_flags |= LCTF_DIRTY;
655 if (ctf_str_add_external (fp, str, offset) == NULL)
656 err = ENOMEM;
657
658 ctf_dynhash_iter (fp->ctf_link_outputs, ctf_link_intern_extern_string,
659 &iter_arg);
660 if (iter_arg.err)
661 err = iter_arg.err;
662 }
663
664 return -err;
665 }
666
667 /* Not yet implemented. */
668 int
669 ctf_link_shuffle_syms (ctf_file_t *fp _libctf_unused_,
670 ctf_link_iter_symbol_f *add_sym _libctf_unused_,
671 void *arg _libctf_unused_)
672 {
673 return 0;
674 }
675
676 typedef struct ctf_name_list_accum_cb_arg
677 {
678 char **names;
679 ctf_file_t *fp;
680 ctf_file_t **files;
681 size_t i;
682 char **dynames;
683 size_t ndynames;
684 } ctf_name_list_accum_cb_arg_t;
685
686 /* Accumulate the names and a count of the names in the link output hash,
687 and run ctf_update() on them to generate them. */
688 static void
689 ctf_accumulate_archive_names (void *key, void *value, void *arg_)
690 {
691 const char *name = (const char *) key;
692 ctf_file_t *fp = (ctf_file_t *) value;
693 char **names;
694 ctf_file_t **files;
695 ctf_name_list_accum_cb_arg_t *arg = (ctf_name_list_accum_cb_arg_t *) arg_;
696 int err;
697
698 if ((err = ctf_update (fp)) < 0)
699 {
700 ctf_set_errno (arg->fp, ctf_errno (fp));
701 return;
702 }
703
704 if ((names = realloc (arg->names, sizeof (char *) * ++(arg->i))) == NULL)
705 {
706 (arg->i)--;
707 ctf_set_errno (arg->fp, ENOMEM);
708 return;
709 }
710
711 if ((files = realloc (arg->files, sizeof (ctf_file_t *) * arg->i)) == NULL)
712 {
713 (arg->i)--;
714 ctf_set_errno (arg->fp, ENOMEM);
715 return;
716 }
717
718 /* Allow the caller to get in and modify the name at the last minute. If the
719 caller *does* modify the name, we have to stash away the new name the
720 caller returned so we can free it later on. (The original name is the key
721 of the ctf_link_outputs hash and is freed by the dynhash machinery.) */
722
723 if (fp->ctf_link_memb_name_changer)
724 {
725 char **dynames;
726 char *dyname;
727 void *nc_arg = fp->ctf_link_memb_name_changer_arg;
728
729 dyname = fp->ctf_link_memb_name_changer (fp, name, nc_arg);
730
731 if (dyname != NULL)
732 {
733 if ((dynames = realloc (arg->dynames,
734 sizeof (char *) * ++(arg->ndynames))) == NULL)
735 {
736 (arg->ndynames)--;
737 ctf_set_errno (arg->fp, ENOMEM);
738 return;
739 }
740 arg->dynames = dynames;
741 name = (const char *) dyname;
742 }
743 }
744
745 arg->names = names;
746 arg->names[(arg->i) - 1] = (char *) name;
747 arg->files = files;
748 arg->files[(arg->i) - 1] = fp;
749 }
750
751 /* Change the name of the parent CTF section, if the name transformer has got to
752 it. */
753 static void
754 ctf_change_parent_name (void *key _libctf_unused_, void *value, void *arg)
755 {
756 ctf_file_t *fp = (ctf_file_t *) value;
757 const char *name = (const char *) arg;
758
759 ctf_parent_name_set (fp, name);
760 }
761
762 /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file
763 (otherwise) into a new dynamically-allocated string, and return it.
764 Members with sizes above THRESHOLD are compressed. */
765 unsigned char *
766 ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
767 {
768 ctf_name_list_accum_cb_arg_t arg;
769 char **names;
770 char *transformed_name = NULL;
771 ctf_file_t **files;
772 FILE *f = NULL;
773 int err;
774 long fsize;
775 const char *errloc;
776 unsigned char *buf = NULL;
777
778 memset (&arg, 0, sizeof (ctf_name_list_accum_cb_arg_t));
779 arg.fp = fp;
780
781 if (ctf_update (fp) < 0)
782 {
783 errloc = "CTF file construction";
784 goto err;
785 }
786
787 if (fp->ctf_link_outputs)
788 {
789 ctf_dynhash_iter (fp->ctf_link_outputs, ctf_accumulate_archive_names, &arg);
790 if (ctf_errno (fp) < 0)
791 {
792 errloc = "hash creation";
793 goto err;
794 }
795 }
796
797 /* No extra outputs? Just write a simple ctf_file_t. */
798 if (arg.i == 0)
799 return ctf_write_mem (fp, size, threshold);
800
801 /* Writing an archive. Stick ourselves (the shared repository, parent of all
802 other archives) on the front of it with the default name. */
803 if ((names = realloc (arg.names, sizeof (char *) * (arg.i + 1))) == NULL)
804 {
805 errloc = "name reallocation";
806 goto err_no;
807 }
808 arg.names = names;
809 memmove (&(arg.names[1]), arg.names, sizeof (char *) * (arg.i));
810
811 arg.names[0] = (char *) _CTF_SECTION;
812 if (fp->ctf_link_memb_name_changer)
813 {
814 void *nc_arg = fp->ctf_link_memb_name_changer_arg;
815
816 transformed_name = fp->ctf_link_memb_name_changer (fp, _CTF_SECTION,
817 nc_arg);
818
819 if (transformed_name != NULL)
820 {
821 arg.names[0] = transformed_name;
822 ctf_dynhash_iter (fp->ctf_link_outputs, ctf_change_parent_name,
823 transformed_name);
824 }
825 }
826
827 if ((files = realloc (arg.files,
828 sizeof (struct ctf_file *) * (arg.i + 1))) == NULL)
829 {
830 errloc = "ctf_file reallocation";
831 goto err_no;
832 }
833 arg.files = files;
834 memmove (&(arg.files[1]), arg.files, sizeof (ctf_file_t *) * (arg.i));
835 arg.files[0] = fp;
836
837 if ((f = tmpfile ()) == NULL)
838 {
839 errloc = "tempfile creation";
840 goto err_no;
841 }
842
843 if ((err = ctf_arc_write_fd (fileno (f), arg.files, arg.i + 1,
844 (const char **) arg.names,
845 threshold)) < 0)
846 {
847 errloc = "archive writing";
848 ctf_set_errno (fp, err);
849 goto err;
850 }
851
852 if (fseek (f, 0, SEEK_END) < 0)
853 {
854 errloc = "seeking to end";
855 goto err_no;
856 }
857
858 if ((fsize = ftell (f)) < 0)
859 {
860 errloc = "filesize determination";
861 goto err_no;
862 }
863
864 if (fseek (f, 0, SEEK_SET) < 0)
865 {
866 errloc = "filepos resetting";
867 goto err_no;
868 }
869
870 if ((buf = malloc (fsize)) == NULL)
871 {
872 errloc = "CTF archive buffer allocation";
873 goto err_no;
874 }
875
876 while (!feof (f) && fread (buf, fsize, 1, f) == 0)
877 if (ferror (f))
878 {
879 errloc = "reading archive from temporary file";
880 goto err_no;
881 }
882
883 *size = fsize;
884 free (arg.names);
885 free (arg.files);
886 free (transformed_name);
887 if (arg.ndynames)
888 {
889 size_t i;
890 for (i = 0; i < arg.ndynames; i++)
891 free (arg.dynames[i]);
892 free (arg.dynames);
893 }
894 return buf;
895
896 err_no:
897 ctf_set_errno (fp, errno);
898 err:
899 free (buf);
900 if (f)
901 fclose (f);
902 free (arg.names);
903 free (arg.files);
904 free (transformed_name);
905 if (arg.ndynames)
906 {
907 size_t i;
908 for (i = 0; i < arg.ndynames; i++)
909 free (arg.dynames[i]);
910 free (arg.dynames);
911 }
912 ctf_dprintf ("Cannot write archive in link: %s failure: %s\n", errloc,
913 ctf_errmsg (ctf_errno (fp)));
914 return NULL;
915 }
This page took 0.048234 seconds and 4 git commands to generate.