diff options
author | jb <jb@FreeBSD.org> | 2008-04-25 09:07:28 +0000 |
---|---|---|
committer | jb <jb@FreeBSD.org> | 2008-04-25 09:07:28 +0000 |
commit | ce71c4333f4e7b75db9902ddea203b1083ad4561 (patch) | |
tree | 759de4e92b645ce6ce4bba19feb1e8ab20798cfc /cddl/contrib/opensolaris/tools/ctf/cvt/util.c | |
parent | e01c5b125247b0d4bd1f054886d3956ae4bb63cf (diff) | |
download | FreeBSD-src-ce71c4333f4e7b75db9902ddea203b1083ad4561.zip FreeBSD-src-ce71c4333f4e7b75db9902ddea203b1083ad4561.tar.gz |
Vendor import of the CTF (Compact C Type Format) code used by DTrace
from OpenSolaris.
Diffstat (limited to 'cddl/contrib/opensolaris/tools/ctf/cvt/util.c')
-rw-r--r-- | cddl/contrib/opensolaris/tools/ctf/cvt/util.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/util.c b/cddl/contrib/opensolaris/tools/ctf/cvt/util.c new file mode 100644 index 0000000..0f36fa0 --- /dev/null +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/util.c @@ -0,0 +1,283 @@ +/* + * 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Utility functions + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libelf.h> +#include <gelf.h> +#include <errno.h> +#include <stdarg.h> +#include <pthread.h> +#include <unistd.h> +#include <sys/param.h> + +#include "ctftools.h" +#include "memory.h" + +static void (*terminate_cleanup)(void) = NULL; + +/* returns 1 if s1 == s2, 0 otherwise */ +int +streq(const char *s1, const char *s2) +{ + if (s1 == NULL) { + if (s2 != NULL) + return (0); + } else if (s2 == NULL) + return (0); + else if (strcmp(s1, s2) != 0) + return (0); + + return (1); +} + +int +findelfsecidx(Elf *elf, const char *file, const char *tofind) +{ + Elf_Scn *scn = NULL; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + + if (gelf_getehdr(elf, &ehdr) == NULL) + elfterminate(file, "Couldn't read ehdr"); + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + char *name; + + if (gelf_getshdr(scn, &shdr) == NULL) { + elfterminate(file, + "Couldn't read header for section %d", + elf_ndxscn(scn)); + } + + if ((name = elf_strptr(elf, ehdr.e_shstrndx, + (size_t)shdr.sh_name)) == NULL) { + elfterminate(file, + "Couldn't get name for section %d", + elf_ndxscn(scn)); + } + + if (strcmp(name, tofind) == 0) + return (elf_ndxscn(scn)); + } + + return (-1); +} + +size_t +elf_ptrsz(Elf *elf) +{ + GElf_Ehdr ehdr; + + if (gelf_getehdr(elf, &ehdr) == NULL) { + terminate("failed to read ELF header: %s\n", + elf_errmsg(-1)); + } + + if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) + return (4); + else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) + return (8); + else + terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); + + /*NOTREACHED*/ + return (0); +} + +/*PRINTFLIKE2*/ +static void +whine(const char *type, const char *format, va_list ap) +{ + int error = errno; + + fprintf(stderr, "%s: %s: ", type, progname); + vfprintf(stderr, format, ap); + + if (format[strlen(format) - 1] != '\n') + fprintf(stderr, ": %s\n", strerror(error)); +} + +void +set_terminate_cleanup(void (*cleanup)(void)) +{ + terminate_cleanup = cleanup; +} + +/*PRINTFLIKE1*/ +void +terminate(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + whine("ERROR", format, ap); + va_end(ap); + + if (terminate_cleanup) + terminate_cleanup(); + + if (getenv("CTF_ABORT_ON_TERMINATE") != NULL) + abort(); +#if defined(__FreeBSD__) +/* + * For the time being just output the termination message, but don't + * return an exit status that would cause the build to fail. We need + * to get as much stuff built as possible before going back and + * figuring out what is wrong with certain files. + */ + exit(0); +#else + exit(1); +#endif +} + +/*PRINTFLIKE1*/ +void +aborterr(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + whine("ERROR", format, ap); + va_end(ap); + +#if defined(sun) + abort(); +#else + exit(0); +#endif +} + +/*PRINTFLIKE1*/ +void +warning(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + whine("WARNING", format, ap); + va_end(ap); + + if (debug_level >= 3) + terminate("Termination due to warning\n"); +} + +/*PRINTFLIKE2*/ +void +vadebug(int level, const char *format, va_list ap) +{ + if (level > debug_level) + return; + + (void) fprintf(DEBUG_STREAM, "DEBUG: "); + (void) vfprintf(DEBUG_STREAM, format, ap); + fflush(DEBUG_STREAM); +} + +/*PRINTFLIKE2*/ +void +debug(int level, const char *format, ...) +{ + va_list ap; + + if (level > debug_level) + return; + + va_start(ap, format); + (void) vadebug(level, format, ap); + va_end(ap); +} + +char * +mktmpname(const char *origname, const char *suffix) +{ + char *newname; + + newname = xmalloc(strlen(origname) + strlen(suffix) + 1); + (void) strcpy(newname, origname); + (void) strcat(newname, suffix); + return (newname); +} + +/*PRINTFLIKE2*/ +void +elfterminate(const char *file, const char *fmt, ...) +{ + static char msgbuf[BUFSIZ]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); + va_end(ap); + + terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1)); +} + +const char * +tdesc_name(tdesc_t *tdp) +{ + return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); +} + +char *watch_address = NULL; +int watch_length = 0; + +void +watch_set(void *addr, int len) +{ + watch_address = addr; + watch_length = len; +} + +void +watch_dump(int v) +{ + char *p = watch_address; + int i; + + if (watch_address == NULL || watch_length == 0) + return; + + printf("%d: watch %p len %d\n",v,watch_address,watch_length); + for (i = 0; i < watch_length; i++) { + if (*p >= 0x20 && *p < 0x7f) { + printf(" %c",*p++ & 0xff); + } else { + printf(" %02x",*p++ & 0xff); + } + } + printf("\n"); + +} + + |