libctf: compilation failure on MinGW due to missing errno values
[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)
df16e041 231 goto err_close;
5537f9b9
NA
232
233 if ((err = close (fd)) < 0)
df16e041
NC
234 ctf_dprintf ("ctf_arc_write(): Cannot close after writing to archive: "
235 "%s\n", strerror (errno));
236 goto err;
5537f9b9
NA
237
238 err_close:
df16e041
NC
239 (void) close (fd);
240 err:
5537f9b9
NA
241 if (err < 0)
242 unlink (file);
243
244 return err;
245}
246
9402cc59
NA
247/* Write one CTF file out. Return the file position of the written file (or
248 rather, of the file-size uint64_t that precedes it): negative return is a
249 negative errno or ctf_errno value. On error, the file position may no longer
250 be at the end of the file. */
251static off_t
252arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold)
253{
254 off_t off, end_off;
255 uint64_t ctfsz = 0;
256 char *ctfszp;
257 size_t ctfsz_len;
258 int (*writefn) (ctf_file_t * fp, int fd);
259
676c3ecb
NA
260 if (ctf_serialize (f) < 0)
261 return f->ctf_errno * -1;
262
9402cc59
NA
263 if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
264 return errno * -1;
265
266 if (f->ctf_size > threshold)
267 writefn = ctf_compress_write;
268 else
269 writefn = ctf_write;
270
271 /* This zero-write turns into the size in a moment. */
272 ctfsz_len = sizeof (ctfsz);
273 ctfszp = (char *) &ctfsz;
274 while (ctfsz_len > 0)
275 {
276 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
277 if (writelen < 0)
278 return errno * -1;
279 ctfsz_len -= writelen;
280 ctfszp += writelen;
281 }
282
283 if (writefn (f, fd) != 0)
284 return f->ctf_errno * -1;
285
286 if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
287 return errno * -1;
288 ctfsz = htole64 (end_off - off);
289
290 if ((lseek (fd, off, SEEK_SET)) < 0)
291 return errno * -1;
292
293 /* ... here. */
294 ctfsz_len = sizeof (ctfsz);
295 ctfszp = (char *) &ctfsz;
296 while (ctfsz_len > 0)
297 {
298 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
299 if (writelen < 0)
300 return errno * -1;
301 ctfsz_len -= writelen;
302 ctfszp += writelen;
303 }
304
305 end_off = LCTF_ALIGN_OFFS (end_off, 8);
306 if ((lseek (fd, end_off, SEEK_SET)) < 0)
307 return errno * -1;
308
309 return off;
310}
311
312/* qsort() function to sort the array of struct ctf_archive_modents into
313 ascending name order. */
314static int
315sort_modent_by_name (const void *one, const void *two, void *n)
316{
317 const struct ctf_archive_modent *a = one;
318 const struct ctf_archive_modent *b = two;
319 char *nametbl = n;
320
321 return strcmp (&nametbl[le64toh (a->name_offset)],
322 &nametbl[le64toh (b->name_offset)]);
323}
324
2e428e74 325/* bsearch_r() function to search for a given name in the sorted array of struct
9402cc59
NA
326 ctf_archive_modents. */
327static int
2e428e74 328search_modent_by_name (const void *key, const void *ent, void *arg)
9402cc59
NA
329{
330 const char *k = key;
331 const struct ctf_archive_modent *v = ent;
2e428e74 332 const char *search_nametbl = arg;
9402cc59
NA
333
334 return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
335}
336
2f6ecaed
NA
337/* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
338 ctf_file. Closes ARC and/or FP on error. Arrange to free the SYMSECT or
601e455b 339 STRSECT, as needed, on close. Possibly do not unmap on close. */
2f6ecaed
NA
340
341struct ctf_archive_internal *
601e455b
NA
342ctf_new_archive_internal (int is_archive, int unmap_on_close,
343 struct ctf_archive *arc,
2f6ecaed
NA
344 ctf_file_t *fp, const ctf_sect_t *symsect,
345 const ctf_sect_t *strsect,
346 int *errp)
9402cc59 347{
2f6ecaed 348 struct ctf_archive_internal *arci;
9402cc59 349
2f6ecaed 350 if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL)
9402cc59 351 {
2f6ecaed 352 if (is_archive)
601e455b
NA
353 {
354 if (unmap_on_close)
355 ctf_arc_close_internal (arc);
356 }
2f6ecaed
NA
357 else
358 ctf_file_close (fp);
359 return (ctf_set_open_errno (errp, errno));
9402cc59 360 }
2f6ecaed
NA
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;
d50c0802 371 arci->ctfi_free_strsect = 0;
601e455b 372 arci->ctfi_unmap_on_close = unmap_on_close;
2f6ecaed
NA
373
374 return arci;
375}
376
377/* Open a CTF archive or dictionary from data in a buffer (which the caller must
378 preserve until ctf_arc_close() time). Returns the archive, or NULL and an
379 error in *err (if not NULL). */
380ctf_archive_t *
381ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
382 const ctf_sect_t *strsect, int *errp)
383{
384 struct ctf_archive *arc = NULL;
385 int is_archive;
386 ctf_file_t *fp = NULL;
387
388 if (ctfsect->cts_size > sizeof (uint64_t) &&
4533ed56 389 (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
2f6ecaed 390 {
601e455b
NA
391 /* The archive is mmappable, so this operation is trivial.
392
393 This buffer is nonmodifiable, so the trick involving mmapping only part
394 of it and storing the length in the magic number is not applicable: so
395 record this fact in the archive-wrapper header. (We cannot record it
396 in the archive, because the archive may very well be a read-only
397 mapping.) */
2f6ecaed
NA
398
399 is_archive = 1;
400 arc = (struct ctf_archive *) ctfsect->cts_data;
401 }
402 else
403 {
404 is_archive = 0;
405 if ((fp = ctf_bufopen (ctfsect, symsect, strsect, errp)) == NULL)
406 {
ac2ff760 407 ctf_dprintf ("ctf_arc_bufopen(): cannot open CTF: %s\n",
2f6ecaed
NA
408 ctf_errmsg (*errp));
409 return NULL;
410 }
411 }
601e455b 412 return ctf_new_archive_internal (is_archive, 0, arc, fp, symsect, strsect,
2f6ecaed 413 errp);
9402cc59
NA
414}
415
416/* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
417 not NULL). */
418struct ctf_archive *
419ctf_arc_open_internal (const char *filename, int *errp)
420{
421 const char *errmsg;
422 int fd;
423 struct stat s;
424 struct ctf_archive *arc; /* (Actually the whole file.) */
425
426 libctf_init_debug();
427 if ((fd = open (filename, O_RDONLY)) < 0)
428 {
429 errmsg = "ctf_arc_open(): cannot open %s: %s\n";
430 goto err;
431 }
432 if (fstat (fd, &s) < 0)
433 {
434 errmsg = "ctf_arc_open(): cannot stat %s: %s\n";
435 goto err_close;
436 }
437
438 if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
439 {
440 errmsg = "ctf_arc_open(): Cannot read in %s: %s\n";
441 goto err_close;
442 }
443
444 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
445 {
446 errmsg = "ctf_arc_open(): Invalid magic number";
447 errno = ECTF_FMT;
448 goto err_unmap;
449 }
450
451 /* This horrible hack lets us know how much to unmap when the file is
452 closed. (We no longer need the magic number, and the mapping
453 is private.) */
454 arc->ctfa_magic = s.st_size;
455 close (fd);
456 return arc;
457
458err_unmap:
459 arc_mmap_unmap (arc, s.st_size, NULL);
460err_close:
461 close (fd);
462err:
463 if (errp)
464 *errp = errno;
465 ctf_dprintf (errmsg, filename, errno < ECTF_BASE ? strerror (errno) :
466 ctf_errmsg (errno));
467 return NULL;
468}
469
470/* Close an archive. */
471void
472ctf_arc_close_internal (struct ctf_archive *arc)
473{
474 if (arc == NULL)
475 return;
476
477 /* See the comment in ctf_arc_open(). */
478 arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
479}
480
481/* Public entry point: close an archive, or CTF file. */
482void
483ctf_arc_close (ctf_archive_t *arc)
484{
485 if (arc == NULL)
486 return;
487
488 if (arc->ctfi_is_archive)
601e455b
NA
489 {
490 if (arc->ctfi_unmap_on_close)
491 ctf_arc_close_internal (arc->ctfi_archive);
492 }
9402cc59
NA
493 else
494 ctf_file_close (arc->ctfi_file);
2f6ecaed
NA
495 if (arc->ctfi_free_symsect)
496 free ((void *) arc->ctfi_symsect.cts_data);
d50c0802
NA
497 if (arc->ctfi_free_strsect)
498 free ((void *) arc->ctfi_strsect.cts_data);
9402cc59 499 free (arc->ctfi_data);
f046147d
NA
500 if (arc->ctfi_bfd_close)
501 arc->ctfi_bfd_close (arc);
9402cc59
NA
502 free (arc);
503}
504
505/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
506 non-NULL. A name of NULL means to open the default file. */
507static ctf_file_t *
508ctf_arc_open_by_name_internal (const struct ctf_archive *arc,
509 const ctf_sect_t *symsect,
510 const ctf_sect_t *strsect,
511 const char *name, int *errp)
512{
513 struct ctf_archive_modent *modent;
2e428e74 514 const char *search_nametbl;
9402cc59
NA
515
516 if (name == NULL)
517 name = _CTF_SECTION; /* The default name. */
518
519 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
520
521 modent = (ctf_archive_modent_t *) ((char *) arc
522 + sizeof (struct ctf_archive));
523
2e428e74
NA
524 search_nametbl = (const char *) arc + le64toh (arc->ctfa_names);
525 modent = bsearch_r (name, modent, le64toh (arc->ctfa_nfiles),
526 sizeof (struct ctf_archive_modent),
527 search_modent_by_name, (void *) search_nametbl);
9402cc59
NA
528
529 /* This is actually a common case and normal operation: no error
530 debug output. */
531 if (modent == NULL)
532 {
533 if (errp)
534 *errp = ECTF_ARNNAME;
535 return NULL;
536 }
537
538 return ctf_arc_open_by_offset (arc, symsect, strsect,
539 le64toh (modent->ctf_offset), errp);
540}
541
542/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
543 non-NULL. A name of NULL means to open the default file.
544
545 Use the specified string and symbol table sections.
546
547 Public entry point. */
548ctf_file_t *
549ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
550 const ctf_sect_t *symsect,
551 const ctf_sect_t *strsect,
552 const char *name,
553 int *errp)
554{
555 if (arc->ctfi_is_archive)
556 {
557 ctf_file_t *ret;
558 ret = ctf_arc_open_by_name_internal (arc->ctfi_archive, symsect, strsect,
559 name, errp);
560 if (ret)
561 ret->ctf_archive = (ctf_archive_t *) arc;
562 return ret;
563 }
564
565 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
566 {
567 if (errp)
568 *errp = ECTF_ARNNAME;
569 return NULL;
570 }
571 arc->ctfi_file->ctf_archive = (ctf_archive_t *) arc;
572
573 /* Bump the refcount so that the user can ctf_file_close() it. */
574 arc->ctfi_file->ctf_refcnt++;
575 return arc->ctfi_file;
576}
577
578/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
579 non-NULL. A name of NULL means to open the default file.
580
581 Public entry point. */
582ctf_file_t *
583ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name, int *errp)
584{
585 const ctf_sect_t *symsect = &arc->ctfi_symsect;
586 const ctf_sect_t *strsect = &arc->ctfi_strsect;
587
588 if (symsect->cts_name == NULL)
589 symsect = NULL;
590 if (strsect->cts_name == NULL)
591 strsect = NULL;
592
593 return ctf_arc_open_by_name_sections (arc, symsect, strsect, name, errp);
594}
595
596/* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
597 none, setting 'err' if non-NULL. */
598static ctf_file_t *
599ctf_arc_open_by_offset (const struct ctf_archive *arc,
600 const ctf_sect_t *symsect,
601 const ctf_sect_t *strsect, size_t offset,
602 int *errp)
603{
604 ctf_sect_t ctfsect;
605 ctf_file_t *fp;
606
62d8e3b7 607 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
9402cc59 608
a0486bac 609 memset (&ctfsect, 0, sizeof (ctf_sect_t));
9402cc59
NA
610
611 offset += le64toh (arc->ctfa_ctfs);
612
613 ctfsect.cts_name = _CTF_SECTION;
9402cc59
NA
614 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
615 ctfsect.cts_entsize = 1;
9402cc59
NA
616 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
617 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
618 if (fp)
619 ctf_setmodel (fp, le64toh (arc->ctfa_model));
620 return fp;
621}
622
9c23dfa5
NA
623/* Return the number of members in an archive. */
624size_t
625ctf_archive_count (const ctf_archive_t *wrapper)
626{
627 if (!wrapper->ctfi_is_archive)
628 return 1;
629
630 return wrapper->ctfi_archive->ctfa_nfiles;
631}
632
9402cc59
NA
633/* Raw iteration over all CTF files in an archive. We pass the raw data for all
634 CTF files in turn to the specified callback function. */
635static int
636ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
637 ctf_archive_raw_member_f *func, void *data)
638{
639 int rc;
640 size_t i;
641 struct ctf_archive_modent *modent;
642 const char *nametbl;
643
644 modent = (ctf_archive_modent_t *) ((char *) arc
645 + sizeof (struct ctf_archive));
646 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
647
648 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
649 {
650 const char *name;
651 char *fp;
652
653 name = &nametbl[le64toh (modent[i].name_offset)];
654 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
655 + le64toh (modent[i].ctf_offset));
656
657 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
658 le64toh (*((uint64_t *) fp)), data)) != 0)
659 return rc;
660 }
661 return 0;
662}
663
664/* Raw iteration over all CTF files in an archive: public entry point.
665
666 Returns -EINVAL if not supported for this sort of archive. */
667int
668ctf_archive_raw_iter (const ctf_archive_t *arc,
669 ctf_archive_raw_member_f * func, void *data)
670{
671 if (arc->ctfi_is_archive)
672 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
673
674 return -EINVAL; /* Not supported. */
675}
676
677/* Iterate over all CTF files in an archive. We pass all CTF files in turn to
678 the specified callback function. */
679static int
680ctf_archive_iter_internal (const ctf_archive_t *wrapper,
681 const struct ctf_archive *arc,
682 const ctf_sect_t *symsect,
683 const ctf_sect_t *strsect,
684 ctf_archive_member_f *func, void *data)
685{
686 int rc;
687 size_t i;
688 ctf_file_t *f;
689 struct ctf_archive_modent *modent;
690 const char *nametbl;
691
692 modent = (ctf_archive_modent_t *) ((char *) arc
693 + sizeof (struct ctf_archive));
694 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
695
696 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
697 {
698 const char *name;
699
700 name = &nametbl[le64toh (modent[i].name_offset)];
701 if ((f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
702 name, &rc)) == NULL)
703 return rc;
704
705 f->ctf_archive = (ctf_archive_t *) wrapper;
706 if ((rc = func (f, name, data)) != 0)
707 {
708 ctf_file_close (f);
709 return rc;
710 }
711
712 ctf_file_close (f);
713 }
714 return 0;
715}
716
717/* Iterate over all CTF files in an archive: public entry point. We pass all
718 CTF files in turn to the specified callback function. */
719int
720ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
721 void *data)
722{
723 const ctf_sect_t *symsect = &arc->ctfi_symsect;
724 const ctf_sect_t *strsect = &arc->ctfi_strsect;
725
726 if (symsect->cts_name == NULL)
727 symsect = NULL;
728 if (strsect->cts_name == NULL)
729 strsect = NULL;
730
731 if (arc->ctfi_is_archive)
732 return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
733 func, data);
734
735 return func (arc->ctfi_file, _CTF_SECTION, data);
736}
737
688d28f6
NA
738/* Iterate over all CTF files in an archive, returning each dict in turn as a
739 ctf_file_t, and NULL on error or end of iteration. It is the caller's
740 responsibility to close it. Parent dicts may be skipped. Regardless of
741 whether they are skipped or not, the caller must ctf_import the parent if
742 need be.
743
744 We identify parents by name rather than by flag value: for now, with the
745 linker only emitting parents named _CTF_SECTION, this works well enough. */
746
747ctf_file_t *
748ctf_archive_next (const ctf_archive_t *wrapper, ctf_next_t **it, const char **name,
749 int skip_parent, int *errp)
750{
751 ctf_file_t *f;
752 ctf_next_t *i = *it;
753 struct ctf_archive *arc;
754 struct ctf_archive_modent *modent;
755 const char *nametbl;
756 const char *name_;
757
758 if (!i)
759 {
760 if ((i = ctf_next_create()) == NULL)
761 {
762 if (errp)
763 *errp = ENOMEM;
764 return NULL;
765 }
766 i->cu.ctn_arc = wrapper;
767 i->ctn_iter_fun = (void (*) (void)) ctf_archive_next;
768 *it = i;
769 }
770
771 if ((void (*) (void)) ctf_archive_next != i->ctn_iter_fun)
772 {
773 if (errp)
774 *errp = ECTF_NEXT_WRONGFUN;
775 return NULL;
776 }
777
778 if (wrapper != i->cu.ctn_arc)
779 {
780 if (errp)
781 *errp = ECTF_NEXT_WRONGFP;
782 return NULL;
783 }
784
785 /* Iteration is made a bit more complex by the need to handle ctf_file_t's
786 transparently wrapped in a single-member archive. These are parents: if
787 skip_parent is on, they are skipped and the iterator terminates
788 immediately. */
789
790 if (!wrapper->ctfi_is_archive && i->ctn_n == 0)
791 {
792 i->ctn_n++;
793 if (!skip_parent)
794 {
795 wrapper->ctfi_file->ctf_refcnt++;
796 return wrapper->ctfi_file;
797 }
798 }
799
800 arc = wrapper->ctfi_archive;
801
802 /* The loop keeps going when skip_parent is on as long as the member we find
803 is the parent (i.e. at most two iterations, but possibly an early return if
804 *all* we have is a parent). */
805
806 const ctf_sect_t *symsect;
807 const ctf_sect_t *strsect;
808
809 do
810 {
811 if ((!wrapper->ctfi_is_archive) || (i->ctn_n >= le64toh (arc->ctfa_nfiles)))
812 {
813 ctf_next_destroy (i);
814 *it = NULL;
815 if (errp)
816 *errp = ECTF_NEXT_END;
817 return NULL;
818 }
819
820 symsect = &wrapper->ctfi_symsect;
821 strsect = &wrapper->ctfi_strsect;
822
823 if (symsect->cts_name == NULL)
824 symsect = NULL;
825 if (strsect->cts_name == NULL)
826 strsect = NULL;
827
828 modent = (ctf_archive_modent_t *) ((char *) arc
829 + sizeof (struct ctf_archive));
830 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
831
832 name_ = &nametbl[le64toh (modent[i->ctn_n].name_offset)];
833 i->ctn_n++;
834 } while (skip_parent && strcmp (name_, _CTF_SECTION) == 0);
835
836 if (name)
837 *name = name_;
838
839 f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
840 name_, errp);
841 f->ctf_archive = (ctf_archive_t *) wrapper;
842 return f;
843}
844
9402cc59
NA
845#ifdef HAVE_MMAP
846/* Map the header in. Only used on new, empty files. */
847static void *arc_mmap_header (int fd, size_t headersz)
848{
849 void *hdr;
850 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
851 0)) == MAP_FAILED)
852 return NULL;
853 return hdr;
854}
855
856/* mmap() the whole file, for reading only. (Map it writably, but privately: we
857 need to modify the region, but don't need anyone else to see the
858 modifications.) */
859static void *arc_mmap_file (int fd, size_t size)
860{
861 void *arc;
862 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
863 fd, 0)) == MAP_FAILED)
864 return NULL;
865 return arc;
866}
867
868/* Persist the header to disk. */
869static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
870 size_t headersz, const char **errmsg)
871{
872 if (msync (header, headersz, MS_ASYNC) < 0)
873 {
874 if (errmsg)
875 *errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
876 return -1;
877 }
878 return 0;
879}
880
881/* Unmap the region. */
882static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
883{
884 if (munmap (header, headersz) < 0)
885 {
886 if (errmsg)
887 *errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
888 return -1;
889 }
890 return 0;
891}
892#else
893/* Map the header in. Only used on new, empty files. */
f5e73be1 894static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
9402cc59
NA
895{
896 void *hdr;
897 if ((hdr = malloc (headersz)) == NULL)
898 return NULL;
899 return hdr;
900}
901
902/* Pull in the whole file, for reading only. We assume the current file
903 position is at the start of the file. */
904static void *arc_mmap_file (int fd, size_t size)
905{
906 char *data;
907
908 if ((data = malloc (size)) == NULL)
909 return NULL;
910
911 if (ctf_pread (fd, data, size, 0) < 0)
912 {
913 free (data);
914 return NULL;
915 }
916 return data;
917}
918
919/* Persist the header to disk. */
920static int arc_mmap_writeout (int fd, void *header, size_t headersz,
921 const char **errmsg)
922{
923 ssize_t len;
924 size_t acc = 0;
925 char *data = (char *) header;
926 ssize_t count = headersz;
927
928 if ((lseek (fd, 0, SEEK_SET)) < 0)
929 {
930 if (errmsg)
931 *errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
932 "%s: %s\n";
933 return -1;
934 }
935
936 while (headersz > 0)
937 {
938 if ((len = write (fd, data, count)) < 0)
939 {
940 if (errmsg)
941 *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
942 return len;
943 }
944 if (len == EINTR)
945 continue;
946
947 acc += len;
948 if (len == 0) /* EOF. */
949 break;
950
951 count -= len;
952 data += len;
953 }
954 return 0;
955}
956
957/* Unmap the region. */
958static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
959 const char **errmsg _libctf_unused_)
960{
961 free (header);
962 return 0;
963}
964#endif
This page took 0.151711 seconds and 4 git commands to generate.