xref: /onnv-gate/usr/src/cmd/sgs/prof/common/symintLoad.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
23*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate /*
29*0Sstevel@tonic-gate *	File: symintLoad.c
30*0Sstevel@tonic-gate *	Date: 12/15/88
31*0Sstevel@tonic-gate *
32*0Sstevel@tonic-gate *	This file provides code to build the profiling symbol array
33*0Sstevel@tonic-gate *	(array of PROF_SYMBOL).  This array contains all of the
34*0Sstevel@tonic-gate *	symbol table information plus selected debug information for
35*0Sstevel@tonic-gate *	each file and each function that has a coverage array.
36*0Sstevel@tonic-gate *
37*0Sstevel@tonic-gate *	The symbol table contains entries for every file, every
38*0Sstevel@tonic-gate *	function, and every coverage array.  The debug information
39*0Sstevel@tonic-gate *	has corresponding entries except that there are no entries
40*0Sstevel@tonic-gate *	for the coverage arrays.  (This may change later.)
41*0Sstevel@tonic-gate *
42*0Sstevel@tonic-gate *	The algorithm for building the profiling symbol array
43*0Sstevel@tonic-gate *	consists of scanning the symbol table for file, function,
44*0Sstevel@tonic-gate *	and coverage array entries and building an entry for each.
45*0Sstevel@tonic-gate *	The construction of an entry is constrained by the
46*0Sstevel@tonic-gate *	following factors:
47*0Sstevel@tonic-gate *
48*0Sstevel@tonic-gate *		- An entry is built for every file.
49*0Sstevel@tonic-gate *
50*0Sstevel@tonic-gate *		- An entry is built for a function only if there
51*0Sstevel@tonic-gate *		is a corresponding coverage array for the function.
52*0Sstevel@tonic-gate *
53*0Sstevel@tonic-gate *		- Entries must be ordered in the sense that each
54*0Sstevel@tonic-gate *		non-file entry points to its owner file and each
55*0Sstevel@tonic-gate *		file entry points to the next file (or null).
56*0Sstevel@tonic-gate *
57*0Sstevel@tonic-gate *		- The assembler specification (see C Issue 5 3B2
58*0Sstevel@tonic-gate *		Assembler System Test Specification by Howe, p. 28)
59*0Sstevel@tonic-gate *		states that all local symbols follow their file
60*0Sstevel@tonic-gate *		symbol in the symbol table.  This allows us to relate
61*0Sstevel@tonic-gate *		a function and its coverage array to the file that
62*0Sstevel@tonic-gate *		contains it.
63*0Sstevel@tonic-gate *
64*0Sstevel@tonic-gate *		- For each symbol included in the profiling symbol
65*0Sstevel@tonic-gate *		array, all corresponding symbol table information must
66*0Sstevel@tonic-gate *		be present together with selected debug information.
67*0Sstevel@tonic-gate *		Therefore, the correspondence between a symbol table
68*0Sstevel@tonic-gate *		entry and a debug entry must be established.
69*0Sstevel@tonic-gate *
70*0Sstevel@tonic-gate *		- Although duplicate (static) function names may appear,
71*0Sstevel@tonic-gate *		the names are unique within a given file.  Also, the
72*0Sstevel@tonic-gate *		value (address) of each function is included in both
73*0Sstevel@tonic-gate *		the symbol table information and the debug information.
74*0Sstevel@tonic-gate *		This provides a verifable correspondence between these
75*0Sstevel@tonic-gate *		information sets.
76*0Sstevel@tonic-gate *
77*0Sstevel@tonic-gate *	The algorithm used in this file is as follows:
78*0Sstevel@tonic-gate */
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate /*
83*0Sstevel@tonic-gate * This is a discussion of the problem of multiple files with a single
84*0Sstevel@tonic-gate * name.  (See also, the _err_exit call in the routine "add_function".)
85*0Sstevel@tonic-gate *
86*0Sstevel@tonic-gate * Currently, when the executable contains more than one file with
87*0Sstevel@tonic-gate * a common name, we sometimes mix a set of functions with the wrong
88*0Sstevel@tonic-gate * file.  Because the addresses don't match, add_profsymbol tends to
89*0Sstevel@tonic-gate * fail (with _err_exit).  The problem is to consistently choose the
90*0Sstevel@tonic-gate * correct file for the set of functions that are about to be processed.
91*0Sstevel@tonic-gate * This aspect of the problem has been addressed by the code below,
92*0Sstevel@tonic-gate * but there is another part to the story.
93*0Sstevel@tonic-gate *
94*0Sstevel@tonic-gate * In order to match the symbol table with the debug information, we
95*0Sstevel@tonic-gate * have to strip the path (if any) off of the file name; that is,
96*0Sstevel@tonic-gate * the function _CAleaf is used to find the name of the file.  This
97*0Sstevel@tonic-gate * means that even if we make the match, we may still have trouble
98*0Sstevel@tonic-gate * finding the file.  One solution might be to retain a pointer to
99*0Sstevel@tonic-gate * the full name for use at the proper point (when lprof is trying
100*0Sstevel@tonic-gate * to find the source file).  I have not traced this down completely;
101*0Sstevel@tonic-gate * it may or may not work depending upon whether the full path is
102*0Sstevel@tonic-gate * always included in the debug information.  If it is not possible
103*0Sstevel@tonic-gate * to depend on the complete path, then there may be no way to completely
104*0Sstevel@tonic-gate * solve the problem.  (Consider talking to the debugger people about
105*0Sstevel@tonic-gate * this problem; they have to deal with it also.)
106*0Sstevel@tonic-gate *
107*0Sstevel@tonic-gate * Below I have included the code I used to solve the first part of
108*0Sstevel@tonic-gate * the problem.  I have also included an explanation of what each part
109*0Sstevel@tonic-gate * of the code does.  When the code is implemented this way, it does
110*0Sstevel@tonic-gate * work for some cases, but I'm not sure that the assumptions it makes
111*0Sstevel@tonic-gate * are valid.  In particular, it makes implicit assumptions about the
112*0Sstevel@tonic-gate * ordering of names and pointers; you should check that these assumptions
113*0Sstevel@tonic-gate * do not include that the values returned from malloc are monotone
114*0Sstevel@tonic-gate * increasing (which I think they do).
115*0Sstevel@tonic-gate *
116*0Sstevel@tonic-gate * With the following change, add_profsymbol will scan to the first
117*0Sstevel@tonic-gate * file entry of the given name that has not yet been processed.  It
118*0Sstevel@tonic-gate * detects that a file has been processed by noting that sn_value_p
119*0Sstevel@tonic-gate * has been set to zero; it accepts the first one whose value is not
120*0Sstevel@tonic-gate * zero and calls dbfill_tag to "refill" the tag.  Warning: setting
121*0Sstevel@tonic-gate * sn_value_p to zero is dangerous; in particular, you must avoid
122*0Sstevel@tonic-gate * trying to use this value when it is zero.  Some cpus will produce
123*0Sstevel@tonic-gate * a segmentation violation, but the 3b2 does not.
124*0Sstevel@tonic-gate *
125*0Sstevel@tonic-gate * add_profsymbol()
126*0Sstevel@tonic-gate * {
127*0Sstevel@tonic-gate * ...
128*0Sstevel@tonic-gate * 	} else if (stchk_file(prsym_p)) {
129*0Sstevel@tonic-gate * 		if (
130*0Sstevel@tonic-gate * 			(sn_p + 1) < (dblist + dblist_cnt)
131*0Sstevel@tonic-gate * 			&& strcmp(sn_p[0].sn_name_p, sn_p[1].sn_name_p) == 0
132*0Sstevel@tonic-gate * 		) {
133*0Sstevel@tonic-gate * 			_err_warn(
134*0Sstevel@tonic-gate * 				"File name %s was used more than once.",
135*0Sstevel@tonic-gate * 				sn_p->sn_name_p
136*0Sstevel@tonic-gate * 			);
137*0Sstevel@tonic-gate * 			while (
138*0Sstevel@tonic-gate * 				sn_p->sn_value_p == 0
139*0Sstevel@tonic-gate * 				&& sn_p < (dblist + dblist_cnt)
140*0Sstevel@tonic-gate * 			) {
141*0Sstevel@tonic-gate * 				sn_p++;
142*0Sstevel@tonic-gate * 			}
143*0Sstevel@tonic-gate * 			dbfill_tag(sn_p->sn_value_p, &tag);
144*0Sstevel@tonic-gate * 		}
145*0Sstevel@tonic-gate * 		sn_p->sn_value_p = 0;
146*0Sstevel@tonic-gate * 		add_file(&tag);
147*0Sstevel@tonic-gate * 	} else {
148*0Sstevel@tonic-gate * ...
149*0Sstevel@tonic-gate * }
150*0Sstevel@tonic-gate *
151*0Sstevel@tonic-gate * The change to sn_search is only to prepare for a call to sn_compare
152*0Sstevel@tonic-gate * which has been changed to compare on both the name and the pointer
153*0Sstevel@tonic-gate * value (instead of just the name).  (Here, we might be using the
154*0Sstevel@tonic-gate * incorrect assumption that malloc is monotone increasing; this scheme
155*0Sstevel@tonic-gate * should be carefully thought out.)  The change consists of setting
156*0Sstevel@tonic-gate * the sn_value_p in the local tnode to zero; this allows sn_compare
157*0Sstevel@tonic-gate * to ignore the value and compare only the name.
158*0Sstevel@tonic-gate *
159*0Sstevel@tonic-gate * sn_search()
160*0Sstevel@tonic-gate * {
161*0Sstevel@tonic-gate * ...
162*0Sstevel@tonic-gate * 	tnode.sn_name_p = name_p;
163*0Sstevel@tonic-gate * 	tnode.sn_value_p = 0;
164*0Sstevel@tonic-gate * ...
165*0Sstevel@tonic-gate * }
166*0Sstevel@tonic-gate *
167*0Sstevel@tonic-gate * This routine used to compare only the name; now it compares both
168*0Sstevel@tonic-gate * the name and  the sn_value_p pointer (see note above sn_search).
169*0Sstevel@tonic-gate * When the value pointer is zero, there is no use in comparing
170*0Sstevel@tonic-gate * that part of the item.
171*0Sstevel@tonic-gate *
172*0Sstevel@tonic-gate * sn_compare()
173*0Sstevel@tonic-gate * {
174*0Sstevel@tonic-gate * 	register int i;
175*0Sstevel@tonic-gate *
176*0Sstevel@tonic-gate * 	if (i = strcmp(a_p->sn_name_p, b_p->sn_name_p)) {
177*0Sstevel@tonic-gate * 		return(i);
178*0Sstevel@tonic-gate *  	} else if (a_p->sn_value_p == 0 || b_p->sn_value_p == 0) {
179*0Sstevel@tonic-gate *  		return(i);
180*0Sstevel@tonic-gate *  	} else if (a_p->sn_value_p < b_p->sn_value_p) {
181*0Sstevel@tonic-gate *  		return(-1);
182*0Sstevel@tonic-gate *  	} else {
183*0Sstevel@tonic-gate *  		return(1);
184*0Sstevel@tonic-gate *  	}
185*0Sstevel@tonic-gate * }
186*0Sstevel@tonic-gate */
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate #include "string.h"
190*0Sstevel@tonic-gate #include "symint.h"
191*0Sstevel@tonic-gate #include "debug.h"
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate /* search node */
194*0Sstevel@tonic-gate typedef struct {
195*0Sstevel@tonic-gate 	char *sn_name_p;
196*0Sstevel@tonic-gate 	char *sn_value_p;
197*0Sstevel@tonic-gate } SEARCH_NODE;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate PROF_SYMBOL * _symintLoad();
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate #if isLPROF
203*0Sstevel@tonic-gate static int addcovset();
204*0Sstevel@tonic-gate static SEARCH_NODE *build_stlist();
205*0Sstevel@tonic-gate static int stscan();
206*0Sstevel@tonic-gate static int stchk_focov();
207*0Sstevel@tonic-gate static int stchk_filowog();
208*0Sstevel@tonic-gate static int stchk_gowf();
209*0Sstevel@tonic-gate static int stchk_func();
210*0Sstevel@tonic-gate static int stchk_file();
211*0Sstevel@tonic-gate static int stchk_cov();
212*0Sstevel@tonic-gate static int stchk_match();
213*0Sstevel@tonic-gate static void init_dblist();
214*0Sstevel@tonic-gate static int dbscan_tag();
215*0Sstevel@tonic-gate static void dbfill_tag();
216*0Sstevel@tonic-gate static char * dbseek_att();
217*0Sstevel@tonic-gate static int dbchk_stmnts();
218*0Sstevel@tonic-gate static int dbchk_lowpc();
219*0Sstevel@tonic-gate static int dbchk_highpc();
220*0Sstevel@tonic-gate static int dbchk_filosub();
221*0Sstevel@tonic-gate static PROF_SYMBOL * add_profsymbol();
222*0Sstevel@tonic-gate static int add_function();
223*0Sstevel@tonic-gate static void add_file();
224*0Sstevel@tonic-gate static void check_capacity();
225*0Sstevel@tonic-gate static char * debName();
226*0Sstevel@tonic-gate static LEN4 bytesFor();
227*0Sstevel@tonic-gate static SEARCH_NODE * sn_search();
228*0Sstevel@tonic-gate static int sn_compare();
229*0Sstevel@tonic-gate #ifdef DEBUG
230*0Sstevel@tonic-gate static void sn_dump();
231*0Sstevel@tonic-gate static void profsym_dump();
232*0Sstevel@tonic-gate #endif
233*0Sstevel@tonic-gate static LEN2 alignval2();
234*0Sstevel@tonic-gate static LEN4 alignval4();
235*0Sstevel@tonic-gate static void verify_match();
236*0Sstevel@tonic-gate #endif
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate /* debug tag */
240*0Sstevel@tonic-gate typedef struct {
241*0Sstevel@tonic-gate 	LEN4	tg_length;
242*0Sstevel@tonic-gate 	LEN2	tg_value;
243*0Sstevel@tonic-gate 	char	*tg_att_p;
244*0Sstevel@tonic-gate 	int	tg_attlen;
245*0Sstevel@tonic-gate } DB_TAG;
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate /*
248*0Sstevel@tonic-gate *	Debug list used to connect a symbol table entry to a debug entry.
249*0Sstevel@tonic-gate */
250*0Sstevel@tonic-gate static SEARCH_NODE	*dblist;	/* array */
251*0Sstevel@tonic-gate static int		dblist_cnt;	/* number of elements in array */
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate /*
254*0Sstevel@tonic-gate *	Global symbol table list used to connect coverage array entries
255*0Sstevel@tonic-gate *	with their (global) owner functions.  This list contains all
256*0Sstevel@tonic-gate *	global and weak functions.
257*0Sstevel@tonic-gate */
258*0Sstevel@tonic-gate static SEARCH_NODE	*gstlist;	/* array */
259*0Sstevel@tonic-gate static int		gstlist_cnt;	/* number of elements in array */
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate static PROF_FILE	*profPtr;
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate #define ST_NAME(a)	&profPtr->pf_symstr_p[(a)->st_name]
264*0Sstevel@tonic-gate #define PS_NAME(a)	&profPtr->pf_symstr_p[(a)->ps_sym.st_name]
265*0Sstevel@tonic-gate #define DB_NAME(a)	(a)->ps_dbg.pd_name
266*0Sstevel@tonic-gate #define DB_TAGLEN(ap)	alignval4(ap)
267*0Sstevel@tonic-gate #define DB_STMNTOS(ap)	alignval4((ap) + sizeof(LEN2))
268*0Sstevel@tonic-gate #define DB_PCVALUE(ap)	alignval4((ap) + sizeof(LEN2))
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate /*
271*0Sstevel@tonic-gate *	NOTE: When you change MATCH_STR, also change pcrt1.s.
272*0Sstevel@tonic-gate *	(See notes on "verify_match" below.)
273*0Sstevel@tonic-gate */
274*0Sstevel@tonic-gate #ifdef __STDC__
275*0Sstevel@tonic-gate #define	MATCH_NAME	_edata
276*0Sstevel@tonic-gate #define	MATCH_STR	"_edata"
277*0Sstevel@tonic-gate #else
278*0Sstevel@tonic-gate #define	MATCH_NAME	edata
279*0Sstevel@tonic-gate #define	MATCH_STR	"edata"
280*0Sstevel@tonic-gate #endif
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate static PROF_SYMBOL	*prsym_list_p = 0;	/* the list to return. */
283*0Sstevel@tonic-gate static int		prsym_cnt = 0;	/* #entries in the list */
284*0Sstevel@tonic-gate static int		prsym_cap = 0;	/* #entries capacity allocated */
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate static int		prstsym_size;	/* size of a symbol table symbol */
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate static int		add_profsym_search_fail; /* see add_profsymbol() */
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate #if isLPROF
291*0Sstevel@tonic-gate static int		prsym_size;	/* size of a PROF_SYMBOL */
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate /* * * * * *
295*0Sstevel@tonic-gate  * addr of line information, and of the PROF_DEBUGE,
296*0Sstevel@tonic-gate  * associated with the last file (symbol) seen.
297*0Sstevel@tonic-gate  *
298*0Sstevel@tonic-gate  * also, the DEBUGE for the file in effect Before the current one!
299*0Sstevel@tonic-gate  */
300*0Sstevel@tonic-gate #define DBG_LINE_SIZE	(sizeof(LEN4) + sizeof(LEN2) + sizeof(LEN4))
301*0Sstevel@tonic-gate static char		*curf_lp;
302*0Sstevel@tonic-gate static LEN4		curf_lncnt;
303*0Sstevel@tonic-gate static LEN4		curf_base;
304*0Sstevel@tonic-gate static PROF_LINE	*curf_lns_p;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate static PROF_DEBUGE	*curf_dbp;
307*0Sstevel@tonic-gate static PROF_DEBUGE	*priorFile_dbp;
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate #endif
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate /* * * * * *
312*0Sstevel@tonic-gate  * _symintLoad(proffilePtr)
313*0Sstevel@tonic-gate  * proffilePtr	- PROF_FILE pointer returned by _symintOpen().
314*0Sstevel@tonic-gate  *
315*0Sstevel@tonic-gate  * returns PROF_SYMBOL * - pointer to the malloc-ed array of
316*0Sstevel@tonic-gate  * 			   symbol information entries, or
317*0Sstevel@tonic-gate  * 			   NULL if fails.
318*0Sstevel@tonic-gate  *
319*0Sstevel@tonic-gate  *
320*0Sstevel@tonic-gate  * This routine builds the interface data structure from the data
321*0Sstevel@tonic-gate  * already loaded during _symintOpen().
322*0Sstevel@tonic-gate  *
323*0Sstevel@tonic-gate  * There are two different incarnations of this routine:
324*0Sstevel@tonic-gate  * one for Prof, and one for Lprof.
325*0Sstevel@tonic-gate  *
326*0Sstevel@tonic-gate  * Lprof:
327*0Sstevel@tonic-gate  *
328*0Sstevel@tonic-gate  * 	1. Pass through the symbol table and
329*0Sstevel@tonic-gate  * 	   populate an extended PROF_SYMBOL array.
330*0Sstevel@tonic-gate  *
331*0Sstevel@tonic-gate  * 	2. Include only certain symbols (see intro).
332*0Sstevel@tonic-gate  *
333*0Sstevel@tonic-gate  * 	3. Find and include the debug information
334*0Sstevel@tonic-gate  * 	   for each included symbol.
335*0Sstevel@tonic-gate  *
336*0Sstevel@tonic-gate  * Prof:
337*0Sstevel@tonic-gate  *
338*0Sstevel@tonic-gate  * 	1. Allocate a duplicate copy of the symbol table
339*0Sstevel@tonic-gate  * 	   data.  (For Prof, a PROF_SYMBOL is just
340*0Sstevel@tonic-gate  * 	   a structure containing an Elf32_Sym!)
341*0Sstevel@tonic-gate  *
342*0Sstevel@tonic-gate  * 	2. Set internal parameters to reflect this.
343*0Sstevel@tonic-gate  *
344*0Sstevel@tonic-gate  *
345*0Sstevel@tonic-gate  * Problems are dealt with by issuing an _err_exit().
346*0Sstevel@tonic-gate  *
347*0Sstevel@tonic-gate  */
348*0Sstevel@tonic-gate PROF_SYMBOL *
349*0Sstevel@tonic-gate _symintLoad(proffilePtr)
350*0Sstevel@tonic-gate PROF_FILE	*proffilePtr;
351*0Sstevel@tonic-gate {
352*0Sstevel@tonic-gate 	Elf_Data	*symdat_p;
353*0Sstevel@tonic-gate 	PROF_SYMBOL	*ps;
354*0Sstevel@tonic-gate 	int		symcount = 0;
355*0Sstevel@tonic-gate #if isLPROF
356*0Sstevel@tonic-gate 	Elf32_Sym	*sym_p;
357*0Sstevel@tonic-gate 	Elf32_Sym	*sym_lim_p;
358*0Sstevel@tonic-gate 	Elf32_Sym	*next_p;
359*0Sstevel@tonic-gate 	Elf32_Sym	*tsym_p;
360*0Sstevel@tonic-gate #endif
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	DEBUG_LOC("_symintLoad: top");
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	profPtr = proffilePtr;
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate 	/* * * * * *
367*0Sstevel@tonic-gate 	 * sanity checks.
368*0Sstevel@tonic-gate 	 */
369*0Sstevel@tonic-gate 	DEBUG_EXP(printf("profPtr = %x\n", profPtr));
370*0Sstevel@tonic-gate 	DEBUG_EXP(printf("profPtr->pf_symdat_p = %x\n", profPtr->pf_symdat_p));
371*0Sstevel@tonic-gate 	DEBUG_EXP(printf("profPtr->pf_nstsyms = %x\n", profPtr->pf_nstsyms));
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	assert( profPtr != 0 );
374*0Sstevel@tonic-gate 	assert( profPtr->pf_symdat_p != 0 );
375*0Sstevel@tonic-gate 	assert( profPtr->pf_nstsyms != 0 );
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 	symdat_p = profPtr->pf_symdat_p;
378*0Sstevel@tonic-gate 	DEBUG_EXP(printf("symdat_p->d_size = %x\n", symdat_p->d_size));
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 	prstsym_size = (symdat_p->d_size / profPtr->pf_nstsyms);
381*0Sstevel@tonic-gate 	DEBUG_EXP(printf("_symintLoad: prstsym_size = %d\n",prstsym_size));
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate #if isLPROF
384*0Sstevel@tonic-gate 	prsym_size = prstsym_size + sizeof(PROF_DEBUGE);
385*0Sstevel@tonic-gate 	DEBUG_EXP(printf("_symintLoad: prsym_size = %d\n",prsym_size));
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 	/* * * * * *
388*0Sstevel@tonic-gate 	 * Initialize structure parameters.  Updated by add_profsymbol().
389*0Sstevel@tonic-gate 	 */
390*0Sstevel@tonic-gate 	prsym_cnt = prsym_cap = 0;
391*0Sstevel@tonic-gate 
392*0Sstevel@tonic-gate 	init_dblist();
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	sym_lim_p = (Elf32_Sym *)
395*0Sstevel@tonic-gate 		(((char *) (symdat_p->d_buf)) + symdat_p->d_size);
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate 	tsym_p = NULL;
398*0Sstevel@tonic-gate 	gstlist = build_stlist(tsym_p, sym_lim_p, stchk_gowf, &gstlist_cnt);
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 	verify_match();
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	next_p = NULL;
403*0Sstevel@tonic-gate 	(void) stscan(&next_p, sym_lim_p, stchk_file);
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 	priorFile_dbp = 0;
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	sym_p = next_p;
408*0Sstevel@tonic-gate 	while (sym_p < sym_lim_p) {
409*0Sstevel@tonic-gate 		NO_DEBUG(printf("index for sym_p = %d\n",sym_p->st_name));
410*0Sstevel@tonic-gate 		NO_DEBUG(printf("name for sym_p = %s\n", ST_NAME(sym_p)));
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 		(void) stscan(&next_p, sym_lim_p, stchk_filowog);
413*0Sstevel@tonic-gate 		tsym_p = sym_p;
414*0Sstevel@tonic-gate 		if (stscan(&tsym_p, next_p, stchk_cov)) {
415*0Sstevel@tonic-gate 			symcount += addcovset(sym_p, next_p, tsym_p);
416*0Sstevel@tonic-gate 		}
417*0Sstevel@tonic-gate 		if (!stchk_file(next_p)) {
418*0Sstevel@tonic-gate 			(void) stscan(&next_p, sym_lim_p, stchk_file);
419*0Sstevel@tonic-gate 		}
420*0Sstevel@tonic-gate 		sym_p = next_p;
421*0Sstevel@tonic-gate 	}
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 	free(gstlist);
424*0Sstevel@tonic-gate 	profPtr->pf_nsyms = symcount;
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate 	DEBUG_EXP(printf("number of symbols constructed = %d\n", symcount));
427*0Sstevel@tonic-gate #ifdef DEBUG
428*0Sstevel@tonic-gate 	printf("before profsym_dump\n");
429*0Sstevel@tonic-gate 	profsym_dump(prsym_list_p, symcount);
430*0Sstevel@tonic-gate 	printf("after profsym_dump\n");
431*0Sstevel@tonic-gate #endif
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate #else	/* isPROF */
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	/* * * * * *
436*0Sstevel@tonic-gate 	 * alloc a new copy of the array, and
437*0Sstevel@tonic-gate 	 *  do a bit-wise copy since the structures
438*0Sstevel@tonic-gate 	 *  ARE THE SAME SIZE & (effectively) HAVE THE SAME FIELDS!
439*0Sstevel@tonic-gate 	 *  Set the descriptive `parameters' accordingly.
440*0Sstevel@tonic-gate 	 *
441*0Sstevel@tonic-gate 	 * (We'll take a copy, to simplify the 'Drop'
442*0Sstevel@tonic-gate 	 *  logic.)
443*0Sstevel@tonic-gate 	 */
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate 	{
446*0Sstevel@tonic-gate 	int st_size;	/* size of symbol table data */
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	st_size = symdat_p->d_size;
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	NO_DEBUG_LOC("_symintLoad: before malloc for symbol list (PROF)");
451*0Sstevel@tonic-gate 	prsym_list_p = (PROF_SYMBOL *) _Malloc(st_size, 1);
452*0Sstevel@tonic-gate 	NO_DEBUG_LOC("_symintLoad: after malloc for symbol list (PROF)");
453*0Sstevel@tonic-gate 	prsym_cap = prsym_cnt = profPtr->pf_nstsyms;
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate 	NO_DEBUG_LOC("_symintLoad: before memcpy for symbol list (PROF)");
456*0Sstevel@tonic-gate 	memcpy((char *) &(prsym_list_p->ps_sym), symdat_p->d_buf, st_size);
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate 	profPtr->pf_nsyms = profPtr->pf_nstsyms;
459*0Sstevel@tonic-gate 	}
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate #endif
462*0Sstevel@tonic-gate 	DEBUG_LOC("_symintLoad: bottom");
463*0Sstevel@tonic-gate 	return( prsym_list_p );
464*0Sstevel@tonic-gate }
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 
467*0Sstevel@tonic-gate #ifdef  isLPROF
468*0Sstevel@tonic-gate /*
469*0Sstevel@tonic-gate *	addcovset: Add coverage array set to PROF_SYMBOL array.
470*0Sstevel@tonic-gate *
471*0Sstevel@tonic-gate *	The (local) symbols between the given file symbol and the
472*0Sstevel@tonic-gate *	end contain at least one coverage array.  Sort all function
473*0Sstevel@tonic-gate *	and coverage array symbols (by name) within the given bounds
474*0Sstevel@tonic-gate *	and process each of the coverage array symbols by finding
475*0Sstevel@tonic-gate *	its corresponding (local or global) function and adding entries
476*0Sstevel@tonic-gate *	for both the coverage array and the function to the profile
477*0Sstevel@tonic-gate *	symbol array.  Note that the file is also added to the profile
478*0Sstevel@tonic-gate *	symbol array and that pointers are managed accordingly (the file
479*0Sstevel@tonic-gate *	entries are linked and each of the non-file entries points
480*0Sstevel@tonic-gate *	to its owner file).
481*0Sstevel@tonic-gate *
482*0Sstevel@tonic-gate *	- Add the file to the PROF_SYMBOL array.  If the file is not
483*0Sstevel@tonic-gate *	found (i.e., the filename in the debug information does not
484*0Sstevel@tonic-gate *	match the filename in the symbol table), then fail.
485*0Sstevel@tonic-gate *	- Build (allocate) a sorted list of all function and coverage
486*0Sstevel@tonic-gate *	array symbols within the given limits.
487*0Sstevel@tonic-gate *	- Find the top of the coverage array subset of the pointer list.
488*0Sstevel@tonic-gate *	- For each coverage array pointer:
489*0Sstevel@tonic-gate *		- Find its function (look in local list, then global list).
490*0Sstevel@tonic-gate *		- Add function and assoc coverage array to PROF_SYMBOL array.
491*0Sstevel@tonic-gate *	- Free the sorted list.
492*0Sstevel@tonic-gate *
493*0Sstevel@tonic-gate *	Note: "k" is used to avoid having "cov_p" increment beyond
494*0Sstevel@tonic-gate *	the last allocated search node and thereby (possibly) cause
495*0Sstevel@tonic-gate *	a segmentation violation.
496*0Sstevel@tonic-gate */
497*0Sstevel@tonic-gate static int
498*0Sstevel@tonic-gate addcovset(filsym_p, end_p, cov_p)
499*0Sstevel@tonic-gate Elf32_Sym *filsym_p;
500*0Sstevel@tonic-gate Elf32_Sym *end_p;
501*0Sstevel@tonic-gate Elf32_Sym *cov_p;
502*0Sstevel@tonic-gate {
503*0Sstevel@tonic-gate 	SEARCH_NODE	*stl_p;
504*0Sstevel@tonic-gate 	SEARCH_NODE	*sncov_p;
505*0Sstevel@tonic-gate 	SEARCH_NODE	*snfunc_p;
506*0Sstevel@tonic-gate 	PROF_SYMBOL	*ps_p;
507*0Sstevel@tonic-gate 	int		k, stlcount;
508*0Sstevel@tonic-gate 	char		*fname_p;
509*0Sstevel@tonic-gate 	int		symcount = 0;
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate 	DEBUG_LOC("addcovset: top");
512*0Sstevel@tonic-gate 	ps_p = add_profsymbol(filsym_p);
513*0Sstevel@tonic-gate 	if (add_profsym_search_fail) {
514*0Sstevel@tonic-gate 		_err_exit("Unable to locate file %s in debug information.\n",
515*0Sstevel@tonic-gate 			ST_NAME(filsym_p)
516*0Sstevel@tonic-gate 		);
517*0Sstevel@tonic-gate 	}
518*0Sstevel@tonic-gate 	ps_p->ps_dbg.pd_file_p = 0;
519*0Sstevel@tonic-gate 	symcount++;
520*0Sstevel@tonic-gate 	DEBUG_EXP(printf("debug name for ps_p = %s\n", DB_NAME(ps_p)));
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 	curf_dbp = &(ps_p->ps_dbg);
523*0Sstevel@tonic-gate 	if (priorFile_dbp) {
524*0Sstevel@tonic-gate 		priorFile_dbp->pd_file_p = curf_dbp;
525*0Sstevel@tonic-gate 	}
526*0Sstevel@tonic-gate 	priorFile_dbp = curf_dbp;
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate 	stl_p = build_stlist(filsym_p, end_p, stchk_focov, &stlcount);
529*0Sstevel@tonic-gate 	sncov_p = sn_search(ST_NAME(cov_p), stl_p, stlcount);
530*0Sstevel@tonic-gate 	while (
531*0Sstevel@tonic-gate 		(sncov_p-1) >= stl_p
532*0Sstevel@tonic-gate 		&& strncmp(
533*0Sstevel@tonic-gate 			(sncov_p-1)->sn_name_p,
534*0Sstevel@tonic-gate 			COV_PREFIX,
535*0Sstevel@tonic-gate 			sizeof(COV_PREFIX)-1
536*0Sstevel@tonic-gate 		) == 0
537*0Sstevel@tonic-gate 	) {
538*0Sstevel@tonic-gate 		sncov_p--;
539*0Sstevel@tonic-gate 	}
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate 	k = stlcount;
542*0Sstevel@tonic-gate 	while (k-- > 0 && stchk_cov((Elf32_Sym *) (sncov_p->sn_value_p))) {
543*0Sstevel@tonic-gate 		fname_p = (char *) &(sncov_p->sn_name_p[sizeof(COV_PREFIX)-1]);
544*0Sstevel@tonic-gate 		if (
545*0Sstevel@tonic-gate 			(snfunc_p = sn_search(fname_p, stl_p, stlcount))
546*0Sstevel@tonic-gate 			|| (snfunc_p = sn_search(fname_p, gstlist, gstlist_cnt))
547*0Sstevel@tonic-gate 		) {
548*0Sstevel@tonic-gate 			ps_p = add_profsymbol(snfunc_p->sn_value_p);
549*0Sstevel@tonic-gate 			ps_p->ps_dbg.pd_file_p = curf_dbp;
550*0Sstevel@tonic-gate 			symcount++;
551*0Sstevel@tonic-gate 
552*0Sstevel@tonic-gate 			ps_p = add_profsymbol(sncov_p->sn_value_p);
553*0Sstevel@tonic-gate 			ps_p->ps_dbg.pd_file_p = curf_dbp;
554*0Sstevel@tonic-gate 			symcount++;
555*0Sstevel@tonic-gate 		}
556*0Sstevel@tonic-gate 		sncov_p++;
557*0Sstevel@tonic-gate 	}
558*0Sstevel@tonic-gate 
559*0Sstevel@tonic-gate 	free(stl_p);
560*0Sstevel@tonic-gate 	DEBUG_LOC("addcovset: bottom");
561*0Sstevel@tonic-gate 	return(symcount);
562*0Sstevel@tonic-gate }
563*0Sstevel@tonic-gate 
564*0Sstevel@tonic-gate 
565*0Sstevel@tonic-gate /*
566*0Sstevel@tonic-gate *	build_stlist: Build a tailored list of symbol table entries.
567*0Sstevel@tonic-gate */
568*0Sstevel@tonic-gate static SEARCH_NODE *
569*0Sstevel@tonic-gate build_stlist(begin_p, end_p, filter_p, count_p)
570*0Sstevel@tonic-gate Elf32_Sym	*begin_p;
571*0Sstevel@tonic-gate Elf32_Sym	*end_p;
572*0Sstevel@tonic-gate int		(*filter_p)();
573*0Sstevel@tonic-gate int		*count_p;
574*0Sstevel@tonic-gate {
575*0Sstevel@tonic-gate 	Elf32_Sym	*tsym_p;
576*0Sstevel@tonic-gate 	SEARCH_NODE	*list_p;
577*0Sstevel@tonic-gate 	int		i, count;
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 	DEBUG_LOC("build_stlist: top");
580*0Sstevel@tonic-gate 	DEBUG_EXP(printf("begin_p = 0x%lx,  end_p = 0x%lx\n", begin_p, end_p));
581*0Sstevel@tonic-gate 
582*0Sstevel@tonic-gate 	count = 0;
583*0Sstevel@tonic-gate 	tsym_p = begin_p;
584*0Sstevel@tonic-gate 	while (stscan(&tsym_p, end_p, filter_p)) {
585*0Sstevel@tonic-gate 		count++;
586*0Sstevel@tonic-gate 	}
587*0Sstevel@tonic-gate 	DEBUG_EXP(printf("count = %d\n",count));
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 	list_p = (SEARCH_NODE *) _Malloc(count, sizeof(*list_p));
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 	i = 0;
592*0Sstevel@tonic-gate 	tsym_p = begin_p;
593*0Sstevel@tonic-gate 	while (stscan(&tsym_p, end_p, filter_p)) {
594*0Sstevel@tonic-gate 		list_p[i].sn_name_p = ST_NAME(tsym_p);
595*0Sstevel@tonic-gate 		list_p[i].sn_value_p = (char *) tsym_p;
596*0Sstevel@tonic-gate 		i++;
597*0Sstevel@tonic-gate 	}
598*0Sstevel@tonic-gate 	DEBUG_EXP(sn_dump("symbol table (pre sort)", list_p, count));
599*0Sstevel@tonic-gate 
600*0Sstevel@tonic-gate 	qsort(list_p, count, sizeof(*list_p), sn_compare);
601*0Sstevel@tonic-gate 
602*0Sstevel@tonic-gate 	DEBUG_EXP(sn_dump("symbol table (post sort)", list_p, count));
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	DEBUG_LOC("build_stlist: bottom");
605*0Sstevel@tonic-gate 	*count_p = count;
606*0Sstevel@tonic-gate 	return(list_p);
607*0Sstevel@tonic-gate }
608*0Sstevel@tonic-gate 
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate /*
611*0Sstevel@tonic-gate *	stscan - symbol table scan
612*0Sstevel@tonic-gate *
613*0Sstevel@tonic-gate *	Scan the symbol table until the given limit is reached or
614*0Sstevel@tonic-gate *	the filter function returns true.  Neither the starting
615*0Sstevel@tonic-gate *	symbol (**sym_pp) nor the limit symbol (*lim_p) are legal
616*0Sstevel@tonic-gate *	return values.  Instead, if the starting pointer is NULL,
617*0Sstevel@tonic-gate *	then the first item in the table is a valid return value.
618*0Sstevel@tonic-gate *	This allows the routine to be used as a generator by
619*0Sstevel@tonic-gate *	starting from where the last call stopped.
620*0Sstevel@tonic-gate */
621*0Sstevel@tonic-gate static int
622*0Sstevel@tonic-gate stscan(sym_pp, lim_p, filter_p)
623*0Sstevel@tonic-gate Elf32_Sym	**sym_pp;
624*0Sstevel@tonic-gate Elf32_Sym	*lim_p;
625*0Sstevel@tonic-gate int		(*filter_p)();
626*0Sstevel@tonic-gate {
627*0Sstevel@tonic-gate 	if (*sym_pp == NULL) {
628*0Sstevel@tonic-gate 		*sym_pp = (Elf32_Sym *) (profPtr->pf_symdat_p->d_buf);
629*0Sstevel@tonic-gate 	} else {
630*0Sstevel@tonic-gate 		*sym_pp = (Elf32_Sym *) ((char *) (*sym_pp) + prstsym_size);
631*0Sstevel@tonic-gate 	}
632*0Sstevel@tonic-gate 
633*0Sstevel@tonic-gate 	while (*sym_pp < lim_p) {
634*0Sstevel@tonic-gate 		if ((*filter_p)(*sym_pp)) {
635*0Sstevel@tonic-gate 			return(1);
636*0Sstevel@tonic-gate 		}
637*0Sstevel@tonic-gate 		*sym_pp = (Elf32_Sym *) ((char *) (*sym_pp) + prstsym_size);
638*0Sstevel@tonic-gate 	}
639*0Sstevel@tonic-gate 	return(0);
640*0Sstevel@tonic-gate }
641*0Sstevel@tonic-gate 
642*0Sstevel@tonic-gate 
643*0Sstevel@tonic-gate /*
644*0Sstevel@tonic-gate *	These routines check the type of a symbol table entry.
645*0Sstevel@tonic-gate */
646*0Sstevel@tonic-gate static int
647*0Sstevel@tonic-gate stchk_focov(sym_p)	/* symbol is function or coverage array  */
648*0Sstevel@tonic-gate Elf32_Sym *sym_p; {
649*0Sstevel@tonic-gate 	return(stchk_func(sym_p) || stchk_cov(sym_p));
650*0Sstevel@tonic-gate }
651*0Sstevel@tonic-gate static int
652*0Sstevel@tonic-gate stchk_filowog(sym_p)	/* symbol is a file, a weak, or a global */
653*0Sstevel@tonic-gate Elf32_Sym *sym_p; {
654*0Sstevel@tonic-gate 	return(
655*0Sstevel@tonic-gate 		stchk_file(sym_p)
656*0Sstevel@tonic-gate 		|| ELF32_ST_BIND(sym_p->st_info) == STB_GLOBAL
657*0Sstevel@tonic-gate 		|| ELF32_ST_BIND(sym_p->st_info) == STB_WEAK
658*0Sstevel@tonic-gate 	);
659*0Sstevel@tonic-gate }
660*0Sstevel@tonic-gate static int
661*0Sstevel@tonic-gate stchk_gowf(sym_p)	/* symbol is global or weak function */
662*0Sstevel@tonic-gate Elf32_Sym *sym_p; {
663*0Sstevel@tonic-gate 	return(
664*0Sstevel@tonic-gate 		(stchk_func(sym_p) || stchk_match(sym_p))
665*0Sstevel@tonic-gate 		&& (
666*0Sstevel@tonic-gate 			ELF32_ST_BIND(sym_p->st_info) == STB_GLOBAL
667*0Sstevel@tonic-gate 			|| ELF32_ST_BIND(sym_p->st_info) == STB_WEAK
668*0Sstevel@tonic-gate 		)
669*0Sstevel@tonic-gate 	);
670*0Sstevel@tonic-gate }
671*0Sstevel@tonic-gate static int
672*0Sstevel@tonic-gate stchk_func(sym_p)	/* symbol is a function */
673*0Sstevel@tonic-gate Elf32_Sym *sym_p; {
674*0Sstevel@tonic-gate 	return(ELF32_ST_TYPE(sym_p->st_info) == STT_FUNC);
675*0Sstevel@tonic-gate }
676*0Sstevel@tonic-gate static int
677*0Sstevel@tonic-gate stchk_file(sym_p)	/* symbol is a file */
678*0Sstevel@tonic-gate Elf32_Sym *sym_p; {
679*0Sstevel@tonic-gate 	return(ELF32_ST_TYPE(sym_p->st_info) == STT_FILE);
680*0Sstevel@tonic-gate }
681*0Sstevel@tonic-gate static int
682*0Sstevel@tonic-gate stchk_cov(sym_p)	/* symbol is a coverage array */
683*0Sstevel@tonic-gate Elf32_Sym *sym_p; {
684*0Sstevel@tonic-gate 	return(
685*0Sstevel@tonic-gate 		strncmp(ST_NAME(sym_p), COV_PREFIX, sizeof(COV_PREFIX)-1) == 0
686*0Sstevel@tonic-gate 	);
687*0Sstevel@tonic-gate }
688*0Sstevel@tonic-gate static int
689*0Sstevel@tonic-gate stchk_match(sym_p)	/* symbol is the match symbol */
690*0Sstevel@tonic-gate Elf32_Sym *sym_p; {
691*0Sstevel@tonic-gate 	return(
692*0Sstevel@tonic-gate 		strncmp(ST_NAME(sym_p), MATCH_STR, sizeof(MATCH_STR)-1) == 0
693*0Sstevel@tonic-gate 	);
694*0Sstevel@tonic-gate }
695*0Sstevel@tonic-gate 
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate /*
698*0Sstevel@tonic-gate *	Initialize debug array (dblist).
699*0Sstevel@tonic-gate *
700*0Sstevel@tonic-gate *	This routine prepares the debug array for searching (see
701*0Sstevel@tonic-gate *	also fillout_sym_dbinfo).
702*0Sstevel@tonic-gate *
703*0Sstevel@tonic-gate *	Initialization proceeds as follows:
704*0Sstevel@tonic-gate *
705*0Sstevel@tonic-gate *		- Count the debug entries that we care about.
706*0Sstevel@tonic-gate *		- _Malloc space to contain the pointers.
707*0Sstevel@tonic-gate *		- Extract pointers and fill in array.
708*0Sstevel@tonic-gate *		- Sort entries alphabetically by name.
709*0Sstevel@tonic-gate */
710*0Sstevel@tonic-gate static void
711*0Sstevel@tonic-gate init_dblist()
712*0Sstevel@tonic-gate {
713*0Sstevel@tonic-gate 	DB_TAG		tag;
714*0Sstevel@tonic-gate 	char		*cur_p;
715*0Sstevel@tonic-gate 	char		*lim_p;
716*0Sstevel@tonic-gate 	Elf_Data	*dat_p;
717*0Sstevel@tonic-gate 	int		k;
718*0Sstevel@tonic-gate 	extern char	*_CAleaf();
719*0Sstevel@tonic-gate 
720*0Sstevel@tonic-gate 	DEBUG_LOC("init_dblist: top");
721*0Sstevel@tonic-gate 
722*0Sstevel@tonic-gate 	dat_p = profPtr->pf_debugdat_p;
723*0Sstevel@tonic-gate 
724*0Sstevel@tonic-gate 	DEBUG_EXP(printf("dat_p = 0x%lx, d_buf = 0x%x, d_size = %d\n",
725*0Sstevel@tonic-gate 		dat_p, dat_p->d_buf, dat_p->d_size
726*0Sstevel@tonic-gate 	));
727*0Sstevel@tonic-gate 
728*0Sstevel@tonic-gate 	lim_p = (char *) (dat_p->d_buf) + dat_p->d_size;
729*0Sstevel@tonic-gate 
730*0Sstevel@tonic-gate 	dblist_cnt = 0;
731*0Sstevel@tonic-gate 	cur_p = NULL;
732*0Sstevel@tonic-gate 	while (dbscan_tag(&cur_p, lim_p, &tag, dbchk_filosub)) {
733*0Sstevel@tonic-gate 		dblist_cnt++;
734*0Sstevel@tonic-gate 	}
735*0Sstevel@tonic-gate 
736*0Sstevel@tonic-gate 	dblist = (SEARCH_NODE *) _Malloc(dblist_cnt, sizeof(*dblist));
737*0Sstevel@tonic-gate 
738*0Sstevel@tonic-gate 	DEBUG_EXP(printf("dblist_cnt = %d\n",dblist_cnt));
739*0Sstevel@tonic-gate 	DEBUG_EXP(printf("dblist = 0x%lx\n", dblist));
740*0Sstevel@tonic-gate 
741*0Sstevel@tonic-gate 	k = 0;
742*0Sstevel@tonic-gate 	cur_p = NULL;
743*0Sstevel@tonic-gate 	while (dbscan_tag(&cur_p, lim_p, &tag, dbchk_filosub)) {
744*0Sstevel@tonic-gate 		dblist[k].sn_name_p =
745*0Sstevel@tonic-gate 			_CAleaf(debName(tag.tg_att_p, tag.tg_attlen));
746*0Sstevel@tonic-gate 		dblist[k].sn_value_p = cur_p;
747*0Sstevel@tonic-gate 		k++;
748*0Sstevel@tonic-gate 	}
749*0Sstevel@tonic-gate 
750*0Sstevel@tonic-gate 	DEBUG_EXP(sn_dump("debug info (pre sort)", dblist, dblist_cnt));
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 	qsort(dblist, dblist_cnt, sizeof(*dblist), sn_compare);
753*0Sstevel@tonic-gate 
754*0Sstevel@tonic-gate 	DEBUG_EXP(sn_dump("debug info (post sort)", dblist, dblist_cnt));
755*0Sstevel@tonic-gate 
756*0Sstevel@tonic-gate 	DEBUG_LOC("init_dblist: bottom");
757*0Sstevel@tonic-gate }
758*0Sstevel@tonic-gate 
759*0Sstevel@tonic-gate 
760*0Sstevel@tonic-gate /*
761*0Sstevel@tonic-gate *	Search for a given tag from the given starting point in
762*0Sstevel@tonic-gate *	the debug information.  If found, fill in the tag at the
763*0Sstevel@tonic-gate *	given pointer and return 1.  Otherwise, return 0.
764*0Sstevel@tonic-gate */
765*0Sstevel@tonic-gate static int
766*0Sstevel@tonic-gate dbscan_tag(dbpos_pp, dblim_p, tag_p, filter_p)
767*0Sstevel@tonic-gate char	**dbpos_pp;
768*0Sstevel@tonic-gate char	*dblim_p;
769*0Sstevel@tonic-gate DB_TAG	*tag_p;
770*0Sstevel@tonic-gate int	(*filter_p)();
771*0Sstevel@tonic-gate {
772*0Sstevel@tonic-gate 	NO_DEBUG_LOC("dbscan_tag: top");
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate 	if (*dbpos_pp == NULL) {
775*0Sstevel@tonic-gate 		*dbpos_pp = profPtr->pf_debugdat_p->d_buf;
776*0Sstevel@tonic-gate 	} else {
777*0Sstevel@tonic-gate 		*dbpos_pp += DB_TAGLEN(*dbpos_pp);
778*0Sstevel@tonic-gate 	}
779*0Sstevel@tonic-gate 
780*0Sstevel@tonic-gate 	while (*dbpos_pp < dblim_p) {
781*0Sstevel@tonic-gate 		dbfill_tag(*dbpos_pp, tag_p);
782*0Sstevel@tonic-gate 
783*0Sstevel@tonic-gate 		if ((*filter_p)(tag_p->tg_value)) {
784*0Sstevel@tonic-gate 			goto success;
785*0Sstevel@tonic-gate 		}
786*0Sstevel@tonic-gate 		*dbpos_pp += tag_p->tg_length;
787*0Sstevel@tonic-gate 	}
788*0Sstevel@tonic-gate 	return(0);
789*0Sstevel@tonic-gate success:;
790*0Sstevel@tonic-gate 	return(1);
791*0Sstevel@tonic-gate }
792*0Sstevel@tonic-gate 
793*0Sstevel@tonic-gate static void
794*0Sstevel@tonic-gate dbfill_tag(dbpos_p, tag_p)
795*0Sstevel@tonic-gate char	*dbpos_p;
796*0Sstevel@tonic-gate DB_TAG	*tag_p;
797*0Sstevel@tonic-gate {
798*0Sstevel@tonic-gate 	tag_p->tg_length = DB_TAGLEN(dbpos_p);
799*0Sstevel@tonic-gate 	tag_p->tg_value = alignval2(dbpos_p + sizeof(LEN4));
800*0Sstevel@tonic-gate 	tag_p->tg_att_p = dbpos_p + sizeof(LEN4) + sizeof(LEN2);
801*0Sstevel@tonic-gate 	tag_p->tg_attlen = tag_p->tg_length - sizeof(LEN4) - sizeof(LEN2);
802*0Sstevel@tonic-gate }
803*0Sstevel@tonic-gate 
804*0Sstevel@tonic-gate 
805*0Sstevel@tonic-gate /*
806*0Sstevel@tonic-gate *	Search the given tag for the given attribute(s).
807*0Sstevel@tonic-gate *	Return a pointer to the attribute or NULL if not found.
808*0Sstevel@tonic-gate */
809*0Sstevel@tonic-gate static char *
810*0Sstevel@tonic-gate dbseek_att(tag_p, filter_p)
811*0Sstevel@tonic-gate DB_TAG	*tag_p;
812*0Sstevel@tonic-gate int	(*filter_p)();
813*0Sstevel@tonic-gate {
814*0Sstevel@tonic-gate 	int	size;
815*0Sstevel@tonic-gate 	char	*att_p;
816*0Sstevel@tonic-gate 
817*0Sstevel@tonic-gate 	NO_DEBUG_LOC("dbseek_att: top");
818*0Sstevel@tonic-gate 
819*0Sstevel@tonic-gate 	size = tag_p->tg_attlen;
820*0Sstevel@tonic-gate 	att_p = tag_p->tg_att_p;
821*0Sstevel@tonic-gate 	NO_DEBUG(printf("attribute size = %d\n",size));
822*0Sstevel@tonic-gate 	while (size > 0) {
823*0Sstevel@tonic-gate 		LEN4 length;
824*0Sstevel@tonic-gate 
825*0Sstevel@tonic-gate 		if ((*filter_p)(alignval2(att_p))) {
826*0Sstevel@tonic-gate 			return(att_p);
827*0Sstevel@tonic-gate 		}
828*0Sstevel@tonic-gate 
829*0Sstevel@tonic-gate 		length = bytesFor(att_p);
830*0Sstevel@tonic-gate 		NO_DEBUG(printf("bytesFor returns length = %d\n",length));
831*0Sstevel@tonic-gate 
832*0Sstevel@tonic-gate 		size  -= sizeof(LEN2) + length;
833*0Sstevel@tonic-gate 		att_p += sizeof(LEN2) + length;
834*0Sstevel@tonic-gate 	}
835*0Sstevel@tonic-gate 	return((char *) 0);
836*0Sstevel@tonic-gate }
837*0Sstevel@tonic-gate 
838*0Sstevel@tonic-gate 
839*0Sstevel@tonic-gate /*
840*0Sstevel@tonic-gate *	dbchk...: Routines that check debug tags and attributes.
841*0Sstevel@tonic-gate */
842*0Sstevel@tonic-gate static int
843*0Sstevel@tonic-gate dbchk_stmnts(value)	/* statement list (line section) */
844*0Sstevel@tonic-gate LEN2 value;
845*0Sstevel@tonic-gate {
846*0Sstevel@tonic-gate 	return(value == AT_stmt_list);
847*0Sstevel@tonic-gate }
848*0Sstevel@tonic-gate static int
849*0Sstevel@tonic-gate dbchk_lowpc(value)	/* statement list (line section) */
850*0Sstevel@tonic-gate LEN2 value;
851*0Sstevel@tonic-gate {
852*0Sstevel@tonic-gate 	return(value == AT_low_pc);
853*0Sstevel@tonic-gate }
854*0Sstevel@tonic-gate static int
855*0Sstevel@tonic-gate dbchk_highpc(value)	/* statement list (line section) */
856*0Sstevel@tonic-gate LEN2 value;
857*0Sstevel@tonic-gate {
858*0Sstevel@tonic-gate 	return(value == AT_high_pc);
859*0Sstevel@tonic-gate }
860*0Sstevel@tonic-gate static int
861*0Sstevel@tonic-gate dbchk_filosub(value)	/* file or subroutine */
862*0Sstevel@tonic-gate LEN2 value;
863*0Sstevel@tonic-gate {
864*0Sstevel@tonic-gate 	switch(value) {
865*0Sstevel@tonic-gate 	case TAG_source_file:
866*0Sstevel@tonic-gate 	case TAG_subroutine:
867*0Sstevel@tonic-gate 	case TAG_global_subroutine:
868*0Sstevel@tonic-gate 	case TAG_inline_subroutine:
869*0Sstevel@tonic-gate 		return(1);
870*0Sstevel@tonic-gate 	default:
871*0Sstevel@tonic-gate 		return(0);
872*0Sstevel@tonic-gate 	}
873*0Sstevel@tonic-gate }
874*0Sstevel@tonic-gate 
875*0Sstevel@tonic-gate 
876*0Sstevel@tonic-gate 
877*0Sstevel@tonic-gate #define PS_BLKFACTOR	(64)	/* handle this many symbols at a time */
878*0Sstevel@tonic-gate 
879*0Sstevel@tonic-gate /*
880*0Sstevel@tonic-gate *	add_profsymbol: Add a new entry to the profsymbol array.
881*0Sstevel@tonic-gate *
882*0Sstevel@tonic-gate *	This routine allocates the space required (as needed) for
883*0Sstevel@tonic-gate *	the PROF_SYMBOL array, extracts the required information
884*0Sstevel@tonic-gate *	from the symbol table and from the debug information, if
885*0Sstevel@tonic-gate *	available (none is recorded for the coverage structures).
886*0Sstevel@tonic-gate *
887*0Sstevel@tonic-gate *	- Check current capacity, assuming one new symbol is to be added.
888*0Sstevel@tonic-gate *	- Copy all of the symbol table information.
889*0Sstevel@tonic-gate *	- Search for the symbol in the debug list.  If this search fails,
890*0Sstevel@tonic-gate *	then flag this failure with "add_profsym_search_fail".  This is used
891*0Sstevel@tonic-gate *	by "addcovset()" for an error exit when a file is not found in the
892*0Sstevel@tonic-gate *	debug information.  This applies only to files - other symbols
893*0Sstevel@tonic-gate *	which are not found may still be valid.
894*0Sstevel@tonic-gate *	- If the symbol is a function, it may be either global or local
895*0Sstevel@tonic-gate *	and local functions are not unique.  Therefore we must compare the
896*0Sstevel@tonic-gate *	address (value) in the symbol table with the address (low_pc)
897*0Sstevel@tonic-gate *	given in the debug information to verify the match.
898*0Sstevel@tonic-gate *	- If the symbol is a file, no verification is needed, but we
899*0Sstevel@tonic-gate *	must change to a new statement list.
900*0Sstevel@tonic-gate *	- If the symbol is a coverage structure, then we are finished with it.
901*0Sstevel@tonic-gate */
902*0Sstevel@tonic-gate static PROF_SYMBOL *
903*0Sstevel@tonic-gate add_profsymbol(prsym_p)
904*0Sstevel@tonic-gate Elf32_Sym *prsym_p;
905*0Sstevel@tonic-gate {
906*0Sstevel@tonic-gate 	DB_TAG		tag;
907*0Sstevel@tonic-gate 	PROF_SYMBOL	*ps_p;
908*0Sstevel@tonic-gate 	char		*att_p;
909*0Sstevel@tonic-gate 	SEARCH_NODE	*sn_p;
910*0Sstevel@tonic-gate 
911*0Sstevel@tonic-gate 	DEBUG_LOC("add_profsymbol: top");
912*0Sstevel@tonic-gate 
913*0Sstevel@tonic-gate 	check_capacity();
914*0Sstevel@tonic-gate 
915*0Sstevel@tonic-gate 	ps_p = prsym_list_p + prsym_cnt - 1;
916*0Sstevel@tonic-gate 	memcpy((char *) &(ps_p->ps_sym), (char *) prsym_p, prstsym_size);
917*0Sstevel@tonic-gate 	memset((char *) &(ps_p->ps_dbg), '\0', sizeof(PROF_DEBUGE));
918*0Sstevel@tonic-gate 
919*0Sstevel@tonic-gate 	DEBUG_EXP(printf("symbol name = %s\n", ST_NAME(prsym_p)));
920*0Sstevel@tonic-gate 	ps_p->ps_dbg.pd_name = ST_NAME(prsym_p);
921*0Sstevel@tonic-gate 
922*0Sstevel@tonic-gate 	add_profsym_search_fail = 0;
923*0Sstevel@tonic-gate 	if (!(sn_p = sn_search(ST_NAME(prsym_p), dblist, dblist_cnt))) {
924*0Sstevel@tonic-gate 		add_profsym_search_fail = 1;
925*0Sstevel@tonic-gate 		goto theend;
926*0Sstevel@tonic-gate 	}
927*0Sstevel@tonic-gate 	DEBUG_EXP(printf("Post search: sn_p->sn_name_p = %s\n",sn_p->sn_name_p));
928*0Sstevel@tonic-gate 	dbfill_tag(sn_p->sn_value_p, &tag);
929*0Sstevel@tonic-gate 
930*0Sstevel@tonic-gate 	if (stchk_func(prsym_p)) {
931*0Sstevel@tonic-gate 		while (strcmp(ST_NAME(prsym_p), sn_p->sn_name_p) == 0) {
932*0Sstevel@tonic-gate 			if (add_function(ps_p, &tag)) {
933*0Sstevel@tonic-gate 				break;
934*0Sstevel@tonic-gate 			}
935*0Sstevel@tonic-gate 			sn_p++;
936*0Sstevel@tonic-gate 			dbfill_tag(sn_p->sn_value_p, &tag);
937*0Sstevel@tonic-gate 		}
938*0Sstevel@tonic-gate 	} else if (stchk_file(prsym_p)) {
939*0Sstevel@tonic-gate 		if (
940*0Sstevel@tonic-gate 			(sn_p + 1) < (dblist + dblist_cnt)
941*0Sstevel@tonic-gate 			&& strcmp(sn_p[0].sn_name_p, sn_p[1].sn_name_p) == 0
942*0Sstevel@tonic-gate 		) {
943*0Sstevel@tonic-gate 			_err_warn(
944*0Sstevel@tonic-gate 				"File name %s was used more than once.",
945*0Sstevel@tonic-gate 				sn_p->sn_name_p
946*0Sstevel@tonic-gate 			);
947*0Sstevel@tonic-gate 		}
948*0Sstevel@tonic-gate 		add_file(&tag);
949*0Sstevel@tonic-gate 	} else {
950*0Sstevel@tonic-gate 		goto theend;
951*0Sstevel@tonic-gate 	}
952*0Sstevel@tonic-gate 
953*0Sstevel@tonic-gate 	ps_p->ps_dbg.pd_symtag = tag.tg_value;
954*0Sstevel@tonic-gate 
955*0Sstevel@tonic-gate theend:;
956*0Sstevel@tonic-gate 	DEBUG_LOC("add_profsymbol: bottom");
957*0Sstevel@tonic-gate 	return(ps_p);
958*0Sstevel@tonic-gate }
959*0Sstevel@tonic-gate 
960*0Sstevel@tonic-gate 
961*0Sstevel@tonic-gate static void
962*0Sstevel@tonic-gate add_file(tag_p)
963*0Sstevel@tonic-gate DB_TAG	*tag_p;
964*0Sstevel@tonic-gate {
965*0Sstevel@tonic-gate 	int		i;
966*0Sstevel@tonic-gate 	char		*tp;
967*0Sstevel@tonic-gate 	PROF_LINE	*lnp;
968*0Sstevel@tonic-gate 	char		*att_p;
969*0Sstevel@tonic-gate 
970*0Sstevel@tonic-gate 	att_p = dbseek_att(tag_p, dbchk_stmnts);
971*0Sstevel@tonic-gate 
972*0Sstevel@tonic-gate 	curf_lp = ((char *) profPtr->pf_linedat_p->d_buf) + DB_STMNTOS(att_p);
973*0Sstevel@tonic-gate 	curf_lncnt = (alignval4(curf_lp) - 2*sizeof(LEN4)) / DBG_LINE_SIZE;
974*0Sstevel@tonic-gate 	curf_base = alignval4(curf_lp + sizeof(LEN4));
975*0Sstevel@tonic-gate 	curf_lp += sizeof(LEN4) + sizeof(LEN4);
976*0Sstevel@tonic-gate 
977*0Sstevel@tonic-gate 	curf_lns_p = (PROF_LINE *) _Malloc(curf_lncnt, sizeof(*curf_lns_p));
978*0Sstevel@tonic-gate 
979*0Sstevel@tonic-gate 	i = 0;
980*0Sstevel@tonic-gate 	tp = curf_lp;
981*0Sstevel@tonic-gate 	lnp = curf_lns_p;
982*0Sstevel@tonic-gate 	while (i++ < curf_lncnt) {
983*0Sstevel@tonic-gate 		*lnp++ = alignval4(tp);
984*0Sstevel@tonic-gate 		tp += DBG_LINE_SIZE;
985*0Sstevel@tonic-gate 	}
986*0Sstevel@tonic-gate 
987*0Sstevel@tonic-gate #ifdef DEBUG
988*0Sstevel@tonic-gate 	printf("File Debug Line Information\n");
989*0Sstevel@tonic-gate 	printf("   DBG_LINE_SIZE = %d\n", DBG_LINE_SIZE);
990*0Sstevel@tonic-gate 	printf("   curf_lp = 0x%x\n", curf_lp);
991*0Sstevel@tonic-gate 	printf("   curf_lncnt = %d\n", curf_lncnt);
992*0Sstevel@tonic-gate 	printf("   curf_base = 0x%x\n", curf_base);
993*0Sstevel@tonic-gate 	printf("   curf_lns_p = 0x%x\n", curf_lns_p);
994*0Sstevel@tonic-gate 	printf("Dump of line numbers\n");
995*0Sstevel@tonic-gate 	for (i = 0, lnp = curf_lns_p; i < curf_lncnt; i++) {
996*0Sstevel@tonic-gate 		printf("   line %d = %d\n", i, lnp[i]);
997*0Sstevel@tonic-gate 	}
998*0Sstevel@tonic-gate #endif
999*0Sstevel@tonic-gate }
1000*0Sstevel@tonic-gate 
1001*0Sstevel@tonic-gate 
1002*0Sstevel@tonic-gate 
1003*0Sstevel@tonic-gate /*
1004*0Sstevel@tonic-gate * add_function -- add to function's PROF_DEBUGE, line# pointer info.
1005*0Sstevel@tonic-gate *
1006*0Sstevel@tonic-gate *	Warning: Because we are reading directly from memory, we
1007*0Sstevel@tonic-gate *	cannot depend upon the form of the structures we are reading
1008*0Sstevel@tonic-gate *	(e.g., pl_delta in PROF_LINE).   Thus, line_p is a "char *"
1009*0Sstevel@tonic-gate *	and NOT a "PROF_LINE *".
1010*0Sstevel@tonic-gate *
1011*0Sstevel@tonic-gate *
1012*0Sstevel@tonic-gate * 	Note from below(***):
1013*0Sstevel@tonic-gate *
1014*0Sstevel@tonic-gate * 	Note that this routine finds the range of .line section
1015*0Sstevel@tonic-gate * 	entries that should be associated with this function, from
1016*0Sstevel@tonic-gate * 	those which belong to this file.
1017*0Sstevel@tonic-gate *
1018*0Sstevel@tonic-gate * 	The FIRST line entry for a fcn is selected because
1019*0Sstevel@tonic-gate * 	it is the first with a ``delta,'' or memory offset
1020*0Sstevel@tonic-gate * 	from the file ``base address (curf_base),''
1021*0Sstevel@tonic-gate * 	whose value is GREATER OR EQUAL to the effective offset
1022*0Sstevel@tonic-gate * 	associated with this function (lo_delta).
1023*0Sstevel@tonic-gate *
1024*0Sstevel@tonic-gate * 	The LAST line entry is selected because it is
1025*0Sstevel@tonic-gate * 	the LAST with a ``delta'' whose value is LESS THAN
1026*0Sstevel@tonic-gate * 	the effective offset of the END of this function (hi_delta)
1027*0Sstevel@tonic-gate * 	- i.e. it is the last line number associated with
1028*0Sstevel@tonic-gate * 	code that is wholly included in this function!
1029*0Sstevel@tonic-gate *
1030*0Sstevel@tonic-gate * 	If no line number is found with a delta value that
1031*0Sstevel@tonic-gate * 	exceeds hi_delta (i.e. is part of the next function),
1032*0Sstevel@tonic-gate * 	then it is assumed that the last line number entry seen
1033*0Sstevel@tonic-gate * 	should simply be accepted as part of this function's set
1034*0Sstevel@tonic-gate * 	of line numbers; it simply has no ``bounding line entry.''
1035*0Sstevel@tonic-gate *
1036*0Sstevel@tonic-gate */
1037*0Sstevel@tonic-gate 
1038*0Sstevel@tonic-gate static int
1039*0Sstevel@tonic-gate add_function(ps_p, tag_p)
1040*0Sstevel@tonic-gate PROF_SYMBOL	*ps_p;
1041*0Sstevel@tonic-gate DB_TAG		*tag_p;
1042*0Sstevel@tonic-gate {
1043*0Sstevel@tonic-gate 	char		*att_p;
1044*0Sstevel@tonic-gate 	LEN4		high_pc, hi_delta;
1045*0Sstevel@tonic-gate 	LEN4		low_pc, lo_delta;
1046*0Sstevel@tonic-gate 	char		*line_p;
1047*0Sstevel@tonic-gate 	int		first_found = 0;
1048*0Sstevel@tonic-gate 	PROF_LINE	*pl_p;
1049*0Sstevel@tonic-gate 	int		i;
1050*0Sstevel@tonic-gate 
1051*0Sstevel@tonic-gate 	DEBUG_LOC("add_function: top");
1052*0Sstevel@tonic-gate 
1053*0Sstevel@tonic-gate 	att_p = dbseek_att(tag_p, dbchk_lowpc);
1054*0Sstevel@tonic-gate 	low_pc = DB_PCVALUE(att_p);
1055*0Sstevel@tonic-gate 	if (ps_p->ps_sym.st_value != low_pc) {
1056*0Sstevel@tonic-gate 		DEBUG_LOC("add_function: returning - failed");
1057*0Sstevel@tonic-gate 		return(0);
1058*0Sstevel@tonic-gate 	}
1059*0Sstevel@tonic-gate 	att_p = dbseek_att(tag_p, dbchk_highpc);
1060*0Sstevel@tonic-gate 	high_pc = DB_PCVALUE(att_p);
1061*0Sstevel@tonic-gate 
1062*0Sstevel@tonic-gate 	hi_delta = high_pc - curf_base;
1063*0Sstevel@tonic-gate 	lo_delta = low_pc - curf_base;
1064*0Sstevel@tonic-gate 	DEBUG_EXP(printf("lo_delta = 0x%x\n", lo_delta));
1065*0Sstevel@tonic-gate 	DEBUG_EXP(printf("hi_delta = 0x%x\n", hi_delta));
1066*0Sstevel@tonic-gate 
1067*0Sstevel@tonic-gate 	line_p = curf_lp;
1068*0Sstevel@tonic-gate 	pl_p = curf_lns_p - 1;
1069*0Sstevel@tonic-gate 
1070*0Sstevel@tonic-gate 	DEBUG_EXP(printf("Building symbol: %s\n",SYMBOL_NAME(ps_p)));
1071*0Sstevel@tonic-gate 	i = 0;
1072*0Sstevel@tonic-gate 	while (i++ < curf_lncnt) {
1073*0Sstevel@tonic-gate 		LEN4	delad;
1074*0Sstevel@tonic-gate 
1075*0Sstevel@tonic-gate 		pl_p++;
1076*0Sstevel@tonic-gate 		delad = alignval4(line_p + sizeof(LEN4) + sizeof(LEN2));
1077*0Sstevel@tonic-gate 
1078*0Sstevel@tonic-gate 		NO_DEBUG(printf("delad = 0x%x\n", delad));
1079*0Sstevel@tonic-gate 		NO_DEBUG(printf("line_p = 0x%x\n", line_p));
1080*0Sstevel@tonic-gate 
1081*0Sstevel@tonic-gate 		if (!first_found && (delad >= lo_delta)) {
1082*0Sstevel@tonic-gate 			DEBUG_LOC("found first line");
1083*0Sstevel@tonic-gate 			first_found = 1;
1084*0Sstevel@tonic-gate 			ps_p->ps_dbg.pd_line_p = pl_p;
1085*0Sstevel@tonic-gate 		} else if (delad >= hi_delta) {
1086*0Sstevel@tonic-gate 			DEBUG_LOC("found last line");
1087*0Sstevel@tonic-gate 			ps_p->ps_dbg.pd_lali_p = pl_p-1;
1088*0Sstevel@tonic-gate 			break;
1089*0Sstevel@tonic-gate 		}
1090*0Sstevel@tonic-gate 
1091*0Sstevel@tonic-gate 		line_p += DBG_LINE_SIZE;
1092*0Sstevel@tonic-gate 	}
1093*0Sstevel@tonic-gate 
1094*0Sstevel@tonic-gate 	/*
1095*0Sstevel@tonic-gate 	*	If the first line is not found, then we have failed
1096*0Sstevel@tonic-gate 	*	and must return zero.  It is possible (e.g., sometimes
1097*0Sstevel@tonic-gate 	*	when the function is the last one in the file) for the
1098*0Sstevel@tonic-gate 	*	first line to be found, but the last not.  In this case,
1099*0Sstevel@tonic-gate 	*	we assume it simply the last possible line.
1100*0Sstevel@tonic-gate 	*/
1101*0Sstevel@tonic-gate 	if (ps_p->ps_dbg.pd_line_p == NULL) {
1102*0Sstevel@tonic-gate 		_err_exit(
1103*0Sstevel@tonic-gate 			"Unable to locate line information for function %s.",
1104*0Sstevel@tonic-gate 			SYMBOL_NAME(ps_p)
1105*0Sstevel@tonic-gate 		);
1106*0Sstevel@tonic-gate 	}
1107*0Sstevel@tonic-gate 	if (ps_p->ps_dbg.pd_lali_p == NULL) {
1108*0Sstevel@tonic-gate 		DEBUG_LOC("found last line (by default)");
1109*0Sstevel@tonic-gate 		ps_p->ps_dbg.pd_lali_p = pl_p;
1110*0Sstevel@tonic-gate 	}
1111*0Sstevel@tonic-gate 	DEBUG_EXP(printf("first line (pd_line_p) = 0x%x\n",ps_p->ps_dbg.pd_line_p));
1112*0Sstevel@tonic-gate 	DEBUG_EXP(printf("last line (pd_lali_p) = 0x%x\n",ps_p->ps_dbg.pd_lali_p));
1113*0Sstevel@tonic-gate 
1114*0Sstevel@tonic-gate 	DEBUG_LOC("add_function: bottom");
1115*0Sstevel@tonic-gate 	return(1);
1116*0Sstevel@tonic-gate }
1117*0Sstevel@tonic-gate 
1118*0Sstevel@tonic-gate 
1119*0Sstevel@tonic-gate /* * * * * *
1120*0Sstevel@tonic-gate  * If capacity will be exceeded with a new symbol, then
1121*0Sstevel@tonic-gate  * increase the capacity.
1122*0Sstevel@tonic-gate  */
1123*0Sstevel@tonic-gate static void
1124*0Sstevel@tonic-gate check_capacity()
1125*0Sstevel@tonic-gate {
1126*0Sstevel@tonic-gate 	if ( ++prsym_cnt > prsym_cap ) {
1127*0Sstevel@tonic-gate 		if ( prsym_cap == 0 ) {
1128*0Sstevel@tonic-gate 			prsym_cap = PS_BLKFACTOR;
1129*0Sstevel@tonic-gate 			prsym_list_p = (PROF_SYMBOL *)
1130*0Sstevel@tonic-gate 				_Malloc( prsym_size, prsym_cap );
1131*0Sstevel@tonic-gate 		} else {
1132*0Sstevel@tonic-gate 			prsym_cap += PS_BLKFACTOR;
1133*0Sstevel@tonic-gate 			prsym_list_p = (PROF_SYMBOL *)
1134*0Sstevel@tonic-gate 				_Realloc( (char *) prsym_list_p,
1135*0Sstevel@tonic-gate 					prsym_size * prsym_cap );
1136*0Sstevel@tonic-gate 		}
1137*0Sstevel@tonic-gate 	}
1138*0Sstevel@tonic-gate }
1139*0Sstevel@tonic-gate 
1140*0Sstevel@tonic-gate 
1141*0Sstevel@tonic-gate 
1142*0Sstevel@tonic-gate /* * * * * *
1143*0Sstevel@tonic-gate  * debName -- return ptr to name value for name attr type:attr value pair.
1144*0Sstevel@tonic-gate  *
1145*0Sstevel@tonic-gate  * this routine is called by fillout_sym_dbinfo, to scan
1146*0Sstevel@tonic-gate  * through a list of debug attributes and return a ptr
1147*0Sstevel@tonic-gate  * to the name attrib value, when that type/value pair is found.
1148*0Sstevel@tonic-gate  */
1149*0Sstevel@tonic-gate 
1150*0Sstevel@tonic-gate static
1151*0Sstevel@tonic-gate char *
1152*0Sstevel@tonic-gate debName( att_p, att_size )
1153*0Sstevel@tonic-gate char	*att_p;		/* ptr to list of (attr_type,attr_value) pairs */
1154*0Sstevel@tonic-gate int	att_size;	/* byte length attribute list */
1155*0Sstevel@tonic-gate {
1156*0Sstevel@tonic-gate 	char *name_p = "";
1157*0Sstevel@tonic-gate 	/* * * * * *
1158*0Sstevel@tonic-gate 	 * loop through the entries.  when you find a name,
1159*0Sstevel@tonic-gate 	 * return the addr of the related data (a char string).
1160*0Sstevel@tonic-gate 	 */
1161*0Sstevel@tonic-gate 
1162*0Sstevel@tonic-gate 	NO_DEBUG_LOC("debName: top");
1163*0Sstevel@tonic-gate 	while ( att_size>0 ) {
1164*0Sstevel@tonic-gate 		LEN2 typea_one;
1165*0Sstevel@tonic-gate 		LEN4 lena_one;
1166*0Sstevel@tonic-gate 
1167*0Sstevel@tonic-gate 		NO_DEBUG(printf("att_size = %d\n",att_size));
1168*0Sstevel@tonic-gate 		typea_one = alignval2(att_p) ;
1169*0Sstevel@tonic-gate 		NO_DEBUG(printf("typea_one = 0x%x\n",typea_one));
1170*0Sstevel@tonic-gate 		lena_one  =  bytesFor(att_p) ;
1171*0Sstevel@tonic-gate 		NO_DEBUG(printf("lena_one = %d\n",lena_one));
1172*0Sstevel@tonic-gate 		NO_DEBUG(printf("att_p = 0x%x\n",att_p));
1173*0Sstevel@tonic-gate 
1174*0Sstevel@tonic-gate 		if( typea_one == AT_name ) {
1175*0Sstevel@tonic-gate 			name_p = att_p + sizeof(LEN2);
1176*0Sstevel@tonic-gate 			break;
1177*0Sstevel@tonic-gate 		}
1178*0Sstevel@tonic-gate 		att_size -= sizeof(LEN2) + lena_one;
1179*0Sstevel@tonic-gate 		att_p    += sizeof(LEN2) + lena_one;
1180*0Sstevel@tonic-gate 	}
1181*0Sstevel@tonic-gate 	NO_DEBUG(printf("name = %s\n",name_p));
1182*0Sstevel@tonic-gate 	NO_DEBUG_LOC("debName: bottom");
1183*0Sstevel@tonic-gate 	return( name_p );
1184*0Sstevel@tonic-gate }
1185*0Sstevel@tonic-gate 
1186*0Sstevel@tonic-gate 
1187*0Sstevel@tonic-gate /* * * * * *
1188*0Sstevel@tonic-gate  * bytesFor - indicate the number of bytes of attribute data
1189*0Sstevel@tonic-gate  * 		expected to be defined for an attribute type,
1190*0Sstevel@tonic-gate  * 		given a ptr to the attribute type:value pair.
1191*0Sstevel@tonic-gate  *
1192*0Sstevel@tonic-gate  * we don't particularly care about the specific attribute;
1193*0Sstevel@tonic-gate  * more, we are interested in the 'form' of the value
1194*0Sstevel@tonic-gate  * associated with this attribute type; hence the 'bit un-masking'.
1195*0Sstevel@tonic-gate  *
1196*0Sstevel@tonic-gate  * used by fillout1().
1197*0Sstevel@tonic-gate  */
1198*0Sstevel@tonic-gate static LEN4
1199*0Sstevel@tonic-gate bytesFor(attr_p)
1200*0Sstevel@tonic-gate char	*attr_p;
1201*0Sstevel@tonic-gate {
1202*0Sstevel@tonic-gate 	LEN4 len;
1203*0Sstevel@tonic-gate 	LEN2 form, type;
1204*0Sstevel@tonic-gate 	char *data_p = attr_p + sizeof(LEN2);	/* beginning of attr data */
1205*0Sstevel@tonic-gate 
1206*0Sstevel@tonic-gate 
1207*0Sstevel@tonic-gate 	NO_DEBUG_LOC("bytesFor: top");
1208*0Sstevel@tonic-gate 
1209*0Sstevel@tonic-gate 	type = alignval2(attr_p);
1210*0Sstevel@tonic-gate 	form = type & FORM_MASK ;
1211*0Sstevel@tonic-gate 	NO_DEBUG(printf("attribute: type = 0x%x",type));
1212*0Sstevel@tonic-gate 	NO_DEBUG(printf(", form = 0x%x\n",form));
1213*0Sstevel@tonic-gate 	switch( form )
1214*0Sstevel@tonic-gate 	{
1215*0Sstevel@tonic-gate 	case FORM_STRING:	/* NUL-terminated string */
1216*0Sstevel@tonic-gate 	/* * * * * *
1217*0Sstevel@tonic-gate 	 * len of string is #chars plus one for NULL.
1218*0Sstevel@tonic-gate 	 */
1219*0Sstevel@tonic-gate 		len = strlen(data_p) + 1;
1220*0Sstevel@tonic-gate 		break;
1221*0Sstevel@tonic-gate 
1222*0Sstevel@tonic-gate 	case FORM_DATA2:	/* 2 bytes */
1223*0Sstevel@tonic-gate 		len = 2;
1224*0Sstevel@tonic-gate 		break;
1225*0Sstevel@tonic-gate 
1226*0Sstevel@tonic-gate 	case FORM_ADDR:		/* relocated address */
1227*0Sstevel@tonic-gate 	case FORM_REF:		/* reference to another .debug entry */
1228*0Sstevel@tonic-gate 	case FORM_DATA4:	/* 4 bytes */
1229*0Sstevel@tonic-gate 		len = 4;
1230*0Sstevel@tonic-gate 		break;
1231*0Sstevel@tonic-gate 
1232*0Sstevel@tonic-gate 	case FORM_DATA8:	/* 8 bytes (two 4-byte values) */
1233*0Sstevel@tonic-gate 		len = 8;
1234*0Sstevel@tonic-gate 		break;
1235*0Sstevel@tonic-gate 
1236*0Sstevel@tonic-gate 	case FORM_BLOCK2:	/* block with 2-byte length, then data */
1237*0Sstevel@tonic-gate 		len = alignval2(data_p) + 2 ; /* + 2 -> len of length */
1238*0Sstevel@tonic-gate 		break;
1239*0Sstevel@tonic-gate 
1240*0Sstevel@tonic-gate 	case FORM_BLOCK4:	/* block with 4-byte length, then data */
1241*0Sstevel@tonic-gate 		len = alignval4(data_p) + 4 ; /* + 4 -> len of length */
1242*0Sstevel@tonic-gate 		break;
1243*0Sstevel@tonic-gate 
1244*0Sstevel@tonic-gate 	case FORM_NONE:		/* error */
1245*0Sstevel@tonic-gate 	default:
1246*0Sstevel@tonic-gate 		len = 0;
1247*0Sstevel@tonic-gate 		break;
1248*0Sstevel@tonic-gate 	}
1249*0Sstevel@tonic-gate 
1250*0Sstevel@tonic-gate 	if (len==0)
1251*0Sstevel@tonic-gate 		_err_exit("Invalid FORM_value %#x for attribute type %#x\n",
1252*0Sstevel@tonic-gate 			form , type);
1253*0Sstevel@tonic-gate 
1254*0Sstevel@tonic-gate 	NO_DEBUG_LOC("bytesFor: bottom");
1255*0Sstevel@tonic-gate 	return(len);
1256*0Sstevel@tonic-gate }
1257*0Sstevel@tonic-gate 
1258*0Sstevel@tonic-gate 
1259*0Sstevel@tonic-gate /*
1260*0Sstevel@tonic-gate *	sn_search: Search sorted list of SEARCH_NODE for given name.
1261*0Sstevel@tonic-gate *
1262*0Sstevel@tonic-gate *	Search the list for the entry with the given name.  If there
1263*0Sstevel@tonic-gate *	is no such entry, return 0.  Otherwise return a pointer to
1264*0Sstevel@tonic-gate *	the *first* entry in the list that matches.
1265*0Sstevel@tonic-gate */
1266*0Sstevel@tonic-gate static SEARCH_NODE *
1267*0Sstevel@tonic-gate sn_search(name_p, list_p, count)
1268*0Sstevel@tonic-gate char		*name_p;
1269*0Sstevel@tonic-gate SEARCH_NODE	*list_p;
1270*0Sstevel@tonic-gate int		count;
1271*0Sstevel@tonic-gate {
1272*0Sstevel@tonic-gate 	SEARCH_NODE	tnode;
1273*0Sstevel@tonic-gate 	SEARCH_NODE	*sn_p;
1274*0Sstevel@tonic-gate 	int		index;
1275*0Sstevel@tonic-gate 
1276*0Sstevel@tonic-gate 	tnode.sn_name_p = name_p;
1277*0Sstevel@tonic-gate 
1278*0Sstevel@tonic-gate 	sn_p = (SEARCH_NODE *) bsearch(
1279*0Sstevel@tonic-gate 		(char *) &tnode,
1280*0Sstevel@tonic-gate 		(char *) list_p,
1281*0Sstevel@tonic-gate 		count,
1282*0Sstevel@tonic-gate 		sizeof(*list_p),
1283*0Sstevel@tonic-gate 		sn_compare
1284*0Sstevel@tonic-gate 	);
1285*0Sstevel@tonic-gate 
1286*0Sstevel@tonic-gate 	if (sn_p == NULL) {
1287*0Sstevel@tonic-gate 		return(NULL);
1288*0Sstevel@tonic-gate 	}
1289*0Sstevel@tonic-gate 
1290*0Sstevel@tonic-gate 	index = sn_p - list_p;
1291*0Sstevel@tonic-gate 	while ((index > 0) && (sn_compare(&list_p[index-1], &tnode) == 0))
1292*0Sstevel@tonic-gate 		index--;
1293*0Sstevel@tonic-gate 
1294*0Sstevel@tonic-gate 	return(&list_p[index]);
1295*0Sstevel@tonic-gate }
1296*0Sstevel@tonic-gate 
1297*0Sstevel@tonic-gate static int
1298*0Sstevel@tonic-gate sn_compare(a_p, b_p)
1299*0Sstevel@tonic-gate SEARCH_NODE *a_p;
1300*0Sstevel@tonic-gate SEARCH_NODE *b_p;
1301*0Sstevel@tonic-gate {
1302*0Sstevel@tonic-gate 	return(strcmp(a_p->sn_name_p, b_p->sn_name_p));
1303*0Sstevel@tonic-gate }
1304*0Sstevel@tonic-gate 
1305*0Sstevel@tonic-gate #ifdef DEBUG
1306*0Sstevel@tonic-gate static void
1307*0Sstevel@tonic-gate sn_dump(title_p, snlist_p, sncount)
1308*0Sstevel@tonic-gate char		*title_p;
1309*0Sstevel@tonic-gate SEARCH_NODE	*snlist_p;
1310*0Sstevel@tonic-gate int		sncount;
1311*0Sstevel@tonic-gate {
1312*0Sstevel@tonic-gate 	int i;
1313*0Sstevel@tonic-gate 
1314*0Sstevel@tonic-gate 	printf("search list for %s: count = %d\n", title_p, sncount);
1315*0Sstevel@tonic-gate 	for (i = 0; i < sncount; i++) {
1316*0Sstevel@tonic-gate 		printf(
1317*0Sstevel@tonic-gate 			"   name = %s,	pointer = 0x%lx\n"
1318*0Sstevel@tonic-gate 			, snlist_p[i].sn_name_p
1319*0Sstevel@tonic-gate 			, snlist_p[i].sn_value_p
1320*0Sstevel@tonic-gate 		);
1321*0Sstevel@tonic-gate 	}
1322*0Sstevel@tonic-gate }
1323*0Sstevel@tonic-gate 
1324*0Sstevel@tonic-gate static void
1325*0Sstevel@tonic-gate profsym_dump(list_p, count)
1326*0Sstevel@tonic-gate PROF_SYMBOL	*list_p;
1327*0Sstevel@tonic-gate int		count;
1328*0Sstevel@tonic-gate {
1329*0Sstevel@tonic-gate 	int		i;
1330*0Sstevel@tonic-gate 	PROF_LINE	*p;
1331*0Sstevel@tonic-gate 
1332*0Sstevel@tonic-gate 	printf("Dump of %d prof symbols found.\n", count);
1333*0Sstevel@tonic-gate 	for (i = 0; i < count; i++, list_p++) {
1334*0Sstevel@tonic-gate 		printf("%d: location 0x%x\n", i, list_p);
1335*0Sstevel@tonic-gate 		printf("\tSymbol %s\n", ST_NAME(&(list_p->ps_sym)));
1336*0Sstevel@tonic-gate 		printf("\t   st_size = %d\n", list_p->ps_sym.st_size);
1337*0Sstevel@tonic-gate 		printf("\t   st_info = 0x%lx\n", list_p->ps_sym.st_info);
1338*0Sstevel@tonic-gate 		printf("\tDebug Information\n");
1339*0Sstevel@tonic-gate 		printf("\t   pd_name = %s\n", list_p->ps_dbg.pd_name);
1340*0Sstevel@tonic-gate 		printf("\t   pd_symtag = 0x%lx\n", list_p->ps_dbg.pd_symtag);
1341*0Sstevel@tonic-gate 		p = list_p->ps_dbg.pd_line_p;
1342*0Sstevel@tonic-gate 		printf("\t   *pd_line_p = %d\n", (p ? *p : 0));
1343*0Sstevel@tonic-gate 		p = list_p->ps_dbg.pd_lali_p;
1344*0Sstevel@tonic-gate 		printf("\t   *pd_lali_p = %d\n", (p ? *p : 0));
1345*0Sstevel@tonic-gate 		printf("\t   pd_file_p = 0x%lx\n", list_p->ps_dbg.pd_file_p);
1346*0Sstevel@tonic-gate 	}
1347*0Sstevel@tonic-gate }
1348*0Sstevel@tonic-gate #endif
1349*0Sstevel@tonic-gate 
1350*0Sstevel@tonic-gate 
1351*0Sstevel@tonic-gate /*
1352*0Sstevel@tonic-gate *	alignment routines
1353*0Sstevel@tonic-gate *
1354*0Sstevel@tonic-gate *	These routines are used to avoid the EMT trap that occurs
1355*0Sstevel@tonic-gate *	when moving a unit of data (of 2 or more bytes) across a
1356*0Sstevel@tonic-gate *	word boundry.
1357*0Sstevel@tonic-gate */
1358*0Sstevel@tonic-gate static LEN2
1359*0Sstevel@tonic-gate alignval2(p)
1360*0Sstevel@tonic-gate char *p;
1361*0Sstevel@tonic-gate {
1362*0Sstevel@tonic-gate 	LEN2 tmp; char *tp = (char *) &tmp;
1363*0Sstevel@tonic-gate 
1364*0Sstevel@tonic-gate 	tp[0] = p[0]; tp[1] = p[1];
1365*0Sstevel@tonic-gate 	return(tmp);
1366*0Sstevel@tonic-gate }
1367*0Sstevel@tonic-gate 
1368*0Sstevel@tonic-gate static LEN4
1369*0Sstevel@tonic-gate alignval4(p)
1370*0Sstevel@tonic-gate char *p;
1371*0Sstevel@tonic-gate {
1372*0Sstevel@tonic-gate 	LEN4 tmp; char *tp = (char *) &tmp;
1373*0Sstevel@tonic-gate 
1374*0Sstevel@tonic-gate 	tp[0] = p[0]; tp[1] = p[1]; tp[2] = p[2]; tp[3] = p[3];
1375*0Sstevel@tonic-gate 	return(tmp);
1376*0Sstevel@tonic-gate }
1377*0Sstevel@tonic-gate 
1378*0Sstevel@tonic-gate /*
1379*0Sstevel@tonic-gate *	Disscussion of the argv[0] problem and solution.
1380*0Sstevel@tonic-gate *
1381*0Sstevel@tonic-gate *	If a process is run with a misleading first argument (argv[0]),
1382*0Sstevel@tonic-gate *	the profiler will be confused when trying to read the file and
1383*0Sstevel@tonic-gate *	match the information against that in memory.  As a confidence
1384*0Sstevel@tonic-gate *	check, we compare the address of MATCH_STR as seen in the symbol
1385*0Sstevel@tonic-gate *	table to the address of MATCH_STR as seen while running the code.
1386*0Sstevel@tonic-gate *	If these are the same, it is *very* unlikely that the file
1387*0Sstevel@tonic-gate *	does not correspond to the code in memory.
1388*0Sstevel@tonic-gate *
1389*0Sstevel@tonic-gate *	Because this code may be run from a shared object, we must
1390*0Sstevel@tonic-gate *	insure that our reference to MATCH_STR is that of the main routine.
1391*0Sstevel@tonic-gate *	We are depending on MATCH_NAME to not be defined by any shared object
1392*0Sstevel@tonic-gate *	(including this one - libprof.so - when so built).
1393*0Sstevel@tonic-gate *
1394*0Sstevel@tonic-gate *	The search for MATCH_STR in the symbol table is done in _symintLoad
1395*0Sstevel@tonic-gate *	because SymintLoad has an ordered version of selected entries from the
1396*0Sstevel@tonic-gate *	symbol table which makes searching very efficient (O(log n)).
1397*0Sstevel@tonic-gate *
1398*0Sstevel@tonic-gate *	See also soqueue.c.
1399*0Sstevel@tonic-gate */
1400*0Sstevel@tonic-gate 
1401*0Sstevel@tonic-gate int	_prof_check_match;
1402*0Sstevel@tonic-gate 
1403*0Sstevel@tonic-gate static void
1404*0Sstevel@tonic-gate verify_match()
1405*0Sstevel@tonic-gate {
1406*0Sstevel@tonic-gate 	SEARCH_NODE	*sn_p;
1407*0Sstevel@tonic-gate 	Elf32_Sym	*sym_p;
1408*0Sstevel@tonic-gate 	extern char	MATCH_NAME;
1409*0Sstevel@tonic-gate 
1410*0Sstevel@tonic-gate 	if (_prof_check_match) {
1411*0Sstevel@tonic-gate 		if (!(sn_p = sn_search(MATCH_STR, gstlist, gstlist_cnt))) {
1412*0Sstevel@tonic-gate 			_err_exit("Cannot find match name.");
1413*0Sstevel@tonic-gate 		}
1414*0Sstevel@tonic-gate 		sym_p = (Elf32_Sym *) sn_p->sn_value_p;
1415*0Sstevel@tonic-gate 		if (sym_p->st_value != (Elf32_Addr) &MATCH_NAME) {
1416*0Sstevel@tonic-gate 			_err_exit("Location of file for this process unknown.");
1417*0Sstevel@tonic-gate 		}
1418*0Sstevel@tonic-gate 	}
1419*0Sstevel@tonic-gate }
1420*0Sstevel@tonic-gate #endif
1421*0Sstevel@tonic-gate 
1422