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