11673e404SJohn Birrell /* 21673e404SJohn Birrell * CDDL HEADER START 31673e404SJohn Birrell * 41673e404SJohn Birrell * The contents of this file are subject to the terms of the 51673e404SJohn Birrell * Common Development and Distribution License (the "License"). 61673e404SJohn Birrell * You may not use this file except in compliance with the License. 71673e404SJohn Birrell * 81673e404SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91673e404SJohn Birrell * or http://www.opensolaris.org/os/licensing. 101673e404SJohn Birrell * See the License for the specific language governing permissions 111673e404SJohn Birrell * and limitations under the License. 121673e404SJohn Birrell * 131673e404SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 141673e404SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151673e404SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 161673e404SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 171673e404SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 181673e404SJohn Birrell * 191673e404SJohn Birrell * CDDL HEADER END 201673e404SJohn Birrell */ 211673e404SJohn Birrell /* 221673e404SJohn Birrell * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 231673e404SJohn Birrell * Use is subject to license terms. 241673e404SJohn Birrell */ 251673e404SJohn Birrell 261673e404SJohn Birrell #pragma ident "%Z%%M% %I% %E% SMI" 271673e404SJohn Birrell 281673e404SJohn Birrell /* 291673e404SJohn Birrell * Utility functions 301673e404SJohn Birrell */ 311673e404SJohn Birrell 321673e404SJohn Birrell #include <stdio.h> 331673e404SJohn Birrell #include <stdlib.h> 341673e404SJohn Birrell #include <string.h> 351673e404SJohn Birrell #include <libelf.h> 361673e404SJohn Birrell #include <gelf.h> 371673e404SJohn Birrell #include <errno.h> 381673e404SJohn Birrell #include <stdarg.h> 391673e404SJohn Birrell #include <pthread.h> 401673e404SJohn Birrell #include <unistd.h> 411673e404SJohn Birrell #include <sys/param.h> 421673e404SJohn Birrell 431673e404SJohn Birrell #include "ctftools.h" 441673e404SJohn Birrell #include "memory.h" 451673e404SJohn Birrell 461673e404SJohn Birrell static void (*terminate_cleanup)(void) = NULL; 471673e404SJohn Birrell 481673e404SJohn Birrell /* returns 1 if s1 == s2, 0 otherwise */ 491673e404SJohn Birrell int 501673e404SJohn Birrell streq(const char *s1, const char *s2) 511673e404SJohn Birrell { 521673e404SJohn Birrell if (s1 == NULL) { 531673e404SJohn Birrell if (s2 != NULL) 541673e404SJohn Birrell return (0); 551673e404SJohn Birrell } else if (s2 == NULL) 561673e404SJohn Birrell return (0); 571673e404SJohn Birrell else if (strcmp(s1, s2) != 0) 581673e404SJohn Birrell return (0); 591673e404SJohn Birrell 601673e404SJohn Birrell return (1); 611673e404SJohn Birrell } 621673e404SJohn Birrell 631673e404SJohn Birrell int 641673e404SJohn Birrell findelfsecidx(Elf *elf, const char *file, const char *tofind) 651673e404SJohn Birrell { 661673e404SJohn Birrell Elf_Scn *scn = NULL; 671673e404SJohn Birrell GElf_Ehdr ehdr; 681673e404SJohn Birrell GElf_Shdr shdr; 691673e404SJohn Birrell 701673e404SJohn Birrell if (gelf_getehdr(elf, &ehdr) == NULL) 711673e404SJohn Birrell elfterminate(file, "Couldn't read ehdr"); 721673e404SJohn Birrell 731673e404SJohn Birrell while ((scn = elf_nextscn(elf, scn)) != NULL) { 741673e404SJohn Birrell char *name; 751673e404SJohn Birrell 761673e404SJohn Birrell if (gelf_getshdr(scn, &shdr) == NULL) { 771673e404SJohn Birrell elfterminate(file, 781673e404SJohn Birrell "Couldn't read header for section %d", 791673e404SJohn Birrell elf_ndxscn(scn)); 801673e404SJohn Birrell } 811673e404SJohn Birrell 821673e404SJohn Birrell if ((name = elf_strptr(elf, ehdr.e_shstrndx, 831673e404SJohn Birrell (size_t)shdr.sh_name)) == NULL) { 841673e404SJohn Birrell elfterminate(file, 851673e404SJohn Birrell "Couldn't get name for section %d", 861673e404SJohn Birrell elf_ndxscn(scn)); 871673e404SJohn Birrell } 881673e404SJohn Birrell 891673e404SJohn Birrell if (strcmp(name, tofind) == 0) 901673e404SJohn Birrell return (elf_ndxscn(scn)); 911673e404SJohn Birrell } 921673e404SJohn Birrell 931673e404SJohn Birrell return (-1); 941673e404SJohn Birrell } 951673e404SJohn Birrell 961673e404SJohn Birrell size_t 971673e404SJohn Birrell elf_ptrsz(Elf *elf) 981673e404SJohn Birrell { 991673e404SJohn Birrell GElf_Ehdr ehdr; 1001673e404SJohn Birrell 1011673e404SJohn Birrell if (gelf_getehdr(elf, &ehdr) == NULL) { 1021673e404SJohn Birrell terminate("failed to read ELF header: %s\n", 1031673e404SJohn Birrell elf_errmsg(-1)); 1041673e404SJohn Birrell } 1051673e404SJohn Birrell 1061673e404SJohn Birrell if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 1071673e404SJohn Birrell return (4); 1081673e404SJohn Birrell else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 1091673e404SJohn Birrell return (8); 1101673e404SJohn Birrell else 1111673e404SJohn Birrell terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); 1121673e404SJohn Birrell 1131673e404SJohn Birrell /*NOTREACHED*/ 1141673e404SJohn Birrell return (0); 1151673e404SJohn Birrell } 1161673e404SJohn Birrell 1171673e404SJohn Birrell /*PRINTFLIKE2*/ 1181673e404SJohn Birrell static void 1191673e404SJohn Birrell whine(const char *type, const char *format, va_list ap) 1201673e404SJohn Birrell { 1211673e404SJohn Birrell int error = errno; 1221673e404SJohn Birrell 1231673e404SJohn Birrell fprintf(stderr, "%s: %s: ", type, progname); 1241673e404SJohn Birrell vfprintf(stderr, format, ap); 1251673e404SJohn Birrell 1261673e404SJohn Birrell if (format[strlen(format) - 1] != '\n') 1271673e404SJohn Birrell fprintf(stderr, ": %s\n", strerror(error)); 1281673e404SJohn Birrell } 1291673e404SJohn Birrell 1301673e404SJohn Birrell void 1311673e404SJohn Birrell set_terminate_cleanup(void (*cleanup)(void)) 1321673e404SJohn Birrell { 1331673e404SJohn Birrell terminate_cleanup = cleanup; 1341673e404SJohn Birrell } 1351673e404SJohn Birrell 1361673e404SJohn Birrell /*PRINTFLIKE1*/ 1371673e404SJohn Birrell void 1381673e404SJohn Birrell terminate(const char *format, ...) 1391673e404SJohn Birrell { 1401673e404SJohn Birrell va_list ap; 1411673e404SJohn Birrell 1421673e404SJohn Birrell va_start(ap, format); 1431673e404SJohn Birrell whine("ERROR", format, ap); 1441673e404SJohn Birrell va_end(ap); 1451673e404SJohn Birrell 1461673e404SJohn Birrell if (terminate_cleanup) 1471673e404SJohn Birrell terminate_cleanup(); 1481673e404SJohn Birrell 1491673e404SJohn Birrell if (getenv("CTF_ABORT_ON_TERMINATE") != NULL) 1501673e404SJohn Birrell abort(); 1511673e404SJohn Birrell #if defined(__FreeBSD__) 1521673e404SJohn Birrell /* 1531673e404SJohn Birrell * For the time being just output the termination message, but don't 1541673e404SJohn Birrell * return an exit status that would cause the build to fail. We need 1551673e404SJohn Birrell * to get as much stuff built as possible before going back and 1561673e404SJohn Birrell * figuring out what is wrong with certain files. 1571673e404SJohn Birrell */ 1581673e404SJohn Birrell exit(0); 1591673e404SJohn Birrell #else 1601673e404SJohn Birrell exit(1); 1611673e404SJohn Birrell #endif 1621673e404SJohn Birrell } 1631673e404SJohn Birrell 1641673e404SJohn Birrell /*PRINTFLIKE1*/ 1651673e404SJohn Birrell void 1661673e404SJohn Birrell aborterr(const char *format, ...) 1671673e404SJohn Birrell { 1681673e404SJohn Birrell va_list ap; 1691673e404SJohn Birrell 1701673e404SJohn Birrell va_start(ap, format); 1711673e404SJohn Birrell whine("ERROR", format, ap); 1721673e404SJohn Birrell va_end(ap); 1731673e404SJohn Birrell 1741673e404SJohn Birrell #if defined(sun) 1751673e404SJohn Birrell abort(); 1761673e404SJohn Birrell #else 1771673e404SJohn Birrell exit(0); 1781673e404SJohn Birrell #endif 1791673e404SJohn Birrell } 1801673e404SJohn Birrell 1811673e404SJohn Birrell /*PRINTFLIKE1*/ 1821673e404SJohn Birrell void 1831673e404SJohn Birrell warning(const char *format, ...) 1841673e404SJohn Birrell { 1851673e404SJohn Birrell va_list ap; 1861673e404SJohn Birrell 1871673e404SJohn Birrell va_start(ap, format); 1881673e404SJohn Birrell whine("WARNING", format, ap); 1891673e404SJohn Birrell va_end(ap); 1901673e404SJohn Birrell 1911673e404SJohn Birrell if (debug_level >= 3) 1921673e404SJohn Birrell terminate("Termination due to warning\n"); 1931673e404SJohn Birrell } 1941673e404SJohn Birrell 1951673e404SJohn Birrell /*PRINTFLIKE2*/ 1961673e404SJohn Birrell void 1971673e404SJohn Birrell vadebug(int level, const char *format, va_list ap) 1981673e404SJohn Birrell { 1991673e404SJohn Birrell if (level > debug_level) 2001673e404SJohn Birrell return; 2011673e404SJohn Birrell 2021673e404SJohn Birrell (void) fprintf(DEBUG_STREAM, "DEBUG: "); 2031673e404SJohn Birrell (void) vfprintf(DEBUG_STREAM, format, ap); 2041673e404SJohn Birrell fflush(DEBUG_STREAM); 2051673e404SJohn Birrell } 2061673e404SJohn Birrell 2071673e404SJohn Birrell /*PRINTFLIKE2*/ 2081673e404SJohn Birrell void 2091673e404SJohn Birrell debug(int level, const char *format, ...) 2101673e404SJohn Birrell { 2111673e404SJohn Birrell va_list ap; 2121673e404SJohn Birrell 2131673e404SJohn Birrell if (level > debug_level) 2141673e404SJohn Birrell return; 2151673e404SJohn Birrell 2161673e404SJohn Birrell va_start(ap, format); 2171673e404SJohn Birrell (void) vadebug(level, format, ap); 2181673e404SJohn Birrell va_end(ap); 2191673e404SJohn Birrell } 2201673e404SJohn Birrell 2211673e404SJohn Birrell char * 2221673e404SJohn Birrell mktmpname(const char *origname, const char *suffix) 2231673e404SJohn Birrell { 2241673e404SJohn Birrell char *newname; 2251673e404SJohn Birrell 2261673e404SJohn Birrell newname = xmalloc(strlen(origname) + strlen(suffix) + 1); 2271673e404SJohn Birrell (void) strcpy(newname, origname); 2281673e404SJohn Birrell (void) strcat(newname, suffix); 2291673e404SJohn Birrell return (newname); 2301673e404SJohn Birrell } 2311673e404SJohn Birrell 2321673e404SJohn Birrell /*PRINTFLIKE2*/ 2331673e404SJohn Birrell void 2341673e404SJohn Birrell elfterminate(const char *file, const char *fmt, ...) 2351673e404SJohn Birrell { 2361673e404SJohn Birrell static char msgbuf[BUFSIZ]; 2371673e404SJohn Birrell va_list ap; 2381673e404SJohn Birrell 2391673e404SJohn Birrell va_start(ap, fmt); 2401673e404SJohn Birrell vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 2411673e404SJohn Birrell va_end(ap); 2421673e404SJohn Birrell 2431673e404SJohn Birrell terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1)); 2441673e404SJohn Birrell } 2451673e404SJohn Birrell 2461673e404SJohn Birrell const char * 2471673e404SJohn Birrell tdesc_name(tdesc_t *tdp) 2481673e404SJohn Birrell { 2491673e404SJohn Birrell return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); 2501673e404SJohn Birrell } 2511673e404SJohn Birrell 2521673e404SJohn Birrell char *watch_address = NULL; 2531673e404SJohn Birrell int watch_length = 0; 2541673e404SJohn Birrell 2551673e404SJohn Birrell void 2561673e404SJohn Birrell watch_set(void *addr, int len) 2571673e404SJohn Birrell { 2581673e404SJohn Birrell watch_address = addr; 2591673e404SJohn Birrell watch_length = len; 2601673e404SJohn Birrell } 2611673e404SJohn Birrell 2621673e404SJohn Birrell void 2631673e404SJohn Birrell watch_dump(int v) 2641673e404SJohn Birrell { 2651673e404SJohn Birrell char *p = watch_address; 2661673e404SJohn Birrell int i; 2671673e404SJohn Birrell 2681673e404SJohn Birrell if (watch_address == NULL || watch_length == 0) 2691673e404SJohn Birrell return; 2701673e404SJohn Birrell 2711673e404SJohn Birrell printf("%d: watch %p len %d\n",v,watch_address,watch_length); 2721673e404SJohn Birrell for (i = 0; i < watch_length; i++) { 2731673e404SJohn Birrell if (*p >= 0x20 && *p < 0x7f) { 2741673e404SJohn Birrell printf(" %c",*p++ & 0xff); 2751673e404SJohn Birrell } else { 2761673e404SJohn Birrell printf(" %02x",*p++ & 0xff); 2771673e404SJohn Birrell } 2781673e404SJohn Birrell } 2791673e404SJohn Birrell printf("\n"); 2801673e404SJohn Birrell 2811673e404SJohn Birrell } 2821673e404SJohn Birrell 2831673e404SJohn Birrell 284