2 Copyright (C) 2019 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. The entries in CTF_FILES are referenced by name:
51 the names are passed in the names array, which must have CTF_FILES entries.
53 Returns 0 on success, or an errno, or an ECTF_* value. */
55 ctf_arc_write (const char *file
, ctf_file_t
** ctf_files
, size_t ctf_file_cnt
,
56 const char **names
, size_t threshold
)
59 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 archive %s with %lu files\n", file
,
72 (unsigned long) ctf_file_cnt
);
74 if ((fd
= open (file
, O_RDWR
| O_CREAT
| O_TRUNC
| O_CLOEXEC
, 0666)) < 0)
76 errmsg
= "ctf_arc_write(): cannot create %s: %s\n";
80 /* Figure out the size of the mmap()ed header, including the
81 ctf_archive_modent array. We assume that all of this needs no
82 padding: a likely assumption, given that it's all made up of
84 headersz
= sizeof (struct ctf_archive
)
85 + (ctf_file_cnt
* sizeof (uint64_t) * 2);
86 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz
);
88 /* From now on we work in two pieces: an mmap()ed region from zero up to the
89 headersz, and a region updated via write() starting after that, containing
90 all the tables. Platforms that do not support mmap() just use write(). */
91 ctf_startoffs
= headersz
;
92 if (lseek (fd
, ctf_startoffs
- 1, SEEK_SET
) < 0)
94 errmsg
= "ctf_arc_write(): cannot extend file while writing %s: %s\n";
98 if (write (fd
, &dummy
, 1) < 0)
100 errmsg
= "ctf_arc_write(): cannot extend file while writing %s: %s\n";
104 if ((archdr
= arc_mmap_header (fd
, headersz
)) == NULL
)
106 errmsg
= "ctf_arc_write(): Cannot mmap() %s: %s\n";
110 /* Fill in everything we can, which is everything other than the name
112 archdr
->ctfa_magic
= htole64 (CTFA_MAGIC
);
113 archdr
->ctfa_nfiles
= htole64 (ctf_file_cnt
);
114 archdr
->ctfa_ctfs
= htole64 (ctf_startoffs
);
116 /* We could validate that all CTF files have the same data model, but
117 since any reasonable construction process will be building things of
118 only one bitness anyway, this is pretty pointless, so just use the
119 model of the first CTF file for all of them. (It *is* valid to
120 create an empty archive: the value of ctfa_model is irrelevant in
121 this case, but we must be sure not to dereference uninitialized
124 if (ctf_file_cnt
> 0)
125 archdr
->ctfa_model
= htole64 (ctf_getmodel (ctf_files
[0]));
127 /* Now write out the CTFs: ctf_archive_modent array via the mapping,
128 ctfs via write(). The names themselves have not been written yet: we
129 track them in a local strtab until the time is right, and sort the
130 modents array after construction.
132 The name table is not sorted. */
134 for (i
= 0, namesz
= 0; i
< le64toh (archdr
->ctfa_nfiles
); i
++)
135 namesz
+= strlen (names
[i
]) + 1;
137 nametbl
= malloc (namesz
);
140 errmsg
= "Error writing named CTF to %s: %s\n";
144 for (i
= 0, namesz
= 0,
145 modent
= (ctf_archive_modent_t
*) ((char *) archdr
146 + sizeof (struct ctf_archive
));
147 i
< le64toh (archdr
->ctfa_nfiles
); i
++)
151 strcpy (&nametbl
[namesz
], names
[i
]);
153 off
= arc_write_one_ctf (ctf_files
[i
], fd
, threshold
);
154 if ((off
< 0) && (off
> -ECTF_BASE
))
156 errmsg
= "ctf_arc_write(): Cannot determine file "
157 "position while writing %s: %s";
162 errmsg
= "ctf_arc_write(): Cannot write CTF file to %s: %s\n";
167 modent
->name_offset
= htole64 (namesz
);
168 modent
->ctf_offset
= htole64 (off
- ctf_startoffs
);
169 namesz
+= strlen (names
[i
]) + 1;
173 ctf_qsort_r ((ctf_archive_modent_t
*) ((char *) archdr
174 + sizeof (struct ctf_archive
)),
175 le64toh (archdr
->ctfa_nfiles
),
176 sizeof (struct ctf_archive_modent
), sort_modent_by_name
,
179 /* Now the name table. */
181 if ((nameoffs
= lseek (fd
, 0, SEEK_CUR
)) < 0)
183 errmsg
= "ctf_arc_write(): Cannot get current file position "
187 archdr
->ctfa_names
= htole64 (nameoffs
);
192 if ((len
= write (fd
, np
, namesz
)) < 0)
194 errmsg
= "ctf_arc_write(): Cannot write name table in %s: %s\n";
202 if (arc_mmap_writeout (fd
, archdr
, headersz
, &errmsg
) < 0)
204 if (arc_mmap_unmap (archdr
, headersz
, &errmsg
) < 0)
208 errmsg
= "ctf_arc_write(): Cannot close after writing to %s: %s\n";
217 arc_mmap_unmap (archdr
, headersz
, NULL
);
223 ctf_dprintf (errmsg
, file
, errno
< ECTF_BASE
? strerror (errno
) :
228 /* Write one CTF file out. Return the file position of the written file (or
229 rather, of the file-size uint64_t that precedes it): negative return is a
230 negative errno or ctf_errno value. On error, the file position may no longer
231 be at the end of the file. */
233 arc_write_one_ctf (ctf_file_t
* f
, int fd
, size_t threshold
)
239 int (*writefn
) (ctf_file_t
* fp
, int fd
);
241 if ((off
= lseek (fd
, 0, SEEK_CUR
)) < 0)
244 if (f
->ctf_size
> threshold
)
245 writefn
= ctf_compress_write
;
249 /* This zero-write turns into the size in a moment. */
250 ctfsz_len
= sizeof (ctfsz
);
251 ctfszp
= (char *) &ctfsz
;
252 while (ctfsz_len
> 0)
254 ssize_t writelen
= write (fd
, ctfszp
, ctfsz_len
);
257 ctfsz_len
-= writelen
;
261 if (writefn (f
, fd
) != 0)
262 return f
->ctf_errno
* -1;
264 if ((end_off
= lseek (fd
, 0, SEEK_CUR
)) < 0)
266 ctfsz
= htole64 (end_off
- off
);
268 if ((lseek (fd
, off
, SEEK_SET
)) < 0)
272 ctfsz_len
= sizeof (ctfsz
);
273 ctfszp
= (char *) &ctfsz
;
274 while (ctfsz_len
> 0)
276 ssize_t writelen
= write (fd
, ctfszp
, ctfsz_len
);
279 ctfsz_len
-= writelen
;
283 end_off
= LCTF_ALIGN_OFFS (end_off
, 8);
284 if ((lseek (fd
, end_off
, SEEK_SET
)) < 0)
290 /* qsort() function to sort the array of struct ctf_archive_modents into
291 ascending name order. */
293 sort_modent_by_name (const void *one
, const void *two
, void *n
)
295 const struct ctf_archive_modent
*a
= one
;
296 const struct ctf_archive_modent
*b
= two
;
299 return strcmp (&nametbl
[le64toh (a
->name_offset
)],
300 &nametbl
[le64toh (b
->name_offset
)]);
303 /* bsearch() function to search for a given name in the sorted array of struct
304 ctf_archive_modents. */
306 search_modent_by_name (const void *key
, const void *ent
)
309 const struct ctf_archive_modent
*v
= ent
;
311 return strcmp (k
, &search_nametbl
[le64toh (v
->name_offset
)]);
314 /* A trivial wrapper: open a CTF archive, from data in a buffer (which the
315 caller must preserve until ctf_arc_close() time). Returns the archive, or
316 NULL and an error in *err (if not NULL). */
318 ctf_arc_bufopen (const void *buf
, size_t size _libctf_unused_
, int *errp
)
320 struct ctf_archive
*arc
= (struct ctf_archive
*) buf
;
322 if (le64toh (arc
->ctfa_magic
) != CTFA_MAGIC
)
331 /* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
334 ctf_arc_open_internal (const char *filename
, int *errp
)
339 struct ctf_archive
*arc
; /* (Actually the whole file.) */
342 if ((fd
= open (filename
, O_RDONLY
)) < 0)
344 errmsg
= "ctf_arc_open(): cannot open %s: %s\n";
347 if (fstat (fd
, &s
) < 0)
349 errmsg
= "ctf_arc_open(): cannot stat %s: %s\n";
353 if ((arc
= arc_mmap_file (fd
, s
.st_size
)) == NULL
)
355 errmsg
= "ctf_arc_open(): Cannot read in %s: %s\n";
359 if (le64toh (arc
->ctfa_magic
) != CTFA_MAGIC
)
361 errmsg
= "ctf_arc_open(): Invalid magic number";
366 /* This horrible hack lets us know how much to unmap when the file is
367 closed. (We no longer need the magic number, and the mapping
369 arc
->ctfa_magic
= s
.st_size
;
374 arc_mmap_unmap (arc
, s
.st_size
, NULL
);
380 ctf_dprintf (errmsg
, filename
, errno
< ECTF_BASE
? strerror (errno
) :
385 /* Close an archive. */
387 ctf_arc_close_internal (struct ctf_archive
*arc
)
392 /* See the comment in ctf_arc_open(). */
393 arc_mmap_unmap (arc
, arc
->ctfa_magic
, NULL
);
396 /* Public entry point: close an archive, or CTF file. */
398 ctf_arc_close (ctf_archive_t
*arc
)
403 if (arc
->ctfi_is_archive
)
404 ctf_arc_close_internal (arc
->ctfi_archive
);
406 ctf_file_close (arc
->ctfi_file
);
407 free ((void *) arc
->ctfi_symsect
.cts_data
);
408 free ((void *) arc
->ctfi_strsect
.cts_data
);
409 free (arc
->ctfi_data
);
413 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
414 non-NULL. A name of NULL means to open the default file. */
416 ctf_arc_open_by_name_internal (const struct ctf_archive
*arc
,
417 const ctf_sect_t
*symsect
,
418 const ctf_sect_t
*strsect
,
419 const char *name
, int *errp
)
421 struct ctf_archive_modent
*modent
;
424 name
= _CTF_SECTION
; /* The default name. */
426 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name
);
428 modent
= (ctf_archive_modent_t
*) ((char *) arc
429 + sizeof (struct ctf_archive
));
431 search_nametbl
= (char *) arc
+ le64toh (arc
->ctfa_names
);
432 modent
= bsearch (name
, modent
, le64toh (arc
->ctfa_nfiles
),
433 sizeof (struct ctf_archive_modent
),
434 search_modent_by_name
);
436 /* This is actually a common case and normal operation: no error
441 *errp
= ECTF_ARNNAME
;
445 return ctf_arc_open_by_offset (arc
, symsect
, strsect
,
446 le64toh (modent
->ctf_offset
), errp
);
449 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
450 non-NULL. A name of NULL means to open the default file.
452 Use the specified string and symbol table sections.
454 Public entry point. */
456 ctf_arc_open_by_name_sections (const ctf_archive_t
*arc
,
457 const ctf_sect_t
*symsect
,
458 const ctf_sect_t
*strsect
,
462 if (arc
->ctfi_is_archive
)
465 ret
= ctf_arc_open_by_name_internal (arc
->ctfi_archive
, symsect
, strsect
,
468 ret
->ctf_archive
= (ctf_archive_t
*) arc
;
472 if ((name
!= NULL
) && (strcmp (name
, _CTF_SECTION
) != 0))
475 *errp
= ECTF_ARNNAME
;
478 arc
->ctfi_file
->ctf_archive
= (ctf_archive_t
*) arc
;
480 /* Bump the refcount so that the user can ctf_file_close() it. */
481 arc
->ctfi_file
->ctf_refcnt
++;
482 return arc
->ctfi_file
;
485 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
486 non-NULL. A name of NULL means to open the default file.
488 Public entry point. */
490 ctf_arc_open_by_name (const ctf_archive_t
*arc
, const char *name
, int *errp
)
492 const ctf_sect_t
*symsect
= &arc
->ctfi_symsect
;
493 const ctf_sect_t
*strsect
= &arc
->ctfi_strsect
;
495 if (symsect
->cts_name
== NULL
)
497 if (strsect
->cts_name
== NULL
)
500 return ctf_arc_open_by_name_sections (arc
, symsect
, strsect
, name
, errp
);
503 /* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
504 none, setting 'err' if non-NULL. */
506 ctf_arc_open_by_offset (const struct ctf_archive
*arc
,
507 const ctf_sect_t
*symsect
,
508 const ctf_sect_t
*strsect
, size_t offset
,
514 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset
);
516 memset (&ctfsect
, 0, sizeof (ctf_sect_t
));
518 offset
+= le64toh (arc
->ctfa_ctfs
);
520 ctfsect
.cts_name
= _CTF_SECTION
;
521 ctfsect
.cts_size
= le64toh (*((uint64_t *) ((char *) arc
+ offset
)));
522 ctfsect
.cts_entsize
= 1;
523 ctfsect
.cts_data
= (void *) ((char *) arc
+ offset
+ sizeof (uint64_t));
524 fp
= ctf_bufopen (&ctfsect
, symsect
, strsect
, errp
);
526 ctf_setmodel (fp
, le64toh (arc
->ctfa_model
));
530 /* Raw iteration over all CTF files in an archive. We pass the raw data for all
531 CTF files in turn to the specified callback function. */
533 ctf_archive_raw_iter_internal (const struct ctf_archive
*arc
,
534 ctf_archive_raw_member_f
*func
, void *data
)
538 struct ctf_archive_modent
*modent
;
541 modent
= (ctf_archive_modent_t
*) ((char *) arc
542 + sizeof (struct ctf_archive
));
543 nametbl
= (((const char *) arc
) + le64toh (arc
->ctfa_names
));
545 for (i
= 0; i
< le64toh (arc
->ctfa_nfiles
); i
++)
550 name
= &nametbl
[le64toh (modent
[i
].name_offset
)];
551 fp
= ((char *) arc
+ le64toh (arc
->ctfa_ctfs
)
552 + le64toh (modent
[i
].ctf_offset
));
554 if ((rc
= func (name
, (void *) (fp
+ sizeof (uint64_t)),
555 le64toh (*((uint64_t *) fp
)), data
)) != 0)
561 /* Raw iteration over all CTF files in an archive: public entry point.
563 Returns -EINVAL if not supported for this sort of archive. */
565 ctf_archive_raw_iter (const ctf_archive_t
*arc
,
566 ctf_archive_raw_member_f
* func
, void *data
)
568 if (arc
->ctfi_is_archive
)
569 return ctf_archive_raw_iter_internal (arc
->ctfi_archive
, func
, data
);
571 return -EINVAL
; /* Not supported. */
574 /* Iterate over all CTF files in an archive. We pass all CTF files in turn to
575 the specified callback function. */
577 ctf_archive_iter_internal (const ctf_archive_t
*wrapper
,
578 const struct ctf_archive
*arc
,
579 const ctf_sect_t
*symsect
,
580 const ctf_sect_t
*strsect
,
581 ctf_archive_member_f
*func
, void *data
)
586 struct ctf_archive_modent
*modent
;
589 modent
= (ctf_archive_modent_t
*) ((char *) arc
590 + sizeof (struct ctf_archive
));
591 nametbl
= (((const char *) arc
) + le64toh (arc
->ctfa_names
));
593 for (i
= 0; i
< le64toh (arc
->ctfa_nfiles
); i
++)
597 name
= &nametbl
[le64toh (modent
[i
].name_offset
)];
598 if ((f
= ctf_arc_open_by_name_internal (arc
, symsect
, strsect
,
602 f
->ctf_archive
= (ctf_archive_t
*) wrapper
;
603 if ((rc
= func (f
, name
, data
)) != 0)
614 /* Iterate over all CTF files in an archive: public entry point. We pass all
615 CTF files in turn to the specified callback function. */
617 ctf_archive_iter (const ctf_archive_t
*arc
, ctf_archive_member_f
*func
,
620 const ctf_sect_t
*symsect
= &arc
->ctfi_symsect
;
621 const ctf_sect_t
*strsect
= &arc
->ctfi_strsect
;
623 if (symsect
->cts_name
== NULL
)
625 if (strsect
->cts_name
== NULL
)
628 if (arc
->ctfi_is_archive
)
629 return ctf_archive_iter_internal (arc
, arc
->ctfi_archive
, symsect
, strsect
,
632 return func (arc
->ctfi_file
, _CTF_SECTION
, data
);
636 /* Map the header in. Only used on new, empty files. */
637 static void *arc_mmap_header (int fd
, size_t headersz
)
640 if ((hdr
= mmap (NULL
, headersz
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
,
646 /* mmap() the whole file, for reading only. (Map it writably, but privately: we
647 need to modify the region, but don't need anyone else to see the
649 static void *arc_mmap_file (int fd
, size_t size
)
652 if ((arc
= mmap (NULL
, size
, PROT_READ
| PROT_WRITE
, MAP_PRIVATE
,
653 fd
, 0)) == MAP_FAILED
)
658 /* Persist the header to disk. */
659 static int arc_mmap_writeout (int fd _libctf_unused_
, void *header
,
660 size_t headersz
, const char **errmsg
)
662 if (msync (header
, headersz
, MS_ASYNC
) < 0)
665 *errmsg
= "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
671 /* Unmap the region. */
672 static int arc_mmap_unmap (void *header
, size_t headersz
, const char **errmsg
)
674 if (munmap (header
, headersz
) < 0)
677 *errmsg
= "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
683 /* Map the header in. Only used on new, empty files. */
684 static void *arc_mmap_header (int fd _libctf_unused_
, size_t headersz
)
687 if ((hdr
= malloc (headersz
)) == NULL
)
692 /* Pull in the whole file, for reading only. We assume the current file
693 position is at the start of the file. */
694 static void *arc_mmap_file (int fd
, size_t size
)
698 if ((data
= malloc (size
)) == NULL
)
701 if (ctf_pread (fd
, data
, size
, 0) < 0)
709 /* Persist the header to disk. */
710 static int arc_mmap_writeout (int fd
, void *header
, size_t headersz
,
715 char *data
= (char *) header
;
716 ssize_t count
= headersz
;
718 if ((lseek (fd
, 0, SEEK_SET
)) < 0)
721 *errmsg
= "arc_mmap_writeout(): Cannot seek while writing header to "
728 if ((len
= write (fd
, data
, count
)) < 0)
731 *errmsg
= "arc_mmap_writeout(): Cannot write header to %s: %s\n";
738 if (len
== 0) /* EOF. */
747 /* Unmap the region. */
748 static int arc_mmap_unmap (void *header
, size_t headersz _libctf_unused_
,
749 const char **errmsg _libctf_unused_
)
This page took 0.044864 seconds and 4 git commands to generate.