xref: /illumos-gate/usr/src/cmd/sgs/libelf/demo/pcom.c (revision b76c1459)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * pcom: Print Comment
29  *
30  * This program demonstrates the use of the libelf interface to
31  * read an ELF file.  pcom will open an ELF file using
32  * elf_begin(ELF_C_READ) and examine search the ELF file
33  * for a .comment section.  If a .comment section is found it's
34  * contents will be displayed on stdout.
35  */
36 
37 #pragma ident	"%Z%%M%	%I%	%E% SMI"
38 
39 #include <stdio.h>
40 #include <libelf.h>
41 #include <gelf.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <string.h>
46 
47 
48 static const char	*CommentStr = ".comment";
49 
50 static void
51 print_comment(Elf *elf, const char *file)
52 {
53 	Elf_Scn		*scn = 0;
54 	GElf_Shdr	shdr;
55 	Elf_Data	*data;
56 	size_t		shstrndx;
57 
58 
59 	(void) printf("%s .comment:\n", file);
60 
61 	if (elf_getshstrndx(elf, &shstrndx) == 0) {
62 		(void) fprintf(stderr, "%s: elf_getshstrndx() failed: %s\n",
63 			file, elf_errmsg(0));
64 		return;
65 	}
66 
67 	while ((scn = elf_nextscn(elf, scn)) != 0) {
68 		/*
69 		 * Do a string compare to examine each section header
70 		 * to see if it is a ".comment" section.  If it is then
71 		 * this is the section we want to process.
72 		 */
73 		if (gelf_getshdr(scn, &shdr) == 0) {
74 			(void) fprintf(stderr,
75 				"%s: elf_getshdr() failed: %s\n",
76 				file, elf_errmsg(0));
77 			return;
78 		}
79 		if (strcmp(CommentStr, elf_strptr(elf, shstrndx,
80 		    shdr.sh_name)) == 0) {
81 			int	i;
82 			char	*ptr;
83 
84 			/*
85 			 * Get the data associated with the .comment
86 			 * section.
87 			 */
88 			if ((data = elf_getdata(scn, 0)) == 0) {
89 				(void) fprintf(stderr,
90 					"%s: elf_getdata() failed: %s\n",
91 					file, elf_errmsg(0));
92 				return;
93 			}
94 			/*
95 			 * Data in a .comment section is a list of 'null'
96 			 * terminated strings.  The following will print
97 			 * one string per line.
98 			 */
99 			for (i = 0, ptr = (char *)data->d_buf;
100 			    i < data->d_size; i++)
101 				if (ptr[i]) {
102 					(void) puts(&ptr[i]);
103 					i += strlen(&ptr[i]);
104 				}
105 			(void) putchar('\n');
106 		}
107 	}
108 
109 }
110 
111 
112 static void
113 process_elf(Elf *elf, char *file, int fd, int member)
114 {
115 	Elf_Cmd	cmd;
116 	Elf	*_elf;
117 
118 	switch (elf_kind(elf)) {
119 	case ELF_K_ELF:
120 		/*
121 		 * This is an ELF file, now attempt to find it's
122 		 * .comment section and to display it.
123 		 */
124 		print_comment(elf, file);
125 		break;
126 	case ELF_K_AR:
127 		/*
128 		 * Archives contain multiple ELF files, which can each
129 		 * in turn be examined with libelf.
130 		 *
131 		 * The below loop will iterate over each member of the
132 		 * archive and recursivly call process_elf() for processing.
133 		 */
134 		cmd = ELF_C_READ;
135 		while ((_elf = elf_begin(fd, cmd, elf)) != 0) {
136 			Elf_Arhdr	*arhdr;
137 			char		buffer[1024];
138 
139 			arhdr = elf_getarhdr(_elf);
140 
141 			/*
142 			 * Build up file names based off of
143 			 * 'archivename(membername)'.
144 			 */
145 			(void) sprintf(buffer, "%s(%s)", file, arhdr->ar_name);
146 
147 			/*
148 			 * recursivly process the ELF members.
149 			 */
150 			process_elf(_elf, buffer, fd, 1);
151 			cmd = elf_next(_elf);
152 			(void) elf_end(_elf);
153 		}
154 		break;
155 	default:
156 		if (!member)
157 			(void) fprintf(stderr,
158 				"%s: unexpected elf_kind(): 0x%x\n",
159 				file, elf_kind(elf));
160 		return;
161 	}
162 }
163 
164 int
165 main(int argc, char **argv)
166 {
167 	int	i;
168 
169 
170 	if (argc < 2) {
171 		(void) printf("usage: %s elf_file ...\n", argv[0]);
172 		return (1);
173 	}
174 
175 	/*
176 	 * Initialize the elf library, must be called before elf_begin()
177 	 * can be called.
178 	 */
179 	if (elf_version(EV_CURRENT) == EV_NONE) {
180 		(void) fprintf(stderr,
181 			"elf_version() failed: %s\n", elf_errmsg(0));
182 		return (1);
183 	}
184 
185 	for (i = 1; i < argc; i++) {
186 		int	fd;
187 		Elf	*elf;
188 		char	*elf_fname;
189 
190 		elf_fname = argv[i];
191 		if ((fd = open(elf_fname, O_RDONLY)) == -1) {
192 			perror("open");
193 			continue;
194 		}
195 
196 		/*
197 		 * Attempt to open an Elf descriptor Read/Write
198 		 * for each file.
199 		 */
200 		if ((elf = elf_begin(fd, ELF_C_READ, 0)) == NULL) {
201 			(void) fprintf(stderr, "elf_begin() failed: %s\n",
202 			    elf_errmsg(0));
203 			(void) close(fd);
204 			continue;
205 		}
206 
207 		/*
208 		 * Process each elf descriptor.
209 		 */
210 		process_elf(elf, elf_fname, fd, 0);
211 		(void) elf_end(elf);
212 		(void) close(fd);
213 	}
214 
215 	return (0);
216 }
217