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