ctf-open-bfd.c revision 1.1.1.2 1 1.1 christos /* Opening CTF files with BFD.
2 1.1.1.2 christos Copyright (C) 2019-2022 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 <stddef.h>
22 1.1 christos #include <assert.h>
23 1.1 christos #include <sys/types.h>
24 1.1 christos #include <sys/stat.h>
25 1.1 christos #include <errno.h>
26 1.1 christos #include <string.h>
27 1.1 christos #include <fcntl.h>
28 1.1.1.2 christos #include <unistd.h>
29 1.1 christos #include <elf.h>
30 1.1 christos #include <bfd.h>
31 1.1 christos #include "swap.h"
32 1.1 christos #include "ctf-endian.h"
33 1.1 christos
34 1.1 christos #include "elf-bfd.h"
35 1.1 christos
36 1.1 christos /* Free the BFD bits of a CTF file on ctf_arc_close(). */
37 1.1 christos
38 1.1 christos static void
39 1.1 christos ctf_bfdclose (struct ctf_archive_internal *arci)
40 1.1 christos {
41 1.1 christos if (arci->ctfi_abfd != NULL)
42 1.1 christos if (!bfd_close_all_done (arci->ctfi_abfd))
43 1.1.1.2 christos ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
44 1.1.1.2 christos bfd_errmsg (bfd_get_error ()));
45 1.1 christos }
46 1.1 christos
47 1.1 christos /* Open a CTF file given the specified BFD. */
48 1.1 christos
49 1.1 christos ctf_archive_t *
50 1.1 christos ctf_bfdopen (struct bfd *abfd, int *errp)
51 1.1 christos {
52 1.1 christos ctf_archive_t *arc;
53 1.1 christos asection *ctf_asect;
54 1.1 christos bfd_byte *contents;
55 1.1 christos ctf_sect_t ctfsect;
56 1.1 christos
57 1.1 christos libctf_init_debug();
58 1.1 christos
59 1.1 christos if ((ctf_asect = bfd_get_section_by_name (abfd, _CTF_SECTION)) == NULL)
60 1.1 christos {
61 1.1 christos return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
62 1.1 christos }
63 1.1 christos
64 1.1 christos if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents))
65 1.1 christos {
66 1.1.1.2 christos ctf_err_warn (NULL, 0, 0, _("ctf_bfdopen(): cannot malloc "
67 1.1.1.2 christos "CTF section: %s"),
68 1.1.1.2 christos bfd_errmsg (bfd_get_error ()));
69 1.1 christos return (ctf_set_open_errno (errp, ECTF_FMT));
70 1.1 christos }
71 1.1 christos
72 1.1 christos ctfsect.cts_name = _CTF_SECTION;
73 1.1 christos ctfsect.cts_entsize = 1;
74 1.1 christos ctfsect.cts_size = bfd_section_size (ctf_asect);
75 1.1 christos ctfsect.cts_data = contents;
76 1.1 christos
77 1.1 christos if ((arc = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL)
78 1.1 christos {
79 1.1.1.2 christos /* This frees the cts_data later. */
80 1.1 christos arc->ctfi_data = (void *) ctfsect.cts_data;
81 1.1 christos return arc;
82 1.1 christos }
83 1.1 christos
84 1.1 christos free (contents);
85 1.1 christos return NULL; /* errno is set for us. */
86 1.1 christos }
87 1.1 christos
88 1.1 christos /* Open a CTF file given the specified BFD and CTF section (which may contain a
89 1.1.1.2 christos CTF archive or a file). */
90 1.1 christos
91 1.1 christos ctf_archive_t *
92 1.1 christos ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
93 1.1 christos const ctf_sect_t *ctfsect, int *errp)
94 1.1 christos {
95 1.1 christos ctf_archive_t *arci;
96 1.1 christos ctf_sect_t *symsectp = NULL;
97 1.1 christos ctf_sect_t *strsectp = NULL;
98 1.1 christos const char *bfderrstr = NULL;
99 1.1.1.2 christos char *strtab_alloc = NULL;
100 1.1.1.2 christos int symsect_endianness = -1;
101 1.1.1.2 christos
102 1.1.1.2 christos libctf_init_debug();
103 1.1 christos
104 1.1 christos #ifdef HAVE_BFD_ELF
105 1.1 christos ctf_sect_t symsect, strsect;
106 1.1.1.2 christos Elf_Internal_Shdr *symhdr;
107 1.1.1.2 christos size_t symcount;
108 1.1 christos Elf_Internal_Sym *isymbuf;
109 1.1.1.2 christos bfd_byte *symtab = NULL;
110 1.1.1.2 christos const char *symtab_name;
111 1.1 christos const char *strtab = NULL;
112 1.1.1.2 christos const char *strtab_name;
113 1.1.1.2 christos size_t strsize;
114 1.1.1.2 christos const ctf_preamble_t *preamble;
115 1.1 christos
116 1.1.1.2 christos if (ctfsect->cts_data == NULL)
117 1.1 christos {
118 1.1.1.2 christos bfderrstr = N_("CTF section is NULL");
119 1.1 christos goto err;
120 1.1 christos }
121 1.1.1.2 christos preamble = ctf_arc_bufpreamble (ctfsect);
122 1.1 christos
123 1.1.1.2 christos if (preamble->ctp_flags & CTF_F_DYNSTR)
124 1.1.1.2 christos {
125 1.1.1.2 christos symhdr = &elf_tdata (abfd)->dynsymtab_hdr;
126 1.1.1.2 christos strtab_name = ".dynstr";
127 1.1.1.2 christos symtab_name = ".dynsym";
128 1.1.1.2 christos }
129 1.1.1.2 christos else
130 1.1 christos {
131 1.1.1.2 christos symhdr = &elf_tdata (abfd)->symtab_hdr;
132 1.1.1.2 christos strtab_name = ".strtab";
133 1.1.1.2 christos symtab_name = ".symtab";
134 1.1 christos }
135 1.1 christos
136 1.1.1.2 christos /* TODO: handle SYMTAB_SHNDX. */
137 1.1.1.2 christos
138 1.1.1.2 christos /* Get the symtab, and the strtab associated with it. */
139 1.1.1.2 christos if (elf_tdata (abfd) && symhdr && symhdr->sh_size && symhdr->sh_entsize)
140 1.1.1.2 christos {
141 1.1.1.2 christos symcount = symhdr->sh_size / symhdr->sh_entsize;
142 1.1.1.2 christos if ((symtab = malloc (symhdr->sh_size)) == NULL)
143 1.1.1.2 christos {
144 1.1.1.2 christos bfderrstr = N_("cannot malloc symbol table");
145 1.1.1.2 christos goto err;
146 1.1.1.2 christos }
147 1.1.1.2 christos
148 1.1.1.2 christos isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0,
149 1.1.1.2 christos NULL, symtab, NULL);
150 1.1.1.2 christos free (isymbuf);
151 1.1.1.2 christos if (isymbuf == NULL)
152 1.1.1.2 christos {
153 1.1.1.2 christos bfderrstr = N_("cannot read symbol table");
154 1.1.1.2 christos goto err_free_sym;
155 1.1.1.2 christos }
156 1.1.1.2 christos
157 1.1.1.2 christos if (elf_elfsections (abfd) != NULL
158 1.1.1.2 christos && symhdr->sh_link < elf_numsections (abfd))
159 1.1.1.2 christos {
160 1.1.1.2 christos Elf_Internal_Shdr *strhdr = elf_elfsections (abfd)[symhdr->sh_link];
161 1.1.1.2 christos
162 1.1.1.2 christos strsize = strhdr->sh_size;
163 1.1.1.2 christos if (strhdr->contents == NULL)
164 1.1.1.2 christos {
165 1.1.1.2 christos if ((strtab = bfd_elf_get_str_section (abfd, symhdr->sh_link)) == NULL)
166 1.1.1.2 christos {
167 1.1.1.2 christos bfderrstr = N_("cannot read string table");
168 1.1.1.2 christos goto err_free_sym;
169 1.1.1.2 christos }
170 1.1.1.2 christos }
171 1.1.1.2 christos else
172 1.1.1.2 christos strtab = (const char *) strhdr->contents;
173 1.1.1.2 christos }
174 1.1.1.2 christos }
175 1.1.1.2 christos else /* No symtab: just try getting .strtab or .dynstr by name. */
176 1.1 christos {
177 1.1.1.2 christos bfd_byte *str_bcontents;
178 1.1.1.2 christos asection *str_asect;
179 1.1.1.2 christos
180 1.1.1.2 christos if ((str_asect = bfd_get_section_by_name (abfd, strtab_name)) != NULL)
181 1.1 christos {
182 1.1.1.2 christos if (bfd_malloc_and_get_section (abfd, str_asect, &str_bcontents))
183 1.1 christos {
184 1.1.1.2 christos strtab = (const char *) str_bcontents;
185 1.1.1.2 christos strtab_alloc = (char *) str_bcontents;
186 1.1.1.2 christos strsize = str_asect->size;
187 1.1 christos }
188 1.1 christos }
189 1.1 christos }
190 1.1 christos
191 1.1 christos if (strtab)
192 1.1 christos {
193 1.1 christos /* The names here are more or less arbitrary, but there is no point
194 1.1 christos thrashing around digging the name out of the shstrtab given that we don't
195 1.1 christos use it for anything but debugging. */
196 1.1 christos
197 1.1 christos strsect.cts_data = strtab;
198 1.1.1.2 christos strsect.cts_name = strtab_name;
199 1.1.1.2 christos strsect.cts_size = strsize;
200 1.1 christos strsectp = &strsect;
201 1.1.1.2 christos }
202 1.1 christos
203 1.1.1.2 christos if (symtab)
204 1.1.1.2 christos {
205 1.1 christos assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym);
206 1.1.1.2 christos symsect.cts_name = symtab_name;
207 1.1 christos symsect.cts_entsize = symhdr->sh_entsize;
208 1.1 christos symsect.cts_size = symhdr->sh_size;
209 1.1 christos symsect.cts_data = symtab;
210 1.1 christos symsectp = &symsect;
211 1.1 christos }
212 1.1.1.2 christos
213 1.1.1.2 christos symsect_endianness = bfd_little_endian (abfd);
214 1.1 christos #endif
215 1.1 christos
216 1.1.1.2 christos arci = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp);
217 1.1.1.2 christos if (arci)
218 1.1 christos {
219 1.1.1.2 christos /* Request freeing of the symsect and possibly the strsect. */
220 1.1.1.2 christos arci->ctfi_free_symsect = 1;
221 1.1.1.2 christos if (strtab_alloc)
222 1.1.1.2 christos arci->ctfi_free_strsect = 1;
223 1.1.1.2 christos
224 1.1.1.2 christos /* Get the endianness right. */
225 1.1.1.2 christos if (symsect_endianness > -1)
226 1.1.1.2 christos ctf_arc_symsect_endianness (arci, symsect_endianness);
227 1.1.1.2 christos return arci;
228 1.1 christos }
229 1.1 christos #ifdef HAVE_BFD_ELF
230 1.1 christos err_free_sym:
231 1.1 christos free (symtab);
232 1.1.1.2 christos free (strtab_alloc);
233 1.1 christos #endif
234 1.1 christos err: _libctf_unused_;
235 1.1 christos if (bfderrstr)
236 1.1 christos {
237 1.1.1.2 christos ctf_err_warn (NULL, 0, 0, "ctf_bfdopen(): %s: %s", gettext (bfderrstr),
238 1.1 christos bfd_errmsg (bfd_get_error()));
239 1.1 christos ctf_set_open_errno (errp, ECTF_FMT);
240 1.1 christos }
241 1.1 christos return NULL;
242 1.1 christos }
243 1.1 christos
244 1.1 christos /* Open the specified file descriptor and return a pointer to a CTF archive that
245 1.1.1.2 christos contains one or more CTF dicts. The file can be an ELF file, a file
246 1.1.1.2 christos containing raw CTF, or a CTF archive. The caller is responsible for closing
247 1.1.1.2 christos the file descriptor when it is no longer needed. If this is an ELF file,
248 1.1.1.2 christos TARGET, if non-NULL, should be the name of a suitable BFD target. */
249 1.1 christos
250 1.1 christos ctf_archive_t *
251 1.1 christos ctf_fdopen (int fd, const char *filename, const char *target, int *errp)
252 1.1 christos {
253 1.1 christos ctf_archive_t *arci;
254 1.1 christos bfd *abfd;
255 1.1 christos int nfd;
256 1.1 christos
257 1.1 christos struct stat st;
258 1.1 christos ssize_t nbytes;
259 1.1 christos
260 1.1 christos ctf_preamble_t ctfhdr;
261 1.1 christos uint64_t arc_magic;
262 1.1 christos
263 1.1 christos memset (&ctfhdr, 0, sizeof (ctfhdr));
264 1.1 christos
265 1.1 christos libctf_init_debug();
266 1.1 christos
267 1.1 christos if (fstat (fd, &st) == -1)
268 1.1 christos return (ctf_set_open_errno (errp, errno));
269 1.1 christos
270 1.1 christos if ((nbytes = ctf_pread (fd, &ctfhdr, sizeof (ctfhdr), 0)) <= 0)
271 1.1 christos return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
272 1.1 christos
273 1.1 christos /* If we have read enough bytes to form a CTF header and the magic string
274 1.1 christos matches, in either endianness, attempt to interpret the file as raw
275 1.1 christos CTF. */
276 1.1 christos
277 1.1 christos if ((size_t) nbytes >= sizeof (ctf_preamble_t)
278 1.1 christos && (ctfhdr.ctp_magic == CTF_MAGIC
279 1.1 christos || ctfhdr.ctp_magic == bswap_16 (CTF_MAGIC)))
280 1.1 christos {
281 1.1.1.2 christos ctf_dict_t *fp = NULL;
282 1.1 christos void *data;
283 1.1 christos
284 1.1 christos if ((data = ctf_mmap (st.st_size, 0, fd)) == NULL)
285 1.1 christos return (ctf_set_open_errno (errp, errno));
286 1.1 christos
287 1.1 christos if ((fp = ctf_simple_open (data, (size_t) st.st_size, NULL, 0, 0,
288 1.1 christos NULL, 0, errp)) == NULL)
289 1.1 christos {
290 1.1 christos ctf_munmap (data, (size_t) st.st_size);
291 1.1 christos return NULL; /* errno is set for us. */
292 1.1 christos }
293 1.1 christos
294 1.1 christos fp->ctf_data_mmapped = data;
295 1.1 christos fp->ctf_data_mmapped_len = (size_t) st.st_size;
296 1.1 christos
297 1.1.1.2 christos return ctf_new_archive_internal (0, 1, NULL, fp, NULL, NULL, errp);
298 1.1 christos }
299 1.1 christos
300 1.1 christos if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0)
301 1.1 christos return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
302 1.1 christos
303 1.1 christos if ((size_t) nbytes >= sizeof (uint64_t) && le64toh (arc_magic) == CTFA_MAGIC)
304 1.1 christos {
305 1.1 christos struct ctf_archive *arc;
306 1.1 christos
307 1.1 christos if ((arc = ctf_arc_open_internal (filename, errp)) == NULL)
308 1.1 christos return NULL; /* errno is set for us. */
309 1.1 christos
310 1.1.1.2 christos return ctf_new_archive_internal (1, 1, arc, NULL, NULL, NULL, errp);
311 1.1 christos }
312 1.1 christos
313 1.1 christos /* Attempt to open the file with BFD. We must dup the fd first, since bfd
314 1.1 christos takes ownership of the passed fd. */
315 1.1 christos
316 1.1 christos if ((nfd = dup (fd)) < 0)
317 1.1 christos return (ctf_set_open_errno (errp, errno));
318 1.1 christos
319 1.1 christos if ((abfd = bfd_fdopenr (filename, target, nfd)) == NULL)
320 1.1 christos {
321 1.1.1.2 christos ctf_err_warn (NULL, 0, 0, _("cannot open BFD from %s: %s"),
322 1.1.1.2 christos filename ? filename : _("(unknown file)"),
323 1.1.1.2 christos bfd_errmsg (bfd_get_error ()));
324 1.1 christos return (ctf_set_open_errno (errp, ECTF_FMT));
325 1.1 christos }
326 1.1 christos bfd_set_cacheable (abfd, 1);
327 1.1 christos
328 1.1 christos if (!bfd_check_format (abfd, bfd_object))
329 1.1 christos {
330 1.1.1.2 christos ctf_err_warn (NULL, 0, 0, _("BFD format problem in %s: %s"),
331 1.1.1.2 christos filename ? filename : _("(unknown file)"),
332 1.1.1.2 christos bfd_errmsg (bfd_get_error ()));
333 1.1 christos if (bfd_get_error() == bfd_error_file_ambiguously_recognized)
334 1.1 christos return (ctf_set_open_errno (errp, ECTF_BFD_AMBIGUOUS));
335 1.1 christos else
336 1.1 christos return (ctf_set_open_errno (errp, ECTF_FMT));
337 1.1 christos }
338 1.1 christos
339 1.1 christos if ((arci = ctf_bfdopen (abfd, errp)) == NULL)
340 1.1 christos {
341 1.1 christos if (!bfd_close_all_done (abfd))
342 1.1.1.2 christos ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
343 1.1.1.2 christos bfd_errmsg (bfd_get_error ()));
344 1.1 christos return NULL; /* errno is set for us. */
345 1.1 christos }
346 1.1 christos arci->ctfi_bfd_close = ctf_bfdclose;
347 1.1 christos arci->ctfi_abfd = abfd;
348 1.1 christos
349 1.1 christos return arci;
350 1.1 christos }
351 1.1 christos
352 1.1.1.2 christos /* Open the specified file and return a pointer to a CTF dict. The file
353 1.1 christos can be either an ELF file or raw CTF file. This is just a convenient
354 1.1 christos wrapper around ctf_fdopen() for callers. */
355 1.1 christos
356 1.1 christos ctf_archive_t *
357 1.1 christos ctf_open (const char *filename, const char *target, int *errp)
358 1.1 christos {
359 1.1 christos ctf_archive_t *arc;
360 1.1 christos int fd;
361 1.1 christos
362 1.1 christos if ((fd = open (filename, O_RDONLY)) == -1)
363 1.1 christos {
364 1.1 christos if (errp != NULL)
365 1.1 christos *errp = errno;
366 1.1 christos return NULL;
367 1.1 christos }
368 1.1 christos
369 1.1 christos arc = ctf_fdopen (fd, filename, target, errp);
370 1.1 christos (void) close (fd);
371 1.1 christos return arc;
372 1.1 christos }
373 1.1 christos
374 1.1 christos /* Public entry point: open a CTF archive, or CTF file. Returns the archive, or
375 1.1 christos NULL and an error in *err. Despite the fact that this uses CTF archives, it
376 1.1 christos must be in this file to avoid dragging in BFD into non-BFD-using programs. */
377 1.1 christos ctf_archive_t *
378 1.1 christos ctf_arc_open (const char *filename, int *errp)
379 1.1 christos {
380 1.1 christos return ctf_open (filename, NULL, errp);
381 1.1 christos }
382