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 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * pcom: Print Comment
27 *
28 * This program demonstrates the use of the libelf interface to
29 * read an ELF file. pcom will open an ELF file using
30 * elf_begin(ELF_C_READ) and examine search the ELF file
31 * for a .comment section. If a .comment section is found it's
32 * contents will be displayed on stdout.
33 */
34
35 #include <stdio.h>
36 #include <libelf.h>
37 #include <gelf.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43
44 static const char *CommentStr = ".comment";
45
46 static void
print_comment(Elf * elf,const char * file)47 print_comment(Elf *elf, const char *file)
48 {
49 Elf_Scn *scn = NULL;
50 GElf_Shdr shdr;
51 Elf_Data *data;
52 size_t shstrndx;
53
54
55 (void) printf("%s .comment:\n", file);
56
57 if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
58 (void) fprintf(stderr, "%s: elf_getshdrstrndx() failed: %s\n",
59 file, elf_errmsg(0));
60 return;
61 }
62
63 while ((scn = elf_nextscn(elf, scn)) != NULL) {
64 /*
65 * Do a string compare to examine each section header
66 * to see if it is a ".comment" section. If it is then
67 * this is the section we want to process.
68 */
69 if (gelf_getshdr(scn, &shdr) == NULL) {
70 (void) fprintf(stderr, "%s: elf_getshdr() failed: %s\n",
71 file, elf_errmsg(0));
72 return;
73 }
74 if (strcmp(CommentStr, elf_strptr(elf, shstrndx,
75 shdr.sh_name)) == 0) {
76 int i;
77 char *ptr;
78
79 /*
80 * Get the data associated with the .comment
81 * section.
82 */
83 if ((data = elf_getdata(scn, NULL)) == NULL) {
84 (void) fprintf(stderr,
85 "%s: elf_getdata() failed: %s\n",
86 file, elf_errmsg(0));
87 return;
88 }
89
90 /*
91 * Data in a .comment section is a list of 'null'
92 * terminated strings. The following will print
93 * one string per line.
94 */
95 for (i = 0, ptr = (char *)data->d_buf;
96 i < data->d_size; i++)
97 if (ptr[i]) {
98 (void) puts(&ptr[i]);
99 i += strlen(&ptr[i]);
100 }
101 (void) putchar('\n');
102 }
103 }
104
105 }
106
107 static void
process_elf(Elf * elf,char * file,int fd,int member)108 process_elf(Elf *elf, char *file, int fd, int member)
109 {
110 Elf_Cmd cmd;
111 Elf *_elf;
112
113 switch (elf_kind(elf)) {
114 case ELF_K_ELF:
115 /*
116 * This is an ELF file, now attempt to find it's
117 * .comment section and to display it.
118 */
119 print_comment(elf, file);
120 break;
121 case ELF_K_AR:
122 /*
123 * Archives contain multiple ELF files, which can each
124 * in turn be examined with libelf.
125 *
126 * The below loop will iterate over each member of the
127 * archive and recursively call process_elf().
128 */
129 cmd = ELF_C_READ;
130 while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
131 Elf_Arhdr *arhdr;
132 char buffer[1024];
133
134 arhdr = elf_getarhdr(_elf);
135
136 /*
137 * Build up file names based off of
138 * 'archivename(membername)'.
139 */
140 (void) sprintf(buffer, "%s(%s)", file, arhdr->ar_name);
141
142 /*
143 * Recursively process the ELF members.
144 */
145 process_elf(_elf, buffer, fd, 1);
146 cmd = elf_next(_elf);
147 (void) elf_end(_elf);
148 }
149 break;
150 default:
151 if (!member)
152 (void) fprintf(stderr,
153 "%s: unexpected elf_kind(): 0x%x\n",
154 file, elf_kind(elf));
155 return;
156 }
157 }
158
159 int
main(int argc,char ** argv)160 main(int argc, char **argv)
161 {
162 int i;
163
164 if (argc < 2) {
165 (void) printf("usage: %s elf_file ...\n", argv[0]);
166 return (1);
167 }
168
169 /*
170 * Initialize the elf library, must be called before elf_begin()
171 * can be called.
172 */
173 if (elf_version(EV_CURRENT) == EV_NONE) {
174 (void) fprintf(stderr,
175 "elf_version() failed: %s\n", elf_errmsg(0));
176 return (1);
177 }
178
179 for (i = 1; i < argc; i++) {
180 int fd;
181 Elf *elf;
182 char *elf_fname;
183
184 elf_fname = argv[i];
185 if ((fd = open(elf_fname, O_RDONLY)) == -1) {
186 perror("open");
187 continue;
188 }
189
190 /*
191 * Attempt to open an Elf descriptor Read/Write
192 * for each file.
193 */
194 if ((elf = elf_begin(fd, ELF_C_READ, 0)) == NULL) {
195 (void) fprintf(stderr, "elf_begin() failed: %s\n",
196 elf_errmsg(0));
197 (void) close(fd);
198 continue;
199 }
200
201 /*
202 * Process each elf descriptor.
203 */
204 process_elf(elf, elf_fname, fd, 0);
205 (void) elf_end(elf);
206 (void) close(fd);
207 }
208
209 return (0);
210 }
211