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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
40 * symintFcns.c -- symbol information interface routines.
42 * these routines form a symbol information access
43 * interface, for the profilers to get at object file
44 * information. this interface was designed to aid
45 * in the COFF to ELF conversion of prof, lprof and friends.
51 * _symintOpen(aout_name)
52 * aout_name - char string file name of object file
55 * returns PROF_FILE * - pointer to the PROF_FILE structure built,
61 * .H 3 "Executable File Open and Close"
63 * Under COFF, the routine ldopen, given a file name, returns a pointer to a
64 * structure called an LDFILE. This descriptor is then passed to each of
65 * the library routines (such as read header, read symbol table entry, etc)
66 * to access the information contained in the file. These calls are spread
67 * throughout the profiling code.
69 * Under ELF, the file must be opened using a system open call. The file
70 * descriptor is then passed to a routine which returns a pointer to an
71 * Elf structure. This pointer is then passed along to another routine which
72 * returns a different pointer which is in turn passed along to another
73 * routine. In an attempt to avoid disturbing the current format of the
74 * code (by having to pass around different types of pointers), we plan to
75 * build a PROF_FILE descriptor which will then be passed around in the
76 * same way as the pointer to LDFILE.
78 * Thus, for ELF, an open will consist of opening the file and extracting
79 * enough from it to fill in the PROF_FILE structure. The code for the
80 * open is as follows; the code for building the symbol table (extracting
81 * information from the sections to fill an array of PROF_SYMBOLS) has
92 *fail_open_s
= "Unable to open file",
93 *fail_begin_s
= "Unable to read (begin) file",
94 *fail_ehdr_s
= "Unable to get elf header in",
95 *fail_sec_s
= "Unable to get section",
96 *fail_shd_s
= "Unable to get header for section",
97 *fail_dat_s
= "Unable to get data for section",
98 *fail_sym_s
= "Cannot find symbol table section in",
99 *fail_pfsym_s
= "Unable to process symbols in",
100 *fail_buf_s
= "Data buffer is null for section",
101 *fail_sym32_s
= "Cannot handle more than 2^32 symbols"
106 * this points at the name of the executable.
108 static char *executableName
;
113 * section_data_p() - return ptr to section data,
114 * given section ptr and name of section.
118 section_data_p(Elf_Scn
*sec_p
, char *str
)
122 if ((dat_p
= elf_getdata(sec_p
, NULL
)) == NULL
)
123 _err_exit("%s %s in %s.", fail_dat_s
, str
, executableName
);
129 _symintOpen(char *aout_name
)
132 * Elf file open operation
134 * - point at executable's name, globally
136 * - align to current version
137 * - read the elf descriptor and header
138 * - read header-names section descriptor, header, and data
139 * - allocate space for all the section hdrs (pf_shdarr_p).
140 * - set a pointer to the header-names buffer
141 * - search the section headers for
142 * - debug section header and data
143 * - line section header and data
144 * - symbol table header, data, strings, and number of symbols
145 * and copy each section hdr into our array.
146 * - populate the PROF_SYMBOL array and anchor it in (pf_symarr_p).
149 PROF_FILE
*pfile_p
; /* PROF_FILE ptr to return. */
155 Elf64_Xword nsyms_pri
= 0, nsyms_aux
= 0;
157 executableName
= aout_name
;
159 DEBUG_LOC("_symintOpen: top");
160 if (aout_name
== NULL
) {
161 _err_exit("name of executable is null\n");
163 DEBUG_EXP(printf("Attempting to open %s\n", aout_name
));
164 pfile_p
= _Malloc(sizeof (PROF_FILE
), 1);
166 if ((pfile_p
->pf_fildes
= open(aout_name
, O_RDONLY
)) == -1)
167 _err_exit("%s %s.", fail_open_s
, aout_name
);
168 if ((elf_version(EV_CURRENT
)) == EV_NONE
)
169 _err_exit("Elf library out of date");
170 if ((pfile_p
->pf_elf_p
= elf_begin(pfile_p
->pf_fildes
,
171 ELF_C_READ
, (Elf
*)NULL
)) == NULL
)
172 _err_exit("%s %s.", fail_begin_s
, aout_name
);
174 DEBUG_EXP(printf("elfkind = %d\n", elf_kind(pfile_p
->pf_elf_p
)));
175 if ((pfile_p
->pf_elfhd_p
= elf32_getehdr(pfile_p
->pf_elf_p
)) == NULL
)
176 _err_exit("%s %s.", fail_ehdr_s
, aout_name
);
178 DEBUG_LOC("_symintOpen: after call to getehdr");
179 telf_p
= pfile_p
->pf_elf_p
;
181 tscn_p
= elf_getscn(telf_p
, k
= pfile_p
->pf_elfhd_p
->e_shstrndx
);
183 _err_exit("%s %d in %s.", fail_sec_s
, k
, aout_name
);
185 if (elf32_getshdr(tscn_p
) == NULL
)
186 _err_exit("%s %s in %s.", fail_shd_s
, "header names",
188 if ((pfile_p
->pf_snmdat_p
= elf_getdata(tscn_p
, NULL
)) == NULL
)
189 _err_exit("%s %s in %s.", fail_dat_s
, "header names",
192 DEBUG_EXP(printf("Address of data header = 0x%lx\n",
193 pfile_p
->pf_snmdat_p
));
194 DEBUG_EXP(printf("d_buf = 0x%lx\n",
195 pfile_p
->pf_snmdat_p
->d_buf
));
196 DEBUG_EXP(printf("d_type = %d\n",
197 pfile_p
->pf_snmdat_p
->d_type
));
198 DEBUG_EXP(printf("d_size = %d\n",
199 pfile_p
->pf_snmdat_p
->d_size
));
200 DEBUG_EXP(printf("d_off = %d\n",
201 pfile_p
->pf_snmdat_p
->d_off
));
202 DEBUG_EXP(printf("d_align = %d\n",
203 pfile_p
->pf_snmdat_p
->d_align
));
204 DEBUG_EXP(printf("d_version = %d\n",
205 pfile_p
->pf_snmdat_p
->d_version
));
207 if (pfile_p
->pf_snmdat_p
->d_buf
== NULL
)
208 _err_exit("%s %s in %s.", fail_buf_s
, "header names",
211 DEBUG_LOC("_symintOpen: after call to getdata (for header names)");
213 pfile_p
->pf_shdarr_p
= _Malloc(pfile_p
->pf_elfhd_p
->e_shentsize
,
214 pfile_p
->pf_elfhd_p
->e_shnum
);
218 char *shdnms_p
= (char *)pfile_p
->pf_snmdat_p
->d_buf
;
221 char *dest_p
= (char *)pfile_p
->pf_shdarr_p
;
222 int shdsize
= pfile_p
->pf_elfhd_p
->e_shentsize
;
224 int symtab_found
= 0;
227 DEBUG_EXP(printf("Section header entry size = %d\n", shdsize
));
228 DEBUG_EXP(printf("First section header name = %s\n", &shdnms_p
[1]));
229 pfile_p
->pf_symdat_aux_p
= NULL
;
231 * Scan the section headers looking for a symbol table. Our
232 * preference is to use .symtab, because it contains the full
233 * set of symbols. If we find it, we stop looking immediately
234 * and use it. In the absence of a .symtab section, we are
235 * willing to use the dynamic symbol table (.dynsym), possibly
236 * augmented by the .SUNW_ldynsym, which contains local symbols.
238 while ((tscn_p
= elf_nextscn(telf_p
, tscn_p
)) != NULL
) {
239 if ((tshd_p
= elf32_getshdr(tscn_p
)) == NULL
)
240 _err_exit("%s %d in %s.", fail_shd_s
, i
, aout_name
);
243 (void) memcpy(dest_p
, tshd_p
, shdsize
);
246 DEBUG_EXP(printf("index of section name = %d\n",
248 DEBUG_EXP(printf("_symintOpen: reading section %s\n",
249 &shdnms_p
[tshd_p
->sh_name
]));
253 switch (tshd_p
->sh_type
) {
255 DEBUG_LOC("_symintOpen: found symbol section");
256 pfile_p
->pf_symstr_ndx
= tshd_p
->sh_link
;
257 pfile_p
->pf_symdat_pri_p
=
258 section_data_p(tscn_p
, "symtab");
259 nsyms_pri
= tshd_p
->sh_size
/ tshd_p
->sh_entsize
;
260 /* Throw away .SUNW_ldynsym. It is for .dynsym only */
262 pfile_p
->pf_symdat_aux_p
= NULL
;
263 /* We have found the best symbol table. Stop looking */
268 /* We will use .dynsym if no .symtab is found */
269 DEBUG_LOC("_symintOpen: found dynamic symbol section");
270 pfile_p
->pf_symstr_ndx
= tshd_p
->sh_link
;
271 pfile_p
->pf_symdat_pri_p
=
272 section_data_p(tscn_p
, "dynsym");
273 nsyms_pri
= tshd_p
->sh_size
/ tshd_p
->sh_entsize
;
276 case SHT_SUNW_LDYNSYM
:
277 /* Auxiliary table, used with .dynsym */
278 DEBUG_LOC("_symintOpen: found dynamic symbol section");
279 pfile_p
->pf_symdat_aux_p
=
280 section_data_p(tscn_p
, "SUNW_ldynsym");
281 nsyms_aux
= tshd_p
->sh_size
/ tshd_p
->sh_entsize
;
288 if (pfile_p
->pf_symdat_pri_p
== NULL
|| pfile_p
->pf_symstr_ndx
== 0)
289 _err_exit("%s %s.", fail_sym_s
, executableName
);
291 pfile_p
->pf_nstsyms
= (int)(nsyms_pri
+ nsyms_aux
);
292 pfile_p
->pf_nstsyms_aux
= (int)nsyms_aux
;
293 if ((nsyms_pri
+ nsyms_aux
) != (Elf64_Xword
)pfile_p
->pf_nstsyms
)
294 _err_exit("%s %s.", fail_sym32_s
, executableName
);
297 DEBUG_LOC("_symintOpen: after for loop that reads the sections");
299 DEBUG_LOC("_symintOpen: before call to _symintLoad");
301 if ((pfile_p
->pf_symarr_p
= _symintLoad(pfile_p
)) == NULL
)
302 _err_exit("%s %s.", fail_pfsym_s
, executableName
);
304 DEBUG_LOC("_symintOpen: after call to _symintLoad");
307 * At this point we might want to include some consistency
308 * checks to be sure all is well. For example, we can check
309 * symbol table consistency by comparing "the product of the
310 * number of symbols and the size of each symbol" to "the
311 * length of the symbol table data".
313 * Also, NULL may be a proper value (e.g., the debugger
314 * information when there is none) for some things that
315 * we cannot afford to be without. We should check these
316 * at this point also.
319 DEBUG_LOC("_symintOpen: bottom");