17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 247c478bd9Sstevel@tonic-gate * All Rights Reserved 257c478bd9Sstevel@tonic-gate * 26dc0f59e5SAli Bahrami * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Library processing 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 34*875546acSRichard Lowe #include <errno.h> 35dc0f59e5SAli Bahrami #include <ar.h> 365aefb655Srie #include <debug.h> 377c478bd9Sstevel@tonic-gate #include "msg.h" 387c478bd9Sstevel@tonic-gate #include "_libld.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 418dea2860Srie * Archive members are typically extracted to resolve an existing undefined 428dea2860Srie * reference. However, other symbol definitions can cause archive members to 438dea2860Srie * be processed to determine if the archive member provides a more appropriate 448dea2860Srie * definition. This routine processes the archive member to determine if the 458dea2860Srie * member is really required. 468dea2860Srie * 478dea2860Srie * i. Tentative symbols may cause the extraction of an archive member. 488dea2860Srie * If the archive member has a strong defined symbol it will be used. 498dea2860Srie * If the archive member simply contains another tentative definition, 508dea2860Srie * or a defined function symbol, then it will not be used. 518dea2860Srie * 528dea2860Srie * ii. A symbol reference may define a hidden or protected visibility. The 538dea2860Srie * reference can only be bound to a definition within a relocatable object 548dea2860Srie * for this restricted visibility to be satisfied. If the archive member 558dea2860Srie * provides a definition of the same symbol type, this definition is 568dea2860Srie * taken. The visibility of the defined symbol is irrelevant, as the most 578dea2860Srie * restrictive visibility of the reference and the definition will be 588dea2860Srie * applied to the final symbol. 59dc0f59e5SAli Bahrami * 60dc0f59e5SAli Bahrami * exit: 61dc0f59e5SAli Bahrami * Returns 1 if there is a match, 0 if no match is seen, and S_ERROR if an 62dc0f59e5SAli Bahrami * error occurred. 637c478bd9Sstevel@tonic-gate */ 64dc0f59e5SAli Bahrami static uintptr_t 658dea2860Srie process_member(Ar_mem *amp, const char *name, Sym_desc *sdp, Ofl_desc *ofl) 667c478bd9Sstevel@tonic-gate { 678dea2860Srie Sym *syms, *osym = sdp->sd_sym; 687c478bd9Sstevel@tonic-gate Xword symn, cnt; 697c478bd9Sstevel@tonic-gate char *strs; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * Find the first symbol table in the archive member, obtain its 737c478bd9Sstevel@tonic-gate * data buffer and determine the number of global symbols (Note, 747c478bd9Sstevel@tonic-gate * there must be a symbol table present otherwise the archive would 757c478bd9Sstevel@tonic-gate * never have been able to generate its own symbol entry for this 767c478bd9Sstevel@tonic-gate * member). 777c478bd9Sstevel@tonic-gate */ 7857ef7aa9SRod Evans if (amp->am_syms == NULL) { 797c478bd9Sstevel@tonic-gate Elf_Scn *scn = NULL; 807c478bd9Sstevel@tonic-gate Shdr *shdr; 817c478bd9Sstevel@tonic-gate Elf_Data *data; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate while (scn = elf_nextscn(amp->am_elf, scn)) { 847c478bd9Sstevel@tonic-gate if ((shdr = elf_getshdr(scn)) == NULL) { 851007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 865aefb655Srie MSG_INTL(MSG_ELF_GETSHDR), amp->am_path); 87dc0f59e5SAli Bahrami return (S_ERROR); 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate if ((shdr->sh_type == SHT_SYMTAB) || 907c478bd9Sstevel@tonic-gate (shdr->sh_type == SHT_DYNSYM)) 917c478bd9Sstevel@tonic-gate break; 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate if ((data = elf_getdata(scn, NULL)) == NULL) { 941007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETDATA), 951007fd6fSAli Bahrami amp->am_path); 96dc0f59e5SAli Bahrami return (S_ERROR); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate syms = (Sym *)data->d_buf; 997c478bd9Sstevel@tonic-gate syms += shdr->sh_info; 1007c478bd9Sstevel@tonic-gate symn = shdr->sh_size / shdr->sh_entsize; 1017c478bd9Sstevel@tonic-gate symn -= shdr->sh_info; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * Get the data for the associated string table. 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate if ((scn = elf_getscn(amp->am_elf, (size_t)shdr->sh_link)) == 1077c478bd9Sstevel@tonic-gate NULL) { 1081007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETSCN), 1091007fd6fSAli Bahrami amp->am_path); 110dc0f59e5SAli Bahrami return (S_ERROR); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate if ((data = elf_getdata(scn, NULL)) == NULL) { 1131007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETDATA), 1141007fd6fSAli Bahrami amp->am_path); 115dc0f59e5SAli Bahrami return (S_ERROR); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate strs = data->d_buf; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * Initialize the archive member structure in case we have to 1217c478bd9Sstevel@tonic-gate * come through here again. 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate amp->am_syms = syms; 1247c478bd9Sstevel@tonic-gate amp->am_strs = strs; 1257c478bd9Sstevel@tonic-gate amp->am_symn = symn; 1267c478bd9Sstevel@tonic-gate } else { 1277c478bd9Sstevel@tonic-gate syms = amp->am_syms; 1287c478bd9Sstevel@tonic-gate strs = amp->am_strs; 1297c478bd9Sstevel@tonic-gate symn = amp->am_symn; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * Loop through the symbol table entries looking for a match for the 1348dea2860Srie * original symbol. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < symn; syms++, cnt++) { 1378dea2860Srie Word shndx; 1387c478bd9Sstevel@tonic-gate 1398dea2860Srie if ((shndx = syms->st_shndx) == SHN_UNDEF) 1408dea2860Srie continue; 1418dea2860Srie 1428dea2860Srie if (osym->st_shndx == SHN_COMMON) { 1438dea2860Srie /* 1448dea2860Srie * Determine whether a tentative symbol definition 1458dea2860Srie * should be overridden. 1468dea2860Srie */ 1477c478bd9Sstevel@tonic-gate if ((shndx == SHN_ABS) || (shndx == SHN_COMMON) || 1488dea2860Srie (ELF_ST_TYPE(syms->st_info) == STT_FUNC)) 1497c478bd9Sstevel@tonic-gate continue; 1507c478bd9Sstevel@tonic-gate 1518dea2860Srie /* 1528dea2860Srie * A historic detail requires that a weak definition 1538dea2860Srie * within an archive will not override a strong 1548dea2860Srie * definition (see sym_realtent() resolution and ABI 1558dea2860Srie * symbol binding description - page 4-27). 1568dea2860Srie */ 1578dea2860Srie if ((ELF_ST_BIND(syms->st_info) == STB_WEAK) && 1588dea2860Srie (ELF_ST_BIND(osym->st_info) != STB_WEAK)) 1597c478bd9Sstevel@tonic-gate continue; 1608dea2860Srie } else { 1618dea2860Srie /* 1628dea2860Srie * Determine whether a restricted visibility reference 1638dea2860Srie * should be overridden. Don't worry about the 1648dea2860Srie * visibility of the archive member definition, nor 1658dea2860Srie * whether it is weak or global. Any definition is 1668dea2860Srie * better than a binding to an external shared object 1678dea2860Srie * (which is the only event that must presently exist 1688dea2860Srie * for us to be here looking for a better alternative). 1698dea2860Srie */ 1708dea2860Srie if (ELF_ST_TYPE(syms->st_info) != 1718dea2860Srie ELF_ST_TYPE(osym->st_info)) 1728dea2860Srie continue; 1738dea2860Srie } 1747c478bd9Sstevel@tonic-gate 1756b3ba5bdSAli Bahrami if (strcmp(strs + syms->st_name, name) == 0) 1767c478bd9Sstevel@tonic-gate return (1); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate return (0); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * Create an archive descriptor. By maintaining a list of archives any 1837c478bd9Sstevel@tonic-gate * duplicate occurrences of the same archive specified by the user enable us to 1847c478bd9Sstevel@tonic-gate * pick off where the last processing finished. 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate Ar_desc * 1875aefb655Srie ld_ar_setup(const char *name, Elf *elf, Ofl_desc *ofl) 1887c478bd9Sstevel@tonic-gate { 1897c478bd9Sstevel@tonic-gate Ar_desc * adp; 1907c478bd9Sstevel@tonic-gate size_t number; 1917c478bd9Sstevel@tonic-gate Elf_Arsym * start; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* 194dc0f59e5SAli Bahrami * Unless, -z allextract is specified, get the archive symbol table 195dc0f59e5SAli Bahrami * if one exists, and ignore the file with a warning message otherwise. 1967c478bd9Sstevel@tonic-gate */ 197dc0f59e5SAli Bahrami if (ofl->ofl_flags1 & FLG_OF1_ALLEXRT) { 198dc0f59e5SAli Bahrami start = NULL; 199dc0f59e5SAli Bahrami } else if ((start = elf_getarsym(elf, &number)) == NULL) { 2001007fd6fSAli Bahrami if (elf_errno()) 2011007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETARSYM), 2021007fd6fSAli Bahrami name); 2031007fd6fSAli Bahrami else 2041007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ELF_ARSYM), 2051007fd6fSAli Bahrami name); 2067c478bd9Sstevel@tonic-gate return (0); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * As this is a new archive reference establish a new descriptor. 2117c478bd9Sstevel@tonic-gate */ 21257ef7aa9SRod Evans if ((adp = libld_malloc(sizeof (Ar_desc))) == NULL) 2137c478bd9Sstevel@tonic-gate return ((Ar_desc *)S_ERROR); 2147c478bd9Sstevel@tonic-gate adp->ad_name = name; 2157c478bd9Sstevel@tonic-gate adp->ad_elf = elf; 2167c478bd9Sstevel@tonic-gate adp->ad_start = start; 217dc0f59e5SAli Bahrami if (start) { 218dc0f59e5SAli Bahrami adp->ad_aux = libld_calloc(sizeof (Ar_aux), number); 219dc0f59e5SAli Bahrami if (adp->ad_aux == NULL) 2207c478bd9Sstevel@tonic-gate return ((Ar_desc *)S_ERROR); 221dc0f59e5SAli Bahrami } else { 222dc0f59e5SAli Bahrami adp->ad_aux = NULL; 223dc0f59e5SAli Bahrami } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * Retain any command line options that are applicable to archive 2277c478bd9Sstevel@tonic-gate * extraction in case we have to rescan this archive later. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate adp->ad_flags = ofl->ofl_flags1 & MSK_OF1_ARCHIVE; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate ofl->ofl_arscnt++; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* 2347c478bd9Sstevel@tonic-gate * Add this new descriptor to the list of archives. 2357c478bd9Sstevel@tonic-gate */ 23657ef7aa9SRod Evans if (aplist_append(&ofl->ofl_ars, adp, AL_CNT_OFL_LIBS) == NULL) 2377c478bd9Sstevel@tonic-gate return ((Ar_desc *)S_ERROR); 2387c478bd9Sstevel@tonic-gate else 2397c478bd9Sstevel@tonic-gate return (adp); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2435aefb655Srie * For each archive descriptor, maintain an `Ar_aux' table to parallel the 2445aefb655Srie * archive symbol table (returned from elf_getarsym(3e)). Use this table to 2455aefb655Srie * hold a `Sym_desc' for each symbol (thus reducing the number of 2465aefb655Srie * ld_sym_find()'s), and to hold the `Ar_mem' pointer. The `Ar_mem' element 2475aefb655Srie * can have one of three values indicating the state of the archive member 2487c478bd9Sstevel@tonic-gate * associated with the offset for this symbol table entry: 2497c478bd9Sstevel@tonic-gate * 2507c478bd9Sstevel@tonic-gate * 0 indicates that the member has not been processed. 2517c478bd9Sstevel@tonic-gate * 2527c478bd9Sstevel@tonic-gate * FLG_ARMEM_PROC 2537c478bd9Sstevel@tonic-gate * indicates that the member has been processed. 2547c478bd9Sstevel@tonic-gate * 2557c478bd9Sstevel@tonic-gate * addr indicates that the member has been investigated to determine if 2567c478bd9Sstevel@tonic-gate * it contained a symbol definition we need, but was found not to 2577c478bd9Sstevel@tonic-gate * be a candidate for extraction. In this case the members 2587c478bd9Sstevel@tonic-gate * structure is maintained for possible later use. 2597c478bd9Sstevel@tonic-gate * 2607c478bd9Sstevel@tonic-gate * Each time we process an archive member we use its offset value to scan this 2617c478bd9Sstevel@tonic-gate * `Ar_aux' list. If the member has been extracted, each entry with the same 262a6d4d7d5SRod Evans * offset has its `Ar_mem' pointer set to FLG_ARMEM_PROC. Thus if we cycle back 2637c478bd9Sstevel@tonic-gate * through the archive symbol table we will ignore these symbols as they will 2647c478bd9Sstevel@tonic-gate * have already been added to the output image. If a member has been processed 2657c478bd9Sstevel@tonic-gate * but found not to contain a symbol we need, each entry with the same offset 2667c478bd9Sstevel@tonic-gate * has its `Ar_mem' pointer set to the member structures address. 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate void 2695aefb655Srie ld_ar_member(Ar_desc * adp, Elf_Arsym * arsym, Ar_aux * aup, Ar_mem * amp) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate Elf_Arsym * _arsym = arsym; 2727c478bd9Sstevel@tonic-gate Ar_aux * _aup = aup; 2737c478bd9Sstevel@tonic-gate size_t _off = arsym->as_off; 2747c478bd9Sstevel@tonic-gate 275dc0f59e5SAli Bahrami if (adp->ad_start == NULL) 276dc0f59e5SAli Bahrami return; 277dc0f59e5SAli Bahrami 278dc0f59e5SAli Bahrami /* 279dc0f59e5SAli Bahrami * Note: This algorithm assumes that the archive symbol table is 280dc0f59e5SAli Bahrami * built from the member objects, in the same order as those 281dc0f59e5SAli Bahrami * members are found in the archive. As such, the symbols for a 282dc0f59e5SAli Bahrami * given member will all cluster together. If this is not true, 283dc0f59e5SAli Bahrami * we will fail to mark some symbols. In that case, archive 284dc0f59e5SAli Bahrami * processing may be less efficient than it would be otherwise. 285dc0f59e5SAli Bahrami */ 286dc0f59e5SAli Bahrami 2877c478bd9Sstevel@tonic-gate if (_arsym != adp->ad_start) { 2887c478bd9Sstevel@tonic-gate do { 2897c478bd9Sstevel@tonic-gate _arsym--; 2907c478bd9Sstevel@tonic-gate _aup--; 2917c478bd9Sstevel@tonic-gate if (_arsym->as_off != _off) 2927c478bd9Sstevel@tonic-gate break; 2937c478bd9Sstevel@tonic-gate _aup->au_mem = amp; 2947c478bd9Sstevel@tonic-gate } while (_arsym != adp->ad_start); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate _arsym = arsym; 2987c478bd9Sstevel@tonic-gate _aup = aup; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate do { 3017c478bd9Sstevel@tonic-gate if (_arsym->as_off != _off) 3027c478bd9Sstevel@tonic-gate break; 3037c478bd9Sstevel@tonic-gate _aup->au_mem = amp; 3047c478bd9Sstevel@tonic-gate _arsym++; 3057c478bd9Sstevel@tonic-gate _aup++; 3067c478bd9Sstevel@tonic-gate } while (_arsym->as_name); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3102a93c375SAli Bahrami * Return the archive member's name. 311dc0f59e5SAli Bahrami * 312dc0f59e5SAli Bahrami * entry: 313dc0f59e5SAli Bahrami * name - Name of archive 3142a93c375SAli Bahrami * arelf - ELF descriptor for archive member. 315dc0f59e5SAli Bahrami * ofl - output descriptor 316dc0f59e5SAli Bahrami * 317dc0f59e5SAli Bahrami * exit: 3182a93c375SAli Bahrami * Returns pointer to archive member name on success, NULL on error. 319dc0f59e5SAli Bahrami */ 3202a93c375SAli Bahrami static const char * 3212a93c375SAli Bahrami ar_member_name(const char *name, Elf *arelf, Ofl_desc *ofl) 322dc0f59e5SAli Bahrami { 323dc0f59e5SAli Bahrami Elf_Arhdr *arhdr; 324dc0f59e5SAli Bahrami 3252a93c375SAli Bahrami if ((arhdr = elf_getarhdr(arelf)) == NULL) { 3261007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETARHDR), name); 3272a93c375SAli Bahrami return (NULL); 328dc0f59e5SAli Bahrami } 3292a93c375SAli Bahrami return (arhdr->ar_name); 330dc0f59e5SAli Bahrami } 331dc0f59e5SAli Bahrami 332dc0f59e5SAli Bahrami /* 3332a93c375SAli Bahrami * Construct the member's full pathname, using the format "%s(%s)". 3342a93c375SAli Bahrami * 3352a93c375SAli Bahrami * entry: 3362a93c375SAli Bahrami * name - Name of archive 3372a93c375SAli Bahrami * arname - Name of archive member 338*875546acSRichard Lowe * ofl - output descriptor 3392a93c375SAli Bahrami * exit: 3402a93c375SAli Bahrami * Returns pointer to constructed pathname on success, NULL on error. 341dc0f59e5SAli Bahrami */ 3422a93c375SAli Bahrami static const char * 343*875546acSRichard Lowe ar_member_path(const char *name, const char *arname, Ofl_desc *ofl) 3442a93c375SAli Bahrami { 3452a93c375SAli Bahrami size_t len; 3462a93c375SAli Bahrami char *path; 347dc0f59e5SAli Bahrami 3482a93c375SAli Bahrami len = strlen(name) + strlen(arname) + 3; 349*875546acSRichard Lowe if ((path = libld_malloc(len)) == NULL) { 350*875546acSRichard Lowe ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYS_MALLOC), 351*875546acSRichard Lowe strerror(errno)); 3522a93c375SAli Bahrami return (NULL); 353*875546acSRichard Lowe } 3542a93c375SAli Bahrami (void) snprintf(path, len, MSG_ORIG(MSG_FMT_ARMEM), name, arname); 3552a93c375SAli Bahrami return (path); 356dc0f59e5SAli Bahrami } 357dc0f59e5SAli Bahrami 358dc0f59e5SAli Bahrami /* 359dc0f59e5SAli Bahrami * Input the specified archive member to the link. 360dc0f59e5SAli Bahrami * 361dc0f59e5SAli Bahrami * entry: 362dc0f59e5SAli Bahrami * fd - Open file descriptor for archive 363dc0f59e5SAli Bahrami * adp - Archive descriptor 364dc0f59e5SAli Bahrami * ofl - output descriptor 365dc0f59e5SAli Bahrami * arelf - ELF descriptor for archive member. 366dc0f59e5SAli Bahrami * arpath - Address of pointer to be set to constructed path name 367dc0f59e5SAli Bahrami * for object. 368dc0f59e5SAli Bahrami * rej - Rejection descriptor to pass to ld_process_ifl(). 369dc0f59e5SAli Bahrami * 370dc0f59e5SAli Bahrami * exit: 371dc0f59e5SAli Bahrami * This routine can return one of the following: 372dc0f59e5SAli Bahrami * S_ERROR: Fatal error encountered. 373dc0f59e5SAli Bahrami * 0: Object was rejected, and should be ignored. 374dc0f59e5SAli Bahrami * rej will carry the rejection information. 375dc0f59e5SAli Bahrami * 1: The archive member has been input to the link. 376dc0f59e5SAli Bahrami */ 377dc0f59e5SAli Bahrami static uintptr_t 3782a93c375SAli Bahrami ar_input(int fd, Ar_desc *adp, Ofl_desc *ofl, Elf *arelf, 379dc0f59e5SAli Bahrami const char *arpath, Rej_desc *rej) 380dc0f59e5SAli Bahrami { 381dc0f59e5SAli Bahrami Rej_desc _rej = { 0 }; 382dc0f59e5SAli Bahrami 383dc0f59e5SAli Bahrami switch (ld_process_ifl(arpath, NULL, fd, arelf, 384dc0f59e5SAli Bahrami (FLG_IF_EXTRACT | FLG_IF_NEEDED), ofl, &_rej, NULL)) { 385dc0f59e5SAli Bahrami case S_ERROR: 386dc0f59e5SAli Bahrami return (S_ERROR); 387dc0f59e5SAli Bahrami case 0: 388dc0f59e5SAli Bahrami /* 389dc0f59e5SAli Bahrami * If this member is rejected maintain the first rejection 390dc0f59e5SAli Bahrami * error for possible later display. 391dc0f59e5SAli Bahrami */ 392dc0f59e5SAli Bahrami if (_rej.rej_type) { 393dc0f59e5SAli Bahrami if (rej->rej_type == 0) { 394dc0f59e5SAli Bahrami rej->rej_type = _rej.rej_type; 395dc0f59e5SAli Bahrami rej->rej_info = _rej.rej_info; 396dc0f59e5SAli Bahrami rej->rej_name = arpath; 397dc0f59e5SAli Bahrami } 398dc0f59e5SAli Bahrami (void) elf_end(arelf); 399dc0f59e5SAli Bahrami return (0); 400dc0f59e5SAli Bahrami } 401dc0f59e5SAli Bahrami } 402dc0f59e5SAli Bahrami 403dc0f59e5SAli Bahrami /* 404dc0f59e5SAli Bahrami * Indicate that the extracted member is in use. This 405dc0f59e5SAli Bahrami * enables debugging diags, and indicates that a further 406dc0f59e5SAli Bahrami * rescan of all archives may be necessary. 407dc0f59e5SAli Bahrami */ 408dc0f59e5SAli Bahrami ofl->ofl_flags1 |= FLG_OF1_EXTRACT; 409dc0f59e5SAli Bahrami adp->ad_flags |= FLG_ARD_EXTRACT; 410dc0f59e5SAli Bahrami return (1); 411dc0f59e5SAli Bahrami } 412dc0f59e5SAli Bahrami 413dc0f59e5SAli Bahrami /* 41460758829Srie * Data structure to indicate whether a symbol is visible for the purpose 41560758829Srie * of archive extraction. 41660758829Srie */ 41760758829Srie static const Boolean 41860758829Srie sym_vis[STV_NUM] = { 41960758829Srie TRUE, /* STV_DEFAULT */ 42060758829Srie FALSE, /* STV_INTERNAL */ 42160758829Srie FALSE, /* STV_HIDDEN */ 42260758829Srie FALSE, /* STV_PROTECTED */ 42360758829Srie TRUE, /* STV_EXPORTED */ 42460758829Srie TRUE, /* STV_SINGLETON */ 42560758829Srie FALSE /* STV_ELIMINATE */ 42660758829Srie }; 42760758829Srie #if STV_NUM != (STV_ELIMINATE + 1) 42860758829Srie #error "STV_NUM has grown. Update sym_vis[]." 42960758829Srie #endif 43060758829Srie 43160758829Srie /* 4328dea2860Srie * Read the archive symbol table. For each symbol in the table, determine 4338dea2860Srie * whether that symbol satisfies an unresolved reference, tentative reference, 4348dea2860Srie * or a reference that expects hidden or protected visibility. If so, the 4358dea2860Srie * corresponding object from the archive is processed. The archive symbol 4368dea2860Srie * table is searched until we go through a complete pass without satisfying any 4378dea2860Srie * unresolved symbols 438dc0f59e5SAli Bahrami * 439dc0f59e5SAli Bahrami * entry: 440dc0f59e5SAli Bahrami * name - Name of archive 441dc0f59e5SAli Bahrami * fd - Open file descriptor for archive 442dc0f59e5SAli Bahrami * adp - Archive descriptor 443dc0f59e5SAli Bahrami * ofl - output descriptor 444dc0f59e5SAli Bahrami * found - Address of variable to set to TRUE if any objects are extracted 445dc0f59e5SAli Bahrami * rej - Rejection descriptor to pass to ld_process_ifl(). 446dc0f59e5SAli Bahrami * 447dc0f59e5SAli Bahrami * exit: 448dc0f59e5SAli Bahrami * Returns FALSE on fatal error. On success, *found will be TRUE 449dc0f59e5SAli Bahrami * if any object was extracted, rej will be set if any object 450dc0f59e5SAli Bahrami * was rejected, and TRUE is returned. 4517c478bd9Sstevel@tonic-gate */ 452dc0f59e5SAli Bahrami static Boolean 4532a93c375SAli Bahrami ar_extract_bysym(const char *name, int fd, Ar_desc *adp, 454dc0f59e5SAli Bahrami Ofl_desc *ofl, Boolean *found, Rej_desc *rej) 4557c478bd9Sstevel@tonic-gate { 4567c478bd9Sstevel@tonic-gate Elf_Arsym * arsym; 4577c478bd9Sstevel@tonic-gate Elf * arelf; 4587c478bd9Sstevel@tonic-gate Ar_aux * aup; 4597c478bd9Sstevel@tonic-gate Sym_desc * sdp; 460dc0f59e5SAli Bahrami const char *arname, *arpath; 461dc0f59e5SAli Bahrami Boolean again = FALSE; 4627c478bd9Sstevel@tonic-gate uintptr_t err; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* 465dc0f59e5SAli Bahrami * An archive without a symbol table should not reach this function, 466dc0f59e5SAli Bahrami * because it can only get past ld_ar_setup() in the case where 467dc0f59e5SAli Bahrami * the archive is first seen under the influence of '-z allextract'. 468dc0f59e5SAli Bahrami * That will cause the entire archive to be extracted, and any 469dc0f59e5SAli Bahrami * subsequent reference to the archive will be ignored by 470dc0f59e5SAli Bahrami * ld_process_archive(). 4717c478bd9Sstevel@tonic-gate */ 472dc0f59e5SAli Bahrami if (adp->ad_start == NULL) { 473dc0f59e5SAli Bahrami assert(adp->ad_start != NULL); 474dc0f59e5SAli Bahrami return (TRUE); 475dc0f59e5SAli Bahrami } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * Loop through archive symbol table until we make a complete pass 4797c478bd9Sstevel@tonic-gate * without satisfying an unresolved reference. For each archive 4807c478bd9Sstevel@tonic-gate * symbol, see if there is a symbol with the same name in ld's 4817c478bd9Sstevel@tonic-gate * symbol table. If so, and if that symbol is still unresolved or 4827c478bd9Sstevel@tonic-gate * tentative, process the corresponding archive member. 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate do { 4855aefb655Srie DBG_CALL(Dbg_file_ar(ofl->ofl_lml, name, again)); 4865aefb655Srie DBG_CALL(Dbg_syms_ar_title(ofl->ofl_lml, name, again)); 487dc0f59e5SAli Bahrami again = FALSE; 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate for (arsym = adp->ad_start, aup = adp->ad_aux; arsym->as_name; 490dc0f59e5SAli Bahrami ++arsym, ++aup) { 4917c478bd9Sstevel@tonic-gate Ar_mem *amp; 4927c478bd9Sstevel@tonic-gate Sym *sym; 49360758829Srie Boolean visible = TRUE; 494dc0f59e5SAli Bahrami Boolean vers; 495dc0f59e5SAli Bahrami Ifl_desc *ifl; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* 4987c478bd9Sstevel@tonic-gate * If the auxiliary members value indicates that this 4997c478bd9Sstevel@tonic-gate * member has been processed then this symbol will have 5007c478bd9Sstevel@tonic-gate * been added to the output file image already or the 5017c478bd9Sstevel@tonic-gate * object was rejected in which case we don't want to 5027c478bd9Sstevel@tonic-gate * process it again. 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate if (aup->au_mem == FLG_ARMEM_PROC) 5057c478bd9Sstevel@tonic-gate continue; 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* 5087c478bd9Sstevel@tonic-gate * If the auxiliary symbol element is non-zero lookup 5097c478bd9Sstevel@tonic-gate * the symbol from the internal symbol table. 5107c478bd9Sstevel@tonic-gate */ 511dc0f59e5SAli Bahrami if ((sdp = aup->au_syms) == NULL) { 5125aefb655Srie if ((sdp = ld_sym_find(arsym->as_name, 5137c478bd9Sstevel@tonic-gate /* LINTED */ 514635216b6SRod Evans (Word)arsym->as_hash, NULL, ofl)) == NULL) { 515dc0f59e5SAli Bahrami DBG_CALL(Dbg_syms_ar_skip(ofl->ofl_lml, 516dc0f59e5SAli Bahrami name, arsym)); 5177c478bd9Sstevel@tonic-gate continue; 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate aup->au_syms = sdp; 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate /* 5237c478bd9Sstevel@tonic-gate * With '-z allextract', all members will be extracted. 5247c478bd9Sstevel@tonic-gate * 5257c478bd9Sstevel@tonic-gate * This archive member is a candidate for extraction if 5268dea2860Srie * the internal symbol originates from an explicit file, 5278dea2860Srie * and represents an undefined or tentative symbol. 5288dea2860Srie * 5298dea2860Srie * By default, weak references do not cause archive 5308dea2860Srie * extraction, however the -zweakextract flag overrides 5318dea2860Srie * this default. 5328dea2860Srie * 5338dea2860Srie * If this symbol has already been bound to a versioned 5348dea2860Srie * shared object, but the shared objects version is not 5358dea2860Srie * available, then a definition of this symbol from 5368dea2860Srie * within the archive is a better candidate. Similarly, 5378dea2860Srie * if this symbol has been bound to a shared object, but 5388dea2860Srie * the original reference expected hidden or protected 5398dea2860Srie * visibility, then a definition of this symbol from 5408dea2860Srie * within the archive is a better candidate. 5417c478bd9Sstevel@tonic-gate */ 542dc0f59e5SAli Bahrami vers = TRUE; 543dc0f59e5SAli Bahrami ifl = sdp->sd_file; 5447c478bd9Sstevel@tonic-gate 5458dea2860Srie sym = sdp->sd_sym; 5468dea2860Srie 5478dea2860Srie if (sdp->sd_ref == REF_DYN_NEED) { 54860758829Srie uchar_t vis; 5498dea2860Srie 5508dea2860Srie if (ifl->ifl_vercnt) { 5517c478bd9Sstevel@tonic-gate Word vndx; 5527c478bd9Sstevel@tonic-gate Ver_index *vip; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate vndx = sdp->sd_aux->sa_dverndx; 5558dea2860Srie vip = &ifl->ifl_verndx[vndx]; 556dc0f59e5SAli Bahrami if (!(vip->vi_flags & FLG_VER_AVAIL)) 5577c478bd9Sstevel@tonic-gate vers = FALSE; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate 56060758829Srie vis = ELF_ST_VISIBILITY(sym->st_other); 56160758829Srie visible = sym_vis[vis]; 5628dea2860Srie } 5638dea2860Srie 5648dea2860Srie if (((ifl->ifl_flags & FLG_IF_NEEDED) == 0) || 565dc0f59e5SAli Bahrami (visible && vers && (sym->st_shndx != SHN_UNDEF) && 5668dea2860Srie (sym->st_shndx != SHN_COMMON)) || 5677c478bd9Sstevel@tonic-gate ((ELF_ST_BIND(sym->st_info) == STB_WEAK) && 5687c478bd9Sstevel@tonic-gate (!(ofl->ofl_flags1 & FLG_OF1_WEAKEXT)))) { 569dc0f59e5SAli Bahrami DBG_CALL(Dbg_syms_ar_skip(ofl->ofl_lml, 570dc0f59e5SAli Bahrami name, arsym)); 5717c478bd9Sstevel@tonic-gate continue; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * Determine if we have already extracted this member, 5767c478bd9Sstevel@tonic-gate * and if so reuse the Ar_mem information. 5777c478bd9Sstevel@tonic-gate */ 5787c478bd9Sstevel@tonic-gate if ((amp = aup->au_mem) != 0) { 5797c478bd9Sstevel@tonic-gate arelf = amp->am_elf; 5807c478bd9Sstevel@tonic-gate arname = amp->am_name; 5817c478bd9Sstevel@tonic-gate arpath = amp->am_path; 5827c478bd9Sstevel@tonic-gate } else { 5837c478bd9Sstevel@tonic-gate /* 5847c478bd9Sstevel@tonic-gate * Set up a new elf descriptor for this member. 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate if (elf_rand(adp->ad_elf, arsym->as_off) != 5877c478bd9Sstevel@tonic-gate arsym->as_off) { 5881007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 5897c478bd9Sstevel@tonic-gate MSG_INTL(MSG_ELF_ARMEM), name, 590dc0f59e5SAli Bahrami EC_WORD(arsym->as_off), 5917c478bd9Sstevel@tonic-gate demangle(arsym->as_name)); 592dc0f59e5SAli Bahrami return (FALSE); 5937c478bd9Sstevel@tonic-gate } 5943906e0c2Srie 5957c478bd9Sstevel@tonic-gate if ((arelf = elf_begin(fd, ELF_C_READ, 5967c478bd9Sstevel@tonic-gate adp->ad_elf)) == NULL) { 5971007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, 5987c478bd9Sstevel@tonic-gate MSG_INTL(MSG_ELF_BEGIN), name); 599dc0f59e5SAli Bahrami return (FALSE); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate 6022a93c375SAli Bahrami /* Get member filename */ 6032a93c375SAli Bahrami if ((arname = ar_member_name(name, arelf, 6042a93c375SAli Bahrami ofl)) == NULL) 605dc0f59e5SAli Bahrami return (FALSE); 6062a93c375SAli Bahrami 6072a93c375SAli Bahrami /* Construct the member's full pathname */ 608*875546acSRichard Lowe if ((arpath = ar_member_path(name, arname, 609*875546acSRichard Lowe ofl)) == NULL) 610*875546acSRichard Lowe return (FALSE); 6112a93c375SAli Bahrami 6122a93c375SAli Bahrami /* 6132a93c375SAli Bahrami * Determine whether the support libraries wish 6142a93c375SAli Bahrami * to process this open. See comments in 6152a93c375SAli Bahrami * ld_process_open(). 6162a93c375SAli Bahrami */ 6172a93c375SAli Bahrami ld_sup_open(ofl, &arpath, &arname, &fd, 6182a93c375SAli Bahrami (FLG_IF_EXTRACT | FLG_IF_NEEDED), 6192a93c375SAli Bahrami &arelf, adp->ad_elf, arsym->as_off, 6202a93c375SAli Bahrami elf_kind(arelf)); 6212a93c375SAli Bahrami if (arelf == NULL) { 6222a93c375SAli Bahrami /* Ignore this archive member */ 623a6d4d7d5SRod Evans aup->au_mem = FLG_ARMEM_PROC; 624a6d4d7d5SRod Evans continue; 625a6d4d7d5SRod Evans } 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6298dea2860Srie * The symbol for which this archive member is being 6308dea2860Srie * processed may provide a better alternative to the 6318dea2860Srie * symbol that is presently known. Two cases are 6328dea2860Srie * covered: 6338dea2860Srie * 6348dea2860Srie * i. The present symbol represents tentative data. 6358dea2860Srie * The archive member may provide a data 6368dea2860Srie * definition symbol. 6378dea2860Srie * ii. The present symbol represents a reference that 6388dea2860Srie * has seen a definition within a shared object 6398dea2860Srie * dependency, but the reference expects to be 6408dea2860Srie * reduced to hidden or protected visibility. 6417c478bd9Sstevel@tonic-gate */ 642dc0f59e5SAli Bahrami if ((sym->st_shndx == SHN_COMMON) || 643dc0f59e5SAli Bahrami (visible == FALSE)) { 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * If we don't already have a member structure 6467c478bd9Sstevel@tonic-gate * allocate one. 6477c478bd9Sstevel@tonic-gate */ 6487c478bd9Sstevel@tonic-gate if (!amp) { 6497c478bd9Sstevel@tonic-gate if ((amp = libld_calloc(sizeof (Ar_mem), 65057ef7aa9SRod Evans 1)) == NULL) 651dc0f59e5SAli Bahrami return (FALSE); 6527c478bd9Sstevel@tonic-gate amp->am_elf = arelf; 6537c478bd9Sstevel@tonic-gate amp->am_name = arname; 6547c478bd9Sstevel@tonic-gate amp->am_path = arpath; 6557c478bd9Sstevel@tonic-gate } 6565aefb655Srie DBG_CALL(Dbg_syms_ar_checking(ofl->ofl_lml, 657dc0f59e5SAli Bahrami name, arname, arsym)); 6587c478bd9Sstevel@tonic-gate if ((err = process_member(amp, arsym->as_name, 6598dea2860Srie sdp, ofl)) == S_ERROR) 660dc0f59e5SAli Bahrami return (FALSE); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * If it turns out that we don't need this 6647c478bd9Sstevel@tonic-gate * member simply initialize all other auxiliary 6657c478bd9Sstevel@tonic-gate * entries that match this offset with this 6667c478bd9Sstevel@tonic-gate * members address. In this way we can resuse 6677c478bd9Sstevel@tonic-gate * this information if we recurse back to this 6687c478bd9Sstevel@tonic-gate * symbol. 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate if (err == 0) { 67157ef7aa9SRod Evans if (aup->au_mem == NULL) 6725aefb655Srie ld_ar_member(adp, arsym, 6735aefb655Srie aup, amp); 6747c478bd9Sstevel@tonic-gate continue; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate /* 6797c478bd9Sstevel@tonic-gate * Process the archive member. Retain any error for 6807c478bd9Sstevel@tonic-gate * return to the caller. 6817c478bd9Sstevel@tonic-gate */ 682dc0f59e5SAli Bahrami DBG_CALL(Dbg_syms_ar_resolve(ofl->ofl_lml, 683dc0f59e5SAli Bahrami name, arname, arsym)); 6842a93c375SAli Bahrami switch (ar_input(fd, adp, ofl, arelf, arpath, 685dc0f59e5SAli Bahrami rej)) { 686dc0f59e5SAli Bahrami case S_ERROR: 687dc0f59e5SAli Bahrami return (FALSE); 688dc0f59e5SAli Bahrami case 0: 6897c478bd9Sstevel@tonic-gate /* 690dc0f59e5SAli Bahrami * Mark the member as extracted so that we 691dc0f59e5SAli Bahrami * don't try and process it again on a rescan. 6927c478bd9Sstevel@tonic-gate */ 6935aefb655Srie ld_ar_member(adp, arsym, aup, FLG_ARMEM_PROC); 6947c478bd9Sstevel@tonic-gate continue; 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate /* 698dc0f59e5SAli Bahrami * Note that this archive has contributed something 699dc0f59e5SAli Bahrami * during this specific operation, and also signal 700dc0f59e5SAli Bahrami * the need to rescan the archive. 7017c478bd9Sstevel@tonic-gate */ 702dc0f59e5SAli Bahrami *found = again = TRUE; 7037c478bd9Sstevel@tonic-gate 7045aefb655Srie ld_ar_member(adp, arsym, aup, FLG_ARMEM_PROC); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate } while (again); 7077c478bd9Sstevel@tonic-gate 708dc0f59e5SAli Bahrami return (TRUE); 709dc0f59e5SAli Bahrami } 710dc0f59e5SAli Bahrami 711dc0f59e5SAli Bahrami 712dc0f59e5SAli Bahrami /* 713dc0f59e5SAli Bahrami * Extract every object in the given archive directly without going through 714dc0f59e5SAli Bahrami * the symbol table. 715dc0f59e5SAli Bahrami * 716dc0f59e5SAli Bahrami * entry: 717dc0f59e5SAli Bahrami * name - Name of archive 718dc0f59e5SAli Bahrami * fd - Open file descriptor for archive 719dc0f59e5SAli Bahrami * adp - Archive descriptor 720dc0f59e5SAli Bahrami * ofl - output descriptor 721dc0f59e5SAli Bahrami * found - Address of variable to set to TRUE if any objects are extracted 722dc0f59e5SAli Bahrami * rej - Rejection descriptor to pass to ld_process_ifl(). 723dc0f59e5SAli Bahrami * 724dc0f59e5SAli Bahrami * exit: 725dc0f59e5SAli Bahrami * Returns FALSE on fatal error. On success, *found will be TRUE 726dc0f59e5SAli Bahrami * if any object was extracted, rej will be set if any object 727dc0f59e5SAli Bahrami * was rejected, and TRUE is returned. 728dc0f59e5SAli Bahrami */ 729dc0f59e5SAli Bahrami static Boolean 7302a93c375SAli Bahrami ar_extract_all(const char *name, int fd, Ar_desc *adp, Ofl_desc *ofl, 731dc0f59e5SAli Bahrami Boolean *found, Rej_desc *rej) 732dc0f59e5SAli Bahrami { 733dc0f59e5SAli Bahrami Elf_Cmd cmd = ELF_C_READ; 734dc0f59e5SAli Bahrami Elf *arelf; 735dc0f59e5SAli Bahrami const char *arname, *arpath; 7362a93c375SAli Bahrami size_t off, next_off; 737dc0f59e5SAli Bahrami 738dc0f59e5SAli Bahrami DBG_CALL(Dbg_file_ar(ofl->ofl_lml, name, FALSE)); 739dc0f59e5SAli Bahrami 740dc0f59e5SAli Bahrami while ((arelf = elf_begin(fd, cmd, adp->ad_elf)) != NULL) { 741dc0f59e5SAli Bahrami /* 742dc0f59e5SAli Bahrami * Call elf_next() so that the next call to elf_begin() will 743dc0f59e5SAli Bahrami * fetch the archive member following this one. We do this now 744dc0f59e5SAli Bahrami * because it simplifies the logic below, and because the 7452a93c375SAli Bahrami * support libraries called below can set our handle to NULL. 746dc0f59e5SAli Bahrami */ 747dc0f59e5SAli Bahrami cmd = elf_next(arelf); 748dc0f59e5SAli Bahrami 7492a93c375SAli Bahrami /* Get member filename */ 7502a93c375SAli Bahrami if ((arname = ar_member_name(name, arelf, ofl)) == NULL) 751dc0f59e5SAli Bahrami return (FALSE); 7522a93c375SAli Bahrami 7532a93c375SAli Bahrami /* 7542a93c375SAli Bahrami * Skip the symbol table, string table, or any other special 7552a93c375SAli Bahrami * archive member. These all start with a '/' character. 7562a93c375SAli Bahrami */ 7572a93c375SAli Bahrami if (*arname == '/') { 7582a93c375SAli Bahrami (void) elf_end(arelf); 759dc0f59e5SAli Bahrami continue; 760dc0f59e5SAli Bahrami } 761dc0f59e5SAli Bahrami 7622a93c375SAli Bahrami /* Obtain archive member offset within the file */ 7632a93c375SAli Bahrami off = _elf_getarhdrbase(arelf); 7642a93c375SAli Bahrami 7652a93c375SAli Bahrami /* 7662a93c375SAli Bahrami * ld_sup_open() will reset the current iteration point for 7672a93c375SAli Bahrami * the archive to point at this member rather than the next 7682a93c375SAli Bahrami * one for the benefit of the support libraries. Since 7692a93c375SAli Bahrami * this loop relies on the current position not changing 7702a93c375SAli Bahrami * underneath it, we save and restore the current 7712a93c375SAli Bahrami * position around the support library call. 7722a93c375SAli Bahrami */ 7732a93c375SAli Bahrami next_off = _elf_getnextoff(adp->ad_elf); 7742a93c375SAli Bahrami 7752a93c375SAli Bahrami /* Construct the member's full pathname */ 776*875546acSRichard Lowe if ((arpath = ar_member_path(name, arname, ofl)) == NULL) 777*875546acSRichard Lowe return (FALSE); 7782a93c375SAli Bahrami 7792a93c375SAli Bahrami /* 7802a93c375SAli Bahrami * Determine whether the support libraries wish to process 7812a93c375SAli Bahrami * this open. See comments in ld_process_open(). 7822a93c375SAli Bahrami */ 7832a93c375SAli Bahrami ld_sup_open(ofl, &arpath, &arname, &fd, 7842a93c375SAli Bahrami (FLG_IF_EXTRACT | FLG_IF_NEEDED), &arelf, adp->ad_elf, 7852a93c375SAli Bahrami off, elf_kind(arelf)); 7862a93c375SAli Bahrami (void) elf_rand(adp->ad_elf, next_off); 7872a93c375SAli Bahrami if (arelf == NULL) 7882a93c375SAli Bahrami continue; 7892a93c375SAli Bahrami 790dc0f59e5SAli Bahrami DBG_CALL(Dbg_syms_ar_force(ofl->ofl_lml, name, arname)); 7912a93c375SAli Bahrami switch (ar_input(fd, adp, ofl, arelf, arpath, rej)) { 792dc0f59e5SAli Bahrami case S_ERROR: 793dc0f59e5SAli Bahrami return (FALSE); 794dc0f59e5SAli Bahrami case 0: 795dc0f59e5SAli Bahrami continue; 796dc0f59e5SAli Bahrami } 797dc0f59e5SAli Bahrami 798dc0f59e5SAli Bahrami *found = TRUE; 799dc0f59e5SAli Bahrami 800dc0f59e5SAli Bahrami } 801dc0f59e5SAli Bahrami 802dc0f59e5SAli Bahrami /* 803dc0f59e5SAli Bahrami * As this archive was extracted by -z allextract, the ar_aux table 804dc0f59e5SAli Bahrami * and elf descriptor can be freed. Set ad_elf to NULL to mark the 805dc0f59e5SAli Bahrami * archive is completely processed. 806dc0f59e5SAli Bahrami */ 807dc0f59e5SAli Bahrami (void) elf_end(adp->ad_elf); 808dc0f59e5SAli Bahrami adp->ad_elf = NULL; 809dc0f59e5SAli Bahrami 810dc0f59e5SAli Bahrami return (TRUE); 811dc0f59e5SAli Bahrami } 812dc0f59e5SAli Bahrami 813dc0f59e5SAli Bahrami 814dc0f59e5SAli Bahrami /* 815dc0f59e5SAli Bahrami * Process the given archive and extract objects for inclusion into 816dc0f59e5SAli Bahrami * the link. 817dc0f59e5SAli Bahrami * 818dc0f59e5SAli Bahrami * entry: 819dc0f59e5SAli Bahrami * name - Name of archive 820dc0f59e5SAli Bahrami * fd - Open file descriptor for archive 821dc0f59e5SAli Bahrami * adp - Archive descriptor 822dc0f59e5SAli Bahrami * ofl - output descriptor 823dc0f59e5SAli Bahrami * 824dc0f59e5SAli Bahrami * exit: 825dc0f59e5SAli Bahrami * Returns FALSE on fatal error, TRUE otherwise. 826dc0f59e5SAli Bahrami */ 827dc0f59e5SAli Bahrami Boolean 828dc0f59e5SAli Bahrami ld_process_archive(const char *name, int fd, Ar_desc *adp, Ofl_desc *ofl) 829dc0f59e5SAli Bahrami { 830dc0f59e5SAli Bahrami Boolean found = FALSE; 831dc0f59e5SAli Bahrami Rej_desc rej = { 0 }; 832dc0f59e5SAli Bahrami 833dc0f59e5SAli Bahrami /* 834dc0f59e5SAli Bahrami * If a fatal error condition has been set there's really no point in 835dc0f59e5SAli Bahrami * processing the archive further. Having got to this point we have at 836dc0f59e5SAli Bahrami * least established that the archive exists (thus verifying that the 837dc0f59e5SAli Bahrami * command line options that got us to this archive are correct). Very 838dc0f59e5SAli Bahrami * large archives can take a significant time to process, therefore 839dc0f59e5SAli Bahrami * continuing on from here may significantly delay the fatal error 840dc0f59e5SAli Bahrami * message the user is already set to receive. 841dc0f59e5SAli Bahrami */ 842dc0f59e5SAli Bahrami if (ofl->ofl_flags & FLG_OF_FATAL) 843dc0f59e5SAli Bahrami return (TRUE); 844dc0f59e5SAli Bahrami 845dc0f59e5SAli Bahrami /* 846dc0f59e5SAli Bahrami * If this archive was processed with -z allextract, then all members 847dc0f59e5SAli Bahrami * have already been extracted. 848dc0f59e5SAli Bahrami */ 849dc0f59e5SAli Bahrami if (adp->ad_elf == NULL) 850dc0f59e5SAli Bahrami return (TRUE); 851dc0f59e5SAli Bahrami 852dc0f59e5SAli Bahrami if (ofl->ofl_flags1 & FLG_OF1_ALLEXRT) { 8532a93c375SAli Bahrami if (!ar_extract_all(name, fd, adp, ofl, &found, &rej)) 854dc0f59e5SAli Bahrami return (FALSE); 855dc0f59e5SAli Bahrami } else { 8562a93c375SAli Bahrami if (!ar_extract_bysym(name, fd, adp, ofl, &found, &rej)) 857dc0f59e5SAli Bahrami return (FALSE); 858dc0f59e5SAli Bahrami } 859dc0f59e5SAli Bahrami 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * If no objects have been found in the archive test for any rejections 8627c478bd9Sstevel@tonic-gate * and if one had occurred issue a warning - its possible a user has 8637c478bd9Sstevel@tonic-gate * pointed at an archive containing the wrong class of elf members. 8647c478bd9Sstevel@tonic-gate */ 865a6d4d7d5SRod Evans if ((found == 0) && rej.rej_type) { 866de777a60Sab196087 Conv_reject_desc_buf_t rej_buf; 867de777a60Sab196087 8681007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(reject[rej.rej_type]), 869de777a60Sab196087 rej.rej_name ? rej.rej_name : MSG_INTL(MSG_STR_UNKNOWN), 870ba2be530Sab196087 conv_reject_desc(&rej, &rej_buf, ld_targ.t_m.m_mach)); 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate 874dc0f59e5SAli Bahrami return (TRUE); 8757c478bd9Sstevel@tonic-gate } 876