libctf: map from old to corresponding newly-added types in ctf_add_type
[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 typedef struct ctf_link_in_member_cb_arg
179 {
180 ctf_file_t *out_fp;
181 const char *file_name;
182 ctf_file_t *in_fp;
183 ctf_file_t *main_input_fp;
184 const char *cu_name;
185 char *arcname;
186 int done_main_member;
187 int share_mode;
188 int in_input_cu_file;
189 } ctf_link_in_member_cb_arg_t;
190
191 /* Link one type into the link. We rely on ctf_add_type() to detect
192 duplicates. This is not terribly reliable yet (unnmamed types will be
193 mindlessly duplicated), but will improve shortly. */
194
195 static int
196 ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_)
197 {
198 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
199 ctf_file_t *per_cu_out_fp;
200 int err;
201
202 if (arg->share_mode != CTF_LINK_SHARE_UNCONFLICTED)
203 {
204 ctf_dprintf ("Share-duplicated mode not yet implemented.\n");
205 return ctf_set_errno (arg->out_fp, ECTF_NOTYET);
206 }
207
208 /* Simply call ctf_add_type: if it reports a conflict and we're adding to the
209 main CTF file, add to the per-CU archive member instead, creating it if
210 necessary. If we got this type from a per-CU archive member, add it
211 straight back to the corresponding member in the output. */
212
213 if (!arg->in_input_cu_file)
214 {
215 if (ctf_add_type (arg->out_fp, arg->in_fp, type) != CTF_ERR)
216 return 0;
217
218 err = ctf_errno (arg->out_fp);
219 if (err != ECTF_CONFLICT)
220 {
221 ctf_dprintf ("Cannot link type %lx from archive member %s, input file %s "
222 "into output link: %s\n", type, arg->arcname, arg->file_name,
223 ctf_errmsg (err));
224 return -1;
225 }
226 ctf_set_errno (arg->out_fp, 0);
227 }
228
229 if ((per_cu_out_fp = ctf_dynhash_lookup (arg->out_fp->ctf_link_outputs,
230 arg->arcname)) == NULL)
231 {
232 int err;
233
234 if ((per_cu_out_fp = ctf_create (&err)) == NULL)
235 {
236 ctf_dprintf ("Cannot create per-CU CTF archive for member %s: %s\n",
237 arg->arcname, ctf_errmsg (err));
238 ctf_set_errno (arg->out_fp, err);
239 return -1;
240 }
241
242 if (ctf_dynhash_insert (arg->out_fp->ctf_link_outputs, arg->arcname,
243 per_cu_out_fp) < 0)
244 {
245 ctf_set_errno (arg->out_fp, ENOMEM);
246 return -1;
247 }
248
249 ctf_import (per_cu_out_fp, arg->out_fp);
250 ctf_cuname_set (per_cu_out_fp, arg->cu_name);
251 }
252
253 if (ctf_add_type (per_cu_out_fp, arg->in_fp, type) != CTF_ERR)
254 return 0;
255
256 err = ctf_errno (per_cu_out_fp);
257 if (err == ECTF_CONFLICT)
258 /* Conflicts are possible at this stage only if a non-ld user has combined
259 multiple TUs into a single output dictionary. Even in this case we do not
260 want to stop the link or propagate the error. */
261 ctf_set_errno (arg->out_fp, 0);
262
263 return 0; /* As above: do not lose types. */
264 }
265
266 /* Merge every type and variable in this archive member into the link, so we can
267 relink things that have already had ld run on them. We use the archive
268 member name, sans any leading '.ctf.', as the CU name for ambiguous types if
269 there is one and it's not the default: otherwise, we use the name of the
270 input file. */
271 static int
272 ctf_link_one_input_archive_member (ctf_file_t *in_fp, const char *name, void *arg_)
273 {
274 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
275 int err = 0;
276
277 if (strcmp (name, _CTF_SECTION) == 0)
278 {
279 /* This file is the default member of this archive, and has already been
280 explicitly processed.
281
282 In the default sharing mode of CTF_LINK_SHARE_UNCONFLICTED, it does no
283 harm to rescan an existing shared repo again: all the types will just
284 end up in the same place. But in CTF_LINK_SHARE_DUPLICATED mode, this
285 causes the system to erroneously conclude that all types are duplicated
286 and should be shared, even if they are not. */
287
288 if (arg->done_main_member)
289 return 0;
290 arg->arcname = strdup (".ctf.");
291 if (arg->arcname)
292 {
293 char *new_name;
294
295 new_name = ctf_str_append (arg->arcname, arg->file_name);
296 if (new_name)
297 arg->arcname = new_name;
298 else
299 free (arg->arcname);
300 }
301 }
302 else
303 {
304 arg->arcname = strdup (name);
305
306 /* Get ambiguous types from our parent. */
307 ctf_import (in_fp, arg->main_input_fp);
308 arg->in_input_cu_file = 1;
309 }
310
311 if (!arg->arcname)
312 return ctf_set_errno (in_fp, ENOMEM);
313
314 arg->cu_name = name;
315 if (strncmp (arg->cu_name, ".ctf.", strlen (".ctf.")) == 0)
316 arg->cu_name += strlen (".ctf.");
317 arg->in_fp = in_fp;
318
319 err = ctf_type_iter_all (in_fp, ctf_link_one_type, arg);
320
321 arg->in_input_cu_file = 0;
322 free (arg->arcname);
323
324 if (err < 0)
325 return -1; /* Errno is set for us. */
326
327 return 0;
328 }
329
330 /* Dump the unnecessary link type mapping after one input file is processed. */
331 static void
332 empty_link_type_mapping (void *key _libctf_unused_, void *value,
333 void *arg _libctf_unused_)
334 {
335 ctf_file_t *fp = (ctf_file_t *) value;
336
337 if (fp->ctf_link_type_mapping)
338 ctf_dynhash_empty (fp->ctf_link_type_mapping);
339 }
340
341 /* Link one input file's types into the output file. */
342 static void
343 ctf_link_one_input_archive (void *key, void *value, void *arg_)
344 {
345 const char *file_name = (const char *) key;
346 ctf_archive_t *arc = (ctf_archive_t *) value;
347 ctf_link_in_member_cb_arg_t *arg = (ctf_link_in_member_cb_arg_t *) arg_;
348 int err;
349
350 arg->file_name = file_name;
351 arg->done_main_member = 0;
352 if ((arg->main_input_fp = ctf_arc_open_by_name (arc, NULL, &err)) == NULL)
353 if (err != ECTF_ARNNAME)
354 {
355 ctf_dprintf ("Cannot open main archive member in input file %s in the "
356 "link: skipping: %s.\n", arg->file_name,
357 ctf_errmsg (err));
358 return;
359 }
360
361 if (ctf_link_one_input_archive_member (arg->main_input_fp,
362 _CTF_SECTION, arg) < 0)
363 {
364 ctf_file_close (arg->main_input_fp);
365 return;
366 }
367 arg->done_main_member = 1;
368 if (ctf_archive_iter (arc, ctf_link_one_input_archive_member, arg) < 0)
369 ctf_dprintf ("Cannot traverse archive in input file %s: link "
370 "cannot continue: %s.\n", arg->file_name,
371 ctf_errmsg (ctf_errno (arg->out_fp)));
372 else
373 {
374 /* The only error indication to the caller is the errno: so ensure that it
375 is zero if there was no actual error from the caller. */
376 ctf_set_errno (arg->out_fp, 0);
377 }
378 ctf_file_close (arg->main_input_fp);
379
380 /* Discard the now-unnecessary mapping table data. */
381 if (arg->out_fp->ctf_link_type_mapping)
382 ctf_dynhash_empty (arg->out_fp->ctf_link_type_mapping);
383 ctf_dynhash_iter (arg->out_fp->ctf_link_outputs, empty_link_type_mapping, NULL);
384 }
385
386 /* Merge types and variable sections in all files added to the link
387 together. */
388 int
389 ctf_link (ctf_file_t *fp, int share_mode)
390 {
391 ctf_link_in_member_cb_arg_t arg;
392
393 memset (&arg, 0, sizeof (struct ctf_link_in_member_cb_arg));
394 arg.out_fp = fp;
395 arg.share_mode = share_mode;
396
397 if (fp->ctf_link_inputs == NULL)
398 return 0; /* Nothing to do. */
399
400 if (fp->ctf_link_outputs == NULL)
401 fp->ctf_link_outputs = ctf_dynhash_create (ctf_hash_string,
402 ctf_hash_eq_string, free,
403 ctf_file_close_thunk);
404
405 if (fp->ctf_link_outputs == NULL)
406 return ctf_set_errno (fp, ENOMEM);
407
408 ctf_dynhash_iter (fp->ctf_link_inputs, ctf_link_one_input_archive,
409 &arg);
410
411 if (ctf_errno (fp) != 0)
412 return -1;
413 return 0;
414 }
415
416 typedef struct ctf_link_out_string_cb_arg
417 {
418 const char *str;
419 uint32_t offset;
420 int err;
421 } ctf_link_out_string_cb_arg_t;
422
423 /* Intern a string in the string table of an output per-CU CTF file. */
424 static void
425 ctf_link_intern_extern_string (void *key _libctf_unused_, void *value,
426 void *arg_)
427 {
428 ctf_file_t *fp = (ctf_file_t *) value;
429 ctf_link_out_string_cb_arg_t *arg = (ctf_link_out_string_cb_arg_t *) arg_;
430
431 fp->ctf_flags |= LCTF_DIRTY;
432 if (ctf_str_add_external (fp, arg->str, arg->offset) == NULL)
433 arg->err = ENOMEM;
434 }
435
436 /* Repeatedly call ADD_STRING to acquire strings from the external string table,
437 adding them to the atoms table for this CU and all subsidiary CUs.
438
439 If ctf_link() is also called, it must be called first if you want the new CTF
440 files ctf_link() can create to get their strings dedupped against the ELF
441 strtab properly. */
442 int
443 ctf_link_add_strtab (ctf_file_t *fp, ctf_link_strtab_string_f *add_string,
444 void *arg)
445 {
446 const char *str;
447 uint32_t offset;
448 int err = 0;
449
450 while ((str = add_string (&offset, arg)) != NULL)
451 {
452 ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 };
453
454 fp->ctf_flags |= LCTF_DIRTY;
455 if (ctf_str_add_external (fp, str, offset) == NULL)
456 err = ENOMEM;
457
458 ctf_dynhash_iter (fp->ctf_link_outputs, ctf_link_intern_extern_string,
459 &iter_arg);
460 if (iter_arg.err)
461 err = iter_arg.err;
462 }
463
464 return -err;
465 }
466
467 /* Not yet implemented. */
468 int
469 ctf_link_shuffle_syms (ctf_file_t *fp _libctf_unused_,
470 ctf_link_iter_symbol_f *add_sym _libctf_unused_,
471 void *arg _libctf_unused_)
472 {
473 return 0;
474 }
475
476 typedef struct ctf_name_list_accum_cb_arg
477 {
478 char **names;
479 ctf_file_t *fp;
480 ctf_file_t **files;
481 size_t i;
482 } ctf_name_list_accum_cb_arg_t;
483
484 /* Accumulate the names and a count of the names in the link output hash,
485 and run ctf_update() on them to generate them. */
486 static void
487 ctf_accumulate_archive_names (void *key, void *value, void *arg_)
488 {
489 const char *name = (const char *) key;
490 ctf_file_t *fp = (ctf_file_t *) value;
491 char **names;
492 ctf_file_t **files;
493 ctf_name_list_accum_cb_arg_t *arg = (ctf_name_list_accum_cb_arg_t *) arg_;
494 int err;
495
496 if ((err = ctf_update (fp)) < 0)
497 {
498 ctf_set_errno (arg->fp, ctf_errno (fp));
499 return;
500 }
501
502 if ((names = realloc (arg->names, sizeof (char *) * ++(arg->i))) == NULL)
503 {
504 (arg->i)--;
505 ctf_set_errno (arg->fp, ENOMEM);
506 return;
507 }
508
509 if ((files = realloc (arg->files, sizeof (ctf_file_t *) * arg->i)) == NULL)
510 {
511 (arg->i)--;
512 ctf_set_errno (arg->fp, ENOMEM);
513 return;
514 }
515 arg->names = names;
516 arg->names[(arg->i) - 1] = (char *) name;
517 arg->files = files;
518 arg->files[(arg->i) - 1] = fp;
519 }
520
521 /* Write out a CTF archive (if there are per-CU CTF files) or a CTF file
522 (otherwise) into a new dynamically-allocated string, and return it.
523 Members with sizes above THRESHOLD are compressed. */
524 unsigned char *
525 ctf_link_write (ctf_file_t *fp, size_t *size, size_t threshold)
526 {
527 ctf_name_list_accum_cb_arg_t arg;
528 char **names;
529 ctf_file_t **files;
530 FILE *f = NULL;
531 int err;
532 long fsize;
533 const char *errloc;
534 unsigned char *buf = NULL;
535
536 memset (&arg, 0, sizeof (ctf_name_list_accum_cb_arg_t));
537 arg.fp = fp;
538
539 if (ctf_update (fp) < 0)
540 {
541 errloc = "CTF file construction";
542 goto err;
543 }
544
545 if (fp->ctf_link_outputs)
546 {
547 ctf_dynhash_iter (fp->ctf_link_outputs, ctf_accumulate_archive_names, &arg);
548 if (ctf_errno (fp) < 0)
549 {
550 errloc = "hash creation";
551 goto err;
552 }
553 }
554
555 /* No extra outputs? Just write a simple ctf_file_t. */
556 if (arg.i == 0)
557 return ctf_write_mem (fp, size, threshold);
558
559 /* Writing an archive. Stick ourselves (the shared repository, parent of all
560 other archives) on the front of it with the default name. */
561 if ((names = realloc (arg.names, sizeof (char *) * (arg.i + 1))) == NULL)
562 {
563 errloc = "name reallocation";
564 goto err_no;
565 }
566 arg.names = names;
567 memmove (&(arg.names[1]), arg.names, sizeof (char *) * (arg.i));
568 arg.names[0] = (char *) _CTF_SECTION;
569
570 if ((files = realloc (arg.files,
571 sizeof (struct ctf_file *) * (arg.i + 1))) == NULL)
572 {
573 errloc = "ctf_file reallocation";
574 goto err_no;
575 }
576 arg.files = files;
577 memmove (&(arg.files[1]), arg.files, sizeof (ctf_file_t *) * (arg.i));
578 arg.files[0] = fp;
579
580 if ((f = tmpfile ()) == NULL)
581 {
582 errloc = "tempfile creation";
583 goto err_no;
584 }
585
586 if ((err = ctf_arc_write_fd (fileno (f), arg.files, arg.i + 1,
587 (const char **) arg.names,
588 threshold)) < 0)
589 {
590 errloc = "archive writing";
591 ctf_set_errno (fp, err);
592 goto err;
593 }
594
595 if (fseek (f, 0, SEEK_END) < 0)
596 {
597 errloc = "seeking to end";
598 goto err_no;
599 }
600
601 if ((fsize = ftell (f)) < 0)
602 {
603 errloc = "filesize determination";
604 goto err_no;
605 }
606
607 if (fseek (f, 0, SEEK_SET) < 0)
608 {
609 errloc = "filepos resetting";
610 goto err_no;
611 }
612
613 if ((buf = malloc (fsize)) == NULL)
614 {
615 errloc = "CTF archive buffer allocation";
616 goto err_no;
617 }
618
619 while (!feof (f) && fread (buf, fsize, 1, f) == 0)
620 if (ferror (f))
621 {
622 errloc = "reading archive from temporary file";
623 goto err_no;
624 }
625
626 *size = fsize;
627 free (arg.names);
628 free (arg.files);
629 return buf;
630
631 err_no:
632 ctf_set_errno (fp, errno);
633 err:
634 free (buf);
635 if (f)
636 fclose (f);
637 free (arg.names);
638 free (arg.files);
639 ctf_dprintf ("Cannot write archive in link: %s failure: %s\n", errloc,
640 ctf_errmsg (ctf_errno (fp)));
641 return NULL;
642 }
This page took 0.043906 seconds and 5 git commands to generate.