2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
4 This file is part of libctf.
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
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.
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/>. */
21 #include <sys/types.h>
24 #include "ctf-endian.h"
35 static off_t
arc_write_one_ctf (ctf_file_t
* f
, int fd
, size_t threshold
);
36 static ctf_file_t
*ctf_arc_open_by_offset (const struct ctf_archive
*arc
,
37 const ctf_sect_t
*symsect
,
38 const ctf_sect_t
*strsect
,
39 size_t offset
, int *errp
);
40 static int sort_modent_by_name (const void *one
, const void *two
, void *n
);
41 static void *arc_mmap_header (int fd
, size_t headersz
);
42 static void *arc_mmap_file (int fd
, size_t size
);
43 static int arc_mmap_writeout (int fd
, void *header
, size_t headersz
,
45 static int arc_mmap_unmap (void *header
, size_t headersz
, const char **errmsg
);
47 /* bsearch() internal state. */
48 static __thread
char *search_nametbl
;
50 /* Write out a CTF archive to the start of the file referenced by the passed-in
51 fd. The entries in CTF_FILES are referenced by name: the names are passed in
52 the names array, which must have CTF_FILES entries.
54 Returns 0 on success, or an errno, or an ECTF_* value. */
56 ctf_arc_write_fd (int fd
, ctf_file_t
**ctf_files
, size_t ctf_file_cnt
,
57 const char **names
, size_t threshold
)
60 struct ctf_archive
*archdr
;
65 size_t ctf_startoffs
; /* Start of the section we are working over. */
66 char *nametbl
= NULL
; /* The name table. */
69 struct ctf_archive_modent
*modent
;
71 ctf_dprintf ("Writing CTF archive with %lu files\n",
72 (unsigned long) ctf_file_cnt
);
74 /* Figure out the size of the mmap()ed header, including the
75 ctf_archive_modent array. We assume that all of this needs no
76 padding: a likely assumption, given that it's all made up of
78 headersz
= sizeof (struct ctf_archive
)
79 + (ctf_file_cnt
* sizeof (uint64_t) * 2);
80 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz
);
82 /* From now on we work in two pieces: an mmap()ed region from zero up to the
83 headersz, and a region updated via write() starting after that, containing
84 all the tables. Platforms that do not support mmap() just use write(). */
85 ctf_startoffs
= headersz
;
86 if (lseek (fd
, ctf_startoffs
- 1, SEEK_SET
) < 0)
88 errmsg
= "ctf_arc_write(): cannot extend file while writing: %s\n";
92 if (write (fd
, &dummy
, 1) < 0)
94 errmsg
= "ctf_arc_write(): cannot extend file while writing: %s\n";
98 if ((archdr
= arc_mmap_header (fd
, headersz
)) == NULL
)
100 errmsg
= "ctf_arc_write(): Cannot mmap(): %s\n";
104 /* Fill in everything we can, which is everything other than the name
106 archdr
->ctfa_magic
= htole64 (CTFA_MAGIC
);
107 archdr
->ctfa_nfiles
= htole64 (ctf_file_cnt
);
108 archdr
->ctfa_ctfs
= htole64 (ctf_startoffs
);
110 /* We could validate that all CTF files have the same data model, but
111 since any reasonable construction process will be building things of
112 only one bitness anyway, this is pretty pointless, so just use the
113 model of the first CTF file for all of them. (It *is* valid to
114 create an empty archive: the value of ctfa_model is irrelevant in
115 this case, but we must be sure not to dereference uninitialized
118 if (ctf_file_cnt
> 0)
119 archdr
->ctfa_model
= htole64 (ctf_getmodel (ctf_files
[0]));
121 /* Now write out the CTFs: ctf_archive_modent array via the mapping,
122 ctfs via write(). The names themselves have not been written yet: we
123 track them in a local strtab until the time is right, and sort the
124 modents array after construction.
126 The name table is not sorted. */
128 for (i
= 0, namesz
= 0; i
< le64toh (archdr
->ctfa_nfiles
); i
++)
129 namesz
+= strlen (names
[i
]) + 1;
131 nametbl
= malloc (namesz
);
134 errmsg
= "Error writing named CTF to archive: %s\n";
138 for (i
= 0, namesz
= 0,
139 modent
= (ctf_archive_modent_t
*) ((char *) archdr
140 + sizeof (struct ctf_archive
));
141 i
< le64toh (archdr
->ctfa_nfiles
); i
++)
145 strcpy (&nametbl
[namesz
], names
[i
]);
147 off
= arc_write_one_ctf (ctf_files
[i
], fd
, threshold
);
148 if ((off
< 0) && (off
> -ECTF_BASE
))
150 errmsg
= "ctf_arc_write(): Cannot determine file "
151 "position while writing to archive: %s";
156 errmsg
= "ctf_arc_write(): Cannot write CTF file to archive: %s\n";
161 modent
->name_offset
= htole64 (namesz
);
162 modent
->ctf_offset
= htole64 (off
- ctf_startoffs
);
163 namesz
+= strlen (names
[i
]) + 1;
167 ctf_qsort_r ((ctf_archive_modent_t
*) ((char *) archdr
168 + sizeof (struct ctf_archive
)),
169 le64toh (archdr
->ctfa_nfiles
),
170 sizeof (struct ctf_archive_modent
), sort_modent_by_name
,
173 /* Now the name table. */
175 if ((nameoffs
= lseek (fd
, 0, SEEK_CUR
)) < 0)
177 errmsg
= "ctf_arc_write(): Cannot get current file position "
181 archdr
->ctfa_names
= htole64 (nameoffs
);
186 if ((len
= write (fd
, np
, namesz
)) < 0)
188 errmsg
= "ctf_arc_write(): Cannot write name table to archive: %s\n";
196 if (arc_mmap_writeout (fd
, archdr
, headersz
, &errmsg
) < 0)
198 if (arc_mmap_unmap (archdr
, headersz
, &errmsg
) < 0)
205 arc_mmap_unmap (archdr
, headersz
, NULL
);
207 ctf_dprintf (errmsg
, errno
< ECTF_BASE
? strerror (errno
) :
212 /* Write out a CTF archive. The entries in CTF_FILES are referenced by name:
213 the names are passed in the names array, which must have CTF_FILES entries.
215 If the filename is NULL, create a temporary file and return a pointer to it.
217 Returns 0 on success, or an errno, or an ECTF_* value. */
219 ctf_arc_write (const char *file
, ctf_file_t
** ctf_files
, size_t ctf_file_cnt
,
220 const char **names
, size_t threshold
)
225 if ((fd
= open (file
, O_RDWR
| O_CREAT
| O_TRUNC
| O_CLOEXEC
, 0666)) < 0)
227 ctf_dprintf ("ctf_arc_write(): cannot create %s: %s\n", file
,
232 err
= ctf_arc_write_fd (fd
, ctf_files
, ctf_file_cnt
, names
, threshold
);
236 if ((err
= close (fd
)) < 0)
238 ctf_dprintf ("ctf_arc_write(): Cannot close after writing to archive: "
239 "%s\n", strerror (errno
));
257 /* Write one CTF file out. Return the file position of the written file (or
258 rather, of the file-size uint64_t that precedes it): negative return is a
259 negative errno or ctf_errno value. On error, the file position may no longer
260 be at the end of the file. */
262 arc_write_one_ctf (ctf_file_t
* f
, int fd
, size_t threshold
)
268 int (*writefn
) (ctf_file_t
* fp
, int fd
);
270 if (ctf_serialize (f
) < 0)
271 return f
->ctf_errno
* -1;
273 if ((off
= lseek (fd
, 0, SEEK_CUR
)) < 0)
276 if (f
->ctf_size
> threshold
)
277 writefn
= ctf_compress_write
;
281 /* This zero-write turns into the size in a moment. */
282 ctfsz_len
= sizeof (ctfsz
);
283 ctfszp
= (char *) &ctfsz
;
284 while (ctfsz_len
> 0)
286 ssize_t writelen
= write (fd
, ctfszp
, ctfsz_len
);
289 ctfsz_len
-= writelen
;
293 if (writefn (f
, fd
) != 0)
294 return f
->ctf_errno
* -1;
296 if ((end_off
= lseek (fd
, 0, SEEK_CUR
)) < 0)
298 ctfsz
= htole64 (end_off
- off
);
300 if ((lseek (fd
, off
, SEEK_SET
)) < 0)
304 ctfsz_len
= sizeof (ctfsz
);
305 ctfszp
= (char *) &ctfsz
;
306 while (ctfsz_len
> 0)
308 ssize_t writelen
= write (fd
, ctfszp
, ctfsz_len
);
311 ctfsz_len
-= writelen
;
315 end_off
= LCTF_ALIGN_OFFS (end_off
, 8);
316 if ((lseek (fd
, end_off
, SEEK_SET
)) < 0)
322 /* qsort() function to sort the array of struct ctf_archive_modents into
323 ascending name order. */
325 sort_modent_by_name (const void *one
, const void *two
, void *n
)
327 const struct ctf_archive_modent
*a
= one
;
328 const struct ctf_archive_modent
*b
= two
;
331 return strcmp (&nametbl
[le64toh (a
->name_offset
)],
332 &nametbl
[le64toh (b
->name_offset
)]);
335 /* bsearch() function to search for a given name in the sorted array of struct
336 ctf_archive_modents. */
338 search_modent_by_name (const void *key
, const void *ent
)
341 const struct ctf_archive_modent
*v
= ent
;
343 return strcmp (k
, &search_nametbl
[le64toh (v
->name_offset
)]);
346 /* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
347 ctf_file. Closes ARC and/or FP on error. Arrange to free the SYMSECT or
348 STRSECT, as needed, on close. */
350 struct ctf_archive_internal
*
351 ctf_new_archive_internal (int is_archive
, struct ctf_archive
*arc
,
352 ctf_file_t
*fp
, const ctf_sect_t
*symsect
,
353 const ctf_sect_t
*strsect
,
356 struct ctf_archive_internal
*arci
;
358 if ((arci
= calloc (1, sizeof (struct ctf_archive_internal
))) == NULL
)
361 ctf_arc_close_internal (arc
);
364 return (ctf_set_open_errno (errp
, errno
));
366 arci
->ctfi_is_archive
= is_archive
;
368 arci
->ctfi_archive
= arc
;
370 arci
->ctfi_file
= fp
;
372 memcpy (&arci
->ctfi_symsect
, symsect
, sizeof (struct ctf_sect
));
374 memcpy (&arci
->ctfi_strsect
, strsect
, sizeof (struct ctf_sect
));
375 arci
->ctfi_free_symsect
= 0;
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). */
384 ctf_arc_bufopen (const ctf_sect_t
*ctfsect
, const ctf_sect_t
*symsect
,
385 const ctf_sect_t
*strsect
, int *errp
)
387 struct ctf_archive
*arc
= NULL
;
389 ctf_file_t
*fp
= NULL
;
391 if (ctfsect
->cts_size
> sizeof (uint64_t) &&
392 ((*(uint64_t *) ctfsect
->cts_data
) == CTFA_MAGIC
))
394 /* The archive is mmappable, so this operation is trivial. */
397 arc
= (struct ctf_archive
*) ctfsect
->cts_data
;
402 if ((fp
= ctf_bufopen (ctfsect
, symsect
, strsect
, errp
)) == NULL
)
404 ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n",
409 return ctf_new_archive_internal (is_archive
, arc
, fp
, symsect
, strsect
,
413 /* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
416 ctf_arc_open_internal (const char *filename
, int *errp
)
421 struct ctf_archive
*arc
; /* (Actually the whole file.) */
424 if ((fd
= open (filename
, O_RDONLY
)) < 0)
426 errmsg
= "ctf_arc_open(): cannot open %s: %s\n";
429 if (fstat (fd
, &s
) < 0)
431 errmsg
= "ctf_arc_open(): cannot stat %s: %s\n";
435 if ((arc
= arc_mmap_file (fd
, s
.st_size
)) == NULL
)
437 errmsg
= "ctf_arc_open(): Cannot read in %s: %s\n";
441 if (le64toh (arc
->ctfa_magic
) != CTFA_MAGIC
)
443 errmsg
= "ctf_arc_open(): Invalid magic number";
448 /* This horrible hack lets us know how much to unmap when the file is
449 closed. (We no longer need the magic number, and the mapping
451 arc
->ctfa_magic
= s
.st_size
;
456 arc_mmap_unmap (arc
, s
.st_size
, NULL
);
462 ctf_dprintf (errmsg
, filename
, errno
< ECTF_BASE
? strerror (errno
) :
467 /* Close an archive. */
469 ctf_arc_close_internal (struct ctf_archive
*arc
)
474 /* See the comment in ctf_arc_open(). */
475 arc_mmap_unmap (arc
, arc
->ctfa_magic
, NULL
);
478 /* Public entry point: close an archive, or CTF file. */
480 ctf_arc_close (ctf_archive_t
*arc
)
485 if (arc
->ctfi_is_archive
)
486 ctf_arc_close_internal (arc
->ctfi_archive
);
488 ctf_file_close (arc
->ctfi_file
);
489 if (arc
->ctfi_free_symsect
)
490 free ((void *) arc
->ctfi_symsect
.cts_data
);
491 free (arc
->ctfi_data
);
492 if (arc
->ctfi_bfd_close
)
493 arc
->ctfi_bfd_close (arc
);
497 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
498 non-NULL. A name of NULL means to open the default file. */
500 ctf_arc_open_by_name_internal (const struct ctf_archive
*arc
,
501 const ctf_sect_t
*symsect
,
502 const ctf_sect_t
*strsect
,
503 const char *name
, int *errp
)
505 struct ctf_archive_modent
*modent
;
508 name
= _CTF_SECTION
; /* The default name. */
510 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name
);
512 modent
= (ctf_archive_modent_t
*) ((char *) arc
513 + sizeof (struct ctf_archive
));
515 search_nametbl
= (char *) arc
+ le64toh (arc
->ctfa_names
);
516 modent
= bsearch (name
, modent
, le64toh (arc
->ctfa_nfiles
),
517 sizeof (struct ctf_archive_modent
),
518 search_modent_by_name
);
520 /* This is actually a common case and normal operation: no error
525 *errp
= ECTF_ARNNAME
;
529 return ctf_arc_open_by_offset (arc
, symsect
, strsect
,
530 le64toh (modent
->ctf_offset
), errp
);
533 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
534 non-NULL. A name of NULL means to open the default file.
536 Use the specified string and symbol table sections.
538 Public entry point. */
540 ctf_arc_open_by_name_sections (const ctf_archive_t
*arc
,
541 const ctf_sect_t
*symsect
,
542 const ctf_sect_t
*strsect
,
546 if (arc
->ctfi_is_archive
)
549 ret
= ctf_arc_open_by_name_internal (arc
->ctfi_archive
, symsect
, strsect
,
552 ret
->ctf_archive
= (ctf_archive_t
*) arc
;
556 if ((name
!= NULL
) && (strcmp (name
, _CTF_SECTION
) != 0))
559 *errp
= ECTF_ARNNAME
;
562 arc
->ctfi_file
->ctf_archive
= (ctf_archive_t
*) arc
;
564 /* Bump the refcount so that the user can ctf_file_close() it. */
565 arc
->ctfi_file
->ctf_refcnt
++;
566 return arc
->ctfi_file
;
569 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
570 non-NULL. A name of NULL means to open the default file.
572 Public entry point. */
574 ctf_arc_open_by_name (const ctf_archive_t
*arc
, const char *name
, int *errp
)
576 const ctf_sect_t
*symsect
= &arc
->ctfi_symsect
;
577 const ctf_sect_t
*strsect
= &arc
->ctfi_strsect
;
579 if (symsect
->cts_name
== NULL
)
581 if (strsect
->cts_name
== NULL
)
584 return ctf_arc_open_by_name_sections (arc
, symsect
, strsect
, name
, errp
);
587 /* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
588 none, setting 'err' if non-NULL. */
590 ctf_arc_open_by_offset (const struct ctf_archive
*arc
,
591 const ctf_sect_t
*symsect
,
592 const ctf_sect_t
*strsect
, size_t offset
,
598 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset
);
600 memset (&ctfsect
, 0, sizeof (ctf_sect_t
));
602 offset
+= le64toh (arc
->ctfa_ctfs
);
604 ctfsect
.cts_name
= _CTF_SECTION
;
605 ctfsect
.cts_size
= le64toh (*((uint64_t *) ((char *) arc
+ offset
)));
606 ctfsect
.cts_entsize
= 1;
607 ctfsect
.cts_data
= (void *) ((char *) arc
+ offset
+ sizeof (uint64_t));
608 fp
= ctf_bufopen (&ctfsect
, symsect
, strsect
, errp
);
610 ctf_setmodel (fp
, le64toh (arc
->ctfa_model
));
614 /* Raw iteration over all CTF files in an archive. We pass the raw data for all
615 CTF files in turn to the specified callback function. */
617 ctf_archive_raw_iter_internal (const struct ctf_archive
*arc
,
618 ctf_archive_raw_member_f
*func
, void *data
)
622 struct ctf_archive_modent
*modent
;
625 modent
= (ctf_archive_modent_t
*) ((char *) arc
626 + sizeof (struct ctf_archive
));
627 nametbl
= (((const char *) arc
) + le64toh (arc
->ctfa_names
));
629 for (i
= 0; i
< le64toh (arc
->ctfa_nfiles
); i
++)
634 name
= &nametbl
[le64toh (modent
[i
].name_offset
)];
635 fp
= ((char *) arc
+ le64toh (arc
->ctfa_ctfs
)
636 + le64toh (modent
[i
].ctf_offset
));
638 if ((rc
= func (name
, (void *) (fp
+ sizeof (uint64_t)),
639 le64toh (*((uint64_t *) fp
)), data
)) != 0)
645 /* Raw iteration over all CTF files in an archive: public entry point.
647 Returns -EINVAL if not supported for this sort of archive. */
649 ctf_archive_raw_iter (const ctf_archive_t
*arc
,
650 ctf_archive_raw_member_f
* func
, void *data
)
652 if (arc
->ctfi_is_archive
)
653 return ctf_archive_raw_iter_internal (arc
->ctfi_archive
, func
, data
);
655 return -EINVAL
; /* Not supported. */
658 /* Iterate over all CTF files in an archive. We pass all CTF files in turn to
659 the specified callback function. */
661 ctf_archive_iter_internal (const ctf_archive_t
*wrapper
,
662 const struct ctf_archive
*arc
,
663 const ctf_sect_t
*symsect
,
664 const ctf_sect_t
*strsect
,
665 ctf_archive_member_f
*func
, void *data
)
670 struct ctf_archive_modent
*modent
;
673 modent
= (ctf_archive_modent_t
*) ((char *) arc
674 + sizeof (struct ctf_archive
));
675 nametbl
= (((const char *) arc
) + le64toh (arc
->ctfa_names
));
677 for (i
= 0; i
< le64toh (arc
->ctfa_nfiles
); i
++)
681 name
= &nametbl
[le64toh (modent
[i
].name_offset
)];
682 if ((f
= ctf_arc_open_by_name_internal (arc
, symsect
, strsect
,
686 f
->ctf_archive
= (ctf_archive_t
*) wrapper
;
687 if ((rc
= func (f
, name
, data
)) != 0)
698 /* Iterate over all CTF files in an archive: public entry point. We pass all
699 CTF files in turn to the specified callback function. */
701 ctf_archive_iter (const ctf_archive_t
*arc
, ctf_archive_member_f
*func
,
704 const ctf_sect_t
*symsect
= &arc
->ctfi_symsect
;
705 const ctf_sect_t
*strsect
= &arc
->ctfi_strsect
;
707 if (symsect
->cts_name
== NULL
)
709 if (strsect
->cts_name
== NULL
)
712 if (arc
->ctfi_is_archive
)
713 return ctf_archive_iter_internal (arc
, arc
->ctfi_archive
, symsect
, strsect
,
716 return func (arc
->ctfi_file
, _CTF_SECTION
, data
);
720 /* Map the header in. Only used on new, empty files. */
721 static void *arc_mmap_header (int fd
, size_t headersz
)
724 if ((hdr
= mmap (NULL
, headersz
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
,
730 /* mmap() the whole file, for reading only. (Map it writably, but privately: we
731 need to modify the region, but don't need anyone else to see the
733 static void *arc_mmap_file (int fd
, size_t size
)
736 if ((arc
= mmap (NULL
, size
, PROT_READ
| PROT_WRITE
, MAP_PRIVATE
,
737 fd
, 0)) == MAP_FAILED
)
742 /* Persist the header to disk. */
743 static int arc_mmap_writeout (int fd _libctf_unused_
, void *header
,
744 size_t headersz
, const char **errmsg
)
746 if (msync (header
, headersz
, MS_ASYNC
) < 0)
749 *errmsg
= "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
755 /* Unmap the region. */
756 static int arc_mmap_unmap (void *header
, size_t headersz
, const char **errmsg
)
758 if (munmap (header
, headersz
) < 0)
761 *errmsg
= "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
767 /* Map the header in. Only used on new, empty files. */
768 static void *arc_mmap_header (int fd _libctf_unused_
, size_t headersz
)
771 if ((hdr
= malloc (headersz
)) == NULL
)
776 /* Pull in the whole file, for reading only. We assume the current file
777 position is at the start of the file. */
778 static void *arc_mmap_file (int fd
, size_t size
)
782 if ((data
= malloc (size
)) == NULL
)
785 if (ctf_pread (fd
, data
, size
, 0) < 0)
793 /* Persist the header to disk. */
794 static int arc_mmap_writeout (int fd
, void *header
, size_t headersz
,
799 char *data
= (char *) header
;
800 ssize_t count
= headersz
;
802 if ((lseek (fd
, 0, SEEK_SET
)) < 0)
805 *errmsg
= "arc_mmap_writeout(): Cannot seek while writing header to "
812 if ((len
= write (fd
, data
, count
)) < 0)
815 *errmsg
= "arc_mmap_writeout(): Cannot write header to %s: %s\n";
822 if (len
== 0) /* EOF. */
831 /* Unmap the region. */
832 static int arc_mmap_unmap (void *header
, size_t headersz _libctf_unused_
,
833 const char **errmsg _libctf_unused_
)
This page took 0.05882 seconds and 5 git commands to generate.