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