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#if HAVE_NBTOOL_CONFIG_H 33# include "nbtool_config.h" 34#endif 35 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <libelf.h> 40#include <gelf.h> 41#include <errno.h> 42#include <stdarg.h> 43#include <pthread.h> 44#include <unistd.h> 45#include <sys/param.h> 46 47#include "ctftools.h" 48#include "memory.h" 49 50static void (*terminate_cleanup)(void) = NULL; 51 52/* returns 1 if s1 == s2, 0 otherwise */ 53int 54streq(const char *s1, const char *s2) 55{ 56 if (s1 == NULL) { 57 if (s2 != NULL) 58 return (0); 59 } else if (s2 == NULL) 60 return (0); 61 else if (strcmp(s1, s2) != 0) 62 return (0); 63 64 return (1); 65} 66 67int 68findelfsecidx(Elf *elf, const char *file, const char *tofind) 69{ 70 Elf_Scn *scn = NULL; 71 GElf_Ehdr ehdr; 72 GElf_Shdr shdr; 73 74 if (gelf_getehdr(elf, &ehdr) == NULL) 75 elfterminate(file, "Couldn't read ehdr"); 76 77 while ((scn = elf_nextscn(elf, scn)) != NULL) { 78 char *name; 79 80 if (gelf_getshdr(scn, &shdr) == NULL) { 81 elfterminate(file, 82 "Couldn't read header for section %zu", 83 elf_ndxscn(scn)); 84 } 85 86 if ((name = elf_strptr(elf, ehdr.e_shstrndx, 87 (size_t)shdr.sh_name)) == NULL) { 88 elfterminate(file, 89 "Couldn't get name for section %zu", 90 elf_ndxscn(scn)); 91 } 92 93 if (strcmp(name, tofind) == 0) 94 return (elf_ndxscn(scn)); 95 } 96 97 return (-1); 98} 99 100size_t 101elf_ptrsz(Elf *elf) 102{ 103 GElf_Ehdr ehdr; 104 105 if (gelf_getehdr(elf, &ehdr) == NULL) { 106 terminate("failed to read ELF header: %s\n", 107 elf_errmsg(-1)); 108 } 109 110 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 111 return (4); 112 else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 113 return (8); 114 else 115 terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); 116 117 /*NOTREACHED*/ 118 return (0); 119} 120 121/*PRINTFLIKE2*/ 122static void 123whine(const char *type, const char *format, va_list ap) 124{ 125 int error = errno; 126 127 fprintf(stderr, "%s: %s: ", type, progname); 128 vfprintf(stderr, format, ap); 129 130 if (format[strlen(format) - 1] != '\n') 131 fprintf(stderr, ": %s\n", strerror(error)); 132} 133 134void 135set_terminate_cleanup(void (*cleanup)(void)) 136{ 137 terminate_cleanup = cleanup; 138} 139 140/*PRINTFLIKE1*/ 141void 142terminate(const char *format, ...) 143{ 144 va_list ap; 145 146 va_start(ap, format); 147 whine("ERROR", format, ap); 148 va_end(ap); 149 150 if (terminate_cleanup) 151 terminate_cleanup(); 152 153 if (getenv("CTF_ABORT_ON_TERMINATE") != NULL) 154 abort(); 155#if defined(__FreeBSD__) 156/* 157 * For the time being just output the termination message, but don't 158 * return an exit status that would cause the build to fail. We need 159 * to get as much stuff built as possible before going back and 160 * figuring out what is wrong with certain files. 161 */ 162 exit(0); 163#else 164 exit(1); 165#endif 166} 167 168/*PRINTFLIKE1*/ 169void 170aborterr(const char *format, ...) 171{ 172 va_list ap; 173 174 va_start(ap, format); 175 whine("ERROR", format, ap); 176 va_end(ap); 177 178#ifdef illumos 179 abort(); 180#else 181 exit(0); 182#endif 183} 184 185/*PRINTFLIKE1*/ 186void 187warning(const char *format, ...) 188{ 189 va_list ap; 190 191 va_start(ap, format); 192 whine("WARNING", format, ap); 193 va_end(ap); 194 195 if (debug_level >= 3) 196 terminate("Termination due to warning\n"); 197} 198 199/*PRINTFLIKE2*/ 200void 201vadebug(int level, const char *format, va_list ap) 202{ 203 if (level > debug_level) 204 return; 205 206 (void) fprintf(DEBUG_STREAM, "DEBUG: "); 207 (void) vfprintf(DEBUG_STREAM, format, ap); 208 fflush(DEBUG_STREAM); 209} 210 211/*PRINTFLIKE2*/ 212void 213debug(int level, const char *format, ...) 214{ 215 va_list ap; 216 217 if (level > debug_level) 218 return; 219 220 va_start(ap, format); 221 (void) vadebug(level, format, ap); 222 va_end(ap); 223} 224 225char * 226mktmpname(const char *origname, const char *suffix) 227{ 228 char *newname; 229 230 newname = xmalloc(strlen(origname) + strlen(suffix) + 1); 231 (void) strcpy(newname, origname); 232 (void) strcat(newname, suffix); 233 return (newname); 234} 235 236/*PRINTFLIKE2*/ 237void 238elfterminate(const char *file, const char *fmt, ...) 239{ 240 static char msgbuf[BUFSIZ]; 241 va_list ap; 242 243 va_start(ap, fmt); 244 vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 245 va_end(ap); 246 247 terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1)); 248} 249 250const char * 251tdesc_name(tdesc_t *tdp) 252{ 253 return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); 254} 255 256static char *watch_address = NULL; 257static int watch_length = 0; 258 259void 260watch_set(void *addr, int len) 261{ 262 watch_address = addr; 263 watch_length = len; 264} 265 266void 267watch_dump(int v) 268{ 269 char *p = watch_address; 270 int i; 271 272 if (watch_address == NULL || watch_length == 0) 273 return; 274 275 printf("%d: watch %p len %d\n",v,watch_address,watch_length); 276 for (i = 0; i < watch_length; i++) { 277 if (*p >= 0x20 && *p < 0x7f) { 278 printf(" %c",*p++ & 0xff); 279 } else { 280 printf(" %02x",*p++ & 0xff); 281 } 282 } 283 printf("\n"); 284 285} 286 287 288