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 47 static void (*terminate_cleanup)(void) = NULL; 48 49 /* returns 1 if s1 == s2, 0 otherwise */ 50 int 51 streq(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 64 int 65 findelfsecidx(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 97 size_t 98 elf_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*/ 119 static void 120 whine(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 131 void 132 set_terminate_cleanup(void (*cleanup)(void)) 133 { 134 terminate_cleanup = cleanup; 135 } 136 137 /*PRINTFLIKE1*/ 138 void 139 terminate(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*/ 166 void 167 aborterr(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*/ 183 void 184 warning(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*/ 197 void 198 vadebug(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*/ 209 void 210 debug(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 222 char * 223 mktmpname(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*/ 234 void 235 elfterminate(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 247 const char * 248 tdesc_name(tdesc_t *tdp) 249 { 250 return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); 251 } 252 253 static char *watch_address = NULL; 254 static int watch_length = 0; 255 256 void 257 watch_set(void *addr, int len) 258 { 259 watch_address = addr; 260 watch_length = len; 261 } 262 263 void 264 watch_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