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 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <stdarg.h> 32 #include <string.h> 33 #include <libgen.h> 34 #include <errno.h> 35 #include <libelf.h> 36 #include <gelf.h> 37 #include <fcntl.h> 38 #include <unistd.h> 39 #include <sys/stat.h> 40 #include <sys/types.h> 41 42 #include <findfp.h> 43 #include <util.h> 44 45 #define OP(x) ((unsigned)(0x3 & x) << 30) /* general opcode */ 46 #define OP2(x) ((0x7 & x) << 22) /* op2 opcode */ 47 #define OP3(x) ((0x3f & x) << 19) /* op3 opcode */ 48 49 #define OPMSK 0xC0000000 50 #define OP2MSK 0x01C00000 51 #define OP3MSK 0x01F80000 52 53 #define MAXEXCLUDES 5 54 55 typedef struct mask { 56 uint32_t m_mask; 57 uint32_t m_val; 58 const char *m_name; 59 } mask_t; 60 61 static const mask_t masks[] = { 62 { OPMSK|OP2MSK, OP(0) | OP2(5), "FBPfcc" }, 63 { OPMSK|OP2MSK, OP(0) | OP2(6), "FBfcc" }, 64 { OPMSK|OP3MSK, OP(2) | OP3(0x34), "FPop1" }, 65 { OPMSK|OP3MSK, OP(2) | OP3(0x35), "FPop2" }, 66 { OPMSK|OP3(0x38), OP(3) | OP3(0x20), "FPldst1" }, 67 { OPMSK|OP3(0x38), OP(3) | OP3(0x30), "FPldst2" } 68 }; 69 70 const char *progname; 71 72 static void 73 usage(void) 74 { 75 (void) fprintf(stderr, "Usage: %s infile\n", progname); 76 exit(2); 77 } 78 79 int 80 main(int argc, char **argv) 81 { 82 Elf *elf; 83 Elf_Scn *scn; 84 GElf_Shdr shdr; 85 Elf_Data *text; 86 uint32_t *instrs; 87 char *excludes[MAXEXCLUDES]; 88 int fd, textidx, i, j, c; 89 int shownames = 1; 90 int nexcludes = 0; 91 int found = 0; 92 char *filename; 93 94 progname = basename(argv[0]); 95 96 while ((c = getopt(argc, argv, ":nx:")) != EOF) { 97 switch (c) { 98 case 'n': 99 shownames = 0; 100 break; 101 case 'x': 102 if (nexcludes == MAXEXCLUDES - 1) 103 die("exclusion limit is %d", MAXEXCLUDES); 104 excludes[nexcludes++] = optarg; 105 break; 106 default: 107 usage(); 108 } 109 } 110 111 if (argc - optind != 1) 112 usage(); 113 filename = argv[optind]; 114 115 if ((fd = open(filename, O_RDONLY)) < 0) 116 die("failed to open %s", filename); 117 118 (void) elf_version(EV_CURRENT); 119 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) 120 elfdie("failed to open %s as ELF", filename); 121 122 if ((textidx = findelfsecidx(elf, ".text")) < 0) 123 die("failed to find .text section in %s\n", filename); 124 125 if ((scn = elf_getscn(elf, textidx)) == NULL || 126 gelf_getshdr(scn, &shdr) == NULL || 127 (text = elf_rawdata(scn, NULL)) == NULL) 128 elfdie("failed to read .text"); 129 130 instrs = text->d_buf; 131 132 for (i = 0; i < shdr.sh_size / 4; i++) { 133 for (j = 0; j < sizeof (masks) / sizeof (mask_t); j++) { 134 char *symname = NULL; 135 offset_t off; 136 int len = 35; 137 int xcl; 138 139 if ((instrs[i] & masks[j].m_mask) != masks[j].m_val) 140 continue; 141 142 if (findelfsym(elf, i * 4, &symname, &off)) { 143 if (nexcludes > 0) { 144 for (xcl = 0; xcl < nexcludes; xcl++) { 145 if (strcmp(symname, 146 excludes[xcl]) == 0) 147 break; 148 } 149 150 if (xcl < nexcludes) 151 continue; /* exclude matched */ 152 } 153 } 154 155 found++; 156 157 if (!shownames || symname == NULL) { 158 (void) printf("%-*x", len, i * 4); 159 } else { 160 len -= printf("%s+%llx", symname, off); 161 (void) printf("%*s", (len > 0 ? len : 0), ""); 162 } 163 164 (void) printf(" %08x %s\n", instrs[i], 165 masks[j].m_name); 166 } 167 } 168 169 (void) elf_end(elf); 170 (void) close(fd); 171 172 return (found > 0); 173 } 174