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
process_member(Ar_mem * amp,const char * name,Sym_desc * sdp,Ofl_desc * ofl)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 *
ld_ar_setup(const char * name,Elf * elf,Ofl_desc * ofl)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
ld_ar_member(Ar_desc * adp,Elf_Arsym * arsym,Ar_aux * aup,Ar_mem * amp)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 *
ar_member_name(const char * name,Elf * arelf,Ofl_desc * ofl)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 *
ar_member_path(const char * name,const char * arname,Ofl_desc * ofl)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
ar_input(int fd,Ar_desc * adp,Ofl_desc * ofl,Elf * arelf,const char * arpath,Rej_desc * rej)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
ar_extract_bysym(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl,Boolean * found,Rej_desc * rej)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
ar_extract_all(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl,Boolean * found,Rej_desc * rej)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
ld_process_archive(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl)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