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:
Nick Alcock 2026-05-18 16:51:35 +01:00
parent dcbcb6a0b3
commit 5532fbca2e
19 changed files with 361 additions and 272 deletions

View file

@ -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));

View file

@ -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));

View file

@ -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));

View file

@ -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 *);

View file

@ -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 */

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

@ -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"),

View file

@ -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;
}
}

View file

@ -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:
*;
};

View file

@ -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, &sect), NULL, &err)) != NULL)
{
fprintf (stderr, "wildly corrupted dict still opened OK?!\n");
exit (1);

View file

@ -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)

View file

@ -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, &sect), NULL,
&open_err)) == NULL)
goto open_err;
err = "looking up";

View file

@ -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, &sect), NULL, &err)) == NULL)
goto open_err;
/* Verify symbol order against the order we expect if this dict is sorted and