Coverage Report

Created: 2025-06-24 06:45

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