1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <libgen.h> 34*7c478bd9Sstevel@tonic-gate #include <errno.h> 35*7c478bd9Sstevel@tonic-gate #include <libelf.h> 36*7c478bd9Sstevel@tonic-gate #include <gelf.h> 37*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 38*7c478bd9Sstevel@tonic-gate #include <unistd.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #include <findfp.h> 43*7c478bd9Sstevel@tonic-gate #include <util.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #define OP(x) ((unsigned)(0x3 & x) << 30) /* general opcode */ 46*7c478bd9Sstevel@tonic-gate #define OP2(x) ((0x7 & x) << 22) /* op2 opcode */ 47*7c478bd9Sstevel@tonic-gate #define OP3(x) ((0x3f & x) << 19) /* op3 opcode */ 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #define OPMSK 0xC0000000 50*7c478bd9Sstevel@tonic-gate #define OP2MSK 0x01C00000 51*7c478bd9Sstevel@tonic-gate #define OP3MSK 0x01F80000 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #define MAXEXCLUDES 5 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate typedef struct mask { 56*7c478bd9Sstevel@tonic-gate uint32_t m_mask; 57*7c478bd9Sstevel@tonic-gate uint32_t m_val; 58*7c478bd9Sstevel@tonic-gate const char *m_name; 59*7c478bd9Sstevel@tonic-gate } mask_t; 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate static const mask_t masks[] = { 62*7c478bd9Sstevel@tonic-gate { OPMSK|OP2MSK, OP(0) | OP2(5), "FBPfcc" }, 63*7c478bd9Sstevel@tonic-gate { OPMSK|OP2MSK, OP(0) | OP2(6), "FBfcc" }, 64*7c478bd9Sstevel@tonic-gate { OPMSK|OP3MSK, OP(2) | OP3(0x34), "FPop1" }, 65*7c478bd9Sstevel@tonic-gate { OPMSK|OP3MSK, OP(2) | OP3(0x35), "FPop2" }, 66*7c478bd9Sstevel@tonic-gate { OPMSK|OP3(0x38), OP(3) | OP3(0x20), "FPldst1" }, 67*7c478bd9Sstevel@tonic-gate { OPMSK|OP3(0x38), OP(3) | OP3(0x30), "FPldst2" } 68*7c478bd9Sstevel@tonic-gate }; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate const char *progname; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate static void 73*7c478bd9Sstevel@tonic-gate usage(void) 74*7c478bd9Sstevel@tonic-gate { 75*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Usage: %s infile\n", progname); 76*7c478bd9Sstevel@tonic-gate exit(2); 77*7c478bd9Sstevel@tonic-gate } 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate int 80*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 81*7c478bd9Sstevel@tonic-gate { 82*7c478bd9Sstevel@tonic-gate Elf *elf; 83*7c478bd9Sstevel@tonic-gate Elf_Scn *scn; 84*7c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 85*7c478bd9Sstevel@tonic-gate Elf_Data *text; 86*7c478bd9Sstevel@tonic-gate uint32_t *instrs; 87*7c478bd9Sstevel@tonic-gate char *excludes[MAXEXCLUDES]; 88*7c478bd9Sstevel@tonic-gate int fd, textidx, i, j, c; 89*7c478bd9Sstevel@tonic-gate int shownames = 1; 90*7c478bd9Sstevel@tonic-gate int nexcludes = 0; 91*7c478bd9Sstevel@tonic-gate int found = 0; 92*7c478bd9Sstevel@tonic-gate char *filename; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate progname = basename(argv[0]); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, ":nx:")) != EOF) { 97*7c478bd9Sstevel@tonic-gate switch (c) { 98*7c478bd9Sstevel@tonic-gate case 'n': 99*7c478bd9Sstevel@tonic-gate shownames = 0; 100*7c478bd9Sstevel@tonic-gate break; 101*7c478bd9Sstevel@tonic-gate case 'x': 102*7c478bd9Sstevel@tonic-gate if (nexcludes == MAXEXCLUDES - 1) 103*7c478bd9Sstevel@tonic-gate die("exclusion limit is %d", MAXEXCLUDES); 104*7c478bd9Sstevel@tonic-gate excludes[nexcludes++] = optarg; 105*7c478bd9Sstevel@tonic-gate break; 106*7c478bd9Sstevel@tonic-gate default: 107*7c478bd9Sstevel@tonic-gate usage(); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate if (argc - optind != 1) 112*7c478bd9Sstevel@tonic-gate usage(); 113*7c478bd9Sstevel@tonic-gate filename = argv[optind]; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate if ((fd = open(filename, O_RDONLY)) < 0) 116*7c478bd9Sstevel@tonic-gate die("failed to open %s", filename); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate (void) elf_version(EV_CURRENT); 119*7c478bd9Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) 120*7c478bd9Sstevel@tonic-gate elfdie("failed to open %s as ELF", filename); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate if ((textidx = findelfsecidx(elf, ".text")) < 0) 123*7c478bd9Sstevel@tonic-gate die("failed to find .text section in %s\n", filename); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate if ((scn = elf_getscn(elf, textidx)) == NULL || 126*7c478bd9Sstevel@tonic-gate gelf_getshdr(scn, &shdr) == NULL || 127*7c478bd9Sstevel@tonic-gate (text = elf_rawdata(scn, NULL)) == NULL) 128*7c478bd9Sstevel@tonic-gate elfdie("failed to read .text"); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate instrs = text->d_buf; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate for (i = 0; i < shdr.sh_size / 4; i++) { 133*7c478bd9Sstevel@tonic-gate for (j = 0; j < sizeof (masks) / sizeof (mask_t); j++) { 134*7c478bd9Sstevel@tonic-gate char *symname = NULL; 135*7c478bd9Sstevel@tonic-gate offset_t off; 136*7c478bd9Sstevel@tonic-gate int len = 35; 137*7c478bd9Sstevel@tonic-gate int xcl; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate if ((instrs[i] & masks[j].m_mask) != masks[j].m_val) 140*7c478bd9Sstevel@tonic-gate continue; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate if (findelfsym(elf, i * 4, &symname, &off)) { 143*7c478bd9Sstevel@tonic-gate if (nexcludes > 0) { 144*7c478bd9Sstevel@tonic-gate for (xcl = 0; xcl < nexcludes; xcl++) { 145*7c478bd9Sstevel@tonic-gate if (strcmp(symname, 146*7c478bd9Sstevel@tonic-gate excludes[xcl]) == 0) 147*7c478bd9Sstevel@tonic-gate break; 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (xcl < nexcludes) 151*7c478bd9Sstevel@tonic-gate continue; /* exclude matched */ 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate found++; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate if (!shownames || symname == NULL) { 158*7c478bd9Sstevel@tonic-gate (void) printf("%-*x", len, i * 4); 159*7c478bd9Sstevel@tonic-gate } else { 160*7c478bd9Sstevel@tonic-gate len -= printf("%s+%llx", symname, off); 161*7c478bd9Sstevel@tonic-gate (void) printf("%*s", (len > 0 ? len : 0), ""); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate (void) printf(" %08x %s\n", instrs[i], 165*7c478bd9Sstevel@tonic-gate masks[j].m_name); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate (void) elf_end(elf); 170*7c478bd9Sstevel@tonic-gate (void) close(fd); 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate return (found > 0); 173*7c478bd9Sstevel@tonic-gate } 174