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