1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#pragma ident "%Z%%M% %I% %E% SMI" 27 28/* 29 * Utility functions 30 */ 31 32#include <assert.h> 33#include <stdio.h> 34#include <stdlib.h> 35#include <string.h> 36#include <libelf.h> 37#include <gelf.h> 38#include <errno.h> 39#include <stdarg.h> 40#include <pthread.h> 41#include <unistd.h> 42#include <sys/param.h> 43 44#include "ctftools.h" 45#include "memory.h" 46 47static void (*terminate_cleanup)(void) = NULL; 48 49/* returns 1 if s1 == s2, 0 otherwise */ 50int 51streq(const char *s1, const char *s2) 52{ 53 if (s1 == NULL) { 54 if (s2 != NULL) 55 return (0); 56 } else if (s2 == NULL) 57 return (0); 58 else if (strcmp(s1, s2) != 0) 59 return (0); 60 61 return (1); 62} 63 64int 65findelfsecidx(Elf *elf, const char *file, const char *tofind) 66{ 67 Elf_Scn *scn = NULL; 68 GElf_Ehdr ehdr; 69 GElf_Shdr shdr; 70 71 if (gelf_getehdr(elf, &ehdr) == NULL) 72 elfterminate(file, "Couldn't read ehdr"); 73 74 while ((scn = elf_nextscn(elf, scn)) != NULL) { 75 char *name; 76 77 if (gelf_getshdr(scn, &shdr) == NULL) { 78 elfterminate(file, 79 "Couldn't read header for section %d", 80 elf_ndxscn(scn)); 81 } 82 83 if ((name = elf_strptr(elf, ehdr.e_shstrndx, 84 (size_t)shdr.sh_name)) == NULL) { 85 elfterminate(file, 86 "Couldn't get name for section %d", 87 elf_ndxscn(scn)); 88 } 89 90 if (strcmp(name, tofind) == 0) 91 return (elf_ndxscn(scn)); 92 } 93 94 return (-1); 95} 96 97size_t 98elf_ptrsz(Elf *elf) 99{ 100 GElf_Ehdr ehdr; 101 102 if (gelf_getehdr(elf, &ehdr) == NULL) { 103 terminate("failed to read ELF header: %s\n", 104 elf_errmsg(-1)); 105 } 106 107 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 108 return (4); 109 else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 110 return (8); 111 else 112 terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); 113 114 /*NOTREACHED*/ 115 return (0); 116} 117 118/*PRINTFLIKE2*/ 119static void 120whine(const char *type, const char *format, va_list ap) 121{ 122 int error = errno; 123 124 fprintf(stderr, "%s: %s: ", type, progname); 125 vfprintf(stderr, format, ap); 126 127 if (format[strlen(format) - 1] != '\n') 128 fprintf(stderr, ": %s\n", strerror(error)); 129} 130 131void 132set_terminate_cleanup(void (*cleanup)(void)) 133{ 134 terminate_cleanup = cleanup; 135} 136 137/*PRINTFLIKE1*/ 138void 139terminate(const char *format, ...) 140{ 141 va_list ap; 142 143 va_start(ap, format); 144 whine("ERROR", format, ap); 145 va_end(ap); 146 147 if (terminate_cleanup) 148 terminate_cleanup(); 149 150 if (getenv("CTF_ABORT_ON_TERMINATE") != NULL) 151 abort(); 152#if defined(__FreeBSD__) 153/* 154 * For the time being just output the termination message, but don't 155 * return an exit status that would cause the build to fail. We need 156 * to get as much stuff built as possible before going back and 157 * figuring out what is wrong with certain files. 158 */ 159 exit(0); 160#else 161 exit(1); 162#endif 163} 164 165/*PRINTFLIKE1*/ 166void 167aborterr(const char *format, ...) 168{ 169 va_list ap; 170 171 va_start(ap, format); 172 whine("ERROR", format, ap); 173 va_end(ap); 174 175#ifdef illumos 176 abort(); 177#else 178 exit(0); 179#endif 180} 181 182/*PRINTFLIKE1*/ 183void 184warning(const char *format, ...) 185{ 186 va_list ap; 187 188 va_start(ap, format); 189 whine("WARNING", format, ap); 190 va_end(ap); 191 192 if (debug_level >= 3) 193 terminate("Termination due to warning\n"); 194} 195 196/*PRINTFLIKE2*/ 197void 198vadebug(int level, const char *format, va_list ap) 199{ 200 if (level > debug_level) 201 return; 202 203 (void) fprintf(DEBUG_STREAM, "DEBUG: "); 204 (void) vfprintf(DEBUG_STREAM, format, ap); 205 fflush(DEBUG_STREAM); 206} 207 208/*PRINTFLIKE2*/ 209void 210debug(int level, const char *format, ...) 211{ 212 va_list ap; 213 214 if (level > debug_level) 215 return; 216 217 va_start(ap, format); 218 (void) vadebug(level, format, ap); 219 va_end(ap); 220} 221 222char * 223mktmpname(const char *origname, const char *suffix) 224{ 225 char *newname; 226 227 newname = xmalloc(strlen(origname) + strlen(suffix) + 1); 228 (void) strcpy(newname, origname); 229 (void) strcat(newname, suffix); 230 return (newname); 231} 232 233/*PRINTFLIKE2*/ 234void 235elfterminate(const char *file, const char *fmt, ...) 236{ 237 static char msgbuf[BUFSIZ]; 238 va_list ap; 239 240 va_start(ap, fmt); 241 vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 242 va_end(ap); 243 244 terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1)); 245} 246 247const char * 248tdesc_name(tdesc_t *tdp) 249{ 250 return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); 251} 252 253static char *watch_address = NULL; 254static int watch_length = 0; 255 256void 257watch_set(void *addr, int len) 258{ 259 watch_address = addr; 260 watch_length = len; 261} 262 263void 264watch_dump(int v) 265{ 266 char *p = watch_address; 267 int i; 268 269 if (watch_address == NULL || watch_length == 0) 270 return; 271 272 printf("%d: watch %p len %d\n",v,watch_address,watch_length); 273 for (i = 0; i < watch_length; i++) { 274 if (*p >= 0x20 && *p < 0x7f) { 275 printf(" %c",*p++ & 0xff); 276 } else { 277 printf(" %02x",*p++ & 0xff); 278 } 279 } 280 printf("\n"); 281 282} 283 284 285