xref: /titanic_41/usr/src/cmd/sgs/prof/common/symintOpen.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1988 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include "symint.h"
29 
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include "debug.h"
33 
34 /* * * * * *
35  * symintFcns.c -- symbol information interface routines.
36  *
37  * these routines form a symbol information access
38  * interface, for the profilers to get at object file
39  * information.  this interface was designed to aid
40  * in the COFF to ELF conversion of prof, lprof and friends.
41  *
42  */
43 
44 
45 /* * * * * *
46  * _symintOpen(aout_name)
47  * aout_name 	- char string file name of object file
48  * 		  to open.
49  *
50  * returns PROF_FILE * - pointer to the PROF_FILE structure built,
51  * 			 or NULL if fails.
52  */
53 
54 /* * * * * *
55  *
56  * .H 3 "Executable File Open and Close"
57  *
58  * Under COFF, the routine ldopen, given a file name, returns a pointer to a
59  * structure called an LDFILE.  This descriptor is then passed to each of
60  * the library routines (such as read header, read symbol table entry, etc)
61  * to access the information contained in the file.  These calls are spread
62  * throughout the profiling code.
63  *
64  * Under ELF, the file must be opened using a system open call.  The file
65  * descriptor is then passed to a routine which returns a pointer to an
66  * Elf structure.  This pointer is then passed along to another routine which
67  * returns a different pointer which is in turn passed along to another
68  * routine.  In an attempt to avoid disturbing the current format of the
69  * code (by having to pass around different types of pointers), we plan to
70  * build a PROF_FILE descriptor which will then be passed around in the
71  * same way as the pointer to LDFILE.
72  *
73  * Thus, for ELF, an open will consist of opening the file and extracting
74  * enough from it to fill in the PROF_FILE structure.  The code for the
75  * open is as follows; the code for building the symbol table (extracting
76  * information from the sections to fill an array of PROF_SYMBOLS) has
77  * yet to be written.
78  *
79  */
80 
81 
82 /* * * * * *
83  * #defines and globals.
84  */
85 
86 #define	SCN_NAME_DEBUG	".debug"	/* debug information section */
87 #define	SCN_NAME_LINE	".line"		/* line number section */
88 #define	SCN_NAME_SYM	".symtab"	/* symbol table entry section */
89 #define	SCN_NAME_SST	".strtab"	/* symbol table string table */
90 
91 
92 static char
93 	*fail_open_s =	"Unable to open file",
94 	*fail_begin_s =	"Unable to read (begin) file",
95 	*fail_ehdr_s =	"Unable to get elf header in",
96 	*fail_sec_s =	"Unable to get section",
97 	*fail_shd_s =	"Unable to get header for section",
98 	*fail_dat_s =	"Unable to get data for section",
99 	*fail_sym_s =	"Cannot find symbol table section in",
100 	*fail_line_s =	"Cannot find line number section in",
101 	*fail_debug_s =	"Cannot find debug section in",
102 	*fail_pfsym_s =	"Unable to process symbols in",
103 	*fail_buf_s =	"Data buffer is null for section"
104 	;
105 
106 /* * * * * *
107  * this routine loads the symbols into the PROF_SYMBOL
108  * array.
109  */
110 extern  PROF_SYMBOL *	_symintLoad();	/* NULL or ptr */
111 
112 
113 /* * * * * *
114  * this points at the name of the executable.
115  */
116 static  char *executableName;
117 
118 
119 
120 
121 
122 /* * * * * *
123  * section_data_p() - return ptr to section data,
124  * 	given section ptr and name of section.
125  */
126 
127 static
128 Elf_Data *
129 section_data_p(sec_p, str)
130 
131 Elf_Scn *sec_p;
132 char	*str;
133 {
134 	Elf_Data *dat_p;
135 
136 	if ((dat_p = elf_getdata(sec_p, NULL)) == NULL)
137 		_err_exit("%s %s in %s.", fail_dat_s, str, executableName);
138 	return(dat_p);
139 }
140 
141 
142 
143 
144 
145 
146 PROF_FILE *
147 _symintOpen(aout_name)
148 
149 char	*aout_name; {
150 
151 
152 /*
153 *	Elf file open operation
154 *
155 * 	- point at executable's name, globally
156 *	- open file
157 *	- align to current version
158 *	- read the elf descriptor and header
159 *	- read header-names section descriptor, header, and data
160 *	- allocate space for all the section hdrs (pf_shdarr_p).
161 *	- set a pointer to the header-names buffer
162 *	- search the section headers for
163 *		- debug section header and data
164 *		- line section header and data
165 *		- symbol table header, data, strings, and number of symbols
166 *	  and copy each section hdr into our array.
167 * 	- populate the PROF_SYMBOL array and anchor it in (pf_symarr_p).
168 */
169 
170 	PROF_FILE	*pfile_p;	/* PROF_FILE ptr to return. */
171 
172 	Elf		*telf_p;
173 	Elf_Scn		*tscn_p;
174 	Elf32_Shdr	*tshd_p;
175 	int		k;
176 
177 	executableName = aout_name;
178 
179 	DEBUG_LOC("_symintOpen: top");
180 	if(aout_name==NULL){
181 		_err_exit("name of executable is null\n");
182 	}
183 	DEBUG_EXP(printf("Attempting to open %s\n", aout_name));
184 	pfile_p = (PROF_FILE *) _Malloc( sizeof(PROF_FILE), 1);
185 
186 	if ((pfile_p->pf_fildes = open(aout_name, O_RDONLY)) == -1)
187 		_err_exit("%s %s.", fail_open_s, aout_name);
188 	if ((elf_version(EV_CURRENT)) == EV_NONE)
189 		_err_exit("Elf library out of date");
190 	if (
191 		(pfile_p->pf_elf_p
192 			= elf_begin(
193 				pfile_p->pf_fildes,
194 				ELF_C_READ,
195 				(Elf *) 0
196 			)
197 		) == NULL
198 	)
199 		_err_exit("%s %s.", fail_begin_s, aout_name);
200 
201 	DEBUG_EXP(printf("elfkind = %d\n", elf_kind(pfile_p->pf_elf_p)));
202 	if ((pfile_p->pf_elfhd_p = elf32_getehdr(pfile_p->pf_elf_p)) == NULL)
203 		_err_exit("%s %s.", fail_ehdr_s, aout_name);
204 
205 	DEBUG_LOC("_symintOpen: after call to getehdr");
206 	telf_p = pfile_p->pf_elf_p;
207 
208 	tscn_p = elf_getscn(telf_p, k = pfile_p->pf_elfhd_p->e_shstrndx);
209 	if (tscn_p == NULL)
210 		_err_exit("%s %d in %s.", fail_sec_s, k, aout_name);
211 
212 	if ((pfile_p->pf_snmshd_p = elf32_getshdr(tscn_p)) == NULL)
213 		_err_exit("%s %s in %s.", fail_shd_s, "header names", aout_name);
214 	if ((pfile_p->pf_snmdat_p = elf_getdata(tscn_p, NULL)) == NULL)
215 		_err_exit("%s %s in %s.", fail_dat_s, "header names", aout_name);
216 
217 	DEBUG_EXP(printf("Address of data header = 0x%lx\n",pfile_p->pf_snmdat_p));
218 	DEBUG_EXP(printf("d_buf     = 0x%lx\n",pfile_p->pf_snmdat_p->d_buf));
219 	DEBUG_EXP(printf("d_type    = %d\n",pfile_p->pf_snmdat_p->d_type));
220 	DEBUG_EXP(printf("d_size    = %d\n",pfile_p->pf_snmdat_p->d_size));
221 	DEBUG_EXP(printf("d_off     = %d\n",pfile_p->pf_snmdat_p->d_off));
222 	DEBUG_EXP(printf("d_align   = %d\n",pfile_p->pf_snmdat_p->d_align));
223 	DEBUG_EXP(printf("d_version = %d\n",pfile_p->pf_snmdat_p->d_version));
224 
225 	if (pfile_p->pf_snmdat_p->d_buf == NULL)
226 		_err_exit("%s %s in %s.", fail_buf_s, "header names", aout_name);
227 
228 	DEBUG_LOC("_symintOpen: after call to getdata (for header names)");
229 
230 	pfile_p->pf_shdarr_p = (Elf32_Shdr *)
231 			_Malloc( pfile_p->pf_elfhd_p->e_shentsize,
232 			        pfile_p->pf_elfhd_p->e_shnum );
233 
234 	{
235 	char	*shdnms_p = (char *) pfile_p->pf_snmdat_p->d_buf;
236 
237 	char	*dest_p = (char *) pfile_p->pf_shdarr_p ;
238 	int	shdsize = pfile_p->pf_elfhd_p->e_shentsize ;
239 	int	i;
240 	char	*s;
241 
242 	i = 0;
243 	tscn_p = 0;
244 	DEBUG_EXP(printf("Section header entry size = %d\n",shdsize));
245 	DEBUG_EXP(printf("First section header name = %s\n",&shdnms_p[1]));
246 	while ((tscn_p = elf_nextscn(telf_p, tscn_p)) != NULL) {
247 		if ((tshd_p = elf32_getshdr(tscn_p)) == NULL)
248 			_err_exit("%s %d in %s.", fail_shd_s, i, aout_name);
249 
250 		memcpy( dest_p, tshd_p, shdsize );
251 		dest_p += shdsize ;
252 
253 		s = &shdnms_p[tshd_p->sh_name];
254 		DEBUG_EXP(printf("index of section name = %d\n",tshd_p->sh_name));
255 		DEBUG_EXP(printf("_symintOpen: reading section %s\n",s));
256 		if (strcmp(s, SCN_NAME_DEBUG) == 0) {
257 			DEBUG_LOC("_symintOpen: found debug section");
258 			pfile_p->pf_debugshd_p = tshd_p;
259 			pfile_p->pf_debugdat_p = section_data_p(tscn_p,"debug");
260 		} else if (strcmp(s, SCN_NAME_LINE) == 0) {
261 			DEBUG_LOC("_symintOpen: found line section");
262 			pfile_p->pf_lineshd_p = tshd_p;
263 			pfile_p->pf_linedat_p = section_data_p(tscn_p, "line");
264 		} else if (strcmp(s, SCN_NAME_SYM) == 0) {
265 			DEBUG_LOC("_symintOpen: found symbol section");
266 			pfile_p->pf_symshd_p = tshd_p;
267 			pfile_p->pf_symdat_p = section_data_p(tscn_p, "symtab");
268 			pfile_p->pf_nstsyms =
269 				tshd_p->sh_size / tshd_p->sh_entsize;
270 		} else if (strcmp(s, SCN_NAME_SST) == 0) {
271 			DEBUG_LOC("_symintOpen: found symbol table strings");
272 			pfile_p->pf_strshd_p = tshd_p;
273 			pfile_p->pf_strdat_p = section_data_p(tscn_p, "strtab");
274 			pfile_p->pf_symstr_p = pfile_p->pf_strdat_p->d_buf;
275 		}
276 
277 		i++;
278 	}
279 	}
280 
281 	if (!pfile_p->pf_symdat_p) {
282 		_err_exit("%s %s.", fail_sym_s, executableName);
283 	}
284 #if isLPROF
285 	if (!pfile_p->pf_linedat_p) {
286 		_err_exit("%s %s.", fail_line_s, executableName);
287 	}
288 	if (!pfile_p->pf_debugdat_p) {
289 		_err_exit("%s %s.", fail_debug_s, executableName);
290 	}
291 #endif
292 
293 	DEBUG_LOC("_symintOpen: after for loop that reads the sections");
294 
295 	DEBUG_LOC("_symintOpen: before call to _symintLoad");
296 
297 	if ((pfile_p->pf_symarr_p = _symintLoad(pfile_p)) == NULL)
298 		_err_exit("%s %s.", fail_pfsym_s, executableName);
299 
300 	DEBUG_LOC("_symintOpen: after call to _symintLoad");
301 
302 	/*
303 	*	At this point we might want to include some consistency
304 	*	checks to be sure all is well.  For example, we can check
305 	*	symbol table consistency by comparing "the product of the
306 	*	number of symbols and the size of each symbol" to "the
307 	*	length of the symbol table data".
308 	*
309 	*	Also, NULL may be a proper value (e.g., the debugger
310 	*	information when there is none) for some things that
311 	*	we cannot afford to be without.  We should check these
312 	*	at this point also.
313 	*/
314 
315 	DEBUG_LOC("_symintOpen: bottom");
316 	return( pfile_p );
317 }
318 
319