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 (c) 1994, by Sun Microsytems, Inc. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate /* 29*7c478bd9Sstevel@tonic-gate * Functions that know how to create and decode combinations that are 30*7c478bd9Sstevel@tonic-gate * used for connecting probe functions. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #ifndef DEBUG 34*7c478bd9Sstevel@tonic-gate #define NDEBUG 1 35*7c478bd9Sstevel@tonic-gate #endif 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <stdio.h> 38*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 39*7c478bd9Sstevel@tonic-gate #include <string.h> 40*7c478bd9Sstevel@tonic-gate #include <search.h> 41*7c478bd9Sstevel@tonic-gate #include <assert.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #include "tnfctl_int.h" 45*7c478bd9Sstevel@tonic-gate #include "dbg.h" 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* 49*7c478bd9Sstevel@tonic-gate * Typedefs 50*7c478bd9Sstevel@tonic-gate */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate typedef struct comb_callinfo { 53*7c478bd9Sstevel@tonic-gate unsigned offset; 54*7c478bd9Sstevel@tonic-gate unsigned shift; /* shift right <n> bits */ 55*7c478bd9Sstevel@tonic-gate unsigned mask; 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate } comb_callinfo_t; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate typedef struct comb_calltmpl { 60*7c478bd9Sstevel@tonic-gate uintptr_t entry; 61*7c478bd9Sstevel@tonic-gate uintptr_t down; 62*7c478bd9Sstevel@tonic-gate uintptr_t next; 63*7c478bd9Sstevel@tonic-gate uintptr_t end; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate } comb_calltmpl_t; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate typedef struct comb_key { 68*7c478bd9Sstevel@tonic-gate comb_op_t op; 69*7c478bd9Sstevel@tonic-gate uintptr_t down; 70*7c478bd9Sstevel@tonic-gate uintptr_t next; 71*7c478bd9Sstevel@tonic-gate uintptr_t comb; 72*7c478bd9Sstevel@tonic-gate } comb_key_t; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate typedef struct decode_key { 75*7c478bd9Sstevel@tonic-gate uintptr_t addr; 76*7c478bd9Sstevel@tonic-gate char **name_ptrs; 77*7c478bd9Sstevel@tonic-gate uintptr_t *func_addrs; 78*7c478bd9Sstevel@tonic-gate } decode_key_t; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Global - defined in assembler file 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate extern comb_callinfo_t prb_callinfo; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate extern void prb_chain_entry(void); 87*7c478bd9Sstevel@tonic-gate extern void prb_chain_down(void); 88*7c478bd9Sstevel@tonic-gate extern void prb_chain_next(void); 89*7c478bd9Sstevel@tonic-gate extern void prb_chain_end(void); 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate static comb_calltmpl_t calltmpl[PRB_COMB_COUNT] = { 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate (uintptr_t) prb_chain_entry, 94*7c478bd9Sstevel@tonic-gate (uintptr_t) prb_chain_down, 95*7c478bd9Sstevel@tonic-gate (uintptr_t) prb_chain_next, 96*7c478bd9Sstevel@tonic-gate (uintptr_t) prb_chain_end} 97*7c478bd9Sstevel@tonic-gate }; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * Declarations 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t decode(tnfctl_handle_t *hndl, uintptr_t addr, 104*7c478bd9Sstevel@tonic-gate char ***func_names, uintptr_t **func_addrs); 105*7c478bd9Sstevel@tonic-gate static boolean_t find(tnfctl_handle_t *hndl, comb_op_t op, uintptr_t down, 106*7c478bd9Sstevel@tonic-gate uintptr_t next, uintptr_t * comb_p); 107*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t build(tnfctl_handle_t *hndl, comb_op_t op, 108*7c478bd9Sstevel@tonic-gate uintptr_t down, uintptr_t next, uintptr_t * comb_p); 109*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t add(tnfctl_handle_t *hndl, comb_op_t op, uintptr_t down, 110*7c478bd9Sstevel@tonic-gate uintptr_t next, uintptr_t comb); 111*7c478bd9Sstevel@tonic-gate static int comb_compare(const void *a, const void *b); 112*7c478bd9Sstevel@tonic-gate static int decode_compare(const void *v0p, const void *v1p); 113*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t iscomb(tnfctl_handle_t *hndl, uintptr_t addr, 114*7c478bd9Sstevel@tonic-gate uintptr_t *down_p, uintptr_t *next_p, boolean_t *ret_val); 115*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t findname(tnfctl_handle_t *hndl, uintptr_t addr, 116*7c478bd9Sstevel@tonic-gate char **ret_name); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* ---------------------------------------------------------------- */ 120*7c478bd9Sstevel@tonic-gate /* ----------------------- Public Functions ----------------------- */ 121*7c478bd9Sstevel@tonic-gate /* ---------------------------------------------------------------- */ 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * _tnfctl_comb_build() - finds (or builds) a combination satisfing the op, 125*7c478bd9Sstevel@tonic-gate * down and next constraints of the caller. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t 128*7c478bd9Sstevel@tonic-gate _tnfctl_comb_build(tnfctl_handle_t *hndl, comb_op_t op, 129*7c478bd9Sstevel@tonic-gate uintptr_t down, uintptr_t next, uintptr_t *comb_p) 130*7c478bd9Sstevel@tonic-gate { 131*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t prexstat; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate *comb_p = NULL; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(_tnfctl_comb_build_start, "libtnfctl", 136*7c478bd9Sstevel@tonic-gate "start _tnfctl_comb_build; sunw%verbosity 1"); 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate if (find(hndl, op, down, next, comb_p)) { 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(_tnfctl_comb_build_end, "libtnfctl", 141*7c478bd9Sstevel@tonic-gate "end _tnfctl_comb_build; sunw%verbosity 1", 142*7c478bd9Sstevel@tonic-gate tnf_opaque, found_comb_at, *comb_p); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate prexstat = build(hndl, op, down, next, comb_p); 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(_tnfctl_comb_build_end, "libtnfctl", 149*7c478bd9Sstevel@tonic-gate "end _tnfctl_comb_build; sunw%verbosity 1", 150*7c478bd9Sstevel@tonic-gate tnf_opaque, built_comb_at, *comb_p); 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate return (prexstat); 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * _tnfctl_comb_decode() - returns a string describing the probe functions 158*7c478bd9Sstevel@tonic-gate * NOTE - the string is for reference purposes ONLY, it should not be freed 159*7c478bd9Sstevel@tonic-gate * by the client. 160*7c478bd9Sstevel@tonic-gate */ 161*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t 162*7c478bd9Sstevel@tonic-gate _tnfctl_comb_decode(tnfctl_handle_t *hndl, uintptr_t addr, char ***func_names, 163*7c478bd9Sstevel@tonic-gate uintptr_t **func_addrs) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t prexstat; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(_tnfctl_comb_decode_start, "libtnfctl", 168*7c478bd9Sstevel@tonic-gate "start _tnfctl_comb_decode; sunw%verbosity 2"); 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate prexstat = decode(hndl, addr, func_names, func_addrs); 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(_tnfctl_comb_decode_end, "libtnfctl", 173*7c478bd9Sstevel@tonic-gate "end _tnfctl_comb_decode; sunw%verbosity 2"); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate return (prexstat); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* ---------------------------------------------------------------- */ 180*7c478bd9Sstevel@tonic-gate /* ----------------------- Private Functions ---------------------- */ 181*7c478bd9Sstevel@tonic-gate /* ---------------------------------------------------------------- */ 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * if combination has been decoded, return decoded info., else 185*7c478bd9Sstevel@tonic-gate * decode combination and cache information 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 188*7c478bd9Sstevel@tonic-gate decode(tnfctl_handle_t *hndl, uintptr_t addr, char ***func_names, 189*7c478bd9Sstevel@tonic-gate uintptr_t **func_addrs) 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t prexstat = TNFCTL_ERR_NONE; 192*7c478bd9Sstevel@tonic-gate decode_key_t key; 193*7c478bd9Sstevel@tonic-gate decode_key_t *new_p = NULL; 194*7c478bd9Sstevel@tonic-gate decode_key_t **find_pp; 195*7c478bd9Sstevel@tonic-gate uintptr_t down; 196*7c478bd9Sstevel@tonic-gate uintptr_t next; 197*7c478bd9Sstevel@tonic-gate char *thisname = NULL; 198*7c478bd9Sstevel@tonic-gate boolean_t is_combination; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* see if we can find the previously decoded answer */ 201*7c478bd9Sstevel@tonic-gate key.addr = addr; 202*7c478bd9Sstevel@tonic-gate find_pp = (decode_key_t **) tfind(&key, &hndl->decoderoot, 203*7c478bd9Sstevel@tonic-gate decode_compare); 204*7c478bd9Sstevel@tonic-gate if (find_pp) { 205*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(decode_1, "libtnfctl", 206*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; sunw%debug 'found existing'"); 207*7c478bd9Sstevel@tonic-gate *func_names = (*find_pp)->name_ptrs; 208*7c478bd9Sstevel@tonic-gate *func_addrs = (*find_pp)->func_addrs; 209*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate new_p = (decode_key_t *) calloc(1, sizeof (decode_key_t)); 213*7c478bd9Sstevel@tonic-gate if (!new_p) 214*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_ALLOCFAIL); 215*7c478bd9Sstevel@tonic-gate new_p->addr = addr; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate prexstat = iscomb(hndl, addr, &down, &next, &is_combination); 218*7c478bd9Sstevel@tonic-gate if (prexstat) 219*7c478bd9Sstevel@tonic-gate goto Error; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate if (is_combination) { 222*7c478bd9Sstevel@tonic-gate char **nextnames; 223*7c478bd9Sstevel@tonic-gate uintptr_t *nextaddrs; 224*7c478bd9Sstevel@tonic-gate char **name_pp; 225*7c478bd9Sstevel@tonic-gate uintptr_t *addr_p; 226*7c478bd9Sstevel@tonic-gate int count, j; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_2(decode_2, "libtnfctl", "sunw%verbosity 2;", 229*7c478bd9Sstevel@tonic-gate tnf_opaque, down, down, 230*7c478bd9Sstevel@tonic-gate tnf_opaque, next, next); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate prexstat = findname(hndl, down, &thisname); 233*7c478bd9Sstevel@tonic-gate if (prexstat == TNFCTL_ERR_USR1) { 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * should never happen - combination should not 236*7c478bd9Sstevel@tonic-gate * point at the end function 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_INTERNAL; 239*7c478bd9Sstevel@tonic-gate goto Error; 240*7c478bd9Sstevel@tonic-gate } else if (prexstat) 241*7c478bd9Sstevel@tonic-gate goto Error; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate prexstat = decode(hndl, next, &nextnames, &nextaddrs); 244*7c478bd9Sstevel@tonic-gate if (prexstat) 245*7c478bd9Sstevel@tonic-gate goto Error; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* count number of elements - caution: empty 'for' loop */ 248*7c478bd9Sstevel@tonic-gate for (count = 0; nextnames[count]; count++); 249*7c478bd9Sstevel@tonic-gate count++; /* since it was 0 based */ 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* allocate one more for new function name */ 252*7c478bd9Sstevel@tonic-gate new_p->name_ptrs = malloc((count + 1) * 253*7c478bd9Sstevel@tonic-gate sizeof (new_p->name_ptrs[0])); 254*7c478bd9Sstevel@tonic-gate if (new_p->name_ptrs == NULL) { 255*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_ALLOCFAIL; 256*7c478bd9Sstevel@tonic-gate goto Error; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate new_p->func_addrs = malloc((count + 1) * 259*7c478bd9Sstevel@tonic-gate sizeof (new_p->func_addrs[0])); 260*7c478bd9Sstevel@tonic-gate if (new_p->func_addrs == NULL) { 261*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_ALLOCFAIL; 262*7c478bd9Sstevel@tonic-gate goto Error; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate name_pp = new_p->name_ptrs; 265*7c478bd9Sstevel@tonic-gate addr_p = new_p->func_addrs; 266*7c478bd9Sstevel@tonic-gate addr_p[0] = down; 267*7c478bd9Sstevel@tonic-gate name_pp[0] = thisname; 268*7c478bd9Sstevel@tonic-gate for (j = 0; j < count; j++) { 269*7c478bd9Sstevel@tonic-gate name_pp[j + 1] = nextnames[j]; 270*7c478bd9Sstevel@tonic-gate addr_p[j + 1] = nextaddrs[j]; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate } else { 273*7c478bd9Sstevel@tonic-gate prexstat = findname(hndl, addr, &thisname); 274*7c478bd9Sstevel@tonic-gate if (prexstat != TNFCTL_ERR_USR1) { 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * base case - end function is the only function 277*7c478bd9Sstevel@tonic-gate * that can be pointed at directly 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate if (prexstat == TNFCTL_ERR_NONE) 280*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_NONE; 281*7c478bd9Sstevel@tonic-gate goto Error; 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate new_p->name_ptrs = malloc(sizeof (new_p->name_ptrs[0])); 284*7c478bd9Sstevel@tonic-gate if (new_p->name_ptrs == NULL) { 285*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_ALLOCFAIL; 286*7c478bd9Sstevel@tonic-gate goto Error; 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate new_p->func_addrs = malloc(sizeof (new_p->func_addrs[0])); 289*7c478bd9Sstevel@tonic-gate if (new_p->func_addrs == NULL) { 290*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_ALLOCFAIL; 291*7c478bd9Sstevel@tonic-gate goto Error; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate new_p->name_ptrs[0] = NULL; 294*7c478bd9Sstevel@tonic-gate new_p->func_addrs[0] = NULL; 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(decode_3, "libtnfctl", 298*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; sunw%debug 'decode built'", 299*7c478bd9Sstevel@tonic-gate tnf_string, func_name, 300*7c478bd9Sstevel@tonic-gate (thisname) ? (thisname) : "end_func"); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate find_pp = (decode_key_t **) tsearch(new_p, 303*7c478bd9Sstevel@tonic-gate &hndl->decoderoot, decode_compare); 304*7c478bd9Sstevel@tonic-gate assert(*find_pp == new_p); 305*7c478bd9Sstevel@tonic-gate *func_names = new_p->name_ptrs; 306*7c478bd9Sstevel@tonic-gate *func_addrs = new_p->func_addrs; 307*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate Error: 310*7c478bd9Sstevel@tonic-gate if (new_p) { 311*7c478bd9Sstevel@tonic-gate if (new_p->name_ptrs) 312*7c478bd9Sstevel@tonic-gate free(new_p->name_ptrs); 313*7c478bd9Sstevel@tonic-gate if (new_p->func_addrs) 314*7c478bd9Sstevel@tonic-gate free(new_p->func_addrs); 315*7c478bd9Sstevel@tonic-gate free(new_p); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate return (prexstat); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * iscomb() - determine whether the pointed to function is a combination. If 323*7c478bd9Sstevel@tonic-gate * it is, return the down and next pointers 324*7c478bd9Sstevel@tonic-gate */ 325*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 326*7c478bd9Sstevel@tonic-gate iscomb(tnfctl_handle_t *hndl, 327*7c478bd9Sstevel@tonic-gate uintptr_t addr, uintptr_t *down_p, uintptr_t *next_p, 328*7c478bd9Sstevel@tonic-gate boolean_t *ret_val) 329*7c478bd9Sstevel@tonic-gate { 330*7c478bd9Sstevel@tonic-gate int type; 331*7c478bd9Sstevel@tonic-gate boolean_t matched = B_FALSE; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate for (type = 0; type < PRB_COMB_COUNT; type++) { 334*7c478bd9Sstevel@tonic-gate size_t size; 335*7c478bd9Sstevel@tonic-gate int miscstat; 336*7c478bd9Sstevel@tonic-gate char *targ_p; 337*7c478bd9Sstevel@tonic-gate char *ptr; 338*7c478bd9Sstevel@tonic-gate char *tptr; 339*7c478bd9Sstevel@tonic-gate uintptr_t downaddr; 340*7c478bd9Sstevel@tonic-gate uintptr_t nextaddr; 341*7c478bd9Sstevel@tonic-gate int num_bits = 0; 342*7c478bd9Sstevel@tonic-gate int tmp_bits = prb_callinfo.mask; 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* allocate room to copy the target code */ 345*7c478bd9Sstevel@tonic-gate size = (size_t) (calltmpl[type].end - calltmpl[type].entry); 346*7c478bd9Sstevel@tonic-gate targ_p = (char *) malloc(size); 347*7c478bd9Sstevel@tonic-gate if (!targ_p) 348*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_ALLOCFAIL); 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate /* copy code from target */ 351*7c478bd9Sstevel@tonic-gate miscstat = hndl->p_read(hndl->proc_p, addr, targ_p, size); 352*7c478bd9Sstevel@tonic-gate if (miscstat) { 353*7c478bd9Sstevel@tonic-gate free(targ_p); 354*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_INTERNAL); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* find the number of bits before the highest bit in mask */ 358*7c478bd9Sstevel@tonic-gate while (tmp_bits > 0) { 359*7c478bd9Sstevel@tonic-gate num_bits++; 360*7c478bd9Sstevel@tonic-gate tmp_bits <<= 1; 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate /* loop over all the words */ 364*7c478bd9Sstevel@tonic-gate tptr = (char *) calltmpl[type].entry; 365*7c478bd9Sstevel@tonic-gate for (ptr = targ_p; ptr < (targ_p + size); ptr++, tptr++) { 366*7c478bd9Sstevel@tonic-gate int downbits; 367*7c478bd9Sstevel@tonic-gate int nextbits; 368*7c478bd9Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 369*7c478bd9Sstevel@tonic-gate int *uptr = (int *) ptr; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * If we are pointing at one of the words that we 373*7c478bd9Sstevel@tonic-gate * patch, * (down or next displ) then read that value 374*7c478bd9Sstevel@tonic-gate * in. * Otherwise make sure the words match. 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate if ((uintptr_t) tptr == calltmpl[type].down + 377*7c478bd9Sstevel@tonic-gate prb_callinfo.offset) { 378*7c478bd9Sstevel@tonic-gate downbits = *uptr; 379*7c478bd9Sstevel@tonic-gate downbits &= prb_callinfo.mask; 380*7c478bd9Sstevel@tonic-gate /* sign extend */ 381*7c478bd9Sstevel@tonic-gate downbits = (downbits << num_bits) >> num_bits; 382*7c478bd9Sstevel@tonic-gate downbits <<= prb_callinfo.shift; 383*7c478bd9Sstevel@tonic-gate downaddr = addr + (ptr - targ_p) + downbits; 384*7c478bd9Sstevel@tonic-gate #if defined(i386) 385*7c478bd9Sstevel@tonic-gate downaddr += 4; 386*7c478bd9Sstevel@tonic-gate /* intel is relative to *next* instruction */ 387*7c478bd9Sstevel@tonic-gate #endif 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate ptr += 3; 390*7c478bd9Sstevel@tonic-gate tptr += 3; 391*7c478bd9Sstevel@tonic-gate } else if ((uintptr_t) tptr == calltmpl[type].next + 392*7c478bd9Sstevel@tonic-gate prb_callinfo.offset) { 393*7c478bd9Sstevel@tonic-gate nextbits = *uptr; 394*7c478bd9Sstevel@tonic-gate nextbits &= prb_callinfo.mask; 395*7c478bd9Sstevel@tonic-gate /* sign extend */ 396*7c478bd9Sstevel@tonic-gate nextbits = (nextbits << num_bits) >> num_bits; 397*7c478bd9Sstevel@tonic-gate nextbits <<= prb_callinfo.shift; 398*7c478bd9Sstevel@tonic-gate nextaddr = addr + (ptr - targ_p) + nextbits; 399*7c478bd9Sstevel@tonic-gate #if defined(i386) 400*7c478bd9Sstevel@tonic-gate nextaddr += 4; 401*7c478bd9Sstevel@tonic-gate /* intel is relative to *next* instruction */ 402*7c478bd9Sstevel@tonic-gate #endif 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate ptr += 3; 405*7c478bd9Sstevel@tonic-gate tptr += 3; 406*7c478bd9Sstevel@tonic-gate } else { 407*7c478bd9Sstevel@tonic-gate /* the byte better match or we bail */ 408*7c478bd9Sstevel@tonic-gate if (*ptr != *tptr) 409*7c478bd9Sstevel@tonic-gate goto NextComb; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate /* YOWSA! - its a match */ 414*7c478bd9Sstevel@tonic-gate matched = B_TRUE; 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate NextComb: 417*7c478bd9Sstevel@tonic-gate /* free allocated memory */ 418*7c478bd9Sstevel@tonic-gate if (targ_p) 419*7c478bd9Sstevel@tonic-gate free(targ_p); 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate if (matched) { 422*7c478bd9Sstevel@tonic-gate *down_p = downaddr; 423*7c478bd9Sstevel@tonic-gate *next_p = nextaddr; 424*7c478bd9Sstevel@tonic-gate *ret_val = B_TRUE; 425*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate *ret_val = B_FALSE; 430*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate #define FUNC_BUF_SIZE 32 435*7c478bd9Sstevel@tonic-gate /* 436*7c478bd9Sstevel@tonic-gate * findname() - find a name for a function given its address. 437*7c478bd9Sstevel@tonic-gate */ 438*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 439*7c478bd9Sstevel@tonic-gate findname(tnfctl_handle_t *hndl, uintptr_t addr, char **ret_name) 440*7c478bd9Sstevel@tonic-gate { 441*7c478bd9Sstevel@tonic-gate char *symname; 442*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t prexstat; 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate symname = NULL; 445*7c478bd9Sstevel@tonic-gate prexstat = _tnfctl_sym_findname(hndl, addr, &symname); 446*7c478bd9Sstevel@tonic-gate if ((prexstat == TNFCTL_ERR_NONE) && (symname != NULL)) { 447*7c478bd9Sstevel@tonic-gate /* found a name */ 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* 450*7c478bd9Sstevel@tonic-gate * SPECIAL CASE 451*7c478bd9Sstevel@tonic-gate * If we find "tnf_trace_end" then we should not report it 452*7c478bd9Sstevel@tonic-gate * as this is the "end-cap" function and should be hidden 453*7c478bd9Sstevel@tonic-gate * from the user. Return a null string instead ... 454*7c478bd9Sstevel@tonic-gate */ 455*7c478bd9Sstevel@tonic-gate if (strcmp(symname, TRACE_END_FUNC) == 0) { 456*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_USR1); 457*7c478bd9Sstevel@tonic-gate } else { 458*7c478bd9Sstevel@tonic-gate *ret_name = symname; 459*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate } else { 462*7c478bd9Sstevel@tonic-gate char *buffer; 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate buffer = malloc(FUNC_BUF_SIZE); 465*7c478bd9Sstevel@tonic-gate if (buffer == NULL) 466*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_ALLOCFAIL); 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate /* no name found, use the address */ 469*7c478bd9Sstevel@tonic-gate (void) sprintf(buffer, "func@0x%p", addr); 470*7c478bd9Sstevel@tonic-gate *ret_name = buffer; 471*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate /* 477*7c478bd9Sstevel@tonic-gate * find() - try to find an existing combination that satisfies ... 478*7c478bd9Sstevel@tonic-gate */ 479*7c478bd9Sstevel@tonic-gate static boolean_t 480*7c478bd9Sstevel@tonic-gate find(tnfctl_handle_t *hndl, comb_op_t op, uintptr_t down, uintptr_t next, 481*7c478bd9Sstevel@tonic-gate uintptr_t * comb_p) 482*7c478bd9Sstevel@tonic-gate { 483*7c478bd9Sstevel@tonic-gate comb_key_t key; 484*7c478bd9Sstevel@tonic-gate comb_key_t **find_pp; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate key.op = op; 487*7c478bd9Sstevel@tonic-gate key.down = down; 488*7c478bd9Sstevel@tonic-gate key.next = next; 489*7c478bd9Sstevel@tonic-gate key.comb = NULL; 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate find_pp = (comb_key_t **) tfind(&key, &hndl->buildroot, comb_compare); 492*7c478bd9Sstevel@tonic-gate if (find_pp) { 493*7c478bd9Sstevel@tonic-gate *comb_p = (*find_pp)->comb; 494*7c478bd9Sstevel@tonic-gate return (B_TRUE); 495*7c478bd9Sstevel@tonic-gate } else 496*7c478bd9Sstevel@tonic-gate return (B_FALSE); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate /* 501*7c478bd9Sstevel@tonic-gate * add() - adds a combination to combination cache 502*7c478bd9Sstevel@tonic-gate */ 503*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 504*7c478bd9Sstevel@tonic-gate add(tnfctl_handle_t *hndl, comb_op_t op, uintptr_t down, uintptr_t next, 505*7c478bd9Sstevel@tonic-gate uintptr_t comb) 506*7c478bd9Sstevel@tonic-gate { 507*7c478bd9Sstevel@tonic-gate comb_key_t *new_p; 508*7c478bd9Sstevel@tonic-gate /* LINTED set but not used in function */ 509*7c478bd9Sstevel@tonic-gate comb_key_t **ret_pp; 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate new_p = (comb_key_t *) malloc(sizeof (comb_key_t)); 512*7c478bd9Sstevel@tonic-gate if (!new_p) 513*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_ALLOCFAIL); 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate new_p->op = op; 516*7c478bd9Sstevel@tonic-gate new_p->down = down; 517*7c478bd9Sstevel@tonic-gate new_p->next = next; 518*7c478bd9Sstevel@tonic-gate new_p->comb = comb; 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate ret_pp = (comb_key_t **) tsearch(new_p, &hndl->buildroot, 521*7c478bd9Sstevel@tonic-gate comb_compare); 522*7c478bd9Sstevel@tonic-gate assert(*ret_pp == new_p); 523*7c478bd9Sstevel@tonic-gate return (TNFCTL_ERR_NONE); 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate /* 528*7c478bd9Sstevel@tonic-gate * decode_compare() - comparison function used for tree search for 529*7c478bd9Sstevel@tonic-gate * combinations 530*7c478bd9Sstevel@tonic-gate */ 531*7c478bd9Sstevel@tonic-gate static int 532*7c478bd9Sstevel@tonic-gate decode_compare(const void *v0p, const void *v1p) 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate decode_key_t *k0p = (decode_key_t *) v0p; 535*7c478bd9Sstevel@tonic-gate decode_key_t *k1p = (decode_key_t *) v1p; 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate return (int) ((uintptr_t) k1p->addr - (uintptr_t) k0p->addr); 538*7c478bd9Sstevel@tonic-gate } /* end decode_compare */ 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate /* 542*7c478bd9Sstevel@tonic-gate * comb_compare() - comparison function used for tree search for combinations 543*7c478bd9Sstevel@tonic-gate */ 544*7c478bd9Sstevel@tonic-gate static int 545*7c478bd9Sstevel@tonic-gate comb_compare(const void *v0p, const void *v1p) 546*7c478bd9Sstevel@tonic-gate { 547*7c478bd9Sstevel@tonic-gate comb_key_t *k0p = (comb_key_t *) v0p; 548*7c478bd9Sstevel@tonic-gate comb_key_t *k1p = (comb_key_t *) v1p; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate if (k0p->op != k1p->op) 551*7c478bd9Sstevel@tonic-gate return ((k0p->op < k1p->op) ? -1 : 1); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate if (k0p->down != k1p->down) 554*7c478bd9Sstevel@tonic-gate return ((k0p->down < k1p->down) ? -1 : 1); 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate if (k0p->next != k1p->next) 557*7c478bd9Sstevel@tonic-gate return ((k0p->next < k1p->next) ? -1 : 1); 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate return (0); 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate } /* end comb_compare */ 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate /* 564*7c478bd9Sstevel@tonic-gate * build() - build a composition 565*7c478bd9Sstevel@tonic-gate */ 566*7c478bd9Sstevel@tonic-gate static tnfctl_errcode_t 567*7c478bd9Sstevel@tonic-gate build(tnfctl_handle_t *hndl, comb_op_t op, uintptr_t down, uintptr_t next, 568*7c478bd9Sstevel@tonic-gate uintptr_t *comb_p) 569*7c478bd9Sstevel@tonic-gate { 570*7c478bd9Sstevel@tonic-gate size_t size; 571*7c478bd9Sstevel@tonic-gate uintptr_t addr; 572*7c478bd9Sstevel@tonic-gate char *buffer_p = NULL; 573*7c478bd9Sstevel@tonic-gate uintptr_t offset; 574*7c478bd9Sstevel@tonic-gate uintptr_t contents; 575*7c478bd9Sstevel@tonic-gate unsigned *word_p; 576*7c478bd9Sstevel@tonic-gate int miscstat; 577*7c478bd9Sstevel@tonic-gate tnfctl_errcode_t prexstat; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate #if 0 580*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "off=0x%x shift=0x%x mask=0x%x size=%d\n", 581*7c478bd9Sstevel@tonic-gate prb_callinfo.offset, 582*7c478bd9Sstevel@tonic-gate prb_callinfo.shift, 583*7c478bd9Sstevel@tonic-gate prb_callinfo.mask, 584*7c478bd9Sstevel@tonic-gate calltmpl[op].end - calltmpl[op].entry); 585*7c478bd9Sstevel@tonic-gate #endif 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate *comb_p = NULL; 588*7c478bd9Sstevel@tonic-gate size = calltmpl[op].end - calltmpl[op].entry; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate /* allocate memory in the target process */ 591*7c478bd9Sstevel@tonic-gate prexstat = _tnfctl_targmem_alloc(hndl, size, &addr); 592*7c478bd9Sstevel@tonic-gate if (prexstat) { 593*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 594*7c478bd9Sstevel@tonic-gate "build: trouble allocating target memory:\n")); 595*7c478bd9Sstevel@tonic-gate goto Error; 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* allocate a scratch buffer, copy the template into it */ 599*7c478bd9Sstevel@tonic-gate buffer_p = malloc(size); 600*7c478bd9Sstevel@tonic-gate if (!buffer_p) { 601*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, "build: alloc failed\n")); 602*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_ALLOCFAIL; 603*7c478bd9Sstevel@tonic-gate goto Error; 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer_p, (void *) calltmpl[op].entry, size); 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate /* poke the down address */ 608*7c478bd9Sstevel@tonic-gate offset = calltmpl[op].down - calltmpl[op].entry; 609*7c478bd9Sstevel@tonic-gate /*LINTED pointer cast may result in improper alignment*/ 610*7c478bd9Sstevel@tonic-gate word_p = (unsigned *) (buffer_p + offset + prb_callinfo.offset); 611*7c478bd9Sstevel@tonic-gate contents = down - (addr + offset); 612*7c478bd9Sstevel@tonic-gate #if defined(i386) 613*7c478bd9Sstevel@tonic-gate contents -= 5; /* intel offset is relative to *next* instr */ 614*7c478bd9Sstevel@tonic-gate #endif 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_4(build_1, "libtnfctl", "sunw%verbosity 3", 617*7c478bd9Sstevel@tonic-gate tnf_opaque, down, down, 618*7c478bd9Sstevel@tonic-gate tnf_opaque, contents, contents, 619*7c478bd9Sstevel@tonic-gate tnf_opaque, word_p, word_p, 620*7c478bd9Sstevel@tonic-gate tnf_long, offset, offset); 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate *word_p &= ~prb_callinfo.mask; /* clear the relevant field */ 623*7c478bd9Sstevel@tonic-gate *word_p |= ((contents >> prb_callinfo.shift) & prb_callinfo.mask); 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate /* poke the next address */ 626*7c478bd9Sstevel@tonic-gate offset = calltmpl[op].next - calltmpl[op].entry; 627*7c478bd9Sstevel@tonic-gate /*LINTED pointer cast may result in improper alignment*/ 628*7c478bd9Sstevel@tonic-gate word_p = (unsigned *) (buffer_p + offset + prb_callinfo.offset); 629*7c478bd9Sstevel@tonic-gate contents = next - (addr + offset); 630*7c478bd9Sstevel@tonic-gate #if defined(i386) 631*7c478bd9Sstevel@tonic-gate contents -= 5; /* intel offset is relative to *next* instr */ 632*7c478bd9Sstevel@tonic-gate #endif 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_4(build_2, "libtnfctl", "sunw%verbosity 3", 635*7c478bd9Sstevel@tonic-gate tnf_opaque, next, next, 636*7c478bd9Sstevel@tonic-gate tnf_opaque, contents, contents, 637*7c478bd9Sstevel@tonic-gate tnf_opaque, word_p, word_p, 638*7c478bd9Sstevel@tonic-gate tnf_long, offset, offset); 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate *word_p &= ~prb_callinfo.mask; /* clear the relevant field */ 641*7c478bd9Sstevel@tonic-gate *word_p |= ((contents >> prb_callinfo.shift) & prb_callinfo.mask); 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate /* copy the combination template into target memory */ 644*7c478bd9Sstevel@tonic-gate miscstat = hndl->p_write(hndl->proc_p, addr, buffer_p, size); 645*7c478bd9Sstevel@tonic-gate if (miscstat) { 646*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 647*7c478bd9Sstevel@tonic-gate "build: trouble writing combination: \n")); 648*7c478bd9Sstevel@tonic-gate prexstat = TNFCTL_ERR_INTERNAL; 649*7c478bd9Sstevel@tonic-gate goto Error; 650*7c478bd9Sstevel@tonic-gate } 651*7c478bd9Sstevel@tonic-gate *comb_p = addr; 652*7c478bd9Sstevel@tonic-gate prexstat = add(hndl, op, down, next, addr); 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate Error: 655*7c478bd9Sstevel@tonic-gate if (buffer_p) 656*7c478bd9Sstevel@tonic-gate free(buffer_p); 657*7c478bd9Sstevel@tonic-gate return (prexstat); 658*7c478bd9Sstevel@tonic-gate } 659