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