xref: /freebsd/cddl/contrib/opensolaris/tools/ctf/cvt/util.c (revision c01977ed3b6d325bae5de5025eb0c6357ee73be5)
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 
46c01977edSJohn 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
119c01977edSJohn 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
131c01977edSJohn Birrell set_terminate_cleanup(void (*cleanup)(void))
1321673e404SJohn Birrell {
1331673e404SJohn Birrell 	terminate_cleanup = cleanup;
1341673e404SJohn Birrell }
1351673e404SJohn Birrell 
1361673e404SJohn Birrell /*PRINTFLIKE1*/
1371673e404SJohn Birrell void
138c01977edSJohn 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();
151c01977edSJohn Birrell #if defined(__FreeBSD__)
152c01977edSJohn Birrell /*
153c01977edSJohn Birrell  * For the time being just output the termination message, but don't
154c01977edSJohn Birrell  * return an exit status that would cause the build to fail. We need
155c01977edSJohn Birrell  * to get as much stuff built as possible before going back and
156c01977edSJohn Birrell  * figuring out what is wrong with certain files.
157c01977edSJohn Birrell  */
158c01977edSJohn Birrell 	exit(0);
159c01977edSJohn Birrell #else
1601673e404SJohn Birrell 	exit(1);
161c01977edSJohn Birrell #endif
1621673e404SJohn Birrell }
1631673e404SJohn Birrell 
1641673e404SJohn Birrell /*PRINTFLIKE1*/
1651673e404SJohn Birrell void
166c01977edSJohn 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 
174c01977edSJohn Birrell #if defined(sun)
1751673e404SJohn Birrell 	abort();
176c01977edSJohn Birrell #else
177c01977edSJohn Birrell 	exit(0);
178c01977edSJohn Birrell #endif
1791673e404SJohn Birrell }
1801673e404SJohn Birrell 
1811673e404SJohn Birrell /*PRINTFLIKE1*/
1821673e404SJohn Birrell void
183c01977edSJohn 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
197c01977edSJohn 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
209c01977edSJohn 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 }
251c01977edSJohn Birrell 
252c01977edSJohn Birrell char	*watch_address = NULL;
253c01977edSJohn Birrell int	watch_length = 0;
254c01977edSJohn Birrell 
255c01977edSJohn Birrell void
256c01977edSJohn Birrell watch_set(void *addr, int len)
257c01977edSJohn Birrell {
258c01977edSJohn Birrell 	watch_address = addr;
259c01977edSJohn Birrell 	watch_length  = len;
260c01977edSJohn Birrell }
261c01977edSJohn Birrell 
262c01977edSJohn Birrell void
263c01977edSJohn Birrell watch_dump(int v)
264c01977edSJohn Birrell {
265c01977edSJohn Birrell 	char *p = watch_address;
266c01977edSJohn Birrell 	int i;
267c01977edSJohn Birrell 
268c01977edSJohn Birrell 	if (watch_address == NULL || watch_length == 0)
269c01977edSJohn Birrell 		return;
270c01977edSJohn Birrell 
271c01977edSJohn Birrell 	printf("%d: watch %p len %d\n",v,watch_address,watch_length);
272c01977edSJohn Birrell         for (i = 0; i < watch_length; i++) {
273c01977edSJohn Birrell                 if (*p >= 0x20 && *p < 0x7f) {
274c01977edSJohn Birrell                         printf(" %c",*p++ & 0xff);
275c01977edSJohn Birrell                 } else {
276c01977edSJohn Birrell                         printf(" %02x",*p++ & 0xff);
277c01977edSJohn Birrell                 }
278c01977edSJohn Birrell         }
279c01977edSJohn Birrell         printf("\n");
280c01977edSJohn Birrell 
281c01977edSJohn Birrell }
282c01977edSJohn Birrell 
283c01977edSJohn Birrell 
284