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 38260670Sjhibbits#include <libproc_compat.h> 39260670Sjhibbits 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{ 45260670Sjhibbits ftp->ftps_type = DTFTP_ENTRY; 46260670Sjhibbits ftp->ftps_pc = (uintptr_t)symp->st_value; 47260670Sjhibbits ftp->ftps_size = (size_t)symp->st_size; 48260670Sjhibbits ftp->ftps_noffs = 1; 49260670Sjhibbits ftp->ftps_offs[0] = 0; 50242723Sjhibbits 51260670Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 52260670Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 53260670Sjhibbits strerror(errno)); 54260670Sjhibbits return (dt_set_errno(dtp, errno)); 55260670Sjhibbits } 56260670Sjhibbits 57260670Sjhibbits 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 65260670Sjhibbits uintptr_t temp; 66260670Sjhibbits uint32_t *text; 67260670Sjhibbits int i; 68260670Sjhibbits int srdepth = 0; 69260670Sjhibbits 70260670Sjhibbits if ((text = malloc(symp->st_size + 4)) == NULL) { 71260670Sjhibbits dt_dprintf("mr sparkle: malloc() failed\n"); 72260670Sjhibbits return (DT_PROC_ERR); 73260670Sjhibbits } 74260670Sjhibbits 75260670Sjhibbits if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) { 76260670Sjhibbits dt_dprintf("mr sparkle: Pread() failed\n"); 77260670Sjhibbits free(text); 78260670Sjhibbits return (DT_PROC_ERR); 79260670Sjhibbits } 80260670Sjhibbits 81260670Sjhibbits /* 82260670Sjhibbits * Leave a dummy instruction in the last slot to simplify edge 83260670Sjhibbits * conditions. 84260670Sjhibbits */ 85260670Sjhibbits text[symp->st_size / 4] = 0; 86260670Sjhibbits 87260670Sjhibbits ftp->ftps_type = DTFTP_RETURN; 88260670Sjhibbits ftp->ftps_pc = symp->st_value; 89260670Sjhibbits ftp->ftps_size = symp->st_size; 90260670Sjhibbits ftp->ftps_noffs = 0; 91260670Sjhibbits 92260670Sjhibbits for (i = 0; i < symp->st_size / 4; i++) { 93260670Sjhibbits 94260670Sjhibbits if ((text[i] & 0xfc000001) != 0x48000000 && 95260670Sjhibbits text[i] != 0x4e800020) 96260670Sjhibbits continue; 97260670Sjhibbits 98260670Sjhibbits /* 99260670Sjhibbits * Check for a jump within this function. If it's outside this 100260670Sjhibbits * function then it's a tail-call, so a return point. 101260670Sjhibbits */ 102260670Sjhibbits if ((text[i] & 0xfc000000) == 0x48000000) { 103260670Sjhibbits temp = (text[i] & 0x03fffffc); 104260670Sjhibbits /* Bit 30 denotes an absolute address. */ 105260670Sjhibbits if (!(text[i] & 0x02)) { 106260670Sjhibbits temp += symp->st_value + i * 4; 107260670Sjhibbits } 108260670Sjhibbits else { 109260670Sjhibbits /* Sign extend the absolute address. */ 110260670Sjhibbits if (temp & 0x02000000) { 111260670Sjhibbits temp |= (UINTPTR_MAX - 0x03ffffff); 112260670Sjhibbits } 113260670Sjhibbits } 114260670Sjhibbits if (temp >= symp->st_value && 115260670Sjhibbits temp <= (symp->st_value + symp->st_size)) 116260670Sjhibbits continue; 117260670Sjhibbits } 118260670Sjhibbits dt_dprintf("return at offset %x\n", i * 4); 119260670Sjhibbits ftp->ftps_offs[ftp->ftps_noffs++] = i * 4; 120260670Sjhibbits } 121260670Sjhibbits 122260670Sjhibbits free(text); 123260670Sjhibbits if (ftp->ftps_noffs > 0) { 124260670Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 125260670Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 126260670Sjhibbits strerror(errno)); 127260670Sjhibbits return (dt_set_errno(dtp, errno)); 128260670Sjhibbits } 129260670Sjhibbits } 130260670Sjhibbits 131260670Sjhibbits 132260670Sjhibbits 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{ 140260670Sjhibbits if (off & 0x3) 141260670Sjhibbits return (DT_PROC_ALIGN); 142242723Sjhibbits 143260670Sjhibbits ftp->ftps_type = DTFTP_OFFSETS; 144260670Sjhibbits ftp->ftps_pc = (uintptr_t)symp->st_value; 145260670Sjhibbits ftp->ftps_size = (size_t)symp->st_size; 146260670Sjhibbits ftp->ftps_noffs = 1; 147260670Sjhibbits ftp->ftps_offs[0] = off; 148260670Sjhibbits 149260670Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 150260670Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 151260670Sjhibbits strerror(errno)); 152260670Sjhibbits return (dt_set_errno(dtp, errno)); 153260670Sjhibbits } 154260670Sjhibbits 155260670Sjhibbits 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{ 163260670Sjhibbits ulong_t i; 164242723Sjhibbits 165260670Sjhibbits ftp->ftps_type = DTFTP_OFFSETS; 166260670Sjhibbits ftp->ftps_pc = (uintptr_t)symp->st_value; 167260670Sjhibbits ftp->ftps_size = (size_t)symp->st_size; 168260670Sjhibbits ftp->ftps_noffs = 0; 169260670Sjhibbits 170260670Sjhibbits /* 171260670Sjhibbits * If we're matching against everything, just iterate through each 172260670Sjhibbits * instruction in the function, otherwise look for matching offset 173260670Sjhibbits * names by constructing the string and comparing it against the 174260670Sjhibbits * pattern. 175260670Sjhibbits */ 176260670Sjhibbits if (strcmp("*", pattern) == 0) { 177260670Sjhibbits for (i = 0; i < symp->st_size; i += 4) { 178260670Sjhibbits ftp->ftps_offs[ftp->ftps_noffs++] = i; 179260670Sjhibbits } 180260670Sjhibbits } else { 181260670Sjhibbits char name[sizeof (i) * 2 + 1]; 182260670Sjhibbits 183260670Sjhibbits for (i = 0; i < symp->st_size; i += 4) { 184260670Sjhibbits (void) sprintf(name, "%lx", i); 185260670Sjhibbits if (gmatch(name, pattern)) 186260670Sjhibbits ftp->ftps_offs[ftp->ftps_noffs++] = i; 187260670Sjhibbits } 188260670Sjhibbits } 189260670Sjhibbits 190260670Sjhibbits if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { 191260670Sjhibbits dt_dprintf("fasttrap probe creation ioctl failed: %s\n", 192260670Sjhibbits strerror(errno)); 193260670Sjhibbits return (dt_set_errno(dtp, errno)); 194260670Sjhibbits } 195260670Sjhibbits 196260670Sjhibbits return (ftp->ftps_noffs); 197242723Sjhibbits} 198