pcom.c revision 12927:a27c46eb192b
112256Sgoetz/*
212256Sgoetz * CDDL HEADER START
312256Sgoetz *
412256Sgoetz * The contents of this file are subject to the terms of the
512256Sgoetz * Common Development and Distribution License (the "License").
612256Sgoetz * You may not use this file except in compliance with the License.
712256Sgoetz *
812256Sgoetz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912256Sgoetz * or http://www.opensolaris.org/os/licensing.
1012256Sgoetz * See the License for the specific language governing permissions
1112256Sgoetz * and limitations under the License.
1212256Sgoetz *
1312256Sgoetz * When distributing Covered Code, include this CDDL HEADER in each
1412256Sgoetz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512256Sgoetz * If applicable, add the following below this CDDL HEADER, with the
1612256Sgoetz * fields enclosed by brackets "[]" replaced with your own identifying
1712256Sgoetz * information: Portions Copyright [yyyy] [name of copyright owner]
1812256Sgoetz *
1912256Sgoetz * CDDL HEADER END
2012256Sgoetz */
2112256Sgoetz/*
2212256Sgoetz * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
2312256Sgoetz */
2412256Sgoetz
2512256Sgoetz/*
2612256Sgoetz * pcom: Print Comment
2712256Sgoetz *
2812256Sgoetz * This program demonstrates the use of the libelf interface to
2912256Sgoetz * read an ELF file.  pcom will open an ELF file using
3012256Sgoetz * elf_begin(ELF_C_READ) and examine search the ELF file
3112256Sgoetz * for a .comment section.  If a .comment section is found it's
3212256Sgoetz * contents will be displayed on stdout.
3312256Sgoetz */
3412256Sgoetz
3512256Sgoetz#include <stdio.h>
3612256Sgoetz#include <libelf.h>
3712256Sgoetz#include <gelf.h>
3812256Sgoetz#include <fcntl.h>
3912256Sgoetz#include <unistd.h>
4012256Sgoetz#include <stdlib.h>
4112256Sgoetz#include <string.h>
4212256Sgoetz
4312256Sgoetz
4412256Sgoetzstatic const char	*CommentStr = ".comment";
4512256Sgoetz
4612256Sgoetzstatic void
4712256Sgoetzprint_comment(Elf *elf, const char *file)
4812256Sgoetz{
4912256Sgoetz	Elf_Scn		*scn = NULL;
5012256Sgoetz	GElf_Shdr	shdr;
5112256Sgoetz	Elf_Data	*data;
5212256Sgoetz	size_t		shstrndx;
5312256Sgoetz
5412256Sgoetz
5512256Sgoetz	(void) printf("%s .comment:\n", file);
5612256Sgoetz
5712256Sgoetz	if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
5812256Sgoetz		(void) fprintf(stderr, "%s: elf_getshdrstrndx() failed: %s\n",
5912256Sgoetz		    file, elf_errmsg(0));
6012256Sgoetz		return;
6112256Sgoetz	}
6212256Sgoetz
6312256Sgoetz	while ((scn = elf_nextscn(elf, scn)) != NULL) {
6412256Sgoetz		/*
6512256Sgoetz		 * Do a string compare to examine each section header
6612256Sgoetz		 * to see if it is a ".comment" section.  If it is then
6712256Sgoetz		 * this is the section we want to process.
6812256Sgoetz		 */
6912256Sgoetz		if (gelf_getshdr(scn, &shdr) == NULL) {
7012256Sgoetz			(void) fprintf(stderr, "%s: elf_getshdr() failed: %s\n",
7112256Sgoetz			    file, elf_errmsg(0));
7212256Sgoetz			return;
7312256Sgoetz		}
7412256Sgoetz		if (strcmp(CommentStr, elf_strptr(elf, shstrndx,
7512256Sgoetz		    shdr.sh_name)) == 0) {
7612256Sgoetz			int	i;
7712256Sgoetz			char	*ptr;
7812256Sgoetz
7912256Sgoetz			/*
8012256Sgoetz			 * Get the data associated with the .comment
8112256Sgoetz			 * section.
8212256Sgoetz			 */
8312256Sgoetz			if ((data = elf_getdata(scn, NULL)) == NULL) {
8412256Sgoetz				(void) fprintf(stderr,
8512256Sgoetz				    "%s: elf_getdata() failed: %s\n",
8612256Sgoetz				    file, elf_errmsg(0));
8712256Sgoetz				return;
8812256Sgoetz			}
8912256Sgoetz
9012256Sgoetz			/*
9112256Sgoetz			 * Data in a .comment section is a list of 'null'
9212256Sgoetz			 * terminated strings.  The following will print
9312256Sgoetz			 * one string per line.
9412256Sgoetz			 */
9512256Sgoetz			for (i = 0, ptr = (char *)data->d_buf;
9612256Sgoetz			    i < data->d_size; i++)
9712256Sgoetz				if (ptr[i]) {
9812256Sgoetz					(void) puts(&ptr[i]);
9912256Sgoetz					i += strlen(&ptr[i]);
10012256Sgoetz				}
10112256Sgoetz			(void) putchar('\n');
10212256Sgoetz		}
10312256Sgoetz	}
10412256Sgoetz
10512256Sgoetz}
10612256Sgoetz
10712256Sgoetzstatic void
10812256Sgoetzprocess_elf(Elf *elf, char *file, int fd, int member)
10912256Sgoetz{
11012256Sgoetz	Elf_Cmd	cmd;
11112256Sgoetz	Elf	*_elf;
11212256Sgoetz
11312256Sgoetz	switch (elf_kind(elf)) {
11412256Sgoetz	case ELF_K_ELF:
11512256Sgoetz		/*
11612256Sgoetz		 * This is an ELF file, now attempt to find it's
11712256Sgoetz		 * .comment section and to display it.
11812256Sgoetz		 */
11912256Sgoetz		print_comment(elf, file);
12012256Sgoetz		break;
12112256Sgoetz	case ELF_K_AR:
12212256Sgoetz		/*
12312256Sgoetz		 * Archives contain multiple ELF files, which can each
12412256Sgoetz		 * in turn be examined with libelf.
12512256Sgoetz		 *
12612256Sgoetz		 * The below loop will iterate over each member of the
12712256Sgoetz		 * archive and recursively call process_elf().
12812256Sgoetz		 */
12912256Sgoetz		cmd = ELF_C_READ;
13012256Sgoetz		while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
13112256Sgoetz			Elf_Arhdr	*arhdr;
13212256Sgoetz			char		buffer[1024];
13312256Sgoetz
13412256Sgoetz			arhdr = elf_getarhdr(_elf);
13512256Sgoetz
13612256Sgoetz			/*
13712256Sgoetz			 * Build up file names based off of
13812256Sgoetz			 * 'archivename(membername)'.
13912256Sgoetz			 */
14012256Sgoetz			(void) sprintf(buffer, "%s(%s)", file, arhdr->ar_name);
14112256Sgoetz
14212256Sgoetz			/*
14312256Sgoetz			 * Recursively process the ELF members.
14412256Sgoetz			 */
14512256Sgoetz			process_elf(_elf, buffer, fd, 1);
14612256Sgoetz			cmd = elf_next(_elf);
14712256Sgoetz			(void) elf_end(_elf);
14812256Sgoetz		}
14912256Sgoetz		break;
15012256Sgoetz	default:
15112256Sgoetz		if (!member)
15212256Sgoetz			(void) fprintf(stderr,
15312256Sgoetz			    "%s: unexpected elf_kind(): 0x%x\n",
15412256Sgoetz			    file, elf_kind(elf));
15512256Sgoetz		return;
15612256Sgoetz	}
15712256Sgoetz}
15812256Sgoetz
15912256Sgoetzint
160main(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