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