libctf: creation functions

The CTF creation process looks roughly like (error handling elided):

int err;
ctf_file_t *foo = ctf_create (&err);

ctf_id_t type = ctf_add_THING (foo, ...);
ctf_update (foo);
ctf_*write (...);

Some ctf_add_THING functions accept other type IDs as arguments,
depending on the type: cv-quals, pointers, and structure and union
members all take other types as arguments.  So do 'slices', which
let you take an existing integral type and recast it as a type
with a different bitness or offset within a byte, for bitfields.
One class of THING is not a type: "variables", which are mappings
of names (in the internal string table) to types.  These are mostly
useful when encoding variables that do not appear in a symbol table
but which some external user has some other way to figure out the
address of at runtime (dynamic symbol lookup or querying a VM
interpreter or something).

You can snapshot the creation process at any point: rolling back to a
snapshot deletes all types and variables added since that point.

You can make arbitrary type queries on the CTF container during the
creation process, but you must call ctf_update() first, which
translates the growing dynamic container into a static one (this uses
the CTF opening machinery, added in a later commit), which is quite
expensive.  This function must also be called after adding types
and before writing the container out.

Because addition of types involves looking up existing types, we add a
little of the type lookup machinery here, as well: only enough to
look up types in dynamic containers under construction.

libctf/
	* ctf-create.c: New file.
	* ctf-lookup.c: New file.

include/
	* ctf-api.h (zlib.h): New include.
	(ctf_sect_t): New.
	(ctf_sect_names_t): Likewise.
	(ctf_encoding_t): Likewise.
	(ctf_membinfo_t): Likewise.
	(ctf_arinfo_t): Likewise.
	(ctf_funcinfo_t): Likewise.
	(ctf_lblinfo_t): Likewise.
	(ctf_snapshot_id_t): Likewise.
	(CTF_FUNC_VARARG): Likewise.
	(ctf_simple_open): Likewise.
	(ctf_bufopen): Likewise.
	(ctf_create): Likewise.
	(ctf_add_array): Likewise.
	(ctf_add_const): Likewise.
	(ctf_add_enum_encoded): Likewise.
	(ctf_add_enum): Likewise.
	(ctf_add_float): Likewise.
	(ctf_add_forward): Likewise.
	(ctf_add_function): Likewise.
	(ctf_add_integer): Likewise.
	(ctf_add_slice): Likewise.
	(ctf_add_pointer): Likewise.
	(ctf_add_type): Likewise.
	(ctf_add_typedef): Likewise.
	(ctf_add_restrict): Likewise.
	(ctf_add_struct): Likewise.
	(ctf_add_union): Likewise.
	(ctf_add_struct_sized): Likewise.
	(ctf_add_union_sized): Likewise.
	(ctf_add_volatile): Likewise.
	(ctf_add_enumerator): Likewise.
	(ctf_add_member): Likewise.
	(ctf_add_member_offset): Likewise.
	(ctf_add_member_encoded): Likewise.
	(ctf_add_variable): Likewise.
	(ctf_set_array): Likewise.
	(ctf_update): Likewise.
	(ctf_snapshot): Likewise.
	(ctf_rollback): Likewise.
	(ctf_discard): Likewise.
	(ctf_write): Likewise.
	(ctf_gzwrite): Likewise.
	(ctf_compress_write): Likewise.
This commit is contained in:
Nick Alcock 2019-04-23 22:45:46 +01:00
parent a5be9bbe89
commit 47d546f427
5 changed files with 1791 additions and 0 deletions

View File

@ -1,3 +1,50 @@
2019-05-28 Nick Alcock <nick.alcock@oracle.com>
* ctf-api.h (zlib.h): New include.
(ctf_sect_t): New.
(ctf_sect_names_t): Likewise.
(ctf_encoding_t): Likewise.
(ctf_membinfo_t): Likewise.
(ctf_arinfo_t): Likewise.
(ctf_funcinfo_t): Likewise.
(ctf_lblinfo_t): Likewise.
(ctf_snapshot_id_t): Likewise.
(CTF_FUNC_VARARG): Likewise.
(ctf_simple_open): Likewise.
(ctf_bufopen): Likewise.
(ctf_create): Likewise.
(ctf_add_array): Likewise.
(ctf_add_const): Likewise.
(ctf_add_enum_encoded): Likewise.
(ctf_add_enum): Likewise.
(ctf_add_float): Likewise.
(ctf_add_forward): Likewise.
(ctf_add_function): Likewise.
(ctf_add_integer): Likewise.
(ctf_add_slice): Likewise.
(ctf_add_pointer): Likewise.
(ctf_add_type): Likewise.
(ctf_add_typedef): Likewise.
(ctf_add_restrict): Likewise.
(ctf_add_struct): Likewise.
(ctf_add_union): Likewise.
(ctf_add_struct_sized): Likewise.
(ctf_add_union_sized): Likewise.
(ctf_add_volatile): Likewise.
(ctf_add_enumerator): Likewise.
(ctf_add_member): Likewise.
(ctf_add_member_offset): Likewise.
(ctf_add_member_encoded): Likewise.
(ctf_add_variable): Likewise.
(ctf_set_array): Likewise.
(ctf_update): Likewise.
(ctf_snapshot): Likewise.
(ctf_rollback): Likewise.
(ctf_discard): Likewise.
(ctf_write): Likewise.
(ctf_gzwrite): Likewise.
(ctf_compress_write): Likewise.
2019-05-28 Nick Alcock <nick.alcock@oracle.com>
* ctf-api.h (ctf_errno): New declaration.

