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 2005 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 <stdlib.h> 30 #include <assert.h> 31 #include <errno.h> 32 #include <string.h> 33 #include <libgen.h> 34 #include <sys/ioctl.h> 35 36 #include <dt_impl.h> 37 #include <dt_pid.h> 38 39 #define OP(x) ((x) >> 30) 40 #define OP2(x) (((x) >> 22) & 0x07) 41 #define COND(x) (((x) >> 25) & 0x0f) 42 #define A(x) (((x) >> 29) & 0x01) 43 44 #define OP_BRANCH 0 45 46 #define OP2_BPcc 0x1 47 #define OP2_Bicc 0x2 48 #define OP2_BPr 0x3 49 #define OP2_FBPfcc 0x5 50 #define OP2_FBfcc 0x6 51 52 /*ARGSUSED*/ 53 int 54 dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, 55 fasttrap_probe_spec_t *ftp, const GElf_Sym *symp) 56 { 57 ftp->ftps_type = DTFTP_ENTRY; 58 ftp->ftps_pc = (uintptr_t)symp->st_value; 59 ftp->ftps_size = (size_t)symp->st_size; 60 ftp->ftps_noffs = 1; 61 ftp->ftps_offs[0] = 0; 62 63 if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 64 dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 65 strerror(errno)); 66 return (dt_set_errno(dtp, errno)); 67 } 68 69 return (1); 70 } 71 72 int 73 dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, 74 fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret) 75 { 76 77 uint32_t *text; 78 int i; 79 int srdepth = 0; 80 81 dt_dprintf("%s: unimplemented\n", __func__); 82 return (DT_PROC_ERR); 83 84 if ((text = malloc(symp->st_size + 4)) == NULL) { 85 dt_dprintf("mr sparkle: malloc() failed\n"); 86 return (DT_PROC_ERR); 87 } 88 #ifdef DOODAD 89 if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) { 90 dt_dprintf("mr sparkle: Pread() failed\n"); 91 free(text); 92 return (DT_PROC_ERR); 93 } 94 #endif 95 96 /* 97 * Leave a dummy instruction in the last slot to simplify edge 98 * conditions. 99 */ 100 text[symp->st_size / 4] = 0; 101 102 ftp->ftps_type = DTFTP_RETURN; 103 ftp->ftps_pc = symp->st_value; 104 ftp->ftps_size = symp->st_size; 105 ftp->ftps_noffs = 0; 106 107 108 free(text); 109 if (ftp->ftps_noffs > 0) { 110 if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 111 dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 112 strerror(errno)); 113 return (dt_set_errno(dtp, errno)); 114 } 115 } 116 117 118 return (ftp->ftps_noffs); 119 } 120 121 /*ARGSUSED*/ 122 int 123 dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, 124 fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off) 125 { 126 if (off & 0x3) 127 return (DT_PROC_ALIGN); 128 129 ftp->ftps_type = DTFTP_OFFSETS; 130 ftp->ftps_pc = (uintptr_t)symp->st_value; 131 ftp->ftps_size = (size_t)symp->st_size; 132 ftp->ftps_noffs = 1; 133 ftp->ftps_offs[0] = off; 134 135 if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 136 dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 137 strerror(errno)); 138 return (dt_set_errno(dtp, errno)); 139 } 140 141 return (1); 142 } 143 144 /*ARGSUSED*/ 145 int 146 dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp, 147 fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern) 148 { 149 ulong_t i; 150 151 ftp->ftps_type = DTFTP_OFFSETS; 152 ftp->ftps_pc = (uintptr_t)symp->st_value; 153 ftp->ftps_size = (size_t)symp->st_size; 154 ftp->ftps_noffs = 0; 155 156 /* 157 * If we're matching against everything, just iterate through each 158 * instruction in the function, otherwise look for matching offset 159 * names by constructing the string and comparing it against the 160 * pattern. 161 */ 162 if (strcmp("*", pattern) == 0) { 163 for (i = 0; i < symp->st_size; i += 4) { 164 ftp->ftps_offs[ftp->ftps_noffs++] = i; 165 } 166 } else { 167 char name[sizeof (i) * 2 + 1]; 168 169 for (i = 0; i < symp->st_size; i += 4) { 170 (void) snprintf(name, sizeof(name), "%lx", i); 171 if (gmatch(name, pattern)) 172 ftp->ftps_offs[ftp->ftps_noffs++] = i; 173 } 174 } 175 176 if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 177 dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 178 strerror(errno)); 179 return (dt_set_errno(dtp, errno)); 180 } 181 182 return (ftp->ftps_noffs); 183 } 184 185