[gdb/testsuite] Restore breakpoint command in ui-redirect.exp
[external/binutils.git] / libctf / ctf-archive.c
1 /* CTF archive files.
2    Copyright (C) 2019 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_file_t * f, int fd, size_t threshold);
36 static ctf_file_t *ctf_arc_open_by_offset (const struct ctf_archive *arc,
37                                            const ctf_sect_t *symsect,
38                                            const ctf_sect_t *strsect,
39                                            size_t offset, int *errp);
40 static int sort_modent_by_name (const void *one, const void *two, void *n);
41 static void *arc_mmap_header (int fd, size_t headersz);
42 static void *arc_mmap_file (int fd, size_t size);
43 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
44                               const char **errmsg);
45 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
46
47 /* bsearch() internal state.  */
48 static __thread char *search_nametbl;
49
50 /* Write out a CTF archive.  The entries in CTF_FILES are referenced by name:
51    the names are passed in the names array, which must have CTF_FILES entries.
52
53    Returns 0 on success, or an errno, or an ECTF_* value.  */
54 int
55 ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt,
56                const char **names, size_t threshold)
57 {
58   const char *errmsg;
59   struct ctf_archive *archdr;
60   int fd;
61   size_t i;
62   char dummy = 0;
63   size_t headersz;
64   ssize_t namesz;
65   size_t ctf_startoffs;         /* Start of the section we are working over.  */
66   char *nametbl = NULL;         /* The name table.  */
67   char *np;
68   off_t nameoffs;
69   struct ctf_archive_modent *modent;
70
71   ctf_dprintf ("Writing archive %s with %lu files\n", file,
72                (unsigned long) ctf_file_cnt);
73
74   if ((fd = open (file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0)
75     {
76       errmsg = "ctf_arc_write(): cannot create %s: %s\n";
77       goto err;
78     }
79
80   /* Figure out the size of the mmap()ed header, including the
81      ctf_archive_modent array.  We assume that all of this needs no
82      padding: a likely assumption, given that it's all made up of
83      uint64_t's.  */
84   headersz = sizeof (struct ctf_archive)
85     + (ctf_file_cnt * sizeof (uint64_t) * 2);
86   ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
87
88   /* From now on we work in two pieces: an mmap()ed region from zero up to the
89      headersz, and a region updated via write() starting after that, containing
90      all the tables.  Platforms that do not support mmap() just use write().  */
91   ctf_startoffs = headersz;
92   if (lseek (fd, ctf_startoffs - 1, SEEK_SET) < 0)
93     {
94       errmsg = "ctf_arc_write(): cannot extend file while writing %s: %s\n";
95       goto err_close;
96     }
97
98   if (write (fd, &dummy, 1) < 0)
99     {
100       errmsg = "ctf_arc_write(): cannot extend file while writing %s: %s\n";
101       goto err_close;
102     }
103
104   if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
105     {
106       errmsg = "ctf_arc_write(): Cannot mmap() %s: %s\n";
107       goto err_close;
108     }
109
110   /* Fill in everything we can, which is everything other than the name
111      table offset.  */
112   archdr->ctfa_magic = htole64 (CTFA_MAGIC);
113   archdr->ctfa_nfiles = htole64 (ctf_file_cnt);
114   archdr->ctfa_ctfs = htole64 (ctf_startoffs);
115
116   /* We could validate that all CTF files have the same data model, but
117      since any reasonable construction process will be building things of
118      only one bitness anyway, this is pretty pointless, so just use the
119      model of the first CTF file for all of them.  (It *is* valid to
120      create an empty archive: the value of ctfa_model is irrelevant in
121      this case, but we must be sure not to dereference uninitialized
122      memory.)  */
123
124   if (ctf_file_cnt > 0)
125     archdr->ctfa_model = htole64 (ctf_getmodel (ctf_files[0]));
126
127   /* Now write out the CTFs: ctf_archive_modent array via the mapping,
128      ctfs via write().  The names themselves have not been written yet: we
129      track them in a local strtab until the time is right, and sort the
130      modents array after construction.
131
132     The name table is not sorted.  */
133
134   for (i = 0, namesz = 0; i < le64toh (archdr->ctfa_nfiles); i++)
135     namesz += strlen (names[i]) + 1;
136
137   nametbl = malloc (namesz);
138   if (nametbl == NULL)
139     {
140       errmsg = "Error writing named CTF to %s: %s\n";
141       goto err_unmap;
142     }
143
144   for (i = 0, namesz = 0,
145        modent = (ctf_archive_modent_t *) ((char *) archdr
146                                           + sizeof (struct ctf_archive));
147        i < le64toh (archdr->ctfa_nfiles); i++)
148     {
149       off_t off;
150
151       strcpy (&nametbl[namesz], names[i]);
152
153       off = arc_write_one_ctf (ctf_files[i], fd, threshold);
154       if ((off < 0) && (off > -ECTF_BASE))
155         {
156           errmsg = "ctf_arc_write(): Cannot determine file "
157             "position while writing %s: %s";
158           goto err_free;
159         }
160       if (off < 0)
161         {
162           errmsg = "ctf_arc_write(): Cannot write CTF file to %s: %s\n";
163           errno = off * -1;
164           goto err_free;
165         }
166
167       modent->name_offset = htole64 (namesz);
168       modent->ctf_offset = htole64 (off - ctf_startoffs);
169       namesz += strlen (names[i]) + 1;
170       modent++;
171     }
172
173   ctf_qsort_r ((ctf_archive_modent_t *) ((char *) archdr
174                                          + sizeof (struct ctf_archive)),
175                le64toh (archdr->ctfa_nfiles),
176                sizeof (struct ctf_archive_modent), sort_modent_by_name,
177                nametbl);
178
179    /* Now the name table.  */
180
181   if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
182     {
183       errmsg = "ctf_arc_write(): Cannot get current file position "
184         "in %s: %s\n";
185       goto err_free;
186     }
187   archdr->ctfa_names = htole64 (nameoffs);
188   np = nametbl;
189   while (namesz > 0)
190     {
191       ssize_t len;
192       if ((len = write (fd, np, namesz)) < 0)
193         {
194           errmsg = "ctf_arc_write(): Cannot write name table in %s: %s\n";
195           goto err_free;
196         }
197       namesz -= len;
198       np += len;
199     }
200   free (nametbl);
201
202   if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
203     goto err_unmap;
204   if (arc_mmap_unmap (archdr, headersz, &errmsg) < 0)
205     goto err_unlink;
206   if (close (fd) < 0)
207     {
208       errmsg = "ctf_arc_write(): Cannot close after writing to %s: %s\n";
209       goto err_unlink;
210     }
211
212   return 0;
213
214 err_free:
215   free (nametbl);
216 err_unmap:
217   arc_mmap_unmap (archdr, headersz, NULL);
218 err_close:
219   close (fd);
220 err_unlink:
221   unlink (file);
222 err:
223   ctf_dprintf (errmsg, file, errno < ECTF_BASE ? strerror (errno) :
224                ctf_errmsg (errno));
225   return errno;
226 }
227
228 /* Write one CTF file out.  Return the file position of the written file (or
229    rather, of the file-size uint64_t that precedes it): negative return is a
230    negative errno or ctf_errno value.  On error, the file position may no longer
231    be at the end of the file.  */
232 static off_t
233 arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold)
234 {
235   off_t off, end_off;
236   uint64_t ctfsz = 0;
237   char *ctfszp;
238   size_t ctfsz_len;
239   int (*writefn) (ctf_file_t * fp, int fd);
240
241   if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
242     return errno * -1;
243
244   if (f->ctf_size > threshold)
245     writefn = ctf_compress_write;
246   else
247     writefn = ctf_write;
248
249   /* This zero-write turns into the size in a moment. */
250   ctfsz_len = sizeof (ctfsz);
251   ctfszp = (char *) &ctfsz;
252   while (ctfsz_len > 0)
253     {
254       ssize_t writelen = write (fd, ctfszp, ctfsz_len);
255       if (writelen < 0)
256         return errno * -1;
257       ctfsz_len -= writelen;
258       ctfszp += writelen;
259     }
260
261   if (writefn (f, fd) != 0)
262     return f->ctf_errno * -1;
263
264   if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
265     return errno * -1;
266   ctfsz = htole64 (end_off - off);
267
268   if ((lseek (fd, off, SEEK_SET)) < 0)
269     return errno * -1;
270
271   /* ... here.  */
272   ctfsz_len = sizeof (ctfsz);
273   ctfszp = (char *) &ctfsz;
274   while (ctfsz_len > 0)
275     {
276       ssize_t writelen = write (fd, ctfszp, ctfsz_len);
277       if (writelen < 0)
278         return errno * -1;
279       ctfsz_len -= writelen;
280       ctfszp += writelen;
281     }
282
283   end_off = LCTF_ALIGN_OFFS (end_off, 8);
284   if ((lseek (fd, end_off, SEEK_SET)) < 0)
285     return errno * -1;
286
287   return off;
288 }
289
290 /* qsort() function to sort the array of struct ctf_archive_modents into
291    ascending name order.  */
292 static int
293 sort_modent_by_name (const void *one, const void *two, void *n)
294 {
295   const struct ctf_archive_modent *a = one;
296   const struct ctf_archive_modent *b = two;
297   char *nametbl = n;
298
299   return strcmp (&nametbl[le64toh (a->name_offset)],
300                  &nametbl[le64toh (b->name_offset)]);
301 }
302
303 /* bsearch() function to search for a given name in the sorted array of struct
304    ctf_archive_modents.  */
305 static int
306 search_modent_by_name (const void *key, const void *ent)
307 {
308   const char *k = key;
309   const struct ctf_archive_modent *v = ent;
310
311   return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
312 }
313
314 /* A trivial wrapper: open a CTF archive, from data in a buffer (which the
315    caller must preserve until ctf_arc_close() time).  Returns the archive, or
316    NULL and an error in *err (if not NULL).  */
317 struct ctf_archive *
318 ctf_arc_bufopen (const void *buf, size_t size _libctf_unused_, int *errp)
319 {
320   struct ctf_archive *arc = (struct ctf_archive *) buf;
321
322   if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
323     {
324       if (errp)
325         *errp = ECTF_FMT;
326       return NULL;
327     }
328   return arc;
329 }
330
331 /* Open a CTF archive.  Returns the archive, or NULL and an error in *err (if
332    not NULL).  */
333 struct ctf_archive *
334 ctf_arc_open_internal (const char *filename, int *errp)
335 {
336   const char *errmsg;
337   int fd;
338   struct stat s;
339   struct ctf_archive *arc;              /* (Actually the whole file.)  */
340
341   libctf_init_debug();
342   if ((fd = open (filename, O_RDONLY)) < 0)
343     {
344       errmsg = "ctf_arc_open(): cannot open %s: %s\n";
345       goto err;
346     }
347   if (fstat (fd, &s) < 0)
348     {
349       errmsg = "ctf_arc_open(): cannot stat %s: %s\n";
350       goto err_close;
351     }
352
353   if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
354     {
355       errmsg = "ctf_arc_open(): Cannot read in %s: %s\n";
356       goto err_close;
357     }
358
359   if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
360     {
361       errmsg = "ctf_arc_open(): Invalid magic number";
362       errno = ECTF_FMT;
363       goto err_unmap;
364     }
365
366   /* This horrible hack lets us know how much to unmap when the file is
367      closed.  (We no longer need the magic number, and the mapping
368      is private.)  */
369   arc->ctfa_magic = s.st_size;
370   close (fd);
371   return arc;
372
373 err_unmap:
374   arc_mmap_unmap (arc, s.st_size, NULL);
375 err_close:
376   close (fd);
377 err:
378   if (errp)
379     *errp = errno;
380   ctf_dprintf (errmsg, filename, errno < ECTF_BASE ? strerror (errno) :
381                ctf_errmsg (errno));
382   return NULL;
383 }
384
385 /* Close an archive.  */
386 void
387 ctf_arc_close_internal (struct ctf_archive *arc)
388 {
389   if (arc == NULL)
390     return;
391
392   /* See the comment in ctf_arc_open().  */
393   arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
394 }
395
396 /* Public entry point: close an archive, or CTF file.  */
397 void
398 ctf_arc_close (ctf_archive_t *arc)
399 {
400   if (arc == NULL)
401     return;
402
403   if (arc->ctfi_is_archive)
404     ctf_arc_close_internal (arc->ctfi_archive);
405   else
406     ctf_file_close (arc->ctfi_file);
407   free ((void *) arc->ctfi_symsect.cts_data);
408   free ((void *) arc->ctfi_strsect.cts_data);
409   free (arc->ctfi_data);
410   free (arc);
411 }
412
413 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
414    non-NULL.  A name of NULL means to open the default file.  */
415 static ctf_file_t *
416 ctf_arc_open_by_name_internal (const struct ctf_archive *arc,
417                                const ctf_sect_t *symsect,
418                                const ctf_sect_t *strsect,
419                                const char *name, int *errp)
420 {
421   struct ctf_archive_modent *modent;
422
423   if (name == NULL)
424     name = _CTF_SECTION;                 /* The default name.  */
425
426   ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
427
428   modent = (ctf_archive_modent_t *) ((char *) arc
429                                      + sizeof (struct ctf_archive));
430
431   search_nametbl = (char *) arc + le64toh (arc->ctfa_names);
432   modent = bsearch (name, modent, le64toh (arc->ctfa_nfiles),
433                     sizeof (struct ctf_archive_modent),
434                     search_modent_by_name);
435
436   /* This is actually a common case and normal operation: no error
437      debug output.  */
438   if (modent == NULL)
439     {
440       if (errp)
441         *errp = ECTF_ARNNAME;
442       return NULL;
443     }
444
445   return ctf_arc_open_by_offset (arc, symsect, strsect,
446                                  le64toh (modent->ctf_offset), errp);
447 }
448
449 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
450    non-NULL.  A name of NULL means to open the default file.
451
452    Use the specified string and symbol table sections.
453
454    Public entry point.  */
455 ctf_file_t *
456 ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
457                                const ctf_sect_t *symsect,
458                                const ctf_sect_t *strsect,
459                                const char *name,
460                                int *errp)
461 {
462   if (arc->ctfi_is_archive)
463     {
464       ctf_file_t *ret;
465       ret = ctf_arc_open_by_name_internal (arc->ctfi_archive, symsect, strsect,
466                                            name, errp);
467       if (ret)
468         ret->ctf_archive = (ctf_archive_t *) arc;
469       return ret;
470     }
471
472   if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
473     {
474       if (errp)
475         *errp = ECTF_ARNNAME;
476       return NULL;
477     }
478   arc->ctfi_file->ctf_archive = (ctf_archive_t *) arc;
479
480   /* Bump the refcount so that the user can ctf_file_close() it.  */
481   arc->ctfi_file->ctf_refcnt++;
482   return arc->ctfi_file;
483 }
484
485 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
486    non-NULL.  A name of NULL means to open the default file.
487
488    Public entry point.  */
489 ctf_file_t *
490 ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name, int *errp)
491 {
492   const ctf_sect_t *symsect = &arc->ctfi_symsect;
493   const ctf_sect_t *strsect = &arc->ctfi_strsect;
494
495   if (symsect->cts_name == NULL)
496     symsect = NULL;
497   if (strsect->cts_name == NULL)
498     strsect = NULL;
499
500   return ctf_arc_open_by_name_sections (arc, symsect, strsect, name, errp);
501 }
502
503 /* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
504    none, setting 'err' if non-NULL.  */
505 static ctf_file_t *
506 ctf_arc_open_by_offset (const struct ctf_archive *arc,
507                         const ctf_sect_t *symsect,
508                         const ctf_sect_t *strsect, size_t offset,
509                         int *errp)
510 {
511   ctf_sect_t ctfsect;
512   ctf_file_t *fp;
513
514   ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
515
516   memset (&ctfsect, 0, sizeof (ctf_sect_t));
517
518   offset += le64toh (arc->ctfa_ctfs);
519
520   ctfsect.cts_name = _CTF_SECTION;
521   ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
522   ctfsect.cts_entsize = 1;
523   ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
524   fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
525   if (fp)
526     ctf_setmodel (fp, le64toh (arc->ctfa_model));
527   return fp;
528 }
529
530 /* Raw iteration over all CTF files in an archive.  We pass the raw data for all
531    CTF files in turn to the specified callback function.  */
532 static int
533 ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
534                                ctf_archive_raw_member_f *func, void *data)
535 {
536   int rc;
537   size_t i;
538   struct ctf_archive_modent *modent;
539   const char *nametbl;
540
541   modent = (ctf_archive_modent_t *) ((char *) arc
542                                      + sizeof (struct ctf_archive));
543   nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
544
545   for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
546     {
547       const char *name;
548       char *fp;
549
550       name = &nametbl[le64toh (modent[i].name_offset)];
551       fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
552             + le64toh (modent[i].ctf_offset));
553
554       if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
555                       le64toh (*((uint64_t *) fp)), data)) != 0)
556         return rc;
557     }
558   return 0;
559 }
560
561 /* Raw iteration over all CTF files in an archive: public entry point.
562
563    Returns -EINVAL if not supported for this sort of archive.  */
564 int
565 ctf_archive_raw_iter (const ctf_archive_t *arc,
566                       ctf_archive_raw_member_f * func, void *data)
567 {
568   if (arc->ctfi_is_archive)
569     return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
570
571   return -EINVAL;                        /* Not supported. */
572 }
573
574 /* Iterate over all CTF files in an archive.  We pass all CTF files in turn to
575    the specified callback function.  */
576 static int
577 ctf_archive_iter_internal (const ctf_archive_t *wrapper,
578                            const struct ctf_archive *arc,
579                            const ctf_sect_t *symsect,
580                            const ctf_sect_t *strsect,
581                            ctf_archive_member_f *func, void *data)
582 {
583   int rc;
584   size_t i;
585   ctf_file_t *f;
586   struct ctf_archive_modent *modent;
587   const char *nametbl;
588
589   modent = (ctf_archive_modent_t *) ((char *) arc
590                                      + sizeof (struct ctf_archive));
591   nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
592
593   for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
594     {
595       const char *name;
596
597       name = &nametbl[le64toh (modent[i].name_offset)];
598       if ((f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
599                                               name, &rc)) == NULL)
600         return rc;
601
602       f->ctf_archive = (ctf_archive_t *) wrapper;
603       if ((rc = func (f, name, data)) != 0)
604         {
605           ctf_file_close (f);
606           return rc;
607         }
608
609       ctf_file_close (f);
610     }
611   return 0;
612 }
613
614 /* Iterate over all CTF files in an archive: public entry point.  We pass all
615    CTF files in turn to the specified callback function.  */
616 int
617 ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
618                   void *data)
619 {
620   const ctf_sect_t *symsect = &arc->ctfi_symsect;
621   const ctf_sect_t *strsect = &arc->ctfi_strsect;
622
623   if (symsect->cts_name == NULL)
624     symsect = NULL;
625   if (strsect->cts_name == NULL)
626     strsect = NULL;
627
628   if (arc->ctfi_is_archive)
629     return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
630                                       func, data);
631
632   return func (arc->ctfi_file, _CTF_SECTION, data);
633 }
634
635 #ifdef HAVE_MMAP
636 /* Map the header in.  Only used on new, empty files.  */
637 static void *arc_mmap_header (int fd, size_t headersz)
638 {
639   void *hdr;
640   if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
641                    0)) == MAP_FAILED)
642     return NULL;
643   return hdr;
644 }
645
646 /* mmap() the whole file, for reading only.  (Map it writably, but privately: we
647    need to modify the region, but don't need anyone else to see the
648    modifications.)  */
649 static void *arc_mmap_file (int fd, size_t size)
650 {
651   void *arc;
652   if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
653                    fd, 0)) == MAP_FAILED)
654     return NULL;
655   return arc;
656 }
657
658 /* Persist the header to disk.  */
659 static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
660                               size_t headersz, const char **errmsg)
661 {
662     if (msync (header, headersz, MS_ASYNC) < 0)
663     {
664       if (errmsg)
665         *errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
666       return -1;
667     }
668     return 0;
669 }
670
671 /* Unmap the region.  */
672 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
673 {
674   if (munmap (header, headersz) < 0)
675     {
676       if (errmsg)
677         *errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
678       return -1;
679     }
680     return 0;
681 }
682 #else
683 /* Map the header in.  Only used on new, empty files.  */
684 static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
685 {
686   void *hdr;
687   if ((hdr = malloc (headersz)) == NULL)
688     return NULL;
689   return hdr;
690 }
691
692 /* Pull in the whole file, for reading only.  We assume the current file
693    position is at the start of the file.  */
694 static void *arc_mmap_file (int fd, size_t size)
695 {
696   char *data;
697
698   if ((data = malloc (size)) == NULL)
699     return NULL;
700
701   if (ctf_pread (fd, data, size, 0) < 0)
702     {
703       free (data);
704       return NULL;
705     }
706   return data;
707 }
708
709 /* Persist the header to disk.  */
710 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
711                               const char **errmsg)
712 {
713   ssize_t len;
714   size_t acc = 0;
715   char *data = (char *) header;
716   ssize_t count = headersz;
717
718   if ((lseek (fd, 0, SEEK_SET)) < 0)
719     {
720       if (errmsg)
721         *errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
722           "%s: %s\n";
723       return -1;
724     }
725
726   while (headersz > 0)
727     {
728       if ((len = write (fd, data, count)) < 0)
729         {
730           if (errmsg)
731             *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
732           return len;
733         }
734       if (len == EINTR)
735         continue;
736
737       acc += len;
738       if (len == 0)                             /* EOF.  */
739         break;
740
741       count -= len;
742       data += len;
743     }
744   return 0;
745 }
746
747 /* Unmap the region.  */
748 static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
749                            const char **errmsg _libctf_unused_)
750 {
751   free (header);
752   return 0;
753 }
754 #endif