View File

@ -27,6 +27,7 @@
#include <sys/param.h>
#include <sys/types.h>
#include <ctf.h>
#include <zlib.h>
#ifdef __cplusplus
extern "C"
@ -44,6 +45,81 @@ typedef struct ctf_file ctf_file_t;
typedef struct ctf_archive_internal ctf_archive_t;
typedef long ctf_id_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().
The contents of this structure must always be in native endianness (no
byteswapping is performed). */
typedef struct ctf_sect
{
const char *cts_name; /* Section name (if any). */
unsigned long cts_type; /* Section type (ELF SHT_... value). */
unsigned long cts_flags; /* Section flags (ELF SHF_... value). */
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). */
off64_t cts_offset; /* File offset of this section (if any). */
} ctf_sect_t;
/* Symbolic names for CTF sections. */
typedef enum ctf_sect_names
{
CTF_SECT_HEADER,
CTF_SECT_LABEL,
CTF_SECT_OBJT,
CTF_SECT_FUNC,
CTF_SECT_VAR,
CTF_SECT_TYPE,
CTF_SECT_STR
} ctf_sect_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>. */
typedef struct ctf_encoding
{
uint32_t cte_format; /* Data format (CTF_INT_* or CTF_FP_* flags). */
uint32_t cte_offset; /* Offset of value in bits. */
uint32_t cte_bits; /* Size of storage in bits. */
} ctf_encoding_t;
typedef struct ctf_membinfo
{
ctf_id_t ctm_type; /* Type of struct or union member. */
unsigned long ctm_offset; /* Offset of member in bits. */
} ctf_membinfo_t;
typedef struct ctf_arinfo
{
ctf_id_t ctr_contents; /* Type of array contents. */
ctf_id_t ctr_index; /* Type of array index. */
uint32_t ctr_nelems; /* Number of elements. */
} ctf_arinfo_t;
typedef struct ctf_funcinfo
{
ctf_id_t ctc_return; /* Function return type. */
uint32_t ctc_argc; /* Number of typed arguments to function. */
uint32_t ctc_flags; /* Function attributes (see below). */
} ctf_funcinfo_t;
typedef struct ctf_lblinfo
{
ctf_id_t ctb_type; /* Last type associated with the label. */
} ctf_lblinfo_t;
typedef struct ctf_snapshot_id
{
unsigned long dtd_id; /* Highest DTD ID at time of snapshot. */
unsigned long snapshot_id; /* Snapshot id at time of snapshot. */
} ctf_snapshot_id_t;
#define CTF_FUNC_VARARG 0x1 /* Function arguments end with varargs. */
/* Functions that return integer status or a ctf_id_t use the following value
to indicate failure. ctf_errno() can be used to obtain an error code. */
#define CTF_ERR (-1L)
@ -122,8 +198,61 @@ enum
#define CTF_ADD_NONROOT 0 /* Type only visible in nested scope. */
#define CTF_ADD_ROOT 1 /* Type visible at top-level scope. */
extern ctf_file_t *ctf_simple_open (const char *, size_t, const char *, size_t,
size_t, const char *, size_t, int *);
extern ctf_file_t *ctf_bufopen (const ctf_sect_t *, const ctf_sect_t *,
const ctf_sect_t *, int *);
extern int ctf_errno (ctf_file_t *);
extern const char *ctf_errmsg (int);
extern ctf_id_t ctf_add_array (ctf_file_t *, uint32_t,
const ctf_arinfo_t *);
extern ctf_id_t ctf_add_const (ctf_file_t *, uint32_t, ctf_id_t);
extern ctf_id_t ctf_add_enum_encoded (ctf_file_t *, uint32_t, const char *,
const ctf_encoding_t *);
extern ctf_id_t ctf_add_enum (ctf_file_t *, uint32_t, const char *);
extern ctf_id_t ctf_add_float (ctf_file_t *, uint32_t,
const char *, const ctf_encoding_t *);
extern ctf_id_t ctf_add_forward (ctf_file_t *, uint32_t, const char *,
uint32_t);
extern ctf_id_t ctf_add_function (ctf_file_t *, uint32_t,
const ctf_funcinfo_t *, const ctf_id_t *);
extern ctf_id_t ctf_add_integer (ctf_file_t *, uint32_t, const char *,
const ctf_encoding_t *);
extern ctf_id_t ctf_add_slice (ctf_file_t *, uint32_t, ctf_id_t, const ctf_encoding_t *);
extern ctf_id_t ctf_add_pointer (ctf_file_t *, uint32_t, ctf_id_t);
extern ctf_id_t ctf_add_type (ctf_file_t *, ctf_file_t *, ctf_id_t);
extern ctf_id_t ctf_add_typedef (ctf_file_t *, uint32_t, const char *,
ctf_id_t);
extern ctf_id_t ctf_add_restrict (ctf_file_t *, uint32_t, ctf_id_t);
extern ctf_id_t ctf_add_struct (ctf_file_t *, uint32_t, const char *);
extern ctf_id_t ctf_add_union (ctf_file_t *, uint32_t, const char *);
extern ctf_id_t ctf_add_struct_sized (ctf_file_t *, uint32_t, const char *,
size_t);
extern ctf_id_t ctf_add_union_sized (ctf_file_t *, uint32_t, const char *,
size_t);
extern ctf_id_t ctf_add_volatile (ctf_file_t *, uint32_t, ctf_id_t);
extern int ctf_add_enumerator (ctf_file_t *, ctf_id_t, const char *, int);
extern int ctf_add_member (ctf_file_t *, ctf_id_t, const char *, ctf_id_t);
extern int ctf_add_member_offset (ctf_file_t *, ctf_id_t, const char *,
ctf_id_t, unsigned long);
extern int ctf_add_member_encoded (ctf_file_t *, ctf_id_t, const char *,
ctf_id_t, unsigned long,
const ctf_encoding_t);
extern int ctf_add_variable (ctf_file_t *, const char *, ctf_id_t);
extern int ctf_set_array (ctf_file_t *, ctf_id_t, const ctf_arinfo_t *);
extern ctf_file_t *ctf_create (int *);
extern int ctf_update (ctf_file_t *);
extern ctf_snapshot_id_t ctf_snapshot (ctf_file_t *);
extern int ctf_rollback (ctf_file_t *, ctf_snapshot_id_t);
extern int ctf_discard (ctf_file_t *);
extern int ctf_write (ctf_file_t *, int);
extern int ctf_gzwrite (ctf_file_t * fp, gzFile fd);
extern int ctf_compress_write (ctf_file_t * fp, int fd);
extern void ctf_setdebug (int debug);
extern int ctf_getdebug (void);

