1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*
33  *	File: symintLoad.c
34  *	Date: 12/15/88
35  *
36  *	This file provides code to build the profiling symbol array
37  *	(array of PROF_SYMBOL).  This array contains all of the
38  *	symbol table information plus selected debug information for
39  *	each file and each function that has a coverage array.
40  *
41  *	The symbol table contains entries for every file, every
42  *	function, and every coverage array.  The debug information
43  *	has corresponding entries except that there are no entries
44  *	for the coverage arrays.  (This may change later.)
45  *
46  *	The algorithm for building the profiling symbol array
47  *	consists of scanning the symbol table for file, function,
48  *	and coverage array entries and building an entry for each.
49  *	The construction of an entry is constrained by the
50  *	following factors:
51  *
52  *		- An entry is built for every file.
53  *
54  *		- An entry is built for a function only if there
55  *		is a corresponding coverage array for the function.
56  *
57  *		- Entries must be ordered in the sense that each
58  *		non-file entry points to its owner file and each
59  *		file entry points to the next file (or null).
60  *
61  *		- The assembler specification (see C Issue 5 3B2
62  *		Assembler System Test Specification by Howe, p. 28)
63  *		states that all local symbols follow their file
64  *		symbol in the symbol table.  This allows us to relate
65  *		a function and its coverage array to the file that
66  *		contains it.
67  *
68  *		- For each symbol included in the profiling symbol
69  *		array, all corresponding symbol table information must
70  *		be present together with selected debug information.
71  *		Therefore, the correspondence between a symbol table
72  *		entry and a debug entry must be established.
73  *
74  *		- Although duplicate (static) function names may appear,
75  *		the names are unique within a given file.  Also, the
76  *		value (address) of each function is included in both
77  *		the symbol table information and the debug information.
78  *		This provides a verifable correspondence between these
79  *		information sets.
80  *
81  */
82 
83 #include "string.h"
84 #include "symint.h"
85 #include "debug.h"
86 
87 static PROF_FILE	*profPtr;
88 
89 /* LINTED: set but not used */
90 static int	prstsym_size;	/* size of a symbol table symbol */
91 
92 static PROF_SYMBOL	*prsym_list_p = 0;	/* the list to return. */
93 
94 /*
95  * _symintLoad(proffilePtr)
96  * proffilePtr	- PROF_FILE pointer returned by _symintOpen().
97  *
98  * returns PROF_SYMBOL * - pointer to the malloc-ed array of
99  *			   symbol information entries, or
100  *			   NULL if fails.
101  *
102  *
103  * This routine builds the interface data structure from the data
104  * already loaded during _symintOpen().
105  *
106  * Prof:
107  *
108  * 	1. Allocate a duplicate copy of the symbol table
109  *	   data.  (For Prof, a PROF_SYMBOL is just
110  *	   a structure containing an Elf32_Sym!)
111  *
112  * 	2. Set internal parameters to reflect this.
113  *
114  *
115  * Problems are dealt with by issuing an _err_exit().
116  *
117  */
118 PROF_SYMBOL *
_symintLoad(PROF_FILE * proffilePtr)119 _symintLoad(PROF_FILE *proffilePtr)
120 {
121 	Elf_Data	*symdat_pri_p;
122 	Elf_Data	*symdat_aux_p;
123 	PROF_SYMBOL	*symlist;
124 
125 	DEBUG_LOC("_symintLoad: top");
126 
127 	profPtr = proffilePtr;
128 
129 	/*
130 	 * sanity checks.
131 	 */
132 	DEBUG_EXP(printf("profPtr = %x\n", profPtr));
133 	DEBUG_EXP(printf("profPtr->pf_symdat_p = %x\n",
134 	    profPtr->pf_symdat_pri_p));
135 	DEBUG_EXP(printf("profPtr->pf_nstsyms = %x\n", profPtr->pf_nstsyms));
136 
137 	assert(profPtr != 0);
138 	assert(profPtr->pf_symdat_pri_p != 0);
139 	assert(profPtr->pf_nstsyms != 0);
140 
141 	symdat_pri_p = profPtr->pf_symdat_pri_p;
142 	symdat_aux_p = profPtr->pf_symdat_aux_p;
143 	DEBUG_EXP(printf("symdat_pri_p->d_size = %x\n", symdat_pri_p->d_size));
144 
145 	prstsym_size = (symdat_pri_p->d_size / profPtr->pf_nstsyms);
146 	DEBUG_EXP(printf("_symintLoad: prstsym_size = %d\n",
147 	    prstsym_size));
148 
149 	/*
150 	 * alloc a new copy of the array, and
151 	 *  do a bit-wise copy since the structures
152 	 *  ARE THE SAME SIZE & (effectively) HAVE THE SAME FIELDS!
153 	 *  Set the descriptive `parameters' accordingly.
154 	 *
155 	 * If there is an auxiliary symbol table (.SUNW_ldynsym) augmenting
156 	 * the dynamic symbol table (.dynsym), then we copy both tables
157 	 * into our copy, with the auxiliary coming first.
158 	 *
159 	 * (We'll take a copy, to simplify the 'Drop' logic.)
160 	 */
161 
162 	{
163 	size_t st_size;	/* size of symbol table data */
164 
165 	st_size = symdat_pri_p->d_size;
166 	if (profPtr->pf_nstsyms_aux != 0)
167 		st_size += symdat_aux_p->d_size;
168 
169 	NO_DEBUG_LOC("_symintLoad: before malloc for symbol list (PROF)");
170 	prsym_list_p = symlist = (PROF_SYMBOL *)_Malloc(st_size, 1);
171 	NO_DEBUG_LOC("_symintLoad: after malloc for symbol list (PROF)");
172 
173 	if (profPtr->pf_nstsyms_aux > 0) {
174 		NO_DEBUG_LOC("_symintLoad: before memcpy for "
175 		    "auxiliary symbol list (PROF)");
176 		(void) memcpy(symlist, symdat_aux_p->d_buf,
177 		    symdat_aux_p->d_size);
178 		symlist += profPtr->pf_nstsyms_aux;
179 	}
180 
181 	NO_DEBUG_LOC("_symintLoad: before memcpy for symbol list (PROF)");
182 	(void) memcpy(symlist, symdat_pri_p->d_buf, symdat_pri_p->d_size);
183 
184 	profPtr->pf_nsyms = profPtr->pf_nstsyms;
185 	}
186 
187 	DEBUG_LOC("_symintLoad: bottom");
188 	return (prsym_list_p);
189 }
190