10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*6812Sraf * Common Development and Distribution License (the "License"). 6*6812Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21*6812Sraf 220Sstevel@tonic-gate /* 23*6812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*6812Sraf * Use is subject to license terms. 250Sstevel@tonic-gate */ 26*6812Sraf 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * This file contains all functions relating to stab processing. The 310Sstevel@tonic-gate * stab table is compressed by eliminating duplicate include file entries. 320Sstevel@tonic-gate */ 33*6812Sraf #include <stdio.h> 34*6812Sraf #include <string.h> 35*6812Sraf #include <stab.h> 36*6812Sraf #include <unistd.h> 37*6812Sraf #include <stdlib.h> 38*6812Sraf #include <signal.h> 39*6812Sraf #include <sys/param.h> 40*6812Sraf #include <errno.h> 41*6812Sraf #include <libintl.h> 42*6812Sraf #include "libld.h" 43*6812Sraf #include "msg.h" 440Sstevel@tonic-gate 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * With the 5.x compiler, stab.h changed struct nlist into 480Sstevel@tonic-gate * struct stab and got rid of it's embeded unions. 490Sstevel@tonic-gate */ 500Sstevel@tonic-gate #if __SUNPRO_C >= 0x500 || defined(__GNUC__) 510Sstevel@tonic-gate #define nlist stab 520Sstevel@tonic-gate #else 530Sstevel@tonic-gate #define n_strx n_un.n_strx 540Sstevel@tonic-gate #endif 550Sstevel@tonic-gate 560Sstevel@tonic-gate 570Sstevel@tonic-gate /* 580Sstevel@tonic-gate * Data structure that holds persistent data that sbfocus_symbol & sbfocus_close 590Sstevel@tonic-gate * needs. Passing in a pointer to this struct makes them re-entrant. 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate typedef struct sbld_tag { 620Sstevel@tonic-gate FILE *fd; 630Sstevel@tonic-gate int failed; 640Sstevel@tonic-gate } *Sbld, Sbld_rec; 650Sstevel@tonic-gate 660Sstevel@tonic-gate 670Sstevel@tonic-gate extern Sbld_rec sb_data; 680Sstevel@tonic-gate extern const char *out_fname, *in_fname; 690Sstevel@tonic-gate extern Half out_e_type; 700Sstevel@tonic-gate extern void sbfocus_symbol(Sbld, const char *, const char *, 710Sstevel@tonic-gate const char *); 720Sstevel@tonic-gate 730Sstevel@tonic-gate #if !defined(_ELF64) 740Sstevel@tonic-gate 750Sstevel@tonic-gate /* 760Sstevel@tonic-gate * holds information needed by sbfocus_symbol and sbfocus_close. 770Sstevel@tonic-gate */ 780Sstevel@tonic-gate Sbld_rec sb_data = { NULL, 0 }; 790Sstevel@tonic-gate 800Sstevel@tonic-gate /* 810Sstevel@tonic-gate * holds information out the output file being created. 820Sstevel@tonic-gate */ 830Sstevel@tonic-gate const char *out_fname = NULL; 840Sstevel@tonic-gate const char *in_fname = NULL; /* current input file */ 850Sstevel@tonic-gate Half out_e_type = ET_NONE; 860Sstevel@tonic-gate 870Sstevel@tonic-gate /* 880Sstevel@tonic-gate * Signal handler is called when a SIGPIPE is encountered. This would 890Sstevel@tonic-gate * happen in case `sbfocus' did not exist and `ld' is writing down a 900Sstevel@tonic-gate * pipe with no reader. Trap signal and set failed field so that no 910Sstevel@tonic-gate * more subsequent writes occur. 920Sstevel@tonic-gate */ 930Sstevel@tonic-gate static void 940Sstevel@tonic-gate sigpipe_handler() 950Sstevel@tonic-gate { 960Sstevel@tonic-gate sb_data.failed = 1; 970Sstevel@tonic-gate } 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* 1000Sstevel@tonic-gate * sbfocus_symbol() will write one symbol to a pipe that has the program 1010Sstevel@tonic-gate * "sbfocus" at the receiving end. If the program has not been started yet, 1020Sstevel@tonic-gate * it is started, and the pipe established. "sbfocus" is started with the 1030Sstevel@tonic-gate * function arguments "type" and "name" as its arguments, in that order. 1040Sstevel@tonic-gate * 1050Sstevel@tonic-gate * sbfocus_symbol() should be called with four arguments: 1060Sstevel@tonic-gate * data Pointer to a Sbld struct that the caller has allocated in 1070Sstevel@tonic-gate * permanent storage. It must be the same struct for all related 1080Sstevel@tonic-gate * calls to sbfocus_symbol(). 1090Sstevel@tonic-gate * name This is the string name of the library/executable being built. 1100Sstevel@tonic-gate * type A string, should be one of: 1110Sstevel@tonic-gate * "-x": Building an executable or shared object 1120Sstevel@tonic-gate * "-r": Concatenating object files 1130Sstevel@tonic-gate * symbol The string that should be written to "sbfocus". If this 1140Sstevel@tonic-gate * argument is NULL "sbfocus" is started, but no symbol is 1150Sstevel@tonic-gate * written to it. 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate void 1180Sstevel@tonic-gate sbfocus_symbol(Sbld data, const char *name, const char *type, 1190Sstevel@tonic-gate const char *symbol) 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate int fd[2], err; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (data->failed) { 1240Sstevel@tonic-gate return; 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate (void) signal(SIGPIPE, (void (*)(int)) sigpipe_handler); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate if (data->fd == NULL) { 1300Sstevel@tonic-gate data->failed = 0; 1310Sstevel@tonic-gate (void) pipe(fd); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate switch (fork()) { 1340Sstevel@tonic-gate case -1: 1350Sstevel@tonic-gate err = errno; 1360Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK), 1370Sstevel@tonic-gate in_fname, strerror(err), 1380Sstevel@tonic-gate MSG_INTL(MSG_STAB_NOSBROW)); 1390Sstevel@tonic-gate data->failed = 1; 1400Sstevel@tonic-gate (void) close(fd[0]); 1410Sstevel@tonic-gate (void) close(fd[1]); 1420Sstevel@tonic-gate return; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate /* 1450Sstevel@tonic-gate * Child process 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate case 0: 1480Sstevel@tonic-gate (void) close(fd[1]); 1490Sstevel@tonic-gate (void) dup2(fd[0], fileno(stdin)); 1500Sstevel@tonic-gate (void) close(fd[0]); 1510Sstevel@tonic-gate (void) execlp(MSG_ORIG(MSG_STR_SBFOCUS), 1520Sstevel@tonic-gate MSG_ORIG(MSG_STR_SBFOCUS), type, name, 0); 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate err = errno; 1550Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), 1560Sstevel@tonic-gate in_fname, MSG_ORIG(MSG_STR_SBFOCUS), 1570Sstevel@tonic-gate strerror(err), MSG_INTL(MSG_STAB_NOSBROW)); 1580Sstevel@tonic-gate exit(-1); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate /* 1610Sstevel@tonic-gate * Parent process 1620Sstevel@tonic-gate */ 1630Sstevel@tonic-gate default: 1640Sstevel@tonic-gate (void) close(fd[0]); 1650Sstevel@tonic-gate data->fd = fdopen(fd[1], MSG_ORIG(MSG_STR_W)); 1660Sstevel@tonic-gate break; 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate if (symbol != NULL) { 1700Sstevel@tonic-gate (void) fputs(symbol, data->fd); 1710Sstevel@tonic-gate (void) putc('\n', data->fd); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate #endif /* !defined(_ELF64) */ 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate static Xword 1780Sstevel@tonic-gate pass1_stabindex(const Elf_Data *s_data, const Elf_Data *str_data, 1790Sstevel@tonic-gate const size_t cwd_len, const size_t name_len) 1800Sstevel@tonic-gate { 181*6812Sraf struct nlist *elem; 182*6812Sraf struct nlist *last = NULL; 183*6812Sraf size_t i; 184*6812Sraf size_t str_offset = 0; 185*6812Sraf size_t new_size = 0; 186*6812Sraf size_t first_object = 1; 187*6812Sraf size_t any_obj = 0; 188*6812Sraf size_t num_elem; 1890Sstevel@tonic-gate /* 1900Sstevel@tonic-gate * The processing of the stab table happens in two passes. 1910Sstevel@tonic-gate * 1920Sstevel@tonic-gate * first pass: calculate if any change is needed and if so, how much 1930Sstevel@tonic-gate * the string table needs to be expanded by. 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate num_elem = s_data->d_size / sizeof (struct nlist); 1960Sstevel@tonic-gate for (i = 0; i < num_elem; i++) { 1970Sstevel@tonic-gate char *str; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate elem = (struct nlist *)s_data->d_buf + i; 2000Sstevel@tonic-gate switch (elem->n_type) { 2010Sstevel@tonic-gate case 0: 2020Sstevel@tonic-gate if (last) 2030Sstevel@tonic-gate str_offset += last->n_value; 2040Sstevel@tonic-gate last = elem; 2050Sstevel@tonic-gate break; 2060Sstevel@tonic-gate case N_OBJ: 2070Sstevel@tonic-gate str = (char *)str_data->d_buf + str_offset + 208*6812Sraf elem->n_strx; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate if ((*str == '\0') && first_object) { 2110Sstevel@tonic-gate /* 2120Sstevel@tonic-gate * This is a 'CWD' N_OBJ 2130Sstevel@tonic-gate * 2140Sstevel@tonic-gate * we only record the 'cwd' once in each 2150Sstevel@tonic-gate * stringtable. so - we only need to add 2160Sstevel@tonic-gate * it's length once to the new_size 2170Sstevel@tonic-gate */ 2180Sstevel@tonic-gate if (any_obj == 0) { 2190Sstevel@tonic-gate any_obj++; 2200Sstevel@tonic-gate new_size += cwd_len + 1; 2210Sstevel@tonic-gate } /* if */ 2220Sstevel@tonic-gate first_object = 0; 2230Sstevel@tonic-gate } /* if */ 2240Sstevel@tonic-gate else if (*str == '\0') { 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * This is a 'object_name' N_OBJ 2270Sstevel@tonic-gate */ 2280Sstevel@tonic-gate new_size += name_len + 1; 2290Sstevel@tonic-gate first_object = 1; 2300Sstevel@tonic-gate } /* else if */ 2310Sstevel@tonic-gate break; 2320Sstevel@tonic-gate default: 2330Sstevel@tonic-gate /* no-op */ 2340Sstevel@tonic-gate break; 2350Sstevel@tonic-gate } /* switch */ 2360Sstevel@tonic-gate } /* for */ 2370Sstevel@tonic-gate /*LINTED*/ 2380Sstevel@tonic-gate return ((Xword) new_size); 2390Sstevel@tonic-gate } /* pass1_stabindex */ 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate static int 2430Sstevel@tonic-gate pass2_stabindex(Elf_Data *s_data, Elf_Data *str_data, const char *name, 2440Sstevel@tonic-gate size_t name_len, size_t cwd_pos, size_t free_pos) 2450Sstevel@tonic-gate { 246*6812Sraf struct nlist *elem; 247*6812Sraf struct nlist *last = NULL; 248*6812Sraf size_t i; 249*6812Sraf size_t str_offset = 0; 250*6812Sraf size_t first_object = 1; 251*6812Sraf size_t num_elem; 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * The processing of the stab table happens in two passes. 2540Sstevel@tonic-gate * 2550Sstevel@tonic-gate * first pass: calculate if any change is needed and if so, how much 2560Sstevel@tonic-gate * the string table needs to be expanded by. 2570Sstevel@tonic-gate */ 2580Sstevel@tonic-gate num_elem = s_data->d_size / sizeof (struct nlist); 2590Sstevel@tonic-gate for (i = 0; i < num_elem; i++) { 2600Sstevel@tonic-gate char *str; 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate elem = (struct nlist *)s_data->d_buf + i; 2630Sstevel@tonic-gate switch (elem->n_type) { 2640Sstevel@tonic-gate case 0: 2650Sstevel@tonic-gate if (last) 2660Sstevel@tonic-gate str_offset += last->n_value; 2670Sstevel@tonic-gate last = elem; 2680Sstevel@tonic-gate break; 2690Sstevel@tonic-gate case N_OBJ: 2700Sstevel@tonic-gate str = (char *)str_data->d_buf + str_offset + 271*6812Sraf elem->n_strx; 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate if ((*str == '\0') && first_object) { 2740Sstevel@tonic-gate /* 2750Sstevel@tonic-gate * This is a 'CWD' N_OBJ 2760Sstevel@tonic-gate * 2770Sstevel@tonic-gate * We point it at the CWD entry that we've 2780Sstevel@tonic-gate * already placed in the new string_table. 2790Sstevel@tonic-gate */ 2800Sstevel@tonic-gate /*LINTED*/ 2810Sstevel@tonic-gate elem->n_strx = (unsigned)(cwd_pos - str_offset); 2820Sstevel@tonic-gate first_object = 0; 2830Sstevel@tonic-gate } /* if */ 2840Sstevel@tonic-gate else if (*str == '\0') { 2850Sstevel@tonic-gate /* 2860Sstevel@tonic-gate * This is a 'object_name' N_OBJ. 2870Sstevel@tonic-gate * 2880Sstevel@tonic-gate * Append the object name to the string table 2890Sstevel@tonic-gate * and set the elem->n_un.n_strx to point 2900Sstevel@tonic-gate * to it. 2910Sstevel@tonic-gate */ 2920Sstevel@tonic-gate (void) strcpy((char *)str_data->d_buf + 293*6812Sraf free_pos, name); 2940Sstevel@tonic-gate /*LINTED*/ 2950Sstevel@tonic-gate elem->n_strx = (unsigned)(free_pos - 2960Sstevel@tonic-gate str_offset); 2970Sstevel@tonic-gate free_pos += name_len + 1; 2980Sstevel@tonic-gate first_object = 1; 2990Sstevel@tonic-gate } /* if */ 3000Sstevel@tonic-gate break; 3010Sstevel@tonic-gate default: 3020Sstevel@tonic-gate break; 3030Sstevel@tonic-gate } /* switch */ 3040Sstevel@tonic-gate } /* for */ 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /*LINTED*/ 3070Sstevel@tonic-gate last->n_value = (unsigned)(str_data->d_size - str_offset); 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate return (1); 3100Sstevel@tonic-gate } /* pass2_stabindex() */ 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate /* 3140Sstevel@tonic-gate * find_scn() 3150Sstevel@tonic-gate * 3160Sstevel@tonic-gate * Find a section in elf that matches the supplied section name, 3170Sstevel@tonic-gate * type, and flags. 3180Sstevel@tonic-gate * 3190Sstevel@tonic-gate * Returns: 3200Sstevel@tonic-gate * section number if found 3210Sstevel@tonic-gate * 0 - if no matching section found 3220Sstevel@tonic-gate * -1 - if error 3230Sstevel@tonic-gate * 3240Sstevel@tonic-gate * If shdr is a non-null pointer it will be set to the section header 3250Sstevel@tonic-gate * that was found. 3260Sstevel@tonic-gate */ 3270Sstevel@tonic-gate static size_t 3280Sstevel@tonic-gate find_scn(Elf *elf, const char *elf_strtab, const char *name, 3290Sstevel@tonic-gate const Word sh_type, const Xword sh_flags, Elf_Scn **ret_scn) 3300Sstevel@tonic-gate { 3310Sstevel@tonic-gate Elf_Scn *scn = NULL; 3320Sstevel@tonic-gate Shdr *scn_shdr; 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate while ((scn = elf_nextscn(elf, scn)) != 0) { 3350Sstevel@tonic-gate if ((scn_shdr = elf_getshdr(scn)) == NULL) 3360Sstevel@tonic-gate return ((size_t)-1); 3370Sstevel@tonic-gate if ((scn_shdr->sh_type == sh_type) && 3380Sstevel@tonic-gate (scn_shdr->sh_flags == sh_flags) && 3390Sstevel@tonic-gate (strcmp(elf_strtab + scn_shdr->sh_name, name) == 0)) { 3400Sstevel@tonic-gate size_t scn_ndx; 3410Sstevel@tonic-gate /* 3420Sstevel@tonic-gate * we've got a match 3430Sstevel@tonic-gate */ 3440Sstevel@tonic-gate if ((scn_ndx = elf_ndxscn(scn)) == SHN_UNDEF) 3450Sstevel@tonic-gate return ((size_t)-1); 3460Sstevel@tonic-gate if (ret_scn) 3470Sstevel@tonic-gate *ret_scn = scn; 3480Sstevel@tonic-gate return (scn_ndx); 3490Sstevel@tonic-gate } /* if */ 3500Sstevel@tonic-gate } /* while */ 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate /* 3530Sstevel@tonic-gate * no match found 3540Sstevel@tonic-gate */ 3550Sstevel@tonic-gate return (0); 3560Sstevel@tonic-gate } /* find_scn() */ 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate static Elf_Data * 3600Sstevel@tonic-gate get_str_data(Elf *elf, const char *strtab, const char *name, Shdr *shdr) 3610Sstevel@tonic-gate { 3620Sstevel@tonic-gate Elf_Scn *str_scn; 3630Sstevel@tonic-gate Elf_Data *str_data; 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate /* 3660Sstevel@tonic-gate * The stab's string table can be found through the 3670Sstevel@tonic-gate * shdr->sh_link value. 3680Sstevel@tonic-gate */ 3690Sstevel@tonic-gate if (shdr->sh_link == 0) { 3700Sstevel@tonic-gate /* 3710Sstevel@tonic-gate * Normally the sh_link field should point to the 3720Sstevel@tonic-gate * required strtab. But if it's not filled in (which 3730Sstevel@tonic-gate * means something goofed somewhere) we will try to look 3740Sstevel@tonic-gate * it up from the elf file itself. 3750Sstevel@tonic-gate */ 3760Sstevel@tonic-gate size_t strscn_ndx; 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate strscn_ndx = find_scn(elf, strtab, name, SHT_STRTAB, 3790Sstevel@tonic-gate shdr->sh_flags, &str_scn); 3800Sstevel@tonic-gate if (strscn_ndx == 0) { 3810Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_STAB_MISTBL), 382*6812Sraf in_fname); 3830Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 3840Sstevel@tonic-gate } else if (strscn_ndx == (size_t)-1) { 3850Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_STAB_BADTBL), 386*6812Sraf in_fname); 3870Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate } else { 3900Sstevel@tonic-gate if ((str_scn = elf_getscn(elf, shdr->sh_link)) == NULL) { 3910Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETSCN), 392*6812Sraf in_fname, elf_errmsg(0)); 3930Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate if ((str_data = elf_getdata(str_scn, NULL)) == NULL) { 3980Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA), in_fname, 399*6812Sraf elf_errmsg(0)); 4000Sstevel@tonic-gate return ((Elf_Data *)S_ERROR); 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate return (str_data); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate /* 4100Sstevel@tonic-gate * We examine all the stab's looking for pairs of N_OBJ's who's 4110Sstevel@tonic-gate * string pointers (elem->n_un.n_strx) points to a null string. 4120Sstevel@tonic-gate * When we find a pair we set the first string pointing to the 4130Sstevel@tonic-gate * CWD and we set the second string to the file object name (*name). 4140Sstevel@tonic-gate * 4150Sstevel@tonic-gate * The stab's string table will have to be expanded to hold 4160Sstevel@tonic-gate * these new enties. 4170Sstevel@tonic-gate */ 4180Sstevel@tonic-gate static void 4190Sstevel@tonic-gate process_stabindex(Elf *elf, const char *elf_strtab, const char *strtab_name, 4200Sstevel@tonic-gate Shdr *shdr, Elf_Data *s_data) 4210Sstevel@tonic-gate { 4220Sstevel@tonic-gate Elf_Data *str_data; 4230Sstevel@tonic-gate static char *cwd = NULL; 4240Sstevel@tonic-gate static size_t cwd_len; 425*6812Sraf size_t new_size; 426*6812Sraf size_t cwd_pos; 427*6812Sraf size_t name_len; 4280Sstevel@tonic-gate Elf_Void *data; 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate if ((str_data = get_str_data(elf, elf_strtab, strtab_name, 4310Sstevel@tonic-gate shdr)) == (Elf_Data *)S_ERROR) 4320Sstevel@tonic-gate return; 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate if (cwd == NULL) { 4350Sstevel@tonic-gate if ((cwd = getcwd(NULL, MAXPATHLEN)) == NULL) { 4360Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_GETCWD), 437*6812Sraf in_fname, strerror(errno)); 4380Sstevel@tonic-gate return; 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate cwd_len = strlen(cwd); 4410Sstevel@tonic-gate } 4420Sstevel@tonic-gate name_len = strlen(in_fname); 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate new_size = pass1_stabindex(s_data, str_data, cwd_len, name_len); 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate if (new_size == 0) 4470Sstevel@tonic-gate /* no changes are needed */ 4480Sstevel@tonic-gate return; 4490Sstevel@tonic-gate /* 4500Sstevel@tonic-gate * The .stab.index data buffer must be updated so a new copy is 4510Sstevel@tonic-gate * allocated. The original is read-only. 4520Sstevel@tonic-gate */ 4530Sstevel@tonic-gate if ((data = malloc(s_data->d_size)) == 0) 4540Sstevel@tonic-gate return; 4550Sstevel@tonic-gate (void) memcpy(data, s_data->d_buf, s_data->d_size); 4560Sstevel@tonic-gate s_data->d_buf = data; 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate /* 4590Sstevel@tonic-gate * Allocate a new .stab.indexstr that is big enough to hold the new 4600Sstevel@tonic-gate * entries that we will need to place into it. 4610Sstevel@tonic-gate * 4620Sstevel@tonic-gate * Then append the 'cwd' onto the end of the current data. 4630Sstevel@tonic-gate */ 4640Sstevel@tonic-gate if ((data = malloc(str_data->d_size + new_size)) == 0) 4650Sstevel@tonic-gate return; 4660Sstevel@tonic-gate (void) memcpy(data, str_data->d_buf, str_data->d_size); 4670Sstevel@tonic-gate cwd_pos = str_data->d_size; 4680Sstevel@tonic-gate (void) strcpy((char *)data + cwd_pos, cwd); 4690Sstevel@tonic-gate str_data->d_buf = data; 4700Sstevel@tonic-gate str_data->d_size = str_data->d_size + new_size; 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate (void) pass2_stabindex(s_data, str_data, in_fname, name_len, cwd_pos, 473*6812Sraf cwd_pos + cwd_len + 1); 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate static void 4780Sstevel@tonic-gate process_stabsbfocus(Elf *elf, const char *elf_strtab, 4790Sstevel@tonic-gate const char *strtab_name, Shdr *shdr, Elf_Data *s_data, 4800Sstevel@tonic-gate const char *out_name, Half etype) 4810Sstevel@tonic-gate { 4820Sstevel@tonic-gate Elf_Data *str_data; 4830Sstevel@tonic-gate struct nlist *elem, *last = NULL; 4840Sstevel@tonic-gate size_t i, str_offset = 0, num_elem; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate if ((str_data = get_str_data(elf, elf_strtab, strtab_name, 4870Sstevel@tonic-gate shdr)) == (Elf_Data *)S_ERROR) 4880Sstevel@tonic-gate return; 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate num_elem = s_data->d_size / sizeof (struct nlist); 4910Sstevel@tonic-gate for (i = 0; i < num_elem; i++) { 4920Sstevel@tonic-gate const char *type, *str; 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate elem = (struct nlist *)s_data->d_buf + i; 4950Sstevel@tonic-gate switch (elem->n_type) { 4960Sstevel@tonic-gate case 0: 4970Sstevel@tonic-gate if (last) 4980Sstevel@tonic-gate str_offset += last->n_value; 4990Sstevel@tonic-gate last = elem; 5000Sstevel@tonic-gate break; 5010Sstevel@tonic-gate case N_BROWS: 5020Sstevel@tonic-gate str = (char *)str_data->d_buf + elem->n_strx + 5030Sstevel@tonic-gate str_offset; 5040Sstevel@tonic-gate if (etype == ET_REL) 5050Sstevel@tonic-gate type = MSG_ORIG(MSG_STR_DASHR); 5060Sstevel@tonic-gate else 5070Sstevel@tonic-gate type = MSG_ORIG(MSG_STR_DASHX); 5080Sstevel@tonic-gate sbfocus_symbol(&sb_data, out_name, type, str); 5090Sstevel@tonic-gate break; 5100Sstevel@tonic-gate default: 5110Sstevel@tonic-gate /* no-op */ 5120Sstevel@tonic-gate break; 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate } 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate /* ARGSUSED2 */ 5190Sstevel@tonic-gate void 5200Sstevel@tonic-gate #if defined(_ELF64) 5210Sstevel@tonic-gate ld_start64(const char *out_name, const Half etype, const char *caller) 5220Sstevel@tonic-gate #else 5230Sstevel@tonic-gate ld_start(const char *out_name, const Half etype, const char *caller) 5240Sstevel@tonic-gate #endif 5250Sstevel@tonic-gate { 5260Sstevel@tonic-gate out_fname = out_name; 5270Sstevel@tonic-gate out_e_type = etype; 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate /* ARGSUSED1 */ 5320Sstevel@tonic-gate void 5330Sstevel@tonic-gate #if defined(_ELF64) 5340Sstevel@tonic-gate ld_file64(const char *name, const Elf_Kind kind, int flags, Elf *elf) 5350Sstevel@tonic-gate #else 5360Sstevel@tonic-gate ld_file(const char *name, const Elf_Kind kind, int flags, Elf *elf) 5370Sstevel@tonic-gate #endif 5380Sstevel@tonic-gate { 5390Sstevel@tonic-gate in_fname = name; 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate /* 5440Sstevel@tonic-gate * ld_section() 5450Sstevel@tonic-gate * 5460Sstevel@tonic-gate * Args: 5470Sstevel@tonic-gate * name - pointer to name of current section being processed. 5480Sstevel@tonic-gate * shdr - pointer to Section Header of current in-file being 5490Sstevel@tonic-gate * processed. 5500Sstevel@tonic-gate * s_data - pointer to Section Data structure of current in-file 5510Sstevel@tonic-gate * being processed. 5520Sstevel@tonic-gate * elf - pointer to elf structure for current in-file being 5530Sstevel@tonic-gate * processed 5540Sstevel@tonic-gate */ 5550Sstevel@tonic-gate /* ARGSUSED2 */ 5560Sstevel@tonic-gate void 5570Sstevel@tonic-gate #if defined(_ELF64) 5580Sstevel@tonic-gate ld_section64(const char *scn_name, Shdr *shdr, Word scnndx, 5590Sstevel@tonic-gate #else 5600Sstevel@tonic-gate ld_section(const char *scn_name, Shdr *shdr, Word scnndx, 5610Sstevel@tonic-gate #endif 5620Sstevel@tonic-gate Elf_Data *s_data, Elf *elf) 5630Sstevel@tonic-gate { 5640Sstevel@tonic-gate Ehdr *ehdr; 5650Sstevel@tonic-gate Elf_Data *str_data; 5660Sstevel@tonic-gate Elf_Scn *str_scn; 5670Sstevel@tonic-gate char *strtab; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate ehdr = elf_getehdr(elf); 5700Sstevel@tonic-gate if ((ehdr->e_type != ET_DYN) && (shdr->sh_type == SHT_PROGBITS)) { 5710Sstevel@tonic-gate /* 5720Sstevel@tonic-gate * this is a minor optimization for speed. If it's not a 5730Sstevel@tonic-gate * stab string we aren't going to strcmp() it. 5740Sstevel@tonic-gate */ 5750Sstevel@tonic-gate if ((scn_name[1] == 's') && 5760Sstevel@tonic-gate (scn_name[2] == 't') && 5770Sstevel@tonic-gate (scn_name[3] == 'a') && 5780Sstevel@tonic-gate (scn_name[4] == 'b')) { 5790Sstevel@tonic-gate Word shstrndx; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate /* 5820Sstevel@tonic-gate * If 'extended sections' are in use, then 5830Sstevel@tonic-gate * e_shstrndx == Shdr[0].sh_link 5840Sstevel@tonic-gate */ 5850Sstevel@tonic-gate if (ehdr->e_shstrndx == SHN_XINDEX) { 5860Sstevel@tonic-gate Elf_Scn *scn0; 5870Sstevel@tonic-gate Shdr *shdr0; 5880Sstevel@tonic-gate scn0 = elf_getscn(elf, 0); 5890Sstevel@tonic-gate shdr0 = elf_getshdr(scn0); 5900Sstevel@tonic-gate shstrndx = shdr0->sh_link; 5910Sstevel@tonic-gate } else 5920Sstevel@tonic-gate shstrndx = ehdr->e_shstrndx; 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate str_scn = elf_getscn(elf, shstrndx); 5950Sstevel@tonic-gate str_data = elf_getdata(str_scn, NULL); 5960Sstevel@tonic-gate strtab = str_data->d_buf; 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate if (strcmp(scn_name, MSG_ORIG(MSG_SCN_STAB)) == 0) { 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * Process .stab 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate process_stabsbfocus(elf, strtab, 6030Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABSTR), shdr, 6040Sstevel@tonic-gate s_data, out_fname, out_e_type); 6050Sstevel@tonic-gate } else if (strcmp(scn_name, 6060Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABINDEX)) == 0) { 6070Sstevel@tonic-gate /* 6080Sstevel@tonic-gate * Process .stab.index 6090Sstevel@tonic-gate */ 6100Sstevel@tonic-gate process_stabindex(elf, strtab, 6110Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABINDEXSTR), shdr, 6120Sstevel@tonic-gate s_data); 6130Sstevel@tonic-gate } else if (strcmp(scn_name, 6140Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABSBFOCUS)) == 0) { 6150Sstevel@tonic-gate /* 6160Sstevel@tonic-gate * Process .stab.sbfocus 6170Sstevel@tonic-gate */ 6180Sstevel@tonic-gate process_stabsbfocus(elf, strtab, 6190Sstevel@tonic-gate MSG_ORIG(MSG_SCN_STABSBFOCUSTR), shdr, 6200Sstevel@tonic-gate s_data, out_fname, out_e_type); 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate } 6230Sstevel@tonic-gate } 6240Sstevel@tonic-gate } 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate /* 6270Sstevel@tonic-gate * Null atexit() routine, causes dlsym() to pass and thus no dlerror() message 6280Sstevel@tonic-gate * generation. 6290Sstevel@tonic-gate */ 6300Sstevel@tonic-gate /* ARGSUSED */ 6310Sstevel@tonic-gate void 6320Sstevel@tonic-gate #if defined(_ELF64) 6330Sstevel@tonic-gate ld_atexit64(int status) 6340Sstevel@tonic-gate #else 6350Sstevel@tonic-gate ld_atexit(int status) 6360Sstevel@tonic-gate #endif 6370Sstevel@tonic-gate { 6380Sstevel@tonic-gate } 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate #if !defined(_ELF64) 6410Sstevel@tonic-gate /* 642*6812Sraf * Messaging support - funnel everything through dgettext(). 6430Sstevel@tonic-gate */ 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate const char * 6460Sstevel@tonic-gate _libldstab_msg(Msg mid) 6470Sstevel@tonic-gate { 648*6812Sraf return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate #endif 651