Changed MDEC_OPT=BOOTWAIT= to BOOTWAIT=
[unix-history] / gnu / usr.bin / ld / lib.c
CommitLineData
1136f72d 1/*
6a61ea88 2 * $Id: lib.c,v 1.8 1993/12/22 23:28:11 jkh Exp $ - library routines
1136f72d
PR
3 */
4
5#include <sys/param.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <sys/file.h>
11#include <sys/time.h>
12#include <fcntl.h>
13#include <ar.h>
14#include <ranlib.h>
15#include <a.out.h>
16#include <stab.h>
17#include <string.h>
18#include <dirent.h>
19
20#include "ld.h"
21
6a61ea88
JH
22static void linear_library __P((int, struct file_entry *));
23static void symdef_library __P((int, struct file_entry *, int));
24static struct file_entry *decode_library_subfile __P((int,
25 struct file_entry *,
26 int, int *));
1136f72d
PR
27
28/*
29 * Search the library ENTRY, already open on descriptor DESC. This means
30 * deciding which library members to load, making a chain of `struct
31 * file_entry' for those members, and entering their global symbols in the
32 * hash table.
33 */
34
35void
36search_library(desc, entry)
37 int desc;
38 struct file_entry *entry;
39{
40 int member_length;
41 register char *name;
42 register struct file_entry *subentry;
43
44 if (!(link_mode & FORCEARCHIVE) && !undefined_global_sym_count)
45 return;
46
47 /* Examine its first member, which starts SARMAG bytes in. */
48 subentry = decode_library_subfile(desc, entry, SARMAG, &member_length);
49 if (!subentry)
50 return;
51
52 name = subentry->filename;
53 free(subentry);
54
55 /* Search via __.SYMDEF if that exists, else linearly. */
56
57 if (!strcmp(name, "__.SYMDEF"))
58 symdef_library(desc, entry, member_length);
59 else
60 linear_library(desc, entry);
61}
62
63/*
64 * Construct and return a file_entry for a library member. The library's
65 * file_entry is library_entry, and the library is open on DESC.
66 * SUBFILE_OFFSET is the byte index in the library of this member's header.
67 * We store the length of the member into *LENGTH_LOC.
68 */
69
6a61ea88 70static struct file_entry *
1136f72d
PR
71decode_library_subfile(desc, library_entry, subfile_offset, length_loc)
72 int desc;
73 struct file_entry *library_entry;
74 int subfile_offset;
75 int *length_loc;
76{
77 int bytes_read;
78 register int namelen;
0f052032
JH
79 int member_length, content_length;
80 int starting_offset;
1136f72d
PR
81 register char *name;
82 struct ar_hdr hdr1;
83 register struct file_entry *subentry;
1558d71a 84
1136f72d
PR
85 lseek(desc, subfile_offset, 0);
86
87 bytes_read = read(desc, &hdr1, sizeof hdr1);
88 if (!bytes_read)
89 return 0; /* end of archive */
90
91 if (sizeof hdr1 != bytes_read)
92 fatal_with_file("malformed library archive ", library_entry);
93
94 if (sscanf(hdr1.ar_size, "%d", &member_length) != 1)
95 fatal_with_file("malformatted header of archive member in ", library_entry);
96
97 subentry = (struct file_entry *) xmalloc(sizeof(struct file_entry));
98 bzero(subentry, sizeof(struct file_entry));
99
100 for (namelen = 0;
101 namelen < sizeof hdr1.ar_name
102 && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' '
103 && hdr1.ar_name[namelen] != '/';
104 namelen++);
105
0f052032
JH
106 starting_offset = subfile_offset + sizeof hdr1;
107 content_length = member_length;
108
109#ifdef AR_EFMT1
110 /*
111 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
112 * first <namelen> bytes of the file
113 */
6a61ea88
JH
114 if (strncmp(hdr1.ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 &&
115 isdigit(hdr1.ar_name[sizeof(AR_EFMT1) - 1])) {
0f052032 116
6a61ea88 117 namelen = atoi(&hdr1.ar_name[sizeof(AR_EFMT1) - 1]);
0f052032
JH
118 name = (char *)xmalloc(namelen + 1);
119 if (read(desc, name, namelen) != namelen)
120 fatal_with_file(
121 "malformatted header of archive member in ",
122 library_entry);
123 name[namelen] = 0;
124 content_length -= namelen;
125 starting_offset += namelen;
126 } else
127
128#endif
129 {
130 name = (char *)xmalloc(namelen + 1);
131 strncpy(name, hdr1.ar_name, namelen);
132 name[namelen] = 0;
133 }
1558d71a 134
1136f72d
PR
135 subentry->filename = name;
136 subentry->local_sym_name = name;
137 subentry->symbols = 0;
138 subentry->strings = 0;
139 subentry->subfiles = 0;
0f052032 140 subentry->starting_offset = starting_offset;
1136f72d 141 subentry->superfile = library_entry;
1136f72d 142 subentry->chain = 0;
6a61ea88 143 subentry->flags = 0;
0f052032 144 subentry->total_size = content_length;
1136f72d
PR
145
146 (*length_loc) = member_length;
147
148 return subentry;
149}
150
6a61ea88 151static int subfile_wanted_p __P((struct file_entry *));
1136f72d
PR
152
153/*
154 * Search a library that has a __.SYMDEF member. DESC is a descriptor on
155 * which the library is open. The file pointer is assumed to point at the
156 * __.SYMDEF data. ENTRY is the library's file_entry. MEMBER_LENGTH is the
157 * length of the __.SYMDEF data.
158 */
159
6a61ea88 160static void
1136f72d
PR
161symdef_library(desc, entry, member_length)
162 int desc;
163 struct file_entry *entry;
164 int member_length;
165{
166 int *symdef_data = (int *) xmalloc(member_length);
167 register struct ranlib *symdef_base;
168 char *sym_name_base;
6a61ea88 169 int nsymdefs;
1136f72d
PR
170 int length_of_strings;
171 int not_finished;
172 int bytes_read;
173 register int i;
174 struct file_entry *prev = 0;
175 int prev_offset = 0;
176
177 bytes_read = read(desc, symdef_data, member_length);
178 if (bytes_read != member_length)
179 fatal_with_file("malformatted __.SYMDEF in ", entry);
180
6a61ea88
JH
181 nsymdefs = md_swap_long(*symdef_data) / sizeof(struct ranlib);
182 if (nsymdefs < 0 ||
183 nsymdefs * sizeof(struct ranlib) + 2 * sizeof(int) > member_length)
1136f72d
PR
184 fatal_with_file("malformatted __.SYMDEF in ", entry);
185
186 symdef_base = (struct ranlib *) (symdef_data + 1);
6a61ea88 187 length_of_strings = md_swap_long(*(int *) (symdef_base + nsymdefs));
1136f72d
PR
188
189 if (length_of_strings < 0
6a61ea88 190 || nsymdefs * sizeof(struct ranlib) + length_of_strings
1136f72d
PR
191 + 2 * sizeof(int) > member_length)
192 fatal_with_file("malformatted __.SYMDEF in ", entry);
193
6a61ea88 194 sym_name_base = sizeof(int) + (char *) (symdef_base + nsymdefs);
1136f72d
PR
195
196 /* Check all the string indexes for validity. */
6a61ea88
JH
197 md_swapin_ranlib_hdr(symdef_base, nsymdefs);
198 for (i = 0; i < nsymdefs; i++) {
1136f72d
PR
199 register int index = symdef_base[i].ran_un.ran_strx;
200 if (index < 0 || index >= length_of_strings
201 || (index && *(sym_name_base + index - 1)))
202 fatal_with_file("malformatted __.SYMDEF in ", entry);
203 }
204
205 /*
206 * Search the symdef data for members to load. Do this until one
207 * whole pass finds nothing to load.
208 */
209
210 not_finished = 1;
211 while (not_finished) {
212
213 not_finished = 0;
214
215 /*
216 * Scan all the symbols mentioned in the symdef for ones that
217 * we need. Load the library members that contain such
218 * symbols.
219 */
220
6a61ea88 221 for (i = 0; (i < nsymdefs &&
1136f72d
PR
222 ((link_mode & FORCEARCHIVE) ||
223 undefined_global_sym_count ||
224 common_defined_global_count)); i++) {
225
226 register symbol *sp;
227 int junk;
228 register int j;
229 register int offset = symdef_base[i].ran_off;
230 struct file_entry *subentry;
231
232
233 if (symdef_base[i].ran_un.ran_strx < 0)
234 continue;
235
236 sp = getsym_soft(sym_name_base
237 + symdef_base[i].ran_un.ran_strx);
238
239 /*
240 * If we find a symbol that appears to be needed,
241 * think carefully about the archive member that the
242 * symbol is in.
243 */
244
245 /*
246 * Per Mike Karels' recommendation, we no longer load
247 * library files if the only reference(s) that would
248 * be satisfied are 'common' references. This
249 * prevents some problems with name pollution (e.g. a
250 * global common 'utime' linked to a function).
251 */
252 if (!(link_mode & FORCEARCHIVE) &&
6a61ea88
JH
253 (!sp || sp->defined ||
254 (!(sp->flags & GS_REFERENCED) &&
255 !sp->sorefs)))
1136f72d
PR
256 continue;
257
258 /*
259 * Don't think carefully about any archive member
260 * more than once in a given pass.
261 */
262
263 if (prev_offset == offset)
264 continue;
265 prev_offset = offset;
266
267 /*
268 * Read the symbol table of the archive member.
269 */
270
271 subentry = decode_library_subfile(desc,
272 entry, offset, &junk);
273 if (subentry == 0)
274 fatal(
6a61ea88 275 "invalid offset for %s in symbol table of %s",
1136f72d
PR
276 sym_name_base
277 + symdef_base[i].ran_un.ran_strx,
278 entry->filename);
6a61ea88 279
1136f72d
PR
280 read_entry_symbols(desc, subentry);
281 subentry->strings = (char *)
282 malloc(subentry->string_size);
283 read_entry_strings(desc, subentry);
284
285 /*
286 * Now scan the symbol table and decide whether to
287 * load.
288 */
289
290 if (!(link_mode & FORCEARCHIVE) &&
291 !subfile_wanted_p(subentry)) {
292 free(subentry->symbols);
293 free(subentry);
294 } else {
295 /*
296 * This member is needed; load it. Since we
297 * are loading something on this pass, we
298 * must make another pass through the symdef
299 * data.
300 */
301
302 not_finished = 1;
303
304 read_entry_relocation(desc, subentry);
305 enter_file_symbols(subentry);
306
307 if (prev)
308 prev->chain = subentry;
309 else
310 entry->subfiles = subentry;
311 prev = subentry;
312
313 /*
314 * Clear out this member's symbols from the
315 * symdef data so that following passes won't
316 * waste time on them.
317 */
318
6a61ea88 319 for (j = 0; j < nsymdefs; j++) {
1136f72d
PR
320 if (symdef_base[j].ran_off == offset)
321 symdef_base[j].ran_un.ran_strx = -1;
322 }
323 }
324
325 /*
326 * We'll read the strings again if we need them
327 * again.
328 */
329 free(subentry->strings);
330 subentry->strings = 0;
331 }
332 }
333
334 free(symdef_data);
335}
336
337/*
338 * Search a library that has no __.SYMDEF. ENTRY is the library's file_entry.
339 * DESC is the descriptor it is open on.
340 */
341
6a61ea88 342static void
1136f72d
PR
343linear_library(desc, entry)
344 int desc;
345 struct file_entry *entry;
346{
347 register struct file_entry *prev = 0;
348 register int this_subfile_offset = SARMAG;
349
350 while ((link_mode & FORCEARCHIVE) ||
351 undefined_global_sym_count || common_defined_global_count) {
352
6a61ea88
JH
353 int member_length;
354 register struct file_entry *subentry;
1136f72d 355
6a61ea88
JH
356 subentry = decode_library_subfile(desc, entry,
357 this_subfile_offset, &member_length);
1136f72d
PR
358
359 if (!subentry)
360 return;
361
362 read_entry_symbols(desc, subentry);
363 subentry->strings = (char *) alloca(subentry->string_size);
364 read_entry_strings(desc, subentry);
365
366 if (!(link_mode & FORCEARCHIVE) &&
367 !subfile_wanted_p(subentry)) {
368 free(subentry->symbols);
369 free(subentry);
370 } else {
371 read_entry_relocation(desc, subentry);
372 enter_file_symbols(subentry);
373
374 if (prev)
375 prev->chain = subentry;
376 else
377 entry->subfiles = subentry;
378 prev = subentry;
379 subentry->strings = 0; /* Since space will dissapear
380 * on return */
381 }
382
383 this_subfile_offset += member_length + sizeof(struct ar_hdr);
384 if (this_subfile_offset & 1)
385 this_subfile_offset++;
386 }
387}
388
389/*
390 * ENTRY is an entry for a library member. Its symbols have been read into
391 * core, but not entered. Return nonzero if we ought to load this member.
392 */
393
6a61ea88 394static int
1136f72d
PR
395subfile_wanted_p(entry)
396 struct file_entry *entry;
397{
398 struct localsymbol *lsp, *lspend;
399#ifdef DOLLAR_KLUDGE
400 register int dollar_cond = 0;
401#endif
402
403 lspend = entry->symbols + entry->nsymbols;
404
405 for (lsp = entry->symbols; lsp < lspend; lsp++) {
406 register struct nlist *p = &lsp->nzlist.nlist;
6a61ea88
JH
407 register int type = p->n_type;
408 register char *name = p->n_un.n_strx + entry->strings;
409 register symbol *sp = getsym_soft(name);
1136f72d
PR
410
411 /*
412 * If the symbol has an interesting definition, we could
413 * potentially want it.
414 */
415 if (! (type & N_EXT)
416 || (type == (N_UNDF | N_EXT) && p->n_value == 0
417
418#ifdef DOLLAR_KLUDGE
419 && name[1] != '$'
420#endif
421 )
422#ifdef SET_ELEMENT_P
423 || SET_ELEMENT_P(type)
424 || set_element_prefixed_p(name)
425#endif
426 )
427 continue;
428
429
430#ifdef DOLLAR_KLUDGE
431 if (name[1] == '$') {
432 sp = getsym_soft(&name[2]);
433 dollar_cond = 1;
434 if (!sp)
435 continue;
6a61ea88 436 if (sp->flags & SP_REFERENCED) {
1136f72d
PR
437 if (write_map) {
438 print_file_name(entry, stdout);
439 fprintf(stdout, " needed due to $-conditional %s\n", name);
440 }
441 return 1;
442 }
443 continue;
444 }
445#endif
446
447 /*
448 * If this symbol has not been hashed, we can't be
449 * looking for it.
450 */
451
452 if (!sp)
453 continue;
454
455 /*
456 * We don't load a file if it merely satisfies a
457 * common reference (see explanation above in
458 * symdef_library()).
459 */
6a61ea88 460 if ((sp->flags & GS_REFERENCED) && !sp->defined) {
1136f72d
PR
461 /*
462 * This is a symbol we are looking for. It
463 * is either not yet defined or defined as a
464 * common.
465 */
466#ifdef DOLLAR_KLUDGE
467 if (dollar_cond)
468 continue;
469#endif
470 if (type == (N_UNDF | N_EXT)) {
471 /*
472 * Symbol being defined as common.
473 * Remember this, but don't load
474 * subfile just for this.
475 */
476
477 /*
478 * If it didn't used to be common, up
479 * the count of common symbols.
480 */
6a61ea88 481 if (!sp->common_size)
1136f72d
PR
482 common_defined_global_count++;
483
6a61ea88
JH
484 if (sp->common_size < p->n_value)
485 sp->common_size = p->n_value;
1136f72d
PR
486 if (!sp->defined)
487 undefined_global_sym_count--;
488 sp->defined = type;
489 continue;
490 }
491 if (write_map) {
492 print_file_name(entry, stdout);
493 fprintf(stdout, " needed due to %s\n", sp->name);
494 }
495 return 1;
496 } else {
6a61ea88
JH
497 /*
498 * Check for undefined symbols or commons
499 * in shared objects.
500 */
1136f72d 501 struct localsymbol *lsp;
6a61ea88
JH
502 int wascommon = sp->defined && sp->common_size;
503 int iscommon = type == (N_UNDF|N_EXT) && p->n_value;
504
505 if (wascommon) {
506 /*
507 * sp was defined as common by shared object.
508 */
509 if (iscommon && p->n_value < sp->common_size)
510 sp->common_size = p->n_value;
511 continue;
512 }
1136f72d 513
0f052032
JH
514 if (sp->sorefs == NULL)
515 continue;
516
1136f72d 517 for (lsp = sp->sorefs; lsp; lsp = lsp->next) {
6a61ea88 518 int type = lsp->nzlist.nlist.n_type;
1136f72d
PR
519 if ( (type & N_EXT) &&
520 (type & N_STAB) == 0 &&
521 type != (N_UNDF | N_EXT))
6a61ea88
JH
522 break; /* We don't need it */
523 }
524 if (lsp != NULL) {
525 /* There's a real definition */
526 if (iscommon)
527 /*
528 * But this member wants it to be
529 * a common; ignore it.
530 continue;
531 }
532
533 if (iscommon) {
534 /*
535 * New symbol is common, just takes its
536 * size, but don't load.
537 */
538 sp->common_size = p->n_value;
539 sp->defined = type;
540 continue;
1136f72d 541 }
6a61ea88
JH
542
543 /*
544 * THIS STILL MISSES the case where one shared
545 * object defines a common and the next defines
546 * more strongly; fix this someday by making
547 * `struct glosym' and enter_global_ref() more
548 * symmetric.
549 */
7fc7155d 550
1136f72d
PR
551 if (write_map) {
552 print_file_name(entry, stdout);
553 fprintf(stdout, " needed due to shared lib ref %s\n", sp->name);
554 }
555 return 1;
1136f72d
PR
556 }
557 }
558
559 return 0;
560}
561
562/*
563 * Read the symbols of dynamic entity ENTRY into core. Assume it is already
564 * open, on descriptor DESC.
565 */
566void
567read_shared_object (desc, entry)
568 struct file_entry *entry;
569 int desc;
570{
6a61ea88
JH
571 struct _dynamic dyn;
572 struct section_dispatch_table sdt;
573 struct nlist *np;
574 struct nzlist *nzp;
575 int n, i, has_nz = 0;
1136f72d 576
6a61ea88 577 if (!(entry->flags & E_HEADER_VALID))
1136f72d
PR
578 read_header (desc, entry);
579
580 /* Read DYNAMIC structure (first in data segment) */
581 lseek (desc,
582 text_offset (entry) + entry->header.a_text,
583 L_SET);
584 if (read(desc, &dyn, sizeof dyn) != sizeof dyn) {
585 fatal_with_file (
586 "premature eof in data segment of ", entry);
587 }
6a61ea88 588 md_swapin__dynamic(&dyn);
1136f72d
PR
589
590 /* Check version */
6a61ea88 591 switch (dyn.d_version) {
1136f72d
PR
592 default:
593 fatal_with_file( "unsupported _DYNAMIC version ", entry);
594 break;
595 case LD_VERSION_SUN:
596 break;
597 case LD_VERSION_BSD:
598 has_nz = 1;
599 break;
600 }
601
6a61ea88 602 /* Read Section Dispatch Table (from data segment) */
1136f72d 603 lseek (desc,
6a61ea88
JH
604 text_offset(entry) + (long)dyn.d_un.d_sdt -
605 (DATA_START(entry->header) - N_DATOFF(entry->header)),
1136f72d 606 L_SET);
6a61ea88 607 if (read(desc, &sdt, sizeof sdt) != sizeof sdt) {
1136f72d
PR
608 fatal_with_file( "premature eof in data segment of ", entry);
609 }
6a61ea88 610 md_swapin_section_dispatch_table(&sdt);
1136f72d
PR
611
612 /* Read symbols (text segment) */
6a61ea88 613 n = sdt.sdt_strings - sdt.sdt_nzlist;
1136f72d
PR
614 entry->nsymbols = n /
615 (has_nz ? sizeof(struct nzlist) : sizeof(struct nlist));
616 nzp = (struct nzlist *)(np = (struct nlist *) alloca (n));
617 entry->symbols = (struct localsymbol *)
618 xmalloc(entry->nsymbols * sizeof(struct localsymbol));
6a61ea88
JH
619 lseek(desc, text_offset(entry) + (long)sdt.sdt_nzlist -
620 (TEXT_START(entry->header) - N_TXTOFF(entry->header)),
621 L_SET);
1136f72d
PR
622 if (read(desc, (char *)nzp, n) != n) {
623 fatal_with_file(
6a61ea88 624 "premature eof while reading object symbols ", entry);
1136f72d
PR
625 }
626 if (has_nz)
627 md_swapin_zsymbols(nzp, entry->nsymbols);
628 else
629 md_swapin_symbols(np, entry->nsymbols);
630
631 /* Convert to structs localsymbol */
632 for (i = 0; i < entry->nsymbols; i++) {
633 if (has_nz) {
634 entry->symbols[i].nzlist = *nzp++;
635 } else {
636 entry->symbols[i].nzlist.nlist = *np++;
637 entry->symbols[i].nzlist.nz_size = 0;
638 }
639 entry->symbols[i].symbol = NULL;
640 entry->symbols[i].next = NULL;
6a61ea88 641 entry->symbols[i].entry = entry;
1136f72d 642 entry->symbols[i].gotslot_offset = -1;
6a61ea88 643 entry->symbols[i].flags = 0;
1136f72d
PR
644 }
645
646 /* Read strings (text segment) */
6a61ea88 647 n = entry->string_size = sdt.sdt_str_sz;
1136f72d 648 entry->strings = (char *) alloca(n);
6a61ea88
JH
649 entry->strings_offset = text_offset(entry) + sdt.sdt_strings;
650 lseek(desc, entry->strings_offset -
651 (TEXT_START(entry->header) - N_TXTOFF(entry->header)),
652 L_SET);
1136f72d
PR
653 if (read(desc, entry->strings, n) != n) {
654 fatal_with_file(
6a61ea88 655 "premature eof while reading object strings ", entry);
1136f72d
PR
656 }
657 enter_file_symbols (entry);
658 entry->strings = 0;
659
0f052032
JH
660 /*
661 * Load any subsidiary shared objects.
662 */
6a61ea88
JH
663 if (sdt.sdt_sods) {
664 struct sod sod;
0f052032 665 off_t offset;
6a61ea88 666 struct file_entry *prev = NULL;
0f052032 667
6a61ea88 668 offset = (off_t)sdt.sdt_sods;
0f052032 669 while (1) {
6a61ea88 670 struct file_entry *subentry;
0f052032
JH
671 char *libname, name[MAXPATHLEN]; /*XXX*/
672
6a61ea88
JH
673 subentry = (struct file_entry *)
674 xmalloc(sizeof(struct file_entry));
675 bzero(subentry, sizeof(struct file_entry));
676 subentry->superfile = entry;
677
678 lseek(desc, offset -
679 (TEXT_START(entry->header) - N_TXTOFF(entry->header)),
680 L_SET);
681 if (read(desc, &sod, sizeof(sod)) != sizeof(sod)) {
0f052032 682 fatal_with_file(
6a61ea88 683 "premature eof while reading sod ",
0f052032
JH
684 entry);
685 }
6a61ea88
JH
686 md_swapin_sod(&sod, 1);
687 (void)lseek(desc, (off_t)sod.sod_name -
688 (TEXT_START(entry->header) - N_TXTOFF(entry->header)),
689 L_SET);
0f052032 690 (void)read(desc, name, sizeof(name)); /*XXX*/
6a61ea88
JH
691 if (sod.sod_library) {
692 int sod_major = sod.sod_major;
693 int sod_minor = sod.sod_minor;
0f052032
JH
694
695 libname = findshlib(name,
6a61ea88 696 &sod_major, &sod_minor, 0);
0f052032
JH
697 if (libname == NULL)
698 fatal("no shared -l%s.%d.%d available",
6a61ea88 699 name, sod.sod_major, sod.sod_minor);
0f052032
JH
700 subentry->filename = libname;
701 subentry->local_sym_name = concat("-l", name, "");
702 } else {
703 subentry->filename = strdup(name);
704 subentry->local_sym_name = strdup(name);
705 }
706 read_file_symbols(subentry);
707
708 if (prev)
709 prev->chain = subentry;
710 else
711 entry->subfiles = subentry;
712 prev = subentry;
92575836 713 desc = file_open(entry);
6a61ea88 714 if ((offset = (off_t)sod.sod_next) == 0)
0f052032
JH
715 break;
716 }
717 }
718#ifdef SUN_COMPAT
719 if (link_mode & SILLYARCHIVE) {
720 char *cp, *sa_name;
721 char armag[SARMAG];
722 int fd;
723 struct file_entry *subentry;
724
725 sa_name = strdup(entry->filename);
726 if (sa_name == NULL)
727 goto out;
728 cp = sa_name + strlen(sa_name) - 1;
729 while (cp > sa_name) {
730 if (!isdigit(*cp) && *cp != '.')
731 break;
732 --cp;
733 }
734 if (cp <= sa_name || *cp != 'o') {
735 /* Not in `libxxx.so.n.m' form */
736 free(sa_name);
737 goto out;
738 }
739
740 *cp = 'a';
741 if ((fd = open(sa_name, O_RDONLY, 0)) < 0)
742 goto out;
743
744 /* Read archive magic */
745 bzero(armag, SARMAG);
746 (void)read(fd, armag, SARMAG);
747 (void)close(fd);
748 if (strncmp(armag, ARMAG, SARMAG) != 0) {
749 error("%s: malformed silly archive",
750 get_file_name(entry));
751 goto out;
752 }
753
754 subentry = (struct file_entry *)
755 xmalloc(sizeof(struct file_entry));
756 bzero(subentry, sizeof(struct file_entry));
757
758 entry->silly_archive = subentry;
759 subentry->superfile = entry;
760 subentry->filename = sa_name;
761 subentry->local_sym_name = sa_name;
6a61ea88 762 subentry->flags |= E_IS_LIBRARY;
0f052032
JH
763 search_library(file_open(subentry), subentry);
764out:
765 ;
1136f72d 766 }
0f052032 767#endif
1136f72d
PR
768}
769
770#undef major
771#undef minor
772
773int
774findlib(p)
775struct file_entry *p;
776{
777 int desc;
778 int i;
779 int len;
780 int major = -1, minor = -1;
781 char *cp, *fname = NULL;
782
6a61ea88 783 if (!(p->flags & E_SEARCH_DYNAMIC))
1136f72d
PR
784 goto dot_a;
785
0f052032 786 fname = findshlib(p->filename, &major, &minor, 1);
1136f72d
PR
787
788 if (fname && (desc = open (fname, O_RDONLY, 0)) > 0) {
789 p->filename = fname;
790 p->lib_major = major;
791 p->lib_minor = minor;
6a61ea88 792 p->flags &= ~E_SEARCH_DIRS;
1136f72d
PR
793 return desc;
794 }
795 free (fname);
796
797dot_a:
6a61ea88 798 p->flags &= ~E_SEARCH_DYNAMIC;
1136f72d
PR
799 if (cp = strrchr(p->filename, '/')) {
800 *cp++ = '\0';
801 fname = concat(concat(p->filename, "/lib", cp), ".a", "");
802 *(--cp) = '/';
803 } else
804 fname = concat("lib", p->filename, ".a");
805
806 for (i = 0; i < n_search_dirs; i++) {
807 register char *string
808 = concat (search_dirs[i], "/", fname);
809 desc = open (string, O_RDONLY, 0);
810 if (desc > 0) {
811 p->filename = string;
6a61ea88 812 p->flags &= ~E_SEARCH_DIRS;
1136f72d
PR
813 break;
814 }
815 free (string);
816 }
817 return desc;
818}
819