10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51882Sjohnlev * Common Development and Distribution License (the "License"). 61882Sjohnlev * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 221882Sjohnlev * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * Utility functions 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <stdio.h> 330Sstevel@tonic-gate #include <stdlib.h> 340Sstevel@tonic-gate #include <string.h> 350Sstevel@tonic-gate #include <libelf.h> 360Sstevel@tonic-gate #include <gelf.h> 370Sstevel@tonic-gate #include <errno.h> 380Sstevel@tonic-gate #include <stdarg.h> 390Sstevel@tonic-gate #include <pthread.h> 400Sstevel@tonic-gate #include <unistd.h> 410Sstevel@tonic-gate #include <sys/param.h> 420Sstevel@tonic-gate 430Sstevel@tonic-gate #include "ctftools.h" 440Sstevel@tonic-gate #include "memory.h" 450Sstevel@tonic-gate 460Sstevel@tonic-gate static void (*terminate_cleanup)() = NULL; 470Sstevel@tonic-gate 480Sstevel@tonic-gate /* returns 1 if s1 == s2, 0 otherwise */ 490Sstevel@tonic-gate int 50*2722Sjohnlev streq(const char *s1, const char *s2) 510Sstevel@tonic-gate { 520Sstevel@tonic-gate if (s1 == NULL) { 530Sstevel@tonic-gate if (s2 != NULL) 540Sstevel@tonic-gate return (0); 550Sstevel@tonic-gate } else if (s2 == NULL) 560Sstevel@tonic-gate return (0); 570Sstevel@tonic-gate else if (strcmp(s1, s2) != 0) 580Sstevel@tonic-gate return (0); 590Sstevel@tonic-gate 600Sstevel@tonic-gate return (1); 610Sstevel@tonic-gate } 620Sstevel@tonic-gate 630Sstevel@tonic-gate int 641951Sjohnlev findelfsecidx(Elf *elf, const char *file, const char *tofind) 650Sstevel@tonic-gate { 660Sstevel@tonic-gate Elf_Scn *scn = NULL; 670Sstevel@tonic-gate GElf_Ehdr ehdr; 680Sstevel@tonic-gate GElf_Shdr shdr; 690Sstevel@tonic-gate 701951Sjohnlev if (gelf_getehdr(elf, &ehdr) == NULL) 711951Sjohnlev elfterminate(file, "Couldn't read ehdr"); 720Sstevel@tonic-gate 730Sstevel@tonic-gate while ((scn = elf_nextscn(elf, scn)) != NULL) { 740Sstevel@tonic-gate char *name; 750Sstevel@tonic-gate 761951Sjohnlev if (gelf_getshdr(scn, &shdr) == NULL) { 771951Sjohnlev elfterminate(file, 781951Sjohnlev "Couldn't read header for section %d", 791951Sjohnlev elf_ndxscn(scn)); 801951Sjohnlev } 811951Sjohnlev 821951Sjohnlev if ((name = elf_strptr(elf, ehdr.e_shstrndx, 830Sstevel@tonic-gate (size_t)shdr.sh_name)) == NULL) { 841951Sjohnlev elfterminate(file, 851951Sjohnlev "Couldn't get name for section %d", 861951Sjohnlev elf_ndxscn(scn)); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate if (strcmp(name, tofind) == 0) 900Sstevel@tonic-gate return (elf_ndxscn(scn)); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate return (-1); 940Sstevel@tonic-gate } 950Sstevel@tonic-gate 96*2722Sjohnlev size_t 97*2722Sjohnlev elf_ptrsz(Elf *elf) 98*2722Sjohnlev { 99*2722Sjohnlev GElf_Ehdr ehdr; 100*2722Sjohnlev 101*2722Sjohnlev if (gelf_getehdr(elf, &ehdr) == NULL) { 102*2722Sjohnlev terminate("failed to read ELF header: %s\n", 103*2722Sjohnlev elf_errmsg(-1)); 104*2722Sjohnlev } 105*2722Sjohnlev 106*2722Sjohnlev if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 107*2722Sjohnlev return (4); 108*2722Sjohnlev else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) 109*2722Sjohnlev return (8); 110*2722Sjohnlev else 111*2722Sjohnlev terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]); 112*2722Sjohnlev 113*2722Sjohnlev /*NOTREACHED*/ 114*2722Sjohnlev return (0); 115*2722Sjohnlev } 116*2722Sjohnlev 1170Sstevel@tonic-gate /*PRINTFLIKE2*/ 1180Sstevel@tonic-gate static void 1190Sstevel@tonic-gate whine(char *type, char *format, va_list ap) 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate int error = errno; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate fprintf(stderr, "%s: %s: ", type, progname); 1240Sstevel@tonic-gate vfprintf(stderr, format, ap); 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate if (format[strlen(format) - 1] != '\n') 1270Sstevel@tonic-gate fprintf(stderr, ": %s\n", strerror(error)); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate void 1310Sstevel@tonic-gate set_terminate_cleanup(void (*cleanup)()) 1320Sstevel@tonic-gate { 1330Sstevel@tonic-gate terminate_cleanup = cleanup; 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate /*PRINTFLIKE1*/ 1370Sstevel@tonic-gate void 1380Sstevel@tonic-gate terminate(char *format, ...) 1390Sstevel@tonic-gate { 1401951Sjohnlev va_list ap; 1410Sstevel@tonic-gate 1421951Sjohnlev va_start(ap, format); 1431951Sjohnlev whine("ERROR", format, ap); 1441951Sjohnlev va_end(ap); 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate if (terminate_cleanup) 1470Sstevel@tonic-gate terminate_cleanup(); 1480Sstevel@tonic-gate 1491951Sjohnlev if (getenv("CTF_ABORT_ON_TERMINATE") != NULL) 1501951Sjohnlev abort(); 1510Sstevel@tonic-gate exit(1); 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate /*PRINTFLIKE1*/ 1550Sstevel@tonic-gate void 1561951Sjohnlev aborterr(char *format, ...) 1571951Sjohnlev { 1581951Sjohnlev va_list ap; 1591951Sjohnlev 1601951Sjohnlev va_start(ap, format); 1611951Sjohnlev whine("ERROR", format, ap); 1621951Sjohnlev va_end(ap); 1631951Sjohnlev 1641951Sjohnlev abort(); 1651951Sjohnlev } 1661951Sjohnlev 1671951Sjohnlev /*PRINTFLIKE1*/ 1681951Sjohnlev void 1690Sstevel@tonic-gate warning(char *format, ...) 1700Sstevel@tonic-gate { 1710Sstevel@tonic-gate va_list ap; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate va_start(ap, format); 1740Sstevel@tonic-gate whine("WARNING", format, ap); 1750Sstevel@tonic-gate va_end(ap); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate if (debug_level >= 3) 1780Sstevel@tonic-gate terminate("Termination due to warning\n"); 1790Sstevel@tonic-gate } 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate /*PRINTFLIKE2*/ 1820Sstevel@tonic-gate void 1830Sstevel@tonic-gate vadebug(int level, char *format, va_list ap) 1840Sstevel@tonic-gate { 1850Sstevel@tonic-gate if (level > debug_level) 1860Sstevel@tonic-gate return; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate (void) fprintf(DEBUG_STREAM, "DEBUG: "); 1890Sstevel@tonic-gate (void) vfprintf(DEBUG_STREAM, format, ap); 1900Sstevel@tonic-gate fflush(DEBUG_STREAM); 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate /*PRINTFLIKE2*/ 1940Sstevel@tonic-gate void 1950Sstevel@tonic-gate debug(int level, char *format, ...) 1960Sstevel@tonic-gate { 1970Sstevel@tonic-gate va_list ap; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate if (level > debug_level) 2000Sstevel@tonic-gate return; 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate va_start(ap, format); 2030Sstevel@tonic-gate (void) vadebug(level, format, ap); 2040Sstevel@tonic-gate va_end(ap); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate char * 2080Sstevel@tonic-gate mktmpname(const char *origname, const char *suffix) 2090Sstevel@tonic-gate { 2100Sstevel@tonic-gate char *newname; 2110Sstevel@tonic-gate 2121882Sjohnlev newname = xmalloc(strlen(origname) + strlen(suffix) + 1); 2131882Sjohnlev (void) strcpy(newname, origname); 2141882Sjohnlev (void) strcat(newname, suffix); 2150Sstevel@tonic-gate return (newname); 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /*PRINTFLIKE2*/ 2190Sstevel@tonic-gate void 2200Sstevel@tonic-gate elfterminate(const char *file, const char *fmt, ...) 2210Sstevel@tonic-gate { 2220Sstevel@tonic-gate static char msgbuf[BUFSIZ]; 2230Sstevel@tonic-gate va_list ap; 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate va_start(ap, fmt); 2260Sstevel@tonic-gate vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap); 2270Sstevel@tonic-gate va_end(ap); 2280Sstevel@tonic-gate 2291951Sjohnlev terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1)); 2300Sstevel@tonic-gate } 2311882Sjohnlev 2321882Sjohnlev const char * 2331882Sjohnlev tdesc_name(tdesc_t *tdp) 2341882Sjohnlev { 2351882Sjohnlev return (tdp->t_name == NULL ? "(anon)" : tdp->t_name); 2361882Sjohnlev } 237