libctf, binutils: support CTF archives like objdump
[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_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 /* bsearch() internal state. */
48 static __thread char *search_nametbl;
49
50 /* Write out a CTF archive to the start of the file referenced by the passed-in
51 fd. The entries in CTF_FILES are referenced by name: the names are passed in
52 the names array, which must have CTF_FILES entries.
53
54 Returns 0 on success, or an errno, or an ECTF_* value. */
55 int
56 ctf_arc_write_fd (int fd, ctf_file_t **ctf_files, size_t ctf_file_cnt,
57 const char **names, size_t threshold)
58 {
59 const char *errmsg;
60 struct ctf_archive *archdr;
61 size_t i;
62 char dummy = 0;
63 size_t headersz;
64 ssize_t namesz;
65 size_t ctf_startoffs; /* Start of the section we are working over. */
66 char *nametbl = NULL; /* The name table. */
67 char *np;
68 off_t nameoffs;
69 struct ctf_archive_modent *modent;
70
71 ctf_dprintf ("Writing CTF archive with %lu files\n",
72 (unsigned long) ctf_file_cnt);
73
74 /* Figure out the size of the mmap()ed header, including the
75 ctf_archive_modent array. We assume that all of this needs no
76 padding: a likely assumption, given that it's all made up of
77 uint64_t's. */
78 headersz = sizeof (struct ctf_archive)
79 + (ctf_file_cnt * sizeof (uint64_t) * 2);
80 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
81
82 /* From now on we work in two pieces: an mmap()ed region from zero up to the
83 headersz, and a region updated via write() starting after that, containing
84 all the tables. Platforms that do not support mmap() just use write(). */
85 ctf_startoffs = headersz;
86 if (lseek (fd, ctf_startoffs - 1, SEEK_SET) < 0)
87 {
88 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
89 goto err;
90 }
91
92 if (write (fd, &dummy, 1) < 0)
93 {
94 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
95 goto err;
96 }
97
98 if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
99 {
100 errmsg = "ctf_arc_write(): Cannot mmap(): %s\n";
101 goto err;
102 }
103
104 /* Fill in everything we can, which is everything other than the name
105 table offset. */
106 archdr->ctfa_magic = htole64 (CTFA_MAGIC);
107 archdr->ctfa_nfiles = htole64 (ctf_file_cnt);
108 archdr->ctfa_ctfs = htole64 (ctf_startoffs);
109
110 /* We could validate that all CTF files have the same data model, but
111 since any reasonable construction process will be building things of
112 only one bitness anyway, this is pretty pointless, so just use the
113 model of the first CTF file for all of them. (It *is* valid to
114 create an empty archive: the value of ctfa_model is irrelevant in
115 this case, but we must be sure not to dereference uninitialized
116 memory.) */
117
118 if (ctf_file_cnt > 0)
119 archdr->ctfa_model = htole64 (ctf_getmodel (ctf_files[0]));
120
121 /* Now write out the CTFs: ctf_archive_modent array via the mapping,
122 ctfs via write(). The names themselves have not been written yet: we
123 track them in a local strtab until the time is right, and sort the
124 modents array after construction.
125
126 The name table is not sorted. */
127
128 for (i = 0, namesz = 0; i < le64toh (archdr->ctfa_nfiles); i++)
129 namesz += strlen (names[i]) + 1;
130
131 nametbl = malloc (namesz);
132 if (nametbl == NULL)
133 {
134 errmsg = "Error writing named CTF to archive: %s\n";
135 goto err_unmap;
136 }
137
138 for (i = 0, namesz = 0,
139 modent = (ctf_archive_modent_t *) ((char *) archdr
140 + sizeof (struct ctf_archive));
141 i < le64toh (archdr->ctfa_nfiles); i++)
142 {
143 off_t off;
144
145 strcpy (&nametbl[namesz], names[i]);
146
147 off = arc_write_one_ctf (ctf_files[i], fd, threshold);
148 if ((off < 0) && (off > -ECTF_BASE))
149 {
150 errmsg = "ctf_arc_write(): Cannot determine file "
151 "position while writing to archive: %s";
152 goto err_free;
153 }
154 if (off < 0)
155 {
156 errmsg = "ctf_arc_write(): Cannot write CTF file to archive: %s\n";
157 errno = off * -1;
158 goto err_free;
159 }
160
161 modent->name_offset = htole64 (namesz);
162 modent->ctf_offset = htole64 (off - ctf_startoffs);
163 namesz += strlen (names[i]) + 1;
164 modent++;
165 }
166
167 ctf_qsort_r ((ctf_archive_modent_t *) ((char *) archdr
168 + sizeof (struct ctf_archive)),
169 le64toh (archdr->ctfa_nfiles),
170 sizeof (struct ctf_archive_modent), sort_modent_by_name,
171 nametbl);
172
173 /* Now the name table. */
174
175 if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
176 {
177 errmsg = "ctf_arc_write(): Cannot get current file position "
178 "in archive: %s\n";
179 goto err_free;
180 }
181 archdr->ctfa_names = htole64 (nameoffs);
182 np = nametbl;
183 while (namesz > 0)
184 {
185 ssize_t len;
186 if ((len = write (fd, np, namesz)) < 0)
187 {
188 errmsg = "ctf_arc_write(): Cannot write name table to archive: %s\n";
189 goto err_free;
190 }
191 namesz -= len;
192 np += len;
193 }
194 free (nametbl);
195
196 if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
197 goto err_unmap;
198 if (arc_mmap_unmap (archdr, headersz, &errmsg) < 0)
199 goto err;
200 return 0;
201
202 err_free:
203 free (nametbl);
204 err_unmap:
205 arc_mmap_unmap (archdr, headersz, NULL);
206 err:
207 ctf_dprintf (errmsg, errno < ECTF_BASE ? strerror (errno) :
208 ctf_errmsg (errno));
209 return errno;
210 }
211
212 /* Write out a CTF archive. The entries in CTF_FILES are referenced by name:
213 the names are passed in the names array, which must have CTF_FILES 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_file_t ** ctf_files, size_t ctf_file_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_dprintf ("ctf_arc_write(): cannot create %s: %s\n", file,
228 strerror (errno));
229 return errno;
230 }
231
232 err = ctf_arc_write_fd (fd, ctf_files, ctf_file_cnt, names, threshold);
233 if (err)
234 goto err;
235
236 if ((err = close (fd)) < 0)
237 {
238 ctf_dprintf ("ctf_arc_write(): Cannot close after writing to archive: "
239 "%s\n", strerror (errno));
240 goto err_close;
241 }
242
243 err:
244 close (fd);
245 if (err < 0)
246 unlink (file);
247
248 return err;
249
250 err_close:
251 if (err < 0)
252 unlink (file);
253
254 return err;
255 }
256
257 /* Write one CTF file out. Return the file position of the written file (or
258 rather, of the file-size uint64_t that precedes it): negative return is a
259 negative errno or ctf_errno value. On error, the file position may no longer
260 be at the end of the file. */
261 static off_t
262 arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold)
263 {
264 off_t off, end_off;
265 uint64_t ctfsz = 0;
266 char *ctfszp;
267 size_t ctfsz_len;
268 int (*writefn) (ctf_file_t * fp, int fd);
269
270 if (ctf_serialize (f) < 0)
271 return f->ctf_errno * -1;
272
273 if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
274 return errno * -1;
275
276 if (f->ctf_size > threshold)
277 writefn = ctf_compress_write;
278 else
279 writefn = ctf_write;
280
281 /* This zero-write turns into the size in a moment. */
282 ctfsz_len = sizeof (ctfsz);
283 ctfszp = (char *) &ctfsz;
284 while (ctfsz_len > 0)
285 {
286 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
287 if (writelen < 0)
288 return errno * -1;
289 ctfsz_len -= writelen;
290 ctfszp += writelen;
291 }
292
293 if (writefn (f, fd) != 0)
294 return f->ctf_errno * -1;
295
296 if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
297 return errno * -1;
298 ctfsz = htole64 (end_off - off);
299
300 if ((lseek (fd, off, SEEK_SET)) < 0)
301 return errno * -1;
302
303 /* ... here. */
304 ctfsz_len = sizeof (ctfsz);
305 ctfszp = (char *) &ctfsz;
306 while (ctfsz_len > 0)
307 {
308 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
309 if (writelen < 0)
310 return errno * -1;
311 ctfsz_len -= writelen;
312 ctfszp += writelen;
313 }
314
315 end_off = LCTF_ALIGN_OFFS (end_off, 8);
316 if ((lseek (fd, end_off, SEEK_SET)) < 0)
317 return errno * -1;
318
319 return off;
320 }
321
322 /* qsort() function to sort the array of struct ctf_archive_modents into
323 ascending name order. */
324 static int
325 sort_modent_by_name (const void *one, const void *two, void *n)
326 {
327 const struct ctf_archive_modent *a = one;
328 const struct ctf_archive_modent *b = two;
329 char *nametbl = n;
330
331 return strcmp (&nametbl[le64toh (a->name_offset)],
332 &nametbl[le64toh (b->name_offset)]);
333 }
334
335 /* bsearch() function to search for a given name in the sorted array of struct
336 ctf_archive_modents. */
337 static int
338 search_modent_by_name (const void *key, const void *ent)
339 {
340 const char *k = key;
341 const struct ctf_archive_modent *v = ent;
342
343 return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
344 }
345
346 /* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
347 ctf_file. Closes ARC and/or FP on error. Arrange to free the SYMSECT or
348 STRSECT, as needed, on close. */
349
350 struct ctf_archive_internal *
351 ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
352 ctf_file_t *fp, const ctf_sect_t *symsect,
353 const ctf_sect_t *strsect,
354 int *errp)
355 {
356 struct ctf_archive_internal *arci;
357
358 if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL)
359 {
360 if (is_archive)
361 ctf_arc_close_internal (arc);
362 else
363 ctf_file_close (fp);
364 return (ctf_set_open_errno (errp, errno));
365 }
366 arci->ctfi_is_archive = is_archive;
367 if (is_archive)
368 arci->ctfi_archive = arc;
369 else
370 arci->ctfi_file = fp;
371 if (symsect)
372 memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect));
373 if (strsect)
374 memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
375 arci->ctfi_free_symsect = 0;
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_file_t *fp = NULL;
390
391 if (ctfsect->cts_size > sizeof (uint64_t) &&
392 ((*(uint64_t *) ctfsect->cts_data) == CTFA_MAGIC))
393 {
394 /* The archive is mmappable, so this operation is trivial. */
395
396 is_archive = 1;
397 arc = (struct ctf_archive *) ctfsect->cts_data;
398 }
399 else
400 {
401 is_archive = 0;
402 if ((fp = ctf_bufopen (ctfsect, symsect, strsect, errp)) == NULL)
403 {
404 ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n",
405 ctf_errmsg (*errp));
406 return NULL;
407 }
408 }
409 return ctf_new_archive_internal (is_archive, arc, fp, symsect, strsect,
410 errp);
411 }
412
413 /* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
414 not NULL). */
415 struct ctf_archive *
416 ctf_arc_open_internal (const char *filename, int *errp)
417 {
418 const char *errmsg;
419 int fd;
420 struct stat s;
421 struct ctf_archive *arc; /* (Actually the whole file.) */
422
423 libctf_init_debug();
424 if ((fd = open (filename, O_RDONLY)) < 0)
425 {
426 errmsg = "ctf_arc_open(): cannot open %s: %s\n";
427 goto err;
428 }
429 if (fstat (fd, &s) < 0)
430 {
431 errmsg = "ctf_arc_open(): cannot stat %s: %s\n";
432 goto err_close;
433 }
434
435 if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
436 {
437 errmsg = "ctf_arc_open(): Cannot read in %s: %s\n";
438 goto err_close;
439 }
440
441 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
442 {
443 errmsg = "ctf_arc_open(): Invalid magic number";
444 errno = ECTF_FMT;
445 goto err_unmap;
446 }
447
448 /* This horrible hack lets us know how much to unmap when the file is
449 closed. (We no longer need the magic number, and the mapping
450 is private.) */
451 arc->ctfa_magic = s.st_size;
452 close (fd);
453 return arc;
454
455 err_unmap:
456 arc_mmap_unmap (arc, s.st_size, NULL);
457 err_close:
458 close (fd);
459 err:
460 if (errp)
461 *errp = errno;
462 ctf_dprintf (errmsg, filename, errno < ECTF_BASE ? strerror (errno) :
463 ctf_errmsg (errno));
464 return NULL;
465 }
466
467 /* Close an archive. */
468 void
469 ctf_arc_close_internal (struct ctf_archive *arc)
470 {
471 if (arc == NULL)
472 return;
473
474 /* See the comment in ctf_arc_open(). */
475 arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
476 }
477
478 /* Public entry point: close an archive, or CTF file. */
479 void
480 ctf_arc_close (ctf_archive_t *arc)
481 {
482 if (arc == NULL)
483 return;
484
485 if (arc->ctfi_is_archive)
486 ctf_arc_close_internal (arc->ctfi_archive);
487 else
488 ctf_file_close (arc->ctfi_file);
489 if (arc->ctfi_free_symsect)
490 free ((void *) arc->ctfi_symsect.cts_data);
491 free (arc->ctfi_data);
492 if (arc->ctfi_bfd_close)
493 arc->ctfi_bfd_close (arc);
494 free (arc);
495 }
496
497 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
498 non-NULL. A name of NULL means to open the default file. */
499 static ctf_file_t *
500 ctf_arc_open_by_name_internal (const struct ctf_archive *arc,
501 const ctf_sect_t *symsect,
502 const ctf_sect_t *strsect,
503 const char *name, int *errp)
504 {
505 struct ctf_archive_modent *modent;
506
507 if (name == NULL)
508 name = _CTF_SECTION; /* The default name. */
509
510 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
511
512 modent = (ctf_archive_modent_t *) ((char *) arc
513 + sizeof (struct ctf_archive));
514
515 search_nametbl = (char *) arc + le64toh (arc->ctfa_names);
516 modent = bsearch (name, modent, le64toh (arc->ctfa_nfiles),
517 sizeof (struct ctf_archive_modent),
518 search_modent_by_name);
519
520 /* This is actually a common case and normal operation: no error
521 debug output. */
522 if (modent == NULL)
523 {
524 if (errp)
525 *errp = ECTF_ARNNAME;
526 return NULL;
527 }
528
529 return ctf_arc_open_by_offset (arc, symsect, strsect,
530 le64toh (modent->ctf_offset), errp);
531 }
532
533 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
534 non-NULL. A name of NULL means to open the default file.
535
536 Use the specified string and symbol table sections.
537
538 Public entry point. */
539 ctf_file_t *
540 ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
541 const ctf_sect_t *symsect,
542 const ctf_sect_t *strsect,
543 const char *name,
544 int *errp)
545 {
546 if (arc->ctfi_is_archive)
547 {
548 ctf_file_t *ret;
549 ret = ctf_arc_open_by_name_internal (arc->ctfi_archive, symsect, strsect,
550 name, errp);
551 if (ret)
552 ret->ctf_archive = (ctf_archive_t *) arc;
553 return ret;
554 }
555
556 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
557 {
558 if (errp)
559 *errp = ECTF_ARNNAME;
560 return NULL;
561 }
562 arc->ctfi_file->ctf_archive = (ctf_archive_t *) arc;
563
564 /* Bump the refcount so that the user can ctf_file_close() it. */
565 arc->ctfi_file->ctf_refcnt++;
566 return arc->ctfi_file;
567 }
568
569 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
570 non-NULL. A name of NULL means to open the default file.
571
572 Public entry point. */
573 ctf_file_t *
574 ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name, int *errp)
575 {
576 const ctf_sect_t *symsect = &arc->ctfi_symsect;
577 const ctf_sect_t *strsect = &arc->ctfi_strsect;
578
579 if (symsect->cts_name == NULL)
580 symsect = NULL;
581 if (strsect->cts_name == NULL)
582 strsect = NULL;
583
584 return ctf_arc_open_by_name_sections (arc, symsect, strsect, name, errp);
585 }
586
587 /* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
588 none, setting 'err' if non-NULL. */
589 static ctf_file_t *
590 ctf_arc_open_by_offset (const struct ctf_archive *arc,
591 const ctf_sect_t *symsect,
592 const ctf_sect_t *strsect, size_t offset,
593 int *errp)
594 {
595 ctf_sect_t ctfsect;
596 ctf_file_t *fp;
597
598 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
599
600 memset (&ctfsect, 0, sizeof (ctf_sect_t));
601
602 offset += le64toh (arc->ctfa_ctfs);
603
604 ctfsect.cts_name = _CTF_SECTION;
605 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
606 ctfsect.cts_entsize = 1;
607 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
608 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
609 if (fp)
610 ctf_setmodel (fp, le64toh (arc->ctfa_model));
611 return fp;
612 }
613
614 /* Raw iteration over all CTF files in an archive. We pass the raw data for all
615 CTF files in turn to the specified callback function. */
616 static int
617 ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
618 ctf_archive_raw_member_f *func, void *data)
619 {
620 int rc;
621 size_t i;
622 struct ctf_archive_modent *modent;
623 const char *nametbl;
624
625 modent = (ctf_archive_modent_t *) ((char *) arc
626 + sizeof (struct ctf_archive));
627 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
628
629 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
630 {
631 const char *name;
632 char *fp;
633
634 name = &nametbl[le64toh (modent[i].name_offset)];
635 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
636 + le64toh (modent[i].ctf_offset));
637
638 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
639 le64toh (*((uint64_t *) fp)), data)) != 0)
640 return rc;
641 }
642 return 0;
643 }
644
645 /* Raw iteration over all CTF files in an archive: public entry point.
646
647 Returns -EINVAL if not supported for this sort of archive. */
648 int
649 ctf_archive_raw_iter (const ctf_archive_t *arc,
650 ctf_archive_raw_member_f * func, void *data)
651 {
652 if (arc->ctfi_is_archive)
653 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
654
655 return -EINVAL; /* Not supported. */
656 }
657
658 /* Iterate over all CTF files in an archive. We pass all CTF files in turn to
659 the specified callback function. */
660 static int
661 ctf_archive_iter_internal (const ctf_archive_t *wrapper,
662 const struct ctf_archive *arc,
663 const ctf_sect_t *symsect,
664 const ctf_sect_t *strsect,
665 ctf_archive_member_f *func, void *data)
666 {
667 int rc;
668 size_t i;
669 ctf_file_t *f;
670 struct ctf_archive_modent *modent;
671 const char *nametbl;
672
673 modent = (ctf_archive_modent_t *) ((char *) arc
674 + sizeof (struct ctf_archive));
675 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
676
677 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
678 {
679 const char *name;
680
681 name = &nametbl[le64toh (modent[i].name_offset)];
682 if ((f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
683 name, &rc)) == NULL)
684 return rc;
685
686 f->ctf_archive = (ctf_archive_t *) wrapper;
687 if ((rc = func (f, name, data)) != 0)
688 {
689 ctf_file_close (f);
690 return rc;
691 }
692
693 ctf_file_close (f);
694 }
695 return 0;
696 }
697
698 /* Iterate over all CTF files in an archive: public entry point. We pass all
699 CTF files in turn to the specified callback function. */
700 int
701 ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
702 void *data)
703 {
704 const ctf_sect_t *symsect = &arc->ctfi_symsect;
705 const ctf_sect_t *strsect = &arc->ctfi_strsect;
706
707 if (symsect->cts_name == NULL)
708 symsect = NULL;
709 if (strsect->cts_name == NULL)
710 strsect = NULL;
711
712 if (arc->ctfi_is_archive)
713 return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
714 func, data);
715
716 return func (arc->ctfi_file, _CTF_SECTION, data);
717 }
718
719 #ifdef HAVE_MMAP
720 /* Map the header in. Only used on new, empty files. */
721 static void *arc_mmap_header (int fd, size_t headersz)
722 {
723 void *hdr;
724 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
725 0)) == MAP_FAILED)
726 return NULL;
727 return hdr;
728 }
729
730 /* mmap() the whole file, for reading only. (Map it writably, but privately: we
731 need to modify the region, but don't need anyone else to see the
732 modifications.) */
733 static void *arc_mmap_file (int fd, size_t size)
734 {
735 void *arc;
736 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
737 fd, 0)) == MAP_FAILED)
738 return NULL;
739 return arc;
740 }
741
742 /* Persist the header to disk. */
743 static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
744 size_t headersz, const char **errmsg)
745 {
746 if (msync (header, headersz, MS_ASYNC) < 0)
747 {
748 if (errmsg)
749 *errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
750 return -1;
751 }
752 return 0;
753 }
754
755 /* Unmap the region. */
756 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
757 {
758 if (munmap (header, headersz) < 0)
759 {
760 if (errmsg)
761 *errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
762 return -1;
763 }
764 return 0;
765 }
766 #else
767 /* Map the header in. Only used on new, empty files. */
768 static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
769 {
770 void *hdr;
771 if ((hdr = malloc (headersz)) == NULL)
772 return NULL;
773 return hdr;
774 }
775
776 /* Pull in the whole file, for reading only. We assume the current file
777 position is at the start of the file. */
778 static void *arc_mmap_file (int fd, size_t size)
779 {
780 char *data;
781
782 if ((data = malloc (size)) == NULL)
783 return NULL;
784
785 if (ctf_pread (fd, data, size, 0) < 0)
786 {
787 free (data);
788 return NULL;
789 }
790 return data;
791 }
792
793 /* Persist the header to disk. */
794 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
795 const char **errmsg)
796 {
797 ssize_t len;
798 size_t acc = 0;
799 char *data = (char *) header;
800 ssize_t count = headersz;
801
802 if ((lseek (fd, 0, SEEK_SET)) < 0)
803 {
804 if (errmsg)
805 *errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
806 "%s: %s\n";
807 return -1;
808 }
809
810 while (headersz > 0)
811 {
812 if ((len = write (fd, data, count)) < 0)
813 {
814 if (errmsg)
815 *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
816 return len;
817 }
818 if (len == EINTR)
819 continue;
820
821 acc += len;
822 if (len == 0) /* EOF. */
823 break;
824
825 count -= len;
826 data += len;
827 }
828 return 0;
829 }
830
831 /* Unmap the region. */
832 static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
833 const char **errmsg _libctf_unused_)
834 {
835 free (header);
836 return 0;
837 }
838 #endif
This page took 0.05882 seconds and 5 git commands to generate.