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