mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2026-08-27 00:26:02 -04:00
include, libctf, ld, gdb, binutils: API review: lowlevel opening changes
libctf has a variety of functions that let you open CTF dicts and
archives explicitly, by passing in buffers full of data that usually
correspond to ELF sections rather than by just getting BFD to figure it
out for you. These are all similar in general form: they take a bunch
of ctf_sect_t's containing some of the ELF sections libctf understands
(CTF, string, symbol), and do things with them. Each ELF section gets
its own function parameter.
This is not very extensible, and in the new CTFv4 world we would like to
do as BTF does and keep the .ctf section as devoid of new CTF-internal
sections as possible (so that it stays almost totally the same as BTF),
moving things like the symtypetabs into ordinary ELF sections instead.
This means that the set of ELF sections we accept is likely to grow over
time: we can hardly change all these prototypes, break all their callers
and bump the soname every time we want to add another one.
So change things up a bit. Instead of accepting ctf_sect_t's as
ordinary parameters, we expand the ctf_sect_t so that (internally to
libctf) it is actually a member of a ctf_list_t: there is a new
function, ctf_open_sect, that chains ctf_sect_t's together into a list;
it cannot fail and allocates no memory, so you can call it in nested
fashion in the arguments to the public opening functions and then
otherwise ignore the result. This means you might end up with things
changing from this (in which symsectp and strsectp might be NULL,
indicating that those sections are not present):
arc = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp);
to this:
ctf_sect_t ctfsect = {0}; /* Initialize to zero */
ctf_sect_t symsect = {0}; /* Initialize to zero */
ctf_sect_t strsect = {0}; /* Initialize to zero */
ctf_sect_t *symsectp = NULL, *strsectp = NULL;
ctfsect.cts_section = CTF_ELF_SECT;
...
/* ... and similarly for symsect and strsect, using CTF_ELF_SYMSECT and
CTF_ELF_STRSECT, assigning symsectp and strsectp if set */
arc = ctf_arc_bufopen (ctf_open_sect (ctf_open_sect (ctf_open_sect (NULL,
&ctfsect), symsectp), strsectp), errp);
In the above, you can pass the sections in in any order, pass in fewer
sections (calling ctf_open_sect fewer times), or just pass NULL instead
of calling ctf_open_sect at all if there are none (usually a bad idea,
since one is usually the CTF section): you just have to set cts_section
suitably to indicate which is which. Unknown cts_sections are just
ignored: repeated ones have something undefined happen to them but do
not trigger errors (right now, we consistently pick the last).
The only "don't": do not call supply same ctf_sect_t repeatedly in the
same arg list (you'll get a circular list internally, and an immediate
infloop).
With this machinery in place, we can add new sections without changing
the public API at all except by extending ctf_elfsect_names_t. We use
this in upcoming commits.
This commit is contained in:
parent
dcbcb6a0b3
commit
5532fbca2e
19 changed files with 361 additions and 272 deletions
|
|
@ -4784,13 +4784,13 @@ dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED,
|
|||
return xasprintf ("%s%s", blanks, s);
|
||||
}
|
||||
|
||||
/* Make a ctfsect suitable for ctf_bfdopen_ctfsect(). */
|
||||
/* Make a ctfsect suitable for ctf_bfdopen(). */
|
||||
static ctf_sect_t
|
||||
make_ctfsect (const char *name, bfd_byte *data,
|
||||
bfd_size_type size)
|
||||
make_ctfsect (const char *name, bfd_byte *data, bfd_size_type size)
|
||||
{
|
||||
ctf_sect_t ctfsect;
|
||||
ctf_sect_t ctfsect = {0};
|
||||
|
||||
ctfsect.cts_section = CTF_ELF_SECT;
|
||||
ctfsect.cts_name = name;
|
||||
ctfsect.cts_entsize = 1;
|
||||
ctfsect.cts_size = size;
|
||||
|
|
@ -4913,7 +4913,7 @@ dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name,
|
|||
from a different section entirely. */
|
||||
|
||||
ctfsect = make_ctfsect (sect_name, ctfdata, bfd_section_size (sec));
|
||||
if ((ctfa = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL)
|
||||
if ((ctfa = ctf_bfdopen (abfd, ctf_open_sect (NULL, &ctfsect), &err)) == NULL)
|
||||
{
|
||||
dump_ctf_errs (NULL);
|
||||
non_fatal (_("CTF open failure: %s"), ctf_errmsg (err));
|
||||
|
|
@ -4932,8 +4932,10 @@ dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name,
|
|||
return;
|
||||
}
|
||||
|
||||
ctfsect = make_ctfsect (parent_sect_name, ctfpdata, bfd_section_size (psec));
|
||||
if ((ctfpa = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL)
|
||||
ctfsect = make_ctfsect (parent_sect_name, ctfpdata,
|
||||
bfd_section_size (psec));
|
||||
if ((ctfpa = ctf_bfdopen (abfd, ctf_open_sect (NULL, &ctfsect),
|
||||
&err)) == NULL)
|
||||
{
|
||||
dump_ctf_errs (NULL);
|
||||
non_fatal (_("CTF open failure: %s"), ctf_errmsg (err));
|
||||
|
|
|
|||
|
|
@ -17331,8 +17331,10 @@ dump_section_as_bytes (Elf_Internal_Shdr *section,
|
|||
|
||||
#ifdef ENABLE_LIBCTF
|
||||
static ctf_sect_t *
|
||||
shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata)
|
||||
shdr_to_ctf_sect (ctf_sect_t *buf, ctf_elfsect_names_t sect,
|
||||
Elf_Internal_Shdr *shdr, Filedata *filedata)
|
||||
{
|
||||
buf->cts_section = sect;
|
||||
buf->cts_name = printable_section_name (filedata, shdr);
|
||||
buf->cts_size = shdr->sh_size;
|
||||
buf->cts_entsize = shdr->sh_entsize;
|
||||
|
|
@ -17427,7 +17429,7 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||
void * data = NULL;
|
||||
void * symdata = NULL;
|
||||
void * strdata = NULL;
|
||||
ctf_sect_t ctfsect, symsect, strsect;
|
||||
ctf_sect_t ctfsect = {0}, symsect = {0}, strsect = {0};
|
||||
ctf_sect_t * symsectp = NULL;
|
||||
ctf_sect_t * strsectp = NULL;
|
||||
ctf_archive_t * ctfa = NULL;
|
||||
|
|
@ -17440,7 +17442,7 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||
ctf_error_t err;
|
||||
bool ret = false;
|
||||
|
||||
shdr_to_ctf_sect (&ctfsect, section, filedata);
|
||||
shdr_to_ctf_sect (&ctfsect, CTF_ELF_SECT, section, filedata);
|
||||
data = get_section_contents (section, filedata);
|
||||
ctfsect.cts_data = data;
|
||||
|
||||
|
|
@ -17462,7 +17464,8 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||
symtab_sec->sh_size,
|
||||
_("symbols"))) == NULL)
|
||||
goto fail;
|
||||
symsectp = shdr_to_ctf_sect (&symsect, symtab_sec, filedata);
|
||||
symsectp = shdr_to_ctf_sect (&symsect, CTF_ELF_SYMSECT, symtab_sec,
|
||||
filedata);
|
||||
symsect.cts_data = symdata;
|
||||
}
|
||||
|
||||
|
|
@ -17479,7 +17482,8 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||
strtab_sec->sh_size,
|
||||
_("strings"))) == NULL)
|
||||
goto fail;
|
||||
strsectp = shdr_to_ctf_sect (&strsect, strtab_sec, filedata);
|
||||
strsectp = shdr_to_ctf_sect (&strsect, CTF_ELF_STRSECT, strtab_sec,
|
||||
filedata);
|
||||
strsect.cts_data = strdata;
|
||||
}
|
||||
|
||||
|
|
@ -17487,7 +17491,8 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||
archive: libctf papers over the difference, so we can pretend it is always
|
||||
an archive. */
|
||||
|
||||
if ((ctfa = ctf_arc_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL)
|
||||
if ((ctfa = ctf_arc_bufopen (ctf_open_sect (ctf_open_sect (ctf_open_sect (NULL,
|
||||
&ctfsect), symsectp), strsectp), &err)) == NULL)
|
||||
{
|
||||
dump_ctf_errs (NULL);
|
||||
error (_("CTF open failure: %s\n"), ctf_errmsg (err));
|
||||
|
|
|
|||
|
|
@ -1468,7 +1468,7 @@ elfctf_build_psymtabs (struct objfile *of)
|
|||
const char *name;
|
||||
ctf_error_t err;
|
||||
|
||||
ctf_archive_t *arc = ctf_bfdopen (abfd, &err);
|
||||
ctf_archive_t *arc = ctf_bfdopen (abfd, NULL, &err);
|
||||
if (arc == nullptr)
|
||||
error (_("ctf_bfdopen failed on %s - %s"),
|
||||
bfd_get_filename (abfd), ctf_errmsg (err));
|
||||
|
|
|
|||
|
|
@ -78,21 +78,51 @@ typedef int ctf_error_t;
|
|||
|
||||
struct bfd;
|
||||
|
||||
/* Symbolic names for CTF sections. */
|
||||
|
||||
typedef enum ctf_sect_names
|
||||
{
|
||||
CTF_SECT_HEADER,
|
||||
CTF_SECT_OBJT,
|
||||
CTF_SECT_OBJTIDX = CTF_SECT_OBJT,
|
||||
CTF_SECT_FUNC,
|
||||
CTF_SECT_FUNCIDX = CTF_SECT_FUNC,
|
||||
CTF_SECT_VAR,
|
||||
CTF_SECT_TYPE,
|
||||
CTF_SECT_STR
|
||||
} ctf_sect_names_t;
|
||||
|
||||
/* Symbolic names for ELF sections associated with CTF. */
|
||||
typedef enum ctf_elfsect_names
|
||||
{
|
||||
CTF_ELF_SECT, /* The .ctf section. */
|
||||
CTF_ELF_SYMSECT, /* The associated symtab. */
|
||||
CTF_ELF_STRSECT, /* The ELF string table. */
|
||||
} ctf_elfsect_names_t;
|
||||
|
||||
/* If the debugger needs to provide the CTF library with a set of raw buffers
|
||||
for use as the CTF data, symbol table, and string table, it can do so by
|
||||
filling in ctf_sect_t structures and passing them to ctf_bufopen.
|
||||
filling in ctf_sect_t structures and passing them to ctf_bufopen et al via
|
||||
the ctf_open_sect_t function.
|
||||
|
||||
The contents of this structure must always be in native endianness. At read
|
||||
time, the symbol table endianness is derived from the BFD target (if BFD is
|
||||
in use): if a BFD target is not in use, please call ctf_symsect_endianness or
|
||||
ctf_arc_symsect_endianness. */
|
||||
At read time, the symbol table endianness is derived from the BFD target (if
|
||||
BFD is in use): if a BFD target is not in use, please call
|
||||
ctf_symsect_endianness or ctf_arc_symsect_endianness. */
|
||||
|
||||
typedef struct ctf_sect
|
||||
{
|
||||
/* Used by ctf_open_sect et al. Must be zero-initialized. */
|
||||
struct
|
||||
{
|
||||
void *reserved1;
|
||||
void *reserved2;
|
||||
} reserved;
|
||||
|
||||
ctf_elfsect_names_t cts_section; /* ELF section this corresponds to. */
|
||||
const char *cts_name; /* Section name (if any). */
|
||||
const void *cts_data; /* Pointer to section data. */
|
||||
size_t cts_size; /* Size of data in bytes. */
|
||||
size_t cts_entsize; /* Size of each section entry (symtab only). */
|
||||
size_t cts_entsize; /* Size of each section entry (symtab only). */
|
||||
} ctf_sect_t;
|
||||
|
||||
/* A minimal symbol extracted from a linker's internal symbol table
|
||||
|
|
@ -161,28 +191,6 @@ enum ctf_link_flags
|
|||
typedef int ctf_link_flags_t;
|
||||
#endif
|
||||
|
||||
/* Symbolic names for CTF sections. */
|
||||
|
||||
typedef enum ctf_sect_names
|
||||
{
|
||||
CTF_SECT_HEADER,
|
||||
CTF_SECT_OBJT,
|
||||
CTF_SECT_OBJTIDX = CTF_SECT_OBJT,
|
||||
CTF_SECT_FUNC,
|
||||
CTF_SECT_FUNCIDX = CTF_SECT_FUNC,
|
||||
CTF_SECT_VAR,
|
||||
CTF_SECT_TYPE,
|
||||
CTF_SECT_STR
|
||||
} ctf_sect_names_t;
|
||||
|
||||
/* Symbolic names for ELF sections associated with CTF. */
|
||||
typedef enum ctf_elfsect_names
|
||||
{
|
||||
CTF_ELF_SECT, /* The .ctf section. */
|
||||
CTF_ELF_SYMSECT, /* The associated symtab. */
|
||||
CTF_ELF_STRSECT, /* The ELF string table. */
|
||||
} ctf_elfsect_names_t;
|
||||
|
||||
/* Encoding information for integers, floating-point values, and certain other
|
||||
intrinsics can be obtained by calling ctf_type_encoding, below. The flags
|
||||
field will contain values appropriate for the type defined in <ctf.h>.
|
||||
|
|
@ -288,7 +296,7 @@ typedef int ctf_func_type_flags_t;
|
|||
_CTF_ITEM (ECTF_SYMBAD, "symbol table data buffer is not valid") \
|
||||
_CTF_ITEM (ECTF_STRBAD, "string table data buffer is not valid") \
|
||||
_CTF_ITEM (ECTF_CORRUPT, "file data structure corruption detected") \
|
||||
_CTF_ITEM (ECTF_NOCTFDATA, "file does not contain CTF data") \
|
||||
_CTF_ITEM (ECTF_NOCTFDATA, "no .ctf or .BTF section") \
|
||||
_CTF_ITEM (ECTF_NOCTFBUF, "buffer does not contain CTF data") \
|
||||
_CTF_ITEM (ECTF_NOSYMTAB, "symbol table information is not available") \
|
||||
_CTF_ITEM (ECTF_NOPARENT, "the parent CTF dictionary is needed but unavailable") \
|
||||
|
|
@ -445,12 +453,37 @@ extern ctf_next_t *ctf_next_copy (ctf_next_t *);
|
|||
|
||||
All these functions except for ctf_close use BFD and can open anything BFD
|
||||
can open, hunting down the .ctf section for you, so are not available in the
|
||||
libctf-nobfd flavour of the library. If you want to provide the CTF section
|
||||
yourself, you can do that with ctf_bfdopen_ctfsect. */
|
||||
libctf-nobfd flavour of the library. If you want to provide some sections
|
||||
yourself, you can do that using the optional ctf_open_sect_t argument to
|
||||
ctf_bfdopen.
|
||||
|
||||
extern ctf_archive_t *ctf_bfdopen (struct bfd *, ctf_error_t *);
|
||||
extern ctf_archive_t *ctf_bfdopen_ctfsect (struct bfd *, const ctf_sect_t *,
|
||||
ctf_error_t *);
|
||||
Some of these functions take a list of sections, constructed by the
|
||||
ctf_open_sect function, which chains together ctf_open_sect_t structs (pass
|
||||
the return value of each into the next call). These other sections are
|
||||
optional and usually consist of symtab, strtab, and symtypetab sections. If
|
||||
you don't pass the right sections in (usually symtypetab and associated
|
||||
string and symbol tables linked via sh_link), opening will succeed but things
|
||||
like symbol->type lookup will not be available, and the ctf_*_lookup_symbol
|
||||
functions will fail with ECTF_NOSYMTAB. The structures returned by
|
||||
ctf_open_sect are consumed by the open functions and should not be used
|
||||
again. The ctf_sect_t's passed in, and the buffers they wrap, are still
|
||||
owned by the caller; the ctf_sect_t's can be freed, but the buffers are in
|
||||
use: do not free them until the archive, and all dicts derived from it, are
|
||||
closed.
|
||||
|
||||
We do not define what happens if you pass in multiple sections of the same
|
||||
type in ctf_open_sect (this is to enable us to define useful behaviour in the
|
||||
future if need be).
|
||||
|
||||
ctf_open_sect cannot fail and can be called in a nested fashion in the
|
||||
argument list of functions taking a ctf_open_sect_t to pass in multiple
|
||||
sections easily. */
|
||||
|
||||
typedef struct ctf_open_sect ctf_open_sect_t;
|
||||
extern ctf_open_sect_t *ctf_open_sect (ctf_open_sect_t *, ctf_sect_t *);
|
||||
|
||||
extern ctf_archive_t *ctf_bfdopen (struct bfd *, ctf_open_sect_t *,
|
||||
ctf_error_t *);
|
||||
extern ctf_archive_t *ctf_fdopen (int fd, const char *filename,
|
||||
const char *target, ctf_error_t *);
|
||||
extern ctf_archive_t *ctf_open (const char *filename,
|
||||
|
|
@ -483,24 +516,11 @@ extern void ctf_arc_symsect_endianness (ctf_archive_t *, int little_endian);
|
|||
Almost all functions that open archives will also open raw CTF dicts, which
|
||||
are treated as if they were archives with only one member.
|
||||
|
||||
Some of these functions take optional raw symtab and strtab section content
|
||||
in the form of ctf_sect_t structures. For CTF in ELF files, the more
|
||||
convenient opening functions above extract these .dynsym and its associated
|
||||
string table (usually .dynsym) whenever the CTF_F_DYNSTR flag is set in the
|
||||
CTF preamble (which it almost always will be for linked objects, but not for
|
||||
.o files). If you use ctf_arc_bufopen and do not specify symbol/string
|
||||
tables, the ctf_*_lookup_symbol functions will fail with ECTF_NOSYMTAB.
|
||||
Do not free the buffers passed to ctf_arc_bufopen until the archive, and
|
||||
all dicts derived from it, are closed.
|
||||
|
||||
Like many other convenient opening functions, ctf_arc_open needs BFD and is
|
||||
not available in libctf-nobfd. */
|
||||
|
||||
extern ctf_archive_t *ctf_arc_open (const char *, ctf_error_t *);
|
||||
extern ctf_archive_t *ctf_arc_bufopen (const ctf_sect_t *ctfsect,
|
||||
const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect,
|
||||
ctf_error_t *);
|
||||
extern ctf_archive_t *ctf_arc_bufopen (ctf_open_sect_t *, ctf_error_t *);
|
||||
extern void ctf_arc_close (ctf_archive_t *);
|
||||
|
||||
/* Get boolean properties of an archive. Only one property is defined so far: a
|
||||
|
|
@ -588,7 +608,7 @@ extern void ctf_arc_flush_caches (ctf_archive_t *);
|
|||
|
||||
/* The next functions return or close real CTF files, not archives or ELF files
|
||||
containing CTF content. They can be passed symbol and string table sections
|
||||
if need be.
|
||||
if need be. (A sect of type CTF_ELF_SECT is obviously mandatory.)
|
||||
|
||||
Unlike ctf_dict_open et al above, these low-level functions expose the
|
||||
parent/child relationship between CTF dicts (ctf_dict_open* opens parents as
|
||||
|
|
@ -610,9 +630,7 @@ extern void ctf_arc_flush_caches (ctf_archive_t *);
|
|||
something other than input object files, see ctf_link_add_cu_mapping and
|
||||
CTF_LINK_SHARE_*. */
|
||||
|
||||
extern ctf_dict_t *ctf_bufopen (const ctf_sect_t *ctfsect,
|
||||
const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect, ctf_dict_t *parent,
|
||||
extern ctf_dict_t *ctf_bufopen (ctf_open_sect_t *sects, ctf_dict_t *parent,
|
||||
ctf_error_t *);
|
||||
extern void ctf_dict_close (ctf_dict_t *);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
/* Testsuite-internal API to libctf.
|
||||
Copyright (C) 2025 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/>. */
|
||||
|
||||
/* This header file defines the interfaces available from the CTF debugger
|
||||
library, libctf. This API can be used by a debugger to operate on data in
|
||||
the Compact ANSI-C Type Format (CTF). */
|
||||
|
||||
#ifndef _CTF_TEST_API_H
|
||||
#define _CTF_TEST_API_H
|
||||
|
||||
#include <ctf-api.h>
|
||||
|
||||
extern ctf_dict_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size,
|
||||
const char *symsect, size_t symsect_size,
|
||||
size_t symsect_entsize,
|
||||
const char *strsect, size_t strsect_size,
|
||||
ctf_dict_t *parent, ctf_error_t *errp);
|
||||
|
||||
#endif /* _CTF_TEST_API_H */
|
||||
|
|
@ -3849,7 +3849,7 @@ ldlang_open_ctf (void)
|
|||
wrapper): files derived from a previous relocatable link have a CTF
|
||||
archive containing possibly many CTF files. */
|
||||
|
||||
if ((file->the_ctf = ctf_bfdopen (file->the_bfd, &err)) == NULL)
|
||||
if ((file->the_ctf = ctf_bfdopen (file->the_bfd, NULL, &err)) == NULL)
|
||||
{
|
||||
if (err != ECTF_NOCTFDATA)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -124,6 +124,6 @@ EXTRA_DEJAGNU_SITE_CONFIG = development.exp
|
|||
|
||||
DISTCLEANFILES += site.exp development.exp
|
||||
|
||||
EXTRA_DIST = libtool-version libctf.ver $(INCDIR)/ctf-test-api.h
|
||||
EXTRA_DIST = libtool-version libctf.ver
|
||||
|
||||
include doc/local.mk
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ CC_FOR_TARGET = ` \
|
|||
# development.sh is used to determine -Werror default.
|
||||
CONFIG_STATUS_DEPENDENCIES = $(BFDDIR)/development.sh
|
||||
EXTRA_DEJAGNU_SITE_CONFIG = development.exp
|
||||
EXTRA_DIST = libtool-version libctf.ver $(INCDIR)/ctf-test-api.h
|
||||
EXTRA_DIST = libtool-version libctf.ver
|
||||
@BUILD_INFO_TRUE@AM_MAKEINFOFLAGS = --no-split
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
|
|
|||
|
|
@ -618,14 +618,16 @@ ctf_arc_find_magic (unsigned char *buf, size_t len, int *strtab)
|
|||
contain a ctf_archive) or a single ctf_dict: endian-swap the archive
|
||||
header as necessary, and check all its offsets for validity.
|
||||
Close/optionally unmap BUF and/or FP on error. Arrange to free or unmap
|
||||
the SYMSECT or STRSECT, as needed, on close. */
|
||||
any passed-in symbol or string sections on close. The CTF section in the
|
||||
passed-in SECTS is ignored: it's assumed to already be passed in as BUF. */
|
||||
|
||||
struct ctf_archive_internal *
|
||||
ctf_new_archive_internal (unsigned char *buf, ctf_dict_t *fp, int v1,
|
||||
enum arc_on_close_operation on_close,
|
||||
size_t len, const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect, ctf_error_t *errp)
|
||||
size_t len, ctf_open_sect_t *sects,
|
||||
ctf_error_t *errp)
|
||||
{
|
||||
ctf_sect_t *strsect = NULL, *symsect = NULL;
|
||||
struct ctf_archive_internal *arci = NULL;
|
||||
size_t ufsize;
|
||||
ctf_error_t err = 0;
|
||||
|
|
@ -772,7 +774,7 @@ ctf_new_archive_internal (unsigned char *buf, ctf_dict_t *fp, int v1,
|
|||
while ((magic = ctf_arc_find_magic (p, MIN (65, len - (p - buf)), &strtab)) != NULL)
|
||||
{
|
||||
ssize_t dict_len;
|
||||
ctf_sect_t tmp;
|
||||
ctf_sect_t tmp = {0};
|
||||
|
||||
if (strtab)
|
||||
break;
|
||||
|
|
@ -780,10 +782,9 @@ ctf_new_archive_internal (unsigned char *buf, ctf_dict_t *fp, int v1,
|
|||
p = magic;
|
||||
arci->ctfi_members[i] = (p - buf);
|
||||
|
||||
memset (&tmp, 0, sizeof (ctf_sect_t));
|
||||
tmp.cts_size = len - (p - buf); /* (upper bound) */
|
||||
tmp.cts_data = p;
|
||||
if ((dict_len = ctf_buflen (&tmp, &err)) < 0)
|
||||
if ((dict_len = ctf_buflen (ctf_open_sect (NULL, &tmp), &err)) < 0)
|
||||
{
|
||||
ctf_set_open_errno (errp, err);
|
||||
ctf_err (err_locus (NULL), err,
|
||||
|
|
@ -879,10 +880,28 @@ ctf_new_archive_internal (unsigned char *buf, ctf_dict_t *fp, int v1,
|
|||
goto err_set;
|
||||
}
|
||||
|
||||
if (sects)
|
||||
{
|
||||
ctf_sect_t *sect = (ctf_sect_t *) sects;
|
||||
|
||||
do
|
||||
{
|
||||
switch (sect->cts_section)
|
||||
{
|
||||
case CTF_ELF_SYMSECT: symsect = sect; break;
|
||||
case CTF_ELF_STRSECT: strsect = sect; break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
sect = ctf_list_next (sect);
|
||||
} while (sect);
|
||||
}
|
||||
|
||||
if (symsect)
|
||||
memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect));
|
||||
memcpy (&arci->ctfi_symsect, symsect, sizeof (struct ctf_sect));
|
||||
if (strsect)
|
||||
memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
|
||||
memcpy (&arci->ctfi_strsect, strsect, sizeof (struct ctf_sect));
|
||||
|
||||
arci->ctfi_free_symsect = 0;
|
||||
arci->ctfi_free_strsect = 0;
|
||||
arci->ctfi_symsect_little_endian = -1;
|
||||
|
|
@ -915,12 +934,11 @@ ctf_new_archive_internal (unsigned char *buf, ctf_dict_t *fp, int v1,
|
|||
is. */
|
||||
|
||||
struct ctf_archive_internal *
|
||||
ctf_new_archive_wrapper (ctf_dict_t *fp, const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect, ctf_error_t *errp)
|
||||
ctf_new_archive_wrapper (ctf_dict_t *fp, ctf_open_sect_t *sects, ctf_error_t *errp)
|
||||
{
|
||||
struct ctf_archive_internal *arci;
|
||||
if ((arci = ctf_new_archive_internal (NULL, fp, 0, FREE_ARCHIVE_ON_DICT_CLOSE,
|
||||
0, symsect, strsect, errp)) != NULL)
|
||||
0, sects, errp)) != NULL)
|
||||
arci->ctfi_symsect_little_endian = fp->ctf_symsect_little_endian;
|
||||
return arci;
|
||||
}
|
||||
|
|
@ -944,7 +962,7 @@ ctf_sect_t
|
|||
ctf_arc_elf_sect (const struct ctf_archive_internal *arci,
|
||||
ctf_elfsect_names_t sect)
|
||||
{
|
||||
ctf_sect_t error = { "ERROR", NULL, 0, 0 };
|
||||
ctf_sect_t error = { {0}, 0, "ERROR", NULL, 0, 0 };
|
||||
|
||||
if (arci->ctfi_dict)
|
||||
return ctf_elf_sect (arci->ctfi_dict, sect);
|
||||
|
|
@ -1000,11 +1018,26 @@ ctf_arc_bufpreamble_v1 (const ctf_sect_t *ctfsect)
|
|||
preserve until ctf_arc_close() time). Returns the archive, or NULL and an
|
||||
error in *err (if not NULL). */
|
||||
ctf_archive_t *
|
||||
ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect, ctf_error_t *errp)
|
||||
ctf_arc_bufopen (ctf_open_sect_t *sects, ctf_error_t *errp)
|
||||
{
|
||||
ctf_sect_t *sect = (ctf_sect_t *) sects;
|
||||
ctf_sect_t *ctfsect = NULL;
|
||||
|
||||
int v1 = 0;
|
||||
|
||||
if (sect == NULL)
|
||||
return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
|
||||
|
||||
do
|
||||
{
|
||||
if (sect->cts_section == CTF_ELF_SECT)
|
||||
ctfsect = sect;
|
||||
sect = ctf_list_next (sect);
|
||||
} while (sect);
|
||||
|
||||
if (ctfsect == NULL)
|
||||
return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
|
||||
|
||||
if (ctfsect->cts_data != NULL
|
||||
&& ctfsect->cts_size > sizeof (uint64_t)
|
||||
&& (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_V1_MAGIC))
|
||||
|
|
@ -1012,7 +1045,7 @@ ctf_arc_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
|||
|
||||
return ctf_new_archive_internal ((unsigned char *) ctfsect->cts_data, NULL,
|
||||
v1, FREE_ARCHIVE_ONLY_DICT, ctfsect->cts_size,
|
||||
symsect, strsect, errp);
|
||||
sects, errp);
|
||||
}
|
||||
|
||||
/* Open a CTF archive from a given fd. Returns the archive (wrapper), or
|
||||
|
|
@ -1064,7 +1097,7 @@ ctf_arc_open_internal (int fd, const char *filename, ctf_error_t *errp)
|
|||
v1 = 1;
|
||||
|
||||
ret = ctf_new_archive_internal (content, NULL, v1, close_op, s.st_size,
|
||||
NULL, NULL, errp);
|
||||
NULL, errp);
|
||||
|
||||
/* ctf_new_archive_internal cleans up on error, so shouldn't do so. */
|
||||
return ret;
|
||||
|
|
@ -1210,28 +1243,21 @@ ctf_arc_set_parent (struct ctf_archive_internal *arci, ctf_dict_t *parent)
|
|||
if non-NULL. */
|
||||
static ctf_dict_t *
|
||||
ctf_dict_open_by_offset (struct ctf_archive_internal *arci,
|
||||
const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect, size_t offset,
|
||||
size_t len, ctf_dict_t *parent,
|
||||
int little_endian_symtab, ctf_error_t *errp)
|
||||
ctf_open_sect_t *sects, size_t offset, size_t len,
|
||||
ctf_dict_t *parent, int little_endian_symtab,
|
||||
ctf_error_t *errp)
|
||||
{
|
||||
ctf_sect_t ctfsect;
|
||||
ctf_sect_t ctfsect = {0};
|
||||
ctf_dict_t *fp;
|
||||
|
||||
ctf_dprintf ("ctf_dict_open_by_offset(%zi): opening\n", offset);
|
||||
|
||||
if (symsect->cts_name == NULL)
|
||||
symsect = NULL;
|
||||
if (strsect->cts_name == NULL)
|
||||
strsect = NULL;
|
||||
|
||||
memset (&ctfsect, 0, sizeof (ctf_sect_t));
|
||||
|
||||
/* Offsets in v1 are relative to the ctfs header offset. In v2 they are
|
||||
simply file offsets. */
|
||||
if (arci->ctfi_v1_hdr)
|
||||
offset += arci->ctfi_v1_hdr->ctfs;
|
||||
|
||||
ctfsect.cts_section = CTF_ELF_SECT;
|
||||
ctfsect.cts_name = _CTF_SECTION;
|
||||
ctfsect.cts_entsize = 1;
|
||||
ctfsect.cts_data = (void *) (&arci->ctfi_archive[offset]);
|
||||
|
|
@ -1241,7 +1267,7 @@ ctf_dict_open_by_offset (struct ctf_archive_internal *arci,
|
|||
if (arci->ctfi_v1_hdr)
|
||||
ctfsect.cts_data = (void *) (&arci->ctfi_archive[offset] + sizeof (uint64_t));
|
||||
|
||||
fp = ctf_bufopen_len (&ctfsect, symsect, strsect, NULL, parent, arci,
|
||||
fp = ctf_bufopen_len (ctf_open_sect (sects, &ctfsect), NULL, parent, arci,
|
||||
0, errp);
|
||||
if (!fp)
|
||||
return NULL; /* errno is set for us. */
|
||||
|
|
@ -1285,6 +1311,8 @@ ctf_dict_open_by_index (struct ctf_archive_internal *arci, size_t index,
|
|||
{
|
||||
ctf_dict_t *fp;
|
||||
ctf_dict_t *parent = arci->ctfi_parent;
|
||||
ctf_sect_t symsect, strsect;
|
||||
ctf_sect_t *symsectp = NULL, *strsectp = NULL;
|
||||
size_t len;
|
||||
|
||||
if (index >= arci->ctfi_nmemb)
|
||||
|
|
@ -1312,8 +1340,21 @@ ctf_dict_open_by_index (struct ctf_archive_internal *arci, size_t index,
|
|||
}
|
||||
|
||||
len = ctf_arc_get_dict_len (arci, index);
|
||||
fp = ctf_dict_open_by_offset (arci, &arci->ctfi_symsect,
|
||||
&arci->ctfi_strsect,
|
||||
|
||||
/* Take a copy of the ctf_sect_t's out of the way to keep the list chaining
|
||||
done by ctf_open_sect from persisting or crossing threads unpleasantly. */
|
||||
if (arci->ctfi_symsect.cts_name != NULL)
|
||||
{
|
||||
memcpy (&symsect, &arci->ctfi_symsect, sizeof (struct ctf_sect));
|
||||
symsectp = &symsect;
|
||||
}
|
||||
if (arci->ctfi_strsect.cts_name != NULL)
|
||||
{
|
||||
memcpy (&strsect, &arci->ctfi_strsect, sizeof (struct ctf_sect));
|
||||
strsectp = &strsect;
|
||||
}
|
||||
|
||||
fp = ctf_dict_open_by_offset (arci, ctf_open_sect (ctf_open_sect (NULL, symsectp), strsectp),
|
||||
arci->ctfi_members[index], len, parent,
|
||||
arci->ctfi_symsect_little_endian, errp);
|
||||
if (fp)
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ ctf_create_internal (ctf_dict_t *parent, ctf_import_flags_t import_flags,
|
|||
|
||||
ctf_dynhash_t *structs = NULL, *unions = NULL, *enums = NULL, *names = NULL;
|
||||
ctf_dynhash_t *datasecs = NULL, *tags = NULL;
|
||||
ctf_sect_t cts;
|
||||
ctf_sect_t cts = {0};
|
||||
ctf_dict_t *fp;
|
||||
|
||||
libctf_init_debug();
|
||||
|
|
@ -222,13 +222,14 @@ ctf_create_internal (ctf_dict_t *parent, ctf_import_flags_t import_flags,
|
|||
goto err;
|
||||
}
|
||||
|
||||
cts.cts_section = CTF_ELF_SECT;
|
||||
cts.cts_name = _CTF_SECTION;
|
||||
cts.cts_data = &hdr;
|
||||
cts.cts_size = sizeof (hdr);
|
||||
cts.cts_entsize = 1;
|
||||
|
||||
if ((fp = ctf_bufopen_len (&cts, NULL, NULL, NULL, parent, NULL, import_flags
|
||||
| CTF_IMPORT_NEW, errp)) == NULL)
|
||||
if ((fp = ctf_bufopen_len (ctf_open_sect (NULL, &cts), NULL, parent, NULL,
|
||||
import_flags | CTF_IMPORT_NEW, errp)) == NULL)
|
||||
goto err;
|
||||
|
||||
/* These hashes will have been initialized with a starting size of zero,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include <errno.h>
|
||||
#include "ctf-util-port.h"
|
||||
#include <ctf-api.h>
|
||||
#include <ctf-test-api.h>
|
||||
#include "ctf-util-sha1.h"
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -888,11 +887,9 @@ extern void ctf_depreserialize (ctf_dict_t *fp);
|
|||
extern struct ctf_archive_internal *
|
||||
ctf_new_archive_internal (unsigned char *buf, ctf_dict_t *fp, int v1,
|
||||
enum arc_on_close_operation on_close, size_t len,
|
||||
const ctf_sect_t *symsect, const ctf_sect_t *strsect,
|
||||
ctf_error_t *errp);
|
||||
ctf_open_sect_t *sects, ctf_error_t *errp);
|
||||
struct ctf_archive_internal *ctf_new_archive_wrapper (ctf_dict_t *fp,
|
||||
const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect,
|
||||
ctf_open_sect_t *sects,
|
||||
ctf_error_t *errp);
|
||||
extern struct ctf_archive_internal *
|
||||
ctf_arc_open_internal (int fd, const char *filename, ctf_error_t *errp);
|
||||
|
|
@ -909,13 +906,11 @@ extern ctf_dict_t *ctf_create_internal (ctf_dict_t *parent,
|
|||
ctf_import_flags_t import_flags,
|
||||
ctf_error_t *errp);
|
||||
extern void *ctf_set_open_errno (ctf_error_t *, ctf_error_t);
|
||||
extern ssize_t ctf_buflen (const ctf_sect_t *ctfsect, ctf_error_t *errp);
|
||||
extern ssize_t ctf_buflen (ctf_open_sect_t *sects, ctf_error_t *errp);
|
||||
extern ctf_ret_t ctf_flip_header (void *, int, int, int);
|
||||
extern ctf_error_t ctf_flip (ctf_dict_t *, ctf_header_t *, unsigned char *,
|
||||
int is_btf, int to_foreign);
|
||||
extern ctf_dict_t *ctf_bufopen_len (const ctf_sect_t *ctfsect,
|
||||
const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect,
|
||||
extern ctf_dict_t *ctf_bufopen_len (ctf_open_sect_t *sects,
|
||||
ssize_t *len, ctf_dict_t *parent,
|
||||
ctf_archive_t *ctf_archive,
|
||||
ctf_import_flags_t import_flags,
|
||||
|
|
|
|||
|
|
@ -1187,7 +1187,7 @@ ctf_link_deduplicating_per_cu (ctf_dict_t *fp)
|
|||
|
||||
if ((in_arc = ctf_new_archive_internal (NULL, outputs[0], 0,
|
||||
FREE_ARCHIVE_ONLY_DICT, 0,
|
||||
NULL, NULL, &err)) == NULL)
|
||||
NULL, &err)) == NULL)
|
||||
{
|
||||
ctf_set_errno (fp, err);
|
||||
goto err_outputs;
|
||||
|
|
@ -1515,9 +1515,10 @@ ctf_link_against (ctf_dict_t *fp, ctf_archive_t *against, ctf_archive_t *dict,
|
|||
== NULL)
|
||||
return ctf_err (err_locus (fp), err, _("cannot open against-types parent dict"));
|
||||
|
||||
/* Add the sole parent, then the single child. */
|
||||
/* Add the sole parent, then the single child. The parent is never written
|
||||
out or CU-mapped, so give it a non-colliding name. */
|
||||
|
||||
if (ctf_link_add (fp, against, _CTF_SECTION, NULL) < 0)
|
||||
if (ctf_link_add (fp, against, "//@@parent@name@irrelevant//", NULL) < 0)
|
||||
return -1; /* errno is set for us. */
|
||||
|
||||
if (ctf_link_add (fp, dict, name, NULL) < 0)
|
||||
|
|
|
|||
|
|
@ -44,63 +44,42 @@ ctf_bfdclose (struct ctf_archive_internal *arci)
|
|||
bfd_errmsg (bfd_get_error ()));
|
||||
}
|
||||
|
||||
/* Open a CTF file given the specified BFD. */
|
||||
/* Open a CTF file given the specified BFD, and other sections which may
|
||||
override it (the CTF section may contain a CTF archive or a file). */
|
||||
|
||||
ctf_archive_t *
|
||||
ctf_bfdopen (struct bfd *abfd, ctf_error_t *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)
|
||||
&& ((ctf_asect = bfd_get_section_by_name (abfd, ".BTF")) == NULL))
|
||||
{
|
||||
return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
|
||||
}
|
||||
|
||||
if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents))
|
||||
{
|
||||
ctf_err (err_locus (NULL), 0, _("cannot malloc CTF section: %s"),
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
return (ctf_set_open_errno (errp, ECTF_FMT));
|
||||
}
|
||||
|
||||
ctfsect.cts_name = bfd_section_name(ctf_asect);
|
||||
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, ctf_error_t *errp)
|
||||
ctf_bfdopen (struct bfd *abfd _libctf_unused_, ctf_open_sect_t *sects, ctf_error_t *errp)
|
||||
{
|
||||
ctf_archive_t *arci;
|
||||
ctf_sect_t *sect = (ctf_sect_t *) sects;
|
||||
ctf_sect_t ctfsect = {0};
|
||||
ctf_sect_t *ctfsectp = NULL;
|
||||
ctf_sect_t *symsectp = NULL;
|
||||
ctf_sect_t *strsectp = NULL;
|
||||
const char *bfderrstr = NULL;
|
||||
char *ctf_alloc = NULL;
|
||||
char *strtab_alloc = NULL;
|
||||
int symsect_endianness = -1;
|
||||
int free_ctfsect = 0;
|
||||
|
||||
libctf_init_debug();
|
||||
|
||||
/* Extract user-passed sects. */
|
||||
|
||||
do
|
||||
{
|
||||
switch (sect->cts_section)
|
||||
{
|
||||
case CTF_ELF_SECT: ctfsectp = sect; break;
|
||||
case CTF_ELF_SYMSECT: symsectp = sect; break;
|
||||
case CTF_ELF_STRSECT: strsectp = sect; break;
|
||||
default:
|
||||
/* Unknown sections are fine, and ignored. */
|
||||
;
|
||||
}
|
||||
sect = ctf_list_next (sect);
|
||||
} while (sect);
|
||||
|
||||
#ifdef HAVE_BFD_ELF
|
||||
ctf_sect_t symsect, strsect;
|
||||
Elf_Internal_Shdr *symhdr;
|
||||
|
|
@ -113,10 +92,29 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
|
|||
size_t strsize;
|
||||
const ctf_preamble_t *preamble;
|
||||
|
||||
if (ctfsect->cts_data == NULL)
|
||||
if (!ctfsectp)
|
||||
{
|
||||
bfderrstr = N_("CTF section is NULL");
|
||||
goto err;
|
||||
asection *ctf_asect;
|
||||
bfd_byte *contents;
|
||||
|
||||
if (((ctf_asect = bfd_get_section_by_name (abfd, _CTF_SECTION)) == NULL)
|
||||
&& ((ctf_asect = bfd_get_section_by_name (abfd, ".BTF")) == NULL))
|
||||
return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
|
||||
|
||||
if (!bfd_malloc_and_get_section (abfd, ctf_asect, &contents))
|
||||
{
|
||||
bfderrstr = N_("cannot malloc CTF section");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctf_alloc = (char *) contents;
|
||||
ctfsect.cts_section = CTF_ELF_SECT;
|
||||
ctfsect.cts_name = bfd_section_name (ctf_asect);
|
||||
ctfsect.cts_entsize = 1;
|
||||
ctfsect.cts_size = bfd_section_size (ctf_asect);
|
||||
ctfsect.cts_data = contents;
|
||||
ctfsectp = &ctfsect;
|
||||
free_ctfsect = 1;
|
||||
}
|
||||
|
||||
/* v3 dicts may cite the symtab or the dynsymtab, without using sh_link to
|
||||
|
|
@ -124,11 +122,11 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
|
|||
now). */
|
||||
|
||||
errno = 0;
|
||||
preamble = ctf_arc_bufpreamble_v1 (ctfsect);
|
||||
preamble = ctf_arc_bufpreamble_v1 (ctfsectp);
|
||||
if (!preamble && errno == EOVERFLOW)
|
||||
{
|
||||
bfderrstr = N_("section too short to be CTF or BTF");
|
||||
goto err;
|
||||
goto err_free_ctf;
|
||||
}
|
||||
|
||||
if (!preamble || (preamble && preamble->ctp_flags & CTF_F_DYNSTR))
|
||||
|
|
@ -153,7 +151,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
|
|||
if ((symtab = malloc (symhdr->sh_size)) == NULL)
|
||||
{
|
||||
bfderrstr = N_("cannot malloc symbol table");
|
||||
goto err;
|
||||
goto err_free_ctf;
|
||||
}
|
||||
|
||||
isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0,
|
||||
|
|
@ -205,6 +203,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
|
|||
thrashing around digging the name out of the shstrtab given that we don't
|
||||
use it for anything but debugging. */
|
||||
|
||||
strsect.cts_section = CTF_ELF_STRSECT;
|
||||
strsect.cts_data = strtab;
|
||||
strsect.cts_name = strtab_name;
|
||||
strsect.cts_size = strsize;
|
||||
|
|
@ -214,6 +213,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
|
|||
if (symtab)
|
||||
{
|
||||
assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym);
|
||||
symsect.cts_section = CTF_ELF_SYMSECT;
|
||||
symsect.cts_name = symtab_name;
|
||||
symsect.cts_entsize = symhdr->sh_entsize;
|
||||
symsect.cts_size = symhdr->sh_size;
|
||||
|
|
@ -224,7 +224,8 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
|
|||
symsect_endianness = bfd_little_endian (abfd);
|
||||
#endif
|
||||
|
||||
arci = ctf_arc_bufopen (ctfsect, symsectp, strsectp, errp);
|
||||
arci = ctf_arc_bufopen (ctf_open_sect (ctf_open_sect (ctf_open_sect (NULL,
|
||||
ctfsectp), symsectp), strsectp), errp);
|
||||
if (arci)
|
||||
{
|
||||
/* Request freeing of the symsect and possibly the strsect. */
|
||||
|
|
@ -236,10 +237,16 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_,
|
|||
if (symsect_endianness > -1)
|
||||
ctf_arc_symsect_endianness (arci, symsect_endianness);
|
||||
|
||||
/* This frees the cts_data later. */
|
||||
if (free_ctfsect)
|
||||
arci->ctfi_data = (void *) ctfsect.cts_data;
|
||||
|
||||
/* XXX get the data model right. */
|
||||
return arci;
|
||||
}
|
||||
#ifdef HAVE_BFD_ELF
|
||||
err_free_ctf:
|
||||
free (ctf_alloc);
|
||||
err_free_sym:
|
||||
free (symtab);
|
||||
free (strtab_alloc);
|
||||
|
|
@ -328,7 +335,7 @@ ctf_fdopen (int fd, const char *filename, const char *target, ctf_error_t *errp)
|
|||
return (ctf_set_open_errno (errp, err));
|
||||
}
|
||||
|
||||
if ((arci = ctf_bfdopen (abfd, errp)) == NULL)
|
||||
if ((arci = ctf_bfdopen (abfd, NULL, errp)) == NULL)
|
||||
{
|
||||
if (!bfd_close_all_done (abfd))
|
||||
ctf_err (err_locus (NULL), 0, _("cannot close BFD: %s"),
|
||||
|
|
|
|||
|
|
@ -1720,50 +1720,33 @@ void ctf_set_ctl_hashes (ctf_dict_t *fp)
|
|||
fp->ctf_lookups[5].ctl_hash = NULL;
|
||||
}
|
||||
|
||||
/* Open a CTF file, mocking up a suitable ctf_sect. */
|
||||
/* Chain ctf_sect_t's together. No memory allocation is needed, so this
|
||||
function cannot fail and can be called in a nested fashion safely. */
|
||||
|
||||
ctf_dict_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size,
|
||||
const char *symsect, size_t symsect_size,
|
||||
size_t symsect_entsize,
|
||||
const char *strsect, size_t strsect_size,
|
||||
ctf_dict_t *parent, ctf_error_t *errp)
|
||||
ctf_open_sect_t *ctf_open_sect (ctf_open_sect_t *open_sect, ctf_sect_t *sect)
|
||||
{
|
||||
ctf_sect_t skeleton;
|
||||
/* A ctf_open_sect_t *is* a ctf_sect_t: they are layout-equivalent, but also
|
||||
they both start with a ctf_list_t. */
|
||||
|
||||
ctf_sect_t ctf_sect, sym_sect, str_sect;
|
||||
ctf_sect_t *ctfsectp = NULL;
|
||||
ctf_sect_t *symsectp = NULL;
|
||||
ctf_sect_t *strsectp = NULL;
|
||||
ctf_list_t *existing = (ctf_list_t *) open_sect;
|
||||
|
||||
skeleton.cts_name = _CTF_SECTION;
|
||||
skeleton.cts_entsize = 1;
|
||||
/* Allow the caller to pass in a NULL sect: return the passed-in sect and do
|
||||
nothing to it. (Simplifies call chains in which some members are
|
||||
optional, e.g. ctf_bfdopen). */
|
||||
|
||||
if (ctfsect)
|
||||
if (!sect)
|
||||
return (ctf_open_sect_t *) open_sect;
|
||||
|
||||
/* Allow reuse of the same section in multiple calls. */
|
||||
memset ((ctf_list_t *) sect, 0, sizeof (ctf_list_t));
|
||||
|
||||
if (open_sect)
|
||||
{
|
||||
memcpy (&ctf_sect, &skeleton, sizeof (struct ctf_sect));
|
||||
ctf_sect.cts_data = ctfsect;
|
||||
ctf_sect.cts_size = ctfsect_size;
|
||||
ctfsectp = &ctf_sect;
|
||||
ctf_list_append (existing, sect);
|
||||
return (ctf_open_sect_t *) existing;
|
||||
}
|
||||
|
||||
if (symsect)
|
||||
{
|
||||
memcpy (&sym_sect, &skeleton, sizeof (struct ctf_sect));
|
||||
sym_sect.cts_data = symsect;
|
||||
sym_sect.cts_size = symsect_size;
|
||||
sym_sect.cts_entsize = symsect_entsize;
|
||||
symsectp = &sym_sect;
|
||||
}
|
||||
|
||||
if (strsect)
|
||||
{
|
||||
memcpy (&str_sect, &skeleton, sizeof (struct ctf_sect));
|
||||
str_sect.cts_data = strsect;
|
||||
str_sect.cts_size = strsect_size;
|
||||
strsectp = &str_sect;
|
||||
}
|
||||
|
||||
return ctf_bufopen (ctfsectp, symsectp, strsectp, parent, errp);
|
||||
else
|
||||
return (ctf_open_sect_t *) sect;
|
||||
}
|
||||
|
||||
/* Decode the specified CTF or BTF buffer and optional symbol table, and create
|
||||
|
|
@ -1772,12 +1755,9 @@ ctf_dict_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size,
|
|||
ctf_open(), below. */
|
||||
|
||||
ctf_dict_t *
|
||||
ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect, ctf_dict_t *parent,
|
||||
ctf_error_t *errp)
|
||||
ctf_bufopen (ctf_open_sect_t *sects, ctf_dict_t *parent, ctf_error_t *errp)
|
||||
{
|
||||
return ctf_bufopen_len (ctfsect, symsect, strsect, NULL, parent, NULL,
|
||||
0, errp);
|
||||
return ctf_bufopen_len (sects, NULL, parent, NULL, 0, errp);
|
||||
}
|
||||
|
||||
/* Get the length of a CTF buffer, without returning it. The length includes
|
||||
|
|
@ -1785,11 +1765,11 @@ ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
|||
though will not be larger than the section size. */
|
||||
|
||||
ssize_t
|
||||
ctf_buflen (const ctf_sect_t *ctfsect, ctf_error_t *errp)
|
||||
ctf_buflen (ctf_open_sect_t *sects, ctf_error_t *errp)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
ctf_bufopen_len (ctfsect, NULL, NULL, &len, NULL, NULL, 0, errp);
|
||||
ctf_bufopen_len (sects, &len, NULL, NULL, 0, errp);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -1801,8 +1781,7 @@ ctf_buflen (const ctf_sect_t *ctfsect, ctf_error_t *errp)
|
|||
if LEN is NULL, the dict is returned in ctf_dict_t, or NULL on error. */
|
||||
|
||||
ctf_dict_t *
|
||||
ctf_bufopen_len (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
||||
const ctf_sect_t *strsect, ssize_t *len, ctf_dict_t *parent,
|
||||
ctf_bufopen_len (ctf_open_sect_t *sects, ssize_t *len, ctf_dict_t *parent,
|
||||
ctf_archive_t *ctf_archive, ctf_import_flags_t import_flags,
|
||||
ctf_error_t *errp)
|
||||
{
|
||||
|
|
@ -1817,6 +1796,8 @@ ctf_bufopen_len (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
|||
ctf_header_v3_t *header_v3 = NULL;
|
||||
ctf_dict_t *fp;
|
||||
size_t ctf_adjustment = 0;
|
||||
ctf_sect_t *sect = (ctf_sect_t *) sects;
|
||||
ctf_sect_t *ctfsect = NULL, *strsect = NULL, *symsect = NULL;
|
||||
|
||||
/* These match the CTF_VERSION definitions up to IS_BTF. */
|
||||
enum
|
||||
|
|
@ -1839,6 +1820,28 @@ ctf_bufopen_len (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
|||
|
||||
ctf_set_open_errno (errp, 0);
|
||||
|
||||
/* Figure out what sects we've got. */
|
||||
|
||||
if (sect == NULL)
|
||||
return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
|
||||
|
||||
do
|
||||
{
|
||||
switch (sect->cts_section)
|
||||
{
|
||||
case CTF_ELF_SECT: ctfsect = sect; break;
|
||||
case CTF_ELF_SYMSECT: symsect = sect; break;
|
||||
case CTF_ELF_STRSECT: strsect = sect; break;
|
||||
default:
|
||||
/* Unknown sections are fine, and ignored. */
|
||||
;
|
||||
}
|
||||
sect = ctf_list_next (sect);
|
||||
} while (sect);
|
||||
|
||||
if (ctfsect == NULL)
|
||||
return (ctf_set_open_errno (errp, ECTF_NOCTFDATA));
|
||||
|
||||
ctf_dprintf ("ctf_bufopen %zi+%zi+%zi bytes: validating\n",
|
||||
ctfsect ? ctfsect->cts_size : 0,
|
||||
symsect ? symsect->cts_size : 0,
|
||||
|
|
@ -2451,10 +2454,10 @@ ctf_bufopen_len (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
|||
memcpy (&fp->ctf_data, ctfsect, sizeof (ctf_sect_t));
|
||||
|
||||
if (symsect != NULL)
|
||||
{
|
||||
memcpy (&fp->ctf_ext_symtab, symsect, sizeof (ctf_sect_t));
|
||||
memcpy (&fp->ctf_ext_strtab, strsect, sizeof (ctf_sect_t));
|
||||
}
|
||||
memcpy (&fp->ctf_ext_symtab, symsect, sizeof (ctf_sect_t));
|
||||
|
||||
if (strsect != NULL)
|
||||
memcpy (&fp->ctf_ext_strtab, strsect, sizeof (ctf_sect_t));
|
||||
|
||||
if (fp->ctf_data.cts_name != NULL)
|
||||
if ((fp->ctf_data.cts_name = strdup (fp->ctf_data.cts_name)) == NULL)
|
||||
|
|
@ -2796,6 +2799,8 @@ ctf_archive_t *
|
|||
ctf_dict_arc (ctf_dict_t *fp, int flags)
|
||||
{
|
||||
struct ctf_archive_internal *arci;
|
||||
ctf_sect_t symsect, strsect;
|
||||
ctf_sect_t *symsectp = NULL, *strsectp = NULL;
|
||||
ctf_error_t err;
|
||||
|
||||
if (fp->ctf_archive)
|
||||
|
|
@ -2808,8 +2813,21 @@ ctf_dict_arc (ctf_dict_t *fp, int flags)
|
|||
if (flags & CTF_DICT_ARC_ORIGINAL)
|
||||
return NULL;
|
||||
|
||||
if ((arci = ctf_new_archive_wrapper (fp, &fp->ctf_ext_symtab,
|
||||
&fp->ctf_ext_strtab, &err)) == NULL)
|
||||
/* Take a copy of the ctf_sect_t's out of the way to keep the list chaining
|
||||
done by ctf_open_sect from persisting or crossing threads unpleasantly. */
|
||||
if (fp->ctf_ext_symtab.cts_name != NULL)
|
||||
{
|
||||
memcpy (&symsect, &fp->ctf_ext_symtab, sizeof (struct ctf_sect));
|
||||
symsectp = &symsect;
|
||||
}
|
||||
if (fp->ctf_ext_symtab.cts_name != NULL)
|
||||
{
|
||||
memcpy (&strsect, &fp->ctf_ext_symtab, sizeof (struct ctf_sect));
|
||||
strsectp = &strsect;
|
||||
}
|
||||
|
||||
if ((arci = ctf_new_archive_wrapper (fp, ctf_open_sect (ctf_open_sect (NULL, symsectp), strsectp),
|
||||
&err)) == NULL)
|
||||
{
|
||||
ctf_set_errno (fp, err);
|
||||
return NULL;
|
||||
|
|
@ -2829,7 +2847,7 @@ ctf_dict_arc (ctf_dict_t *fp, int flags)
|
|||
ctf_sect_t
|
||||
ctf_elf_sect (const ctf_dict_t *fp, ctf_elfsect_names_t sect)
|
||||
{
|
||||
ctf_sect_t error = { "ERROR", NULL, 0, 0 };
|
||||
ctf_sect_t error = { {0}, 0, "ERROR", NULL, 0, 0 };
|
||||
|
||||
switch (sect)
|
||||
{
|
||||
|
|
@ -2840,6 +2858,7 @@ ctf_elf_sect (const ctf_dict_t *fp, ctf_elfsect_names_t sect)
|
|||
case CTF_ELF_STRSECT:
|
||||
return fp->ctf_ext_strtab;
|
||||
default:
|
||||
error.cts_section = sect;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ LIBCTF_2.0 {
|
|||
|
||||
ctf_dict_open;
|
||||
ctf_dict_open_by_index;
|
||||
ctf_open_sect;
|
||||
ctf_bufopen;
|
||||
ctf_simple_open;
|
||||
ctf_create;
|
||||
ctf_close;
|
||||
ctf_dict_close;
|
||||
|
|
@ -34,7 +34,6 @@ LIBCTF_2.0 {
|
|||
ctf_dict_parent;
|
||||
ctf_type_isparent;
|
||||
|
||||
|
||||
ctf_dict_set_model;
|
||||
ctf_dict_model;
|
||||
|
||||
|
|
@ -180,7 +179,6 @@ LIBCTF_2.0 {
|
|||
ctf_open; /* libctf only. */
|
||||
ctf_arc_open; /* libctf only. */
|
||||
ctf_bfdopen; /* libctf only. */
|
||||
ctf_bfdopen_ctfsect; /* libctf only. */
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctf-test-api.h>
|
||||
#include <ctf-api.h>
|
||||
#include <ctf.h>
|
||||
|
||||
#ifdef HAVE_VALGRIND_VALGRIND_H
|
||||
|
|
@ -105,6 +105,7 @@ void free (void *ptr)
|
|||
int main (void)
|
||||
{
|
||||
ctf_dict_t *fp;
|
||||
ctf_sect_t sect = {0};
|
||||
ctf_encoding_t e = { CTF_INT_SIGNED, 0, sizeof (long) };
|
||||
int err;
|
||||
ctf_id_t type;
|
||||
|
|
@ -156,8 +157,13 @@ int main (void)
|
|||
malloc_count = 0;
|
||||
free_count = 0;
|
||||
|
||||
if ((ctf_simple_open (written, written_size, NULL, 0, 0, NULL, 0,
|
||||
NULL, &err)) != NULL)
|
||||
sect.cts_section = CTF_ELF_SECT;
|
||||
sect.cts_name = ".ctf";
|
||||
sect.cts_entsize = 1;
|
||||
sect.cts_size = written_size;
|
||||
sect.cts_data = written;
|
||||
|
||||
if ((ctf_bufopen (ctf_open_sect (NULL, §), NULL, &err)) != NULL)
|
||||
{
|
||||
fprintf (stderr, "wildly corrupted dict still opened OK?!\n");
|
||||
exit (1);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,26 @@
|
|||
/* Test parent / child ID assignment. */
|
||||
|
||||
#include <ctf-test-api.h>
|
||||
#include <ctf-api.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Make a ctfsect suitable for ctf_bfdopen(). */
|
||||
static ctf_sect_t
|
||||
make_ctfsect (const char *name, bfd_byte *data, bfd_size_type size)
|
||||
{
|
||||
ctf_sect_t ctfsect = {0};
|
||||
|
||||
ctfsect.cts_section = CTF_ELF_SECT;
|
||||
ctfsect.cts_name = name;
|
||||
ctfsect.cts_entsize = 1;
|
||||
ctfsect.cts_size = size;
|
||||
ctfsect.cts_data = data;
|
||||
|
||||
return ctfsect;
|
||||
}
|
||||
|
||||
int
|
||||
test (int empty_parent, int unserialized_parent)
|
||||
{
|
||||
|
|
@ -47,7 +62,8 @@ test (int empty_parent, int unserialized_parent)
|
|||
|
||||
ctf_dict_close (parent);
|
||||
|
||||
if ((parent = ctf_simple_open ((char *) pbuf, psize, NULL, 0, 0, NULL, 0, NULL, &err)) == NULL)
|
||||
if ((parent = ctf_bufopen (ctf_open_sect (NULL, make_ctfsect (".ctf", (char *) pbuf, psize)),
|
||||
NULL, &err)) == NULL)
|
||||
goto parent_open_err;
|
||||
|
||||
if (!empty_parent)
|
||||
|
|
@ -201,12 +217,12 @@ test (int empty_parent, int unserialized_parent)
|
|||
free (pbuf);
|
||||
free (cbuf);
|
||||
|
||||
if ((parent = ctf_simple_open ((char *) pbuf2, psize, NULL, 0, 0, NULL, 0,
|
||||
NULL, &err)) == NULL)
|
||||
if ((parent = ctf_bufopen (ctf_open_sect (NULL, make_ctfsect ((char *) pbuf2, psize)),
|
||||
NULL, &err)) == NULL)
|
||||
goto parent_open_err;
|
||||
|
||||
if ((child = ctf_simple_open ((char *) cbuf2, csize, NULL, 0, 0, NULL,
|
||||
0, parent, &err)) == NULL)
|
||||
if ((child = ctf_bufopen (ctf_open_sect (NULL, make_ctfsect ((char *) cbuf2, csize)),
|
||||
parent, &err)) == NULL)
|
||||
goto child_open_err;
|
||||
|
||||
if (!empty_parent)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
int bitfieldery (int count, int up, int pos)
|
||||
{
|
||||
unsigned char *ctf_written;
|
||||
ctf_sect_t sect = {0};
|
||||
size_t size;
|
||||
ctf_dict_t *dict;
|
||||
const char *err = "opening";
|
||||
|
|
@ -72,8 +73,15 @@ int bitfieldery (int count, int up, int pos)
|
|||
ctf_dict_close (dict);
|
||||
|
||||
err = "opening";
|
||||
if ((dict = ctf_simple_open ((char *) ctf_written, size, NULL, 0,
|
||||
0, NULL, 0, NULL, &open_err)) == NULL)
|
||||
|
||||
sect.cts_section = CTF_ELF_SECT;
|
||||
sect.cts_name = ".ctf";
|
||||
sect.cts_entsize = 1;
|
||||
sect.cts_size = size;
|
||||
sect.cts_data = (char *) ctf_written;
|
||||
|
||||
if ((dict = ctf_bufopen (ctf_open_sect (NULL, §), NULL,
|
||||
&open_err)) == NULL)
|
||||
goto open_err;
|
||||
|
||||
err = "looking up";
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ try_maybe_reporting (int report)
|
|||
ctf_dict_t *fp;
|
||||
ctf_id_t func, func2, func3, base, base2, base3;
|
||||
ctf_encoding_t e = { CTF_INT_SIGNED, 0, sizeof (long) };
|
||||
ctf_sect_t sect = {0};
|
||||
ctf_id_t dummy = 0;
|
||||
ctf_next_t *i = NULL;
|
||||
ctf_id_t symtype;
|
||||
|
|
@ -167,8 +168,14 @@ try_maybe_reporting (int report)
|
|||
ctf_file_close (fp);
|
||||
|
||||
/* Read back in. */
|
||||
if ((fp = ctf_simple_open ((const char *) buf, bufsiz, NULL, 0, 0, NULL,
|
||||
0, NULL, &err)) == NULL)
|
||||
|
||||
sect.cts_section = CTF_ELF_SECT;
|
||||
sect.cts_name = ".ctf";
|
||||
sect.cts_entsize = 1;
|
||||
sect.cts_size = bufsize;
|
||||
sect.cts_data = (char *) buf;
|
||||
|
||||
if ((fp = ctf_bufopen (ctf_open_sect (NULL, §), NULL, &err)) == NULL)
|
||||
goto open_err;
|
||||
|
||||
/* Verify symbol order against the order we expect if this dict is sorted and
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue