]> Git Repo - binutils.git/blob - libctf/ctf-archive.c
54d3d0a48f8f2b6db2da64b9e7b61091e9bc0bb8
[binutils.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
This page took 0.069227 seconds and 2 git commands to generate.