Home | History | Annotate | Line # | Download | only in libctf
      1      1.1  christos /* Opening CTF files with BFD.
      2  1.1.1.5  christos    Copyright (C) 2019-2026 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