binutils-gdb/libctf/ctf-open-bfd.c
Nick Alcock 139633c307 libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t
The naming of the ctf_file_t type in libctf is a historical curiosity.
Back in the Solaris days, CTF dictionaries were originally generated as
a separate file and then (sometimes) merged into objects: hence the
datatype was named ctf_file_t, and known as a "CTF file".  Nowadays, raw
CTF is essentially never written to a file on its own, and the datatype
changed name to a "CTF dictionary" years ago.  So the term "CTF file"
refers to something that is never a file!  This is at best confusing.

The type has also historically been known as a 'CTF container", which is
even more confusing now that we have CTF archives which are *also* a
sort of container (they contain CTF dictionaries), but which are never
referred to as containers in the source code.

So fix this by completing the renaming, renaming ctf_file_t to
ctf_dict_t throughout, and renaming those few functions that refer to
CTF files by name (keeping compatibility aliases) to refer to dicts
instead.  Old users who still refer to ctf_file_t will see (harmless)
pointer-compatibility warnings at compile time, but the ABI is unchanged
(since C doesn't mangle names, and ctf_file_t was always an opaque type)
and things will still compile fine as long as -Werror is not specified.
All references to CTF containers and CTF files in the source code are
fixed to refer to CTF dicts instead.

Further (smaller) renamings of annoyingly-named functions to come, as
part of the process of souping up queries across whole archives at once
(needed for the function info and data object sections).

binutils/ChangeLog
2020-11-20  Nick Alcock  <nick.alcock@oracle.com>

	* objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t.
	(dump_ctf_archive_member): Likewise.
	(dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close.
	* readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t.
	(dump_ctf_archive_member): Likewise.
	(dump_section_as_ctf): Likewise.  Use ctf_dict_close, not
	ctf_file_close.

gdb/ChangeLog
2020-11-20  Nick Alcock  <nick.alcock@oracle.com>

	* ctfread.c: Change uses of ctf_file_t to ctf_dict_t.
	(ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close.

include/ChangeLog
2020-11-20  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-api.h (ctf_file_t): Rename to...
	(ctf_dict_t): ... this.  Keep ctf_file_t around for compatibility.
	(struct ctf_file): Likewise rename to...
	(struct ctf_dict): ... this.
	(ctf_file_close): Rename to...
	(ctf_dict_close): ... this, keeping compatibility function.
	(ctf_parent_file): Rename to...
	(ctf_parent_dict): ... this, keeping compatibility function.
	All callers adjusted.
	* ctf.h: Rename references to ctf_file_t to ctf_dict_t.
	(struct ctf_archive) <ctfa_nfiles>: Rename to...
	<ctfa_ndicts>: ... this.

ld/ChangeLog
2020-11-20  Nick Alcock  <nick.alcock@oracle.com>

	* ldlang.c (ctf_output): This is a ctf_dict_t now.
	(lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t.
	(ldlang_open_ctf): Adjust comment.
	(lang_merge_ctf): Use ctf_dict_close, not ctf_file_close.
	* ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to
	ctf_dict_t.  Change opaque declaration accordingly.
	* ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust.
	* ldemul.h (examine_strtab_for_ctf): Likewise.
	(ldemul_examine_strtab_for_ctf): Likewise.
	* ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise.

libctf/ChangeLog
2020-11-20  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations
	adjusted.
	(ctf_fileops): Rename to...
	(ctf_dictops): ... this.
	(ctf_dedup_t) <cd_id_to_file_t>: Rename to...
	<cd_id_to_dict_t>: ... this.
	(ctf_file_t): Fix outdated comment.
	<ctf_fileops>: Rename to...
	<ctf_dictops>: ... this.
	(struct ctf_archive_internal) <ctfi_file>: Rename to...
	<ctfi_dict>: ... this.
	* ctf-archive.c: Rename ctf_file_t to ctf_dict_t.
	Rename ctf_archive.ctfa_nfiles to ctfa_ndicts.
	Rename ctf_file_close to ctf_dict_close.  All users adjusted.
	* ctf-create.c: Likewise.  Refer to CTF dicts, not CTF containers.
	(ctf_bundle_t) <ctb_file>: Rename to...
	<ctb_dict): ... this.
	* ctf-decl.c: Rename ctf_file_t to ctf_dict_t.
	* ctf-dedup.c: Likewise.  Rename ctf_file_close to
	ctf_dict_close. Refer to CTF dicts, not CTF containers.
	* ctf-dump.c: Likewise.
	* ctf-error.c: Likewise.
	* ctf-hash.c: Likewise.
	* ctf-inlines.h: Likewise.
	* ctf-labels.c: Likewise.
	* ctf-link.c: Likewise.
	* ctf-lookup.c: Likewise.
	* ctf-open-bfd.c: Likewise.
	* ctf-string.c: Likewise.
	* ctf-subr.c: Likewise.
	* ctf-types.c: Likewise.
	* ctf-util.c: Likewise.
	* ctf-open.c: Likewise.
	(ctf_file_close): Rename to...
	(ctf_dict_close): ...this.
	(ctf_file_close): New trivial wrapper around ctf_dict_close, for
	compatibility.
	(ctf_parent_file): Rename to...
	(ctf_parent_dict): ... this.
	(ctf_parent_file): New trivial wrapper around ctf_parent_dict, for
	compatibility.
	* libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 13:34:04 +00:00

348 lines
9.7 KiB
C

/* Opening CTF files with BFD.
Copyright (C) 2019-2020 Free Software Foundation, Inc.
This file is part of libctf.
libctf is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not see
<http://www.gnu.org/licenses/>. */
#include <ctf-impl.h>
#include <stddef.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
#include <bfd.h>
#include "swap.h"
#include "ctf-endian.h"
#include "elf-bfd.h"
/* Free the BFD bits of a CTF file on ctf_arc_close(). */
static void
ctf_bfdclose (struct ctf_archive_internal *arci)
{
if (arci->ctfi_abfd != NULL)
if (!bfd_close_all_done (arci->ctfi_abfd))
ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
bfd_errmsg (bfd_get_error ()));
}
/* Open a CTF file given the specified BFD. */
ctf_archive_t *
ctf_bfdopen (struct bfd *abfd, int *errp)
{
ctf_archive_t *arc;
asection *ctf_asect;
bfd_byte *contents;
ctf_sect_t ctfsect;
libctf_init_debug();
if ((ctf_asect = bfd_get_section_by_name (abfd, _CTF_SECTION)) == NULL)
{
return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
}
if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents))
{
ctf_err_warn (NULL, 0, 0, _("ctf_bfdopen(): cannot malloc "
"CTF section: %s"),
bfd_errmsg (bfd_get_error ()));
return (ctf_set_open_errno (errp, ECTF_FMT));
}
ctfsect.cts_name = _CTF_SECTION;
ctfsect.cts_entsize = 1;
ctfsect.cts_size = bfd_section_size (ctf_asect);
ctfsect.cts_data = contents;
if ((arc = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL)
{
/* This frees the cts_data later. */
arc->ctfi_data = (void *) ctfsect.cts_data;
return arc;
}
free (contents);
return NULL; /* errno is set for us. */
}
/* Open a CTF file given the specified BFD and CTF section (which may contain a
CTF archive or a file). */
ctf_archive_t *
ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
const ctf_sect_t *ctfsect, int *errp)
{
ctf_archive_t *arci;
ctf_sect_t *symsectp = NULL;
ctf_sect_t *strsectp = NULL;
const char *bfderrstr = NULL;
char *strtab_alloc = NULL;
#ifdef HAVE_BFD_ELF
ctf_sect_t symsect, strsect;
Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd);
size_t symcount;
Elf_Internal_Sym *isymbuf;
bfd_byte *symtab = NULL;
const char *strtab = NULL;
size_t strsize;
/* TODO: handle SYMTAB_SHNDX. */
/* Get the symtab, and the strtab associated with it. */
if (elf_tdata (abfd) && symhdr && symhdr->sh_size && symhdr->sh_entsize)
{
symcount = symhdr->sh_size / symhdr->sh_entsize;
if ((symtab = malloc (symhdr->sh_size)) == NULL)
{
bfderrstr = N_("cannot malloc symbol table");
goto err;
}
isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0,
NULL, symtab, NULL);
free (isymbuf);
if (isymbuf == NULL)
{
bfderrstr = N_("cannot read symbol table");
goto err_free_sym;
}
if (elf_elfsections (abfd) != NULL
&& symhdr->sh_link < elf_numsections (abfd))
{
Elf_Internal_Shdr *strhdr = elf_elfsections (abfd)[symhdr->sh_link];
strsize = strhdr->sh_size;
if (strhdr->contents == NULL)
{
if ((strtab = bfd_elf_get_str_section (abfd, symhdr->sh_link)) == NULL)
{
bfderrstr = N_("cannot read string table");
goto err_free_sym;
}
}
else
strtab = (const char *) strhdr->contents;
}
}
else /* No symtab: just try getting .strtab by name. */
{
bfd_byte *str_bcontents;
asection *str_asect;
if ((str_asect = bfd_get_section_by_name (abfd, ".strtab")) != NULL)
{
if (bfd_malloc_and_get_section (abfd, str_asect, &str_bcontents))
{
strtab = (const char *) str_bcontents;
strtab_alloc = (char *) str_bcontents;
strsize = str_asect->size;
}
}
}
if (strtab)
{
/* The names here are more or less arbitrary, but there is no point
thrashing around digging the name out of the shstrtab given that we don't
use it for anything but debugging. */
strsect.cts_data = strtab;
strsect.cts_name = ".strtab";
strsect.cts_size = strsize;
strsectp = &strsect;
}
if (symtab)
{
assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym);
symsect.cts_name = ".symtab";
symsect.cts_entsize = symhdr->sh_entsize;
symsect.cts_size = symhdr->sh_size;
symsect.cts_data = symtab;
symsectp = &symsect;
}
#endif
arci = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp);
if (arci)
{
/* Request freeing of the symsect and possibly the strsect. */
arci->ctfi_free_symsect = 1;
if (strtab_alloc)
arci->ctfi_free_strsect = 1;
return arci;
}
#ifdef HAVE_BFD_ELF
err_free_sym:
free (symtab);
free (strtab_alloc);
#endif
err: _libctf_unused_;
if (bfderrstr)
{
ctf_err_warn (NULL, 0, 0, "ctf_bfdopen(): %s: %s", gettext (bfderrstr),
bfd_errmsg (bfd_get_error()));
ctf_set_open_errno (errp, ECTF_FMT);
}
return NULL;
}
/* Open the specified file descriptor and return a pointer to a CTF archive that
contains one or more CTF dicts. The file can be an ELF file, a file
containing raw CTF, or a CTF archive. The caller is responsible for closing
the file descriptor when it is no longer needed. If this is an ELF file,
TARGET, if non-NULL, should be the name of a suitable BFD target. */
ctf_archive_t *
ctf_fdopen (int fd, const char *filename, const char *target, int *errp)
{
ctf_archive_t *arci;
bfd *abfd;
int nfd;
struct stat st;
ssize_t nbytes;
ctf_preamble_t ctfhdr;
uint64_t arc_magic;
memset (&ctfhdr, 0, sizeof (ctfhdr));
libctf_init_debug();
if (fstat (fd, &st) == -1)
return (ctf_set_open_errno (errp, errno));
if ((nbytes = ctf_pread (fd, &ctfhdr, sizeof (ctfhdr), 0)) <= 0)
return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
/* If we have read enough bytes to form a CTF header and the magic string
matches, in either endianness, attempt to interpret the file as raw
CTF. */
if ((size_t) nbytes >= sizeof (ctf_preamble_t)
&& (ctfhdr.ctp_magic == CTF_MAGIC
|| ctfhdr.ctp_magic == bswap_16 (CTF_MAGIC)))
{
ctf_dict_t *fp = NULL;
void *data;
if ((data = ctf_mmap (st.st_size, 0, fd)) == NULL)
return (ctf_set_open_errno (errp, errno));
if ((fp = ctf_simple_open (data, (size_t) st.st_size, NULL, 0, 0,
NULL, 0, errp)) == NULL)
{
ctf_munmap (data, (size_t) st.st_size);
return NULL; /* errno is set for us. */
}
fp->ctf_data_mmapped = data;
fp->ctf_data_mmapped_len = (size_t) st.st_size;
return ctf_new_archive_internal (0, 1, NULL, fp, NULL, NULL, errp);
}
if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0)
return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT));
if ((size_t) nbytes >= sizeof (uint64_t) && le64toh (arc_magic) == CTFA_MAGIC)
{
struct ctf_archive *arc;
if ((arc = ctf_arc_open_internal (filename, errp)) == NULL)
return NULL; /* errno is set for us. */
return ctf_new_archive_internal (1, 1, arc, NULL, NULL, NULL, errp);
}
/* Attempt to open the file with BFD. We must dup the fd first, since bfd
takes ownership of the passed fd. */
if ((nfd = dup (fd)) < 0)
return (ctf_set_open_errno (errp, errno));
if ((abfd = bfd_fdopenr (filename, target, nfd)) == NULL)
{
ctf_err_warn (NULL, 0, 0, _("cannot open BFD from %s: %s"),
filename ? filename : _("(unknown file)"),
bfd_errmsg (bfd_get_error ()));
return (ctf_set_open_errno (errp, ECTF_FMT));
}
bfd_set_cacheable (abfd, 1);
if (!bfd_check_format (abfd, bfd_object))
{
ctf_err_warn (NULL, 0, 0, _("BFD format problem in %s: %s"),
filename ? filename : _("(unknown file)"),
bfd_errmsg (bfd_get_error ()));
if (bfd_get_error() == bfd_error_file_ambiguously_recognized)
return (ctf_set_open_errno (errp, ECTF_BFD_AMBIGUOUS));
else
return (ctf_set_open_errno (errp, ECTF_FMT));
}
if ((arci = ctf_bfdopen (abfd, errp)) == NULL)
{
if (!bfd_close_all_done (abfd))
ctf_err_warn (NULL, 0, 0, _("cannot close BFD: %s"),
bfd_errmsg (bfd_get_error ()));
return NULL; /* errno is set for us. */
}
arci->ctfi_bfd_close = ctf_bfdclose;
arci->ctfi_abfd = abfd;
return arci;
}
/* Open the specified file and return a pointer to a CTF dict. The file
can be either an ELF file or raw CTF file. This is just a convenient
wrapper around ctf_fdopen() for callers. */
ctf_archive_t *
ctf_open (const char *filename, const char *target, int *errp)
{
ctf_archive_t *arc;
int fd;
if ((fd = open (filename, O_RDONLY)) == -1)
{
if (errp != NULL)
*errp = errno;
return NULL;
}
arc = ctf_fdopen (fd, filename, target, errp);
(void) close (fd);
return arc;
}
/* Public entry point: open a CTF archive, or CTF file. Returns the archive, or
NULL and an error in *err. Despite the fact that this uses CTF archives, it
must be in this file to avoid dragging in BFD into non-BFD-using programs. */
ctf_archive_t *
ctf_arc_open (const char *filename, int *errp)
{
return ctf_open (filename, NULL, errp);
}