xref: /netbsd-src/external/gpl3/gdb/dist/libctf/ctf-open-bfd.c (revision c9055873d0546e63388f027d3d7f85381cde0545)
18dffb485Schristos /* Opening CTF files with BFD.
2*c9055873Schristos    Copyright (C) 2019-2024 Free Software Foundation, Inc.
38dffb485Schristos 
48dffb485Schristos    This file is part of libctf.
58dffb485Schristos 
68dffb485Schristos    libctf is free software; you can redistribute it and/or modify it under
78dffb485Schristos    the terms of the GNU General Public License as published by the Free
88dffb485Schristos    Software Foundation; either version 3, or (at your option) any later
98dffb485Schristos    version.
108dffb485Schristos 
118dffb485Schristos    This program is distributed in the hope that it will be useful, but
128dffb485Schristos    WITHOUT ANY WARRANTY; without even the implied warranty of
138dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
148dffb485Schristos    See the GNU General Public License for more details.
158dffb485Schristos 
168dffb485Schristos    You should have received a copy of the GNU General Public License
178dffb485Schristos    along with this program; see the file COPYING.  If not see
188dffb485Schristos    <http://www.gnu.org/licenses/>.  */
198dffb485Schristos 
208dffb485Schristos #include <ctf-impl.h>
218dffb485Schristos #include <stddef.h>
228dffb485Schristos #include <assert.h>
238dffb485Schristos #include <sys/types.h>
248dffb485Schristos #include <sys/stat.h>
258dffb485Schristos #include <errno.h>
268dffb485Schristos #include <string.h>
278dffb485Schristos #include <fcntl.h>
288dffb485Schristos #include <unistd.h>
298dffb485Schristos #include <elf.h>
308dffb485Schristos #include <bfd.h>
318dffb485Schristos #include "swap.h"
328dffb485Schristos #include "ctf-endian.h"
338dffb485Schristos 
348dffb485Schristos #include "elf-bfd.h"
358dffb485Schristos 
368dffb485Schristos /* Free the BFD bits of a CTF file on ctf_arc_close().  */
378dffb485Schristos 
388dffb485Schristos static void
398dffb485Schristos ctf_bfdclose (struct ctf_archive_internal *arci)
408dffb485Schristos {
418dffb485Schristos   if (arci->ctfi_abfd != NULL)
428dffb485Schristos     if (!bfd_close_all_done (arci->ctfi_abfd))
438dffb485Schristos       ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
448dffb485Schristos 		    bfd_errmsg (bfd_get_error ()));
458dffb485Schristos }
468dffb485Schristos 
478dffb485Schristos /* Open a CTF file given the specified BFD.  */
488dffb485Schristos 
498dffb485Schristos ctf_archive_t *
508dffb485Schristos ctf_bfdopen (struct bfd *abfd, int *errp)
518dffb485Schristos {
528dffb485Schristos   ctf_archive_t *arc;
538dffb485Schristos   asection *ctf_asect;
548dffb485Schristos   bfd_byte *contents;
558dffb485Schristos   ctf_sect_t ctfsect;
568dffb485Schristos 
578dffb485Schristos   libctf_init_debug();
588dffb485Schristos 
598dffb485Schristos   if ((ctf_asect = bfd_get_section_by_name (abfd, _CTF_SECTION)) == NULL)
608dffb485Schristos     {
618dffb485Schristos       return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
628dffb485Schristos     }
638dffb485Schristos 
648dffb485Schristos   if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents))
658dffb485Schristos     {
668dffb485Schristos       ctf_err_warn (NULL, 0, 0, _("ctf_bfdopen(): cannot malloc "
678dffb485Schristos 				  "CTF section: %s"),
688dffb485Schristos 		    bfd_errmsg (bfd_get_error ()));
698dffb485Schristos       return (ctf_set_open_errno (errp, ECTF_FMT));
708dffb485Schristos     }
718dffb485Schristos 
728dffb485Schristos   ctfsect.cts_name = _CTF_SECTION;
738dffb485Schristos   ctfsect.cts_entsize = 1;
748dffb485Schristos   ctfsect.cts_size = bfd_section_size (ctf_asect);
758dffb485Schristos   ctfsect.cts_data = contents;
768dffb485Schristos 
778dffb485Schristos   if ((arc = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL)
788dffb485Schristos     {
798dffb485Schristos       /* This frees the cts_data later.  */
808dffb485Schristos       arc->ctfi_data = (void *) ctfsect.cts_data;
818dffb485Schristos       return arc;
828dffb485Schristos     }
838dffb485Schristos 
848dffb485Schristos   free (contents);
858dffb485Schristos   return NULL;				/* errno is set for us.  */
868dffb485Schristos }
878dffb485Schristos 
888dffb485Schristos /* Open a CTF file given the specified BFD and CTF section (which may contain a
898dffb485Schristos    CTF archive or a file).  */
908dffb485Schristos 
918dffb485Schristos ctf_archive_t *
928dffb485Schristos ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
938dffb485Schristos 		     const ctf_sect_t *ctfsect, int *errp)
948dffb485Schristos {
958dffb485Schristos   ctf_archive_t *arci;
968dffb485Schristos   ctf_sect_t *symsectp = NULL;
978dffb485Schristos   ctf_sect_t *strsectp = NULL;
988dffb485Schristos   const char *bfderrstr = NULL;
998dffb485Schristos   char *strtab_alloc = NULL;
1004b169a6bSchristos   int symsect_endianness = -1;
1014b169a6bSchristos 
1024b169a6bSchristos   libctf_init_debug();
1038dffb485Schristos 
1048dffb485Schristos #ifdef HAVE_BFD_ELF
1058dffb485Schristos   ctf_sect_t symsect, strsect;
1064b169a6bSchristos   Elf_Internal_Shdr *symhdr;
1078dffb485Schristos   size_t symcount;
1088dffb485Schristos   Elf_Internal_Sym *isymbuf;
1098dffb485Schristos   bfd_byte *symtab = NULL;
1104b169a6bSchristos   const char *symtab_name;
1118dffb485Schristos   const char *strtab = NULL;
1124b169a6bSchristos   const char *strtab_name;
1138dffb485Schristos   size_t strsize;
1144b169a6bSchristos   const ctf_preamble_t *preamble;
1154b169a6bSchristos 
1164b169a6bSchristos   if (ctfsect->cts_data == NULL)
1174b169a6bSchristos     {
1184b169a6bSchristos       bfderrstr = N_("CTF section is NULL");
1194b169a6bSchristos       goto err;
1204b169a6bSchristos     }
1214b169a6bSchristos   preamble = ctf_arc_bufpreamble (ctfsect);
1224b169a6bSchristos 
1234b169a6bSchristos   if (preamble->ctp_flags & CTF_F_DYNSTR)
1244b169a6bSchristos     {
1254b169a6bSchristos       symhdr = &elf_tdata (abfd)->dynsymtab_hdr;
1264b169a6bSchristos       strtab_name = ".dynstr";
1274b169a6bSchristos       symtab_name = ".dynsym";
1284b169a6bSchristos     }
1294b169a6bSchristos   else
1304b169a6bSchristos     {
1314b169a6bSchristos       symhdr = &elf_tdata (abfd)->symtab_hdr;
1324b169a6bSchristos       strtab_name = ".strtab";
1334b169a6bSchristos       symtab_name = ".symtab";
1344b169a6bSchristos     }
1354b169a6bSchristos 
1368dffb485Schristos   /* TODO: handle SYMTAB_SHNDX.  */
1378dffb485Schristos 
1388dffb485Schristos   /* Get the symtab, and the strtab associated with it.  */
1398dffb485Schristos   if (elf_tdata (abfd) && symhdr && symhdr->sh_size && symhdr->sh_entsize)
1408dffb485Schristos     {
1418dffb485Schristos       symcount = symhdr->sh_size / symhdr->sh_entsize;
1428dffb485Schristos       if ((symtab = malloc (symhdr->sh_size)) == NULL)
1438dffb485Schristos 	{
1448dffb485Schristos 	  bfderrstr = N_("cannot malloc symbol table");
1458dffb485Schristos 	  goto err;
1468dffb485Schristos 	}
1478dffb485Schristos 
1488dffb485Schristos       isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0,
1498dffb485Schristos 				      NULL, symtab, NULL);
1508dffb485Schristos       free (isymbuf);
1518dffb485Schristos       if (isymbuf == NULL)
1528dffb485Schristos 	{
1538dffb485Schristos 	  bfderrstr = N_("cannot read symbol table");
1548dffb485Schristos 	  goto err_free_sym;
1558dffb485Schristos 	}
1568dffb485Schristos 
1578dffb485Schristos       if (elf_elfsections (abfd) != NULL
1588dffb485Schristos 	  && symhdr->sh_link < elf_numsections (abfd))
1598dffb485Schristos 	{
1608dffb485Schristos 	  Elf_Internal_Shdr *strhdr = elf_elfsections (abfd)[symhdr->sh_link];
1618dffb485Schristos 
1628dffb485Schristos 	  strsize = strhdr->sh_size;
1638dffb485Schristos 	  if (strhdr->contents == NULL)
1648dffb485Schristos 	    {
1658dffb485Schristos 	      if ((strtab = bfd_elf_get_str_section (abfd, symhdr->sh_link)) == NULL)
1668dffb485Schristos 		{
1678dffb485Schristos 		  bfderrstr = N_("cannot read string table");
1688dffb485Schristos 		  goto err_free_sym;
1698dffb485Schristos 		}
1708dffb485Schristos 	    }
1718dffb485Schristos 	  else
1728dffb485Schristos 	    strtab = (const char *) strhdr->contents;
1738dffb485Schristos 	}
1748dffb485Schristos     }
1754b169a6bSchristos   else		/* No symtab: just try getting .strtab or .dynstr by name.  */
1768dffb485Schristos     {
1778dffb485Schristos       bfd_byte *str_bcontents;
1788dffb485Schristos       asection *str_asect;
1798dffb485Schristos 
1804b169a6bSchristos       if ((str_asect = bfd_get_section_by_name (abfd, strtab_name)) != NULL)
1818dffb485Schristos 	{
1828dffb485Schristos 	  if (bfd_malloc_and_get_section (abfd, str_asect, &str_bcontents))
1838dffb485Schristos 	    {
1848dffb485Schristos 	      strtab = (const char *) str_bcontents;
1858dffb485Schristos 	      strtab_alloc = (char *) str_bcontents;
1868dffb485Schristos 	      strsize = str_asect->size;
1878dffb485Schristos 	    }
1888dffb485Schristos 	}
1898dffb485Schristos     }
1908dffb485Schristos 
1918dffb485Schristos   if (strtab)
1928dffb485Schristos     {
1938dffb485Schristos       /* The names here are more or less arbitrary, but there is no point
1948dffb485Schristos 	 thrashing around digging the name out of the shstrtab given that we don't
1958dffb485Schristos 	 use it for anything but debugging.  */
1968dffb485Schristos 
1978dffb485Schristos       strsect.cts_data = strtab;
1984b169a6bSchristos       strsect.cts_name = strtab_name;
1998dffb485Schristos       strsect.cts_size = strsize;
2008dffb485Schristos       strsectp = &strsect;
2018dffb485Schristos     }
2028dffb485Schristos 
2038dffb485Schristos   if (symtab)
2048dffb485Schristos     {
2058dffb485Schristos       assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym);
2064b169a6bSchristos       symsect.cts_name = symtab_name;
2078dffb485Schristos       symsect.cts_entsize = symhdr->sh_entsize;
2088dffb485Schristos       symsect.cts_size = symhdr->sh_size;
2098dffb485Schristos       symsect.cts_data = symtab;
2108dffb485Schristos       symsectp = &symsect;
2118dffb485Schristos     }
2124b169a6bSchristos 
2134b169a6bSchristos   symsect_endianness = bfd_little_endian (abfd);
2148dffb485Schristos #endif
2158dffb485Schristos 
2168dffb485Schristos   arci = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp);
2178dffb485Schristos   if (arci)
2188dffb485Schristos     {
2198dffb485Schristos       /* Request freeing of the symsect and possibly the strsect.  */
2208dffb485Schristos       arci->ctfi_free_symsect = 1;
2218dffb485Schristos       if (strtab_alloc)
2228dffb485Schristos 	arci->ctfi_free_strsect = 1;
2234b169a6bSchristos 
2244b169a6bSchristos       /* Get the endianness right.  */
2254b169a6bSchristos       if (symsect_endianness > -1)
2264b169a6bSchristos 	ctf_arc_symsect_endianness (arci, symsect_endianness);
2278dffb485Schristos       return arci;
2288dffb485Schristos     }
2298dffb485Schristos #ifdef HAVE_BFD_ELF
2308dffb485Schristos  err_free_sym:
2318dffb485Schristos   free (symtab);
2328dffb485Schristos   free (strtab_alloc);
2338dffb485Schristos #endif
2348dffb485Schristos err: _libctf_unused_;
2358dffb485Schristos   if (bfderrstr)
2368dffb485Schristos     {
2378dffb485Schristos       ctf_err_warn (NULL, 0, 0, "ctf_bfdopen(): %s: %s", gettext (bfderrstr),
2388dffb485Schristos 		   bfd_errmsg (bfd_get_error()));
2398dffb485Schristos       ctf_set_open_errno (errp, ECTF_FMT);
2408dffb485Schristos     }
2418dffb485Schristos   return NULL;
2428dffb485Schristos }
2438dffb485Schristos 
2448dffb485Schristos /* Open the specified file descriptor and return a pointer to a CTF archive that
2454b169a6bSchristos    contains one or more CTF dicts.  The file can be an ELF file, a file
2464b169a6bSchristos    containing raw CTF, or a CTF archive.  The caller is responsible for closing
2474b169a6bSchristos    the file descriptor when it is no longer needed.  If this is an ELF file,
2484b169a6bSchristos    TARGET, if non-NULL, should be the name of a suitable BFD target.  */
2498dffb485Schristos 
2508dffb485Schristos ctf_archive_t *
2518dffb485Schristos ctf_fdopen (int fd, const char *filename, const char *target, int *errp)
2528dffb485Schristos {
2538dffb485Schristos   ctf_archive_t *arci;
2548dffb485Schristos   bfd *abfd;
2558dffb485Schristos   int nfd;
2568dffb485Schristos 
2578dffb485Schristos   struct stat st;
2588dffb485Schristos   ssize_t nbytes;
2598dffb485Schristos 
2608dffb485Schristos   ctf_preamble_t ctfhdr;
2618dffb485Schristos   uint64_t arc_magic;
2628dffb485Schristos 
2638dffb485Schristos   memset (&ctfhdr, 0, sizeof (ctfhdr));
2648dffb485Schristos 
2658dffb485Schristos   libctf_init_debug();
2668dffb485Schristos 
2678dffb485Schristos   if (fstat (fd, &st) == -1)
2688dffb485Schristos     return (ctf_set_open_errno (errp, errno));
2698dffb485Schristos 
2708dffb485Schristos   if ((nbytes = ctf_pread (fd, &ctfhdr, sizeof (ctfhdr), 0)) <= 0)
2718dffb485Schristos     return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
2728dffb485Schristos 
2738dffb485Schristos   /* If we have read enough bytes to form a CTF header and the magic string
2748dffb485Schristos      matches, in either endianness, attempt to interpret the file as raw
2758dffb485Schristos      CTF.  */
2768dffb485Schristos 
2778dffb485Schristos   if ((size_t) nbytes >= sizeof (ctf_preamble_t)
2788dffb485Schristos       && (ctfhdr.ctp_magic == CTF_MAGIC
2798dffb485Schristos 	  || ctfhdr.ctp_magic == bswap_16 (CTF_MAGIC)))
2808dffb485Schristos     {
2814b169a6bSchristos       ctf_dict_t *fp = NULL;
2828dffb485Schristos       void *data;
2838dffb485Schristos 
2848dffb485Schristos       if ((data = ctf_mmap (st.st_size, 0, fd)) == NULL)
2858dffb485Schristos 	return (ctf_set_open_errno (errp, errno));
2868dffb485Schristos 
2878dffb485Schristos       if ((fp = ctf_simple_open (data, (size_t) st.st_size, NULL, 0, 0,
2888dffb485Schristos 				 NULL, 0, errp)) == NULL)
2898dffb485Schristos 	{
2908dffb485Schristos 	  ctf_munmap (data, (size_t) st.st_size);
2918dffb485Schristos 	  return NULL;			/* errno is set for us.  */
2928dffb485Schristos 	}
2938dffb485Schristos 
2948dffb485Schristos       fp->ctf_data_mmapped = data;
2958dffb485Schristos       fp->ctf_data_mmapped_len = (size_t) st.st_size;
2968dffb485Schristos 
2978dffb485Schristos       return ctf_new_archive_internal (0, 1, NULL, fp, NULL, NULL, errp);
2988dffb485Schristos     }
2998dffb485Schristos 
3008dffb485Schristos   if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0)
3018dffb485Schristos     return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
3028dffb485Schristos 
3038dffb485Schristos   if ((size_t) nbytes >= sizeof (uint64_t) && le64toh (arc_magic) == CTFA_MAGIC)
3048dffb485Schristos     {
3058dffb485Schristos       struct ctf_archive *arc;
3068dffb485Schristos 
3078dffb485Schristos       if ((arc = ctf_arc_open_internal (filename, errp)) == NULL)
3088dffb485Schristos 	return NULL;			/* errno is set for us.  */
3098dffb485Schristos 
3108dffb485Schristos       return ctf_new_archive_internal (1, 1, arc, NULL, NULL, NULL, errp);
3118dffb485Schristos     }
3128dffb485Schristos 
3138dffb485Schristos   /* Attempt to open the file with BFD.  We must dup the fd first, since bfd
3148dffb485Schristos      takes ownership of the passed fd.  */
3158dffb485Schristos 
3168dffb485Schristos   if ((nfd = dup (fd)) < 0)
3178dffb485Schristos       return (ctf_set_open_errno (errp, errno));
3188dffb485Schristos 
3198dffb485Schristos   if ((abfd = bfd_fdopenr (filename, target, nfd)) == NULL)
3208dffb485Schristos     {
3218dffb485Schristos       ctf_err_warn (NULL, 0, 0, _("cannot open BFD from %s: %s"),
3228dffb485Schristos 		    filename ? filename : _("(unknown file)"),
3238dffb485Schristos 		    bfd_errmsg (bfd_get_error ()));
3248dffb485Schristos       return (ctf_set_open_errno (errp, ECTF_FMT));
3258dffb485Schristos     }
3268dffb485Schristos   bfd_set_cacheable (abfd, 1);
3278dffb485Schristos 
3288dffb485Schristos   if (!bfd_check_format (abfd, bfd_object))
3298dffb485Schristos     {
3308dffb485Schristos       ctf_err_warn (NULL, 0, 0, _("BFD format problem in %s: %s"),
3318dffb485Schristos 		    filename ? filename : _("(unknown file)"),
3328dffb485Schristos 		    bfd_errmsg (bfd_get_error ()));
3338dffb485Schristos       if (bfd_get_error() == bfd_error_file_ambiguously_recognized)
3348dffb485Schristos 	return (ctf_set_open_errno (errp, ECTF_BFD_AMBIGUOUS));
3358dffb485Schristos       else
3368dffb485Schristos 	return (ctf_set_open_errno (errp, ECTF_FMT));
3378dffb485Schristos     }
3388dffb485Schristos 
3398dffb485Schristos   if ((arci = ctf_bfdopen (abfd, errp)) == NULL)
3408dffb485Schristos     {
3418dffb485Schristos       if (!bfd_close_all_done (abfd))
3428dffb485Schristos 	ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
3438dffb485Schristos 		      bfd_errmsg (bfd_get_error ()));
3448dffb485Schristos       return NULL;			/* errno is set for us.  */
3458dffb485Schristos     }
3468dffb485Schristos   arci->ctfi_bfd_close = ctf_bfdclose;
3478dffb485Schristos   arci->ctfi_abfd = abfd;
3488dffb485Schristos 
3498dffb485Schristos   return arci;
3508dffb485Schristos }
3518dffb485Schristos 
3524b169a6bSchristos /* Open the specified file and return a pointer to a CTF dict.  The file
3538dffb485Schristos    can be either an ELF file or raw CTF file.  This is just a convenient
3548dffb485Schristos    wrapper around ctf_fdopen() for callers.  */
3558dffb485Schristos 
3568dffb485Schristos ctf_archive_t *
3578dffb485Schristos ctf_open (const char *filename, const char *target, int *errp)
3588dffb485Schristos {
3598dffb485Schristos   ctf_archive_t *arc;
3608dffb485Schristos   int fd;
3618dffb485Schristos 
3628dffb485Schristos   if ((fd = open (filename, O_RDONLY)) == -1)
3638dffb485Schristos     {
3648dffb485Schristos       if (errp != NULL)
3658dffb485Schristos 	*errp = errno;
3668dffb485Schristos       return NULL;
3678dffb485Schristos     }
3688dffb485Schristos 
3698dffb485Schristos   arc = ctf_fdopen (fd, filename, target, errp);
3708dffb485Schristos   (void) close (fd);
3718dffb485Schristos   return arc;
3728dffb485Schristos }
3738dffb485Schristos 
3748dffb485Schristos /* Public entry point: open a CTF archive, or CTF file.  Returns the archive, or
3758dffb485Schristos    NULL and an error in *err.  Despite the fact that this uses CTF archives, it
3768dffb485Schristos    must be in this file to avoid dragging in BFD into non-BFD-using programs.  */
3778dffb485Schristos ctf_archive_t *
3788dffb485Schristos ctf_arc_open (const char *filename, int *errp)
3798dffb485Schristos {
3808dffb485Schristos   return ctf_open (filename, NULL, errp);
3818dffb485Schristos }
382