1178481Sjb/* 2178481Sjb * CDDL HEADER START 3178481Sjb * 4178481Sjb * The contents of this file are subject to the terms of the 5178481Sjb * Common Development and Distribution License (the "License"). 6178481Sjb * You may not use this file except in compliance with the License. 7178481Sjb * 8178481Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178481Sjb * or http://www.opensolaris.org/os/licensing. 10178481Sjb * See the License for the specific language governing permissions 11178481Sjb * and limitations under the License. 12178481Sjb * 13178481Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178481Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178481Sjb * If applicable, add the following below this CDDL HEADER, with the 16178481Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178481Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178481Sjb * 19178481Sjb * CDDL HEADER END 20178481Sjb */ 21178481Sjb/* 22178481Sjb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23178481Sjb * Use is subject to license terms. 24178481Sjb */ 25178481Sjb 26178481Sjb#pragma ident "%Z%%M% %I% %E% SMI" 27178481Sjb 28178481Sjb/* 29178481Sjb * Utility functions 30178481Sjb */ 31178481Sjb 32178481Sjb#include <stdio.h> 33178481Sjb#include <stdlib.h> 34178481Sjb#include <string.h> 35178481Sjb#include <libelf.h> 36178481Sjb#include <gelf.h> 37178481Sjb#include <errno.h> 38178481Sjb#include <stdarg.h> 39178481Sjb#include <pthread.h> 40178481Sjb#include <unistd.h> 41178481Sjb#include <sys/param.h> 42178481Sjb 43178481Sjb#include "ctftools.h" 44178481Sjb#include "memory.h" 45178481Sjb 46178544Sjbstatic void (*terminate_cleanup)(void) = NULL; 47178481Sjb 48178481Sjb/* returns 1 if s1 == s2, 0 otherwise */ 49178481Sjbint 50178481Sjbstreq(const char *s1, const char *s2) 51178481Sjb{ 52178481Sjb if (s1 == NULL) { 53178481Sjb if (s2 != NULL) 54178481Sjb return (0); 55178481Sjb } else if (s2 == NULL) 56178481Sjb return (0); 57178481Sjb else if (strcmp(s1, s2) != 0) 58178481Sjb return (0); 59178481Sjb 60178481Sjb return (1); 61178481Sjb} 62178481Sjb 63178481Sjbint 64178481Sjbfindelfsecidx(Elf *elf, const char *file, const char *tofind) 65178481Sjb{ 66178481Sjb Elf_Scn *scn = NULL; 67178481Sjb GElf_Ehdr ehdr; 68178481Sjb GElf_Shdr shdr; 69178481Sjb 70178481Sjb if (gelf_getehdr(elf, &ehdr) == NULL) 71178481Sjb elfterminate(file, "Couldn't read ehdr"); 72178481Sjb 73178481Sjb while ((scn = elf_nextscn(elf, scn)) != NULL) { 74178481Sjb char *name; 75178481Sjb 76178481Sjb if (gelf_getshdr(scn, &shdr) == NULL) { 77178481Sjb elfterminate(file, 78178481Sjb "Couldn't read header for section %d", 79178481Sjb elf_ndxscn(scn)); 80178481Sjb } 81178481Sjb 82178481Sjb if ((name = elf_strptr(elf, ehdr.e_shstrndx, 83178481Sjb (size_t)shdr.sh_name)) == NULL) { 84178481Sjb elfterminate(file, 85178481Sjb "Couldn't get name for section %d", 86178481Sjb elf_ndxscn(scn)); 87178481Sjb } 88178481Sjb 89178481Sjb if (strcmp(name, tofind) == 0) 90178481Sjb return (elf_ndxscn(scn)); 91178481Sjb } 92178481Sjb 93178481Sjb return (-1); 94178481Sjb} 95178481Sjb 96178481Sjbsize_t 97178481Sjbelf_ptrsz(Elf *elf) 98178481Sjb{ 99178481Sjb GElf_Ehdr ehdr; 100178481Sjb 101178481Sjb if (gelf_getehdr(elf, &ehdr) == NULL) { 102178481Sjb terminate("failed to read ELF header: %s\n", 103178481Sjb elf_errmsg(-1)); 104178481Sjb } 105178481Sjb 106178481Sjb if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 107178481Sjb return (4); 108178481Sjb else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 109178481Sjb return (8); 110178481Sjb else 111178481Sjb terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); 112178481Sjb 113178481Sjb /*NOTREACHED*/ 114178481Sjb return (0); 115178481Sjb} 116178481Sjb 117178481Sjb/*PRINTFLIKE2*/ 118178481Sjbstatic void 119178544Sjbwhine(const char *type, const char *format, va_list ap) 120178481Sjb{ 121178481Sjb int error = errno; 122178481Sjb 123178481Sjb fprintf(stderr, "%s: %s: ", type, progname); 124178481Sjb vfprintf(stderr, format, ap); 125178481Sjb 126178481Sjb if (format[strlen(format) - 1] != '\n') 127178481Sjb fprintf(stderr, ": %s\n", strerror(error)); 128178481Sjb} 129178481Sjb 130178481Sjbvoid 131178544Sjbset_terminate_cleanup(void (*cleanup)(void)) 132178481Sjb{ 133178481Sjb terminate_cleanup = cleanup; 134178481Sjb} 135178481Sjb 136178481Sjb/*PRINTFLIKE1*/ 137178481Sjbvoid 138178544Sjbterminate(const char *format, ...) 139178481Sjb{ 140178481Sjb va_list ap; 141178481Sjb 142178481Sjb va_start(ap, format); 143178481Sjb whine("ERROR", format, ap); 144178481Sjb va_end(ap); 145178481Sjb 146178481Sjb if (terminate_cleanup) 147178481Sjb terminate_cleanup(); 148178481Sjb 149178481Sjb if (getenv("CTF_ABORT_ON_TERMINATE") != NULL) 150178481Sjb abort(); 151178544Sjb#if defined(__FreeBSD__) 152178544Sjb/* 153178544Sjb * For the time being just output the termination message, but don't 154178544Sjb * return an exit status that would cause the build to fail. We need 155178544Sjb * to get as much stuff built as possible before going back and 156178544Sjb * figuring out what is wrong with certain files. 157178544Sjb */ 158178544Sjb exit(0); 159178544Sjb#else 160178481Sjb exit(1); 161178544Sjb#endif 162178481Sjb} 163178481Sjb 164178481Sjb/*PRINTFLIKE1*/ 165178481Sjbvoid 166178544Sjbaborterr(const char *format, ...) 167178481Sjb{ 168178481Sjb va_list ap; 169178481Sjb 170178481Sjb va_start(ap, format); 171178481Sjb whine("ERROR", format, ap); 172178481Sjb va_end(ap); 173178481Sjb 174178544Sjb#if defined(sun) 175178481Sjb abort(); 176178544Sjb#else 177178544Sjb exit(0); 178178544Sjb#endif 179178481Sjb} 180178481Sjb 181178481Sjb/*PRINTFLIKE1*/ 182178481Sjbvoid 183178544Sjbwarning(const char *format, ...) 184178481Sjb{ 185178481Sjb va_list ap; 186178481Sjb 187178481Sjb va_start(ap, format); 188178481Sjb whine("WARNING", format, ap); 189178481Sjb va_end(ap); 190178481Sjb 191178481Sjb if (debug_level >= 3) 192178481Sjb terminate("Termination due to warning\n"); 193178481Sjb} 194178481Sjb 195178481Sjb/*PRINTFLIKE2*/ 196178481Sjbvoid 197178544Sjbvadebug(int level, const char *format, va_list ap) 198178481Sjb{ 199178481Sjb if (level > debug_level) 200178481Sjb return; 201178481Sjb 202178481Sjb (void) fprintf(DEBUG_STREAM, "DEBUG: "); 203178481Sjb (void) vfprintf(DEBUG_STREAM, format, ap); 204178481Sjb fflush(DEBUG_STREAM); 205178481Sjb} 206178481Sjb 207178481Sjb/*PRINTFLIKE2*/ 208178481Sjbvoid 209178544Sjbdebug(int level, const char *format, ...) 210178481Sjb{ 211178481Sjb va_list ap; 212178481Sjb 213178481Sjb if (level > debug_level) 214178481Sjb return; 215178481Sjb 216178481Sjb va_start(ap, format); 217178481Sjb (void) vadebug(level, format, ap); 218178481Sjb va_end(ap); 219178481Sjb} 220178481Sjb 221178481Sjbchar * 222178481Sjbmktmpname(const char *origname, const char *suffix) 223178481Sjb{ 224178481Sjb char *newname; 225178481Sjb 226178481Sjb newname = xmalloc(strlen(origname) + strlen(suffix) + 1); 227178481Sjb (void) strcpy(newname, origname); 228178481Sjb (void) strcat(newname, suffix); 229178481Sjb return (newname); 230178481Sjb} 231178481Sjb 232178481Sjb/*PRINTFLIKE2*/ 233178481Sjbvoid 234178481Sjbelfterminate(const char *file, const char *fmt, ...) 235178481Sjb{ 236178481Sjb static char msgbuf[BUFSIZ]; 237178481Sjb va_list ap; 238178481Sjb 239178481Sjb va_start(ap, fmt); 240178481Sjb vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 241178481Sjb va_end(ap); 242178481Sjb 243178481Sjb terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1)); 244178481Sjb} 245178481Sjb 246178481Sjbconst char * 247178481Sjbtdesc_name(tdesc_t *tdp) 248178481Sjb{ 249178481Sjb return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); 250178481Sjb} 251178544Sjb 252249656Sedstatic char *watch_address = NULL; 253249656Sedstatic int watch_length = 0; 254178544Sjb 255178544Sjbvoid 256178544Sjbwatch_set(void *addr, int len) 257178544Sjb{ 258178544Sjb watch_address = addr; 259178544Sjb watch_length = len; 260178544Sjb} 261178544Sjb 262178544Sjbvoid 263178544Sjbwatch_dump(int v) 264178544Sjb{ 265178544Sjb char *p = watch_address; 266178544Sjb int i; 267178544Sjb 268178544Sjb if (watch_address == NULL || watch_length == 0) 269178544Sjb return; 270178544Sjb 271178544Sjb printf("%d: watch %p len %d\n",v,watch_address,watch_length); 272178544Sjb for (i = 0; i < watch_length; i++) { 273178544Sjb if (*p >= 0x20 && *p < 0x7f) { 274178544Sjb printf(" %c",*p++ & 0xff); 275178544Sjb } else { 276178544Sjb printf(" %02x",*p++ & 0xff); 277178544Sjb } 278178544Sjb } 279178544Sjb printf("\n"); 280178544Sjb 281178544Sjb} 282178544Sjb 283178544Sjb 284