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