1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1988 AT&T
24 * All Rights Reserved
25 *
26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27 */
28
29 /*
30 * Library processing
31 */
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <ar.h>
36 #include <debug.h>
37 #include "msg.h"
38 #include "_libld.h"
39
40 /*
41 * Archive members are typically extracted to resolve an existing undefined
42 * reference. However, other symbol definitions can cause archive members to
43 * be processed to determine if the archive member provides a more appropriate
44 * definition. This routine processes the archive member to determine if the
45 * member is really required.
46 *
47 * i. Tentative symbols may cause the extraction of an archive member.
48 * If the archive member has a strong defined symbol it will be used.
49 * If the archive member simply contains another tentative definition,
50 * or a defined function symbol, then it will not be used.
51 *
52 * ii. A symbol reference may define a hidden or protected visibility. The
53 * reference can only be bound to a definition within a relocatable object
54 * for this restricted visibility to be satisfied. If the archive member
55 * provides a definition of the same symbol type, this definition is
56 * taken. The visibility of the defined symbol is irrelevant, as the most
57 * restrictive visibility of the reference and the definition will be
58 * applied to the final symbol.
59 *
60 * exit:
61 * Returns 1 if there is a match, 0 if no match is seen, and S_ERROR if an
62 * error occurred.
63 */
64 static uintptr_t
process_member(Ar_mem * amp,const char * name,Sym_desc * sdp,Ofl_desc * ofl)65 process_member(Ar_mem *amp, const char *name, Sym_desc *sdp, Ofl_desc *ofl)
66 {
67 Sym *syms, *osym = sdp->sd_sym;
68 Xword symn, cnt;
69 char *strs;
70
71 /*
72 * Find the first symbol table in the archive member, obtain its
73 * data buffer and determine the number of global symbols (Note,
74 * there must be a symbol table present otherwise the archive would
75 * never have been able to generate its own symbol entry for this
76 * member).
77 */
78 if (amp->am_syms == NULL) {
79 Elf_Scn *scn = NULL;
80 Shdr *shdr;
81 Elf_Data *data;
82
83 while (scn = elf_nextscn(amp->am_elf, scn)) {
84 if ((shdr = elf_getshdr(scn)) == NULL) {
85 ld_eprintf(ofl, ERR_ELF,
86 MSG_INTL(MSG_ELF_GETSHDR), amp->am_path);
87 return (S_ERROR);
88 }
89 if ((shdr->sh_type == SHT_SYMTAB) ||
90 (shdr->sh_type == SHT_DYNSYM))
91 break;
92 }
93 if ((data = elf_getdata(scn, NULL)) == NULL) {
94 ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETDATA),
95 amp->am_path);
96 return (S_ERROR);
97 }
98 syms = (Sym *)data->d_buf;
99 syms += shdr->sh_info;
100 symn = shdr->sh_size / shdr->sh_entsize;
101 symn -= shdr->sh_info;
102
103 /*
104 * Get the data for the associated string table.
105 */
106 if ((scn = elf_getscn(amp->am_elf, (size_t)shdr->sh_link)) ==
107 NULL) {
108 ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETSCN),
109 amp->am_path);
110 return (S_ERROR);
111 }
112 if ((data = elf_getdata(scn, NULL)) == NULL) {
113 ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETDATA),
114 amp->am_path);
115 return (S_ERROR);
116 }
117 strs = data->d_buf;
118
119 /*
120 * Initialize the archive member structure in case we have to
121 * come through here again.
122 */
123 amp->am_syms = syms;
124 amp->am_strs = strs;
125 amp->am_symn = symn;
126 } else {
127 syms = amp->am_syms;
128 strs = amp->am_strs;
129 symn = amp->am_symn;
130 }
131
132 /*
133 * Loop through the symbol table entries looking for a match for the
134 * original symbol.
135 */
136 for (cnt = 0; cnt < symn; syms++, cnt++) {
137 Word shndx;
138
139 if ((shndx = syms->st_shndx) == SHN_UNDEF)
140 continue;
141
142 if (osym->st_shndx == SHN_COMMON) {
143 /*
144 * Determine whether a tentative symbol definition
145 * should be overridden.
146 */
147 if ((shndx == SHN_ABS) || (shndx == SHN_COMMON) ||
148 (ELF_ST_TYPE(syms->st_info) == STT_FUNC))
149 continue;
150
151 /*
152 * A historic detail requires that a weak definition
153 * within an archive will not override a strong
154 * definition (see sym_realtent() resolution and ABI
155 * symbol binding description - page 4-27).
156 */
157 if ((ELF_ST_BIND(syms->st_info) == STB_WEAK) &&
158 (ELF_ST_BIND(osym->st_info) != STB_WEAK))
159 continue;
160 } else {
161 /*
162 * Determine whether a restricted visibility reference
163 * should be overridden. Don't worry about the
164 * visibility of the archive member definition, nor
165 * whether it is weak or global. Any definition is
166 * better than a binding to an external shared object
167 * (which is the only event that must presently exist
168 * for us to be here looking for a better alternative).
169 */
170 if (ELF_ST_TYPE(syms->st_info) !=
171 ELF_ST_TYPE(osym->st_info))
172 continue;
173 }
174
175 if (strcmp(strs + syms->st_name, name) == 0)
176 return (1);
177 }
178 return (0);
179 }
180
181 /*
182 * Create an archive descriptor. By maintaining a list of archives any
183 * duplicate occurrences of the same archive specified by the user enable us to
184 * pick off where the last processing finished.
185 */
186 Ar_desc *
ld_ar_setup(const char * name,Elf * elf,Ofl_desc * ofl)187 ld_ar_setup(const char *name, Elf *elf, Ofl_desc *ofl)
188 {
189 Ar_desc * adp;
190 size_t number;
191 Elf_Arsym * start;
192
193 /*
194 * Unless, -z allextract is specified, get the archive symbol table
195 * if one exists, and ignore the file with a warning message otherwise.
196 */
197 if (ofl->ofl_flags1 & FLG_OF1_ALLEXRT) {
198 start = NULL;
199 } else if ((start = elf_getarsym(elf, &number)) == NULL) {
200 if (elf_errno())
201 ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETARSYM),
202 name);
203 else
204 ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ELF_ARSYM),
205 name);
206 return (0);
207 }
208
209 /*
210 * As this is a new archive reference establish a new descriptor.
211 */
212 if ((adp = libld_malloc(sizeof (Ar_desc))) == NULL)
213 return ((Ar_desc *)S_ERROR);
214 adp->ad_name = name;
215 adp->ad_elf = elf;
216 adp->ad_start = start;
217 adp->ad_allextract = FALSE;
218 if (start) {
219 adp->ad_aux = libld_calloc(number, sizeof (Ar_aux));
220 if (adp->ad_aux == NULL)
221 return ((Ar_desc *)S_ERROR);
222 } else {
223 adp->ad_aux = NULL;
224 }
225
226 /*
227 * Retain any command line options that are applicable to archive
228 * extraction in case we have to rescan this archive later.
229 */
230 adp->ad_flags = ofl->ofl_flags1 & MSK_OF1_ARCHIVE;
231
232 ofl->ofl_arscnt++;
233
234 /*
235 * Add this new descriptor to the list of archives.
236 */
237 if (aplist_append(&ofl->ofl_ars, adp, AL_CNT_OFL_LIBS) == NULL)
238 return ((Ar_desc *)S_ERROR);
239 else
240 return (adp);
241 }
242
243 /*
244 * For each archive descriptor, maintain an `Ar_aux' table to parallel the
245 * archive symbol table (returned from elf_getarsym(3elf)). Use this table to
246 * hold a `Sym_desc' for each symbol (thus reducing the number of
247 * ld_sym_find()'s), and to hold the `Ar_mem' pointer. The `Ar_mem' element
248 * can have one of three values indicating the state of the archive member
249 * associated with the offset for this symbol table entry:
250 *
251 * 0 indicates that the member has not been processed.
252 *
253 * FLG_ARMEM_PROC
254 * indicates that the member has been processed.
255 *
256 * addr indicates that the member has been investigated to determine if
257 * it contained a symbol definition we need, but was found not to
258 * be a candidate for extraction. In this case the members
259 * structure is maintained for possible later use.
260 *
261 * Each time we process an archive member we use its offset value to scan this
262 * `Ar_aux' list. If the member has been extracted, each entry with the same
263 * offset has its `Ar_mem' pointer set to FLG_ARMEM_PROC. Thus if we cycle back
264 * through the archive symbol table we will ignore these symbols as they will
265 * have already been added to the output image. If a member has been processed
266 * but found not to contain a symbol we need, each entry with the same offset
267 * has its `Ar_mem' pointer set to the member structures address.
268 */
269 void
ld_ar_member(Ar_desc * adp,Elf_Arsym * arsym,Ar_aux * aup,Ar_mem * amp)270 ld_ar_member(Ar_desc * adp, Elf_Arsym * arsym, Ar_aux * aup, Ar_mem * amp)
271 {
272 Elf_Arsym * _arsym = arsym;
273 Ar_aux * _aup = aup;
274 size_t _off = arsym->as_off;
275
276 if (adp->ad_start == NULL)
277 return;
278
279 /*
280 * Note: This algorithm assumes that the archive symbol table is
281 * built from the member objects, in the same order as those
282 * members are found in the archive. As such, the symbols for a
283 * given member will all cluster together. If this is not true,
284 * we will fail to mark some symbols. In that case, archive
285 * processing may be less efficient than it would be otherwise.
286 */
287
288 if (_arsym != adp->ad_start) {
289 do {
290 _arsym--;
291 _aup--;
292 if (_arsym->as_off != _off)
293 break;
294 _aup->au_mem = amp;
295 } while (_arsym != adp->ad_start);
296 }
297
298 _arsym = arsym;
299 _aup = aup;
300
301 do {
302 if (_arsym->as_off != _off)
303 break;
304 _aup->au_mem = amp;
305 _arsym++;
306 _aup++;
307 } while (_arsym->as_name);
308 }
309
310 /*
311 * Return the archive member's name.
312 *
313 * entry:
314 * name - Name of archive
315 * arelf - ELF descriptor for archive member.
316 * ofl - output descriptor
317 *
318 * exit:
319 * Returns pointer to archive member name on success, NULL on error.
320 */
321 static const char *
ar_member_name(const char * name,Elf * arelf,Ofl_desc * ofl)322 ar_member_name(const char *name, Elf *arelf, Ofl_desc *ofl)
323 {
324 Elf_Arhdr *arhdr;
325
326 if ((arhdr = elf_getarhdr(arelf)) == NULL) {
327 ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETARHDR), name);
328 return (NULL);
329 }
330 return (arhdr->ar_name);
331 }
332
333 /*
334 * Construct the member's full pathname, using the format "%s(%s)".
335 *
336 * entry:
337 * name - Name of archive
338 * arname - Name of archive member
339 * ofl - output descriptor
340 * exit:
341 * Returns pointer to constructed pathname on success, NULL on error.
342 */
343 static const char *
ar_member_path(const char * name,const char * arname,Ofl_desc * ofl)344 ar_member_path(const char *name, const char *arname, Ofl_desc *ofl)
345 {
346 size_t len;
347 char *path;
348
349 len = strlen(name) + strlen(arname) + 3;
350 if ((path = libld_malloc(len)) == NULL) {
351 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYS_MALLOC),
352 strerror(errno));
353 return (NULL);
354 }
355 (void) snprintf(path, len, MSG_ORIG(MSG_FMT_ARMEM), name, arname);
356 return (path);
357 }
358
359 /*
360 * Input the specified archive member to the link.
361 *
362 * entry:
363 * fd - Open file descriptor for archive
364 * adp - Archive descriptor
365 * ofl - output descriptor
366 * arelf - ELF descriptor for archive member.
367 * arpath - Address of pointer to be set to constructed path name
368 * for object.
369 * rej - Rejection descriptor to pass to ld_process_ifl().
370 *
371 * exit:
372 * This routine can return one of the following:
373 * S_ERROR: Fatal error encountered.
374 * 0: Object was rejected, and should be ignored.
375 * rej will carry the rejection information.
376 * 1: The archive member has been input to the link.
377 */
378 static uintptr_t
ar_input(int fd,Ar_desc * adp,Ofl_desc * ofl,Elf * arelf,const char * arpath,Rej_desc * rej)379 ar_input(int fd, Ar_desc *adp, Ofl_desc *ofl, Elf *arelf,
380 const char *arpath, Rej_desc *rej)
381 {
382 Rej_desc _rej = { 0 };
383
384 switch (ld_process_ifl(arpath, NULL, fd, arelf,
385 (FLG_IF_EXTRACT | FLG_IF_NEEDED), ofl, &_rej, NULL)) {
386 case S_ERROR:
387 return (S_ERROR);
388 case 0:
389 /*
390 * If this member is rejected maintain the first rejection
391 * error for possible later display.
392 */
393 if (_rej.rej_type) {
394 if (rej->rej_type == 0) {
395 rej->rej_type = _rej.rej_type;
396 rej->rej_info = _rej.rej_info;
397 rej->rej_name = arpath;
398 }
399 (void) elf_end(arelf);
400 return (0);
401 }
402 }
403
404 /*
405 * Indicate that the extracted member is in use. This
406 * enables debugging diags, and indicates that a further
407 * rescan of all archives may be necessary.
408 */
409 ofl->ofl_flags1 |= FLG_OF1_EXTRACT;
410 adp->ad_flags |= FLG_ARD_EXTRACT;
411 return (1);
412 }
413
414 /*
415 * Data structure to indicate whether a symbol is visible for the purpose
416 * of archive extraction.
417 */
418 static const Boolean
419 sym_vis[STV_NUM] = {
420 TRUE, /* STV_DEFAULT */
421 FALSE, /* STV_INTERNAL */
422 FALSE, /* STV_HIDDEN */
423 FALSE, /* STV_PROTECTED */
424 TRUE, /* STV_EXPORTED */
425 TRUE, /* STV_SINGLETON */
426 FALSE /* STV_ELIMINATE */
427 };
428 #if STV_NUM != (STV_ELIMINATE + 1)
429 #error "STV_NUM has grown. Update sym_vis[]."
430 #endif
431
432 /*
433 * Read the archive symbol table. For each symbol in the table, determine
434 * whether that symbol satisfies an unresolved reference, tentative reference,
435 * or a reference that expects hidden or protected visibility. If so, the
436 * corresponding object from the archive is processed. The archive symbol
437 * table is searched until we go through a complete pass without satisfying any
438 * unresolved symbols
439 *
440 * entry:
441 * name - Name of archive
442 * fd - Open file descriptor for archive
443 * adp - Archive descriptor
444 * ofl - output descriptor
445 * found - Address of variable to set to TRUE if any objects are extracted
446 * rej - Rejection descriptor to pass to ld_process_ifl().
447 *
448 * exit:
449 * Returns FALSE on fatal error. On success, *found will be TRUE
450 * if any object was extracted, rej will be set if any object
451 * was rejected, and TRUE is returned.
452 */
453 static Boolean
ar_extract_bysym(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl,Boolean * found,Rej_desc * rej)454 ar_extract_bysym(const char *name, int fd, Ar_desc *adp,
455 Ofl_desc *ofl, Boolean *found, Rej_desc *rej)
456 {
457 Elf_Arsym * arsym;
458 Elf * arelf;
459 Ar_aux * aup;
460 Sym_desc * sdp;
461 const char *arname, *arpath;
462 Boolean again = FALSE;
463 uintptr_t err;
464
465 /*
466 * An archive without a symbol table should not reach this function,
467 * because it can only get past ld_ar_setup() in the case where
468 * the archive is first seen under the influence of '-z allextract'.
469 * That will cause the entire archive to be extracted, and any
470 * subsequent reference to the archive will be ignored by
471 * ld_process_archive().
472 */
473 if (adp->ad_start == NULL) {
474 assert(adp->ad_start != NULL);
475 return (TRUE);
476 }
477
478 /*
479 * Loop through archive symbol table until we make a complete pass
480 * without satisfying an unresolved reference. For each archive
481 * symbol, see if there is a symbol with the same name in ld's
482 * symbol table. If so, and if that symbol is still unresolved or
483 * tentative, process the corresponding archive member.
484 */
485 do {
486 DBG_CALL(Dbg_file_ar(ofl->ofl_lml, name, again));
487 DBG_CALL(Dbg_syms_ar_title(ofl->ofl_lml, name, again));
488 again = FALSE;
489
490 for (arsym = adp->ad_start, aup = adp->ad_aux; arsym->as_name;
491 ++arsym, ++aup) {
492 Ar_mem *amp;
493 Sym *sym;
494 Boolean visible = TRUE;
495 Boolean vers;
496 Ifl_desc *ifl;
497
498 /*
499 * If the auxiliary members value indicates that this
500 * member has been processed then this symbol will have
501 * been added to the output file image already or the
502 * object was rejected in which case we don't want to
503 * process it again.
504 */
505 if (aup->au_mem == FLG_ARMEM_PROC)
506 continue;
507
508 /*
509 * If the auxiliary symbol element is non-zero lookup
510 * the symbol from the internal symbol table.
511 */
512 if ((sdp = aup->au_syms) == NULL) {
513 if ((sdp = ld_sym_find(arsym->as_name,
514 /* LINTED */
515 (Word)arsym->as_hash, NULL, ofl)) == NULL) {
516 DBG_CALL(Dbg_syms_ar_skip(ofl->ofl_lml,
517 name, arsym));
518 continue;
519 }
520 aup->au_syms = sdp;
521 }
522
523 /*
524 * With '-z allextract', all members will be extracted.
525 *
526 * This archive member is a candidate for extraction if
527 * the internal symbol originates from an explicit file,
528 * and represents an undefined or tentative symbol.
529 *
530 * By default, weak references do not cause archive
531 * extraction, however the -zweakextract flag overrides
532 * this default.
533 *
534 * If this symbol has already been bound to a versioned
535 * shared object, but the shared objects version is not
536 * available, then a definition of this symbol from
537 * within the archive is a better candidate. Similarly,
538 * if this symbol has been bound to a shared object, but
539 * the original reference expected hidden or protected
540 * visibility, then a definition of this symbol from
541 * within the archive is a better candidate.
542 */
543 vers = TRUE;
544 ifl = sdp->sd_file;
545
546 sym = sdp->sd_sym;
547
548 if (sdp->sd_ref == REF_DYN_NEED) {
549 uchar_t vis;
550
551 if (ifl->ifl_vercnt) {
552 Word vndx;
553 Ver_index *vip;
554
555 vndx = sdp->sd_aux->sa_dverndx;
556 vip = &ifl->ifl_verndx[vndx];
557 if (!(vip->vi_flags & FLG_VER_AVAIL))
558 vers = FALSE;
559 }
560
561 vis = ELF_ST_VISIBILITY(sym->st_other);
562 visible = sym_vis[vis];
563 }
564
565 if (((ifl->ifl_flags & FLG_IF_NEEDED) == 0) ||
566 (visible && vers && (sym->st_shndx != SHN_UNDEF) &&
567 (sym->st_shndx != SHN_COMMON)) ||
568 ((ELF_ST_BIND(sym->st_info) == STB_WEAK) &&
569 (!(ofl->ofl_flags1 & FLG_OF1_WEAKEXT)))) {
570 DBG_CALL(Dbg_syms_ar_skip(ofl->ofl_lml,
571 name, arsym));
572 continue;
573 }
574
575 /*
576 * Determine if we have already extracted this member,
577 * and if so reuse the Ar_mem information.
578 */
579 if ((amp = aup->au_mem) != 0) {
580 arelf = amp->am_elf;
581 arname = amp->am_name;
582 arpath = amp->am_path;
583 } else {
584 /*
585 * Set up a new elf descriptor for this member.
586 */
587 if (elf_rand(adp->ad_elf, arsym->as_off) !=
588 arsym->as_off) {
589 ld_eprintf(ofl, ERR_ELF,
590 MSG_INTL(MSG_ELF_ARMEM), name,
591 EC_WORD(arsym->as_off),
592 demangle(arsym->as_name));
593 return (FALSE);
594 }
595
596 if ((arelf = elf_begin(fd, ELF_C_READ,
597 adp->ad_elf)) == NULL) {
598 ld_eprintf(ofl, ERR_ELF,
599 MSG_INTL(MSG_ELF_BEGIN), name);
600 return (FALSE);
601 }
602
603 /* Get member filename */
604 if ((arname = ar_member_name(name, arelf,
605 ofl)) == NULL)
606 return (FALSE);
607
608 /* Construct the member's full pathname */
609 if ((arpath = ar_member_path(name, arname,
610 ofl)) == NULL)
611 return (FALSE);
612
613 /*
614 * Determine whether the support libraries wish
615 * to process this open. See comments in
616 * ld_process_open().
617 */
618 ld_sup_open(ofl, &arpath, &arname, &fd,
619 (FLG_IF_EXTRACT | FLG_IF_NEEDED),
620 &arelf, adp->ad_elf, arsym->as_off,
621 elf_kind(arelf));
622 if (arelf == NULL) {
623 /* Ignore this archive member */
624 aup->au_mem = FLG_ARMEM_PROC;
625 continue;
626 }
627 }
628
629 /*
630 * The symbol for which this archive member is being
631 * processed may provide a better alternative to the
632 * symbol that is presently known. Two cases are
633 * covered:
634 *
635 * i. The present symbol represents tentative data.
636 * The archive member may provide a data
637 * definition symbol.
638 * ii. The present symbol represents a reference that
639 * has seen a definition within a shared object
640 * dependency, but the reference expects to be
641 * reduced to hidden or protected visibility.
642 */
643 if ((sym->st_shndx == SHN_COMMON) ||
644 (visible == FALSE)) {
645 /*
646 * If we don't already have a member structure
647 * allocate one.
648 */
649 if (!amp) {
650 if ((amp = libld_calloc(1,
651 sizeof (Ar_mem))) == NULL)
652 return (FALSE);
653 amp->am_elf = arelf;
654 amp->am_name = arname;
655 amp->am_path = arpath;
656 }
657 DBG_CALL(Dbg_syms_ar_checking(ofl->ofl_lml,
658 name, arname, arsym));
659 if ((err = process_member(amp, arsym->as_name,
660 sdp, ofl)) == S_ERROR)
661 return (FALSE);
662
663 /*
664 * If it turns out that we don't need this
665 * member simply initialize all other auxiliary
666 * entries that match this offset with this
667 * members address. In this way we can resuse
668 * this information if we recurse back to this
669 * symbol.
670 */
671 if (err == 0) {
672 if (aup->au_mem == NULL)
673 ld_ar_member(adp, arsym,
674 aup, amp);
675 continue;
676 }
677 }
678
679 /*
680 * Process the archive member. Retain any error for
681 * return to the caller.
682 */
683 DBG_CALL(Dbg_syms_ar_resolve(ofl->ofl_lml,
684 name, arname, arsym));
685 switch (ar_input(fd, adp, ofl, arelf, arpath,
686 rej)) {
687 case S_ERROR:
688 return (FALSE);
689 case 0:
690 /*
691 * Mark the member as extracted so that we
692 * don't try and process it again on a rescan.
693 */
694 ld_ar_member(adp, arsym, aup, FLG_ARMEM_PROC);
695 continue;
696 }
697
698 /*
699 * Note that this archive has contributed something
700 * during this specific operation, and also signal
701 * the need to rescan the archive.
702 */
703 *found = again = TRUE;
704
705 ld_ar_member(adp, arsym, aup, FLG_ARMEM_PROC);
706 }
707 } while (again);
708
709 return (TRUE);
710 }
711
712
713 /*
714 * Extract every object in the given archive directly without going through
715 * the symbol table.
716 *
717 * entry:
718 * name - Name of archive
719 * fd - Open file descriptor for archive
720 * adp - Archive descriptor
721 * ofl - output descriptor
722 * found - Address of variable to set to TRUE if any objects are extracted
723 * rej - Rejection descriptor to pass to ld_process_ifl().
724 *
725 * exit:
726 * Returns FALSE on fatal error. On success, *found will be TRUE
727 * if any object was extracted, rej will be set if any object
728 * was rejected, and TRUE is returned.
729 */
730 static Boolean
ar_extract_all(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl,Boolean * found,Rej_desc * rej)731 ar_extract_all(const char *name, int fd, Ar_desc *adp, Ofl_desc *ofl,
732 Boolean *found, Rej_desc *rej)
733 {
734 Elf_Cmd cmd = ELF_C_READ;
735 Elf *arelf;
736 const char *arname, *arpath;
737 size_t off, next_off;
738
739 DBG_CALL(Dbg_file_ar(ofl->ofl_lml, name, FALSE));
740
741 while ((arelf = elf_begin(fd, cmd, adp->ad_elf)) != NULL) {
742 /*
743 * Call elf_next() so that the next call to elf_begin() will
744 * fetch the archive member following this one. We do this now
745 * because it simplifies the logic below, and because the
746 * support libraries called below can set our handle to NULL.
747 */
748 cmd = elf_next(arelf);
749
750 /* Get member filename */
751 if ((arname = ar_member_name(name, arelf, ofl)) == NULL)
752 return (FALSE);
753
754 /*
755 * Skip the symbol table, string table, or any other special
756 * archive member. These all start with a '/' character.
757 */
758 if (*arname == '/') {
759 (void) elf_end(arelf);
760 continue;
761 }
762
763 /* Obtain archive member offset within the file */
764 off = _elf_getarhdrbase(arelf);
765
766 /*
767 * ld_sup_open() will reset the current iteration point for
768 * the archive to point at this member rather than the next
769 * one for the benefit of the support libraries. Since
770 * this loop relies on the current position not changing
771 * underneath it, we save and restore the current
772 * position around the support library call.
773 */
774 next_off = _elf_getnextoff(adp->ad_elf);
775
776 /* Construct the member's full pathname */
777 if ((arpath = ar_member_path(name, arname, ofl)) == NULL)
778 return (FALSE);
779
780 /*
781 * Determine whether the support libraries wish to process
782 * this open. See comments in ld_process_open().
783 */
784 ld_sup_open(ofl, &arpath, &arname, &fd,
785 (FLG_IF_EXTRACT | FLG_IF_NEEDED), &arelf, adp->ad_elf,
786 off, elf_kind(arelf));
787 (void) elf_rand(adp->ad_elf, next_off);
788 if (arelf == NULL)
789 continue;
790
791 DBG_CALL(Dbg_syms_ar_force(ofl->ofl_lml, name, arname));
792 switch (ar_input(fd, adp, ofl, arelf, arpath, rej)) {
793 case S_ERROR:
794 return (FALSE);
795 case 0:
796 continue;
797 }
798
799 *found = TRUE;
800 }
801
802 /*
803 * Mark this as having been completely processed, so we don't have do
804 * work harder than necessary.
805 */
806 adp->ad_allextract = TRUE;
807
808 return (TRUE);
809 }
810
811
812 /*
813 * Process the given archive and extract objects for inclusion into
814 * the link.
815 *
816 * entry:
817 * name - Name of archive
818 * fd - Open file descriptor for archive
819 * adp - Archive descriptor
820 * ofl - output descriptor
821 *
822 * exit:
823 * Returns FALSE on fatal error, TRUE otherwise.
824 */
825 Boolean
ld_process_archive(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl)826 ld_process_archive(const char *name, int fd, Ar_desc *adp, Ofl_desc *ofl)
827 {
828 Boolean found = FALSE;
829 Rej_desc rej = { 0 };
830
831 /*
832 * If a fatal error condition has been set there's really no point in
833 * processing the archive further. Having got to this point we have at
834 * least established that the archive exists (thus verifying that the
835 * command line options that got us to this archive are correct). Very
836 * large archives can take a significant time to process, therefore
837 * continuing on from here may significantly delay the fatal error
838 * message the user is already set to receive.
839 */
840 if (ofl->ofl_flags & FLG_OF_FATAL)
841 return (TRUE);
842
843 /*
844 * If this archive was processed with -z allextract, then all members
845 * have already been extracted.
846 */
847 if (adp->ad_allextract == TRUE)
848 return (TRUE);
849
850 if (ofl->ofl_flags1 & FLG_OF1_ALLEXRT) {
851 if (!ar_extract_all(name, fd, adp, ofl, &found, &rej))
852 return (FALSE);
853 } else {
854 if (!ar_extract_bysym(name, fd, adp, ofl, &found, &rej))
855 return (FALSE);
856 }
857
858 /*
859 * If no objects have been found in the archive test for any rejections
860 * and if one had occurred issue a warning - its possible a user has
861 * pointed at an archive containing the wrong class of elf members.
862 */
863 if ((found == 0) && rej.rej_type) {
864 Conv_reject_desc_buf_t rej_buf;
865
866 ld_eprintf(ofl, ERR_WARNING, MSG_INTL(reject[rej.rej_type]),
867 rej.rej_name ? rej.rej_name : MSG_INTL(MSG_STR_UNKNOWN),
868 conv_reject_desc(&rej, &rej_buf, ld_targ.t_m.m_mach));
869 }
870
871 return (TRUE);
872 }
873