Coverage Report

Created: 2023-08-28 06:26

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