View File

@ -1,3 +1,8 @@
2019-05-28 Nick Alcock <nick.alcock@oracle.com>
* ctf-create.c: New file.
* ctf-lookup.c: New file.
2019-05-28 Nick Alcock <nick.alcock@oracle.com>
* ctf-impl.h: New definitions and declarations for type creation

1547
libctf/ctf-create.c Normal file

File diff suppressed because it is too large Load Diff

63
libctf/ctf-lookup.c Normal file
View File

@ -0,0 +1,63 @@
/* Type lookup.
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of libctf.
libctf is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not see
<http://www.gnu.org/licenses/>. */
#include <ctf-impl.h>
#include <elf.h>
#include <string.h>
/* Return the pointer to the internal CTF type data corresponding to the
given type ID. If the ID is invalid, the function returns NULL.
This function is not exported outside of the library. */
const ctf_type_t *
ctf_lookup_by_id (ctf_file_t **fpp, ctf_id_t type)
{
ctf_file_t *fp = *fpp; /* Caller passes in starting CTF container. */
ctf_id_t idx;
if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type)
&& (fp = fp->ctf_parent) == NULL)
{
(void) ctf_set_errno (*fpp, ECTF_NOPARENT);
return NULL;
}
idx = LCTF_TYPE_TO_INDEX (fp, type);
if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
{
*fpp = fp; /* Function returns ending CTF container. */
return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
}
/* If this container is writable, check for a dynamic type. */
if (fp->ctf_flags & LCTF_RDWR)
{
ctf_dtdef_t *dtd;
if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
{
*fpp = fp;
return &dtd->dtd_data;
}
}
(void) ctf_set_errno (*fpp, ECTF_BADID);
return NULL;
}