]> Git Repo - binutils.git/blob - libctf/ctf-archive.c
25c30f64b50eba7963a1cc1a362c94e9bba24cd3
[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_dict_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 /* Get the CTF preamble from data in a buffer, which may be either an archive or
381    a CTF dict.  If multiple dicts are present in an archive, the preamble comes
382    from an arbitrary dict.  The preamble is a pointer into the ctfsect passed
383    in.  */
384
385 const ctf_preamble_t *
386 ctf_arc_bufpreamble (const ctf_sect_t *ctfsect)
387 {
388   if (ctfsect->cts_size > sizeof (uint64_t) &&
389       (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
390     {
391       struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data;
392       return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs)
393                                        + sizeof (uint64_t));
394     }
395   else
396     return (const ctf_preamble_t *) ctfsect->cts_data;
397 }
398
399 /* Open a CTF archive or dictionary from data in a buffer (which the caller must
400    preserve until ctf_arc_close() time).  Returns the archive, or NULL and an
401    error in *err (if not NULL).  */
402 ctf_archive_t *
403 ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
404                  const ctf_sect_t *strsect, int *errp)
405 {
406   struct ctf_archive *arc = NULL;
407   int is_archive;
408   ctf_dict_t *fp = NULL;
409
410   if (ctfsect->cts_size > sizeof (uint64_t) &&
411       (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
412     {
413       /* The archive is mmappable, so this operation is trivial.
414
415          This buffer is nonmodifiable, so the trick involving mmapping only part
416          of it and storing the length in the magic number is not applicable: so
417          record this fact in the archive-wrapper header.  (We cannot record it
418          in the archive, because the archive may very well be a read-only
419          mapping.)  */
420
421       is_archive = 1;
422       arc = (struct ctf_archive *) ctfsect->cts_data;
423     }
424   else
425     {
426       is_archive = 0;
427       if ((fp = ctf_bufopen (ctfsect, symsect, strsect, errp)) == NULL)
428         {
429           ctf_err_warn (NULL, 0, *errp, _("ctf_arc_bufopen(): cannot open CTF"));
430           return NULL;
431         }
432     }
433   return ctf_new_archive_internal (is_archive, 0, arc, fp, symsect, strsect,
434                                    errp);
435 }
436
437 /* Open a CTF archive.  Returns the archive, or NULL and an error in *err (if
438    not NULL).  */
439 struct ctf_archive *
440 ctf_arc_open_internal (const char *filename, int *errp)
441 {
442   const char *errmsg;
443   int fd;
444   struct stat s;
445   struct ctf_archive *arc;              /* (Actually the whole file.)  */
446
447   libctf_init_debug();
448   if ((fd = open (filename, O_RDONLY)) < 0)
449     {
450       errmsg = N_("ctf_arc_open(): cannot open %s");
451       goto err;
452     }
453   if (fstat (fd, &s) < 0)
454     {
455       errmsg = N_("ctf_arc_open(): cannot stat %s");
456       goto err_close;
457     }
458
459   if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
460     {
461       errmsg = N_("ctf_arc_open(): cannot read in %s");
462       goto err_close;
463     }
464
465   if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
466     {
467       errmsg = N_("ctf_arc_open(): %s: invalid magic number");
468       errno = ECTF_FMT;
469       goto err_unmap;
470     }
471
472   /* This horrible hack lets us know how much to unmap when the file is
473      closed.  (We no longer need the magic number, and the mapping
474      is private.)  */
475   arc->ctfa_magic = s.st_size;
476   close (fd);
477   return arc;
478
479 err_unmap:
480   arc_mmap_unmap (arc, s.st_size, NULL);
481 err_close:
482   close (fd);
483 err:
484   if (errp)
485     *errp = errno;
486   ctf_err_warn (NULL, 0, errno, gettext (errmsg), filename);
487   return NULL;
488 }
489
490 /* Close an archive.  */
491 void
492 ctf_arc_close_internal (struct ctf_archive *arc)
493 {
494   if (arc == NULL)
495     return;
496
497   /* See the comment in ctf_arc_open().  */
498   arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
499 }
500
501 /* Public entry point: close an archive, or CTF file.  */
502 void
503 ctf_arc_close (ctf_archive_t *arc)
504 {
505   if (arc == NULL)
506     return;
507
508   if (arc->ctfi_is_archive)
509     {
510       if (arc->ctfi_unmap_on_close)
511         ctf_arc_close_internal (arc->ctfi_archive);
512     }
513   else
514     ctf_dict_close (arc->ctfi_dict);
515   if (arc->ctfi_free_symsect)
516     free ((void *) arc->ctfi_symsect.cts_data);
517   if (arc->ctfi_free_strsect)
518     free ((void *) arc->ctfi_strsect.cts_data);
519   free (arc->ctfi_data);
520   if (arc->ctfi_bfd_close)
521     arc->ctfi_bfd_close (arc);
522   free (arc);
523 }
524
525 /* Return the ctf_dict_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 static ctf_dict_t *
528 ctf_dict_open_internal (const struct ctf_archive *arc,
529                         const ctf_sect_t *symsect,
530                         const ctf_sect_t *strsect,
531                         const char *name, int *errp)
532 {
533   struct ctf_archive_modent *modent;
534   const char *search_nametbl;
535
536   if (name == NULL)
537     name = _CTF_SECTION;                 /* The default name.  */
538
539   ctf_dprintf ("ctf_dict_open_internal(%s): opening\n", name);
540
541   modent = (ctf_archive_modent_t *) ((char *) arc
542                                      + sizeof (struct ctf_archive));
543
544   search_nametbl = (const char *) arc + le64toh (arc->ctfa_names);
545   modent = bsearch_r (name, modent, le64toh (arc->ctfa_ndicts),
546                       sizeof (struct ctf_archive_modent),
547                       search_modent_by_name, (void *) search_nametbl);
548
549   /* This is actually a common case and normal operation: no error
550      debug output.  */
551   if (modent == NULL)
552     {
553       if (errp)
554         *errp = ECTF_ARNNAME;
555       return NULL;
556     }
557
558   return ctf_dict_open_by_offset (arc, symsect, strsect,
559                                   le64toh (modent->ctf_offset), errp);
560 }
561
562 /* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
563    non-NULL.  A name of NULL means to open the default file.
564
565    Use the specified string and symbol table sections.
566
567    Public entry point.  */
568 ctf_dict_t *
569 ctf_dict_open_sections (const ctf_archive_t *arc,
570                         const ctf_sect_t *symsect,
571                         const ctf_sect_t *strsect,
572                         const char *name,
573                         int *errp)
574 {
575   if (arc->ctfi_is_archive)
576     {
577       ctf_dict_t *ret;
578       ret = ctf_dict_open_internal (arc->ctfi_archive, symsect, strsect,
579                                     name, errp);
580       if (ret)
581         ret->ctf_archive = (ctf_archive_t *) arc;
582       return ret;
583     }
584
585   if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
586     {
587       if (errp)
588         *errp = ECTF_ARNNAME;
589       return NULL;
590     }
591   arc->ctfi_dict->ctf_archive = (ctf_archive_t *) arc;
592
593   /* Bump the refcount so that the user can ctf_dict_close() it.  */
594   arc->ctfi_dict->ctf_refcnt++;
595   return arc->ctfi_dict;
596 }
597
598 /* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
599    non-NULL.  A name of NULL means to open the default file.
600
601    Public entry point.  */
602 ctf_dict_t *
603 ctf_dict_open (const ctf_archive_t *arc, const char *name, int *errp)
604 {
605   const ctf_sect_t *symsect = &arc->ctfi_symsect;
606   const ctf_sect_t *strsect = &arc->ctfi_strsect;
607
608   if (symsect->cts_name == NULL)
609     symsect = NULL;
610   if (strsect->cts_name == NULL)
611     strsect = NULL;
612
613   return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
614 }
615
616 /* Return the ctf_dict_t at the given ctfa_ctfs-relative offset, or NULL if
617    none, setting 'err' if non-NULL.  */
618 static ctf_dict_t *
619 ctf_dict_open_by_offset (const struct ctf_archive *arc,
620                          const ctf_sect_t *symsect,
621                          const ctf_sect_t *strsect, size_t offset,
622                          int *errp)
623 {
624   ctf_sect_t ctfsect;
625   ctf_dict_t *fp;
626
627   ctf_dprintf ("ctf_dict_open_by_offset(%lu): opening\n", (unsigned long) offset);
628
629   memset (&ctfsect, 0, sizeof (ctf_sect_t));
630
631   offset += le64toh (arc->ctfa_ctfs);
632
633   ctfsect.cts_name = _CTF_SECTION;
634   ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
635   ctfsect.cts_entsize = 1;
636   ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
637   fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
638   if (fp)
639     ctf_setmodel (fp, le64toh (arc->ctfa_model));
640   return fp;
641 }
642
643 /* Backward compatibility.  */
644 ctf_dict_t *
645 ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name,
646                       int *errp)
647 {
648   return ctf_dict_open (arc, name, errp);
649 }
650
651 ctf_dict_t *
652 ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
653                                const ctf_sect_t *symsect,
654                                const ctf_sect_t *strsect,
655                                const char *name,
656                                int *errp)
657 {
658   return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
659 }
660
661 /* Return the number of members in an archive.  */
662 size_t
663 ctf_archive_count (const ctf_archive_t *wrapper)
664 {
665   if (!wrapper->ctfi_is_archive)
666     return 1;
667
668   return wrapper->ctfi_archive->ctfa_ndicts;
669 }
670
671 /* Raw iteration over all CTF files in an archive.  We pass the raw data for all
672    CTF files in turn to the specified callback function.  */
673 static int
674 ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
675                                ctf_archive_raw_member_f *func, void *data)
676 {
677   int rc;
678   size_t i;
679   struct ctf_archive_modent *modent;
680   const char *nametbl;
681
682   modent = (ctf_archive_modent_t *) ((char *) arc
683                                      + sizeof (struct ctf_archive));
684   nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
685
686   for (i = 0; i < le64toh (arc->ctfa_ndicts); i++)
687     {
688       const char *name;
689       char *fp;
690
691       name = &nametbl[le64toh (modent[i].name_offset)];
692       fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
693             + le64toh (modent[i].ctf_offset));
694
695       if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
696                       le64toh (*((uint64_t *) fp)), data)) != 0)
697         return rc;
698     }
699   return 0;
700 }
701
702 /* Raw iteration over all CTF files in an archive: public entry point.
703
704    Returns -EINVAL if not supported for this sort of archive.  */
705 int
706 ctf_archive_raw_iter (const ctf_archive_t *arc,
707                       ctf_archive_raw_member_f * func, void *data)
708 {
709   if (arc->ctfi_is_archive)
710     return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
711
712   return -EINVAL;                        /* Not supported. */
713 }
714
715 /* Iterate over all CTF files in an archive.  We pass all CTF files in turn to
716    the specified callback function.  */
717 static int
718 ctf_archive_iter_internal (const ctf_archive_t *wrapper,
719                            const struct ctf_archive *arc,
720                            const ctf_sect_t *symsect,
721                            const ctf_sect_t *strsect,
722                            ctf_archive_member_f *func, void *data)
723 {
724   int rc;
725   size_t i;
726   ctf_dict_t *f;
727   struct ctf_archive_modent *modent;
728   const char *nametbl;
729
730   modent = (ctf_archive_modent_t *) ((char *) arc
731                                      + sizeof (struct ctf_archive));
732   nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
733
734   for (i = 0; i < le64toh (arc->ctfa_ndicts); i++)
735     {
736       const char *name;
737
738       name = &nametbl[le64toh (modent[i].name_offset)];
739       if ((f = ctf_dict_open_internal (arc, symsect, strsect,
740                                     name, &rc)) == NULL)
741         return rc;
742
743       f->ctf_archive = (ctf_archive_t *) wrapper;
744       if ((rc = func (f, name, data)) != 0)
745         {
746           ctf_dict_close (f);
747           return rc;
748         }
749
750       ctf_dict_close (f);
751     }
752   return 0;
753 }
754
755 /* Iterate over all CTF files in an archive: public entry point.  We pass all
756    CTF files in turn to the specified callback function.  */
757 int
758 ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
759                   void *data)
760 {
761   const ctf_sect_t *symsect = &arc->ctfi_symsect;
762   const ctf_sect_t *strsect = &arc->ctfi_strsect;
763
764   if (symsect->cts_name == NULL)
765     symsect = NULL;
766   if (strsect->cts_name == NULL)
767     strsect = NULL;
768
769   if (arc->ctfi_is_archive)
770     return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
771                                       func, data);
772
773   return func (arc->ctfi_dict, _CTF_SECTION, data);
774 }
775
776 /* Iterate over all CTF files in an archive, returning each dict in turn as a
777    ctf_dict_t, and NULL on error or end of iteration.  It is the caller's
778    responsibility to close it.  Parent dicts may be skipped.  Regardless of
779    whether they are skipped or not, the caller must ctf_import the parent if
780    need be.
781
782    We identify parents by name rather than by flag value: for now, with the
783    linker only emitting parents named _CTF_SECTION, this works well enough.  */
784
785 ctf_dict_t *
786 ctf_archive_next (const ctf_archive_t *wrapper, ctf_next_t **it, const char **name,
787                   int skip_parent, int *errp)
788 {
789   ctf_dict_t *f;
790   ctf_next_t *i = *it;
791   struct ctf_archive *arc;
792   struct ctf_archive_modent *modent;
793   const char *nametbl;
794   const char *name_;
795
796   if (!i)
797     {
798       if ((i = ctf_next_create()) == NULL)
799         {
800           if (errp)
801             *errp = ENOMEM;
802           return NULL;
803         }
804       i->cu.ctn_arc = wrapper;
805       i->ctn_iter_fun = (void (*) (void)) ctf_archive_next;
806       *it = i;
807     }
808
809   if ((void (*) (void)) ctf_archive_next != i->ctn_iter_fun)
810     {
811       if (errp)
812         *errp = ECTF_NEXT_WRONGFUN;
813       return NULL;
814     }
815
816   if (wrapper != i->cu.ctn_arc)
817     {
818       if (errp)
819         *errp = ECTF_NEXT_WRONGFP;
820       return NULL;
821     }
822
823   /* Iteration is made a bit more complex by the need to handle ctf_dict_t's
824      transparently wrapped in a single-member archive.  These are parents: if
825      skip_parent is on, they are skipped and the iterator terminates
826      immediately.  */
827
828   if (!wrapper->ctfi_is_archive && i->ctn_n == 0)
829     {
830       i->ctn_n++;
831       if (!skip_parent)
832         {
833           wrapper->ctfi_dict->ctf_refcnt++;
834           return wrapper->ctfi_dict;
835         }
836     }
837
838   arc = wrapper->ctfi_archive;
839
840   /* The loop keeps going when skip_parent is on as long as the member we find
841      is the parent (i.e. at most two iterations, but possibly an early return if
842      *all* we have is a parent).  */
843
844   const ctf_sect_t *symsect;
845   const ctf_sect_t *strsect;
846
847   do
848     {
849       if ((!wrapper->ctfi_is_archive) || (i->ctn_n >= le64toh (arc->ctfa_ndicts)))
850         {
851           ctf_next_destroy (i);
852           *it = NULL;
853           if (errp)
854             *errp = ECTF_NEXT_END;
855           return NULL;
856         }
857
858       symsect = &wrapper->ctfi_symsect;
859       strsect = &wrapper->ctfi_strsect;
860
861       if (symsect->cts_name == NULL)
862         symsect = NULL;
863       if (strsect->cts_name == NULL)
864         strsect = NULL;
865
866       modent = (ctf_archive_modent_t *) ((char *) arc
867                                          + sizeof (struct ctf_archive));
868       nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
869
870       name_ = &nametbl[le64toh (modent[i->ctn_n].name_offset)];
871       i->ctn_n++;
872     } while (skip_parent && strcmp (name_, _CTF_SECTION) == 0);
873
874   if (name)
875     *name = name_;
876
877   f = ctf_dict_open_internal (arc, symsect, strsect, name_, errp);
878   f->ctf_archive = (ctf_archive_t *) wrapper;
879   return f;
880 }
881
882 #ifdef HAVE_MMAP
883 /* Map the header in.  Only used on new, empty files.  */
884 static void *arc_mmap_header (int fd, size_t headersz)
885 {
886   void *hdr;
887   if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
888                    0)) == MAP_FAILED)
889     return NULL;
890   return hdr;
891 }
892
893 /* mmap() the whole file, for reading only.  (Map it writably, but privately: we
894    need to modify the region, but don't need anyone else to see the
895    modifications.)  */
896 static void *arc_mmap_file (int fd, size_t size)
897 {
898   void *arc;
899   if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
900                    fd, 0)) == MAP_FAILED)
901     return NULL;
902   return arc;
903 }
904
905 /* Persist the header to disk.  */
906 static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
907                               size_t headersz, const char **errmsg)
908 {
909     if (msync (header, headersz, MS_ASYNC) < 0)
910     {
911       if (errmsg)
912         *errmsg = N_("arc_mmap_writeout(): cannot sync after writing "
913                      "to %s: %s");
914       return -1;
915     }
916     return 0;
917 }
918
919 /* Unmap the region.  */
920 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
921 {
922   if (munmap (header, headersz) < 0)
923     {
924       if (errmsg)
925         *errmsg = N_("arc_mmap_munmap(): cannot unmap after writing "
926                      "to %s: %s");
927       return -1;
928     }
929     return 0;
930 }
931 #else
932 /* Map the header in.  Only used on new, empty files.  */
933 static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
934 {
935   void *hdr;
936   if ((hdr = malloc (headersz)) == NULL)
937     return NULL;
938   return hdr;
939 }
940
941 /* Pull in the whole file, for reading only.  We assume the current file
942    position is at the start of the file.  */
943 static void *arc_mmap_file (int fd, size_t size)
944 {
945   char *data;
946
947   if ((data = malloc (size)) == NULL)
948     return NULL;
949
950   if (ctf_pread (fd, data, size, 0) < 0)
951     {
952       free (data);
953       return NULL;
954     }
955   return data;
956 }
957
958 /* Persist the header to disk.  */
959 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
960                               const char **errmsg)
961 {
962   ssize_t len;
963   size_t acc = 0;
964   char *data = (char *) header;
965   ssize_t count = headersz;
966
967   if ((lseek (fd, 0, SEEK_SET)) < 0)
968     {
969       if (errmsg)
970         *errmsg = N_("arc_mmap_writeout(): cannot seek while writing header to "
971                      "%s: %s");
972       return -1;
973     }
974
975   while (headersz > 0)
976     {
977       if ((len = write (fd, data, count)) < 0)
978         {
979           if (errmsg)
980             *errmsg = N_("arc_mmap_writeout(): cannot write header to %s: %s");
981           return len;
982         }
983       if (len == EINTR)
984         continue;
985
986       acc += len;
987       if (len == 0)                             /* EOF.  */
988         break;
989
990       count -= len;
991       data += len;
992     }
993   return 0;
994 }
995
996 /* Unmap the region.  */
997 static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
998                            const char **errmsg _libctf_unused_)
999 {
1000   free (header);
1001   return 0;
1002 }
1003 #endif
This page took 0.073175 seconds and 2 git commands to generate.