xref: /freebsd/cddl/contrib/opensolaris/tools/ctf/cvt/util.c (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
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 
32*9e5787d2SMatt Macy #include <assert.h>
331673e404SJohn Birrell #include <stdio.h>
341673e404SJohn Birrell #include <stdlib.h>
351673e404SJohn Birrell #include <string.h>
361673e404SJohn Birrell #include <libelf.h>
371673e404SJohn Birrell #include <gelf.h>
381673e404SJohn Birrell #include <errno.h>
391673e404SJohn Birrell #include <stdarg.h>
401673e404SJohn Birrell #include <pthread.h>
411673e404SJohn Birrell #include <unistd.h>
421673e404SJohn Birrell #include <sys/param.h>
431673e404SJohn Birrell 
441673e404SJohn Birrell #include "ctftools.h"
451673e404SJohn Birrell #include "memory.h"
461673e404SJohn Birrell 
47c01977edSJohn Birrell static void (*terminate_cleanup)(void) = NULL;
481673e404SJohn Birrell 
491673e404SJohn Birrell /* returns 1 if s1 == s2, 0 otherwise */
501673e404SJohn Birrell int
streq(const char * s1,const char * s2)511673e404SJohn Birrell streq(const char *s1, const char *s2)
521673e404SJohn Birrell {
531673e404SJohn Birrell 	if (s1 == NULL) {
541673e404SJohn Birrell 		if (s2 != NULL)
551673e404SJohn Birrell 			return (0);
561673e404SJohn Birrell 	} else if (s2 == NULL)
571673e404SJohn Birrell 		return (0);
581673e404SJohn Birrell 	else if (strcmp(s1, s2) != 0)
591673e404SJohn Birrell 		return (0);
601673e404SJohn Birrell 
611673e404SJohn Birrell 	return (1);
621673e404SJohn Birrell }
631673e404SJohn Birrell 
641673e404SJohn Birrell int
findelfsecidx(Elf * elf,const char * file,const char * tofind)651673e404SJohn Birrell findelfsecidx(Elf *elf, const char *file, const char *tofind)
661673e404SJohn Birrell {
671673e404SJohn Birrell 	Elf_Scn *scn = NULL;
681673e404SJohn Birrell 	GElf_Ehdr ehdr;
691673e404SJohn Birrell 	GElf_Shdr shdr;
701673e404SJohn Birrell 
711673e404SJohn Birrell 	if (gelf_getehdr(elf, &ehdr) == NULL)
721673e404SJohn Birrell 		elfterminate(file, "Couldn't read ehdr");
731673e404SJohn Birrell 
741673e404SJohn Birrell 	while ((scn = elf_nextscn(elf, scn)) != NULL) {
751673e404SJohn Birrell 		char *name;
761673e404SJohn Birrell 
771673e404SJohn Birrell 		if (gelf_getshdr(scn, &shdr) == NULL) {
781673e404SJohn Birrell 			elfterminate(file,
791673e404SJohn Birrell 			    "Couldn't read header for section %d",
801673e404SJohn Birrell 			    elf_ndxscn(scn));
811673e404SJohn Birrell 		}
821673e404SJohn Birrell 
831673e404SJohn Birrell 		if ((name = elf_strptr(elf, ehdr.e_shstrndx,
841673e404SJohn Birrell 		    (size_t)shdr.sh_name)) == NULL) {
851673e404SJohn Birrell 			elfterminate(file,
861673e404SJohn Birrell 			    "Couldn't get name for section %d",
871673e404SJohn Birrell 			    elf_ndxscn(scn));
881673e404SJohn Birrell 		}
891673e404SJohn Birrell 
901673e404SJohn Birrell 		if (strcmp(name, tofind) == 0)
911673e404SJohn Birrell 			return (elf_ndxscn(scn));
921673e404SJohn Birrell 	}
931673e404SJohn Birrell 
941673e404SJohn Birrell 	return (-1);
951673e404SJohn Birrell }
961673e404SJohn Birrell 
971673e404SJohn Birrell size_t
elf_ptrsz(Elf * elf)981673e404SJohn Birrell elf_ptrsz(Elf *elf)
991673e404SJohn Birrell {
1001673e404SJohn Birrell 	GElf_Ehdr ehdr;
1011673e404SJohn Birrell 
1021673e404SJohn Birrell 	if (gelf_getehdr(elf, &ehdr) == NULL) {
1031673e404SJohn Birrell 		terminate("failed to read ELF header: %s\n",
1041673e404SJohn Birrell 		    elf_errmsg(-1));
1051673e404SJohn Birrell 	}
1061673e404SJohn Birrell 
1071673e404SJohn Birrell 	if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
1081673e404SJohn Birrell 		return (4);
1091673e404SJohn Birrell 	else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
1101673e404SJohn Birrell 		return (8);
1111673e404SJohn Birrell 	else
1121673e404SJohn Birrell 		terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]);
1131673e404SJohn Birrell 
1141673e404SJohn Birrell 	/*NOTREACHED*/
1151673e404SJohn Birrell 	return (0);
1161673e404SJohn Birrell }
1171673e404SJohn Birrell 
1181673e404SJohn Birrell /*PRINTFLIKE2*/
1191673e404SJohn Birrell static void
whine(const char * type,const char * format,va_list ap)120c01977edSJohn Birrell whine(const char *type, const char *format, va_list ap)
1211673e404SJohn Birrell {
1221673e404SJohn Birrell 	int error = errno;
1231673e404SJohn Birrell 
1241673e404SJohn Birrell 	fprintf(stderr, "%s: %s: ", type, progname);
1251673e404SJohn Birrell 	vfprintf(stderr, format, ap);
1261673e404SJohn Birrell 
1271673e404SJohn Birrell 	if (format[strlen(format) - 1] != '\n')
1281673e404SJohn Birrell 		fprintf(stderr, ": %s\n", strerror(error));
1291673e404SJohn Birrell }
1301673e404SJohn Birrell 
1311673e404SJohn Birrell void
set_terminate_cleanup(void (* cleanup)(void))132c01977edSJohn Birrell set_terminate_cleanup(void (*cleanup)(void))
1331673e404SJohn Birrell {
1341673e404SJohn Birrell 	terminate_cleanup = cleanup;
1351673e404SJohn Birrell }
1361673e404SJohn Birrell 
1371673e404SJohn Birrell /*PRINTFLIKE1*/
1381673e404SJohn Birrell void
terminate(const char * format,...)139c01977edSJohn Birrell terminate(const char *format, ...)
1401673e404SJohn Birrell {
1411673e404SJohn Birrell 	va_list ap;
1421673e404SJohn Birrell 
1431673e404SJohn Birrell 	va_start(ap, format);
1441673e404SJohn Birrell 	whine("ERROR", format, ap);
1451673e404SJohn Birrell 	va_end(ap);
1461673e404SJohn Birrell 
1471673e404SJohn Birrell 	if (terminate_cleanup)
1481673e404SJohn Birrell 		terminate_cleanup();
1491673e404SJohn Birrell 
1501673e404SJohn Birrell 	if (getenv("CTF_ABORT_ON_TERMINATE") != NULL)
1511673e404SJohn Birrell 		abort();
15275a81308SBryan Drewery #if defined(__FreeBSD__)
15375a81308SBryan Drewery /*
15475a81308SBryan Drewery  * For the time being just output the termination message, but don't
15575a81308SBryan Drewery  * return an exit status that would cause the build to fail. We need
15675a81308SBryan Drewery  * to get as much stuff built as possible before going back and
15775a81308SBryan Drewery  * figuring out what is wrong with certain files.
15875a81308SBryan Drewery  */
15975a81308SBryan Drewery 	exit(0);
16075a81308SBryan Drewery #else
1611673e404SJohn Birrell 	exit(1);
16275a81308SBryan Drewery #endif
1631673e404SJohn Birrell }
1641673e404SJohn Birrell 
1651673e404SJohn Birrell /*PRINTFLIKE1*/
1661673e404SJohn Birrell void
aborterr(const char * format,...)167c01977edSJohn Birrell aborterr(const char *format, ...)
1681673e404SJohn Birrell {
1691673e404SJohn Birrell 	va_list ap;
1701673e404SJohn Birrell 
1711673e404SJohn Birrell 	va_start(ap, format);
1721673e404SJohn Birrell 	whine("ERROR", format, ap);
1731673e404SJohn Birrell 	va_end(ap);
1741673e404SJohn Birrell 
175bc96366cSSteven Hartland #ifdef illumos
1761673e404SJohn Birrell 	abort();
177c01977edSJohn Birrell #else
178c01977edSJohn Birrell 	exit(0);
179c01977edSJohn Birrell #endif
1801673e404SJohn Birrell }
1811673e404SJohn Birrell 
1821673e404SJohn Birrell /*PRINTFLIKE1*/
1831673e404SJohn Birrell void
warning(const char * format,...)184c01977edSJohn Birrell warning(const char *format, ...)
1851673e404SJohn Birrell {
1861673e404SJohn Birrell 	va_list ap;
1871673e404SJohn Birrell 
1881673e404SJohn Birrell 	va_start(ap, format);
1891673e404SJohn Birrell 	whine("WARNING", format, ap);
1901673e404SJohn Birrell 	va_end(ap);
1911673e404SJohn Birrell 
1921673e404SJohn Birrell 	if (debug_level >= 3)
1931673e404SJohn Birrell 		terminate("Termination due to warning\n");
1941673e404SJohn Birrell }
1951673e404SJohn Birrell 
1961673e404SJohn Birrell /*PRINTFLIKE2*/
1971673e404SJohn Birrell void
vadebug(int level,const char * format,va_list ap)198c01977edSJohn Birrell vadebug(int level, const char *format, va_list ap)
1991673e404SJohn Birrell {
2001673e404SJohn Birrell 	if (level > debug_level)
2011673e404SJohn Birrell 		return;
2021673e404SJohn Birrell 
2031673e404SJohn Birrell 	(void) fprintf(DEBUG_STREAM, "DEBUG: ");
2041673e404SJohn Birrell 	(void) vfprintf(DEBUG_STREAM, format, ap);
2051673e404SJohn Birrell 	fflush(DEBUG_STREAM);
2061673e404SJohn Birrell }
2071673e404SJohn Birrell 
2081673e404SJohn Birrell /*PRINTFLIKE2*/
2091673e404SJohn Birrell void
debug(int level,const char * format,...)210c01977edSJohn Birrell debug(int level, const char *format, ...)
2111673e404SJohn Birrell {
2121673e404SJohn Birrell 	va_list ap;
2131673e404SJohn Birrell 
2141673e404SJohn Birrell 	if (level > debug_level)
2151673e404SJohn Birrell 		return;
2161673e404SJohn Birrell 
2171673e404SJohn Birrell 	va_start(ap, format);
2181673e404SJohn Birrell 	(void) vadebug(level, format, ap);
2191673e404SJohn Birrell 	va_end(ap);
2201673e404SJohn Birrell }
2211673e404SJohn Birrell 
2221673e404SJohn Birrell char *
mktmpname(const char * origname,const char * suffix)2231673e404SJohn Birrell mktmpname(const char *origname, const char *suffix)
2241673e404SJohn Birrell {
2251673e404SJohn Birrell 	char *newname;
2261673e404SJohn Birrell 
2271673e404SJohn Birrell 	newname = xmalloc(strlen(origname) + strlen(suffix) + 1);
2281673e404SJohn Birrell 	(void) strcpy(newname, origname);
2291673e404SJohn Birrell 	(void) strcat(newname, suffix);
2301673e404SJohn Birrell 	return (newname);
2311673e404SJohn Birrell }
2321673e404SJohn Birrell 
2331673e404SJohn Birrell /*PRINTFLIKE2*/
2341673e404SJohn Birrell void
elfterminate(const char * file,const char * fmt,...)2351673e404SJohn Birrell elfterminate(const char *file, const char *fmt, ...)
2361673e404SJohn Birrell {
2371673e404SJohn Birrell 	static char msgbuf[BUFSIZ];
2381673e404SJohn Birrell 	va_list ap;
2391673e404SJohn Birrell 
2401673e404SJohn Birrell 	va_start(ap, fmt);
2411673e404SJohn Birrell 	vsnprintf(msgbuf, sizeof (msgbuf), fmt, ap);
2421673e404SJohn Birrell 	va_end(ap);
2431673e404SJohn Birrell 
2441673e404SJohn Birrell 	terminate("%s: %s: %s\n", file, msgbuf, elf_errmsg(-1));
2451673e404SJohn Birrell }
2461673e404SJohn Birrell 
2471673e404SJohn Birrell const char *
tdesc_name(tdesc_t * tdp)2481673e404SJohn Birrell tdesc_name(tdesc_t *tdp)
2491673e404SJohn Birrell {
2501673e404SJohn Birrell 	return (tdp->t_name == NULL ? "(anon)" : tdp->t_name);
2511673e404SJohn Birrell }
252c01977edSJohn Birrell 
253c0794a84SEd Schouten static char	*watch_address = NULL;
254c0794a84SEd Schouten static int	watch_length = 0;
255c01977edSJohn Birrell 
256c01977edSJohn Birrell void
watch_set(void * addr,int len)257c01977edSJohn Birrell watch_set(void *addr, int len)
258c01977edSJohn Birrell {
259c01977edSJohn Birrell 	watch_address = addr;
260c01977edSJohn Birrell 	watch_length  = len;
261c01977edSJohn Birrell }
262c01977edSJohn Birrell 
263c01977edSJohn Birrell void
watch_dump(int v)264c01977edSJohn Birrell watch_dump(int v)
265c01977edSJohn Birrell {
266c01977edSJohn Birrell 	char *p = watch_address;
267c01977edSJohn Birrell 	int i;
268c01977edSJohn Birrell 
269c01977edSJohn Birrell 	if (watch_address == NULL || watch_length == 0)
270c01977edSJohn Birrell 		return;
271c01977edSJohn Birrell 
272c01977edSJohn Birrell 	printf("%d: watch %p len %d\n",v,watch_address,watch_length);
273c01977edSJohn Birrell         for (i = 0; i < watch_length; i++) {
274c01977edSJohn Birrell                 if (*p >= 0x20 && *p < 0x7f) {
275c01977edSJohn Birrell                         printf(" %c",*p++ & 0xff);
276c01977edSJohn Birrell                 } else {
277c01977edSJohn Birrell                         printf(" %02x",*p++ & 0xff);
278c01977edSJohn Birrell                 }
279c01977edSJohn Birrell         }
280c01977edSJohn Birrell         printf("\n");
281c01977edSJohn Birrell 
282c01977edSJohn Birrell }
283c01977edSJohn Birrell 
284c01977edSJohn Birrell 
285