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