Home | History | Annotate | Line # | Download | only in libctf
ctf-open-bfd.c revision 1.1.1.4
      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 {
     41   if (arci->ctfi_abfd != NULL)
     42     if (!bfd_close_all_done (arci->ctfi_abfd))
     43       ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
     44 		    bfd_errmsg (bfd_get_error ()));
     45 }
     46 
     47 /* Open a CTF file given the specified BFD.  */
     48 
     49 ctf_archive_t *
     50 ctf_bfdopen (struct bfd *abfd, int *errp)
     51 {
     52   ctf_archive_t *arc;
     53   asection *ctf_asect;
     54   bfd_byte *contents;
     55   ctf_sect_t ctfsect;
     56 
     57   libctf_init_debug();
     58 
     59   if ((ctf_asect = bfd_get_section_by_name (abfd, _CTF_SECTION)) == NULL)
     60     {
     61       return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
     62     }
     63 
     64   if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents))
     65     {
     66       ctf_err_warn (NULL, 0, 0, _("ctf_bfdopen(): cannot malloc "
     67 				  "CTF section: %s"),
     68 		    bfd_errmsg (bfd_get_error ()));
     69       return (ctf_set_open_errno (errp, ECTF_FMT));
     70     }
     71 
     72   ctfsect.cts_name = _CTF_SECTION;
     73   ctfsect.cts_entsize = 1;
     74   ctfsect.cts_size = bfd_section_size (ctf_asect);
     75   ctfsect.cts_data = contents;
     76 
     77   if ((arc = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL)
     78     {
     79       /* This frees the cts_data later.  */
     80       arc->ctfi_data = (void *) ctfsect.cts_data;
     81       return arc;
     82     }
     83 
     84   free (contents);
     85   return NULL;				/* errno is set for us.  */
     86 }
     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 {
     95   ctf_archive_t *arci;
     96   ctf_sect_t *symsectp = NULL;
     97   ctf_sect_t *strsectp = NULL;
     98   const char *bfderrstr = NULL;
     99   char *strtab_alloc = NULL;
    100   int symsect_endianness = -1;
    101 
    102   libctf_init_debug();
    103 
    104 #ifdef HAVE_BFD_ELF
    105   ctf_sect_t symsect, strsect;
    106   Elf_Internal_Shdr *symhdr;
    107   size_t symcount;
    108   Elf_Internal_Sym *isymbuf;
    109   bfd_byte *symtab = NULL;
    110   const char *symtab_name;
    111   const char *strtab = NULL;
    112   const char *strtab_name;
    113   size_t strsize;
    114   const ctf_preamble_t *preamble;
    115 
    116   if (ctfsect->cts_data == NULL)
    117     {
    118       bfderrstr = N_("CTF section is NULL");
    119       goto err;
    120     }
    121   preamble = ctf_arc_bufpreamble (ctfsect);
    122 
    123   if (preamble->ctp_flags & CTF_F_DYNSTR)
    124     {
    125       symhdr = &elf_tdata (abfd)->dynsymtab_hdr;
    126       strtab_name = ".dynstr";
    127       symtab_name = ".dynsym";
    128     }
    129   else
    130     {
    131       symhdr = &elf_tdata (abfd)->symtab_hdr;
    132       strtab_name = ".strtab";
    133       symtab_name = ".symtab";
    134     }
    135 
    136   /* TODO: handle SYMTAB_SHNDX.  */
    137 
    138   /* Get the symtab, and the strtab associated with it.  */
    139   if (elf_tdata (abfd) && symhdr && symhdr->sh_size && symhdr->sh_entsize)
    140     {
    141       symcount = symhdr->sh_size / symhdr->sh_entsize;
    142       if ((symtab = malloc (symhdr->sh_size)) == NULL)
    143 	{
    144 	  bfderrstr = N_("cannot malloc symbol table");
    145 	  goto err;
    146 	}
    147 
    148       isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0,
    149 				      NULL, symtab, NULL);
    150       free (isymbuf);
    151       if (isymbuf == NULL)
    152 	{
    153 	  bfderrstr = N_("cannot read symbol table");
    154 	  goto err_free_sym;
    155 	}
    156 
    157       if (elf_elfsections (abfd) != NULL
    158 	  && symhdr->sh_link < elf_numsections (abfd))
    159 	{
    160 	  Elf_Internal_Shdr *strhdr = elf_elfsections (abfd)[symhdr->sh_link];
    161 
    162 	  strsize = strhdr->sh_size;
    163 	  if (strhdr->contents == NULL)
    164 	    {
    165 	      if ((strtab = bfd_elf_get_str_section (abfd, symhdr->sh_link)) == NULL)
    166 		{
    167 		  bfderrstr = N_("cannot read string table");
    168 		  goto err_free_sym;
    169 		}
    170 	    }
    171 	  else
    172 	    strtab = (const char *) strhdr->contents;
    173 	}
    174     }
    175   else		/* No symtab: just try getting .strtab or .dynstr by name.  */
    176     {
    177       bfd_byte *str_bcontents;
    178       asection *str_asect;
    179 
    180       if ((str_asect = bfd_get_section_by_name (abfd, strtab_name)) != NULL)
    181 	{
    182 	  if (bfd_malloc_and_get_section (abfd, str_asect, &str_bcontents))
    183 	    {
    184 	      strtab = (const char *) str_bcontents;
    185 	      strtab_alloc = (char *) str_bcontents;
    186 	      strsize = str_asect->size;
    187 	    }
    188 	}
    189     }
    190 
    191   if (strtab)
    192     {
    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       strsect.cts_data = strtab;
    198       strsect.cts_name = strtab_name;
    199       strsect.cts_size = strsize;
    200       strsectp = &strsect;
    201     }
    202 
    203   if (symtab)
    204     {
    205       assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym);
    206       symsect.cts_name = symtab_name;
    207       symsect.cts_entsize = symhdr->sh_entsize;
    208       symsect.cts_size = symhdr->sh_size;
    209       symsect.cts_data = symtab;
    210       symsectp = &symsect;
    211     }
    212 
    213   symsect_endianness = bfd_little_endian (abfd);
    214 #endif
    215 
    216   arci = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp);
    217   if (arci)
    218     {
    219       /* Request freeing of the symsect and possibly the strsect.  */
    220       arci->ctfi_free_symsect = 1;
    221       if (strtab_alloc)
    222 	arci->ctfi_free_strsect = 1;
    223 
    224       /* Get the endianness right.  */
    225       if (symsect_endianness > -1)
    226 	ctf_arc_symsect_endianness (arci, symsect_endianness);
    227       return arci;
    228     }
    229 #ifdef HAVE_BFD_ELF
    230  err_free_sym:
    231   free (symtab);
    232   free (strtab_alloc);
    233 #endif
    234 err: _libctf_unused_;
    235   if (bfderrstr)
    236     {
    237       ctf_err_warn (NULL, 0, 0, "ctf_bfdopen(): %s: %s", gettext (bfderrstr),
    238 		   bfd_errmsg (bfd_get_error()));
    239       ctf_set_open_errno (errp, ECTF_FMT);
    240     }
    241   return NULL;
    242 }
    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 {
    253   ctf_archive_t *arci;
    254   bfd *abfd;
    255   int nfd;
    256 
    257   struct stat st;
    258   ssize_t nbytes;
    259 
    260   ctf_preamble_t ctfhdr;
    261   uint64_t arc_magic;
    262 
    263   memset (&ctfhdr, 0, sizeof (ctfhdr));
    264 
    265   libctf_init_debug();
    266 
    267   if (fstat (fd, &st) == -1)
    268     return (ctf_set_open_errno (errp, errno));
    269 
    270   if ((nbytes = ctf_pread (fd, &ctfhdr, sizeof (ctfhdr), 0)) <= 0)
    271     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   if ((size_t) nbytes >= sizeof (ctf_preamble_t)
    278       && (ctfhdr.ctp_magic == CTF_MAGIC
    279 	  || ctfhdr.ctp_magic == bswap_16 (CTF_MAGIC)))
    280     {
    281       ctf_dict_t *fp = NULL;
    282       void *data;
    283 
    284       if ((data = ctf_mmap (st.st_size, 0, fd)) == NULL)
    285 	return (ctf_set_open_errno (errp, errno));
    286 
    287       if ((fp = ctf_simple_open (data, (size_t) st.st_size, NULL, 0, 0,
    288 				 NULL, 0, errp)) == NULL)
    289 	{
    290 	  ctf_munmap (data, (size_t) st.st_size);
    291 	  return NULL;			/* errno is set for us.  */
    292 	}
    293 
    294       fp->ctf_data_mmapped = data;
    295       fp->ctf_data_mmapped_len = (size_t) st.st_size;
    296 
    297       return ctf_new_archive_internal (0, 1, NULL, fp, NULL, NULL, errp);
    298     }
    299 
    300   if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0)
    301     return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
    302 
    303   if ((size_t) nbytes >= sizeof (uint64_t) && le64toh (arc_magic) == CTFA_MAGIC)
    304     {
    305       struct ctf_archive *arc;
    306 
    307       if ((arc = ctf_arc_open_internal (filename, errp)) == NULL)
    308 	return NULL;			/* errno is set for us.  */
    309 
    310       return ctf_new_archive_internal (1, 1, arc, NULL, NULL, NULL, errp);
    311     }
    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   if ((nfd = dup (fd)) < 0)
    317       return (ctf_set_open_errno (errp, errno));
    318 
    319   if ((abfd = bfd_fdopenr (filename, target, nfd)) == NULL)
    320     {
    321       ctf_err_warn (NULL, 0, 0, _("cannot open BFD from %s: %s"),
    322 		    filename ? filename : _("(unknown file)"),
    323 		    bfd_errmsg (bfd_get_error ()));
    324       return (ctf_set_open_errno (errp, ECTF_FMT));
    325     }
    326   bfd_set_cacheable (abfd, 1);
    327 
    328   if (!bfd_check_format (abfd, bfd_object))
    329     {
    330       ctf_err_warn (NULL, 0, 0, _("BFD format problem in %s: %s"),
    331 		    filename ? filename : _("(unknown file)"),
    332 		    bfd_errmsg (bfd_get_error ()));
    333       if (bfd_get_error() == bfd_error_file_ambiguously_recognized)
    334 	return (ctf_set_open_errno (errp, ECTF_BFD_AMBIGUOUS));
    335       else
    336 	return (ctf_set_open_errno (errp, ECTF_FMT));
    337     }
    338 
    339   if ((arci = ctf_bfdopen (abfd, errp)) == NULL)
    340     {
    341       if (!bfd_close_all_done (abfd))
    342 	ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
    343 		      bfd_errmsg (bfd_get_error ()));
    344       return NULL;			/* errno is set for us.  */
    345     }
    346   arci->ctfi_bfd_close = ctf_bfdclose;
    347   arci->ctfi_abfd = abfd;
    348 
    349   return arci;
    350 }
    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 {
    359   ctf_archive_t *arc;
    360   int fd;
    361 
    362   if ((fd = open (filename, O_RDONLY)) == -1)
    363     {
    364       if (errp != NULL)
    365 	*errp = errno;
    366       return NULL;
    367     }
    368 
    369   arc = ctf_fdopen (fd, filename, target, errp);
    370   (void) close (fd);
    371   return arc;
    372 }
    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 {
    380   return ctf_open (filename, NULL, errp);
    381 }
    382