]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - libctf/ctf-archive.c
libctf, types: ints, floats and typedefs with no name are invalid
[thirdparty/binutils-gdb.git] / libctf / ctf-archive.c
CommitLineData
9402cc59 1/* CTF archive files.
b3adc24a 2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
9402cc59
NA
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>
a0486bac 24#include "ctf-endian.h"
9402cc59
NA
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
35static off_t arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold);
36static 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);
40static int sort_modent_by_name (const void *one, const void *two, void *n);
41static void *arc_mmap_header (int fd, size_t headersz);
42static void *arc_mmap_file (int fd, size_t size);
43static int arc_mmap_writeout (int fd, void *header, size_t headersz,
44 const char **errmsg);
45static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
46
5537f9b9
NA
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.
9402cc59
NA
50
51 Returns 0 on success, or an errno, or an ECTF_* value. */
52int
5537f9b9
NA
53ctf_arc_write_fd (int fd, ctf_file_t **ctf_files, size_t ctf_file_cnt,
54 const char **names, size_t threshold)
9402cc59
NA
55{
56 const char *errmsg;
57 struct ctf_archive *archdr;
9402cc59
NA
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
5537f9b9 68 ctf_dprintf ("Writing CTF archive with %lu files\n",
62d8e3b7 69 (unsigned long) ctf_file_cnt);
9402cc59 70
9402cc59
NA
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);
62d8e3b7 77 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
9402cc59
NA
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 {
5537f9b9
NA
85 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
86 goto err;
9402cc59
NA
87 }
88
89 if (write (fd, &dummy, 1) < 0)
90 {
5537f9b9
NA
91 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
92 goto err;
9402cc59
NA
93 }
94
95 if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
96 {
5537f9b9
NA
97 errmsg = "ctf_arc_write(): Cannot mmap(): %s\n";
98 goto err;
9402cc59
NA
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 {
5537f9b9 131 errmsg = "Error writing named CTF to archive: %s\n";
9402cc59
NA
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);
9402cc59
NA
145 if ((off < 0) && (off > -ECTF_BASE))
146 {
147 errmsg = "ctf_arc_write(): Cannot determine file "
5537f9b9 148 "position while writing to archive: %s";
9402cc59
NA
149 goto err_free;
150 }
151 if (off < 0)
152 {
5537f9b9 153 errmsg = "ctf_arc_write(): Cannot write CTF file to archive: %s\n";
9402cc59
NA
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
6b22174f
NA
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);
9402cc59
NA
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 "
5537f9b9 175 "in archive: %s\n";
9402cc59
NA
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 {
5537f9b9 185 errmsg = "ctf_arc_write(): Cannot write name table to archive: %s\n";
9402cc59
NA
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)
5537f9b9 196 goto err;
9402cc59
NA
197 return 0;
198
199err_free:
200 free (nametbl);
201err_unmap:
202 arc_mmap_unmap (archdr, headersz, NULL);
9402cc59 203err:
5537f9b9 204 ctf_dprintf (errmsg, errno < ECTF_BASE ? strerror (errno) :
9402cc59
NA
205 ctf_errmsg (errno));
206 return errno;
207}
208
5537f9b9
NA
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. */
215int
216ctf_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)
df16e041 231 goto err_close;
5537f9b9
NA
232
233 if ((err = close (fd)) < 0)
df16e041
NC
234 ctf_dprintf ("ctf_arc_write(): Cannot close after writing to archive: "
235 "%s\n", strerror (errno));
236 goto err;
5537f9b9
NA
237
238 err_close:
df16e041
NC
239 (void) close (fd);
240 err:
5537f9b9
NA
241 if (err < 0)
242 unlink (file);
243
244 return err;
245}
246
9402cc59
NA
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. */
251static off_t
252arc_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
676c3ecb
NA
260 if (ctf_serialize (f) < 0)
261 return f->ctf_errno * -1;
262
9402cc59
NA
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. */
314static int
315sort_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
2e428e74 325/* bsearch_r() function to search for a given name in the sorted array of struct
9402cc59
NA
326 ctf_archive_modents. */
327static int
2e428e74 328search_modent_by_name (const void *key, const void *ent, void *arg)
9402cc59
NA
329{
330 const char *k = key;
331 const struct ctf_archive_modent *v = ent;
2e428e74 332 const char *search_nametbl = arg;
9402cc59
NA
333
334 return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
335}
336
2f6ecaed
NA
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. */
340
341struct ctf_archive_internal *
342ctf_new_archive_internal (int is_archive, struct ctf_archive *arc,
343 ctf_file_t *fp, const ctf_sect_t *symsect,
344 const ctf_sect_t *strsect,
345 int *errp)
9402cc59 346{
2f6ecaed 347 struct ctf_archive_internal *arci;
9402cc59 348
2f6ecaed 349 if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL)
9402cc59 350 {
2f6ecaed
NA
351 if (is_archive)
352 ctf_arc_close_internal (arc);
353 else
354 ctf_file_close (fp);
355 return (ctf_set_open_errno (errp, errno));
9402cc59 356 }
2f6ecaed
NA
357 arci->ctfi_is_archive = is_archive;
358 if (is_archive)
359 arci->ctfi_archive = arc;
360 else
361 arci->ctfi_file = fp;
362 if (symsect)
363 memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect));
364 if (strsect)
365 memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
366 arci->ctfi_free_symsect = 0;
367
368 return arci;
369}
370
371/* Open a CTF archive or dictionary from data in a buffer (which the caller must
372 preserve until ctf_arc_close() time). Returns the archive, or NULL and an
373 error in *err (if not NULL). */
374ctf_archive_t *
375ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
376 const ctf_sect_t *strsect, int *errp)
377{
378 struct ctf_archive *arc = NULL;
379 int is_archive;
380 ctf_file_t *fp = NULL;
381
382 if (ctfsect->cts_size > sizeof (uint64_t) &&
383 ((*(uint64_t *) ctfsect->cts_data) == CTFA_MAGIC))
384 {
385 /* The archive is mmappable, so this operation is trivial. */
386
387 is_archive = 1;
388 arc = (struct ctf_archive *) ctfsect->cts_data;
389 }
390 else
391 {
392 is_archive = 0;
393 if ((fp = ctf_bufopen (ctfsect, symsect, strsect, errp)) == NULL)
394 {
395 ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n",
396 ctf_errmsg (*errp));
397 return NULL;
398 }
399 }
400 return ctf_new_archive_internal (is_archive, arc, fp, symsect, strsect,
401 errp);
9402cc59
NA
402}
403
404/* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
405 not NULL). */
406struct ctf_archive *
407ctf_arc_open_internal (const char *filename, int *errp)
408{
409 const char *errmsg;
410 int fd;
411 struct stat s;
412 struct ctf_archive *arc; /* (Actually the whole file.) */
413
414 libctf_init_debug();
415 if ((fd = open (filename, O_RDONLY)) < 0)
416 {
417 errmsg = "ctf_arc_open(): cannot open %s: %s\n";
418 goto err;
419 }
420 if (fstat (fd, &s) < 0)
421 {
422 errmsg = "ctf_arc_open(): cannot stat %s: %s\n";
423 goto err_close;
424 }
425
426 if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
427 {
428 errmsg = "ctf_arc_open(): Cannot read in %s: %s\n";
429 goto err_close;
430 }
431
432 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
433 {
434 errmsg = "ctf_arc_open(): Invalid magic number";
435 errno = ECTF_FMT;
436 goto err_unmap;
437 }
438
439 /* This horrible hack lets us know how much to unmap when the file is
440 closed. (We no longer need the magic number, and the mapping
441 is private.) */
442 arc->ctfa_magic = s.st_size;
443 close (fd);
444 return arc;
445
446err_unmap:
447 arc_mmap_unmap (arc, s.st_size, NULL);
448err_close:
449 close (fd);
450err:
451 if (errp)
452 *errp = errno;
453 ctf_dprintf (errmsg, filename, errno < ECTF_BASE ? strerror (errno) :
454 ctf_errmsg (errno));
455 return NULL;
456}
457
458/* Close an archive. */
459void
460ctf_arc_close_internal (struct ctf_archive *arc)
461{
462 if (arc == NULL)
463 return;
464
465 /* See the comment in ctf_arc_open(). */
466 arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
467}
468
469/* Public entry point: close an archive, or CTF file. */
470void
471ctf_arc_close (ctf_archive_t *arc)
472{
473 if (arc == NULL)
474 return;
475
476 if (arc->ctfi_is_archive)
477 ctf_arc_close_internal (arc->ctfi_archive);
478 else
479 ctf_file_close (arc->ctfi_file);
2f6ecaed
NA
480 if (arc->ctfi_free_symsect)
481 free ((void *) arc->ctfi_symsect.cts_data);
9402cc59 482 free (arc->ctfi_data);
f046147d
NA
483 if (arc->ctfi_bfd_close)
484 arc->ctfi_bfd_close (arc);
9402cc59
NA
485 free (arc);
486}
487
488/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
489 non-NULL. A name of NULL means to open the default file. */
490static ctf_file_t *
491ctf_arc_open_by_name_internal (const struct ctf_archive *arc,
492 const ctf_sect_t *symsect,
493 const ctf_sect_t *strsect,
494 const char *name, int *errp)
495{
496 struct ctf_archive_modent *modent;
2e428e74 497 const char *search_nametbl;
9402cc59
NA
498
499 if (name == NULL)
500 name = _CTF_SECTION; /* The default name. */
501
502 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
503
504 modent = (ctf_archive_modent_t *) ((char *) arc
505 + sizeof (struct ctf_archive));
506
2e428e74
NA
507 search_nametbl = (const char *) arc + le64toh (arc->ctfa_names);
508 modent = bsearch_r (name, modent, le64toh (arc->ctfa_nfiles),
509 sizeof (struct ctf_archive_modent),
510 search_modent_by_name, (void *) search_nametbl);
9402cc59
NA
511
512 /* This is actually a common case and normal operation: no error
513 debug output. */
514 if (modent == NULL)
515 {
516 if (errp)
517 *errp = ECTF_ARNNAME;
518 return NULL;
519 }
520
521 return ctf_arc_open_by_offset (arc, symsect, strsect,
522 le64toh (modent->ctf_offset), errp);
523}
524
525/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
526 non-NULL. A name of NULL means to open the default file.
527
528 Use the specified string and symbol table sections.
529
530 Public entry point. */
531ctf_file_t *
532ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
533 const ctf_sect_t *symsect,
534 const ctf_sect_t *strsect,
535 const char *name,
536 int *errp)
537{
538 if (arc->ctfi_is_archive)
539 {
540 ctf_file_t *ret;
541 ret = ctf_arc_open_by_name_internal (arc->ctfi_archive, symsect, strsect,
542 name, errp);
543 if (ret)
544 ret->ctf_archive = (ctf_archive_t *) arc;
545 return ret;
546 }
547
548 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
549 {
550 if (errp)
551 *errp = ECTF_ARNNAME;
552 return NULL;
553 }
554 arc->ctfi_file->ctf_archive = (ctf_archive_t *) arc;
555
556 /* Bump the refcount so that the user can ctf_file_close() it. */
557 arc->ctfi_file->ctf_refcnt++;
558 return arc->ctfi_file;
559}
560
561/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
562 non-NULL. A name of NULL means to open the default file.
563
564 Public entry point. */
565ctf_file_t *
566ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name, int *errp)
567{
568 const ctf_sect_t *symsect = &arc->ctfi_symsect;
569 const ctf_sect_t *strsect = &arc->ctfi_strsect;
570
571 if (symsect->cts_name == NULL)
572 symsect = NULL;
573 if (strsect->cts_name == NULL)
574 strsect = NULL;
575
576 return ctf_arc_open_by_name_sections (arc, symsect, strsect, name, errp);
577}
578
579/* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
580 none, setting 'err' if non-NULL. */
581static ctf_file_t *
582ctf_arc_open_by_offset (const struct ctf_archive *arc,
583 const ctf_sect_t *symsect,
584 const ctf_sect_t *strsect, size_t offset,
585 int *errp)
586{
587 ctf_sect_t ctfsect;
588 ctf_file_t *fp;
589
62d8e3b7 590 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
9402cc59 591
a0486bac 592 memset (&ctfsect, 0, sizeof (ctf_sect_t));
9402cc59
NA
593
594 offset += le64toh (arc->ctfa_ctfs);
595
596 ctfsect.cts_name = _CTF_SECTION;
9402cc59
NA
597 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
598 ctfsect.cts_entsize = 1;
9402cc59
NA
599 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
600 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
601 if (fp)
602 ctf_setmodel (fp, le64toh (arc->ctfa_model));
603 return fp;
604}
605
606/* Raw iteration over all CTF files in an archive. We pass the raw data for all
607 CTF files in turn to the specified callback function. */
608static int
609ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
610 ctf_archive_raw_member_f *func, void *data)
611{
612 int rc;
613 size_t i;
614 struct ctf_archive_modent *modent;
615 const char *nametbl;
616
617 modent = (ctf_archive_modent_t *) ((char *) arc
618 + sizeof (struct ctf_archive));
619 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
620
621 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
622 {
623 const char *name;
624 char *fp;
625
626 name = &nametbl[le64toh (modent[i].name_offset)];
627 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
628 + le64toh (modent[i].ctf_offset));
629
630 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
631 le64toh (*((uint64_t *) fp)), data)) != 0)
632 return rc;
633 }
634 return 0;
635}
636
637/* Raw iteration over all CTF files in an archive: public entry point.
638
639 Returns -EINVAL if not supported for this sort of archive. */
640int
641ctf_archive_raw_iter (const ctf_archive_t *arc,
642 ctf_archive_raw_member_f * func, void *data)
643{
644 if (arc->ctfi_is_archive)
645 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
646
647 return -EINVAL; /* Not supported. */
648}
649
650/* Iterate over all CTF files in an archive. We pass all CTF files in turn to
651 the specified callback function. */
652static int
653ctf_archive_iter_internal (const ctf_archive_t *wrapper,
654 const struct ctf_archive *arc,
655 const ctf_sect_t *symsect,
656 const ctf_sect_t *strsect,
657 ctf_archive_member_f *func, void *data)
658{
659 int rc;
660 size_t i;
661 ctf_file_t *f;
662 struct ctf_archive_modent *modent;
663 const char *nametbl;
664
665 modent = (ctf_archive_modent_t *) ((char *) arc
666 + sizeof (struct ctf_archive));
667 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
668
669 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
670 {
671 const char *name;
672
673 name = &nametbl[le64toh (modent[i].name_offset)];
674 if ((f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
675 name, &rc)) == NULL)
676 return rc;
677
678 f->ctf_archive = (ctf_archive_t *) wrapper;
679 if ((rc = func (f, name, data)) != 0)
680 {
681 ctf_file_close (f);
682 return rc;
683 }
684
685 ctf_file_close (f);
686 }
687 return 0;
688}
689
690/* Iterate over all CTF files in an archive: public entry point. We pass all
691 CTF files in turn to the specified callback function. */
692int
693ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
694 void *data)
695{
696 const ctf_sect_t *symsect = &arc->ctfi_symsect;
697 const ctf_sect_t *strsect = &arc->ctfi_strsect;
698
699 if (symsect->cts_name == NULL)
700 symsect = NULL;
701 if (strsect->cts_name == NULL)
702 strsect = NULL;
703
704 if (arc->ctfi_is_archive)
705 return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
706 func, data);
707
708 return func (arc->ctfi_file, _CTF_SECTION, data);
709}
710
711#ifdef HAVE_MMAP
712/* Map the header in. Only used on new, empty files. */
713static void *arc_mmap_header (int fd, size_t headersz)
714{
715 void *hdr;
716 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
717 0)) == MAP_FAILED)
718 return NULL;
719 return hdr;
720}
721
722/* mmap() the whole file, for reading only. (Map it writably, but privately: we
723 need to modify the region, but don't need anyone else to see the
724 modifications.) */
725static void *arc_mmap_file (int fd, size_t size)
726{
727 void *arc;
728 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
729 fd, 0)) == MAP_FAILED)
730 return NULL;
731 return arc;
732}
733
734/* Persist the header to disk. */
735static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
736 size_t headersz, const char **errmsg)
737{
738 if (msync (header, headersz, MS_ASYNC) < 0)
739 {
740 if (errmsg)
741 *errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
742 return -1;
743 }
744 return 0;
745}
746
747/* Unmap the region. */
748static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
749{
750 if (munmap (header, headersz) < 0)
751 {
752 if (errmsg)
753 *errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
754 return -1;
755 }
756 return 0;
757}
758#else
759/* Map the header in. Only used on new, empty files. */
f5e73be1 760static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
9402cc59
NA
761{
762 void *hdr;
763 if ((hdr = malloc (headersz)) == NULL)
764 return NULL;
765 return hdr;
766}
767
768/* Pull in the whole file, for reading only. We assume the current file
769 position is at the start of the file. */
770static void *arc_mmap_file (int fd, size_t size)
771{
772 char *data;
773
774 if ((data = malloc (size)) == NULL)
775 return NULL;
776
777 if (ctf_pread (fd, data, size, 0) < 0)
778 {
779 free (data);
780 return NULL;
781 }
782 return data;
783}
784
785/* Persist the header to disk. */
786static int arc_mmap_writeout (int fd, void *header, size_t headersz,
787 const char **errmsg)
788{
789 ssize_t len;
790 size_t acc = 0;
791 char *data = (char *) header;
792 ssize_t count = headersz;
793
794 if ((lseek (fd, 0, SEEK_SET)) < 0)
795 {
796 if (errmsg)
797 *errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
798 "%s: %s\n";
799 return -1;
800 }
801
802 while (headersz > 0)
803 {
804 if ((len = write (fd, data, count)) < 0)
805 {
806 if (errmsg)
807 *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
808 return len;
809 }
810 if (len == EINTR)
811 continue;
812
813 acc += len;
814 if (len == 0) /* EOF. */
815 break;
816
817 count -= len;
818 data += len;
819 }
820 return 0;
821}
822
823/* Unmap the region. */
824static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
825 const char **errmsg _libctf_unused_)
826{
827 free (header);
828 return 0;
829}
830#endif