xref: /freebsd/cddl/contrib/opensolaris/tools/ctf/cvt/util.c (revision 1673e4046da975ab0e2bf67d45499930ebab0dbe)
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