1178525Sjb/* 2178525Sjb * CDDL HEADER START 3178525Sjb * 4178525Sjb * The contents of this file are subject to the terms of the 5178525Sjb * Common Development and Distribution License, Version 1.0 only 6178525Sjb * (the "License"). You may not use this file except in compliance 7178525Sjb * with the License. 8178525Sjb * 9178525Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10178525Sjb * or http://www.opensolaris.org/os/licensing. 11178525Sjb * See the License for the specific language governing permissions 12178525Sjb * and limitations under the License. 13178525Sjb * 14178525Sjb * When distributing Covered Code, include this CDDL HEADER in each 15178525Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16178525Sjb * If applicable, add the following below this CDDL HEADER, with the 17178525Sjb * fields enclosed by brackets "[]" replaced with your own identifying 18178525Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 19178525Sjb * 20178525Sjb * CDDL HEADER END 21178525Sjb */ 22178525Sjb 23178525Sjb/* 24178525Sjb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25178525Sjb * Use is subject to license terms. 26178525Sjb */ 27254744Sdelphij/* 28254744Sdelphij * Copyright (c) 2012, Joyent, Inc. All rights reserved. 29254744Sdelphij */ 30178525Sjb 31178525Sjb#ifndef _CTF_IMPL_H 32178525Sjb#define _CTF_IMPL_H 33178525Sjb 34178525Sjb#include <sys/types.h> 35178525Sjb#include <sys/errno.h> 36178525Sjb#include <sys/sysmacros.h> 37178525Sjb#include <sys/ctf_api.h> 38178525Sjb 39178525Sjb#ifdef _KERNEL 40178525Sjb 41178525Sjb#include <sys/systm.h> 42178525Sjb#include <sys/cmn_err.h> 43178525Sjb#include <sys/varargs.h> 44178525Sjb 45178525Sjb#define isspace(c) \ 46178525Sjb ((c) == ' ' || (c) == '\t' || (c) == '\n' || \ 47178525Sjb (c) == '\r' || (c) == '\f' || (c) == '\v') 48178525Sjb 49178525Sjb#define MAP_FAILED ((void *)-1) 50178525Sjb 51178525Sjb#else /* _KERNEL */ 52178525Sjb 53178525Sjb#include <strings.h> 54178525Sjb#include <stdlib.h> 55178525Sjb#include <stdarg.h> 56178525Sjb#include <stdio.h> 57178525Sjb#include <limits.h> 58178525Sjb#include <ctype.h> 59178525Sjb 60178525Sjb#endif /* _KERNEL */ 61178525Sjb 62178525Sjb#ifdef __cplusplus 63178525Sjbextern "C" { 64178525Sjb#endif 65178525Sjb 66178525Sjbtypedef struct ctf_helem { 67178525Sjb uint_t h_name; /* reference to name in string table */ 68178525Sjb ushort_t h_type; /* corresponding type ID number */ 69178525Sjb ushort_t h_next; /* index of next element in hash chain */ 70178525Sjb} ctf_helem_t; 71178525Sjb 72178525Sjbtypedef struct ctf_hash { 73178525Sjb ushort_t *h_buckets; /* hash bucket array (chain indices) */ 74178525Sjb ctf_helem_t *h_chains; /* hash chains buffer */ 75178525Sjb ushort_t h_nbuckets; /* number of elements in bucket array */ 76178525Sjb ushort_t h_nelems; /* number of elements in hash table */ 77178525Sjb uint_t h_free; /* index of next free hash element */ 78178525Sjb} ctf_hash_t; 79178525Sjb 80178525Sjbtypedef struct ctf_strs { 81178525Sjb const char *cts_strs; /* base address of string table */ 82178525Sjb size_t cts_len; /* size of string table in bytes */ 83178525Sjb} ctf_strs_t; 84178525Sjb 85178525Sjbtypedef struct ctf_dmodel { 86178525Sjb const char *ctd_name; /* data model name */ 87178525Sjb int ctd_code; /* data model code */ 88178525Sjb size_t ctd_pointer; /* size of void * in bytes */ 89178525Sjb size_t ctd_char; /* size of char in bytes */ 90178525Sjb size_t ctd_short; /* size of short in bytes */ 91178525Sjb size_t ctd_int; /* size of int in bytes */ 92178525Sjb size_t ctd_long; /* size of long in bytes */ 93178525Sjb} ctf_dmodel_t; 94178525Sjb 95178525Sjbtypedef struct ctf_lookup { 96178525Sjb const char *ctl_prefix; /* string prefix for this lookup */ 97178525Sjb size_t ctl_len; /* length of prefix string in bytes */ 98178525Sjb ctf_hash_t *ctl_hash; /* pointer to hash table for lookup */ 99178525Sjb} ctf_lookup_t; 100178525Sjb 101178525Sjbtypedef struct ctf_fileops { 102178525Sjb ushort_t (*ctfo_get_kind)(ushort_t); 103178525Sjb ushort_t (*ctfo_get_root)(ushort_t); 104178525Sjb ushort_t (*ctfo_get_vlen)(ushort_t); 105178525Sjb} ctf_fileops_t; 106178525Sjb 107178525Sjbtypedef struct ctf_list { 108178525Sjb struct ctf_list *l_prev; /* previous pointer or tail pointer */ 109178525Sjb struct ctf_list *l_next; /* next pointer or head pointer */ 110178525Sjb} ctf_list_t; 111178525Sjb 112178525Sjbtypedef enum { 113178525Sjb CTF_PREC_BASE, 114178525Sjb CTF_PREC_POINTER, 115178525Sjb CTF_PREC_ARRAY, 116178525Sjb CTF_PREC_FUNCTION, 117178525Sjb CTF_PREC_MAX 118178525Sjb} ctf_decl_prec_t; 119178525Sjb 120178525Sjbtypedef struct ctf_decl_node { 121178525Sjb ctf_list_t cd_list; /* linked list pointers */ 122178525Sjb ctf_id_t cd_type; /* type identifier */ 123178525Sjb uint_t cd_kind; /* type kind */ 124178525Sjb uint_t cd_n; /* type dimension if array */ 125178525Sjb} ctf_decl_node_t; 126178525Sjb 127178525Sjbtypedef struct ctf_decl { 128178525Sjb ctf_list_t cd_nodes[CTF_PREC_MAX]; /* declaration node stacks */ 129178525Sjb int cd_order[CTF_PREC_MAX]; /* storage order of decls */ 130178525Sjb ctf_decl_prec_t cd_qualp; /* qualifier precision */ 131178525Sjb ctf_decl_prec_t cd_ordp; /* ordered precision */ 132178525Sjb char *cd_buf; /* buffer for output */ 133178525Sjb char *cd_ptr; /* buffer location */ 134178525Sjb char *cd_end; /* buffer limit */ 135178525Sjb size_t cd_len; /* buffer space required */ 136178525Sjb int cd_err; /* saved error value */ 137178525Sjb} ctf_decl_t; 138178525Sjb 139178525Sjbtypedef struct ctf_dmdef { 140178525Sjb ctf_list_t dmd_list; /* list forward/back pointers */ 141178525Sjb char *dmd_name; /* name of this member */ 142178525Sjb ctf_id_t dmd_type; /* type of this member (for sou) */ 143178525Sjb ulong_t dmd_offset; /* offset of this member in bits (for sou) */ 144178525Sjb int dmd_value; /* value of this member (for enum) */ 145178525Sjb} ctf_dmdef_t; 146178525Sjb 147178525Sjbtypedef struct ctf_dtdef { 148178525Sjb ctf_list_t dtd_list; /* list forward/back pointers */ 149178525Sjb struct ctf_dtdef *dtd_hash; /* hash chain pointer for ctf_dthash */ 150178525Sjb char *dtd_name; /* name associated with definition (if any) */ 151178525Sjb ctf_id_t dtd_type; /* type identifier for this definition */ 152178525Sjb ctf_type_t dtd_data; /* type node (see <sys/ctf.h>) */ 153254744Sdelphij int dtd_ref; /* recfount for dyanmic types */ 154178525Sjb union { 155178525Sjb ctf_list_t dtu_members; /* struct, union, or enum */ 156178525Sjb ctf_arinfo_t dtu_arr; /* array */ 157178525Sjb ctf_encoding_t dtu_enc; /* integer or float */ 158178525Sjb ctf_id_t *dtu_argv; /* function */ 159178525Sjb } dtd_u; 160178525Sjb} ctf_dtdef_t; 161178525Sjb 162178525Sjbtypedef struct ctf_bundle { 163178525Sjb ctf_file_t *ctb_file; /* CTF container handle */ 164178525Sjb ctf_id_t ctb_type; /* CTF type identifier */ 165178525Sjb ctf_dtdef_t *ctb_dtd; /* CTF dynamic type definition (if any) */ 166178525Sjb} ctf_bundle_t; 167178525Sjb 168178525Sjb/* 169178525Sjb * The ctf_file is the structure used to represent a CTF container to library 170178525Sjb * clients, who see it only as an opaque pointer. Modifications can therefore 171178525Sjb * be made freely to this structure without regard to client versioning. The 172178525Sjb * ctf_file_t typedef appears in <sys/ctf_api.h> and declares a forward tag. 173178525Sjb * 174178525Sjb * NOTE: ctf_update() requires that everything inside of ctf_file either be an 175178525Sjb * immediate value, a pointer to dynamically allocated data *outside* of the 176178525Sjb * ctf_file itself, or a pointer to statically allocated data. If you add a 177178525Sjb * pointer to ctf_file that points to something within the ctf_file itself, 178178525Sjb * you must make corresponding changes to ctf_update(). 179178525Sjb */ 180178525Sjbstruct ctf_file { 181178525Sjb const ctf_fileops_t *ctf_fileops; /* version-specific file operations */ 182178525Sjb ctf_sect_t ctf_data; /* CTF data from object file */ 183178525Sjb ctf_sect_t ctf_symtab; /* symbol table from object file */ 184178525Sjb ctf_sect_t ctf_strtab; /* string table from object file */ 185178525Sjb ctf_hash_t ctf_structs; /* hash table of struct types */ 186178525Sjb ctf_hash_t ctf_unions; /* hash table of union types */ 187178525Sjb ctf_hash_t ctf_enums; /* hash table of enum types */ 188178525Sjb ctf_hash_t ctf_names; /* hash table of remaining type names */ 189178525Sjb ctf_lookup_t ctf_lookups[5]; /* pointers to hashes for name lookup */ 190178525Sjb ctf_strs_t ctf_str[2]; /* array of string table base and bounds */ 191178525Sjb const uchar_t *ctf_base; /* base of CTF header + uncompressed buffer */ 192178525Sjb const uchar_t *ctf_buf; /* uncompressed CTF data buffer */ 193178525Sjb size_t ctf_size; /* size of CTF header + uncompressed data */ 194178525Sjb uint_t *ctf_sxlate; /* translation table for symtab entries */ 195178525Sjb ulong_t ctf_nsyms; /* number of entries in symtab xlate table */ 196178525Sjb uint_t *ctf_txlate; /* translation table for type IDs */ 197178525Sjb ushort_t *ctf_ptrtab; /* translation table for pointer-to lookups */ 198178525Sjb ulong_t ctf_typemax; /* maximum valid type ID number */ 199178525Sjb const ctf_dmodel_t *ctf_dmodel; /* data model pointer (see above) */ 200178525Sjb struct ctf_file *ctf_parent; /* parent CTF container (if any) */ 201178525Sjb const char *ctf_parlabel; /* label in parent container (if any) */ 202178525Sjb const char *ctf_parname; /* basename of parent (if any) */ 203178525Sjb uint_t ctf_refcnt; /* reference count (for parent links) */ 204178525Sjb uint_t ctf_flags; /* libctf flags (see below) */ 205178525Sjb int ctf_errno; /* error code for most recent error */ 206178525Sjb int ctf_version; /* CTF data version */ 207178525Sjb ctf_dtdef_t **ctf_dthash; /* hash of dynamic type definitions */ 208178525Sjb ulong_t ctf_dthashlen; /* size of dynamic type hash bucket array */ 209178525Sjb ctf_list_t ctf_dtdefs; /* list of dynamic type definitions */ 210178525Sjb size_t ctf_dtstrlen; /* total length of dynamic type strings */ 211178525Sjb ulong_t ctf_dtnextid; /* next dynamic type id to assign */ 212178525Sjb ulong_t ctf_dtoldid; /* oldest id that has been committed */ 213178525Sjb void *ctf_specific; /* data for ctf_get/setspecific */ 214178525Sjb}; 215178525Sjb 216178525Sjb#define LCTF_INDEX_TO_TYPEPTR(fp, i) \ 217178525Sjb ((ctf_type_t *)((uintptr_t)(fp)->ctf_buf + (fp)->ctf_txlate[(i)])) 218178525Sjb 219178525Sjb#define LCTF_INFO_KIND(fp, info) ((fp)->ctf_fileops->ctfo_get_kind(info)) 220178525Sjb#define LCTF_INFO_ROOT(fp, info) ((fp)->ctf_fileops->ctfo_get_root(info)) 221178525Sjb#define LCTF_INFO_VLEN(fp, info) ((fp)->ctf_fileops->ctfo_get_vlen(info)) 222178525Sjb 223178525Sjb#define LCTF_MMAP 0x0001 /* libctf should munmap buffers on close */ 224178525Sjb#define LCTF_CHILD 0x0002 /* CTF container is a child */ 225178525Sjb#define LCTF_RDWR 0x0004 /* CTF container is writable */ 226178525Sjb#define LCTF_DIRTY 0x0008 /* CTF container has been modified */ 227178525Sjb 228178525Sjb#define ECTF_BASE 1000 /* base value for libctf errnos */ 229178525Sjb 230178525Sjbenum { 231178525Sjb ECTF_FMT = ECTF_BASE, /* file is not in CTF or ELF format */ 232178525Sjb ECTF_ELFVERS, /* ELF version is more recent than libctf */ 233178525Sjb ECTF_CTFVERS, /* CTF version is more recent than libctf */ 234178525Sjb ECTF_ENDIAN, /* data is different endian-ness than lib */ 235178525Sjb ECTF_SYMTAB, /* symbol table uses invalid entry size */ 236178525Sjb ECTF_SYMBAD, /* symbol table data buffer invalid */ 237178525Sjb ECTF_STRBAD, /* string table data buffer invalid */ 238178525Sjb ECTF_CORRUPT, /* file data corruption detected */ 239178525Sjb ECTF_NOCTFDATA, /* ELF file does not contain CTF data */ 240178525Sjb ECTF_NOCTFBUF, /* buffer does not contain CTF data */ 241178525Sjb ECTF_NOSYMTAB, /* symbol table data is not available */ 242178525Sjb ECTF_NOPARENT, /* parent CTF container is not available */ 243178525Sjb ECTF_DMODEL, /* data model mismatch */ 244178525Sjb ECTF_MMAP, /* failed to mmap a data section */ 245178525Sjb ECTF_ZMISSING, /* decompression library not installed */ 246178525Sjb ECTF_ZINIT, /* failed to initialize decompression library */ 247178525Sjb ECTF_ZALLOC, /* failed to allocate decompression buffer */ 248178525Sjb ECTF_DECOMPRESS, /* failed to decompress CTF data */ 249178525Sjb ECTF_STRTAB, /* string table for this string is missing */ 250178525Sjb ECTF_BADNAME, /* string offset is corrupt w.r.t. strtab */ 251178525Sjb ECTF_BADID, /* invalid type ID number */ 252178525Sjb ECTF_NOTSOU, /* type is not a struct or union */ 253178525Sjb ECTF_NOTENUM, /* type is not an enum */ 254178525Sjb ECTF_NOTSUE, /* type is not a struct, union, or enum */ 255178525Sjb ECTF_NOTINTFP, /* type is not an integer or float */ 256178525Sjb ECTF_NOTARRAY, /* type is not an array */ 257178525Sjb ECTF_NOTREF, /* type does not reference another type */ 258178525Sjb ECTF_NAMELEN, /* buffer is too small to hold type name */ 259178525Sjb ECTF_NOTYPE, /* no type found corresponding to name */ 260178525Sjb ECTF_SYNTAX, /* syntax error in type name */ 261178525Sjb ECTF_NOTFUNC, /* symtab entry does not refer to a function */ 262178525Sjb ECTF_NOFUNCDAT, /* no func info available for function */ 263178525Sjb ECTF_NOTDATA, /* symtab entry does not refer to a data obj */ 264178525Sjb ECTF_NOTYPEDAT, /* no type info available for object */ 265178525Sjb ECTF_NOLABEL, /* no label found corresponding to name */ 266178525Sjb ECTF_NOLABELDATA, /* file does not contain any labels */ 267178525Sjb ECTF_NOTSUP, /* feature not supported */ 268178525Sjb ECTF_NOENUMNAM, /* enum element name not found */ 269178525Sjb ECTF_NOMEMBNAM, /* member name not found */ 270178525Sjb ECTF_RDONLY, /* CTF container is read-only */ 271178525Sjb ECTF_DTFULL, /* CTF type is full (no more members allowed) */ 272178525Sjb ECTF_FULL, /* CTF container is full */ 273178525Sjb ECTF_DUPMEMBER, /* duplicate member name definition */ 274254744Sdelphij ECTF_CONFLICT, /* conflicting type definition present */ 275254744Sdelphij ECTF_REFERENCED, /* type has outstanding references */ 276254744Sdelphij ECTF_NOTDYN /* type is not a dynamic type */ 277178525Sjb}; 278178525Sjb 279178525Sjbextern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *, 280178525Sjb ssize_t *, ssize_t *); 281178525Sjb 282178525Sjbextern const ctf_type_t *ctf_lookup_by_id(ctf_file_t **, ctf_id_t); 283178525Sjb 284178525Sjbextern int ctf_hash_create(ctf_hash_t *, ulong_t); 285178525Sjbextern int ctf_hash_insert(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t); 286178525Sjbextern int ctf_hash_define(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t); 287178525Sjbextern ctf_helem_t *ctf_hash_lookup(ctf_hash_t *, ctf_file_t *, 288178525Sjb const char *, size_t); 289178525Sjbextern uint_t ctf_hash_size(const ctf_hash_t *); 290178525Sjbextern void ctf_hash_destroy(ctf_hash_t *); 291178525Sjb 292178525Sjb#define ctf_list_prev(elem) ((void *)(((ctf_list_t *)(elem))->l_prev)) 293178525Sjb#define ctf_list_next(elem) ((void *)(((ctf_list_t *)(elem))->l_next)) 294178525Sjb 295178525Sjbextern void ctf_list_append(ctf_list_t *, void *); 296178525Sjbextern void ctf_list_prepend(ctf_list_t *, void *); 297178525Sjbextern void ctf_list_delete(ctf_list_t *, void *); 298178525Sjb 299178525Sjbextern void ctf_dtd_insert(ctf_file_t *, ctf_dtdef_t *); 300178525Sjbextern void ctf_dtd_delete(ctf_file_t *, ctf_dtdef_t *); 301178525Sjbextern ctf_dtdef_t *ctf_dtd_lookup(ctf_file_t *, ctf_id_t); 302178525Sjb 303178525Sjbextern void ctf_decl_init(ctf_decl_t *, char *, size_t); 304178525Sjbextern void ctf_decl_fini(ctf_decl_t *); 305178525Sjbextern void ctf_decl_push(ctf_decl_t *, ctf_file_t *, ctf_id_t); 306178525Sjbextern void ctf_decl_sprintf(ctf_decl_t *, const char *, ...); 307178525Sjb 308178525Sjbextern const char *ctf_strraw(ctf_file_t *, uint_t); 309178525Sjbextern const char *ctf_strptr(ctf_file_t *, uint_t); 310178525Sjb 311178525Sjbextern ctf_file_t *ctf_set_open_errno(int *, int); 312178525Sjbextern long ctf_set_errno(ctf_file_t *, int); 313178525Sjb 314178525Sjbextern const void *ctf_sect_mmap(ctf_sect_t *, int); 315178525Sjbextern void ctf_sect_munmap(const ctf_sect_t *); 316178525Sjb 317178525Sjbextern void *ctf_data_alloc(size_t); 318178525Sjbextern void ctf_data_free(void *, size_t); 319178525Sjbextern void ctf_data_protect(void *, size_t); 320178525Sjb 321178525Sjbextern void *ctf_alloc(size_t); 322178525Sjbextern void ctf_free(void *, size_t); 323178525Sjb 324178525Sjbextern char *ctf_strdup(const char *); 325178525Sjbextern const char *ctf_strerror(int); 326178525Sjbextern void ctf_dprintf(const char *, ...); 327178525Sjb 328178525Sjbextern void *ctf_zopen(int *); 329178525Sjb 330178525Sjbextern const char _CTF_SECTION[]; /* name of CTF ELF section */ 331178525Sjbextern const char _CTF_NULLSTR[]; /* empty string */ 332178525Sjb 333178525Sjbextern int _libctf_version; /* library client version */ 334178525Sjbextern int _libctf_debug; /* debugging messages enabled */ 335178525Sjb 336178525Sjb#ifdef __cplusplus 337178525Sjb} 338178525Sjb#endif 339178525Sjb 340178525Sjb#endif /* _CTF_IMPL_H */ 341