1242723Sjhibbits/* 2242723Sjhibbits * CDDL HEADER START 3242723Sjhibbits * 4242723Sjhibbits * The contents of this file are subject to the terms of the 5242723Sjhibbits * Common Development and Distribution License, Version 1.0 only 6242723Sjhibbits * (the "License"). You may not use this file except in compliance 7242723Sjhibbits * with the License. 8242723Sjhibbits * 9242723Sjhibbits * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10242723Sjhibbits * or http://www.opensolaris.org/os/licensing. 11242723Sjhibbits * See the License for the specific language governing permissions 12242723Sjhibbits * and limitations under the License. 13242723Sjhibbits * 14242723Sjhibbits * When distributing Covered Code, include this CDDL HEADER in each 15242723Sjhibbits * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16242723Sjhibbits * If applicable, add the following below this CDDL HEADER, with the 17242723Sjhibbits * fields enclosed by brackets "[]" replaced with your own identifying 18242723Sjhibbits * information: Portions Copyright [yyyy] [name of copyright owner] 19242723Sjhibbits * 20242723Sjhibbits * CDDL HEADER END 21242723Sjhibbits */ 22242723Sjhibbits/* 23242723Sjhibbits * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24242723Sjhibbits * Use is subject to license terms. 25242723Sjhibbits */ 26242723Sjhibbits 27242723Sjhibbits#pragma ident "%Z%%M% %I% %E% SMI" 28242723Sjhibbits 29242723Sjhibbits#include <stdlib.h> 30242723Sjhibbits#include <assert.h> 31242723Sjhibbits#include <errno.h> 32242723Sjhibbits#include <string.h> 33242723Sjhibbits#include <libgen.h> 34242723Sjhibbits 35242723Sjhibbits#include <dt_impl.h> 36242723Sjhibbits#include <dt_pid.h> 37242723Sjhibbits 38256543Sjhibbits#include <libproc_compat.h> 39256543Sjhibbits 40242723Sjhibbits/*ARGSUSED*/ 41242723Sjhibbitsint 42242723Sjhibbitsdt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, 43242723Sjhibbits fasttrap_probe_spec_t *ftp, const GElf_Sym *symp) 44242723Sjhibbits{ 45256543Sjhibbits ftp->ftps_type = DTFTP_ENTRY; 46256543Sjhibbits ftp->ftps_pc = (uintptr_t)symp->st_value; 47256543Sjhibbits ftp->ftps_size = (size_t)symp->st_size; 48256543Sjhibbits ftp->ftps_noffs = 1; 49256543Sjhibbits ftp->ftps_offs[0] = 0; 50242723Sjhibbits 51256543Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 52256543Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 53256543Sjhibbits strerror(errno)); 54256543Sjhibbits return (dt_set_errno(dtp, errno)); 55256543Sjhibbits } 56256543Sjhibbits 57256543Sjhibbits return (1); 58242723Sjhibbits} 59242723Sjhibbits 60242723Sjhibbitsint 61242723Sjhibbitsdt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, 62242723Sjhibbits fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret) 63242723Sjhibbits{ 64242723Sjhibbits 65256543Sjhibbits uintptr_t temp; 66256543Sjhibbits uint32_t *text; 67256543Sjhibbits int i; 68256543Sjhibbits int srdepth = 0; 69256543Sjhibbits 70256543Sjhibbits if ((text = malloc(symp->st_size + 4)) == NULL) { 71256543Sjhibbits dt_dprintf("mr sparkle: malloc() failed\n"); 72256543Sjhibbits return (DT_PROC_ERR); 73256543Sjhibbits } 74256543Sjhibbits 75256543Sjhibbits if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) { 76256543Sjhibbits dt_dprintf("mr sparkle: Pread() failed\n"); 77256543Sjhibbits free(text); 78256543Sjhibbits return (DT_PROC_ERR); 79256543Sjhibbits } 80256543Sjhibbits 81256543Sjhibbits /* 82256543Sjhibbits * Leave a dummy instruction in the last slot to simplify edge 83256543Sjhibbits * conditions. 84256543Sjhibbits */ 85256543Sjhibbits text[symp->st_size / 4] = 0; 86256543Sjhibbits 87256543Sjhibbits ftp->ftps_type = DTFTP_RETURN; 88256543Sjhibbits ftp->ftps_pc = symp->st_value; 89256543Sjhibbits ftp->ftps_size = symp->st_size; 90256543Sjhibbits ftp->ftps_noffs = 0; 91256543Sjhibbits 92256543Sjhibbits for (i = 0; i < symp->st_size / 4; i++) { 93256543Sjhibbits 94256543Sjhibbits if ((text[i] & 0xfc000001) != 0x48000000 && 95256543Sjhibbits text[i] != 0x4e800020) 96256543Sjhibbits continue; 97256543Sjhibbits 98256543Sjhibbits /* 99256543Sjhibbits * Check for a jump within this function. If it's outside this 100256543Sjhibbits * function then it's a tail-call, so a return point. 101256543Sjhibbits */ 102256543Sjhibbits if ((text[i] & 0xfc000000) == 0x48000000) { 103256543Sjhibbits temp = (text[i] & 0x03fffffc); 104256543Sjhibbits /* Bit 30 denotes an absolute address. */ 105256543Sjhibbits if (!(text[i] & 0x02)) { 106256543Sjhibbits temp += symp->st_value + i * 4; 107256543Sjhibbits } 108256543Sjhibbits else { 109256543Sjhibbits /* Sign extend the absolute address. */ 110256543Sjhibbits if (temp & 0x02000000) { 111256543Sjhibbits temp |= (UINTPTR_MAX - 0x03ffffff); 112256543Sjhibbits } 113256543Sjhibbits } 114256543Sjhibbits if (temp >= symp->st_value && 115256543Sjhibbits temp <= (symp->st_value + symp->st_size)) 116256543Sjhibbits continue; 117256543Sjhibbits } 118256543Sjhibbits dt_dprintf("return at offset %x\n", i * 4); 119256543Sjhibbits ftp->ftps_offs[ftp->ftps_noffs++] = i * 4; 120256543Sjhibbits } 121256543Sjhibbits 122256543Sjhibbits free(text); 123256543Sjhibbits if (ftp->ftps_noffs > 0) { 124256543Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 125256543Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 126256543Sjhibbits strerror(errno)); 127256543Sjhibbits return (dt_set_errno(dtp, errno)); 128256543Sjhibbits } 129256543Sjhibbits } 130256543Sjhibbits 131256543Sjhibbits 132256543Sjhibbits return (ftp->ftps_noffs); 133242723Sjhibbits} 134242723Sjhibbits 135242723Sjhibbits/*ARGSUSED*/ 136242723Sjhibbitsint 137242723Sjhibbitsdt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, 138242723Sjhibbits fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off) 139242723Sjhibbits{ 140256543Sjhibbits if (off & 0x3) 141256543Sjhibbits return (DT_PROC_ALIGN); 142242723Sjhibbits 143256543Sjhibbits ftp->ftps_type = DTFTP_OFFSETS; 144256543Sjhibbits ftp->ftps_pc = (uintptr_t)symp->st_value; 145256543Sjhibbits ftp->ftps_size = (size_t)symp->st_size; 146256543Sjhibbits ftp->ftps_noffs = 1; 147256543Sjhibbits ftp->ftps_offs[0] = off; 148256543Sjhibbits 149256543Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 150256543Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 151256543Sjhibbits strerror(errno)); 152256543Sjhibbits return (dt_set_errno(dtp, errno)); 153256543Sjhibbits } 154256543Sjhibbits 155256543Sjhibbits return (1); 156242723Sjhibbits} 157242723Sjhibbits 158242723Sjhibbits/*ARGSUSED*/ 159242723Sjhibbitsint 160242723Sjhibbitsdt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp, 161242723Sjhibbits fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern) 162242723Sjhibbits{ 163256543Sjhibbits ulong_t i; 164242723Sjhibbits 165256543Sjhibbits ftp->ftps_type = DTFTP_OFFSETS; 166256543Sjhibbits ftp->ftps_pc = (uintptr_t)symp->st_value; 167256543Sjhibbits ftp->ftps_size = (size_t)symp->st_size; 168256543Sjhibbits ftp->ftps_noffs = 0; 169256543Sjhibbits 170256543Sjhibbits /* 171256543Sjhibbits * If we're matching against everything, just iterate through each 172256543Sjhibbits * instruction in the function, otherwise look for matching offset 173256543Sjhibbits * names by constructing the string and comparing it against the 174256543Sjhibbits * pattern. 175256543Sjhibbits */ 176256543Sjhibbits if (strcmp("*", pattern) == 0) { 177256543Sjhibbits for (i = 0; i < symp->st_size; i += 4) { 178256543Sjhibbits ftp->ftps_offs[ftp->ftps_noffs++] = i; 179256543Sjhibbits } 180256543Sjhibbits } else { 181256543Sjhibbits char name[sizeof (i) * 2 + 1]; 182256543Sjhibbits 183256543Sjhibbits for (i = 0; i < symp->st_size; i += 4) { 184256543Sjhibbits (void) sprintf(name, "%lx", i); 185256543Sjhibbits if (gmatch(name, pattern)) 186256543Sjhibbits ftp->ftps_offs[ftp->ftps_noffs++] = i; 187256543Sjhibbits } 188256543Sjhibbits } 189256543Sjhibbits 190256543Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 191256543Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 192256543Sjhibbits strerror(errno)); 193256543Sjhibbits return (dt_set_errno(dtp, errno)); 194256543Sjhibbits } 195256543Sjhibbits 196256543Sjhibbits return (ftp->ftps_noffs); 197242723Sjhibbits} 198