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