diff options
Diffstat (limited to 'gnu/usr.bin/ld/ld.c')
-rw-r--r-- | gnu/usr.bin/ld/ld.c | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/gnu/usr.bin/ld/ld.c b/gnu/usr.bin/ld/ld.c index be17bcb6314..92536dca65d 100644 --- a/gnu/usr.bin/ld/ld.c +++ b/gnu/usr.bin/ld/ld.c @@ -1,3 +1,5 @@ +/* $OpenBSD: ld.c,v 1.3 1996/03/30 15:29:59 niklas Exp $ */ + /*- * This code is derived from software copyrighted by the Free Software * Foundation. @@ -8,7 +10,9 @@ */ #ifndef lint +#if 0 static char sccsid[] = "@(#)ld.c 6.10 (Berkeley) 5/22/91"; +#endif #endif /* not lint */ /* Linker `ld' for GNU @@ -31,10 +35,6 @@ static char sccsid[] = "@(#)ld.c 6.10 (Berkeley) 5/22/91"; /* Written by Richard Stallman with some help from Eric Albert. Set, indirect, and warning symbol features added by Randy Smith. */ -/* - * $Id: ld.c,v 1.2 1995/12/30 08:13:47 deraadt Exp $ - */ - /* Define how to initialize system-dependent header fields. */ #include <sys/param.h> @@ -1891,7 +1891,14 @@ digest_pass1() } } - if (sp->defined) { + /* + * If this symbol has acquired final definition, we're done. + * Commons must be allowed to bind to shared object data + * definitions. + */ + if (sp->defined && + (sp->common_size == 0 || + relocatable_output || building_shared_object)) { if ((sp->defined & N_TYPE) == N_SETV) /* Allocate zero entry in set vector */ setv_fill_count++; @@ -1924,7 +1931,7 @@ digest_pass1() continue; } - spsave=sp; + spsave=sp; /*XXX*/ again: for (lsp = sp->sorefs; lsp; lsp = lsp->next) { register struct nlist *p = &lsp->nzlist.nlist; @@ -1933,6 +1940,27 @@ digest_pass1() if ((type & N_EXT) && type != (N_UNDF | N_EXT) && (type & N_TYPE) != N_FN) { /* non-common definition */ + if (sp->common_size) { + /* + * This common has an so defn; switch + * to it iff defn is: data, first-class + * and not weak. + */ + if (N_AUX(p) != AUX_OBJECT || + N_ISWEAK(p) || + (lsp->entry->flags & E_SECONDCLASS)) + continue; + + /* + * Change common to so ref. First, + * downgrade common to undefined. + */ + sp->common_size = 0; + sp->defined = 0; + common_defined_global_count--; + undefined_global_sym_count++; + } + sp->def_lsp = lsp; sp->so_defined = type; sp->aux = N_AUX(p); @@ -1952,9 +1980,9 @@ printf("pass1: SO definition for %s, type %x in %s at %#x\n", sp->def_lsp->nzlist.nz_value); #endif sp->def_lsp->entry->flags |= E_SYMBOLS_USED; - if (sp->flags & GS_REFERENCED) + if (sp->flags & GS_REFERENCED) { undefined_global_sym_count--; - else + } else sp->flags |= GS_REFERENCED; if (undefined_global_sym_count < 0) errx(1, "internal error: digest_pass1,2: " @@ -1965,8 +1993,19 @@ printf("pass1: SO definition for %s, type %x in %s at %#x\n", sp = sp->alias; goto again; } + } else if (sp->defined) { + if (sp->common_size == 0) + errx(1, "internal error: digest_pass1,3: " + "%s: not a common: %x", + sp->name, sp->defined); + /* + * Common not bound to shared object data; treat + * it now like other defined symbols were above. + */ + if (!sp->alias) + defined_global_sym_count++; } - sp=spsave; + sp=spsave; /*XXX*/ } END_EACH_SYMBOL; if (setv_fill_count != set_sect_size/sizeof(long)) |