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