]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - libctf/ctf-archive.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / libctf / ctf-archive.c
CommitLineData
9402cc59 1/* CTF archive files.
fd67aa11 2 Copyright (C) 2019-2024 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
139633c3 35static off_t arc_write_one_ctf (ctf_dict_t * f, int fd, size_t threshold);
ae41200b
NA
36static 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,
53651de8
NA
39 size_t offset, int little_endian,
40 int *errp);
9402cc59
NA
41static int sort_modent_by_name (const void *one, const void *two, void *n);
42static void *arc_mmap_header (int fd, size_t headersz);
43static void *arc_mmap_file (int fd, size_t size);
44static int arc_mmap_writeout (int fd, void *header, size_t headersz,
45 const char **errmsg);
46static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
2c78e925
NA
47static void ctf_arc_import_parent (const ctf_archive_t *arc, ctf_dict_t *fp);
48
f4f60336
NA
49/* Flag to indicate "symbol not present" in ctf_archive_internal.ctfi_symdicts
50 and ctfi_symnamedicts. Never initialized. */
2c78e925 51static ctf_dict_t enosym;
9402cc59 52
5537f9b9 53/* Write out a CTF archive to the start of the file referenced by the passed-in
139633c3
NA
54 fd. The entries in CTF_DICTS are referenced by name: the names are passed in
55 the names array, which must have CTF_DICTS entries.
9402cc59
NA
56
57 Returns 0 on success, or an errno, or an ECTF_* value. */
58int
139633c3 59ctf_arc_write_fd (int fd, ctf_dict_t **ctf_dicts, size_t ctf_dict_cnt,
5537f9b9 60 const char **names, size_t threshold)
9402cc59
NA
61{
62 const char *errmsg;
63 struct ctf_archive *archdr;
9402cc59
NA
64 size_t i;
65 char dummy = 0;
66 size_t headersz;
67 ssize_t namesz;
68 size_t ctf_startoffs; /* Start of the section we are working over. */
69 char *nametbl = NULL; /* The name table. */
70 char *np;
71 off_t nameoffs;
72 struct ctf_archive_modent *modent;
73
5537f9b9 74 ctf_dprintf ("Writing CTF archive with %lu files\n",
139633c3 75 (unsigned long) ctf_dict_cnt);
9402cc59 76
9402cc59
NA
77 /* Figure out the size of the mmap()ed header, including the
78 ctf_archive_modent array. We assume that all of this needs no
79 padding: a likely assumption, given that it's all made up of
80 uint64_t's. */
81 headersz = sizeof (struct ctf_archive)
139633c3 82 + (ctf_dict_cnt * sizeof (uint64_t) * 2);
62d8e3b7 83 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
9402cc59
NA
84
85 /* From now on we work in two pieces: an mmap()ed region from zero up to the
86 headersz, and a region updated via write() starting after that, containing
87 all the tables. Platforms that do not support mmap() just use write(). */
88 ctf_startoffs = headersz;
89 if (lseek (fd, ctf_startoffs - 1, SEEK_SET) < 0)
90 {
926c9e76 91 errmsg = N_("ctf_arc_write(): cannot extend file while writing");
5537f9b9 92 goto err;
9402cc59
NA
93 }
94
95 if (write (fd, &dummy, 1) < 0)
96 {
926c9e76 97 errmsg = N_("ctf_arc_write(): cannot extend file while writing");
5537f9b9 98 goto err;
9402cc59
NA
99 }
100
101 if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
102 {
926c9e76 103 errmsg = N_("ctf_arc_write(): cannot mmap");
5537f9b9 104 goto err;
9402cc59
NA
105 }
106
107 /* Fill in everything we can, which is everything other than the name
108 table offset. */
109 archdr->ctfa_magic = htole64 (CTFA_MAGIC);
139633c3 110 archdr->ctfa_ndicts = htole64 (ctf_dict_cnt);
9402cc59
NA
111 archdr->ctfa_ctfs = htole64 (ctf_startoffs);
112
113 /* We could validate that all CTF files have the same data model, but
114 since any reasonable construction process will be building things of
115 only one bitness anyway, this is pretty pointless, so just use the
116 model of the first CTF file for all of them. (It *is* valid to
117 create an empty archive: the value of ctfa_model is irrelevant in
118 this case, but we must be sure not to dereference uninitialized
119 memory.) */
120
139633c3
NA
121 if (ctf_dict_cnt > 0)
122 archdr->ctfa_model = htole64 (ctf_getmodel (ctf_dicts[0]));
9402cc59
NA
123
124 /* Now write out the CTFs: ctf_archive_modent array via the mapping,
125 ctfs via write(). The names themselves have not been written yet: we
126 track them in a local strtab until the time is right, and sort the
127 modents array after construction.
128
129 The name table is not sorted. */
130
139633c3 131 for (i = 0, namesz = 0; i < le64toh (archdr->ctfa_ndicts); i++)
9402cc59
NA
132 namesz += strlen (names[i]) + 1;
133
134 nametbl = malloc (namesz);
135 if (nametbl == NULL)
136 {
926c9e76 137 errmsg = N_("ctf_arc_write(): error writing named CTF to archive");
9402cc59
NA
138 goto err_unmap;
139 }
140
141 for (i = 0, namesz = 0,
142 modent = (ctf_archive_modent_t *) ((char *) archdr
143 + sizeof (struct ctf_archive));
139633c3 144 i < le64toh (archdr->ctfa_ndicts); i++)
9402cc59
NA
145 {
146 off_t off;
147
148 strcpy (&nametbl[namesz], names[i]);
149
139633c3 150 off = arc_write_one_ctf (ctf_dicts[i], fd, threshold);
9402cc59
NA
151 if ((off < 0) && (off > -ECTF_BASE))
152 {
926c9e76
NA
153 errmsg = N_("ctf_arc_write(): cannot determine file "
154 "position while writing to archive");
9402cc59
NA
155 goto err_free;
156 }
157 if (off < 0)
158 {
926c9e76 159 errmsg = N_("ctf_arc_write(): cannot write CTF file to archive");
9402cc59
NA
160 errno = off * -1;
161 goto err_free;
162 }
163
164 modent->name_offset = htole64 (namesz);
165 modent->ctf_offset = htole64 (off - ctf_startoffs);
166 namesz += strlen (names[i]) + 1;
167 modent++;
168 }
169
6b22174f
NA
170 ctf_qsort_r ((ctf_archive_modent_t *) ((char *) archdr
171 + sizeof (struct ctf_archive)),
139633c3 172 le64toh (archdr->ctfa_ndicts),
6b22174f
NA
173 sizeof (struct ctf_archive_modent), sort_modent_by_name,
174 nametbl);
9402cc59
NA
175
176 /* Now the name table. */
177
178 if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
179 {
926c9e76
NA
180 errmsg = N_("ctf_arc_write(): cannot get current file position "
181 "in archive");
9402cc59
NA
182 goto err_free;
183 }
184 archdr->ctfa_names = htole64 (nameoffs);
185 np = nametbl;
186 while (namesz > 0)
187 {
188 ssize_t len;
189 if ((len = write (fd, np, namesz)) < 0)
190 {
926c9e76 191 errmsg = N_("ctf_arc_write(): cannot write name table to archive");
9402cc59
NA
192 goto err_free;
193 }
194 namesz -= len;
195 np += len;
196 }
197 free (nametbl);
198
199 if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
200 goto err_unmap;
201 if (arc_mmap_unmap (archdr, headersz, &errmsg) < 0)
5537f9b9 202 goto err;
9402cc59
NA
203 return 0;
204
205err_free:
206 free (nametbl);
207err_unmap:
208 arc_mmap_unmap (archdr, headersz, NULL);
9402cc59 209err:
926c9e76
NA
210 /* We report errors into the first file in the archive, if any: if this is a
211 zero-file archive, put it in the open-errors stream for lack of anywhere
212 else for it to go. */
139633c3 213 ctf_err_warn (ctf_dict_cnt > 0 ? ctf_dicts[0] : NULL, 0, errno, "%s",
926c9e76 214 gettext (errmsg));
9402cc59
NA
215 return errno;
216}
217
139633c3
NA
218/* Write out a CTF archive. The entries in CTF_DICTS are referenced by name:
219 the names are passed in the names array, which must have CTF_DICTS entries.
5537f9b9
NA
220
221 If the filename is NULL, create a temporary file and return a pointer to it.
222
223 Returns 0 on success, or an errno, or an ECTF_* value. */
224int
139633c3 225ctf_arc_write (const char *file, ctf_dict_t **ctf_dicts, size_t ctf_dict_cnt,
5537f9b9
NA
226 const char **names, size_t threshold)
227{
228 int err;
229 int fd;
230
231 if ((fd = open (file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0)
232 {
139633c3 233 ctf_err_warn (ctf_dict_cnt > 0 ? ctf_dicts[0] : NULL, 0, errno,
926c9e76 234 _("ctf_arc_write(): cannot create %s"), file);
5537f9b9
NA
235 return errno;
236 }
237
139633c3 238 err = ctf_arc_write_fd (fd, ctf_dicts, ctf_dict_cnt, names, threshold);
5537f9b9 239 if (err)
df16e041 240 goto err_close;
5537f9b9
NA
241
242 if ((err = close (fd)) < 0)
139633c3 243 ctf_err_warn (ctf_dict_cnt > 0 ? ctf_dicts[0] : NULL, 0, errno,
926c9e76 244 _("ctf_arc_write(): cannot close after writing to archive"));
df16e041 245 goto err;
5537f9b9
NA
246
247 err_close:
df16e041
NC
248 (void) close (fd);
249 err:
5537f9b9
NA
250 if (err < 0)
251 unlink (file);
252
253 return err;
254}
255
483546ce 256/* Write one CTF dict out. Return the file position of the written file (or
9402cc59
NA
257 rather, of the file-size uint64_t that precedes it): negative return is a
258 negative errno or ctf_errno value. On error, the file position may no longer
259 be at the end of the file. */
260static off_t
483546ce 261arc_write_one_ctf (ctf_dict_t *f, int fd, size_t threshold)
9402cc59
NA
262{
263 off_t off, end_off;
264 uint64_t ctfsz = 0;
265 char *ctfszp;
266 size_t ctfsz_len;
139633c3 267 int (*writefn) (ctf_dict_t * fp, int fd);
9402cc59
NA
268
269 if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
270 return errno * -1;
271
272 if (f->ctf_size > threshold)
273 writefn = ctf_compress_write;
274 else
275 writefn = ctf_write;
276
277 /* This zero-write turns into the size in a moment. */
278 ctfsz_len = sizeof (ctfsz);
279 ctfszp = (char *) &ctfsz;
280 while (ctfsz_len > 0)
281 {
282 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
283 if (writelen < 0)
284 return errno * -1;
285 ctfsz_len -= writelen;
286 ctfszp += writelen;
287 }
288
289 if (writefn (f, fd) != 0)
290 return f->ctf_errno * -1;
291
292 if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
293 return errno * -1;
294 ctfsz = htole64 (end_off - off);
295
296 if ((lseek (fd, off, SEEK_SET)) < 0)
297 return errno * -1;
298
299 /* ... here. */
300 ctfsz_len = sizeof (ctfsz);
301 ctfszp = (char *) &ctfsz;
302 while (ctfsz_len > 0)
303 {
304 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
305 if (writelen < 0)
306 return errno * -1;
307 ctfsz_len -= writelen;
308 ctfszp += writelen;
309 }
310
311 end_off = LCTF_ALIGN_OFFS (end_off, 8);
312 if ((lseek (fd, end_off, SEEK_SET)) < 0)
313 return errno * -1;
314
315 return off;
316}
317
318/* qsort() function to sort the array of struct ctf_archive_modents into
319 ascending name order. */
320static int
321sort_modent_by_name (const void *one, const void *two, void *n)
322{
323 const struct ctf_archive_modent *a = one;
324 const struct ctf_archive_modent *b = two;
325 char *nametbl = n;
326
327 return strcmp (&nametbl[le64toh (a->name_offset)],
328 &nametbl[le64toh (b->name_offset)]);
329}
330
2e428e74 331/* bsearch_r() function to search for a given name in the sorted array of struct
9402cc59
NA
332 ctf_archive_modents. */
333static int
2e428e74 334search_modent_by_name (const void *key, const void *ent, void *arg)
9402cc59
NA
335{
336 const char *k = key;
337 const struct ctf_archive_modent *v = ent;
2e428e74 338 const char *search_nametbl = arg;
9402cc59
NA
339
340 return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
341}
342
2f6ecaed 343/* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
139633c3 344 ctf_dict. Closes ARC and/or FP on error. Arrange to free the SYMSECT or
601e455b 345 STRSECT, as needed, on close. Possibly do not unmap on close. */
2f6ecaed
NA
346
347struct ctf_archive_internal *
601e455b
NA
348ctf_new_archive_internal (int is_archive, int unmap_on_close,
349 struct ctf_archive *arc,
139633c3 350 ctf_dict_t *fp, const ctf_sect_t *symsect,
2f6ecaed
NA
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 358 if (is_archive)
601e455b
NA
359 {
360 if (unmap_on_close)
361 ctf_arc_close_internal (arc);
362 }
2f6ecaed 363 else
139633c3 364 ctf_dict_close (fp);
2f6ecaed 365 return (ctf_set_open_errno (errp, errno));
9402cc59 366 }
2f6ecaed
NA
367 arci->ctfi_is_archive = is_archive;
368 if (is_archive)
369 arci->ctfi_archive = arc;
370 else
139633c3 371 arci->ctfi_dict = fp;
2f6ecaed
NA
372 if (symsect)
373 memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect));
374 if (strsect)
375 memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
376 arci->ctfi_free_symsect = 0;
d50c0802 377 arci->ctfi_free_strsect = 0;
601e455b 378 arci->ctfi_unmap_on_close = unmap_on_close;
53651de8 379 arci->ctfi_symsect_little_endian = -1;
2f6ecaed
NA
380
381 return arci;
382}
383
53651de8
NA
384/* Set the symbol-table endianness of an archive (defaulting the symtab
385 endianness of all ctf_file_t's opened from that archive). */
386void
387ctf_arc_symsect_endianness (ctf_archive_t *arc, int little_endian)
388{
389 arc->ctfi_symsect_little_endian = !!little_endian;
390 if (!arc->ctfi_is_archive)
391 ctf_symsect_endianness (arc->ctfi_dict, arc->ctfi_symsect_little_endian);
392}
393
3d16b64e
NA
394/* Get the CTF preamble from data in a buffer, which may be either an archive or
395 a CTF dict. If multiple dicts are present in an archive, the preamble comes
396 from an arbitrary dict. The preamble is a pointer into the ctfsect passed
397 in. */
398
399const ctf_preamble_t *
400ctf_arc_bufpreamble (const ctf_sect_t *ctfsect)
401{
027333da
AM
402 if (ctfsect->cts_data != NULL
403 && ctfsect->cts_size > sizeof (uint64_t)
404 && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
3d16b64e
NA
405 {
406 struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data;
407 return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs)
408 + sizeof (uint64_t));
409 }
410 else
411 return (const ctf_preamble_t *) ctfsect->cts_data;
412}
413
2f6ecaed
NA
414/* Open a CTF archive or dictionary from data in a buffer (which the caller must
415 preserve until ctf_arc_close() time). Returns the archive, or NULL and an
416 error in *err (if not NULL). */
417ctf_archive_t *
418ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
419 const ctf_sect_t *strsect, int *errp)
420{
421 struct ctf_archive *arc = NULL;
422 int is_archive;
139633c3 423 ctf_dict_t *fp = NULL;
2f6ecaed 424
027333da
AM
425 if (ctfsect->cts_data != NULL
426 && ctfsect->cts_size > sizeof (uint64_t)
427 && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
2f6ecaed 428 {
601e455b
NA
429 /* The archive is mmappable, so this operation is trivial.
430
431 This buffer is nonmodifiable, so the trick involving mmapping only part
432 of it and storing the length in the magic number is not applicable: so
433 record this fact in the archive-wrapper header. (We cannot record it
434 in the archive, because the archive may very well be a read-only
435 mapping.) */
2f6ecaed
NA
436
437 is_archive = 1;
438 arc = (struct ctf_archive *) ctfsect->cts_data;
439 }
440 else
441 {
442 is_archive = 0;
443 if ((fp = ctf_bufopen (ctfsect, symsect, strsect, errp)) == NULL)
444 {
926c9e76 445 ctf_err_warn (NULL, 0, *errp, _("ctf_arc_bufopen(): cannot open CTF"));
2f6ecaed
NA
446 return NULL;
447 }
448 }
601e455b 449 return ctf_new_archive_internal (is_archive, 0, arc, fp, symsect, strsect,
2f6ecaed 450 errp);
9402cc59
NA
451}
452
453/* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
454 not NULL). */
455struct ctf_archive *
456ctf_arc_open_internal (const char *filename, int *errp)
457{
458 const char *errmsg;
459 int fd;
460 struct stat s;
461 struct ctf_archive *arc; /* (Actually the whole file.) */
462
463 libctf_init_debug();
464 if ((fd = open (filename, O_RDONLY)) < 0)
465 {
926c9e76 466 errmsg = N_("ctf_arc_open(): cannot open %s");
9402cc59
NA
467 goto err;
468 }
469 if (fstat (fd, &s) < 0)
470 {
926c9e76 471 errmsg = N_("ctf_arc_open(): cannot stat %s");
9402cc59
NA
472 goto err_close;
473 }
474
475 if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
476 {
926c9e76 477 errmsg = N_("ctf_arc_open(): cannot read in %s");
9402cc59
NA
478 goto err_close;
479 }
480
481 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
482 {
926c9e76 483 errmsg = N_("ctf_arc_open(): %s: invalid magic number");
9402cc59
NA
484 errno = ECTF_FMT;
485 goto err_unmap;
486 }
487
488 /* This horrible hack lets us know how much to unmap when the file is
489 closed. (We no longer need the magic number, and the mapping
490 is private.) */
491 arc->ctfa_magic = s.st_size;
492 close (fd);
493 return arc;
494
495err_unmap:
496 arc_mmap_unmap (arc, s.st_size, NULL);
497err_close:
498 close (fd);
499err:
500 if (errp)
501 *errp = errno;
926c9e76 502 ctf_err_warn (NULL, 0, errno, gettext (errmsg), filename);
9402cc59
NA
503 return NULL;
504}
505
506/* Close an archive. */
507void
508ctf_arc_close_internal (struct ctf_archive *arc)
509{
510 if (arc == NULL)
511 return;
512
513 /* See the comment in ctf_arc_open(). */
514 arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
515}
516
517/* Public entry point: close an archive, or CTF file. */
518void
519ctf_arc_close (ctf_archive_t *arc)
520{
521 if (arc == NULL)
522 return;
523
524 if (arc->ctfi_is_archive)
601e455b
NA
525 {
526 if (arc->ctfi_unmap_on_close)
527 ctf_arc_close_internal (arc->ctfi_archive);
528 }
9402cc59 529 else
139633c3 530 ctf_dict_close (arc->ctfi_dict);
2c78e925 531 free (arc->ctfi_symdicts);
f4f60336 532 free (arc->ctfi_symnamedicts);
2c78e925 533 ctf_dynhash_destroy (arc->ctfi_dicts);
2f6ecaed
NA
534 if (arc->ctfi_free_symsect)
535 free ((void *) arc->ctfi_symsect.cts_data);
d50c0802
NA
536 if (arc->ctfi_free_strsect)
537 free ((void *) arc->ctfi_strsect.cts_data);
9402cc59 538 free (arc->ctfi_data);
f046147d
NA
539 if (arc->ctfi_bfd_close)
540 arc->ctfi_bfd_close (arc);
9402cc59
NA
541 free (arc);
542}
543
139633c3 544/* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
9402cc59 545 non-NULL. A name of NULL means to open the default file. */
139633c3 546static ctf_dict_t *
ae41200b
NA
547ctf_dict_open_internal (const struct ctf_archive *arc,
548 const ctf_sect_t *symsect,
549 const ctf_sect_t *strsect,
53651de8
NA
550 const char *name, int little_endian,
551 int *errp)
9402cc59
NA
552{
553 struct ctf_archive_modent *modent;
2e428e74 554 const char *search_nametbl;
9402cc59
NA
555
556 if (name == NULL)
557 name = _CTF_SECTION; /* The default name. */
558
ae41200b 559 ctf_dprintf ("ctf_dict_open_internal(%s): opening\n", name);
9402cc59
NA
560
561 modent = (ctf_archive_modent_t *) ((char *) arc
562 + sizeof (struct ctf_archive));
563
2e428e74 564 search_nametbl = (const char *) arc + le64toh (arc->ctfa_names);
139633c3 565 modent = bsearch_r (name, modent, le64toh (arc->ctfa_ndicts),
2e428e74
NA
566 sizeof (struct ctf_archive_modent),
567 search_modent_by_name, (void *) search_nametbl);
9402cc59
NA
568
569 /* This is actually a common case and normal operation: no error
570 debug output. */
571 if (modent == NULL)
572 {
573 if (errp)
574 *errp = ECTF_ARNNAME;
575 return NULL;
576 }
577
ae41200b 578 return ctf_dict_open_by_offset (arc, symsect, strsect,
53651de8
NA
579 le64toh (modent->ctf_offset),
580 little_endian, errp);
9402cc59
NA
581}
582
139633c3 583/* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
9402cc59
NA
584 non-NULL. A name of NULL means to open the default file.
585
586 Use the specified string and symbol table sections.
587
588 Public entry point. */
139633c3 589ctf_dict_t *
ae41200b
NA
590ctf_dict_open_sections (const ctf_archive_t *arc,
591 const ctf_sect_t *symsect,
592 const ctf_sect_t *strsect,
593 const char *name,
594 int *errp)
9402cc59
NA
595{
596 if (arc->ctfi_is_archive)
597 {
139633c3 598 ctf_dict_t *ret;
ae41200b 599 ret = ctf_dict_open_internal (arc->ctfi_archive, symsect, strsect,
53651de8
NA
600 name, arc->ctfi_symsect_little_endian,
601 errp);
9402cc59 602 if (ret)
2c78e925
NA
603 {
604 ret->ctf_archive = (ctf_archive_t *) arc;
605 ctf_arc_import_parent (arc, ret);
606 }
9402cc59
NA
607 return ret;
608 }
609
610 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
611 {
612 if (errp)
613 *errp = ECTF_ARNNAME;
614 return NULL;
615 }
139633c3 616 arc->ctfi_dict->ctf_archive = (ctf_archive_t *) arc;
9402cc59 617
139633c3
NA
618 /* Bump the refcount so that the user can ctf_dict_close() it. */
619 arc->ctfi_dict->ctf_refcnt++;
620 return arc->ctfi_dict;
9402cc59
NA
621}
622
139633c3 623/* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
9402cc59
NA
624 non-NULL. A name of NULL means to open the default file.
625
626 Public entry point. */
139633c3 627ctf_dict_t *
ae41200b 628ctf_dict_open (const ctf_archive_t *arc, const char *name, int *errp)
9402cc59
NA
629{
630 const ctf_sect_t *symsect = &arc->ctfi_symsect;
631 const ctf_sect_t *strsect = &arc->ctfi_strsect;
632
633 if (symsect->cts_name == NULL)
634 symsect = NULL;
635 if (strsect->cts_name == NULL)
636 strsect = NULL;
637
ae41200b 638 return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
9402cc59
NA
639}
640
2c78e925
NA
641static void
642ctf_cached_dict_close (void *fp)
643{
644 ctf_dict_close ((ctf_dict_t *) fp);
645}
646
f4f60336
NA
647/* Return the ctf_dict_t with the given name and cache it in the archive's
648 ctfi_dicts. If this is the first cached dict, designate it the
649 crossdict_cache. */
2c78e925
NA
650static ctf_dict_t *
651ctf_dict_open_cached (ctf_archive_t *arc, const char *name, int *errp)
652{
653 ctf_dict_t *fp;
654 char *dupname;
655
656 /* Just return from the cache if possible. */
657 if (arc->ctfi_dicts
658 && ((fp = ctf_dynhash_lookup (arc->ctfi_dicts, name)) != NULL))
659 {
660 fp->ctf_refcnt++;
661 return fp;
662 }
663
664 /* Not yet cached: open it. */
665 fp = ctf_dict_open (arc, name, errp);
666 dupname = strdup (name);
667
668 if (!fp || !dupname)
669 goto oom;
670
671 if (arc->ctfi_dicts == NULL)
672 if ((arc->ctfi_dicts
673 = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
674 free, ctf_cached_dict_close)) == NULL)
675 goto oom;
676
677 if (ctf_dynhash_insert (arc->ctfi_dicts, dupname, fp) < 0)
678 goto oom;
679 fp->ctf_refcnt++;
680
f4f60336
NA
681 if (arc->ctfi_crossdict_cache == NULL)
682 arc->ctfi_crossdict_cache = fp;
683
2c78e925
NA
684 return fp;
685
686 oom:
687 ctf_dict_close (fp);
688 free (dupname);
689 if (errp)
690 *errp = ENOMEM;
691 return NULL;
692}
693
694/* Flush any caches the CTF archive may have open. */
695void
696ctf_arc_flush_caches (ctf_archive_t *wrapper)
697{
698 free (wrapper->ctfi_symdicts);
ca019227 699 ctf_dynhash_destroy (wrapper->ctfi_symnamedicts);
2c78e925
NA
700 ctf_dynhash_destroy (wrapper->ctfi_dicts);
701 wrapper->ctfi_symdicts = NULL;
f4f60336 702 wrapper->ctfi_symnamedicts = NULL;
2c78e925 703 wrapper->ctfi_dicts = NULL;
f4f60336 704 wrapper->ctfi_crossdict_cache = NULL;
2c78e925
NA
705}
706
139633c3 707/* Return the ctf_dict_t at the given ctfa_ctfs-relative offset, or NULL if
9402cc59 708 none, setting 'err' if non-NULL. */
139633c3 709static ctf_dict_t *
ae41200b
NA
710ctf_dict_open_by_offset (const struct ctf_archive *arc,
711 const ctf_sect_t *symsect,
712 const ctf_sect_t *strsect, size_t offset,
53651de8 713 int little_endian, int *errp)
9402cc59
NA
714{
715 ctf_sect_t ctfsect;
139633c3 716 ctf_dict_t *fp;
9402cc59 717
ae41200b 718 ctf_dprintf ("ctf_dict_open_by_offset(%lu): opening\n", (unsigned long) offset);
9402cc59 719
a0486bac 720 memset (&ctfsect, 0, sizeof (ctf_sect_t));
9402cc59
NA
721
722 offset += le64toh (arc->ctfa_ctfs);
723
724 ctfsect.cts_name = _CTF_SECTION;
9402cc59
NA
725 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
726 ctfsect.cts_entsize = 1;
9402cc59
NA
727 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
728 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
729 if (fp)
53651de8
NA
730 {
731 ctf_setmodel (fp, le64toh (arc->ctfa_model));
732 if (little_endian >= 0)
733 ctf_symsect_endianness (fp, little_endian);
734 }
9402cc59
NA
735 return fp;
736}
737
ae41200b
NA
738/* Backward compatibility. */
739ctf_dict_t *
740ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name,
741 int *errp)
742{
743 return ctf_dict_open (arc, name, errp);
744}
745
746ctf_dict_t *
747ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
748 const ctf_sect_t *symsect,
749 const ctf_sect_t *strsect,
750 const char *name,
751 int *errp)
752{
753 return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
754}
755
2c78e925
NA
756/* Import the parent into a ctf archive, if this is a child, the parent is not
757 already set, and a suitable archive member exists. No error is raised if
758 this is not possible: this is just a best-effort helper operation to give
759 people useful dicts to start with. */
760static void
761ctf_arc_import_parent (const ctf_archive_t *arc, ctf_dict_t *fp)
762{
763 if ((fp->ctf_flags & LCTF_CHILD) && fp->ctf_parname && !fp->ctf_parent)
764 {
765 ctf_dict_t *parent = ctf_dict_open_cached ((ctf_archive_t *) arc,
766 fp->ctf_parname, NULL);
767 if (parent)
768 {
769 ctf_import (fp, parent);
770 ctf_dict_close (parent);
771 }
772 }
773}
774
9c23dfa5
NA
775/* Return the number of members in an archive. */
776size_t
777ctf_archive_count (const ctf_archive_t *wrapper)
778{
779 if (!wrapper->ctfi_is_archive)
780 return 1;
781
139633c3 782 return wrapper->ctfi_archive->ctfa_ndicts;
9c23dfa5
NA
783}
784
f4f60336
NA
785/* Look up a symbol in an archive by name or index (if the name is set, a lookup
786 by name is done). Return the dict in the archive that the symbol is found
787 in, and (optionally) the ctf_id_t of the symbol in that dict (so you don't
788 have to look it up yourself). The dict is cached, so repeated lookups are
789 nearly free.
2c78e925
NA
790
791 As usual, you should ctf_dict_close() the returned dict once you are done
792 with it.
793
794 Returns NULL on error, and an error in errp (if set). */
795
f4f60336
NA
796static ctf_dict_t *
797ctf_arc_lookup_sym_or_name (ctf_archive_t *wrapper, unsigned long symidx,
798 const char *symname, ctf_id_t *typep, int *errp)
2c78e925
NA
799{
800 ctf_dict_t *fp;
f4f60336 801 void *fpkey;
2c78e925
NA
802 ctf_id_t type;
803
804 /* The usual non-archive-transparent-wrapper special case. */
805 if (!wrapper->ctfi_is_archive)
806 {
f4f60336 807 if (!symname)
2c78e925 808 {
f4f60336
NA
809 if ((type = ctf_lookup_by_symbol (wrapper->ctfi_dict, symidx)) == CTF_ERR)
810 {
811 if (errp)
812 *errp = ctf_errno (wrapper->ctfi_dict);
813 return NULL;
814 }
815 }
816 else
817 {
818 if ((type = ctf_lookup_by_symbol_name (wrapper->ctfi_dict,
819 symname)) == CTF_ERR)
820 {
821 if (errp)
822 *errp = ctf_errno (wrapper->ctfi_dict);
823 return NULL;
824 }
2c78e925
NA
825 }
826 if (typep)
827 *typep = type;
828 wrapper->ctfi_dict->ctf_refcnt++;
829 return wrapper->ctfi_dict;
830 }
831
832 if (wrapper->ctfi_symsect.cts_name == NULL
833 || wrapper->ctfi_symsect.cts_data == NULL
834 || wrapper->ctfi_symsect.cts_size == 0
835 || wrapper->ctfi_symsect.cts_entsize == 0)
836 {
837 if (errp)
838 *errp = ECTF_NOSYMTAB;
839 return NULL;
840 }
841
f4f60336
NA
842 /* Make enough space for all possible symbol indexes, if not already done. We
843 cache the originating dictionary of all symbols. The dict links are weak,
844 to the dictionaries cached in ctfi_dicts: their refcnts are *not* bumped.
845 We also cache similar mappings for symbol names: these are ordinary
846 dynhashes, with weak links to dicts. */
2c78e925 847
f4f60336 848 if (!wrapper->ctfi_symdicts)
2c78e925 849 {
f4f60336
NA
850 if ((wrapper->ctfi_symdicts = calloc (wrapper->ctfi_symsect.cts_size
851 / wrapper->ctfi_symsect.cts_entsize,
852 sizeof (ctf_dict_t *))) == NULL)
2c78e925
NA
853 {
854 if (errp)
855 *errp = ENOMEM;
856 return NULL;
857 }
858 }
f4f60336 859 if (!wrapper->ctfi_symnamedicts)
2c78e925 860 {
f4f60336
NA
861 if ((wrapper->ctfi_symnamedicts = ctf_dynhash_create (ctf_hash_string,
862 ctf_hash_eq_string,
863 free, NULL)) == NULL)
2c78e925
NA
864 {
865 if (errp)
866 *errp = ENOMEM;
867 return NULL;
868 }
869 }
870
f4f60336
NA
871 /* Perhaps the dict in which we found a previous lookup is cached. If it's
872 supposed to be cached but we don't find it, pretend it was always not
873 found: this should never happen, but shouldn't be allowed to cause trouble
874 if it does. */
875
876 if ((symname && ctf_dynhash_lookup_kv (wrapper->ctfi_symnamedicts,
877 symname, NULL, &fpkey))
878 || (!symname && wrapper->ctfi_symdicts[symidx] != NULL))
2c78e925 879 {
f4f60336
NA
880 if (symname)
881 fp = (ctf_dict_t *) fpkey;
882 else
883 fp = wrapper->ctfi_symdicts[symidx];
884
885 if (fp == &enosym)
886 goto no_sym;
887
888 if (symname)
2c78e925 889 {
f4f60336
NA
890 if ((type = ctf_lookup_by_symbol_name (fp, symname)) == CTF_ERR)
891 goto cache_no_sym;
892 }
893 else
894 {
895 if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
896 goto cache_no_sym;
2c78e925
NA
897 }
898
899 if (typep)
f4f60336
NA
900 *typep = type;
901 fp->ctf_refcnt++;
902 return fp;
2c78e925
NA
903 }
904
905 /* Not cached: find it and cache it. We must track open errors ourselves even
906 if our caller doesn't, to be able to distinguish no-error end-of-iteration
907 from open errors. */
908
909 int local_err;
910 int *local_errp;
911 ctf_next_t *i = NULL;
912 const char *name;
913
914 if (errp)
915 local_errp = errp;
916 else
917 local_errp = &local_err;
918
919 while ((fp = ctf_archive_next (wrapper, &i, &name, 0, local_errp)) != NULL)
920 {
f4f60336 921 if (!symname)
2c78e925 922 {
f4f60336
NA
923 if ((type = ctf_lookup_by_symbol (fp, symidx)) != CTF_ERR)
924 wrapper->ctfi_symdicts[symidx] = fp;
925 }
926 else
927 {
928 if ((type = ctf_lookup_by_symbol_name (fp, symname)) != CTF_ERR)
929 {
930 char *tmp;
931 /* No error checking, as above. */
932 if ((tmp = strdup (symname)) != NULL)
933 ctf_dynhash_insert (wrapper->ctfi_symnamedicts, tmp, fp);
934 }
935 }
2c78e925 936
f4f60336
NA
937 if (type != CTF_ERR)
938 {
2c78e925
NA
939 if (typep)
940 *typep = type;
f4f60336 941 ctf_next_destroy (i);
2c78e925
NA
942 return fp;
943 }
f4f60336
NA
944 if (ctf_errno (fp) != ECTF_NOTYPEDAT)
945 {
946 if (errp)
947 *errp = ctf_errno (fp);
948 ctf_next_destroy (i);
949 return NULL; /* errno is set for us. */
950 }
2c78e925
NA
951 ctf_dict_close (fp);
952 }
953 if (*local_errp != ECTF_NEXT_END)
954 {
955 ctf_next_destroy (i);
956 return NULL;
957 }
f4f60336 958
2c78e925
NA
959 /* Don't leak end-of-iteration to the caller. */
960 *local_errp = 0;
961
f4f60336
NA
962 cache_no_sym:
963 if (!symname)
964 wrapper->ctfi_symdicts[symidx] = &enosym;
965 else
966 {
967 char *tmp;
968
969 /* No error checking: if caching fails, there is only a slight performance
970 impact. */
971 if ((tmp = strdup (symname)) != NULL)
972 if (ctf_dynhash_insert (wrapper->ctfi_symnamedicts, tmp, &enosym) < 0)
973 free (tmp);
974 }
2c78e925 975
f4f60336 976 no_sym:
2c78e925
NA
977 if (errp)
978 *errp = ECTF_NOTYPEDAT;
979 if (typep)
980 *typep = CTF_ERR;
981 return NULL;
982}
983
f4f60336
NA
984/* The public API for looking up a symbol by index. */
985ctf_dict_t *
986ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
987 ctf_id_t *typep, int *errp)
988{
989 return ctf_arc_lookup_sym_or_name (wrapper, symidx, NULL, typep, errp);
990}
991
992/* The public API for looking up a symbol by name. */
993
994ctf_dict_t *
995ctf_arc_lookup_symbol_name (ctf_archive_t *wrapper, const char *symname,
996 ctf_id_t *typep, int *errp)
997{
998 return ctf_arc_lookup_sym_or_name (wrapper, 0, symname, typep, errp);
999}
1000
9402cc59
NA
1001/* Raw iteration over all CTF files in an archive. We pass the raw data for all
1002 CTF files in turn to the specified callback function. */
1003static int
1004ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
1005 ctf_archive_raw_member_f *func, void *data)
1006{
1007 int rc;
1008 size_t i;
1009 struct ctf_archive_modent *modent;
1010 const char *nametbl;
1011
1012 modent = (ctf_archive_modent_t *) ((char *) arc
1013 + sizeof (struct ctf_archive));
1014 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
1015
139633c3 1016 for (i = 0; i < le64toh (arc->ctfa_ndicts); i++)
9402cc59
NA
1017 {
1018 const char *name;
1019 char *fp;
1020
1021 name = &nametbl[le64toh (modent[i].name_offset)];
1022 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
1023 + le64toh (modent[i].ctf_offset));
1024
1025 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
1026 le64toh (*((uint64_t *) fp)), data)) != 0)
1027 return rc;
1028 }
1029 return 0;
1030}
1031
1032/* Raw iteration over all CTF files in an archive: public entry point.
1033
1034 Returns -EINVAL if not supported for this sort of archive. */
1035int
1036ctf_archive_raw_iter (const ctf_archive_t *arc,
1037 ctf_archive_raw_member_f * func, void *data)
1038{
1039 if (arc->ctfi_is_archive)
1040 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
1041
1042 return -EINVAL; /* Not supported. */
1043}
1044
ac36e134
NA
1045/* Iterate over all CTF files in an archive: public entry point. We pass all
1046 CTF files in turn to the specified callback function. */
1047int
1048ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
1049 void *data)
9402cc59 1050{
ac36e134
NA
1051 ctf_next_t *i = NULL;
1052 ctf_dict_t *fp;
1053 const char *name;
1054 int err;
9402cc59 1055
ac36e134 1056 while ((fp = ctf_archive_next (arc, &i, &name, 0, &err)) != NULL)
9402cc59 1057 {
ac36e134 1058 int rc;
9402cc59 1059
ac36e134 1060 if ((rc = func (fp, name, data)) != 0)
9402cc59 1061 {
ac36e134
NA
1062 ctf_dict_close (fp);
1063 ctf_next_destroy (i);
9402cc59
NA
1064 return rc;
1065 }
ac36e134 1066 ctf_dict_close (fp);
9402cc59
NA
1067 }
1068 return 0;
1069}
1070
688d28f6 1071/* Iterate over all CTF files in an archive, returning each dict in turn as a
139633c3 1072 ctf_dict_t, and NULL on error or end of iteration. It is the caller's
8769046e 1073 responsibility to close it. Parent dicts may be skipped.
688d28f6 1074
2c78e925
NA
1075 The archive member is cached for rapid return on future calls.
1076
688d28f6
NA
1077 We identify parents by name rather than by flag value: for now, with the
1078 linker only emitting parents named _CTF_SECTION, this works well enough. */
1079
139633c3 1080ctf_dict_t *
688d28f6
NA
1081ctf_archive_next (const ctf_archive_t *wrapper, ctf_next_t **it, const char **name,
1082 int skip_parent, int *errp)
1083{
139633c3 1084 ctf_dict_t *f;
688d28f6
NA
1085 ctf_next_t *i = *it;
1086 struct ctf_archive *arc;
1087 struct ctf_archive_modent *modent;
1088 const char *nametbl;
1089 const char *name_;
1090
1091 if (!i)
1092 {
1093 if ((i = ctf_next_create()) == NULL)
1094 {
1095 if (errp)
1096 *errp = ENOMEM;
1097 return NULL;
1098 }
1099 i->cu.ctn_arc = wrapper;
1100 i->ctn_iter_fun = (void (*) (void)) ctf_archive_next;
1101 *it = i;
1102 }
1103
1104 if ((void (*) (void)) ctf_archive_next != i->ctn_iter_fun)
1105 {
1106 if (errp)
1107 *errp = ECTF_NEXT_WRONGFUN;
1108 return NULL;
1109 }
1110
1111 if (wrapper != i->cu.ctn_arc)
1112 {
1113 if (errp)
1114 *errp = ECTF_NEXT_WRONGFP;
1115 return NULL;
1116 }
1117
139633c3 1118 /* Iteration is made a bit more complex by the need to handle ctf_dict_t's
688d28f6
NA
1119 transparently wrapped in a single-member archive. These are parents: if
1120 skip_parent is on, they are skipped and the iterator terminates
1121 immediately. */
1122
1123 if (!wrapper->ctfi_is_archive && i->ctn_n == 0)
1124 {
1125 i->ctn_n++;
1126 if (!skip_parent)
1127 {
139633c3 1128 wrapper->ctfi_dict->ctf_refcnt++;
eaa2913a
NA
1129 if (name)
1130 *name = _CTF_SECTION;
139633c3 1131 return wrapper->ctfi_dict;
688d28f6
NA
1132 }
1133 }
1134
1135 arc = wrapper->ctfi_archive;
1136
1137 /* The loop keeps going when skip_parent is on as long as the member we find
1138 is the parent (i.e. at most two iterations, but possibly an early return if
1139 *all* we have is a parent). */
1140
688d28f6
NA
1141 do
1142 {
139633c3 1143 if ((!wrapper->ctfi_is_archive) || (i->ctn_n >= le64toh (arc->ctfa_ndicts)))
688d28f6
NA
1144 {
1145 ctf_next_destroy (i);
1146 *it = NULL;
1147 if (errp)
1148 *errp = ECTF_NEXT_END;
1149 return NULL;
1150 }
1151
688d28f6
NA
1152 modent = (ctf_archive_modent_t *) ((char *) arc
1153 + sizeof (struct ctf_archive));
1154 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
1155
1156 name_ = &nametbl[le64toh (modent[i->ctn_n].name_offset)];
1157 i->ctn_n++;
eefe721e
NA
1158 }
1159 while (skip_parent && strcmp (name_, _CTF_SECTION) == 0);
688d28f6
NA
1160
1161 if (name)
1162 *name = name_;
1163
2c78e925 1164 f = ctf_dict_open_cached ((ctf_archive_t *) wrapper, name_, errp);
688d28f6
NA
1165 return f;
1166}
1167
9402cc59
NA
1168#ifdef HAVE_MMAP
1169/* Map the header in. Only used on new, empty files. */
1170static void *arc_mmap_header (int fd, size_t headersz)
1171{
1172 void *hdr;
1173 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1174 0)) == MAP_FAILED)
1175 return NULL;
1176 return hdr;
1177}
1178
1179/* mmap() the whole file, for reading only. (Map it writably, but privately: we
1180 need to modify the region, but don't need anyone else to see the
1181 modifications.) */
1182static void *arc_mmap_file (int fd, size_t size)
1183{
1184 void *arc;
1185 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
1186 fd, 0)) == MAP_FAILED)
1187 return NULL;
1188 return arc;
1189}
1190
1191/* Persist the header to disk. */
1192static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
1193 size_t headersz, const char **errmsg)
1194{
1195 if (msync (header, headersz, MS_ASYNC) < 0)
1196 {
1197 if (errmsg)
926c9e76
NA
1198 *errmsg = N_("arc_mmap_writeout(): cannot sync after writing "
1199 "to %s: %s");
9402cc59
NA
1200 return -1;
1201 }
1202 return 0;
1203}
1204
1205/* Unmap the region. */
1206static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
1207{
1208 if (munmap (header, headersz) < 0)
1209 {
1210 if (errmsg)
926c9e76
NA
1211 *errmsg = N_("arc_mmap_munmap(): cannot unmap after writing "
1212 "to %s: %s");
9402cc59
NA
1213 return -1;
1214 }
1215 return 0;
1216}
1217#else
1218/* Map the header in. Only used on new, empty files. */
f5e73be1 1219static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
9402cc59
NA
1220{
1221 void *hdr;
1222 if ((hdr = malloc (headersz)) == NULL)
1223 return NULL;
1224 return hdr;
1225}
1226
1227/* Pull in the whole file, for reading only. We assume the current file
1228 position is at the start of the file. */
1229static void *arc_mmap_file (int fd, size_t size)
1230{
1231 char *data;
1232
1233 if ((data = malloc (size)) == NULL)
1234 return NULL;
1235
1236 if (ctf_pread (fd, data, size, 0) < 0)
1237 {
1238 free (data);
1239 return NULL;
1240 }
1241 return data;
1242}
1243
1244/* Persist the header to disk. */
1245static int arc_mmap_writeout (int fd, void *header, size_t headersz,
1246 const char **errmsg)
1247{
1248 ssize_t len;
9402cc59
NA
1249 char *data = (char *) header;
1250 ssize_t count = headersz;
1251
1252 if ((lseek (fd, 0, SEEK_SET)) < 0)
1253 {
1254 if (errmsg)
926c9e76
NA
1255 *errmsg = N_("arc_mmap_writeout(): cannot seek while writing header to "
1256 "%s: %s");
9402cc59
NA
1257 return -1;
1258 }
1259
1260 while (headersz > 0)
1261 {
1262 if ((len = write (fd, data, count)) < 0)
1263 {
1264 if (errmsg)
926c9e76 1265 *errmsg = N_("arc_mmap_writeout(): cannot write header to %s: %s");
9402cc59
NA
1266 return len;
1267 }
1268 if (len == EINTR)
1269 continue;
1270
9402cc59
NA
1271 if (len == 0) /* EOF. */
1272 break;
1273
1274 count -= len;
1275 data += len;
1276 }
1277 return 0;
1278}
1279
1280/* Unmap the region. */
1281static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
1282 const char **errmsg _libctf_unused_)
1283{
1284 free (header);
1285 return 0;
1286}
1287#endif