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 if (start) {
218 adp->ad_aux = libld_calloc(sizeof (Ar_aux), number);
219 if (adp->ad_aux == NULL)
220 return ((Ar_desc *)S_ERROR);
221 } else {
222 adp->ad_aux = NULL;
223 }
224
225 /*
226 * Retain any command line options that are applicable to archive
227 * extraction in case we have to rescan this archive later.
228 */
229 adp->ad_flags = ofl->ofl_flags1 & MSK_OF1_ARCHIVE;
230
231 ofl->ofl_arscnt++;
232
233 /*
234 * Add this new descriptor to the list of archives.
235 */
236 if (aplist_append(&ofl->ofl_ars, adp, AL_CNT_OFL_LIBS) == NULL)
237 return ((Ar_desc *)S_ERROR);
238 else
239 return (adp);
240 }
241
242 /*
243 * For each archive descriptor, maintain an `Ar_aux' table to parallel the
244 * archive symbol table (returned from elf_getarsym(3e)). Use this table to
245 * hold a `Sym_desc' for each symbol (thus reducing the number of
246 * ld_sym_find()'s), and to hold the `Ar_mem' pointer. The `Ar_mem' element
247 * can have one of three values indicating the state of the archive member
248 * associated with the offset for this symbol table entry:
249 *
250 * 0 indicates that the member has not been processed.
251 *
252 * FLG_ARMEM_PROC
253 * indicates that the member has been processed.
254 *
255 * addr indicates that the member has been investigated to determine if
256 * it contained a symbol definition we need, but was found not to
257 * be a candidate for extraction. In this case the members
258 * structure is maintained for possible later use.
259 *
260 * Each time we process an archive member we use its offset value to scan this
261 * `Ar_aux' list. If the member has been extracted, each entry with the same
262 * offset has its `Ar_mem' pointer set to FLG_ARMEM_PROC. Thus if we cycle back
263 * through the archive symbol table we will ignore these symbols as they will
264 * have already been added to the output image. If a member has been processed
265 * but found not to contain a symbol we need, each entry with the same offset
266 * has its `Ar_mem' pointer set to the member structures address.
267 */
268 void
ld_ar_member(Ar_desc * adp,Elf_Arsym * arsym,Ar_aux * aup,Ar_mem * amp)269 ld_ar_member(Ar_desc * adp, Elf_Arsym * arsym, Ar_aux * aup, Ar_mem * amp)
270 {
271 Elf_Arsym * _arsym = arsym;
272 Ar_aux * _aup = aup;
273 size_t _off = arsym->as_off;
274
275 if (adp->ad_start == NULL)
276 return;
277
278 /*
279 * Note: This algorithm assumes that the archive symbol table is
280 * built from the member objects, in the same order as those
281 * members are found in the archive. As such, the symbols for a
282 * given member will all cluster together. If this is not true,
283 * we will fail to mark some symbols. In that case, archive
284 * processing may be less efficient than it would be otherwise.
285 */
286
287 if (_arsym != adp->ad_start) {
288 do {
289 _arsym--;
290 _aup--;
291 if (_arsym->as_off != _off)
292 break;
293 _aup->au_mem = amp;
294 } while (_arsym != adp->ad_start);
295 }
296
297 _arsym = arsym;
298 _aup = aup;
299
300 do {
301 if (_arsym->as_off != _off)
302 break;
303 _aup->au_mem = amp;
304 _arsym++;
305 _aup++;
306 } while (_arsym->as_name);
307 }
308
309 /*
310 * Return the archive member's name.
311 *
312 * entry:
313 * name - Name of archive
314 * arelf - ELF descriptor for archive member.
315 * ofl - output descriptor
316 *
317 * exit:
318 * Returns pointer to archive member name on success, NULL on error.
319 */
320 static const char *
ar_member_name(const char * name,Elf * arelf,Ofl_desc * ofl)321 ar_member_name(const char *name, Elf *arelf, Ofl_desc *ofl)
322 {
323 Elf_Arhdr *arhdr;
324
325 if ((arhdr = elf_getarhdr(arelf)) == NULL) {
326 ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETARHDR), name);
327 return (NULL);
328 }
329 return (arhdr->ar_name);
330 }
331
332 /*
333 * Construct the member's full pathname, using the format "%s(%s)".
334 *
335 * entry:
336 * name - Name of archive
337 * arname - Name of archive member
338 * ofl - output descriptor
339 * exit:
340 * Returns pointer to constructed pathname on success, NULL on error.
341 */
342 static const char *
ar_member_path(const char * name,const char * arname,Ofl_desc * ofl)343 ar_member_path(const char *name, const char *arname, Ofl_desc *ofl)
344 {
345 size_t len;
346 char *path;
347
348 len = strlen(name) + strlen(arname) + 3;
349 if ((path = libld_malloc(len)) == NULL) {
350 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYS_MALLOC),
351 strerror(errno));
352 return (NULL);
353 }
354 (void) snprintf(path, len, MSG_ORIG(MSG_FMT_ARMEM), name, arname);
355 return (path);
356 }
357
358 /*
359 * Input the specified archive member to the link.
360 *
361 * entry:
362 * fd - Open file descriptor for archive
363 * adp - Archive descriptor
364 * ofl - output descriptor
365 * arelf - ELF descriptor for archive member.
366 * arpath - Address of pointer to be set to constructed path name
367 * for object.
368 * rej - Rejection descriptor to pass to ld_process_ifl().
369 *
370 * exit:
371 * This routine can return one of the following:
372 * S_ERROR: Fatal error encountered.
373 * 0: Object was rejected, and should be ignored.
374 * rej will carry the rejection information.
375 * 1: The archive member has been input to the link.
376 */
377 static uintptr_t
ar_input(int fd,Ar_desc * adp,Ofl_desc * ofl,Elf * arelf,const char * arpath,Rej_desc * rej)378 ar_input(int fd, Ar_desc *adp, Ofl_desc *ofl, Elf *arelf,
379 const char *arpath, Rej_desc *rej)
380 {
381 Rej_desc _rej = { 0 };
382
383 switch (ld_process_ifl(arpath, NULL, fd, arelf,
384 (FLG_IF_EXTRACT | FLG_IF_NEEDED), ofl, &_rej, NULL)) {
385 case S_ERROR:
386 return (S_ERROR);
387 case 0:
388 /*
389 * If this member is rejected maintain the first rejection
390 * error for possible later display.
391 */
392 if (_rej.rej_type) {
393 if (rej->rej_type == 0) {
394 rej->rej_type = _rej.rej_type;
395 rej->rej_info = _rej.rej_info;
396 rej->rej_name = arpath;
397 }
398 (void) elf_end(arelf);
399 return (0);
400 }
401 }
402
403 /*
404 * Indicate that the extracted member is in use. This
405 * enables debugging diags, and indicates that a further
406 * rescan of all archives may be necessary.
407 */
408 ofl->ofl_flags1 |= FLG_OF1_EXTRACT;
409 adp->ad_flags |= FLG_ARD_EXTRACT;
410 return (1);
411 }
412
413 /*
414 * Data structure to indicate whether a symbol is visible for the purpose
415 * of archive extraction.
416 */
417 static const Boolean
418 sym_vis[STV_NUM] = {
419 TRUE, /* STV_DEFAULT */
420 FALSE, /* STV_INTERNAL */
421 FALSE, /* STV_HIDDEN */
422 FALSE, /* STV_PROTECTED */
423 TRUE, /* STV_EXPORTED */
424 TRUE, /* STV_SINGLETON */
425 FALSE /* STV_ELIMINATE */
426 };
427 #if STV_NUM != (STV_ELIMINATE + 1)
428 #error "STV_NUM has grown. Update sym_vis[]."
429 #endif
430
431 /*
432 * Read the archive symbol table. For each symbol in the table, determine
433 * whether that symbol satisfies an unresolved reference, tentative reference,
434 * or a reference that expects hidden or protected visibility. If so, the
435 * corresponding object from the archive is processed. The archive symbol
436 * table is searched until we go through a complete pass without satisfying any
437 * unresolved symbols
438 *
439 * entry:
440 * name - Name of archive
441 * fd - Open file descriptor for archive
442 * adp - Archive descriptor
443 * ofl - output descriptor
444 * found - Address of variable to set to TRUE if any objects are extracted
445 * rej - Rejection descriptor to pass to ld_process_ifl().
446 *
447 * exit:
448 * Returns FALSE on fatal error. On success, *found will be TRUE
449 * if any object was extracted, rej will be set if any object
450 * was rejected, and TRUE is returned.
451 */
452 static Boolean
ar_extract_bysym(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl,Boolean * found,Rej_desc * rej)453 ar_extract_bysym(const char *name, int fd, Ar_desc *adp,
454 Ofl_desc *ofl, Boolean *found, Rej_desc *rej)
455 {
456 Elf_Arsym * arsym;
457 Elf * arelf;
458 Ar_aux * aup;
459 Sym_desc * sdp;
460 const char *arname, *arpath;
461 Boolean again = FALSE;
462 uintptr_t err;
463
464 /*
465 * An archive without a symbol table should not reach this function,
466 * because it can only get past ld_ar_setup() in the case where
467 * the archive is first seen under the influence of '-z allextract'.
468 * That will cause the entire archive to be extracted, and any
469 * subsequent reference to the archive will be ignored by
470 * ld_process_archive().
471 */
472 if (adp->ad_start == NULL) {
473 assert(adp->ad_start != NULL);
474 return (TRUE);
475 }
476
477 /*
478 * Loop through archive symbol table until we make a complete pass
479 * without satisfying an unresolved reference. For each archive
480 * symbol, see if there is a symbol with the same name in ld's
481 * symbol table. If so, and if that symbol is still unresolved or
482 * tentative, process the corresponding archive member.
483 */
484 do {
485 DBG_CALL(Dbg_file_ar(ofl->ofl_lml, name, again));
486 DBG_CALL(Dbg_syms_ar_title(ofl->ofl_lml, name, again));
487 again = FALSE;
488
489 for (arsym = adp->ad_start, aup = adp->ad_aux; arsym->as_name;
490 ++arsym, ++aup) {
491 Ar_mem *amp;
492 Sym *sym;
493 Boolean visible = TRUE;
494 Boolean vers;
495 Ifl_desc *ifl;
496
497 /*
498 * If the auxiliary members value indicates that this
499 * member has been processed then this symbol will have
500 * been added to the output file image already or the
501 * object was rejected in which case we don't want to
502 * process it again.
503 */
504 if (aup->au_mem == FLG_ARMEM_PROC)
505 continue;
506
507 /*
508 * If the auxiliary symbol element is non-zero lookup
509 * the symbol from the internal symbol table.
510 */
511 if ((sdp = aup->au_syms) == NULL) {
512 if ((sdp = ld_sym_find(arsym->as_name,
513 /* LINTED */
514 (Word)arsym->as_hash, NULL, ofl)) == NULL) {
515 DBG_CALL(Dbg_syms_ar_skip(ofl->ofl_lml,
516 name, arsym));
517 continue;
518 }
519 aup->au_syms = sdp;
520 }
521
522 /*
523 * With '-z allextract', all members will be extracted.
524 *
525 * This archive member is a candidate for extraction if
526 * the internal symbol originates from an explicit file,
527 * and represents an undefined or tentative symbol.
528 *
529 * By default, weak references do not cause archive
530 * extraction, however the -zweakextract flag overrides
531 * this default.
532 *
533 * If this symbol has already been bound to a versioned
534 * shared object, but the shared objects version is not
535 * available, then a definition of this symbol from
536 * within the archive is a better candidate. Similarly,
537 * if this symbol has been bound to a shared object, but
538 * the original reference expected hidden or protected
539 * visibility, then a definition of this symbol from
540 * within the archive is a better candidate.
541 */
542 vers = TRUE;
543 ifl = sdp->sd_file;
544
545 sym = sdp->sd_sym;
546
547 if (sdp->sd_ref == REF_DYN_NEED) {
548 uchar_t vis;
549
550 if (ifl->ifl_vercnt) {
551 Word vndx;
552 Ver_index *vip;
553
554 vndx = sdp->sd_aux->sa_dverndx;
555 vip = &ifl->ifl_verndx[vndx];
556 if (!(vip->vi_flags & FLG_VER_AVAIL))
557 vers = FALSE;
558 }
559
560 vis = ELF_ST_VISIBILITY(sym->st_other);
561 visible = sym_vis[vis];
562 }
563
564 if (((ifl->ifl_flags & FLG_IF_NEEDED) == 0) ||
565 (visible && vers && (sym->st_shndx != SHN_UNDEF) &&
566 (sym->st_shndx != SHN_COMMON)) ||
567 ((ELF_ST_BIND(sym->st_info) == STB_WEAK) &&
568 (!(ofl->ofl_flags1 & FLG_OF1_WEAKEXT)))) {
569 DBG_CALL(Dbg_syms_ar_skip(ofl->ofl_lml,
570 name, arsym));
571 continue;
572 }
573
574 /*
575 * Determine if we have already extracted this member,
576 * and if so reuse the Ar_mem information.
577 */
578 if ((amp = aup->au_mem) != 0) {
579 arelf = amp->am_elf;
580 arname = amp->am_name;
581 arpath = amp->am_path;
582 } else {
583 /*
584 * Set up a new elf descriptor for this member.
585 */
586 if (elf_rand(adp->ad_elf, arsym->as_off) !=
587 arsym->as_off) {
588 ld_eprintf(ofl, ERR_ELF,
589 MSG_INTL(MSG_ELF_ARMEM), name,
590 EC_WORD(arsym->as_off),
591 demangle(arsym->as_name));
592 return (FALSE);
593 }
594
595 if ((arelf = elf_begin(fd, ELF_C_READ,
596 adp->ad_elf)) == NULL) {
597 ld_eprintf(ofl, ERR_ELF,
598 MSG_INTL(MSG_ELF_BEGIN), name);
599 return (FALSE);
600 }
601
602 /* Get member filename */
603 if ((arname = ar_member_name(name, arelf,
604 ofl)) == NULL)
605 return (FALSE);
606
607 /* Construct the member's full pathname */
608 if ((arpath = ar_member_path(name, arname,
609 ofl)) == NULL)
610 return (FALSE);
611
612 /*
613 * Determine whether the support libraries wish
614 * to process this open. See comments in
615 * ld_process_open().
616 */
617 ld_sup_open(ofl, &arpath, &arname, &fd,
618 (FLG_IF_EXTRACT | FLG_IF_NEEDED),
619 &arelf, adp->ad_elf, arsym->as_off,
620 elf_kind(arelf));
621 if (arelf == NULL) {
622 /* Ignore this archive member */
623 aup->au_mem = FLG_ARMEM_PROC;
624 continue;
625 }
626 }
627
628 /*
629 * The symbol for which this archive member is being
630 * processed may provide a better alternative to the
631 * symbol that is presently known. Two cases are
632 * covered:
633 *
634 * i. The present symbol represents tentative data.
635 * The archive member may provide a data
636 * definition symbol.
637 * ii. The present symbol represents a reference that
638 * has seen a definition within a shared object
639 * dependency, but the reference expects to be
640 * reduced to hidden or protected visibility.
641 */
642 if ((sym->st_shndx == SHN_COMMON) ||
643 (visible == FALSE)) {
644 /*
645 * If we don't already have a member structure
646 * allocate one.
647 */
648 if (!amp) {
649 if ((amp = libld_calloc(sizeof (Ar_mem),
650 1)) == NULL)
651 return (FALSE);
652 amp->am_elf = arelf;
653 amp->am_name = arname;
654 amp->am_path = arpath;
655 }
656 DBG_CALL(Dbg_syms_ar_checking(ofl->ofl_lml,
657 name, arname, arsym));
658 if ((err = process_member(amp, arsym->as_name,
659 sdp, ofl)) == S_ERROR)
660 return (FALSE);
661
662 /*
663 * If it turns out that we don't need this
664 * member simply initialize all other auxiliary
665 * entries that match this offset with this
666 * members address. In this way we can resuse
667 * this information if we recurse back to this
668 * symbol.
669 */
670 if (err == 0) {
671 if (aup->au_mem == NULL)
672 ld_ar_member(adp, arsym,
673 aup, amp);
674 continue;
675 }
676 }
677
678 /*
679 * Process the archive member. Retain any error for
680 * return to the caller.
681 */
682 DBG_CALL(Dbg_syms_ar_resolve(ofl->ofl_lml,
683 name, arname, arsym));
684 switch (ar_input(fd, adp, ofl, arelf, arpath,
685 rej)) {
686 case S_ERROR:
687 return (FALSE);
688 case 0:
689 /*
690 * Mark the member as extracted so that we
691 * don't try and process it again on a rescan.
692 */
693 ld_ar_member(adp, arsym, aup, FLG_ARMEM_PROC);
694 continue;
695 }
696
697 /*
698 * Note that this archive has contributed something
699 * during this specific operation, and also signal
700 * the need to rescan the archive.
701 */
702 *found = again = TRUE;
703
704 ld_ar_member(adp, arsym, aup, FLG_ARMEM_PROC);
705 }
706 } while (again);
707
708 return (TRUE);
709 }
710
711
712 /*
713 * Extract every object in the given archive directly without going through
714 * the symbol table.
715 *
716 * entry:
717 * name - Name of archive
718 * fd - Open file descriptor for archive
719 * adp - Archive descriptor
720 * ofl - output descriptor
721 * found - Address of variable to set to TRUE if any objects are extracted
722 * rej - Rejection descriptor to pass to ld_process_ifl().
723 *
724 * exit:
725 * Returns FALSE on fatal error. On success, *found will be TRUE
726 * if any object was extracted, rej will be set if any object
727 * was rejected, and TRUE is returned.
728 */
729 static Boolean
ar_extract_all(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl,Boolean * found,Rej_desc * rej)730 ar_extract_all(const char *name, int fd, Ar_desc *adp, Ofl_desc *ofl,
731 Boolean *found, Rej_desc *rej)
732 {
733 Elf_Cmd cmd = ELF_C_READ;
734 Elf *arelf;
735 const char *arname, *arpath;
736 size_t off, next_off;
737
738 DBG_CALL(Dbg_file_ar(ofl->ofl_lml, name, FALSE));
739
740 while ((arelf = elf_begin(fd, cmd, adp->ad_elf)) != NULL) {
741 /*
742 * Call elf_next() so that the next call to elf_begin() will
743 * fetch the archive member following this one. We do this now
744 * because it simplifies the logic below, and because the
745 * support libraries called below can set our handle to NULL.
746 */
747 cmd = elf_next(arelf);
748
749 /* Get member filename */
750 if ((arname = ar_member_name(name, arelf, ofl)) == NULL)
751 return (FALSE);
752
753 /*
754 * Skip the symbol table, string table, or any other special
755 * archive member. These all start with a '/' character.
756 */
757 if (*arname == '/') {
758 (void) elf_end(arelf);
759 continue;
760 }
761
762 /* Obtain archive member offset within the file */
763 off = _elf_getarhdrbase(arelf);
764
765 /*
766 * ld_sup_open() will reset the current iteration point for
767 * the archive to point at this member rather than the next
768 * one for the benefit of the support libraries. Since
769 * this loop relies on the current position not changing
770 * underneath it, we save and restore the current
771 * position around the support library call.
772 */
773 next_off = _elf_getnextoff(adp->ad_elf);
774
775 /* Construct the member's full pathname */
776 if ((arpath = ar_member_path(name, arname, ofl)) == NULL)
777 return (FALSE);
778
779 /*
780 * Determine whether the support libraries wish to process
781 * this open. See comments in ld_process_open().
782 */
783 ld_sup_open(ofl, &arpath, &arname, &fd,
784 (FLG_IF_EXTRACT | FLG_IF_NEEDED), &arelf, adp->ad_elf,
785 off, elf_kind(arelf));
786 (void) elf_rand(adp->ad_elf, next_off);
787 if (arelf == NULL)
788 continue;
789
790 DBG_CALL(Dbg_syms_ar_force(ofl->ofl_lml, name, arname));
791 switch (ar_input(fd, adp, ofl, arelf, arpath, rej)) {
792 case S_ERROR:
793 return (FALSE);
794 case 0:
795 continue;
796 }
797
798 *found = TRUE;
799
800 }
801
802 /*
803 * As this archive was extracted by -z allextract, the ar_aux table
804 * and elf descriptor can be freed. Set ad_elf to NULL to mark the
805 * archive is completely processed.
806 */
807 (void) elf_end(adp->ad_elf);
808 adp->ad_elf = NULL;
809
810 return (TRUE);
811 }
812
813
814 /*
815 * Process the given archive and extract objects for inclusion into
816 * the link.
817 *
818 * entry:
819 * name - Name of archive
820 * fd - Open file descriptor for archive
821 * adp - Archive descriptor
822 * ofl - output descriptor
823 *
824 * exit:
825 * Returns FALSE on fatal error, TRUE otherwise.
826 */
827 Boolean
ld_process_archive(const char * name,int fd,Ar_desc * adp,Ofl_desc * ofl)828 ld_process_archive(const char *name, int fd, Ar_desc *adp, Ofl_desc *ofl)
829 {
830 Boolean found = FALSE;
831 Rej_desc rej = { 0 };
832
833 /*
834 * If a fatal error condition has been set there's really no point in
835 * processing the archive further. Having got to this point we have at
836 * least established that the archive exists (thus verifying that the
837 * command line options that got us to this archive are correct). Very
838 * large archives can take a significant time to process, therefore
839 * continuing on from here may significantly delay the fatal error
840 * message the user is already set to receive.
841 */
842 if (ofl->ofl_flags & FLG_OF_FATAL)
843 return (TRUE);
844
845 /*
846 * If this archive was processed with -z allextract, then all members
847 * have already been extracted.
848 */
849 if (adp->ad_elf == NULL)
850 return (TRUE);
851
852 if (ofl->ofl_flags1 & FLG_OF1_ALLEXRT) {
853 if (!ar_extract_all(name, fd, adp, ofl, &found, &rej))
854 return (FALSE);
855 } else {
856 if (!ar_extract_bysym(name, fd, adp, ofl, &found, &rej))
857 return (FALSE);
858 }
859
860 /*
861 * If no objects have been found in the archive test for any rejections
862 * and if one had occurred issue a warning - its possible a user has
863 * pointed at an archive containing the wrong class of elf members.
864 */
865 if ((found == 0) && rej.rej_type) {
866 Conv_reject_desc_buf_t rej_buf;
867
868 ld_eprintf(ofl, ERR_WARNING, MSG_INTL(reject[rej.rej_type]),
869 rej.rej_name ? rej.rej_name : MSG_INTL(MSG_STR_UNKNOWN),
870 conv_reject_desc(&rej, &rej_buf, ld_targ.t_m.m_mach));
871 }
872
873
874 return (TRUE);
875 }
876