libctf, include, binutils, gdb: rename CTF-opening functions
[deliverable/binutils-gdb.git] / libctf / ctf-archive.c
1 /* CTF archive files.
2 Copyright (C) 2019-2020 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 <sys/types.h>
22 #include <sys/stat.h>
23 #include <elf.h>
24 #include "ctf-endian.h"
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #ifdef HAVE_MMAP
32 #include <sys/mman.h>
33 #endif
34
35 static off_t arc_write_one_ctf (ctf_dict_t * f, int fd, size_t threshold);
36 static ctf_dict_t *ctf_dict_open_by_offset (const struct ctf_archive *arc,
37 const ctf_sect_t *symsect,
38 const ctf_sect_t *strsect,
39 size_t offset, int *errp);
40 static int sort_modent_by_name (const void *one, const void *two, void *n);
41 static void *arc_mmap_header (int fd, size_t headersz);
42 static void *arc_mmap_file (int fd, size_t size);
43 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
44 const char **errmsg);
45 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
46
47 /* Write out a CTF archive to the start of the file referenced by the passed-in
48 fd. The entries in CTF_DICTS are referenced by name: the names are passed in
49 the names array, which must have CTF_DICTS entries.
50
51 Returns 0 on success, or an errno, or an ECTF_* value. */
52 int
53 ctf_arc_write_fd (int fd, ctf_dict_t **ctf_dicts, size_t ctf_dict_cnt,
54 const char **names, size_t threshold)
55 {
56 const char *errmsg;
57 struct ctf_archive *archdr;
58 size_t i;
59 char dummy = 0;
60 size_t headersz;
61 ssize_t namesz;
62 size_t ctf_startoffs; /* Start of the section we are working over. */
63 char *nametbl = NULL; /* The name table. */
64 char *np;
65 off_t nameoffs;
66 struct ctf_archive_modent *modent;
67
68 ctf_dprintf ("Writing CTF archive with %lu files\n",
69 (unsigned long) ctf_dict_cnt);
70
71 /* Figure out the size of the mmap()ed header, including the
72 ctf_archive_modent array. We assume that all of this needs no
73 padding: a likely assumption, given that it's all made up of
74 uint64_t's. */
75 headersz = sizeof (struct ctf_archive)
76 + (ctf_dict_cnt * sizeof (uint64_t) * 2);
77 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
78
79 /* From now on we work in two pieces: an mmap()ed region from zero up to the
80 headersz, and a region updated via write() starting after that, containing
81 all the tables. Platforms that do not support mmap() just use write(). */
82 ctf_startoffs = headersz;
83 if (lseek (fd, ctf_startoffs - 1, SEEK_SET) < 0)
84 {
85 errmsg = N_("ctf_arc_write(): cannot extend file while writing");
86 goto err;
87 }
88
89 if (write (fd, &dummy, 1) < 0)
90 {
91 errmsg = N_("ctf_arc_write(): cannot extend file while writing");
92 goto err;
93 }
94
95 if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
96 {
97 errmsg = N_("ctf_arc_write(): cannot mmap");
98 goto err;
99 }
100
101 /* Fill in everything we can, which is everything other than the name
102 table offset. */
103 archdr->ctfa_magic = htole64 (CTFA_MAGIC);
104 archdr->ctfa_ndicts = htole64 (ctf_dict_cnt);
105 archdr->ctfa_ctfs = htole64 (ctf_startoffs);
106
107 /* We could validate that all CTF files have the same data model, but
108 since any reasonable construction process will be building things of
109 only one bitness anyway, this is pretty pointless, so just use the
110 model of the first CTF file for all of them. (It *is* valid to
111 create an empty archive: the value of ctfa_model is irrelevant in
112 this case, but we must be sure not to dereference uninitialized
113 memory.) */
114
115 if (ctf_dict_cnt > 0)
116 archdr->ctfa_model = htole64 (ctf_getmodel (ctf_dicts[0]));
117
118 /* Now write out the CTFs: ctf_archive_modent array via the mapping,
119 ctfs via write(). The names themselves have not been written yet: we
120 track them in a local strtab until the time is right, and sort the
121 modents array after construction.
122
123 The name table is not sorted. */
124
125 for (i = 0, namesz = 0; i < le64toh (archdr->ctfa_ndicts); i++)
126 namesz += strlen (names[i]) + 1;
127
128 nametbl = malloc (namesz);
129 if (nametbl == NULL)
130 {
131 errmsg = N_("ctf_arc_write(): error writing named CTF to archive");
132 goto err_unmap;
133 }
134
135 for (i = 0, namesz = 0,
136 modent = (ctf_archive_modent_t *) ((char *) archdr
137 + sizeof (struct ctf_archive));
138 i < le64toh (archdr->ctfa_ndicts); i++)
139 {
140 off_t off;
141
142 strcpy (&nametbl[namesz], names[i]);
143
144 off = arc_write_one_ctf (ctf_dicts[i], fd, threshold);
145 if ((off < 0) && (off > -ECTF_BASE))
146 {
147 errmsg = N_("ctf_arc_write(): cannot determine file "
148 "position while writing to archive");
149 goto err_free;
150 }
151 if (off < 0)
152 {
153 errmsg = N_("ctf_arc_write(): cannot write CTF file to archive");
154 errno = off * -1;
155 goto err_free;
156 }
157
158 modent->name_offset = htole64 (namesz);
159 modent->ctf_offset = htole64 (off - ctf_startoffs);
160 namesz += strlen (names[i]) + 1;
161 modent++;
162 }
163
164 ctf_qsort_r ((ctf_archive_modent_t *) ((char *) archdr
165 + sizeof (struct ctf_archive)),
166 le64toh (archdr->ctfa_ndicts),
167 sizeof (struct ctf_archive_modent), sort_modent_by_name,
168 nametbl);
169
170 /* Now the name table. */
171
172 if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
173 {
174 errmsg = N_("ctf_arc_write(): cannot get current file position "
175 "in archive");
176 goto err_free;
177 }
178 archdr->ctfa_names = htole64 (nameoffs);
179 np = nametbl;
180 while (namesz > 0)
181 {
182 ssize_t len;
183 if ((len = write (fd, np, namesz)) < 0)
184 {
185 errmsg = N_("ctf_arc_write(): cannot write name table to archive");
186 goto err_free;
187 }
188 namesz -= len;
189 np += len;
190 }
191 free (nametbl);
192
193 if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
194 goto err_unmap;
195 if (arc_mmap_unmap (archdr, headersz, &errmsg) < 0)
196 goto err;
197 return 0;
198
199 err_free:
200 free (nametbl);
201 err_unmap:
202 arc_mmap_unmap (archdr, headersz, NULL);
203 err:
204 /* We report errors into the first file in the archive, if any: if this is a
205 zero-file archive, put it in the open-errors stream for lack of anywhere
206 else for it to go. */
207 ctf_err_warn (ctf_dict_cnt > 0 ? ctf_dicts[0] : NULL, 0, errno, "%s",
208 gettext (errmsg));
209 return errno;
210 }
211
212 /* Write out a CTF archive. The entries in CTF_DICTS are referenced by name:
213 the names are passed in the names array, which must have CTF_DICTS entries.
214
215 If the filename is NULL, create a temporary file and return a pointer to it.
216
217 Returns 0 on success, or an errno, or an ECTF_* value. */
218 int
219 ctf_arc_write (const char *file, ctf_dict_t **ctf_dicts, size_t ctf_dict_cnt,
220 const char **names, size_t threshold)
221 {
222 int err;
223 int fd;
224
225 if ((fd = open (file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0)
226 {
227 ctf_err_warn (ctf_dict_cnt > 0 ? ctf_dicts[0] : NULL, 0, errno,
228 _("ctf_arc_write(): cannot create %s"), file);
229 return errno;
230 }
231
232 err = ctf_arc_write_fd (fd, ctf_dicts, ctf_dict_cnt, names, threshold);
233 if (err)
234 goto err_close;
235
236 if ((err = close (fd)) < 0)
237 ctf_err_warn (ctf_dict_cnt > 0 ? ctf_dicts[0] : NULL, 0, errno,
238 _("ctf_arc_write(): cannot close after writing to archive"));
239 goto err;
240
241 err_close:
242 (void) close (fd);
243 err:
244 if (err < 0)
245 unlink (file);
246
247 return err;
248 }
249
250 /* Write one CTF file out. Return the file position of the written file (or
251 rather, of the file-size uint64_t that precedes it): negative return is a
252 negative errno or ctf_errno value. On error, the file position may no longer
253 be at the end of the file. */
254 static off_t
255 arc_write_one_ctf (ctf_dict_t * f, int fd, size_t threshold)
256 {
257 off_t off, end_off;
258 uint64_t ctfsz = 0;
259 char *ctfszp;
260 size_t ctfsz_len;
261 int (*writefn) (ctf_dict_t * fp, int fd);
262
263 if (ctf_serialize (f) < 0)
264 return f->ctf_errno * -1;
265
266 if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
267 return errno * -1;
268
269 if (f->ctf_size > threshold)
270 writefn = ctf_compress_write;
271 else
272 writefn = ctf_write;
273
274 /* This zero-write turns into the size in a moment. */
275 ctfsz_len = sizeof (ctfsz);
276 ctfszp = (char *) &ctfsz;
277 while (ctfsz_len > 0)
278 {
279 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
280 if (writelen < 0)
281 return errno * -1;
282 ctfsz_len -= writelen;
283 ctfszp += writelen;
284 }
285
286 if (writefn (f, fd) != 0)
287 return f->ctf_errno * -1;
288
289 if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
290 return errno * -1;
291 ctfsz = htole64 (end_off - off);
292
293 if ((lseek (fd, off, SEEK_SET)) < 0)
294 return errno * -1;
295
296 /* ... here. */
297 ctfsz_len = sizeof (ctfsz);
298 ctfszp = (char *) &ctfsz;
299 while (ctfsz_len > 0)
300 {
301 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
302 if (writelen < 0)
303 return errno * -1;
304 ctfsz_len -= writelen;
305 ctfszp += writelen;
306 }
307
308 end_off = LCTF_ALIGN_OFFS (end_off, 8);
309 if ((lseek (fd, end_off, SEEK_SET)) < 0)
310 return errno * -1;
311
312 return off;
313 }
314
315 /* qsort() function to sort the array of struct ctf_archive_modents into
316 ascending name order. */
317 static int
318 sort_modent_by_name (const void *one, const void *two, void *n)
319 {
320 const struct ctf_archive_modent *a = one;
321 const struct ctf_archive_modent *b = two;
322 char *nametbl = n;
323
324 return strcmp (&nametbl[le64toh (a->name_offset)],
325 &nametbl[le64toh (b->name_offset)]);
326 }
327
328 /* bsearch_r() function to search for a given name in the sorted array of struct
329 ctf_archive_modents. */
330 static int
331 search_modent_by_name (const void *key, const void *ent, void *arg)
332 {
333 const char *k = key;
334 const struct ctf_archive_modent *v = ent;
335 const char *search_nametbl = arg;
336
337 return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
338 }
339
340 /* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
341 ctf_dict. Closes ARC and/or FP on error. Arrange to free the SYMSECT or
342 STRSECT, as needed, on close. Possibly do not unmap on close. */
343
344 struct ctf_archive_internal *
345 ctf_new_archive_internal (int is_archive, int unmap_on_close,
346 struct ctf_archive *arc,
347 ctf_dict_t *fp, const ctf_sect_t *symsect,
348 const ctf_sect_t *strsect,
349 int *errp)
350 {
351 struct ctf_archive_internal *arci;
352
353 if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL)
354 {
355 if (is_archive)
356 {
357 if (unmap_on_close)
358 ctf_arc_close_internal (arc);
359 }
360 else
361 ctf_dict_close (fp);
362 return (ctf_set_open_errno (errp, errno));
363 }
364 arci->ctfi_is_archive = is_archive;
365 if (is_archive)
366 arci->ctfi_archive = arc;
367 else
368 arci->ctfi_dict = fp;
369 if (symsect)
370 memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect));
371 if (strsect)
372 memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
373 arci->ctfi_free_symsect = 0;
374 arci->ctfi_free_strsect = 0;
375 arci->ctfi_unmap_on_close = unmap_on_close;
376
377 return arci;
378 }
379
380 /* Open a CTF archive or dictionary from data in a buffer (which the caller must
381 preserve until ctf_arc_close() time). Returns the archive, or NULL and an
382 error in *err (if not NULL). */
383 ctf_archive_t *
384 ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
385 const ctf_sect_t *strsect, int *errp)
386 {
387 struct ctf_archive *arc = NULL;
388 int is_archive;
389 ctf_dict_t *fp = NULL;
390
391 if (ctfsect->cts_size > sizeof (uint64_t) &&
392 (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
393 {
394 /* The archive is mmappable, so this operation is trivial.
395
396 This buffer is nonmodifiable, so the trick involving mmapping only part
397 of it and storing the length in the magic number is not applicable: so
398 record this fact in the archive-wrapper header. (We cannot record it
399 in the archive, because the archive may very well be a read-only
400 mapping.) */
401
402 is_archive = 1;
403 arc = (struct ctf_archive *) ctfsect->cts_data;
404 }
405 else
406 {
407 is_archive = 0;
408 if ((fp = ctf_bufopen (ctfsect, symsect, strsect, errp)) == NULL)
409 {
410 ctf_err_warn (NULL, 0, *errp, _("ctf_arc_bufopen(): cannot open CTF"));
411 return NULL;
412 }
413 }
414 return ctf_new_archive_internal (is_archive, 0, arc, fp, symsect, strsect,
415 errp);
416 }
417
418 /* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
419 not NULL). */
420 struct ctf_archive *
421 ctf_arc_open_internal (const char *filename, int *errp)
422 {
423 const char *errmsg;
424 int fd;
425 struct stat s;
426 struct ctf_archive *arc; /* (Actually the whole file.) */
427
428 libctf_init_debug();
429 if ((fd = open (filename, O_RDONLY)) < 0)
430 {
431 errmsg = N_("ctf_arc_open(): cannot open %s");
432 goto err;
433 }
434 if (fstat (fd, &s) < 0)
435 {
436 errmsg = N_("ctf_arc_open(): cannot stat %s");
437 goto err_close;
438 }
439
440 if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
441 {
442 errmsg = N_("ctf_arc_open(): cannot read in %s");
443 goto err_close;
444 }
445
446 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
447 {
448 errmsg = N_("ctf_arc_open(): %s: invalid magic number");
449 errno = ECTF_FMT;
450 goto err_unmap;
451 }
452
453 /* This horrible hack lets us know how much to unmap when the file is
454 closed. (We no longer need the magic number, and the mapping
455 is private.) */
456 arc->ctfa_magic = s.st_size;
457 close (fd);
458 return arc;
459
460 err_unmap:
461 arc_mmap_unmap (arc, s.st_size, NULL);
462 err_close:
463 close (fd);
464 err:
465 if (errp)
466 *errp = errno;
467 ctf_err_warn (NULL, 0, errno, gettext (errmsg), filename);
468 return NULL;
469 }
470
471 /* Close an archive. */
472 void
473 ctf_arc_close_internal (struct ctf_archive *arc)
474 {
475 if (arc == NULL)
476 return;
477
478 /* See the comment in ctf_arc_open(). */
479 arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
480 }
481
482 /* Public entry point: close an archive, or CTF file. */
483 void
484 ctf_arc_close (ctf_archive_t *arc)
485 {
486 if (arc == NULL)
487 return;
488
489 if (arc->ctfi_is_archive)
490 {
491 if (arc->ctfi_unmap_on_close)
492 ctf_arc_close_internal (arc->ctfi_archive);
493 }
494 else
495 ctf_dict_close (arc->ctfi_dict);
496 if (arc->ctfi_free_symsect)
497 free ((void *) arc->ctfi_symsect.cts_data);
498 if (arc->ctfi_free_strsect)
499 free ((void *) arc->ctfi_strsect.cts_data);
500 free (arc->ctfi_data);
501 if (arc->ctfi_bfd_close)
502 arc->ctfi_bfd_close (arc);
503 free (arc);
504 }
505
506 /* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
507 non-NULL. A name of NULL means to open the default file. */
508 static ctf_dict_t *
509 ctf_dict_open_internal (const struct ctf_archive *arc,
510 const ctf_sect_t *symsect,
511 const ctf_sect_t *strsect,
512 const char *name, int *errp)
513 {
514 struct ctf_archive_modent *modent;
515 const char *search_nametbl;
516
517 if (name == NULL)
518 name = _CTF_SECTION; /* The default name. */
519
520 ctf_dprintf ("ctf_dict_open_internal(%s): opening\n", name);
521
522 modent = (ctf_archive_modent_t *) ((char *) arc
523 + sizeof (struct ctf_archive));
524
525 search_nametbl = (const char *) arc + le64toh (arc->ctfa_names);
526 modent = bsearch_r (name, modent, le64toh (arc->ctfa_ndicts),
527 sizeof (struct ctf_archive_modent),
528 search_modent_by_name, (void *) search_nametbl);
529
530 /* This is actually a common case and normal operation: no error
531 debug output. */
532 if (modent == NULL)
533 {
534 if (errp)
535 *errp = ECTF_ARNNAME;
536 return NULL;
537 }
538
539 return ctf_dict_open_by_offset (arc, symsect, strsect,
540 le64toh (modent->ctf_offset), errp);
541 }
542
543 /* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
544 non-NULL. A name of NULL means to open the default file.
545
546 Use the specified string and symbol table sections.
547
548 Public entry point. */
549 ctf_dict_t *
550 ctf_dict_open_sections (const ctf_archive_t *arc,
551 const ctf_sect_t *symsect,
552 const ctf_sect_t *strsect,
553 const char *name,
554 int *errp)
555 {
556 if (arc->ctfi_is_archive)
557 {
558 ctf_dict_t *ret;
559 ret = ctf_dict_open_internal (arc->ctfi_archive, symsect, strsect,
560 name, errp);
561 if (ret)
562 ret->ctf_archive = (ctf_archive_t *) arc;
563 return ret;
564 }
565
566 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
567 {
568 if (errp)
569 *errp = ECTF_ARNNAME;
570 return NULL;
571 }
572 arc->ctfi_dict->ctf_archive = (ctf_archive_t *) arc;
573
574 /* Bump the refcount so that the user can ctf_dict_close() it. */
575 arc->ctfi_dict->ctf_refcnt++;
576 return arc->ctfi_dict;
577 }
578
579 /* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
580 non-NULL. A name of NULL means to open the default file.
581
582 Public entry point. */
583 ctf_dict_t *
584 ctf_dict_open (const ctf_archive_t *arc, const char *name, int *errp)
585 {
586 const ctf_sect_t *symsect = &arc->ctfi_symsect;
587 const ctf_sect_t *strsect = &arc->ctfi_strsect;
588
589 if (symsect->cts_name == NULL)
590 symsect = NULL;
591 if (strsect->cts_name == NULL)
592 strsect = NULL;
593
594 return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
595 }
596
597 /* Return the ctf_dict_t at the given ctfa_ctfs-relative offset, or NULL if
598 none, setting 'err' if non-NULL. */
599 static ctf_dict_t *
600 ctf_dict_open_by_offset (const struct ctf_archive *arc,
601 const ctf_sect_t *symsect,
602 const ctf_sect_t *strsect, size_t offset,
603 int *errp)
604 {
605 ctf_sect_t ctfsect;
606 ctf_dict_t *fp;
607
608 ctf_dprintf ("ctf_dict_open_by_offset(%lu): opening\n", (unsigned long) offset);
609
610 memset (&ctfsect, 0, sizeof (ctf_sect_t));
611
612 offset += le64toh (arc->ctfa_ctfs);
613
614 ctfsect.cts_name = _CTF_SECTION;
615 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
616 ctfsect.cts_entsize = 1;
617 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
618 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
619 if (fp)
620 ctf_setmodel (fp, le64toh (arc->ctfa_model));
621 return fp;
622 }
623
624 /* Backward compatibility. */
625 ctf_dict_t *
626 ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name,
627 int *errp)
628 {
629 return ctf_dict_open (arc, name, errp);
630 }
631
632 ctf_dict_t *
633 ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
634 const ctf_sect_t *symsect,
635 const ctf_sect_t *strsect,
636 const char *name,
637 int *errp)
638 {
639 return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
640 }
641
642 /* Return the number of members in an archive. */
643 size_t
644 ctf_archive_count (const ctf_archive_t *wrapper)
645 {
646 if (!wrapper->ctfi_is_archive)
647 return 1;
648
649 return wrapper->ctfi_archive->ctfa_ndicts;
650 }
651
652 /* Raw iteration over all CTF files in an archive. We pass the raw data for all
653 CTF files in turn to the specified callback function. */
654 static int
655 ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
656 ctf_archive_raw_member_f *func, void *data)
657 {
658 int rc;
659 size_t i;
660 struct ctf_archive_modent *modent;
661 const char *nametbl;
662
663 modent = (ctf_archive_modent_t *) ((char *) arc
664 + sizeof (struct ctf_archive));
665 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
666
667 for (i = 0; i < le64toh (arc->ctfa_ndicts); i++)
668 {
669 const char *name;
670 char *fp;
671
672 name = &nametbl[le64toh (modent[i].name_offset)];
673 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
674 + le64toh (modent[i].ctf_offset));
675
676 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
677 le64toh (*((uint64_t *) fp)), data)) != 0)
678 return rc;
679 }
680 return 0;
681 }
682
683 /* Raw iteration over all CTF files in an archive: public entry point.
684
685 Returns -EINVAL if not supported for this sort of archive. */
686 int
687 ctf_archive_raw_iter (const ctf_archive_t *arc,
688 ctf_archive_raw_member_f * func, void *data)
689 {
690 if (arc->ctfi_is_archive)
691 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
692
693 return -EINVAL; /* Not supported. */
694 }
695
696 /* Iterate over all CTF files in an archive. We pass all CTF files in turn to
697 the specified callback function. */
698 static int
699 ctf_archive_iter_internal (const ctf_archive_t *wrapper,
700 const struct ctf_archive *arc,
701 const ctf_sect_t *symsect,
702 const ctf_sect_t *strsect,
703 ctf_archive_member_f *func, void *data)
704 {
705 int rc;
706 size_t i;
707 ctf_dict_t *f;
708 struct ctf_archive_modent *modent;
709 const char *nametbl;
710
711 modent = (ctf_archive_modent_t *) ((char *) arc
712 + sizeof (struct ctf_archive));
713 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
714
715 for (i = 0; i < le64toh (arc->ctfa_ndicts); i++)
716 {
717 const char *name;
718
719 name = &nametbl[le64toh (modent[i].name_offset)];
720 if ((f = ctf_dict_open_internal (arc, symsect, strsect,
721 name, &rc)) == NULL)
722 return rc;
723
724 f->ctf_archive = (ctf_archive_t *) wrapper;
725 if ((rc = func (f, name, data)) != 0)
726 {
727 ctf_dict_close (f);
728 return rc;
729 }
730
731 ctf_dict_close (f);
732 }
733 return 0;
734 }
735
736 /* Iterate over all CTF files in an archive: public entry point. We pass all
737 CTF files in turn to the specified callback function. */
738 int
739 ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
740 void *data)
741 {
742 const ctf_sect_t *symsect = &arc->ctfi_symsect;
743 const ctf_sect_t *strsect = &arc->ctfi_strsect;
744
745 if (symsect->cts_name == NULL)
746 symsect = NULL;
747 if (strsect->cts_name == NULL)
748 strsect = NULL;
749
750 if (arc->ctfi_is_archive)
751 return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
752 func, data);
753
754 return func (arc->ctfi_dict, _CTF_SECTION, data);
755 }
756
757 /* Iterate over all CTF files in an archive, returning each dict in turn as a
758 ctf_dict_t, and NULL on error or end of iteration. It is the caller's
759 responsibility to close it. Parent dicts may be skipped. Regardless of
760 whether they are skipped or not, the caller must ctf_import the parent if
761 need be.
762
763 We identify parents by name rather than by flag value: for now, with the
764 linker only emitting parents named _CTF_SECTION, this works well enough. */
765
766 ctf_dict_t *
767 ctf_archive_next (const ctf_archive_t *wrapper, ctf_next_t **it, const char **name,
768 int skip_parent, int *errp)
769 {
770 ctf_dict_t *f;
771 ctf_next_t *i = *it;
772 struct ctf_archive *arc;
773 struct ctf_archive_modent *modent;
774 const char *nametbl;
775 const char *name_;
776
777 if (!i)
778 {
779 if ((i = ctf_next_create()) == NULL)
780 {
781 if (errp)
782 *errp = ENOMEM;
783 return NULL;
784 }
785 i->cu.ctn_arc = wrapper;
786 i->ctn_iter_fun = (void (*) (void)) ctf_archive_next;
787 *it = i;
788 }
789
790 if ((void (*) (void)) ctf_archive_next != i->ctn_iter_fun)
791 {
792 if (errp)
793 *errp = ECTF_NEXT_WRONGFUN;
794 return NULL;
795 }
796
797 if (wrapper != i->cu.ctn_arc)
798 {
799 if (errp)
800 *errp = ECTF_NEXT_WRONGFP;
801 return NULL;
802 }
803
804 /* Iteration is made a bit more complex by the need to handle ctf_dict_t's
805 transparently wrapped in a single-member archive. These are parents: if
806 skip_parent is on, they are skipped and the iterator terminates
807 immediately. */
808
809 if (!wrapper->ctfi_is_archive && i->ctn_n == 0)
810 {
811 i->ctn_n++;
812 if (!skip_parent)
813 {
814 wrapper->ctfi_dict->ctf_refcnt++;
815 return wrapper->ctfi_dict;
816 }
817 }
818
819 arc = wrapper->ctfi_archive;
820
821 /* The loop keeps going when skip_parent is on as long as the member we find
822 is the parent (i.e. at most two iterations, but possibly an early return if
823 *all* we have is a parent). */
824
825 const ctf_sect_t *symsect;
826 const ctf_sect_t *strsect;
827
828 do
829 {
830 if ((!wrapper->ctfi_is_archive) || (i->ctn_n >= le64toh (arc->ctfa_ndicts)))
831 {
832 ctf_next_destroy (i);
833 *it = NULL;
834 if (errp)
835 *errp = ECTF_NEXT_END;
836 return NULL;
837 }
838
839 symsect = &wrapper->ctfi_symsect;
840 strsect = &wrapper->ctfi_strsect;
841
842 if (symsect->cts_name == NULL)
843 symsect = NULL;
844 if (strsect->cts_name == NULL)
845 strsect = NULL;
846
847 modent = (ctf_archive_modent_t *) ((char *) arc
848 + sizeof (struct ctf_archive));
849 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
850
851 name_ = &nametbl[le64toh (modent[i->ctn_n].name_offset)];
852 i->ctn_n++;
853 } while (skip_parent && strcmp (name_, _CTF_SECTION) == 0);
854
855 if (name)
856 *name = name_;
857
858 f = ctf_dict_open_internal (arc, symsect, strsect, name_, errp);
859 f->ctf_archive = (ctf_archive_t *) wrapper;
860 return f;
861 }
862
863 #ifdef HAVE_MMAP
864 /* Map the header in. Only used on new, empty files. */
865 static void *arc_mmap_header (int fd, size_t headersz)
866 {
867 void *hdr;
868 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
869 0)) == MAP_FAILED)
870 return NULL;
871 return hdr;
872 }
873
874 /* mmap() the whole file, for reading only. (Map it writably, but privately: we
875 need to modify the region, but don't need anyone else to see the
876 modifications.) */
877 static void *arc_mmap_file (int fd, size_t size)
878 {
879 void *arc;
880 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
881 fd, 0)) == MAP_FAILED)
882 return NULL;
883 return arc;
884 }
885
886 /* Persist the header to disk. */
887 static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
888 size_t headersz, const char **errmsg)
889 {
890 if (msync (header, headersz, MS_ASYNC) < 0)
891 {
892 if (errmsg)
893 *errmsg = N_("arc_mmap_writeout(): cannot sync after writing "
894 "to %s: %s");
895 return -1;
896 }
897 return 0;
898 }
899
900 /* Unmap the region. */
901 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
902 {
903 if (munmap (header, headersz) < 0)
904 {
905 if (errmsg)
906 *errmsg = N_("arc_mmap_munmap(): cannot unmap after writing "
907 "to %s: %s");
908 return -1;
909 }
910 return 0;
911 }
912 #else
913 /* Map the header in. Only used on new, empty files. */
914 static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
915 {
916 void *hdr;
917 if ((hdr = malloc (headersz)) == NULL)
918 return NULL;
919 return hdr;
920 }
921
922 /* Pull in the whole file, for reading only. We assume the current file
923 position is at the start of the file. */
924 static void *arc_mmap_file (int fd, size_t size)
925 {
926 char *data;
927
928 if ((data = malloc (size)) == NULL)
929 return NULL;
930
931 if (ctf_pread (fd, data, size, 0) < 0)
932 {
933 free (data);
934 return NULL;
935 }
936 return data;
937 }
938
939 /* Persist the header to disk. */
940 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
941 const char **errmsg)
942 {
943 ssize_t len;
944 size_t acc = 0;
945 char *data = (char *) header;
946 ssize_t count = headersz;
947
948 if ((lseek (fd, 0, SEEK_SET)) < 0)
949 {
950 if (errmsg)
951 *errmsg = N_("arc_mmap_writeout(): cannot seek while writing header to "
952 "%s: %s");
953 return -1;
954 }
955
956 while (headersz > 0)
957 {
958 if ((len = write (fd, data, count)) < 0)
959 {
960 if (errmsg)
961 *errmsg = N_("arc_mmap_writeout(): cannot write header to %s: %s");
962 return len;
963 }
964 if (len == EINTR)
965 continue;
966
967 acc += len;
968 if (len == 0) /* EOF. */
969 break;
970
971 count -= len;
972 data += len;
973 }
974 return 0;
975 }
976
977 /* Unmap the region. */
978 static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
979 const char **errmsg _libctf_unused_)
980 {
981 free (header);
982 return 0;
983 }
984 #endif
This page took 0.051548 seconds and 5 git commands to generate.