Coverage Report

Created: 2024-05-21 06:29

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