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 /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate /* 29*0Sstevel@tonic-gate * This file contains all functions relating to stab processing. The 30*0Sstevel@tonic-gate * stab table is compressed by eliminating duplicate include file entries. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate #include <stdio.h> 33*0Sstevel@tonic-gate #include <string.h> 34*0Sstevel@tonic-gate #include <stab.h> 35*0Sstevel@tonic-gate #include <unistd.h> 36*0Sstevel@tonic-gate #include <stdlib.h> 37*0Sstevel@tonic-gate #include <signal.h> 38*0Sstevel@tonic-gate #include <sys/param.h> 39*0Sstevel@tonic-gate #include <errno.h> 40*0Sstevel@tonic-gate #include "libld.h" 41*0Sstevel@tonic-gate #include "msg.h" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate /* 45*0Sstevel@tonic-gate * With the 5.x compiler, stab.h changed struct nlist into 46*0Sstevel@tonic-gate * struct stab and got rid of it's embeded unions. 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate #if __SUNPRO_C >= 0x500 || defined(__GNUC__) 49*0Sstevel@tonic-gate #define nlist stab 50*0Sstevel@tonic-gate #else 51*0Sstevel@tonic-gate #define n_strx n_un.n_strx 52*0Sstevel@tonic-gate #endif 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate /* 56*0Sstevel@tonic-gate * Data structure that holds persistent data that sbfocus_symbol & sbfocus_close 57*0Sstevel@tonic-gate * needs. Passing in a pointer to this struct makes them re-entrant. 58*0Sstevel@tonic-gate */ 59*0Sstevel@tonic-gate typedef struct sbld_tag { 60*0Sstevel@tonic-gate FILE *fd; 61*0Sstevel@tonic-gate int failed; 62*0Sstevel@tonic-gate } *Sbld, Sbld_rec; 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate extern Sbld_rec sb_data; 66*0Sstevel@tonic-gate extern const char *out_fname, *in_fname; 67*0Sstevel@tonic-gate extern Half out_e_type; 68*0Sstevel@tonic-gate extern void sbfocus_symbol(Sbld, const char *, const char *, 69*0Sstevel@tonic-gate const char *); 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate #if !defined(_ELF64) 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * holds information needed by sbfocus_symbol and sbfocus_close. 75*0Sstevel@tonic-gate */ 76*0Sstevel@tonic-gate Sbld_rec sb_data = { NULL, 0 }; 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate /* 79*0Sstevel@tonic-gate * holds information out the output file being created. 80*0Sstevel@tonic-gate */ 81*0Sstevel@tonic-gate const char *out_fname = NULL; 82*0Sstevel@tonic-gate const char *in_fname = NULL; /* current input file */ 83*0Sstevel@tonic-gate Half out_e_type = ET_NONE; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * Signal handler is called when a SIGPIPE is encountered. This would 87*0Sstevel@tonic-gate * happen in case `sbfocus' did not exist and `ld' is writing down a 88*0Sstevel@tonic-gate * pipe with no reader. Trap signal and set failed field so that no 89*0Sstevel@tonic-gate * more subsequent writes occur. 90*0Sstevel@tonic-gate */ 91*0Sstevel@tonic-gate static void 92*0Sstevel@tonic-gate sigpipe_handler() 93*0Sstevel@tonic-gate { 94*0Sstevel@tonic-gate sb_data.failed = 1; 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* 98*0Sstevel@tonic-gate * sbfocus_symbol() will write one symbol to a pipe that has the program 99*0Sstevel@tonic-gate * "sbfocus" at the receiving end. If the program has not been started yet, 100*0Sstevel@tonic-gate * it is started, and the pipe established. "sbfocus" is started with the 101*0Sstevel@tonic-gate * function arguments "type" and "name" as its arguments, in that order. 102*0Sstevel@tonic-gate * 103*0Sstevel@tonic-gate * sbfocus_symbol() should be called with four arguments: 104*0Sstevel@tonic-gate * data Pointer to a Sbld struct that the caller has allocated in 105*0Sstevel@tonic-gate * permanent storage. It must be the same struct for all related 106*0Sstevel@tonic-gate * calls to sbfocus_symbol(). 107*0Sstevel@tonic-gate * name This is the string name of the library/executable being built. 108*0Sstevel@tonic-gate * type A string, should be one of: 109*0Sstevel@tonic-gate * "-x": Building an executable or shared object 110*0Sstevel@tonic-gate * "-r": Concatenating object files 111*0Sstevel@tonic-gate * symbol The string that should be written to "sbfocus". If this 112*0Sstevel@tonic-gate * argument is NULL "sbfocus" is started, but no symbol is 113*0Sstevel@tonic-gate * written to it. 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate void 116*0Sstevel@tonic-gate sbfocus_symbol(Sbld data, const char *name, const char *type, 117*0Sstevel@tonic-gate const char *symbol) 118*0Sstevel@tonic-gate { 119*0Sstevel@tonic-gate int fd[2], err; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate if (data->failed) { 122*0Sstevel@tonic-gate return; 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate (void) signal(SIGPIPE, (void (*)(int)) sigpipe_handler); 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate if (data->fd == NULL) { 128*0Sstevel@tonic-gate data->failed = 0; 129*0Sstevel@tonic-gate (void) pipe(fd); 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate switch (fork()) { 132*0Sstevel@tonic-gate case -1: 133*0Sstevel@tonic-gate err = errno; 134*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK), 135*0Sstevel@tonic-gate in_fname, strerror(err), 136*0Sstevel@tonic-gate MSG_INTL(MSG_STAB_NOSBROW)); 137*0Sstevel@tonic-gate data->failed = 1; 138*0Sstevel@tonic-gate (void) close(fd[0]); 139*0Sstevel@tonic-gate (void) close(fd[1]); 140*0Sstevel@tonic-gate return; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * Child process 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate case 0: 146*0Sstevel@tonic-gate (void) close(fd[1]); 147*0Sstevel@tonic-gate (void) dup2(fd[0], fileno(stdin)); 148*0Sstevel@tonic-gate (void) close(fd[0]); 149*0Sstevel@tonic-gate (void) execlp(MSG_ORIG(MSG_STR_SBFOCUS), 150*0Sstevel@tonic-gate MSG_ORIG(MSG_STR_SBFOCUS), type, name, 0); 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate err = errno; 153*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), 154*0Sstevel@tonic-gate in_fname, MSG_ORIG(MSG_STR_SBFOCUS), 155*0Sstevel@tonic-gate strerror(err), MSG_INTL(MSG_STAB_NOSBROW)); 156*0Sstevel@tonic-gate exit(-1); 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* 159*0Sstevel@tonic-gate * Parent process 160*0Sstevel@tonic-gate */ 161*0Sstevel@tonic-gate default: 162*0Sstevel@tonic-gate (void) close(fd[0]); 163*0Sstevel@tonic-gate data->fd = fdopen(fd[1], MSG_ORIG(MSG_STR_W)); 164*0Sstevel@tonic-gate break; 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate if (symbol != NULL) { 168*0Sstevel@tonic-gate (void) fputs(symbol, data->fd); 169*0Sstevel@tonic-gate (void) putc('\n', data->fd); 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate #endif /* !defined(_ELF64) */ 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate static Xword 176*0Sstevel@tonic-gate pass1_stabindex(const Elf_Data *s_data, const Elf_Data *str_data, 177*0Sstevel@tonic-gate const size_t cwd_len, const size_t name_len) 178*0Sstevel@tonic-gate { 179*0Sstevel@tonic-gate struct nlist *elem, 180*0Sstevel@tonic-gate *last = NULL; 181*0Sstevel@tonic-gate size_t i, 182*0Sstevel@tonic-gate str_offset = 0, 183*0Sstevel@tonic-gate new_size = 0, 184*0Sstevel@tonic-gate first_object = 1, 185*0Sstevel@tonic-gate any_obj = 0, 186*0Sstevel@tonic-gate num_elem; 187*0Sstevel@tonic-gate /* 188*0Sstevel@tonic-gate * The processing of the stab table happens in two passes. 189*0Sstevel@tonic-gate * 190*0Sstevel@tonic-gate * first pass: calculate if any change is needed and if so, how much 191*0Sstevel@tonic-gate * the string table needs to be expanded by. 192*0Sstevel@tonic-gate */ 193*0Sstevel@tonic-gate num_elem = s_data->d_size / sizeof (struct nlist); 194*0Sstevel@tonic-gate for (i = 0; i < num_elem; i++) { 195*0Sstevel@tonic-gate char *str; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate elem = (struct nlist *)s_data->d_buf + i; 198*0Sstevel@tonic-gate switch (elem->n_type) { 199*0Sstevel@tonic-gate case 0: 200*0Sstevel@tonic-gate if (last) 201*0Sstevel@tonic-gate str_offset += last->n_value; 202*0Sstevel@tonic-gate last = elem; 203*0Sstevel@tonic-gate break; 204*0Sstevel@tonic-gate case N_OBJ: 205*0Sstevel@tonic-gate str = (char *)str_data->d_buf + str_offset + 206*0Sstevel@tonic-gate elem->n_strx; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate if ((*str == '\0') && first_object) { 209*0Sstevel@tonic-gate /* 210*0Sstevel@tonic-gate * This is a 'CWD' N_OBJ 211*0Sstevel@tonic-gate * 212*0Sstevel@tonic-gate * we only record the 'cwd' once in each 213*0Sstevel@tonic-gate * stringtable. so - we only need to add 214*0Sstevel@tonic-gate * it's length once to the new_size 215*0Sstevel@tonic-gate */ 216*0Sstevel@tonic-gate if (any_obj == 0) { 217*0Sstevel@tonic-gate any_obj++; 218*0Sstevel@tonic-gate new_size += cwd_len + 1; 219*0Sstevel@tonic-gate } /* if */ 220*0Sstevel@tonic-gate first_object = 0; 221*0Sstevel@tonic-gate } /* if */ 222*0Sstevel@tonic-gate else if (*str == '\0') { 223*0Sstevel@tonic-gate /* 224*0Sstevel@tonic-gate * This is a 'object_name' N_OBJ 225*0Sstevel@tonic-gate */ 226*0Sstevel@tonic-gate new_size += name_len + 1; 227*0Sstevel@tonic-gate first_object = 1; 228*0Sstevel@tonic-gate } /* else if */ 229*0Sstevel@tonic-gate break; 230*0Sstevel@tonic-gate default: 231*0Sstevel@tonic-gate /* no-op */ 232*0Sstevel@tonic-gate break; 233*0Sstevel@tonic-gate } /* switch */ 234*0Sstevel@tonic-gate } /* for */ 235*0Sstevel@tonic-gate /*LINTED*/ 236*0Sstevel@tonic-gate return ((Xword) new_size); 237*0Sstevel@tonic-gate } /* pass1_stabindex */ 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate static int 241*0Sstevel@tonic-gate pass2_stabindex(Elf_Data *s_data, Elf_Data *str_data, const char *name, 242*0Sstevel@tonic-gate size_t name_len, size_t cwd_pos, size_t free_pos) 243*0Sstevel@tonic-gate { 244*0Sstevel@tonic-gate struct nlist *elem, 245*0Sstevel@tonic-gate *last = NULL; 246*0Sstevel@tonic-gate size_t i, 247*0Sstevel@tonic-gate str_offset = 0, 248*0Sstevel@tonic-gate first_object = 1, 249*0Sstevel@tonic-gate num_elem; 250*0Sstevel@tonic-gate /* 251*0Sstevel@tonic-gate * The processing of the stab table happens in two passes. 252*0Sstevel@tonic-gate * 253*0Sstevel@tonic-gate * first pass: calculate if any change is needed and if so, how much 254*0Sstevel@tonic-gate * the string table needs to be expanded by. 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate num_elem = s_data->d_size / sizeof (struct nlist); 257*0Sstevel@tonic-gate for (i = 0; i < num_elem; i++) { 258*0Sstevel@tonic-gate char *str; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate elem = (struct nlist *)s_data->d_buf + i; 261*0Sstevel@tonic-gate switch (elem->n_type) { 262*0Sstevel@tonic-gate case 0: 263*0Sstevel@tonic-gate if (last) 264*0Sstevel@tonic-gate str_offset += last->n_value; 265*0Sstevel@tonic-gate last = elem; 266*0Sstevel@tonic-gate break; 267*0Sstevel@tonic-gate case N_OBJ: 268*0Sstevel@tonic-gate str = (char *)str_data->d_buf + str_offset + 269*0Sstevel@tonic-gate elem->n_strx; 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate if ((*str == '\0') && first_object) { 272*0Sstevel@tonic-gate /* 273*0Sstevel@tonic-gate * This is a 'CWD' N_OBJ 274*0Sstevel@tonic-gate * 275*0Sstevel@tonic-gate * We point it at the CWD entry that we've 276*0Sstevel@tonic-gate * already placed in the new string_table. 277*0Sstevel@tonic-gate */ 278*0Sstevel@tonic-gate /*LINTED*/ 279*0Sstevel@tonic-gate elem->n_strx = (unsigned)(cwd_pos - str_offset); 280*0Sstevel@tonic-gate first_object = 0; 281*0Sstevel@tonic-gate } /* if */ 282*0Sstevel@tonic-gate else if (*str == '\0') { 283*0Sstevel@tonic-gate /* 284*0Sstevel@tonic-gate * This is a 'object_name' N_OBJ. 285*0Sstevel@tonic-gate * 286*0Sstevel@tonic-gate * Append the object name to the string table 287*0Sstevel@tonic-gate * and set the elem->n_un.n_strx to point 288*0Sstevel@tonic-gate * to it. 289*0Sstevel@tonic-gate */ 290*0Sstevel@tonic-gate (void) strcpy((char *)str_data->d_buf + 291*0Sstevel@tonic-gate free_pos, name); 292*0Sstevel@tonic-gate /*LINTED*/ 293*0Sstevel@tonic-gate elem->n_strx = (unsigned)(free_pos - 294*0Sstevel@tonic-gate str_offset); 295*0Sstevel@tonic-gate free_pos += name_len + 1; 296*0Sstevel@tonic-gate first_object = 1; 297*0Sstevel@tonic-gate } /* if */ 298*0Sstevel@tonic-gate break; 299*0Sstevel@tonic-gate default: 300*0Sstevel@tonic-gate break; 301*0Sstevel@tonic-gate } /* switch */ 302*0Sstevel@tonic-gate } /* for */ 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /*LINTED*/ 305*0Sstevel@tonic-gate last->n_value = (unsigned)(str_data->d_size - str_offset); 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate return (1); 308*0Sstevel@tonic-gate } /* pass2_stabindex() */ 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate /* 312*0Sstevel@tonic-gate * find_scn() 313*0Sstevel@tonic-gate * 314*0Sstevel@tonic-gate * Find a section in elf that matches the supplied section name, 315*0Sstevel@tonic-gate * type, and flags. 316*0Sstevel@tonic-gate * 317*0Sstevel@tonic-gate * Returns: 318*0Sstevel@tonic-gate * section number if found 319*0Sstevel@tonic-gate * 0 - if no matching section found 320*0Sstevel@tonic-gate * -1 - if error 321*0Sstevel@tonic-gate * 322*0Sstevel@tonic-gate * If shdr is a non-null pointer it will be set to the section header 323*0Sstevel@tonic-gate * that was found. 324*0Sstevel@tonic-gate */ 325*0Sstevel@tonic-gate static size_t 326*0Sstevel@tonic-gate find_scn(Elf *elf, const char *elf_strtab, const char *name, 327*0Sstevel@tonic-gate const Word sh_type, const Xword sh_flags, Elf_Scn **ret_scn) 328*0Sstevel@tonic-gate { 329*0Sstevel@tonic-gate Elf_Scn *scn = NULL; 330*0Sstevel@tonic-gate Shdr *scn_shdr; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate while ((scn = elf_nextscn(elf, scn)) != 0) { 333*0Sstevel@tonic-gate if ((scn_shdr = elf_getshdr(scn)) == NULL) 334*0Sstevel@tonic-gate return ((size_t)-1); 335*0Sstevel@tonic-gate if ((scn_shdr->sh_type == sh_type) && 336*0Sstevel@tonic-gate (scn_shdr->sh_flags == sh_flags) && 337*0Sstevel@tonic-gate (strcmp(elf_strtab + scn_shdr->sh_name, name) == 0)) { 338*0Sstevel@tonic-gate size_t scn_ndx; 339*0Sstevel@tonic-gate /* 340*0Sstevel@tonic-gate * we've got a match 341*0Sstevel@tonic-gate */ 342*0Sstevel@tonic-gate if ((scn_ndx = elf_ndxscn(scn)) == SHN_UNDEF) 343*0Sstevel@tonic-gate return ((size_t)-1); 344*0Sstevel@tonic-gate if (ret_scn) 345*0Sstevel@tonic-gate *ret_scn = scn; 346*0Sstevel@tonic-gate return (scn_ndx); 347*0Sstevel@tonic-gate } /* if */ 348*0Sstevel@tonic-gate } /* while */ 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate /* 351*0Sstevel@tonic-gate * no match found 352*0Sstevel@tonic-gate */ 353*0Sstevel@tonic-gate return (0); 354*0Sstevel@tonic-gate } /* find_scn() */ 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate static Elf_Data * 358*0Sstevel@tonic-gate get_str_data(Elf *elf, const char *strtab, const char *name, Shdr *shdr) 359*0Sstevel@tonic-gate { 360*0Sstevel@tonic-gate Elf_Scn *str_scn; 361*0Sstevel@tonic-gate Elf_Data *str_data; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate /* 364*0Sstevel@tonic-gate * The stab's string table can be found through the 365*0Sstevel@tonic-gate * shdr->sh_link value. 366*0Sstevel@tonic-gate */ 367*0Sstevel@tonic-gate if (shdr->sh_link == 0) { 368*0Sstevel@tonic-gate /* 369*0Sstevel@tonic-gate * Normally the sh_link field should point to the 370*0Sstevel@tonic-gate * required strtab. But if it's not filled in (which 371*0Sstevel@tonic-gate * means something goofed somewhere) we will try to look 372*0Sstevel@tonic-gate * it up from the elf file itself. 373*0Sstevel@tonic-gate */ 374*0Sstevel@tonic-gate size_t strscn_ndx; 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate strscn_ndx = find_scn(elf, strtab, name, SHT_STRTAB, 377*0Sstevel@tonic-gate shdr->sh_flags, &str_scn); 378*0Sstevel@tonic-gate if (strscn_ndx == 0) { 379*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_STAB_MISTBL), 380*0Sstevel@tonic-gate in_fname); 381*0Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 382*0Sstevel@tonic-gate } else if (strscn_ndx == (size_t)-1) { 383*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_STAB_BADTBL), 384*0Sstevel@tonic-gate in_fname); 385*0Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate } else { 388*0Sstevel@tonic-gate if ((str_scn = elf_getscn(elf, shdr->sh_link)) == NULL) { 389*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETSCN), 390*0Sstevel@tonic-gate in_fname, elf_errmsg(0)); 391*0Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate if ((str_data = elf_getdata(str_scn, NULL)) == NULL) { 396*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA), in_fname, 397*0Sstevel@tonic-gate elf_errmsg(0)); 398*0Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate return (str_data); 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate /* 408*0Sstevel@tonic-gate * We examine all the stab's looking for pairs of N_OBJ's who's 409*0Sstevel@tonic-gate * string pointers (elem->n_un.n_strx) points to a null string. 410*0Sstevel@tonic-gate * When we find a pair we set the first string pointing to the 411*0Sstevel@tonic-gate * CWD and we set the second string to the file object name (*name). 412*0Sstevel@tonic-gate * 413*0Sstevel@tonic-gate * The stab's string table will have to be expanded to hold 414*0Sstevel@tonic-gate * these new enties. 415*0Sstevel@tonic-gate */ 416*0Sstevel@tonic-gate static void 417*0Sstevel@tonic-gate process_stabindex(Elf *elf, const char *elf_strtab, const char *strtab_name, 418*0Sstevel@tonic-gate Shdr *shdr, Elf_Data *s_data) 419*0Sstevel@tonic-gate { 420*0Sstevel@tonic-gate Elf_Data *str_data; 421*0Sstevel@tonic-gate static char *cwd = NULL; 422*0Sstevel@tonic-gate static size_t cwd_len; 423*0Sstevel@tonic-gate size_t new_size, 424*0Sstevel@tonic-gate cwd_pos, 425*0Sstevel@tonic-gate name_len; 426*0Sstevel@tonic-gate Elf_Void *data; 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate if ((str_data = get_str_data(elf, elf_strtab, strtab_name, 429*0Sstevel@tonic-gate shdr)) == (Elf_Data *)S_ERROR) 430*0Sstevel@tonic-gate return; 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate if (cwd == NULL) { 433*0Sstevel@tonic-gate if ((cwd = getcwd(NULL, MAXPATHLEN)) == NULL) { 434*0Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_GETCWD), 435*0Sstevel@tonic-gate in_fname, strerror(errno)); 436*0Sstevel@tonic-gate return; 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate cwd_len = strlen(cwd); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate name_len = strlen(in_fname); 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate new_size = pass1_stabindex(s_data, str_data, cwd_len, name_len); 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate if (new_size == 0) 445*0Sstevel@tonic-gate /* no changes are needed */ 446*0Sstevel@tonic-gate return; 447*0Sstevel@tonic-gate /* 448*0Sstevel@tonic-gate * The .stab.index data buffer must be updated so a new copy is 449*0Sstevel@tonic-gate * allocated. The original is read-only. 450*0Sstevel@tonic-gate */ 451*0Sstevel@tonic-gate if ((data = malloc(s_data->d_size)) == 0) 452*0Sstevel@tonic-gate return; 453*0Sstevel@tonic-gate (void) memcpy(data, s_data->d_buf, s_data->d_size); 454*0Sstevel@tonic-gate s_data->d_buf = data; 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate /* 457*0Sstevel@tonic-gate * Allocate a new .stab.indexstr that is big enough to hold the new 458*0Sstevel@tonic-gate * entries that we will need to place into it. 459*0Sstevel@tonic-gate * 460*0Sstevel@tonic-gate * Then append the 'cwd' onto the end of the current data. 461*0Sstevel@tonic-gate */ 462*0Sstevel@tonic-gate if ((data = malloc(str_data->d_size + new_size)) == 0) 463*0Sstevel@tonic-gate return; 464*0Sstevel@tonic-gate (void) memcpy(data, str_data->d_buf, str_data->d_size); 465*0Sstevel@tonic-gate cwd_pos = str_data->d_size; 466*0Sstevel@tonic-gate (void) strcpy((char *)data + cwd_pos, cwd); 467*0Sstevel@tonic-gate str_data->d_buf = data; 468*0Sstevel@tonic-gate str_data->d_size = str_data->d_size + new_size; 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate (void) pass2_stabindex(s_data, str_data, in_fname, name_len, cwd_pos, 471*0Sstevel@tonic-gate cwd_pos + cwd_len + 1); 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate static void 476*0Sstevel@tonic-gate process_stabsbfocus(Elf *elf, const char *elf_strtab, 477*0Sstevel@tonic-gate const char *strtab_name, Shdr *shdr, Elf_Data *s_data, 478*0Sstevel@tonic-gate const char *out_name, Half etype) 479*0Sstevel@tonic-gate { 480*0Sstevel@tonic-gate Elf_Data *str_data; 481*0Sstevel@tonic-gate struct nlist *elem, *last = NULL; 482*0Sstevel@tonic-gate size_t i, str_offset = 0, num_elem; 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate if ((str_data = get_str_data(elf, elf_strtab, strtab_name, 485*0Sstevel@tonic-gate shdr)) == (Elf_Data *)S_ERROR) 486*0Sstevel@tonic-gate return; 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate num_elem = s_data->d_size / sizeof (struct nlist); 489*0Sstevel@tonic-gate for (i = 0; i < num_elem; i++) { 490*0Sstevel@tonic-gate const char *type, *str; 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate elem = (struct nlist *)s_data->d_buf + i; 493*0Sstevel@tonic-gate switch (elem->n_type) { 494*0Sstevel@tonic-gate case 0: 495*0Sstevel@tonic-gate if (last) 496*0Sstevel@tonic-gate str_offset += last->n_value; 497*0Sstevel@tonic-gate last = elem; 498*0Sstevel@tonic-gate break; 499*0Sstevel@tonic-gate case N_BROWS: 500*0Sstevel@tonic-gate str = (char *)str_data->d_buf + elem->n_strx + 501*0Sstevel@tonic-gate str_offset; 502*0Sstevel@tonic-gate if (etype == ET_REL) 503*0Sstevel@tonic-gate type = MSG_ORIG(MSG_STR_DASHR); 504*0Sstevel@tonic-gate else 505*0Sstevel@tonic-gate type = MSG_ORIG(MSG_STR_DASHX); 506*0Sstevel@tonic-gate sbfocus_symbol(&sb_data, out_name, type, str); 507*0Sstevel@tonic-gate break; 508*0Sstevel@tonic-gate default: 509*0Sstevel@tonic-gate /* no-op */ 510*0Sstevel@tonic-gate break; 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate /* ARGSUSED2 */ 517*0Sstevel@tonic-gate void 518*0Sstevel@tonic-gate #if defined(_ELF64) 519*0Sstevel@tonic-gate ld_start64(const char *out_name, const Half etype, const char *caller) 520*0Sstevel@tonic-gate #else 521*0Sstevel@tonic-gate ld_start(const char *out_name, const Half etype, const char *caller) 522*0Sstevel@tonic-gate #endif 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate out_fname = out_name; 525*0Sstevel@tonic-gate out_e_type = etype; 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate /* ARGSUSED1 */ 530*0Sstevel@tonic-gate void 531*0Sstevel@tonic-gate #if defined(_ELF64) 532*0Sstevel@tonic-gate ld_file64(const char *name, const Elf_Kind kind, int flags, Elf *elf) 533*0Sstevel@tonic-gate #else 534*0Sstevel@tonic-gate ld_file(const char *name, const Elf_Kind kind, int flags, Elf *elf) 535*0Sstevel@tonic-gate #endif 536*0Sstevel@tonic-gate { 537*0Sstevel@tonic-gate in_fname = name; 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate /* 542*0Sstevel@tonic-gate * ld_section() 543*0Sstevel@tonic-gate * 544*0Sstevel@tonic-gate * Args: 545*0Sstevel@tonic-gate * name - pointer to name of current section being processed. 546*0Sstevel@tonic-gate * shdr - pointer to Section Header of current in-file being 547*0Sstevel@tonic-gate * processed. 548*0Sstevel@tonic-gate * s_data - pointer to Section Data structure of current in-file 549*0Sstevel@tonic-gate * being processed. 550*0Sstevel@tonic-gate * elf - pointer to elf structure for current in-file being 551*0Sstevel@tonic-gate * processed 552*0Sstevel@tonic-gate */ 553*0Sstevel@tonic-gate /* ARGSUSED2 */ 554*0Sstevel@tonic-gate void 555*0Sstevel@tonic-gate #if defined(_ELF64) 556*0Sstevel@tonic-gate ld_section64(const char *scn_name, Shdr *shdr, Word scnndx, 557*0Sstevel@tonic-gate #else 558*0Sstevel@tonic-gate ld_section(const char *scn_name, Shdr *shdr, Word scnndx, 559*0Sstevel@tonic-gate #endif 560*0Sstevel@tonic-gate Elf_Data *s_data, Elf *elf) 561*0Sstevel@tonic-gate { 562*0Sstevel@tonic-gate Ehdr *ehdr; 563*0Sstevel@tonic-gate Elf_Data *str_data; 564*0Sstevel@tonic-gate Elf_Scn *str_scn; 565*0Sstevel@tonic-gate char *strtab; 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate ehdr = elf_getehdr(elf); 568*0Sstevel@tonic-gate if ((ehdr->e_type != ET_DYN) && (shdr->sh_type == SHT_PROGBITS)) { 569*0Sstevel@tonic-gate /* 570*0Sstevel@tonic-gate * this is a minor optimization for speed. If it's not a 571*0Sstevel@tonic-gate * stab string we aren't going to strcmp() it. 572*0Sstevel@tonic-gate */ 573*0Sstevel@tonic-gate if ((scn_name[1] == 's') && 574*0Sstevel@tonic-gate (scn_name[2] == 't') && 575*0Sstevel@tonic-gate (scn_name[3] == 'a') && 576*0Sstevel@tonic-gate (scn_name[4] == 'b')) { 577*0Sstevel@tonic-gate Word shstrndx; 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate /* 580*0Sstevel@tonic-gate * If 'extended sections' are in use, then 581*0Sstevel@tonic-gate * e_shstrndx == Shdr[0].sh_link 582*0Sstevel@tonic-gate */ 583*0Sstevel@tonic-gate if (ehdr->e_shstrndx == SHN_XINDEX) { 584*0Sstevel@tonic-gate Elf_Scn *scn0; 585*0Sstevel@tonic-gate Shdr *shdr0; 586*0Sstevel@tonic-gate scn0 = elf_getscn(elf, 0); 587*0Sstevel@tonic-gate shdr0 = elf_getshdr(scn0); 588*0Sstevel@tonic-gate shstrndx = shdr0->sh_link; 589*0Sstevel@tonic-gate } else 590*0Sstevel@tonic-gate shstrndx = ehdr->e_shstrndx; 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate str_scn = elf_getscn(elf, shstrndx); 593*0Sstevel@tonic-gate str_data = elf_getdata(str_scn, NULL); 594*0Sstevel@tonic-gate strtab = str_data->d_buf; 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate if (strcmp(scn_name, MSG_ORIG(MSG_SCN_STAB)) == 0) { 597*0Sstevel@tonic-gate /* 598*0Sstevel@tonic-gate * Process .stab 599*0Sstevel@tonic-gate */ 600*0Sstevel@tonic-gate process_stabsbfocus(elf, strtab, 601*0Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABSTR), shdr, 602*0Sstevel@tonic-gate s_data, out_fname, out_e_type); 603*0Sstevel@tonic-gate } else if (strcmp(scn_name, 604*0Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABINDEX)) == 0) { 605*0Sstevel@tonic-gate /* 606*0Sstevel@tonic-gate * Process .stab.index 607*0Sstevel@tonic-gate */ 608*0Sstevel@tonic-gate process_stabindex(elf, strtab, 609*0Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABINDEXSTR), shdr, 610*0Sstevel@tonic-gate s_data); 611*0Sstevel@tonic-gate } else if (strcmp(scn_name, 612*0Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABSBFOCUS)) == 0) { 613*0Sstevel@tonic-gate /* 614*0Sstevel@tonic-gate * Process .stab.sbfocus 615*0Sstevel@tonic-gate */ 616*0Sstevel@tonic-gate process_stabsbfocus(elf, strtab, 617*0Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABSBFOCUSTR), shdr, 618*0Sstevel@tonic-gate s_data, out_fname, out_e_type); 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate } 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate /* 625*0Sstevel@tonic-gate * Null atexit() routine, causes dlsym() to pass and thus no dlerror() message 626*0Sstevel@tonic-gate * generation. 627*0Sstevel@tonic-gate */ 628*0Sstevel@tonic-gate /* ARGSUSED */ 629*0Sstevel@tonic-gate void 630*0Sstevel@tonic-gate #if defined(_ELF64) 631*0Sstevel@tonic-gate ld_atexit64(int status) 632*0Sstevel@tonic-gate #else 633*0Sstevel@tonic-gate ld_atexit(int status) 634*0Sstevel@tonic-gate #endif 635*0Sstevel@tonic-gate { 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate #if !defined(_ELF64) 639*0Sstevel@tonic-gate /* 640*0Sstevel@tonic-gate * Messaging support - funnel everything through _dgettext() as this provides 641*0Sstevel@tonic-gate * a stub binding to libc, or a real binding to libintl. 642*0Sstevel@tonic-gate */ 643*0Sstevel@tonic-gate extern char *_dgettext(const char *, const char *); 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate const char * 646*0Sstevel@tonic-gate _libldstab_msg(Msg mid) 647*0Sstevel@tonic-gate { 648*0Sstevel@tonic-gate return (_dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 649*0Sstevel@tonic-gate } 650*0Sstevel@tonic-gate #endif 651