diff --git a/gnu/usr.bin/ld/etc.c b/gnu/usr.bin/ld/etc.c index 2670283eb900..22fdfd8f1603 100644 --- a/gnu/usr.bin/ld/etc.c +++ b/gnu/usr.bin/ld/etc.c @@ -1,5 +1,5 @@ /* - * $Id: etc.c,v 1.4 1993/12/02 00:56:33 jkh Exp $ + * $Id: etc.c,v 1.5 1993/12/04 00:52:55 jkh Exp $ */ #include @@ -85,7 +85,7 @@ fatal(fmt, va_alist) char * concat(s1, s2, s3) - char *s1, *s2, *s3; + const char *s1, *s2, *s3; { register int len1 = strlen (s1), len2 = strlen (s2), @@ -150,22 +150,6 @@ xrealloc(ptr, size) } -#ifdef USG -void -bzero(p, n) - char *p; -{ - memset (p, 0, n); -} - -void -bcopy(from, to, n) - char *from, *to; -{ - memcpy (to, from, n); -} -#endif - /* These must move */ @@ -192,8 +176,10 @@ mywrite (buf, count, eltsize, desc) } } -/* Output PADDING zero-bytes to descriptor OUTDESC. - PADDING may be negative; in that case, do nothing. */ +/* + * Output PADDING zero-bytes to descriptor OUTDESC. + * PADDING may be negative; in that case, do nothing. + */ void padfile (padding, outdesc) diff --git a/gnu/usr.bin/ld/i386/md.h b/gnu/usr.bin/ld/i386/md.h index 714073bbbbd5..285b0e6a82bc 100644 --- a/gnu/usr.bin/ld/i386/md.h +++ b/gnu/usr.bin/ld/i386/md.h @@ -1,5 +1,33 @@ /* - * $Id: md.h,v 1.3 1993/11/22 19:05:24 jkh Exp $ - I386 dependent definitions + * Copyright (c) 1993 Paul Kranenburg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: md.h,v 1.5 1993/12/08 10:14:48 pk Exp $ */ diff --git a/gnu/usr.bin/ld/ld.c b/gnu/usr.bin/ld/ld.c index 3b24f432b380..567b5364256d 100644 --- a/gnu/usr.bin/ld/ld.c +++ b/gnu/usr.bin/ld/ld.c @@ -32,7 +32,7 @@ static char sccsid[] = "@(#)ld.c 6.10 (Berkeley) 5/22/91"; Set, indirect, and warning symbol features added by Randy Smith. */ /* - * $Id: ld.c,v 1.14 1993/12/02 05:09:52 nate Exp $ + * $Id: ld.c,v 1.15 1993/12/04 00:52:56 jkh Exp $ */ /* Define how to initialize system-dependent header fields. */ @@ -55,6 +55,10 @@ static char sccsid[] = "@(#)ld.c 6.10 (Berkeley) 5/22/91"; #include "ld.h" +#ifndef DEFAULT_SOVERSION +#define DEFAULT_SOVERSION LD_VERSION_BSD +#endif + int building_shared_object; /* 1 => write relocation into output file so can re-input it later. */ @@ -77,6 +81,9 @@ int force_alias_definition; if `relocatable_output'. */ int pic_code_seen; +/* 1 => data segment must be page aligned, even if `-n' or `-N' */ +int page_align_data; + /* * Which symbols should be stripped (omitted from the output): none, all, or * debugger symbols. @@ -127,6 +134,25 @@ int specified_data_size; long *set_vectors; int setv_fill_count; +static void decode_option __P((char *, char *)); +static void decode_command __P((int, char **)); +static int classify_arg __P((char *)); +static void enter_global_ref __P((struct localsymbol *, + char *, struct file_entry *)); +static void digest_symbols __P((void)); +static void digest_pass1 __P((void)), digest_pass2 __P((void)); +static void consider_file_section_lengths __P((struct file_entry *)); +static void relocate_file_addresses __P((struct file_entry *)); +static void consider_relocation __P((struct file_entry *, int)); +static void perform_relocation __P((char *, int, + struct relocation_info *, int, + struct file_entry *, int)); +static void copy_text __P((struct file_entry *)); +static void copy_data __P((struct file_entry *)); +static void coptxtrel __P((struct file_entry *)); +static void copdatrel __P((struct file_entry *)); +static void assign_symbolnums __P((struct file_entry *, int *)); + int main(argc, argv) char **argv; @@ -163,6 +189,7 @@ main(argc, argv) data_pad = 0; text_pad = 0; + page_align_data = 0; /* Initialize the data about options. */ @@ -180,7 +207,10 @@ main(argc, argv) make_executable = 1; force_executable = 0; link_mode = DYNAMIC; - soversion = LD_VERSION_BSD; +#ifdef SUNOS4 + link_mode |= SILLYARCHIVE; +#endif + soversion = DEFAULT_SOVERSION; /* Initialize the cumulative counts of symbols. */ @@ -262,8 +292,6 @@ main(argc, argv) exit(!make_executable); } -void decode_option(); - /* * Analyze a command line argument. Return 0 if the argument is a filename. * Return 1 if the argument is a option complete in itself. Return 2 if the @@ -273,7 +301,7 @@ void decode_option(); * options. */ -int +static int classify_arg(arg) register char *arg; { @@ -320,10 +348,10 @@ classify_arg(arg) * each input file, and setting variables according to the options. */ -void +static void decode_command(argc, argv) - char **argv; int argc; + char **argv; { register int i; register struct file_entry *p; @@ -390,6 +418,12 @@ decode_command(argc, argv) link_mode |= FORCEARCHIVE; else if (strcmp(string, "shareable") == 0) link_mode |= SHAREABLE; +#ifdef SUN_COMPAT + else if (strcmp(string, "silly") == 0) + link_mode |= SILLYARCHIVE; + else if (strcmp(string, "~silly") == 0) + link_mode &= ~SILLYARCHIVE; +#endif } if (argv[i][1] == 'A') { if (p != file_table) @@ -467,7 +501,7 @@ set_element_prefixed_p(name) * files. */ -void +static void decode_option(swt, arg) register char *swt, *arg; { @@ -484,6 +518,10 @@ decode_option(swt, arg) return; if (!strcmp(swt + 1, "assert")) return; +#ifdef SUN_COMPAT + if (!strcmp(swt + 1, "Bsilly")) + return; +#endif if (!strcmp(swt + 1, "Ttext")) { text_start = parse(arg, "%x", "invalid argument to -Ttext"); T_flag_specified = 1; @@ -551,16 +589,19 @@ decode_option(swt, arg) case 'Q': magic = oldmagic = QMAGIC; return; -#endif case 'Z': - magic = ZMAGIC; - oldmagic = 0; + magic = oldmagic = ZMAGIC; return; +#endif case 'o': output_filename = arg; return; + case 'p': + page_align_data = 1; + return; + case 'r': relocatable_output = 1; magic = OMAGIC; @@ -644,17 +685,38 @@ each_file(function, arg) for (i = 0; i < number_of_files; i++) { register struct file_entry *entry = &file_table[i]; + register struct file_entry *subentry; + if (entry->scrapped) continue; - if (entry->library_flag) { - register struct file_entry *subentry = entry->subfiles; + + if (!entry->library_flag) + (*function) (entry, arg); + + subentry = entry->subfiles; + for (; subentry; subentry = subentry->chain) { + if (subentry->scrapped) + continue; + (*function) (subentry, arg); + } + +#ifdef SUN_COMPAT + if (entry->silly_archive) { + + if (!entry->is_dynamic) + error("Silly"); + + if (!entry->silly_archive->library_flag) + error("Sillier"); + + subentry = entry->silly_archive->subfiles; for (; subentry; subentry = subentry->chain) { if (subentry->scrapped) continue; (*function) (subentry, arg); } - } else - (*function) (entry, arg); + } +#endif } } @@ -704,15 +766,41 @@ each_full_file(function, arg) for (i = 0; i < number_of_files; i++) { register struct file_entry *entry = &file_table[i]; - if (entry->scrapped || - entry->just_syms_flag || entry->is_dynamic) + register struct file_entry *subentry; + + if (entry->scrapped || entry->just_syms_flag) continue; - if (entry->library_flag) { - register struct file_entry *subentry = entry->subfiles; - for (; subentry; subentry = subentry->chain) + +#ifdef SUN_COMPAT + if (entry->silly_archive) { + + if (!entry->is_dynamic) + error("Silly"); + + if (!entry->silly_archive->library_flag) + error("Sillier"); + + subentry = entry->silly_archive->subfiles; + for (; subentry; subentry = subentry->chain) { + if (subentry->scrapped) + continue; (*function) (subentry, arg); - } else + } + } +#endif + if (entry->is_dynamic) + continue; + + if (!entry->library_flag) (*function) (entry, arg); + + subentry = entry->subfiles; + for (; subentry; subentry = subentry->chain) { + if (subentry->scrapped) + continue; + (*function) (subentry, arg); + } + } } @@ -737,7 +825,7 @@ file_open (entry) { register int desc; - if (entry->superfile) + if (entry->superfile && entry->superfile->library_flag) return file_open (entry->superfile); if (entry == input_file) @@ -802,6 +890,7 @@ read_header (desc, entry) * descriptor DESC. Also read the length of the string table, which follows * the symbol table, but don't read the contents of the string table. */ + void read_entry_symbols (desc, entry) struct file_entry *entry; @@ -941,8 +1030,6 @@ read_entry_relocation (desc, entry) /* Read in the symbols of all input files. */ -void read_file_symbols (), read_entry_symbols (); -void enter_file_symbols (), enter_global_ref (); void load_symbols () @@ -990,7 +1077,7 @@ read_file_symbols (entry) return; } entry->is_dynamic = 1; - if (rrs_add_shobj(entry)) + if (entry->superfile || rrs_add_shobj(entry)) read_shared_object(desc, entry); else entry->scrapped = 1; @@ -1095,7 +1182,7 @@ enter_file_symbols (entry) * */ -void +static void enter_global_ref (lsp, name, entry) struct localsymbol *lsp; char *name; @@ -1117,8 +1204,9 @@ enter_global_ref (lsp, name, entry) lsp->nzlist.nz_type = N_TEXT|N_EXT; lsp->nzlist.nz_value = 0; make_executable = 0; - } else + } else { global_alias_count++; + } } if (entry->is_dynamic) { @@ -1273,9 +1361,6 @@ contains_symbol (entry, np) } -void consider_file_section_lengths (), relocate_file_addresses (); -void consider_relocation(); - /* * Having entered all the global symbols and found the sizes of sections of * all files to be linked, make all appropriate deductions from this data. @@ -1295,7 +1380,7 @@ void consider_relocation(); * symbols originating from shared objects is searched for a definition. * * 2) Then the relocation information of each relocatable file is examined - * for for possible contributions to the RRS section. + * for possible contributions to the RRS section. * * 3) When this is done, the sizes and start addresses are set of all segments * that will appear in the output file (including the RRS segment). @@ -1307,9 +1392,8 @@ void consider_relocation(); * */ -void digest_pass1(), digest_pass2(); -void +static void digest_symbols () { @@ -1323,9 +1407,9 @@ digest_symbols () * the vector, plus a word for each symbol for a zero at the * end of the vector (for incremental linking). */ - set_sect_size = (2 * set_symbol_count + set_vector_count) * + set_sect_size = (set_symbol_count + 2 * set_vector_count) * sizeof (unsigned long); - set_vectors = (unsigned long *) xmalloc (set_sect_size); + set_vectors = (long *)xmalloc (set_sect_size); setv_fill_count = 0; } @@ -1354,7 +1438,7 @@ digest_symbols () * the padding in the text segment size. */ - if (magic == ZMAGIC) { + if (magic == ZMAGIC || page_align_data) { int text_end = text_size + N_TXTOFF(outheader); text_pad = PALIGN(text_end, page_size) - text_end; text_size += text_pad; @@ -1429,12 +1513,24 @@ printf("bssstart = %#x, bsssize = %#x\n", if (got_symbol->referenced) global_sym_count++; - if (relocatable_output) + if (relocatable_output || building_shared_object) /* For each alias we write out two struct nlists */ - global_sym_count += global_alias_count + size_sym_count; + global_sym_count += global_alias_count; + + if (relocatable_output) + /* We write out the original N_SET* symbols */ + global_sym_count += size_sym_count; + +#ifdef DEBUG +printf("global symbols %d (defined %d, undefined %d, aliases %d), locals: %d, \ +debug symbols: %d, set_symbols %d\n", + global_sym_count, + defined_global_sym_count, undefined_global_sym_count, global_alias_count, + local_sym_count, debugger_sym_count, set_symbol_count); +#endif } -void +static void digest_pass1() { @@ -1510,7 +1606,14 @@ digest_pass1() if ((sp->defined & N_TYPE) == N_SETV) /* Allocate zero entry in set vector */ setv_fill_count++; - defined_global_sym_count++; + /* + * At this stage, we do not know whether an alias + * is going to be defined for real here, or whether + * it refers to a shared object symbol. The decision + * is deferred until digest_pass2(). + */ + if (!sp->alias) + defined_global_sym_count++; continue; } @@ -1528,6 +1631,7 @@ digest_pass1() continue; } + again: for (lsp = sp->sorefs; lsp; lsp = lsp->next) { register struct nlist *p = &lsp->nzlist.nlist; register int type = p->n_type; @@ -1537,17 +1641,29 @@ digest_pass1() /* non-common definition */ sp->def_nlist = p; sp->so_defined = type; - undefined_global_sym_count--; + if (sp->referenced) + undefined_global_sym_count--; + else + sp->referenced = 1; #ifdef DEBUG printf("shr: %s gets defined to %x with value %x\n", sp->name, type, sp->value); #endif + if (sp->alias && !sp->alias->referenced) { + sp = sp->alias; + goto again; + } break; } } } END_EACH_SYMBOL; + + if (setv_fill_count != set_sect_size/sizeof(long)) + fatal("internal error: allocated set symbol space (%d) \ +doesn't match actual (%d)", + set_sect_size/sizeof(long), setv_fill_count); } -void +static void digest_pass2() { /* @@ -1562,6 +1678,16 @@ digest_pass2() if (!sp->referenced) continue; + if (sp->alias && + (relocatable_output || building_shared_object || + (sp->alias->defined && !sp->alias->so_defined))) + /* + * The alias points at a defined symbol, so it + * must itself be counted as one too, in order to + * compute the correct number of symbol table entries. + */ + defined_global_sym_count++; + if ((sp->defined & N_TYPE) == N_SETV) { /* * Set length word at front of vector and zero byte @@ -1676,11 +1802,12 @@ digest_pass2() } END_EACH_SYMBOL; } + /* * Scan relocation info in ENTRY for contributions to the dynamic section of * the output file. */ -void +static void consider_relocation (entry, dataseg) struct file_entry *entry; int dataseg; @@ -1849,7 +1976,7 @@ printf("%s: FUNC flag set\n", sp->name); * Accumulate the section sizes of input file ENTRY into the section sizes of * the output file. */ -void +static void consider_file_section_lengths (entry) register struct file_entry *entry; { @@ -1875,7 +2002,7 @@ consider_file_section_lengths (entry) * and determine which of the local symbols will make it into the * output symbol table. */ -void +static void relocate_file_addresses (entry) register struct file_entry *entry; { @@ -2025,18 +2152,20 @@ write_output () if (chmod (output_filename, filemode | 0111) == -1) perror_name (output_filename); } - -void modify_location (), perform_relocation (), copy_text (), copy_data (); /* Total number of symbols to be written in the output file. */ -int nsyms; +static int nsyms; void write_header () { int flags = (rrs_section_type == RRS_FULL) ? EX_DYNAMIC : 0; - if (!oldmagic) N_SET_FLAG (outheader, flags); +#ifdef QMAGIC + if (!oldmagic) +#endif + N_SET_FLAG (outheader, flags); + outheader.a_text = text_size; outheader.a_data = data_size; outheader.a_bss = bss_size; @@ -2051,15 +2180,6 @@ write_header () if (relocatable_output) nsyms += set_symbol_count; -#ifdef DEBUG -printf("global symbols %d (defined %d, undefined %d), locals: %d, \ -debug symbols: %d, set_symbols %d, aliases %d --> nsyms %d\n", - global_sym_count, - defined_global_sym_count, undefined_global_sym_count, - local_sym_count, debugger_sym_count, - set_symbol_count, global_alias_count, nsyms); -#endif - outheader.a_syms = nsyms * sizeof (struct nlist); if (relocatable_output) { @@ -2462,10 +2582,10 @@ printf("%s: BSS found in so_defined\n", sp->name); } } -/* For relocatable_output only: write out the relocation, - relocating the addresses-to-be-relocated. */ - -void coptxtrel(), copdatrel(), assign_symbolnums(); +/* + * For relocatable_output only: write out the relocation, + * relocating the addresses-to-be-relocated. + */ void write_rel () @@ -2513,10 +2633,11 @@ write_rel () fprintf (stderr, "\n"); } + /* * Assign symbol ordinal numbers to local symbols in each entry. */ -void +static void assign_symbolnums(entry, countp) struct file_entry *entry; int *countp; @@ -2537,7 +2658,7 @@ assign_symbolnums(entry, countp) *countp = n; } -void +static void coptxtrel(entry) struct file_entry *entry; { @@ -2613,7 +2734,7 @@ coptxtrel(entry) sizeof(struct relocation_info), outdesc); } -void +static void copdatrel(entry) struct file_entry *entry; { @@ -2684,28 +2805,28 @@ void write_string_table __P((void)); /* Offsets and current lengths of symbol and string tables in output file. */ -int symbol_table_offset; -int symbol_table_len; +static int symbol_table_offset; +static int symbol_table_len; /* Address in output file where string table starts. */ -int string_table_offset; +static int string_table_offset; /* Offset within string table where the strings in `strtab_vector' should be written. */ -int string_table_len; +static int string_table_len; /* Total size of string table strings allocated so far, including strings in `strtab_vector'. */ -int strtab_size; +static int strtab_size; /* Vector whose elements are strings to be added to the string table. */ -char **strtab_vector; +static char **strtab_vector; /* Vector whose elements are the lengths of those strings. */ -int *strtab_lens; +static int *strtab_lens; /* Index in `strtab_vector' at which the next string will be stored. */ -int strtab_index; +static int strtab_index; /* * Add the string NAME to the output file string table. Record it in @@ -2713,7 +2834,7 @@ int strtab_index; * table that this string will have. */ -int +static int assign_string_table_index(name) char *name; { @@ -2823,6 +2944,7 @@ write_syms() /* Scan the symbol hash table, bucket by bucket. */ FOR_EACH_SYMBOL(i, sp) { + if (sp == dynamic_symbol) /* Already dealt with above */ continue; @@ -2831,7 +2953,7 @@ write_syms() /* Came from shared object but was not used */ continue; - if (sp->so_defined) + if (sp->so_defined || (sp->alias && sp->alias->so_defined)) /* * Definition came from shared object, * don't mention it here @@ -2850,39 +2972,52 @@ write_syms() continue; } - /* Construct a `struct nlist' for the symbol. */ + if (syms_written >= global_sym_count) + fatal( + "internal error: number of symbols exceeds alloc'd %d", + global_sym_count); + /* + * Construct a `struct nlist' for the symbol. + */ nl.n_other = 0; nl.n_desc = 0; - /* - * common condition needs to be before undefined - * condition because unallocated commons are set - * undefined in digest_symbols - */ if (sp->defined > 1) { - /* defined with known type */ - - if (!relocatable_output && sp->alias && - sp->alias->defined > 1) { + /* + * defined with known type + */ + if (!relocatable_output && !building_shared_object && + sp->alias && sp->alias->defined > 1) { /* * If the target of an indirect symbol has * been defined and we are outputting an * executable, resolve the indirection; it's - * no longer needed + * no longer needed. */ nl.n_type = sp->alias->defined; - nl.n_type = sp->alias->value; - } else if (sp->defined == N_SIZE) - nl.n_type = N_DATA | N_EXT; - else - nl.n_type = sp->defined; - nl.n_value = sp->value; + nl.n_value = sp->alias->value; + } else { + if (sp->defined == N_SIZE) + nl.n_type = N_DATA | N_EXT; + else + nl.n_type = sp->defined; + if (nl.n_type == (N_INDR|N_EXT) && + sp->value != 0) + fatal("%s: N_INDR has value %#x", + sp->name, sp->value); + nl.n_value = sp->value; + } + } else if (sp->max_common_size) { /* * defined as common but not allocated, * happens only with -r and not -d, write out - * a common definition + * a common definition. + * + * common condition needs to be before undefined + * condition because unallocated commons are set + * undefined in digest_symbols. */ nl.n_type = N_UNDF | N_EXT; nl.n_value = sp->max_common_size; @@ -2903,10 +3038,6 @@ write_syms() /* Output to the buffer and count it. */ - if (syms_written >= global_sym_count) - fatal( - "internal error: number of symbols exceeds allocated %d", - global_sym_count); *bufp++ = nl; syms_written++; diff --git a/gnu/usr.bin/ld/ld.h b/gnu/usr.bin/ld/ld.h index 7b9a7068582e..081734ed23df 100644 --- a/gnu/usr.bin/ld/ld.h +++ b/gnu/usr.bin/ld/ld.h @@ -1,4 +1,4 @@ -/* $Id: ld.h,v 1.6 1993/12/02 00:56:37 jkh Exp $ */ +/* $Id: ld.h,v 1.7 1993/12/04 00:52:58 jkh Exp $ */ /*- * This code is derived from software copyrighted by the Free Software * Foundation. @@ -678,6 +678,11 @@ struct file_entry { /* For library member, points to next entry for next member. */ struct file_entry *chain; +#ifdef SUN_COMPAT + /* For shared libraries which have a .sa companion */ + struct file_entry *silly_archive; +#endif + /* 1 if file is a library. */ char library_flag; @@ -722,7 +727,8 @@ int number_of_files; #define FORCEARCHIVE 4 /* Force inclusion of all members of archives */ #define SHAREABLE 8 /* Build a shared object */ -int link_mode; +#define SILLYARCHIVE 16 /* Process .sa companions, if any */ +int link_mode; /* * Runtime Relocation Section (RRS). @@ -824,13 +830,14 @@ char **search_dirs; /* Length of the vector `search_dirs'. */ int n_search_dirs; -void digest_symbols __P((void)); void load_symbols __P((void)); -void decode_command __P((int, char **)); void read_header __P((int, struct file_entry *)); void read_entry_symbols __P((int, struct file_entry *)); void read_entry_strings __P((int, struct file_entry *)); void read_entry_relocation __P((int, struct file_entry *)); +void enter_file_symbols __P((struct file_entry *)); +void read_file_symbols __P((struct file_entry *)); + void write_output __P((void)); void write_header __P((void)); void write_text __P((void)); @@ -856,7 +863,7 @@ void *xrealloc __P((void *, int)); void fatal __P((char *, ...)); void error __P((char *, ...)); void padfile __P((int,int)); -char *concat __P((char *, char *, char *)); +char *concat __P((const char *, const char *, const char *)); int parse __P((char *, char *, char *)); /* In symbol.c: */ @@ -869,7 +876,7 @@ void read_shared_object __P((int, struct file_entry *)); int findlib __P((struct file_entry *)); /* In shlib.c: */ -char *findshlib __P((char *, int *, int *)); +char *findshlib __P((char *, int *, int *, int)); void add_search_dir __P((char *)); void std_search_dirs __P((char *)); diff --git a/gnu/usr.bin/ld/lib.c b/gnu/usr.bin/ld/lib.c index 3a6cbbb428e6..46e5d4607cb1 100644 --- a/gnu/usr.bin/ld/lib.c +++ b/gnu/usr.bin/ld/lib.c @@ -1,5 +1,5 @@ /* - * $Id: lib.c,v 1.5 1993/12/02 00:56:38 jkh Exp $ - library routines + * $Id: lib.c,v 1.6 1993/12/04 00:52:59 jkh Exp $ - library routines */ #include @@ -78,7 +78,8 @@ decode_library_subfile(desc, library_entry, subfile_offset, length_loc) { int bytes_read; register int namelen; - int member_length; + int member_length, content_length; + int starting_offset; register char *name; struct ar_hdr hdr1; register struct file_entry *subentry; @@ -104,22 +105,49 @@ decode_library_subfile(desc, library_entry, subfile_offset, length_loc) && hdr1.ar_name[namelen] != '/'; namelen++); - name = (char *) xmalloc(namelen + 1); - strncpy(name, hdr1.ar_name, namelen); - name[namelen] = 0; + starting_offset = subfile_offset + sizeof hdr1; + content_length = member_length; + +#ifdef AR_EFMT1 + /* + * BSD 4.4 extended AR format: #1/, with name as the + * first bytes of the file + */ + if ( (hdr1.ar_name[0] == '#') && + (hdr1.ar_name[1] == '1') && + (hdr1.ar_name[2] == '/') && + (isdigit(hdr1.ar_name[3]))) { + + namelen = atoi(&hdr1.ar_name[3]); + name = (char *)xmalloc(namelen + 1); + if (read(desc, name, namelen) != namelen) + fatal_with_file( + "malformatted header of archive member in ", + library_entry); + name[namelen] = 0; + content_length -= namelen; + starting_offset += namelen; + } else + +#endif + { + name = (char *)xmalloc(namelen + 1); + strncpy(name, hdr1.ar_name, namelen); + name[namelen] = 0; + } subentry->filename = name; subentry->local_sym_name = name; subentry->symbols = 0; subentry->strings = 0; subentry->subfiles = 0; - subentry->starting_offset = subfile_offset + sizeof hdr1; + subentry->starting_offset = starting_offset; subentry->superfile = library_entry; subentry->library_flag = 0; subentry->header_read_flag = 0; subentry->just_syms_flag = 0; subentry->chain = 0; - subentry->total_size = member_length; + subentry->total_size = content_length; (*length_loc) = member_length; @@ -474,6 +502,9 @@ subfile_wanted_p(entry) int defs = 0; /* Check for undefined symbols in shared objects */ + if (sp->sorefs == NULL) + continue; + for (lsp = sp->sorefs; lsp; lsp = lsp->next) { type = lsp->nzlist.nlist.n_type; if ( (type & N_EXT) && @@ -590,9 +621,110 @@ read_shared_object (desc, entry) enter_file_symbols (entry); entry->strings = 0; - /* TODO: examine needed shared objects */ + /* + * Load any subsidiary shared objects. + */ if (dyn2.ld_need) { + struct link_object lobj; + off_t offset; + struct file_entry *subentry, *prev = NULL; + + subentry = (struct file_entry *) + xmalloc(sizeof(struct file_entry)); + bzero(subentry, sizeof(struct file_entry)); + + subentry->superfile = entry; + + offset = (off_t)dyn2.ld_need; + while (1) { + char *libname, name[MAXPATHLEN]; /*XXX*/ + + lseek(desc, offset, L_SET); + if (read(desc, &lobj, sizeof(lobj)) != sizeof(lobj)) { + fatal_with_file( + "premature eof while reading link objects ", + entry); + } + md_swapin_link_object(&lobj, 1); + (void)lseek(desc, (off_t)lobj.lo_name, L_SET); + (void)read(desc, name, sizeof(name)); /*XXX*/ + if (lobj.lo_library) { + int lo_major = lobj.lo_major; + int lo_minor = lobj.lo_minor; + + libname = findshlib(name, + &lo_major, &lo_minor, 0); + if (libname == NULL) + fatal("no shared -l%s.%d.%d available", + name, lobj.lo_major, lobj.lo_minor); + subentry->filename = libname; + subentry->local_sym_name = concat("-l", name, ""); + } else { + subentry->filename = strdup(name); + subentry->local_sym_name = strdup(name); + } + read_file_symbols(subentry); + + if (prev) + prev->chain = subentry; + else + entry->subfiles = subentry; + prev = subentry; + file_open(entry); + if ((offset = (off_t)lobj.lo_next) == 0) + break; + } } +#ifdef SUN_COMPAT + if (link_mode & SILLYARCHIVE) { + char *cp, *sa_name; + char armag[SARMAG]; + int fd; + struct file_entry *subentry; + + sa_name = strdup(entry->filename); + if (sa_name == NULL) + goto out; + cp = sa_name + strlen(sa_name) - 1; + while (cp > sa_name) { + if (!isdigit(*cp) && *cp != '.') + break; + --cp; + } + if (cp <= sa_name || *cp != 'o') { + /* Not in `libxxx.so.n.m' form */ + free(sa_name); + goto out; + } + + *cp = 'a'; + if ((fd = open(sa_name, O_RDONLY, 0)) < 0) + goto out; + + /* Read archive magic */ + bzero(armag, SARMAG); + (void)read(fd, armag, SARMAG); + (void)close(fd); + if (strncmp(armag, ARMAG, SARMAG) != 0) { + error("%s: malformed silly archive", + get_file_name(entry)); + goto out; + } + + subentry = (struct file_entry *) + xmalloc(sizeof(struct file_entry)); + bzero(subentry, sizeof(struct file_entry)); + + entry->silly_archive = subentry; + subentry->superfile = entry; + subentry->filename = sa_name; + subentry->local_sym_name = sa_name; + subentry->library_flag = 1; + search_library(file_open(subentry), subentry); +out: + ; + } +#endif } #undef major @@ -611,7 +743,7 @@ struct file_entry *p; if (p->search_dynamic_flag == 0) goto dot_a; - fname = findshlib(p->filename, &major, &minor); + fname = findshlib(p->filename, &major, &minor, 1); if (fname && (desc = open (fname, O_RDONLY, 0)) > 0) { p->filename = fname; diff --git a/gnu/usr.bin/ld/rrs.c b/gnu/usr.bin/ld/rrs.c index 4be027a07c78..6de17b9ba45f 100644 --- a/gnu/usr.bin/ld/rrs.c +++ b/gnu/usr.bin/ld/rrs.c @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rrs.c,v 1.8 1993/12/02 09:32:26 ache Exp $ + * $Id: rrs.c,v 1.9 1993/12/04 00:53:00 jkh Exp $ */ #include @@ -726,6 +726,16 @@ consider_rrs_section_lengths() rrs_strtab_size += 1 + strlen(sp->name); if (sp != dynamic_symbol) sp->rrs_symbolnum = number_of_rrs_symbols++; + if (sp->alias) { + /* + * (sigh) Always allocate space to hold the + * indirection. At this point there's not + * enough information to decide whether it's + * actually needed or not. + */ + number_of_rrs_symbols++; + rrs_strtab_size += 1 + strlen(sp->alias->name); + } } } END_EACH_SYMBOL; @@ -973,7 +983,17 @@ write_rrs_text() if (sp->defined > 1) { /* defined with known type */ - if (sp->defined == N_SIZE) { + if (!(link_mode & SHAREABLE) && + sp->alias && sp->alias->defined > 1) { + /* + * If the target of an indirect symbol has + * been defined and we are outputting an + * executable, resolve the indirection; it's + * no longer needed. + */ + nlp->nz_type = sp->alias->defined; + nlp->nz_value = sp->alias->value; + } else if (sp->defined == N_SIZE) { /* * Make sure this symbol isn't going * to define anything. @@ -1001,7 +1021,6 @@ write_rrs_text() "internal error: %s defined in mysterious way", sp->name); - /* Handle auxialiary type qualifiers */ switch (sp->aux) { case 0: @@ -1020,7 +1039,7 @@ write_rrs_text() break; default: fatal( - "internal error: %s: unsupported other value: %x", + "internal error: %s: unsupported other value: %x", sp->name, sp->aux); break; } @@ -1030,14 +1049,32 @@ write_rrs_text() strcpy(rrs_strtab + offset, sp->name); offset += 1 + strlen(sp->name); + if (sp->alias) { + /* + * Write an extra symbol for indirections (possibly + * just a dummy). + */ + int t = (nlp->nz_type == N_INDR + N_EXT); + + INCR_NLP(nlp); + nlp->nz_type = N_UNDF + t?N_EXT:0; + nlp->nz_un.n_strx = offset; + nlp->nz_value = 0; + nlp->nz_other = 0; + nlp->nz_desc = 0; + nlp->nz_size = 0; + strcpy(rrs_strtab + offset, sp->alias->name); + offset += 1 + strlen(sp->alias->name); + } + INCR_NLP(nlp); } END_EACH_SYMBOL; if (MALIGN(offset) != rrs_strtab_size) fatal( - "internal error: inconsistent RRS string table length: %d", - offset); + "internal error: inconsistent RRS string table length: %d, expected %d", + offset, rrs_strtab_size); /* Write the symbol table */ if (rrs_symbol_size == sizeof(struct nlist)) @@ -1059,8 +1096,9 @@ write_rrs_text() for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) { char *name = shp->entry->local_sym_name; - if (shp == NULL) - fatal("internal error: shp == NULL"); + if (i >= number_of_shobjs) + fatal("internal error: # of link objects exceeds %d", + number_of_shobjs); lo[i].lo_name = pos; lo[i].lo_major = shp->entry->lib_major; @@ -1075,10 +1113,11 @@ write_rrs_text() pos += 1 + strlen(name); lo[i].lo_next = (i == number_of_shobjs - 1) ? 0 : (rrs_dyn2.ld_need + (i+1)*sizeof(struct link_object)); - } - if (shp != NULL) - fatal("internal error: shp != NULL"); + + if (i < number_of_shobjs) + fatal("internal error: # of link objects less then expected %d", + number_of_shobjs); md_swapout_link_object(lo, number_of_shobjs); mywrite(lo, number_of_shobjs, sizeof(struct link_object), outdesc); diff --git a/gnu/usr.bin/ld/shlib.c b/gnu/usr.bin/ld/shlib.c index b6cb74ef5ea3..dcca01f97c55 100644 --- a/gnu/usr.bin/ld/shlib.c +++ b/gnu/usr.bin/ld/shlib.c @@ -1,5 +1,5 @@ /* - * $Id: shlib.c,v 1.4 1993/12/02 00:56:40 jkh Exp $ + * $Id: shlib.c,v 1.5 1993/12/04 00:53:02 jkh Exp $ */ #include @@ -11,16 +11,21 @@ #include #include #include +#include #include #include #include "ld.h" +#ifdef SUNOS4 +char *strsep(); +#endif + /* * Standard directories to search for files specified by -l. */ #ifndef STANDARD_SEARCH_DIRS -#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/local/lib" +#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/X386/lib", "/usr/local/lib" #endif char *standard_search_dirs[] = { @@ -132,9 +137,10 @@ int n1, n2; #undef minor char * -findshlib(name, majorp, minorp) +findshlib(name, majorp, minorp, do_dot_a) char *name; int *majorp, *minorp; +int do_dot_a; { int dewey[MAXDEWEY]; int ndewey; @@ -154,6 +160,7 @@ int *majorp, *minorp; for (i = 0; i < n_search_dirs; i++) { DIR *dd = opendir(search_dirs[i]); struct dirent *dp; + int found_dot_a = 0; if (dd == NULL) continue; @@ -161,6 +168,16 @@ int *majorp, *minorp; while ((dp = readdir(dd)) != NULL) { int n, j, might_take_it = 0; + if (do_dot_a && path == NULL && + dp->d_namlen == len + 2 && + strncmp(dp->d_name, lname, len) == 0 && + (dp->d_name+len)[0] == '.' && + (dp->d_name+len)[1] == 'a') { + + path = concat(search_dirs[i], "/", dp->d_name); + found_dot_a = 1; + } + if (dp->d_namlen < len + 4) continue; if (strncmp(dp->d_name, lname, len) != 0) @@ -171,6 +188,12 @@ int *majorp, *minorp; if ((n = getdewey(tmp, dp->d_name+len+4)) == 0) continue; + if (major != -1 && found_dot_a) { /* XXX */ + free(path); + path = NULL; + found_dot_a = 0; + } + if (major == -1 && minor == -1) { might_take_it = 1; } else if (major != -1 && minor == -1) { @@ -192,12 +215,19 @@ int *majorp, *minorp; if (path) free(path); path = concat(search_dirs[i], "/", dp->d_name); + found_dot_a = 0; bcopy(tmp, dewey, sizeof(dewey)); ndewey = n; *majorp = dewey[0]; *minorp = dewey[1]; } closedir(dd); + + if (found_dot_a) + /* + * There's a .a archive here. + */ + return path; } return path; diff --git a/gnu/usr.bin/ld/sparc/md-static-funcs.c b/gnu/usr.bin/ld/sparc/md-static-funcs.c index 99e6240f03e1..2672cb596be6 100644 --- a/gnu/usr.bin/ld/sparc/md-static-funcs.c +++ b/gnu/usr.bin/ld/sparc/md-static-funcs.c @@ -1,5 +1,7 @@ /* + * $Id: md-static-funcs.c,v 1.2 1993/12/08 10:28:56 pk Exp $ + * * Simple SPARC relocations for the benefit of self-relocation of ld.so * avoiding the use of global variables (ie. reloc_bitshift[] et. al.). * Only types supported are RELOC_32 and RELOC_RELATIVE. diff --git a/gnu/usr.bin/ld/sparc/md.c b/gnu/usr.bin/ld/sparc/md.c index bfe184b440f1..3ae54e30e9ab 100644 --- a/gnu/usr.bin/ld/sparc/md.c +++ b/gnu/usr.bin/ld/sparc/md.c @@ -1,5 +1,33 @@ /* - * $Id: md.c,v 1.3 1993/11/22 19:05:30 jkh Exp $ + * Copyright (c) 1993 Paul Kranenburg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: md.c,v 1.6 1993/12/08 10:29:02 pk Exp $ */ #include @@ -181,9 +209,14 @@ int type; #if 1 /* * This wouldn't be strictly necessary - we could record the - * location value "in situ" in stead of in the r_addend field - + * relocation value "in situ" in stead of in the r_addend field - * but we are being Sun compatible here. Besides, Sun's ld.so - * has a bug that prevents it from handling this alternate method + * has a bug that prevents it from handling this alternate method. + * + * IT WOULD BE REALLY NICE TO HAVE CONSISTENCY THROUGHOUT THE ENTIRE + * RELOCATION PROCESS, ie. using `r_addend' for storing all partially + * completed relocations, in stead of mixing them in both relocation + * records and in the segment data. */ if (RELOC_PCREL_P(rp)) r->r_addend -= pc_relocation; diff --git a/gnu/usr.bin/ld/warnings.c b/gnu/usr.bin/ld/warnings.c index e1910741a085..1e47cfd3d617 100644 --- a/gnu/usr.bin/ld/warnings.c +++ b/gnu/usr.bin/ld/warnings.c @@ -1,5 +1,5 @@ /* - * $Id: warnings.c,v 1.4 1993/11/05 12:45:25 pk Exp $ + * $Id: warnings.c,v 1.2 1993/11/09 04:19:06 paul Exp $ */ #include @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -112,10 +113,8 @@ fatal_with_file (fmt, entry, va_alist) */ void perror_name (name) - char *name; + char *name; { - extern int errno, sys_nerr; - extern char *sys_errlist[]; char *s; if (errno < sys_nerr) @@ -133,8 +132,6 @@ void perror_file (entry) struct file_entry *entry; { - extern int errno, sys_nerr; - extern char *sys_errlist[]; char *s; if (errno < sys_nerr) @@ -165,19 +162,17 @@ print_symbols(outfile) for (i = 0; i < TABSIZE; i++) { register symbol *sp; for (sp = symtab[i]; sp; sp = sp->link) { - if (sp->defined == 1) + if (sp->defined == (N_UNDF|N_EXT)) fprintf(outfile, " %s: common, length %#x\n", sp->name, sp->max_common_size); - if ( sp->referenced) { - if (sp->defined) - fprintf(outfile, " %s: %#x %#x\n", - sp->name, sp->value, sp->size); - else - fprintf(outfile, " %s: undefined\n", - sp->name); - } else + if (!sp->referenced) fprintf(outfile, " %s: unreferenced\n", - sp->name); + sp->name); + else if (!sp->defined) + fprintf(outfile, " %s: undefined\n", sp->name); + else + fprintf(outfile, " %s: %#x, size %#x\n", + sp->name, sp->value, sp->size); } } @@ -191,7 +186,7 @@ describe_file_sections(entry, outfile) { fprintf(outfile, " "); print_file_name(entry, outfile); - if (entry->just_syms_flag) + if (entry->just_syms_flag || entry->is_dynamic) fprintf(outfile, " symbols only\n", 0); else fprintf(outfile, " text %x(%x), data %x(%x), bss %x(%x) hex\n", @@ -659,15 +654,17 @@ do_file_warnings (entry, outfile) if (list_multiple_defs && g->multiply_defined) { errfmt = "Definition of symbol %s (multiply defined)"; switch (s->n_type) { + case N_TEXT | N_EXT: line_number = address_to_line (s->n_value, text_scan); file_name = text_scan[0].filename; break; + case N_DATA | N_EXT: line_number = address_to_line (s->n_value, data_scan); file_name = data_scan[0].filename; break; -#if 0 + case N_SETA | N_EXT: case N_SETT | N_EXT: case N_SETD | N_EXT: @@ -676,16 +673,16 @@ do_file_warnings (entry, outfile) continue; errfmt = "First set element definition of symbol %s (multiply defined)"; break; -#endif + default: - /* Don't print out multiple defs - at references.*/ +printf("Multiple def: %s, type %#x\n", g->name, s->n_type); + /* Don't print out multiple defs at references.*/ continue; } - } else if (BIT_SET_P (nlist_bitvector, i)) + } else if (BIT_SET_P (nlist_bitvector, i)) { continue; - else if (list_unresolved_refs && !g->defined && !g->so_defined) { + } else if (list_unresolved_refs && !g->defined && !g->so_defined) { if (g->undef_refs >= MAX_UREFS_PRINTED) continue; diff --git a/libexec/rtld-aout/i386/md.h b/libexec/rtld-aout/i386/md.h index 714073bbbbd5..285b0e6a82bc 100644 --- a/libexec/rtld-aout/i386/md.h +++ b/libexec/rtld-aout/i386/md.h @@ -1,5 +1,33 @@ /* - * $Id: md.h,v 1.3 1993/11/22 19:05:24 jkh Exp $ - I386 dependent definitions + * Copyright (c) 1993 Paul Kranenburg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: md.h,v 1.5 1993/12/08 10:14:48 pk Exp $ */ diff --git a/libexec/rtld-aout/shlib.c b/libexec/rtld-aout/shlib.c index b6cb74ef5ea3..dcca01f97c55 100644 --- a/libexec/rtld-aout/shlib.c +++ b/libexec/rtld-aout/shlib.c @@ -1,5 +1,5 @@ /* - * $Id: shlib.c,v 1.4 1993/12/02 00:56:40 jkh Exp $ + * $Id: shlib.c,v 1.5 1993/12/04 00:53:02 jkh Exp $ */ #include @@ -11,16 +11,21 @@ #include #include #include +#include #include #include #include "ld.h" +#ifdef SUNOS4 +char *strsep(); +#endif + /* * Standard directories to search for files specified by -l. */ #ifndef STANDARD_SEARCH_DIRS -#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/local/lib" +#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/X386/lib", "/usr/local/lib" #endif char *standard_search_dirs[] = { @@ -132,9 +137,10 @@ int n1, n2; #undef minor char * -findshlib(name, majorp, minorp) +findshlib(name, majorp, minorp, do_dot_a) char *name; int *majorp, *minorp; +int do_dot_a; { int dewey[MAXDEWEY]; int ndewey; @@ -154,6 +160,7 @@ int *majorp, *minorp; for (i = 0; i < n_search_dirs; i++) { DIR *dd = opendir(search_dirs[i]); struct dirent *dp; + int found_dot_a = 0; if (dd == NULL) continue; @@ -161,6 +168,16 @@ int *majorp, *minorp; while ((dp = readdir(dd)) != NULL) { int n, j, might_take_it = 0; + if (do_dot_a && path == NULL && + dp->d_namlen == len + 2 && + strncmp(dp->d_name, lname, len) == 0 && + (dp->d_name+len)[0] == '.' && + (dp->d_name+len)[1] == 'a') { + + path = concat(search_dirs[i], "/", dp->d_name); + found_dot_a = 1; + } + if (dp->d_namlen < len + 4) continue; if (strncmp(dp->d_name, lname, len) != 0) @@ -171,6 +188,12 @@ int *majorp, *minorp; if ((n = getdewey(tmp, dp->d_name+len+4)) == 0) continue; + if (major != -1 && found_dot_a) { /* XXX */ + free(path); + path = NULL; + found_dot_a = 0; + } + if (major == -1 && minor == -1) { might_take_it = 1; } else if (major != -1 && minor == -1) { @@ -192,12 +215,19 @@ int *majorp, *minorp; if (path) free(path); path = concat(search_dirs[i], "/", dp->d_name); + found_dot_a = 0; bcopy(tmp, dewey, sizeof(dewey)); ndewey = n; *majorp = dewey[0]; *minorp = dewey[1]; } closedir(dd); + + if (found_dot_a) + /* + * There's a .a archive here. + */ + return path; } return path;