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