Index: head/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c =================================================================== --- head/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c (revision 364021) +++ head/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c (revision 364022) @@ -1,528 +1,529 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include +#include #include #include #include #include #include #include #include #ifdef illumos #include #else #include #endif #include #ifdef illumos #ifdef _LP64 static const char *_libctf_zlib = "/usr/lib/64/libz.so"; #else static const char *_libctf_zlib = "/usr/lib/libz.so"; #endif #endif static struct { int (*z_uncompress)(uchar_t *, ulong_t *, const uchar_t *, ulong_t); const char *(*z_error)(int); void *z_dlp; } zlib; static size_t _PAGESIZE; static size_t _PAGEMASK; #ifdef illumos #pragma init(_libctf_init) #else void _libctf_init(void) __attribute__ ((constructor)); #endif void _libctf_init(void) { #ifdef illumos const char *p = getenv("LIBCTF_DECOMPRESSOR"); if (p != NULL) _libctf_zlib = p; /* use alternate decompression library */ #endif _libctf_debug = getenv("LIBCTF_DEBUG") != NULL; _PAGESIZE = getpagesize(); _PAGEMASK = ~(_PAGESIZE - 1); } /* * Attempt to dlopen the decompression library and locate the symbols of * interest that we will need to call. This information in cached so * that multiple calls to ctf_bufopen() do not need to reopen the library. */ void * ctf_zopen(int *errp) { #ifdef illumos ctf_dprintf("decompressing CTF data using %s\n", _libctf_zlib); if (zlib.z_dlp != NULL) return (zlib.z_dlp); /* library is already loaded */ if (access(_libctf_zlib, R_OK) == -1) return (ctf_set_open_errno(errp, ECTF_ZMISSING)); if ((zlib.z_dlp = dlopen(_libctf_zlib, RTLD_LAZY | RTLD_LOCAL)) == NULL) return (ctf_set_open_errno(errp, ECTF_ZINIT)); zlib.z_uncompress = (int (*)(uchar_t *, ulong_t *, const uchar_t *, ulong_t)) dlsym(zlib.z_dlp, "uncompress"); zlib.z_error = (const char *(*)(int)) dlsym(zlib.z_dlp, "zError"); if (zlib.z_uncompress == NULL || zlib.z_error == NULL) { (void) dlclose(zlib.z_dlp); bzero(&zlib, sizeof (zlib)); return (ctf_set_open_errno(errp, ECTF_ZINIT)); } #else zlib.z_uncompress = uncompress; zlib.z_error = zError; /* Dummy return variable as 'no error' */ zlib.z_dlp = (void *) (uintptr_t) 1; #endif return (zlib.z_dlp); } /* * The ctf_bufopen() routine calls these subroutines, defined by , * which we then patch through to the functions in the decompression library. */ int z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) { return (zlib.z_uncompress(dst, (ulong_t *)dstlen, src, srclen)); } const char * z_strerror(int err) { return (zlib.z_error(err)); } /* * Convert a 32-bit ELF file header into GElf. */ static void ehdr_to_gelf(const Elf32_Ehdr *src, GElf_Ehdr *dst) { bcopy(src->e_ident, dst->e_ident, EI_NIDENT); dst->e_type = src->e_type; dst->e_machine = src->e_machine; dst->e_version = src->e_version; dst->e_entry = (Elf64_Addr)src->e_entry; dst->e_phoff = (Elf64_Off)src->e_phoff; dst->e_shoff = (Elf64_Off)src->e_shoff; dst->e_flags = src->e_flags; dst->e_ehsize = src->e_ehsize; dst->e_phentsize = src->e_phentsize; dst->e_phnum = src->e_phnum; dst->e_shentsize = src->e_shentsize; dst->e_shnum = src->e_shnum; dst->e_shstrndx = src->e_shstrndx; } /* * Convert a 32-bit ELF section header into GElf. */ static void shdr_to_gelf(const Elf32_Shdr *src, GElf_Shdr *dst) { dst->sh_name = src->sh_name; dst->sh_type = src->sh_type; dst->sh_flags = src->sh_flags; dst->sh_addr = src->sh_addr; dst->sh_offset = src->sh_offset; dst->sh_size = src->sh_size; dst->sh_link = src->sh_link; dst->sh_info = src->sh_info; dst->sh_addralign = src->sh_addralign; dst->sh_entsize = src->sh_entsize; } /* * In order to mmap a section from the ELF file, we must round down sh_offset * to the previous page boundary, and mmap the surrounding page. We store * the pointer to the start of the actual section data back into sp->cts_data. */ const void * ctf_sect_mmap(ctf_sect_t *sp, int fd) { size_t pageoff = sp->cts_offset & ~_PAGEMASK; caddr_t base = mmap64(NULL, sp->cts_size + pageoff, PROT_READ, MAP_PRIVATE, fd, sp->cts_offset & _PAGEMASK); if (base != MAP_FAILED) sp->cts_data = base + pageoff; return (base); } /* * Since sp->cts_data has the adjusted offset, we have to again round down * to get the actual mmap address and round up to get the size. */ void ctf_sect_munmap(const ctf_sect_t *sp) { uintptr_t addr = (uintptr_t)sp->cts_data; uintptr_t pageoff = addr & ~_PAGEMASK; (void) munmap((void *)(addr - pageoff), sp->cts_size + pageoff); } /* * Open the specified file descriptor and return a pointer to a CTF container. * The file can be either an ELF file or raw CTF file. The caller is * responsible for closing the file descriptor when it is no longer needed. */ ctf_file_t * ctf_fdopen(int fd, int *errp) { ctf_sect_t ctfsect, symsect, strsect; ctf_file_t *fp = NULL; size_t shstrndx, shnum; struct stat64 st; ssize_t nbytes; union { ctf_preamble_t ctf; Elf32_Ehdr e32; GElf_Ehdr e64; } hdr; bzero(&ctfsect, sizeof (ctf_sect_t)); bzero(&symsect, sizeof (ctf_sect_t)); bzero(&strsect, sizeof (ctf_sect_t)); bzero(&hdr, sizeof (hdr)); if (fstat64(fd, &st) == -1) return (ctf_set_open_errno(errp, errno)); if ((nbytes = pread64(fd, &hdr, sizeof (hdr), 0)) <= 0) return (ctf_set_open_errno(errp, nbytes < 0? errno : ECTF_FMT)); /* * If we have read enough bytes to form a CTF header and the magic * string matches, attempt to interpret the file as raw CTF. */ if (nbytes >= (ssize_t) sizeof (ctf_preamble_t) && hdr.ctf.ctp_magic == CTF_MAGIC) { if (hdr.ctf.ctp_version > CTF_VERSION) return (ctf_set_open_errno(errp, ECTF_CTFVERS)); ctfsect.cts_data = mmap64(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (ctfsect.cts_data == MAP_FAILED) return (ctf_set_open_errno(errp, errno)); ctfsect.cts_name = _CTF_SECTION; ctfsect.cts_type = SHT_PROGBITS; ctfsect.cts_flags = SHF_ALLOC; ctfsect.cts_size = (size_t)st.st_size; ctfsect.cts_entsize = 1; ctfsect.cts_offset = 0; if ((fp = ctf_bufopen(&ctfsect, NULL, NULL, errp)) == NULL) ctf_sect_munmap(&ctfsect); return (fp); } /* * If we have read enough bytes to form an ELF header and the magic * string matches, attempt to interpret the file as an ELF file. We * do our own largefile ELF processing, and convert everything to * GElf structures so that clients can operate on any data model. */ if (nbytes >= (ssize_t) sizeof (Elf32_Ehdr) && bcmp(&hdr.e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) { #if BYTE_ORDER == _BIG_ENDIAN uchar_t order = ELFDATA2MSB; #else uchar_t order = ELFDATA2LSB; #endif GElf_Shdr *sp; void *strs_map; size_t strs_mapsz, i; char *strs; if (hdr.e32.e_ident[EI_DATA] != order) return (ctf_set_open_errno(errp, ECTF_ENDIAN)); if (hdr.e32.e_version != EV_CURRENT) return (ctf_set_open_errno(errp, ECTF_ELFVERS)); if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS64) { if (nbytes < (ssize_t) sizeof (GElf_Ehdr)) return (ctf_set_open_errno(errp, ECTF_FMT)); } else { Elf32_Ehdr e32 = hdr.e32; ehdr_to_gelf(&e32, &hdr.e64); } shnum = hdr.e64.e_shnum; shstrndx = hdr.e64.e_shstrndx; /* Extended ELF sections */ if ((shstrndx == SHN_XINDEX) || (shnum == 0)) { if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { Elf32_Shdr x32; if (pread64(fd, &x32, sizeof (x32), hdr.e64.e_shoff) != sizeof (x32)) return (ctf_set_open_errno(errp, errno)); shnum = x32.sh_size; shstrndx = x32.sh_link; } else { Elf64_Shdr x64; if (pread64(fd, &x64, sizeof (x64), hdr.e64.e_shoff) != sizeof (x64)) return (ctf_set_open_errno(errp, errno)); shnum = x64.sh_size; shstrndx = x64.sh_link; } } if (shstrndx >= shnum) return (ctf_set_open_errno(errp, ECTF_CORRUPT)); nbytes = sizeof (GElf_Shdr) * shnum; if ((sp = malloc(nbytes)) == NULL) return (ctf_set_open_errno(errp, errno)); /* * Read in and convert to GElf the array of Shdr structures * from e_shoff so we can locate sections of interest. */ if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { Elf32_Shdr *sp32; nbytes = sizeof (Elf32_Shdr) * shnum; if ((sp32 = malloc(nbytes)) == NULL || pread64(fd, sp32, nbytes, hdr.e64.e_shoff) != nbytes) { free(sp); free(sp32); return (ctf_set_open_errno(errp, errno)); } for (i = 0; i < shnum; i++) shdr_to_gelf(&sp32[i], &sp[i]); free(sp32); } else if (pread64(fd, sp, nbytes, hdr.e64.e_shoff) != nbytes) { free(sp); return (ctf_set_open_errno(errp, errno)); } /* * Now mmap the section header strings section so that we can * perform string comparison on the section names. */ strs_mapsz = sp[shstrndx].sh_size + (sp[shstrndx].sh_offset & ~_PAGEMASK); strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE, fd, sp[shstrndx].sh_offset & _PAGEMASK); strs = (char *)strs_map + (sp[shstrndx].sh_offset & ~_PAGEMASK); if (strs_map == MAP_FAILED) { free(sp); return (ctf_set_open_errno(errp, ECTF_MMAP)); } /* * Iterate over the section header array looking for the CTF * section and symbol table. The strtab is linked to symtab. */ for (i = 0; i < shnum; i++) { const GElf_Shdr *shp = &sp[i]; const GElf_Shdr *lhp = &sp[shp->sh_link]; if (shp->sh_link >= shnum) continue; /* corrupt sh_link field */ if (shp->sh_name >= sp[shstrndx].sh_size || lhp->sh_name >= sp[shstrndx].sh_size) continue; /* corrupt sh_name field */ if (shp->sh_type == SHT_PROGBITS && strcmp(strs + shp->sh_name, _CTF_SECTION) == 0) { ctfsect.cts_name = strs + shp->sh_name; ctfsect.cts_type = shp->sh_type; ctfsect.cts_flags = shp->sh_flags; ctfsect.cts_size = shp->sh_size; ctfsect.cts_entsize = shp->sh_entsize; ctfsect.cts_offset = (off64_t)shp->sh_offset; } else if (shp->sh_type == SHT_SYMTAB) { symsect.cts_name = strs + shp->sh_name; symsect.cts_type = shp->sh_type; symsect.cts_flags = shp->sh_flags; symsect.cts_size = shp->sh_size; symsect.cts_entsize = shp->sh_entsize; symsect.cts_offset = (off64_t)shp->sh_offset; strsect.cts_name = strs + lhp->sh_name; strsect.cts_type = lhp->sh_type; strsect.cts_flags = lhp->sh_flags; strsect.cts_size = lhp->sh_size; strsect.cts_entsize = lhp->sh_entsize; strsect.cts_offset = (off64_t)lhp->sh_offset; } } free(sp); /* free section header array */ if (ctfsect.cts_type == SHT_NULL) { (void) munmap(strs_map, strs_mapsz); return (ctf_set_open_errno(errp, ECTF_NOCTFDATA)); } /* * Now mmap the CTF data, symtab, and strtab sections and * call ctf_bufopen() to do the rest of the work. */ if (ctf_sect_mmap(&ctfsect, fd) == MAP_FAILED) { (void) munmap(strs_map, strs_mapsz); return (ctf_set_open_errno(errp, ECTF_MMAP)); } if (symsect.cts_type != SHT_NULL && strsect.cts_type != SHT_NULL) { if (ctf_sect_mmap(&symsect, fd) == MAP_FAILED || ctf_sect_mmap(&strsect, fd) == MAP_FAILED) { (void) ctf_set_open_errno(errp, ECTF_MMAP); goto bad; /* unmap all and abort */ } fp = ctf_bufopen(&ctfsect, &symsect, &strsect, errp); } else fp = ctf_bufopen(&ctfsect, NULL, NULL, errp); bad: if (fp == NULL) { ctf_sect_munmap(&ctfsect); ctf_sect_munmap(&symsect); ctf_sect_munmap(&strsect); } else fp->ctf_flags |= LCTF_MMAP; (void) munmap(strs_map, strs_mapsz); return (fp); } return (ctf_set_open_errno(errp, ECTF_FMT)); } /* * Open the specified file and return a pointer to a CTF container. The file * can be either an ELF file or raw CTF file. This is just a convenient * wrapper around ctf_fdopen() for callers. */ ctf_file_t * ctf_open(const char *filename, int *errp) { ctf_file_t *fp; int fd; if ((fd = open64(filename, O_RDONLY)) == -1) { if (errp != NULL) *errp = errno; return (NULL); } fp = ctf_fdopen(fd, errp); (void) close(fd); return (fp); } /* * Write the uncompressed CTF data stream to the specified file descriptor. * This is useful for saving the results of dynamic CTF containers. */ int ctf_write(ctf_file_t *fp, int fd) { const uchar_t *buf = fp->ctf_base; ssize_t resid = fp->ctf_size; ssize_t len; while (resid != 0) { if ((len = write(fd, buf, resid)) <= 0) return (ctf_set_errno(fp, errno)); resid -= len; buf += len; } return (0); } /* * Set the CTF library client version to the specified version. If version is * zero, we just return the default library version number. */ int ctf_version(int version) { if (version < 0) { errno = EINVAL; return (-1); } if (version > 0) { if (version > CTF_VERSION) { errno = ENOTSUP; return (-1); } ctf_dprintf("ctf_version: client using version %d\n", version); _libctf_version = version; } return (_libctf_version); } Index: head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h =================================================================== --- head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h (revision 364021) +++ head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h (revision 364022) @@ -1,454 +1,464 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _CTFTOOLS_H #define _CTFTOOLS_H /* * Functions and data structures used in the manipulation of stabs and CTF data */ #include #include #include #include #include #include #include +#include #ifdef __cplusplus extern "C" { #endif #include "list.h" #include "hash.h" #ifndef DEBUG_LEVEL #define DEBUG_LEVEL 0 #endif #ifndef DEBUG_PARSE #define DEBUG_PARSE 0 #endif #ifndef DEBUG_STREAM #define DEBUG_STREAM stderr #endif #ifndef MAX #define MAX(a, b) ((a) < (b) ? (b) : (a)) #endif #ifndef MIN #define MIN(a, b) ((a) > (b) ? (b) : (a)) +#endif + +/* Sanity check for cross-build bootstrap tools */ +#if !defined(BYTE_ORDER) +#error "Missing BYTE_ORDER defines" +#elif !defined(_LITTLE_ENDIAN) +#error "Missing _LITTLE_ENDIAN defines" +#elif !defined(_BIG_ENDIAN) +#error "Missing _BIG_ENDIAN defines" #endif #define TRUE 1 #define FALSE 0 #define CTF_ELF_SCN_NAME ".SUNW_ctf" #define CTF_LABEL_LASTIDX -1 #define CTF_DEFAULT_LABEL "*** No Label Provided ***" /* * Default hash sizes */ #define TDATA_LAYOUT_HASH_SIZE 8191 /* A tdesc hash based on layout */ #define TDATA_ID_HASH_SIZE 997 /* A tdesc hash based on type id */ #define IIDESC_HASH_SIZE 8191 /* Hash of iidesc's */ /* * The default function argument array size. We'll realloc the array larger * if we need to, but we want a default value that will allow us to avoid * reallocation in the common case. */ #define FUNCARG_DEF 5 extern const char *progname; extern int debug_level; extern int debug_parse; extern char *curhdr; /* * This is a partial copy of the stab.h that DevPro includes with their * compiler. */ typedef struct stab { uint32_t n_strx; uint8_t n_type; int8_t n_other; int16_t n_desc; uint32_t n_value; } stab_t; #define N_GSYM 0x20 /* global symbol: name,,0,type,0 */ #define N_FUN 0x24 /* procedure: name,,0,linenumber,0 */ #define N_STSYM 0x26 /* static symbol: name,,0,type,0 or section relative */ #define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,0 or section relative */ #define N_ROSYM 0x2c /* ro_data: name,,0,type,0 or section relative */ #define N_OPT 0x3c /* compiler options */ #define N_RSYM 0x40 /* register sym: name,,0,type,register */ #define N_SO 0x64 /* source file name: name,,0,0,0 */ #define N_LSYM 0x80 /* local sym: name,,0,type,offset */ #define N_SOL 0x84 /* #included file name: name,,0,0,0 */ #define N_PSYM 0xa0 /* parameter: name,,0,type,offset */ #define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,function relative */ #define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,func relative */ #define N_BINCL 0x82 /* header file: name,,0,0,0 */ #define N_EINCL 0xa2 /* end of include file */ /* * Nodes in the type tree * * Each node consists of a single tdesc_t, with one of several auxiliary * structures linked in via the `data' union. */ /* The type of tdesc_t node */ typedef enum stabtype { STABTYPE_FIRST, /* do not use */ INTRINSIC, POINTER, ARRAY, FUNCTION, STRUCT, UNION, ENUM, FORWARD, TYPEDEF, TYPEDEF_UNRES, VOLATILE, CONST, RESTRICT, STABTYPE_LAST /* do not use */ } stabtype_t; typedef struct tdesc tdesc_t; /* Auxiliary structure for array tdesc_t */ typedef struct ardef { tdesc_t *ad_contents; tdesc_t *ad_idxtype; uint_t ad_nelems; } ardef_t; /* Auxiliary structure for structure/union tdesc_t */ typedef struct mlist { int ml_offset; /* Offset from start of structure (in bits) */ int ml_size; /* Member size (in bits) */ char *ml_name; /* Member name */ struct tdesc *ml_type; /* Member type */ struct mlist *ml_next; /* Next member */ } mlist_t; /* Auxiliary structure for enum tdesc_t */ typedef struct elist { char *el_name; int el_number; struct elist *el_next; } elist_t; /* Auxiliary structure for intrinsics (integers and reals) */ typedef enum { INTR_INT, INTR_REAL } intrtype_t; typedef struct intr { intrtype_t intr_type; int intr_signed; union { char _iformat; int _fformat; } _u; int intr_offset; int intr_nbits; } intr_t; #define intr_iformat _u._iformat #define intr_fformat _u._fformat typedef struct fnarg { char *fna_name; struct tdesc *fna_type; } fnarg_t; #define FN_F_GLOBAL 0x1 #define FN_F_VARARGS 0x2 typedef struct fndef { struct tdesc *fn_ret; uint_t fn_nargs; tdesc_t **fn_args; uint_t fn_vargs; } fndef_t; typedef int32_t tid_t; /* * The tdesc_t (Type DESCription) is the basic node type used in the stabs data * structure. Each data node gets a tdesc structure. Each node is linked into * a directed graph (think of it as a tree with multiple roots and multiple * leaves), with the root nodes at the top, and intrinsics at the bottom. The * root nodes, which are pointed to by iidesc nodes, correspond to the types, * globals, and statics defined by the stabs. */ struct tdesc { char *t_name; tdesc_t *t_next; /* Name hash next pointer */ tid_t t_id; tdesc_t *t_hash; /* ID hash next pointer */ stabtype_t t_type; int t_size; /* Size in bytes of object represented by this node */ union { intr_t *intr; /* int, real */ tdesc_t *tdesc; /* ptr, typedef, vol, const, restr */ ardef_t *ardef; /* array */ mlist_t *members; /* struct, union */ elist_t *emem; /* enum */ fndef_t *fndef; /* function - first is return type */ } t_data; int t_flags; int t_vgen; /* Visitation generation (see traverse.c) */ int t_emark; /* Equality mark (see equiv_cb() in merge.c) */ }; #define t_intr t_data.intr #define t_tdesc t_data.tdesc #define t_ardef t_data.ardef #define t_members t_data.members #define t_emem t_data.emem #define t_fndef t_data.fndef #define TDESC_F_ISROOT 0x1 /* Has an iidesc_t (see below) */ #define TDESC_F_GLOBAL 0x2 #define TDESC_F_RESOLVED 0x4 /* * iidesc_t (Interesting Item DESCription) nodes point to tdesc_t nodes that * correspond to "interesting" stabs. A stab is interesting if it defines a * global or static variable, a global or static function, or a data type. */ typedef enum iitype { II_NOT = 0, II_GFUN, /* Global function */ II_SFUN, /* Static function */ II_GVAR, /* Global variable */ II_SVAR, /* Static variable */ II_PSYM, /* Function argument */ II_SOU, /* Struct or union */ II_TYPE /* Type (typedef) */ } iitype_t; typedef struct iidesc { iitype_t ii_type; char *ii_name; tdesc_t *ii_dtype; char *ii_owner; /* File that defined this node */ int ii_flags; /* Function arguments (if any) */ int ii_nargs; tdesc_t **ii_args; int ii_vargs; /* Function uses varargs */ } iidesc_t; #define IIDESC_F_USED 0x1 /* Write this iidesc out */ /* * labelent_t nodes identify labels and corresponding type ranges associated * with them. The label in a given labelent_t is associated with types with * ids <= le_idx. */ typedef struct labelent { char *le_name; int le_idx; } labelent_t; /* * The tdata_t (Type DATA) structure contains or references all type data for * a given file or, during merging, several files. */ typedef struct tdata { int td_curemark; /* Equality mark (see merge.c) */ int td_curvgen; /* Visitation generation (see traverse.c) */ int td_nextid; /* The ID for the next tdesc_t created */ hash_t *td_iihash; /* The iidesc_t nodes for this file */ hash_t *td_layouthash; /* The tdesc nodes, hashed by structure */ hash_t *td_idhash; /* The tdesc nodes, hashed by type id */ list_t *td_fwdlist; /* All forward declaration tdesc nodes */ char *td_parlabel; /* Top label uniq'd against in parent */ char *td_parname; /* Basename of parent */ list_t *td_labels; /* Labels and their type ranges */ pthread_mutex_t td_mergelock; int td_ref; } tdata_t; /* * By design, the iidesc hash is heterogeneous. The CTF emitter, on the * other hand, needs to be able to access the elements of the list by type, * and in a specific sorted order. An iiburst holds these elements in that * order. (A burster is a machine that separates carbon-copy forms) */ typedef struct iiburst { int iib_nfuncs; int iib_curfunc; iidesc_t **iib_funcs; int iib_nobjts; int iib_curobjt; iidesc_t **iib_objts; list_t *iib_types; int iib_maxtypeid; tdata_t *iib_td; struct tdtrav_data *iib_tdtd; /* tdtrav_data_t */ } iiburst_t; typedef struct ctf_buf ctf_buf_t; typedef struct symit_data symit_data_t; /* fixup_tdescs.c */ void cvt_fixstabs(tdata_t *); void cvt_fixups(tdata_t *, size_t); /* ctf.c */ caddr_t ctf_gen(iiburst_t *, size_t *, int); tdata_t *ctf_load(char *, caddr_t, size_t, symit_data_t *, char *); /* iidesc.c */ iidesc_t *iidesc_new(char *); int iidesc_hash(int, void *); void iter_iidescs_by_name(tdata_t *, const char *, int (*)(void *, void *), void *); iidesc_t *iidesc_dup(iidesc_t *); iidesc_t *iidesc_dup_rename(iidesc_t *, char const *, char const *); void iidesc_add(hash_t *, iidesc_t *); void iidesc_free(void *, void *); int iidesc_count_type(void *, void *); void iidesc_stats(hash_t *); int iidesc_dump(iidesc_t *); /* input.c */ typedef enum source_types { SOURCE_NONE = 0, SOURCE_UNKNOWN = 1, SOURCE_C = 2, SOURCE_S = 4 } source_types_t; source_types_t built_source_types(Elf *, const char *); int count_files(char **, int); int read_ctf(char **, int, char *, int (*)(tdata_t *, char *, void *), void *, int); int read_ctf_save_cb(tdata_t *, char *, void *); symit_data_t *symit_new(Elf *, const char *); void symit_reset(symit_data_t *); char *symit_curfile(symit_data_t *); GElf_Sym *symit_next(symit_data_t *, int); char *symit_name(symit_data_t *); void symit_free(symit_data_t *); /* merge.c */ void merge_into_master(tdata_t *, tdata_t *, tdata_t *, int); /* output.c */ #define CTF_FUZZY_MATCH 0x1 /* match local symbols to global CTF */ #define CTF_USE_DYNSYM 0x2 /* use .dynsym not .symtab */ #define CTF_COMPRESS 0x4 /* compress CTF output */ #define CTF_KEEP_STABS 0x8 /* keep .stabs sections */ #define CTF_SWAP_BYTES 0x10 /* target byte order is different from host */ void write_ctf(tdata_t *, const char *, const char *, int); /* parse.c */ void parse_init(tdata_t *); void parse_finish(tdata_t *); int parse_stab(stab_t *, char *, iidesc_t **); tdesc_t *lookup(int); tdesc_t *lookupname(const char *); void check_hash(void); void resolve_typed_bitfields(void); /* stabs.c */ int stabs_read(tdata_t *, Elf *, char *); /* dwarf.c */ int dw_read(tdata_t *, Elf *, char *); const char *dw_tag2str(uint_t); /* tdata.c */ tdata_t *tdata_new(void); void tdata_free(tdata_t *); void tdata_build_hashes(tdata_t *td); const char *tdesc_name(tdesc_t *); int tdesc_idhash(int, void *); int tdesc_idcmp(void *, void *); int tdesc_namehash(int, void *); int tdesc_namecmp(void *, void *); int tdesc_layouthash(int, void *); int tdesc_layoutcmp(void *, void *); void tdesc_free(tdesc_t *); void tdata_label_add(tdata_t *, const char *, int); labelent_t *tdata_label_top(tdata_t *); int tdata_label_find(tdata_t *, char *); void tdata_label_free(tdata_t *); void tdata_merge(tdata_t *, tdata_t *); void tdata_label_newmax(tdata_t *, int); /* util.c */ int streq(const char *, const char *); int findelfsecidx(Elf *, const char *, const char *); size_t elf_ptrsz(Elf *); char *mktmpname(const char *, const char *); void terminate(const char *, ...) __NORETURN; void aborterr(const char *, ...) __NORETURN; void set_terminate_cleanup(void (*)(void)); void elfterminate(const char *, const char *, ...); void warning(const char *, ...); void vadebug(int, const char *, va_list); void debug(int, const char *, ...); void watch_dump(int); void watch_set(void *, int); #ifdef __cplusplus } #endif #endif /* _CTFTOOLS_H */ Index: head/sys/cddl/compat/opensolaris/sys/stat.h =================================================================== --- head/sys/cddl/compat/opensolaris/sys/stat.h (revision 364021) +++ head/sys/cddl/compat/opensolaris/sys/stat.h (revision 364022) @@ -1,56 +1,65 @@ /* * Copyright (C) 2007 John Birrell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * */ #ifndef _COMPAT_OPENSOLARIS_SYS_STAT_H_ #define _COMPAT_OPENSOLARIS_SYS_STAT_H_ #include_next +/* + * When bootstrapping on Linux a stat64/fstat64 functions exists in both + * glibc and musl libc. To avoid compilation errors, use those functions instead + * of redefining them to stat/fstat. + * Similarly, macOS provides (deprecated) stat64 functions that we can use + * for now. + */ +#if !defined(__linux__) && !defined(__APPLE__) #define stat64 stat #define MAXOFFSET_T OFF_MAX -#ifndef _KERNEL +#if !defined(_KERNEL) #include static __inline int fstat64(int fd, struct stat *sb) { int ret; ret = fstat(fd, sb); if (ret == 0) { if (S_ISCHR(sb->st_mode)) (void)ioctl(fd, DIOCGMEDIASIZE, &sb->st_size); } return (ret); } -#endif +#endif /* !defined(_KERNEL) */ +#endif /* !defined(__linux__) && !defined(__APPLE__) */ #endif /* !_COMPAT_OPENSOLARIS_SYS_STAT_H_ */ Index: head/sys/cddl/compat/opensolaris/sys/time.h =================================================================== --- head/sys/cddl/compat/opensolaris/sys/time.h (revision 364021) +++ head/sys/cddl/compat/opensolaris/sys/time.h (revision 364022) @@ -1,94 +1,95 @@ /*- * Copyright (c) 2007 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _OPENSOLARIS_SYS_TIME_H_ #define _OPENSOLARIS_SYS_TIME_H_ +#include #include_next #define SEC 1 #define MILLISEC 1000 #define MICROSEC 1000000 #define NANOSEC 1000000000 #define TIME_MAX LLONG_MAX #define MSEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / MILLISEC)) #define NSEC2MSEC(n) ((n) / (NANOSEC / MILLISEC)) #define USEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / MICROSEC)) #define NSEC2USEC(n) ((n) / (NANOSEC / MICROSEC)) #define NSEC2SEC(n) ((n) / (NANOSEC / SEC)) #define SEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / SEC)) typedef longlong_t hrtime_t; #if defined(__i386__) || defined(__powerpc__) #define TIMESPEC_OVERFLOW(ts) \ ((ts)->tv_sec < INT32_MIN || (ts)->tv_sec > INT32_MAX) #else #define TIMESPEC_OVERFLOW(ts) \ ((ts)->tv_sec < INT64_MIN || (ts)->tv_sec > INT64_MAX) #endif #define SEC_TO_TICK(sec) ((sec) * hz) #define NSEC_TO_TICK(nsec) ((nsec) / (NANOSEC / hz)) #ifdef _KERNEL static __inline hrtime_t gethrtime(void) { struct timespec ts; hrtime_t nsec; getnanouptime(&ts); nsec = (hrtime_t)ts.tv_sec * NANOSEC + ts.tv_nsec; return (nsec); } #define gethrestime_sec() (time_second) #define gethrestime(ts) getnanotime(ts) #define gethrtime_waitfree() gethrtime() extern int nsec_per_tick; /* nanoseconds per clock tick */ #define ddi_get_lbolt64() \ (int64_t)(((getsbinuptime() >> 16) * hz) >> 16) #define ddi_get_lbolt() (clock_t)ddi_get_lbolt64() #else static __inline hrtime_t gethrtime(void) { struct timespec ts; clock_gettime(CLOCK_UPTIME,&ts); return (((u_int64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); } #endif /* _KERNEL */ #endif /* !_OPENSOLARIS_SYS_TIME_H_ */ Index: head/sys/cddl/contrib/opensolaris/uts/common/sys/sysmacros.h =================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/sys/sysmacros.h (revision 364021) +++ head/sys/cddl/contrib/opensolaris/uts/common/sys/sysmacros.h (revision 364022) @@ -1,459 +1,466 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_SYSMACROS_H #define _SYS_SYSMACROS_H #include #include #if defined(__FreeBSD__) && defined(_KERNEL) #include #endif #ifdef __cplusplus extern "C" { #endif /* * Some macros for units conversion */ /* * Disk blocks (sectors) and bytes. */ +#ifndef dtob #define dtob(DD) ((DD) << DEV_BSHIFT) +#endif +#ifndef btod #define btod(BB) (((BB) + DEV_BSIZE - 1) >> DEV_BSHIFT) +#endif #define btodt(BB) ((BB) >> DEV_BSHIFT) #define lbtod(BB) (((offset_t)(BB) + DEV_BSIZE - 1) >> DEV_BSHIFT) /* common macros */ #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) ((a) < (b) ? (b) : (a)) #endif #ifndef ABS #define ABS(a) ((a) < 0 ? -(a) : (a)) #endif #ifndef SIGNOF #define SIGNOF(a) ((a) < 0 ? -1 : (a) > 0) #endif #ifdef _KERNEL /* * Convert a single byte to/from binary-coded decimal (BCD). */ extern unsigned char byte_to_bcd[256]; extern unsigned char bcd_to_byte[256]; #define BYTE_TO_BCD(x) byte_to_bcd[(x) & 0xff] #define BCD_TO_BYTE(x) bcd_to_byte[(x) & 0xff] #endif /* _KERNEL */ /* * WARNING: The device number macros defined here should not be used by device * drivers or user software. Device drivers should use the device functions * defined in the DDI/DKI interface (see also ddi.h). Application software * should make use of the library routines available in makedev(3). A set of * new device macros are provided to operate on the expanded device number * format supported in SVR4. Macro versions of the DDI device functions are * provided for use by kernel proper routines only. Macro routines bmajor(), * major(), minor(), emajor(), eminor(), and makedev() will be removed or * their definitions changed at the next major release following SVR4. */ #define O_BITSMAJOR 7 /* # of SVR3 major device bits */ #define O_BITSMINOR 8 /* # of SVR3 minor device bits */ #define O_MAXMAJ 0x7f /* SVR3 max major value */ #define O_MAXMIN 0xff /* SVR3 max minor value */ #define L_BITSMAJOR32 14 /* # of SVR4 major device bits */ #define L_BITSMINOR32 18 /* # of SVR4 minor device bits */ #define L_MAXMAJ32 0x3fff /* SVR4 max major value */ #define L_MAXMIN32 0x3ffff /* MAX minor for 3b2 software drivers. */ /* For 3b2 hardware devices the minor is */ /* restricted to 256 (0-255) */ #ifdef _LP64 #define L_BITSMAJOR 32 /* # of major device bits in 64-bit Solaris */ #define L_BITSMINOR 32 /* # of minor device bits in 64-bit Solaris */ #define L_MAXMAJ 0xfffffffful /* max major value */ #define L_MAXMIN 0xfffffffful /* max minor value */ #else #define L_BITSMAJOR L_BITSMAJOR32 #define L_BITSMINOR L_BITSMINOR32 #define L_MAXMAJ L_MAXMAJ32 #define L_MAXMIN L_MAXMIN32 #endif #ifdef illumos #ifdef _KERNEL /* major part of a device internal to the kernel */ #define major(x) (major_t)((((unsigned)(x)) >> O_BITSMINOR) & O_MAXMAJ) #define bmajor(x) (major_t)((((unsigned)(x)) >> O_BITSMINOR) & O_MAXMAJ) /* get internal major part of expanded device number */ #define getmajor(x) (major_t)((((dev_t)(x)) >> L_BITSMINOR) & L_MAXMAJ) /* minor part of a device internal to the kernel */ #define minor(x) (minor_t)((x) & O_MAXMIN) /* get internal minor part of expanded device number */ #define getminor(x) (minor_t)((x) & L_MAXMIN) #else /* major part of a device external from the kernel (same as emajor below) */ #define major(x) (major_t)((((unsigned)(x)) >> O_BITSMINOR) & O_MAXMAJ) /* minor part of a device external from the kernel (same as eminor below) */ #define minor(x) (minor_t)((x) & O_MAXMIN) #endif /* _KERNEL */ /* create old device number */ #define makedev(x, y) (unsigned short)(((x) << O_BITSMINOR) | ((y) & O_MAXMIN)) /* make an new device number */ #define makedevice(x, y) (dev_t)(((dev_t)(x) << L_BITSMINOR) | ((y) & L_MAXMIN)) /* * emajor() allows kernel/driver code to print external major numbers * eminor() allows kernel/driver code to print external minor numbers */ #define emajor(x) \ (major_t)(((unsigned int)(x) >> O_BITSMINOR) > O_MAXMAJ) ? \ NODEV : (((unsigned int)(x) >> O_BITSMINOR) & O_MAXMAJ) #define eminor(x) \ (minor_t)((x) & O_MAXMIN) /* * get external major and minor device * components from expanded device number */ #define getemajor(x) (major_t)((((dev_t)(x) >> L_BITSMINOR) > L_MAXMAJ) ? \ NODEV : (((dev_t)(x) >> L_BITSMINOR) & L_MAXMAJ)) #define geteminor(x) (minor_t)((x) & L_MAXMIN) #endif /* illumos */ /* * These are versions of the kernel routines for compressing and * expanding long device numbers that don't return errors. */ #if (L_BITSMAJOR32 == L_BITSMAJOR) && (L_BITSMINOR32 == L_BITSMINOR) #define DEVCMPL(x) (x) #define DEVEXPL(x) (x) #else #define DEVCMPL(x) \ (dev32_t)((((x) >> L_BITSMINOR) > L_MAXMAJ32 || \ ((x) & L_MAXMIN) > L_MAXMIN32) ? NODEV32 : \ ((((x) >> L_BITSMINOR) << L_BITSMINOR32) | ((x) & L_MAXMIN32))) #define DEVEXPL(x) \ (((x) == NODEV32) ? NODEV : \ makedevice(((x) >> L_BITSMINOR32) & L_MAXMAJ32, (x) & L_MAXMIN32)) #endif /* L_BITSMAJOR32 ... */ /* convert to old (SVR3.2) dev format */ #define cmpdev(x) \ (o_dev_t)((((x) >> L_BITSMINOR) > O_MAXMAJ || \ ((x) & L_MAXMIN) > O_MAXMIN) ? NODEV : \ ((((x) >> L_BITSMINOR) << O_BITSMINOR) | ((x) & O_MAXMIN))) /* convert to new (SVR4) dev format */ #define expdev(x) \ (dev_t)(((dev_t)(((x) >> O_BITSMINOR) & O_MAXMAJ) << L_BITSMINOR) | \ ((x) & O_MAXMIN)) /* * Macro for checking power of 2 address alignment. */ #define IS_P2ALIGNED(v, a) ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0) /* * Macros for counting and rounding. */ +#ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef roundup #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) - +#endif /* * Macro to determine if value is a power of 2 */ #define ISP2(x) (((x) & ((x) - 1)) == 0) /* * Macros for various sorts of alignment and rounding. The "align" must * be a power of 2. Often times it is a block, sector, or page. */ /* * return x rounded down to an align boundary * eg, P2ALIGN(1200, 1024) == 1024 (1*align) * eg, P2ALIGN(1024, 1024) == 1024 (1*align) * eg, P2ALIGN(0x1234, 0x100) == 0x1200 (0x12*align) * eg, P2ALIGN(0x5600, 0x100) == 0x5600 (0x56*align) */ #define P2ALIGN(x, align) ((x) & -(align)) /* * return x % (mod) align * eg, P2PHASE(0x1234, 0x100) == 0x34 (x-0x12*align) * eg, P2PHASE(0x5600, 0x100) == 0x00 (x-0x56*align) */ #define P2PHASE(x, align) ((x) & ((align) - 1)) /* * return how much space is left in this block (but if it's perfectly * aligned, return 0). * eg, P2NPHASE(0x1234, 0x100) == 0xcc (0x13*align-x) * eg, P2NPHASE(0x5600, 0x100) == 0x00 (0x56*align-x) */ #define P2NPHASE(x, align) (-(x) & ((align) - 1)) /* * return x rounded up to an align boundary * eg, P2ROUNDUP(0x1234, 0x100) == 0x1300 (0x13*align) * eg, P2ROUNDUP(0x5600, 0x100) == 0x5600 (0x56*align) */ #define P2ROUNDUP(x, align) (-(-(x) & -(align))) /* * return the ending address of the block that x is in * eg, P2END(0x1234, 0x100) == 0x12ff (0x13*align - 1) * eg, P2END(0x5600, 0x100) == 0x56ff (0x57*align - 1) */ #define P2END(x, align) (-(~(x) & -(align))) /* * return x rounded up to the next phase (offset) within align. * phase should be < align. * eg, P2PHASEUP(0x1234, 0x100, 0x10) == 0x1310 (0x13*align + phase) * eg, P2PHASEUP(0x5600, 0x100, 0x10) == 0x5610 (0x56*align + phase) */ #define P2PHASEUP(x, align, phase) ((phase) - (((phase) - (x)) & -(align))) /* * return TRUE if adding len to off would cause it to cross an align * boundary. * eg, P2BOUNDARY(0x1234, 0xe0, 0x100) == TRUE (0x1234 + 0xe0 == 0x1314) * eg, P2BOUNDARY(0x1234, 0x50, 0x100) == FALSE (0x1234 + 0x50 == 0x1284) */ #define P2BOUNDARY(off, len, align) \ (((off) ^ ((off) + (len) - 1)) > (align) - 1) /* * Return TRUE if they have the same highest bit set. * eg, P2SAMEHIGHBIT(0x1234, 0x1001) == TRUE (the high bit is 0x1000) * eg, P2SAMEHIGHBIT(0x1234, 0x3010) == FALSE (high bit of 0x3010 is 0x2000) */ #define P2SAMEHIGHBIT(x, y) (((x) ^ (y)) < ((x) & (y))) /* * Typed version of the P2* macros. These macros should be used to ensure * that the result is correctly calculated based on the data type of (x), * which is passed in as the last argument, regardless of the data * type of the alignment. For example, if (x) is of type uint64_t, * and we want to round it up to a page boundary using "PAGESIZE" as * the alignment, we can do either * P2ROUNDUP(x, (uint64_t)PAGESIZE) * or * P2ROUNDUP_TYPED(x, PAGESIZE, uint64_t) */ #define P2ALIGN_TYPED(x, align, type) \ ((type)(x) & -(type)(align)) #define P2PHASE_TYPED(x, align, type) \ ((type)(x) & ((type)(align) - 1)) #define P2NPHASE_TYPED(x, align, type) \ (-(type)(x) & ((type)(align) - 1)) #define P2ROUNDUP_TYPED(x, align, type) \ (-(-(type)(x) & -(type)(align))) #define P2END_TYPED(x, align, type) \ (-(~(type)(x) & -(type)(align))) #define P2PHASEUP_TYPED(x, align, phase, type) \ ((type)(phase) - (((type)(phase) - (type)(x)) & -(type)(align))) #define P2CROSS_TYPED(x, y, align, type) \ (((type)(x) ^ (type)(y)) > (type)(align) - 1) #define P2SAMEHIGHBIT_TYPED(x, y, type) \ (((type)(x) ^ (type)(y)) < ((type)(x) & (type)(y))) /* * Macros to atomically increment/decrement a variable. mutex and var * must be pointers. */ #define INCR_COUNT(var, mutex) mutex_enter(mutex), (*(var))++, mutex_exit(mutex) #define DECR_COUNT(var, mutex) mutex_enter(mutex), (*(var))--, mutex_exit(mutex) /* * Macros to declare bitfields - the order in the parameter list is * Low to High - that is, declare bit 0 first. We only support 8-bit bitfields * because if a field crosses a byte boundary it's not likely to be meaningful * without reassembly in its nonnative endianness. */ #if defined(_BIT_FIELDS_LTOH) #define DECL_BITFIELD2(_a, _b) \ uint8_t _a, _b #define DECL_BITFIELD3(_a, _b, _c) \ uint8_t _a, _b, _c #define DECL_BITFIELD4(_a, _b, _c, _d) \ uint8_t _a, _b, _c, _d #define DECL_BITFIELD5(_a, _b, _c, _d, _e) \ uint8_t _a, _b, _c, _d, _e #define DECL_BITFIELD6(_a, _b, _c, _d, _e, _f) \ uint8_t _a, _b, _c, _d, _e, _f #define DECL_BITFIELD7(_a, _b, _c, _d, _e, _f, _g) \ uint8_t _a, _b, _c, _d, _e, _f, _g #define DECL_BITFIELD8(_a, _b, _c, _d, _e, _f, _g, _h) \ uint8_t _a, _b, _c, _d, _e, _f, _g, _h #elif defined(_BIT_FIELDS_HTOL) #define DECL_BITFIELD2(_a, _b) \ uint8_t _b, _a #define DECL_BITFIELD3(_a, _b, _c) \ uint8_t _c, _b, _a #define DECL_BITFIELD4(_a, _b, _c, _d) \ uint8_t _d, _c, _b, _a #define DECL_BITFIELD5(_a, _b, _c, _d, _e) \ uint8_t _e, _d, _c, _b, _a #define DECL_BITFIELD6(_a, _b, _c, _d, _e, _f) \ uint8_t _f, _e, _d, _c, _b, _a #define DECL_BITFIELD7(_a, _b, _c, _d, _e, _f, _g) \ uint8_t _g, _f, _e, _d, _c, _b, _a #define DECL_BITFIELD8(_a, _b, _c, _d, _e, _f, _g, _h) \ uint8_t _h, _g, _f, _e, _d, _c, _b, _a #else #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined #endif /* _BIT_FIELDS_LTOH */ #if defined(_KERNEL) && !defined(_KMEMUSER) && !defined(offsetof) /* avoid any possibility of clashing with version */ #define offsetof(s, m) ((size_t)(&(((s *)0)->m))) #endif /* * Find highest one bit set. * Returns bit number + 1 of highest bit that is set, otherwise returns 0. * High order bit is 31 (or 63 in _LP64 kernel). */ static __inline int highbit(unsigned long i) { #if defined(__FreeBSD__) && defined(_KERNEL) && defined(HAVE_INLINE_FLSL) return (flsl(i)); #else int h = 1; if (i == 0) return (0); #ifdef _LP64 if (i & 0xffffffff00000000ul) { h += 32; i >>= 32; } #endif if (i & 0xffff0000) { h += 16; i >>= 16; } if (i & 0xff00) { h += 8; i >>= 8; } if (i & 0xf0) { h += 4; i >>= 4; } if (i & 0xc) { h += 2; i >>= 2; } if (i & 0x2) { h += 1; } return (h); #endif } /* * Find highest one bit set. * Returns bit number + 1 of highest bit that is set, otherwise returns 0. */ static __inline int highbit64(uint64_t i) { #if defined(__FreeBSD__) && defined(_KERNEL) && defined(HAVE_INLINE_FLSLL) return (flsll(i)); #else int h = 1; if (i == 0) return (0); if (i & 0xffffffff00000000ULL) { h += 32; i >>= 32; } if (i & 0xffff0000) { h += 16; i >>= 16; } if (i & 0xff00) { h += 8; i >>= 8; } if (i & 0xf0) { h += 4; i >>= 4; } if (i & 0xc) { h += 2; i >>= 2; } if (i & 0x2) { h += 1; } return (h); #endif } #ifdef __cplusplus } #endif #endif /* _SYS_SYSMACROS_H */