comb.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1994, by Sun Microsytems, Inc.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Functions that know how to create and decode combinations that are
* used for connecting probe functions.
*/
#ifndef DEBUG
#define NDEBUG 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <search.h>
#include <assert.h>
#include "tnfctl_int.h"
#include "dbg.h"
/*
* Typedefs
*/
typedef struct comb_callinfo {
unsigned offset;
unsigned shift; /* shift right <n> bits */
unsigned mask;
typedef struct comb_calltmpl {
typedef struct comb_key {
} comb_key_t;
typedef struct decode_key {
char **name_ptrs;
} decode_key_t;
/*
* Global - defined in assembler file
*/
extern comb_callinfo_t prb_callinfo;
extern void prb_chain_entry(void);
extern void prb_chain_down(void);
extern void prb_chain_next(void);
extern void prb_chain_end(void);
{
};
/*
* Declarations
*/
static int comb_compare(const void *a, const void *b);
char **ret_name);
/* ---------------------------------------------------------------- */
/* ----------------------- Public Functions ----------------------- */
/* ---------------------------------------------------------------- */
/*
* _tnfctl_comb_build() - finds (or builds) a combination satisfing the op,
* down and next constraints of the caller.
*/
{
"start _tnfctl_comb_build; sunw%verbosity 1");
"end _tnfctl_comb_build; sunw%verbosity 1",
return (TNFCTL_ERR_NONE);
}
"end _tnfctl_comb_build; sunw%verbosity 1",
return (prexstat);
}
/*
* _tnfctl_comb_decode() - returns a string describing the probe functions
* NOTE - the string is for reference purposes ONLY, it should not be freed
* by the client.
*/
{
"start _tnfctl_comb_decode; sunw%verbosity 2");
"end _tnfctl_comb_decode; sunw%verbosity 2");
return (prexstat);
}
/* ---------------------------------------------------------------- */
/* ----------------------- Private Functions ---------------------- */
/* ---------------------------------------------------------------- */
/*
* if combination has been decoded, return decoded info., else
* decode combination and cache information
*/
static tnfctl_errcode_t
{
/* see if we can find the previously decoded answer */
if (find_pp) {
"sunw%verbosity 2; sunw%debug 'found existing'");
return (TNFCTL_ERR_NONE);
}
if (!new_p)
return (TNFCTL_ERR_ALLOCFAIL);
if (prexstat)
goto Error;
if (is_combination) {
char **nextnames;
char **name_pp;
int count, j;
if (prexstat == TNFCTL_ERR_USR1) {
/*
* should never happen - combination should not
* point at the end function
*/
goto Error;
} else if (prexstat)
goto Error;
if (prexstat)
goto Error;
/* count number of elements - caution: empty 'for' loop */
count++; /* since it was 0 based */
/* allocate one more for new function name */
goto Error;
}
sizeof (new_p->func_addrs[0]));
goto Error;
}
for (j = 0; j < count; j++) {
}
} else {
if (prexstat != TNFCTL_ERR_USR1) {
/*
* base case - end function is the only function
* that can be pointed at directly
*/
if (prexstat == TNFCTL_ERR_NONE)
goto Error;
}
goto Error;
}
goto Error;
}
}
"sunw%verbosity 2; sunw%debug 'decode built'",
return (TNFCTL_ERR_NONE);
if (new_p) {
if (new_p->func_addrs)
}
return (prexstat);
}
/*
* iscomb() - determine whether the pointed to function is a combination. If
* it is, return the down and next pointers
*/
static tnfctl_errcode_t
{
int type;
int miscstat;
char *targ_p;
char *ptr;
char *tptr;
int num_bits = 0;
/* allocate room to copy the target code */
if (!targ_p)
return (TNFCTL_ERR_ALLOCFAIL);
/* copy code from target */
if (miscstat) {
return (TNFCTL_ERR_INTERNAL);
}
/* find the number of bits before the highest bit in mask */
while (tmp_bits > 0) {
num_bits++;
tmp_bits <<= 1;
}
/* loop over all the words */
int downbits;
int nextbits;
/* LINTED pointer cast may result in improper alignment */
/*
* If we are pointing at one of the words that we
* patch, * (down or next displ) then read that value
* in. * Otherwise make sure the words match.
*/
/* sign extend */
#if defined(i386)
downaddr += 4;
/* intel is relative to *next* instruction */
#endif
ptr += 3;
tptr += 3;
/* sign extend */
#if defined(i386)
nextaddr += 4;
/* intel is relative to *next* instruction */
#endif
ptr += 3;
tptr += 3;
} else {
/* the byte better match or we bail */
goto NextComb;
}
}
/* YOWSA! - its a match */
/* free allocated memory */
if (targ_p)
if (matched) {
return (TNFCTL_ERR_NONE);
}
}
return (TNFCTL_ERR_NONE);
}
#define FUNC_BUF_SIZE 32
/*
* findname() - find a name for a function given its address.
*/
static tnfctl_errcode_t
{
char *symname;
/* found a name */
/*
* SPECIAL CASE
* If we find "tnf_trace_end" then we should not report it
* as this is the "end-cap" function and should be hidden
* from the user. Return a null string instead ...
*/
return (TNFCTL_ERR_USR1);
} else {
return (TNFCTL_ERR_NONE);
}
} else {
char *buffer;
return (TNFCTL_ERR_ALLOCFAIL);
/* no name found, use the address */
return (TNFCTL_ERR_NONE);
}
}
/*
* find() - try to find an existing combination that satisfies ...
*/
static boolean_t
{
if (find_pp) {
return (B_TRUE);
} else
return (B_FALSE);
}
/*
* add() - adds a combination to combination cache
*/
static tnfctl_errcode_t
{
/* LINTED set but not used in function */
comb_key_t **ret_pp;
if (!new_p)
return (TNFCTL_ERR_ALLOCFAIL);
return (TNFCTL_ERR_NONE);
}
/*
* decode_compare() - comparison function used for tree search for
* combinations
*/
static int
{
} /* end decode_compare */
/*
* comb_compare() - comparison function used for tree search for combinations
*/
static int
{
return (0);
} /* end comb_compare */
/*
* build() - build a composition
*/
static tnfctl_errcode_t
{
unsigned *word_p;
int miscstat;
#if 0
#endif
/* allocate memory in the target process */
if (prexstat) {
"build: trouble allocating target memory:\n"));
goto Error;
}
/* allocate a scratch buffer, copy the template into it */
if (!buffer_p) {
goto Error;
}
/* poke the down address */
/*LINTED pointer cast may result in improper alignment*/
#if defined(i386)
#endif
/* poke the next address */
/*LINTED pointer cast may result in improper alignment*/
#if defined(i386)
#endif
/* copy the combination template into target memory */
if (miscstat) {
"build: trouble writing combination: \n"));
goto Error;
}
if (buffer_p)
return (prexstat);
}