xref: /illumos-gate/usr/src/cmd/boot/symdef/symdef.c (revision d81537f42f656d7d5d57dc138f876c0c9bfeff87)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <libelf.h>
34 #include <gelf.h>
35 #include <errno.h>
36 
37 /*
38  * symdef is a very simplified version of nm.  It is used by upgrade and
39  * create_ramdisk in situations where we can't guarantee that nm will be around.
40  *
41  * Two arguments are expected: a binary and a symbol name.  If the symbol is
42  * found in the name table of the binary, 0 is returned.  If it is not found,
43  * 1 is returned.  If an error occurs, a message is printed to stderr and -1
44  * is returned.
45  */
46 
47 
48 static void
49 usage(void)
50 {
51 	(void) fprintf(stderr, "USAGE: symdef file_name symbol\n");
52 }
53 
54 int
55 main(int argc, char *argv[])
56 {
57 	int	fd = 0;
58 	int	rv = 1;
59 	uint_t	cnt, symcnt;
60 	Elf	*elfp = NULL;
61 	Elf_Scn	*scn = NULL;
62 	size_t	shstrndx;
63 	GElf_Ehdr	ehdr;
64 	GElf_Shdr	shdr;
65 	GElf_Sym	sym;
66 	Elf32_Word	shndx;
67 	Elf_Data	*symdata, *shndxdata;
68 
69 	if (argc != 3) {
70 		usage();
71 		return (-1);
72 	}
73 
74 	fd = open(argv[1], O_RDONLY);
75 	if (fd == -1) {
76 		(void) fprintf(stderr, "%s\n", strerror(errno));
77 		rv = -1;
78 		goto done;
79 	}
80 	if (elf_version(EV_CURRENT) == EV_NONE) {
81 		(void) fprintf(stderr, "Elf library version out of date\n");
82 		rv = -1;
83 		goto done;
84 	}
85 	elfp = elf_begin(fd, ELF_C_READ, NULL);
86 	if ((elfp == NULL) || (elf_kind(elfp) != ELF_K_ELF) ||
87 	    ((gelf_getehdr(elfp, &ehdr)) == NULL) ||
88 	    (elf_getshstrndx(elfp, &shstrndx) == 0))
89 		goto done;
90 
91 	while ((scn = elf_nextscn(elfp, scn)) != NULL) {
92 		if ((gelf_getshdr(scn, &shdr) == NULL) ||
93 		    ((shdr.sh_type != SHT_SYMTAB) &&
94 		    (shdr.sh_type != SHT_DYNSYM)) ||
95 		    ((symdata = elf_getdata(scn, NULL)) == NULL))
96 			continue;
97 		symcnt = shdr.sh_size / shdr.sh_entsize;
98 		shndxdata = NULL;
99 		for (cnt = 0; cnt < symcnt; cnt++) {
100 			if ((gelf_getsymshndx(symdata, shndxdata, cnt,
101 			    &sym, &shndx) != NULL) &&
102 			    (strcmp(argv[2], elf_strptr(elfp, shdr.sh_link,
103 			    sym.st_name)) == 0)) {
104 				rv = 0;
105 				goto done;
106 			}
107 		}
108 	}
109 done:
110 	if (elfp)
111 		(void) elf_end(elfp);
112 	if (fd != -1)
113 		(void) close(fd);
114 	return (rv);
115 }
116