diff options
Diffstat (limited to 'gnu/usr.bin')
-rw-r--r-- | gnu/usr.bin/ld/i386/md.c | 47 | ||||
-rw-r--r-- | gnu/usr.bin/ld/i386/md.h | 89 | ||||
-rw-r--r-- | gnu/usr.bin/ld/i386/mdprologue.S | 64 | ||||
-rw-r--r-- | gnu/usr.bin/ld/ld.c | 380 | ||||
-rw-r--r-- | gnu/usr.bin/ld/ld.h | 40 | ||||
-rw-r--r-- | gnu/usr.bin/ld/lib.c | 27 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rrs.c | 395 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/Makefile | 14 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/malloc.c | 5 | ||||
-rw-r--r-- | gnu/usr.bin/ld/rtld/rtld.c | 110 | ||||
-rw-r--r-- | gnu/usr.bin/ld/shlib.c | 4 | ||||
-rw-r--r-- | gnu/usr.bin/ld/sparc/md.h | 12 | ||||
-rw-r--r-- | gnu/usr.bin/ld/sparc/mdprologue.S | 6 | ||||
-rw-r--r-- | gnu/usr.bin/ld/warnings.c | 68 |
14 files changed, 706 insertions, 555 deletions
diff --git a/gnu/usr.bin/ld/i386/md.c b/gnu/usr.bin/ld/i386/md.c index 40d9916..07271fc 100644 --- a/gnu/usr.bin/ld/i386/md.c +++ b/gnu/usr.bin/ld/i386/md.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: md.c,v 1.10 1994/06/15 22:40:44 rich Exp $ + * $Id: md.c,v 1.11 1994/12/23 22:31:12 nate Exp $ */ #include <sys/param.h> @@ -58,9 +58,10 @@ unsigned char *addr; return get_short(addr); case 2: return get_long(addr); + default: + errx(1, "Unsupported relocation size: %x", + RELOC_TARGET_SIZE(rp)); } - errx(1, "Unsupported relocation size: %x", RELOC_TARGET_SIZE(rp)); - return 0; } /* @@ -76,15 +77,17 @@ int relocatable_output; switch (RELOC_TARGET_SIZE(rp)) { case 0: put_byte(addr, relocation); - return; + break; case 1: put_short(addr, relocation); - return; + break; case 2: put_long(addr, relocation); - return; + break; + default: + errx(1, "Unsupported relocation size: %x", + RELOC_TARGET_SIZE(rp)); } - errx(1, "Unsupported relocation size: %x", RELOC_TARGET_SIZE(rp)); } /* @@ -257,7 +260,7 @@ int magic, flags; #endif /* TEXT_START depends on the value of outheader.a_entry. */ - if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */ + if (!(link_mode & SHAREABLE)) hp->a_entry = PAGSIZ; } #endif /* RTLD */ @@ -305,15 +308,15 @@ int n; for (; n; n--, r++) { r->r_address = md_swap_long(r->r_address); bits = ((int *)r)[1]; - r->r_symbolnum = md_swap_long(bits & 0xffffff00); + r->r_symbolnum = md_swap_long(bits) & 0x00ffffff; r->r_pcrel = (bits & 1); - r->r_length = ((bits >> 1) & 3); - r->r_extern = ((bits >> 3) & 1); - r->r_baserel = ((bits >> 4) & 1); - r->r_jmptable = ((bits >> 5) & 1); - r->r_relative = ((bits >> 6) & 1); + r->r_length = (bits >> 1) & 3; + r->r_extern = (bits >> 3) & 1; + r->r_baserel = (bits >> 4) & 1; + r->r_jmptable = (bits >> 5) & 1; + r->r_relative = (bits >> 6) & 1; #ifdef N_SIZE - r->r_copy = ((bits >> 7) & 1); + r->r_copy = (bits >> 7) & 1; #endif } } @@ -327,15 +330,15 @@ int n; for (; n; n--, r++) { r->r_address = md_swap_long(r->r_address); - bits = (md_swap_long(r->r_symbolnum) & 0xffffff00); + bits = md_swap_long(r->r_symbolnum) & 0xffffff00; bits |= (r->r_pcrel & 1); - bits |= ((r->r_length << 1) & 6); - bits |= ((r->r_extern << 3) & 8); - bits |= ((r->r_baserel << 4) & 0x10); - bits |= ((r->r_jmptable << 5) & 0x20); - bits |= ((r->r_relative << 6) & 0x40); + bits |= (r->r_length & 3) << 1; + bits |= (r->r_extern & 1) << 3; + bits |= (r->r_baserel & 1) << 4; + bits |= (r->r_jmptable & 1) << 5; + bits |= (r->r_relative & 1) << 6; #ifdef N_SIZE - bits |= ((r->r_copy << 7) & 0x80); + bits |= (r->r_copy & 1) << 7; #endif ((int *)r)[1] = bits; } diff --git a/gnu/usr.bin/ld/i386/md.h b/gnu/usr.bin/ld/i386/md.h index 89c1213..da5283d 100644 --- a/gnu/usr.bin/ld/i386/md.h +++ b/gnu/usr.bin/ld/i386/md.h @@ -27,14 +27,12 @@ * (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.10 1994/06/15 22:40:46 rich Exp $ + * $Id: md.h,v 1.11 1994/12/23 22:31:14 nate Exp $ */ #if defined(CROSS_LINKER) && defined(XHOST) && XHOST==sparc - #define NEED_SWAP - #endif #define MAX_ALIGNMENT (sizeof (long)) @@ -144,6 +142,34 @@ typedef struct jmpslot { #ifdef CROSS_LINKER +#define get_byte(p) ( ((unsigned char *)(p))[0] ) + +#define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \ + ( ((unsigned char *)(p))[1] ) \ + ) + +#define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \ + ( ((unsigned char *)(p))[1] << 16) | \ + ( ((unsigned char *)(p))[2] << 8 ) | \ + ( ((unsigned char *)(p))[3] ) \ + ) + +#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); } + +#define put_short(p, v) { ((unsigned char *)(p))[0] = \ + ((((unsigned long)(v)) >> 8) & 0xff); \ + ((unsigned char *)(p))[1] = \ + ((((unsigned long)(v)) ) & 0xff); } + +#define put_long(p, v) { ((unsigned char *)(p))[0] = \ + ((((unsigned long)(v)) >> 24) & 0xff); \ + ((unsigned char *)(p))[1] = \ + ((((unsigned long)(v)) >> 16) & 0xff); \ + ((unsigned char *)(p))[2] = \ + ((((unsigned long)(v)) >> 8) & 0xff); \ + ((unsigned char *)(p))[3] = \ + ((((unsigned long)(v)) ) & 0xff); } + #ifdef NEED_SWAP /* Define IO byte swapping routines */ @@ -177,67 +203,11 @@ void md_swapout_jmpslot __P((jmpslot_t *, int)); #define md_swap_long(x) ( (((x) >> 24) & 0xff ) | (((x) >> 8 ) & 0xff00 ) | \ (((x) << 8 ) & 0xff0000) | (((x) << 24) & 0xff000000)) -#define get_byte(p) ( ((unsigned char *)(p))[0] ) - -#define get_short(p) ( ( ((unsigned char *)(p))[1] << 8) | \ - ( ((unsigned char *)(p))[0] ) \ - ) -#define get_long(p) ( ( ((unsigned char *)(p))[3] << 24) | \ - ( ((unsigned char *)(p))[2] << 16) | \ - ( ((unsigned char *)(p))[1] << 8 ) | \ - ( ((unsigned char *)(p))[0] ) \ - ) - -#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); } - -#define put_short(p, v) { ((unsigned char *)(p))[1] = \ - ((((unsigned long)(v)) >> 8) & 0xff); \ - ((unsigned char *)(p))[0] = \ - ((((unsigned long)(v)) ) & 0xff); } - -#define put_long(p, v) { ((unsigned char *)(p))[3] = \ - ((((unsigned long)(v)) >> 24) & 0xff); \ - ((unsigned char *)(p))[2] = \ - ((((unsigned long)(v)) >> 16) & 0xff); \ - ((unsigned char *)(p))[1] = \ - ((((unsigned long)(v)) >> 8) & 0xff); \ - ((unsigned char *)(p))[0] = \ - ((((unsigned long)(v)) ) & 0xff); } - #else /* We need not swap, but must pay attention to alignment: */ #define md_swap_short(x) (x) #define md_swap_long(x) (x) -#define get_byte(p) ( ((unsigned char *)(p))[0] ) - -#define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \ - ( ((unsigned char *)(p))[1] ) \ - ) - -#define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \ - ( ((unsigned char *)(p))[1] << 16) | \ - ( ((unsigned char *)(p))[2] << 8 ) | \ - ( ((unsigned char *)(p))[3] ) \ - ) - - -#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); } - -#define put_short(p, v) { ((unsigned char *)(p))[0] = \ - ((((unsigned long)(v)) >> 8) & 0xff); \ - ((unsigned char *)(p))[1] = \ - ((((unsigned long)(v)) ) & 0xff); } - -#define put_long(p, v) { ((unsigned char *)(p))[0] = \ - ((((unsigned long)(v)) >> 24) & 0xff); \ - ((unsigned char *)(p))[1] = \ - ((((unsigned long)(v)) >> 16) & 0xff); \ - ((unsigned char *)(p))[2] = \ - ((((unsigned long)(v)) >> 8) & 0xff); \ - ((unsigned char *)(p))[3] = \ - ((((unsigned long)(v)) ) & 0xff); } - #endif /* NEED_SWAP */ #else /* Not a cross linker: use native */ @@ -254,4 +224,3 @@ void md_swapout_jmpslot __P((jmpslot_t *, int)); #define put_long(where,what) (*(long *)(where) = (what)) #endif /* CROSS_LINKER */ - diff --git a/gnu/usr.bin/ld/i386/mdprologue.S b/gnu/usr.bin/ld/i386/mdprologue.S index 43640c6..1de0f72 100644 --- a/gnu/usr.bin/ld/i386/mdprologue.S +++ b/gnu/usr.bin/ld/i386/mdprologue.S @@ -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: mdprologue.S,v 1.4 1994/06/15 22:40:49 rich Exp $ + * $Id: mdprologue.S,v 1.7 1994/12/04 07:42:44 mycroft Exp $ */ /* @@ -35,7 +35,6 @@ */ #include <sys/syscall.h> -#define LCALL(x,y) .byte 0x9a ; .long y; .word x .text .globl _binder, _binder_entry @@ -46,76 +45,49 @@ _rtl: # crt0 calls us here pushl %ebp # Allocate stack frame - movl %esp, %ebp + movl %esp,%ebp pushl %ebx + call 1f # PIC function prologue 1: popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx - movl 12(%ebp), %eax # Extract data from interface structure + movl 12(%ebp),%eax # Extract data from interface structure movl (%eax),%eax # base address of ld.so (first field) # setup arguments for rtld() - movl (%ebx), %ecx # 1st entry in GOT is our __DYNAMIC - addl %eax, %ecx # add load address + movl (%ebx),%ecx # 1st entry in GOT is our __DYNAMIC + addl %eax,%ecx # add load address pushl %ecx # 3rd arg pushl 12(%ebp) # 2nd arg == &crt. pushl 8(%ebp) # 1st arg == version - addl _rtld@GOT(%ebx), %eax # relocate address of function + addl _rtld@GOT(%ebx),%eax # relocate address of function call %eax # _rtld(version, crtp, DYNAMIC) addl $12,%esp # pop arguments - movl -4(%ebp), %ebx # restore %ebx - leave # remove stack frame, - ret # let's rock + popl %ebx + leave # remove stack frame + ret # First call to a procedure generally comes through here for # binding. _binder_entry: pushl %ebp # setup a stack frame - movl %esp, %ebp + movl %esp,%ebp pusha # save all regs - movl $0, %eax # clear - movl 4(%ebp), %esi # return address in PLT - movw (%esi), %ax # get hold of relocation number - subl $6, %esi # make it point to the jmpslot + xorl %eax,%eax # clear + movl 4(%ebp),%esi # return address in PLT + movw (%esi),%ax # get hold of relocation number + subl $6,%esi # make it point to the jmpslot pushl %eax # pushd arguments pushl %esi # call _binder@PLT # _binder(rpc, index) - addl $8, %esp # pop arguments - movl %eax, 4(%ebp) # return value from _binder() == actual + addl $8,%esp # pop arguments + movl %eax,4(%ebp) # return value from _binder() == actual # address of function popa # restore regs leave # remove our stack frame ret - - # Special system call stubs which return real and effective user and group - # id's. Saves overhead of making separate calls for each. - # !! Relies on compatability option in BSD 4.three-and-a-half - - .globl _getreuid, _getregid -_getreuid: - lea SYS_getuid, %eax - LCALL(7,0) - jc out - movl 4(%esp), %ecx # get 1st arg - movl %eax, (%ecx) # put value in it - movl 8(%esp), %ecx # same for 2nd arg - movl %edx, (%ecx) # - ret # done - -_getregid: - lea SYS_getgid, %eax - LCALL(7,0) - jc out - movl 4(%esp), %ecx # get 1st arg - movl %eax, (%ecx) # put value in it - movl 8(%esp), %ecx # same for 2nd arg - movl %edx, (%ecx) # - ret # done - -out: jmp cerror@PLT # Call common error routine - diff --git a/gnu/usr.bin/ld/ld.c b/gnu/usr.bin/ld/ld.c index 5d713a0..14f7cd0 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.22 1994/06/15 22:39:40 rich Exp $ + * $Id: ld.c,v 1.23 1994/12/23 22:30:37 nate Exp $ */ /* Define how to initialize system-dependent header fields. */ @@ -135,7 +135,7 @@ int input_desc; /* The name of the file to write; "a.out" by default. */ char *output_filename; /* Output file name. */ -int outdesc; /* Output file descriptor. */ +FILE *outstream; /* Output file descriptor. */ struct exec outheader; /* Output file header. */ int magic; /* Output file magic. */ int oldmagic; @@ -183,11 +183,15 @@ int undefined_shobj_sym_count; /* # of undefined symbols referenced int multiple_def_count; /* # of multiply defined symbols. */ int defined_global_sym_count; /* # of defined global symbols. */ int common_defined_global_count; /* # of common symbols. */ +int undefined_weak_sym_count; /* # of weak symbols referenced and + not defined. */ +#if notused int special_sym_count; /* # of linker defined symbols. */ /* XXX - Currently, only __DYNAMIC and _G_O_T_ go here if required, * perhaps _etext, _edata and _end should go here too. */ +#endif int global_alias_count; /* # of aliased symbols */ int set_symbol_count; /* # of N_SET* symbols. */ int set_vector_count; /* # of set vectors in output. */ @@ -346,9 +350,6 @@ main(argc, argv) /* Create the symbols `etext', `edata' and `end'. */ symtab_init(relocatable_output); - /* Prepare for the run-time linking support. */ - init_rrs(); - /* * Determine whether to count the header as part of the text size, * and initialize the text size accordingly. This depends on the kind @@ -386,7 +387,7 @@ main(argc, argv) * Print error messages for any missing symbols, for any warning * symbols, and possibly multiple definitions */ - make_executable = do_warnings(stderr); + make_executable &= do_warnings(stderr); /* Print a map, if requested. */ if (write_map) @@ -1344,7 +1345,7 @@ enter_global_ref(lsp, name, entry) int olddef = sp->defined; int com = sp->defined && sp->common_size; - if (type == (N_INDR | N_EXT)) { + if (type == (N_INDR | N_EXT) && !olddef) { sp->alias = getsym(entry->strings + (lsp + 1)->nzlist.nz_strx); if (sp == sp->alias) { warnx("%s: %s is alias for itself", @@ -1356,6 +1357,10 @@ enter_global_ref(lsp, name, entry) } else { global_alias_count++; } +#if 0 + if (sp->flags & GS_REFERENCED) + sp->alias->flags |= GS_REFERENCED; +#endif } if (entry->flags & E_DYNAMIC) { @@ -1383,6 +1388,8 @@ enter_global_ref(lsp, name, entry) /* * This is an ex common... */ + if (com) + common_defined_global_count--; sp->common_size = 0; sp->defined = 0; } @@ -1428,32 +1435,72 @@ enter_global_ref(lsp, name, entry) return; } -#ifdef N_SIZE + if (olddef && N_ISWEAK(&nzp->nlist) && !(sp->flags & GS_WEAK)) { +#ifdef DEBUG + printf("%s: not overridden by weak symbol from %s\n", + sp->name, get_file_name(entry)); +#endif + return; + } + if (type == (N_SIZE | N_EXT)) { + if (relocatable_output && nzp->nz_value != 0 && sp->size == 0) size_sym_count++; if (sp->size < nzp->nz_value) sp->size = nzp->nz_value; - } else -#endif - if (type != (N_UNDF | N_EXT) || nzp->nz_value) { + + } else if (type != (N_UNDF | N_EXT) || nzp->nz_value) { /* * Set `->defined' here, so commons and undefined globals * can be counted correctly. */ - if (!sp->defined || sp->defined == (N_UNDF | N_EXT)) + if (!sp->defined || sp->defined == (N_UNDF | N_EXT)) { sp->defined = type; + } - if (oldref && !olddef) + if ((sp->flags & GS_WEAK) && !N_ISWEAK(&nzp->nlist)) { + /* + * Upgrade an existing weak definition. + * We fake it by pretending the symbol is undefined; + * must undo any common fiddling, however. + */ + if (!oldref) + errx(1, "internal error: enter_glob_ref: " + "weak symbol not referenced"); + if (!olddef && !com) + undefined_weak_sym_count--; + undefined_global_sym_count++; + sp->defined = type; + sp->flags &= ~GS_WEAK; + olddef = 0; + if (com) + common_defined_global_count--; + com = 0; + sp->common_size = 0; + } + if (oldref && !olddef) { /* * It used to be undefined and we're defining it. */ undefined_global_sym_count--; - if (undefined_global_sym_count < 0) - errx(1, - "internal error: enter_glob_ref: undefined_global_sym_count = %d", - undefined_global_sym_count); + if (sp->flags & GS_WEAK) + /* Used to be a weak reference */ + undefined_weak_sym_count--; + if (undefined_global_sym_count < 0 || + undefined_weak_sym_count < 0) + errx(1, "internal error: enter_glob_ref: " + "undefined_global_sym_count = %d, " + "undefined_weak_sym_count = %d", + undefined_global_sym_count, + undefined_weak_sym_count); + + } + + if (N_ISWEAK(&nzp->nlist)) + /* The definition is weak */ + sp->flags |= GS_WEAK; if (!olddef && type == (N_UNDF | N_EXT) && nzp->nz_value) { /* @@ -1479,13 +1526,18 @@ enter_global_ref(lsp, name, entry) if (SET_ELEMENT_P(type) && (!olddef || com)) set_vector_count++; - } else if (!oldref && !com) + } else if (!oldref && !com) { /* * An unreferenced symbol can already be defined * as common by shared objects. */ undefined_global_sym_count++; - + if (N_ISWEAK(&nzp->nlist)) { + /* The reference is weak */ + sp->flags |= GS_WEAK; + undefined_weak_sym_count++; + } + } if (sp == end_symbol && (entry->flags & E_JUST_SYMS) && !T_flag_specified) @@ -1495,8 +1547,8 @@ enter_global_ref(lsp, name, entry) register char *reftype; switch (type & N_TYPE) { case N_UNDF: - reftype = nzp->nz_value? - "defined as common":"referenced"; + reftype = nzp->nz_value + ? "defined as common" : "referenced"; break; case N_ABS: @@ -1515,12 +1567,21 @@ enter_global_ref(lsp, name, entry) reftype = "defined in BSS section"; break; + case N_INDR: + reftype = "alias"; + break; + + case N_SIZE: + reftype = "size spec"; + break; + default: reftype = "I don't know this type"; break; } - fprintf(stderr, "symbol %s %s in ", sp->name, reftype); + fprintf(stderr, "symbol %s %s%s in ", sp->name, + (N_ISWEAK(&nzp->nlist))?"weakly ":"", reftype); print_file_name (entry, stderr); fprintf(stderr, "\n"); } @@ -1707,17 +1768,20 @@ printf("set_sect_start = %#x, set_sect_size = %#x\n", } if (relocatable_output) - /* We write out the original N_SET* symbols */ + /* We write out the original N_SIZE symbols */ global_sym_count += size_sym_count; #ifdef DEBUG printf( -"global symbols %d (defined %d, undefined %d, aliases %d, warnings 2 * %d), \ -locals: %d, debug symbols: %d, set_symbols %d\n", +"global symbols %d " +"(defined %d, undefined %d, weak %d, aliases %d, warnings 2 * %d, " +"size symbols %d)\ncommons %d, locals: %d, debug symbols: %d, set_symbols %d\n", global_sym_count, defined_global_sym_count, undefined_global_sym_count, - global_alias_count, warn_sym_count, - local_sym_count, debugger_sym_count, set_symbol_count); + undefined_weak_sym_count, + global_alias_count, warn_sym_count, size_sym_count, + common_defined_global_count, local_sym_count, + debugger_sym_count, set_symbol_count); #endif } @@ -1738,6 +1802,7 @@ digest_pass1() * definition find this way. */ FOR_EACH_SYMBOL(i, sp) { + symbol *spsave; struct localsymbol *lsp; int defs = 0; @@ -1792,6 +1857,7 @@ digest_pass1() * of this set vector. */ bzero(&reloc, sizeof(reloc)); + RELOC_INIT_SEGMENT_RELOC(&reloc); RELOC_ADDRESS(&reloc) = setv_fill_count * sizeof(long); alloc_rrs_segment_reloc(NULL, &reloc); @@ -1801,15 +1867,18 @@ digest_pass1() && (type & N_TYPE) != N_FN && (type & N_TYPE) != N_SIZE) { /* non-common definition */ - if (defs++ && sp->value != p->n_value - && entry_symbol/*XXX*/) { + if (!N_ISWEAK(p)) + ++defs; + if (defs > 1) { sp->mult_defs = 1; multiple_def_count++; + } else if (!N_ISWEAK(p) || + (!sp->def_lsp && !sp->common_size)) { + sp->def_lsp = lsp; + lsp->entry->flags |= E_SYMBOLS_USED; + sp->defined = type; + sp->aux = N_AUX(p); } - sp->def_lsp = lsp; - lsp->entry->flags |= E_SYMBOLS_USED; - sp->defined = type; - sp->aux = N_AUX(p); } } @@ -1846,6 +1915,7 @@ digest_pass1() continue; } + spsave=sp; again: for (lsp = sp->sorefs; lsp; lsp = lsp->next) { register struct nlist *p = &lsp->nzlist.nlist; @@ -1858,31 +1928,41 @@ digest_pass1() sp->so_defined = type; sp->aux = N_AUX(p); if (lsp->entry->flags & E_SECONDCLASS) + /* Keep looking for something better */ continue; - lsp->entry->flags |= E_SYMBOLS_USED; - if (sp->flags & GS_REFERENCED) - undefined_global_sym_count--; - else - sp->flags |= GS_REFERENCED; + if (N_ISWEAK(p)) + /* Keep looking for something better */ + continue; + break; + } + } + if (sp->def_lsp) { #ifdef DEBUG -printf("shr: %s gets defined to %x with value %x\n", sp->name, type, sp->value); +printf("pass1: SO definition for %s, type %x in %s at %#x\n", + sp->name, sp->so_defined, get_file_name(sp->def_lsp->entry), + sp->def_lsp->nzlist.nz_value); #endif - if (undefined_global_sym_count < 0) - errx(1, - "internal error: digest_pass1,2: %s: undefined_global_sym_count = %d", + sp->def_lsp->entry->flags |= E_SYMBOLS_USED; + if (sp->flags & GS_REFERENCED) + undefined_global_sym_count--; + else + sp->flags |= GS_REFERENCED; + if (undefined_global_sym_count < 0) + errx(1, "internal error: digest_pass1,2: " + "%s: undefined_global_sym_count = %d", sp->name, undefined_global_sym_count); - if (sp->alias && !(sp->alias->flags & GS_REFERENCED)) { - sp = sp->alias; - goto again; - } - break; + if (sp->alias && + !(sp->alias->flags & GS_REFERENCED)) { + sp = sp->alias; + goto again; } } + sp=spsave; } END_EACH_SYMBOL; if (setv_fill_count != set_sect_size/sizeof(long)) - errx(1, "internal error: allocated set symbol space (%d) \ -doesn't match actual (%d)", + errx(1, "internal error: allocated set symbol space (%d) " + "doesn't match actual (%d)", set_sect_size/sizeof(long), setv_fill_count); } @@ -1987,7 +2067,7 @@ consider_relocation(entry, dataseg) lsp = &entry->symbols[reloc->r_symbolnum]; sp = lsp->symbol; if (sp == NULL) - errx(1, "%s: internal error, sp==NULL", + errx(1, "%s: bogus relocation record", get_file_name(entry)); if (sp->alias) @@ -2031,7 +2111,8 @@ consider_relocation(entry, dataseg) alloc_rrs_cpy_reloc(entry, sp); sp->defined = N_SIZE; - } else if (!sp->defined && sp->common_size == 0) + } else if (!sp->defined && sp->common_size == 0 && + sp->so_defined) alloc_rrs_reloc(entry, sp); } else { @@ -2217,14 +2298,27 @@ digest_pass2() continue; if (sp->alias && - (relocatable_output || building_shared_object || - (sp->alias->defined && !sp->alias->so_defined))) + (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. */ + if (!sp->defined) { + /* + * Change aliased symbol's definition too. + * These things happen if shared object commons + * or data is going into our symbol table. + */ + if (sp->so_defined != (N_INDR+N_EXT)) + warnx( "pass2: %s: alias isn't", + sp->name); + sp->defined = sp->so_defined; + sp->so_defined = 0; + } defined_global_sym_count++; + } if ((sp->defined & N_TYPE) == N_SETV) { /* @@ -2253,6 +2347,7 @@ digest_pass2() struct relocation_info reloc; bzero(&reloc, sizeof(reloc)); + RELOC_INIT_SEGMENT_RELOC(&reloc); RELOC_ADDRESS(&reloc) = (1 + i + length_word_index) * sizeof(long) @@ -2284,7 +2379,11 @@ digest_pass2() sp->value = sp->def_lsp->nzlist.nz_value; if (sp->so_defined && (sp->def_lsp->entry->flags & E_SECONDCLASS)) + /* Flag second-hand definitions */ undefined_global_sym_count++; + if (sp->flags & GS_TRACE) + printf("symbol %s assigned to location %#x\n", + sp->name, sp->value); } /* @@ -2333,11 +2432,9 @@ digest_pass2() size = PALIGN(size, sizeof(int)); - while (!(size & align)) + while (align < MAX_ALIGNMENT && !(size & align)) align <<= 1; - align = align > MAX_ALIGNMENT ? MAX_ALIGNMENT : align; - bss_size = PALIGN(bss_size + data_size + rrs_data_start, align) - (data_size + rrs_data_start); @@ -2372,19 +2469,21 @@ write_output() (void)unlink(output_filename); } - outdesc = open(output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (outdesc < 0) + outstream = fopen(output_filename, "w"); + if (outstream == NULL) err(1, "open: %s", output_filename); if (atexit(cleanup)) err(1, "atexit"); - if (fstat (outdesc, &statbuf) < 0) + if (fstat(fileno(outstream), &statbuf) < 0) err(1, "fstat: %s", output_filename); filemode = statbuf.st_mode; - chmod (output_filename, filemode & ~0111); + if (S_ISREG(statbuf.st_mode) && + chmod(output_filename, filemode & ~0111) == -1) + err(1, "chmod: %s", output_filename); /* Output the a.out header. */ write_header(); @@ -2406,8 +2505,11 @@ write_output() if (chmod (output_filename, filemode | 0111) == -1) err(1, "chmod: %s", output_filename); - close(outdesc); - outdesc = 0; + fflush(outstream); + /* Report I/O error such as disk full. */ + if (ferror(outstream) || fclose(outstream) != 0) + err(1, "write_output: %s", output_filename); + outstream = 0; } /* Total number of symbols to be written in the output file. */ @@ -2419,12 +2521,19 @@ write_header() int flags; if (link_mode & SHAREABLE) + /* Output is shared object */ flags = EX_DYNAMIC | EX_PIC; - else if (pic_code_seen) + else if (relocatable_output && pic_code_seen) + /* Output is relocatable and contains PIC code */ flags = EX_PIC; else if (rrs_section_type == RRS_FULL) + /* Output is a dynamic executable */ flags = EX_DYNAMIC; else + /* + * Output is a static executable + * or a non-PIC relocatable object + */ flags = 0; if (oldmagic && (flags & EX_DPMASK)) @@ -2457,7 +2566,7 @@ write_header() } md_swapout_exec_hdr(&outheader); - mywrite(&outheader, sizeof (struct exec), 1, outdesc); + mywrite(&outheader, sizeof (struct exec), 1, outstream); md_swapin_exec_hdr(&outheader); /* @@ -2466,7 +2575,7 @@ write_header() */ #ifndef COFF_ENCAPSULATE - padfile(N_TXTOFF(outheader) - sizeof outheader, outdesc); + padfile(N_TXTOFF(outheader) - sizeof outheader, outstream); #endif } @@ -2487,7 +2596,7 @@ write_text() if (trace_files) fprintf(stderr, "\n"); - padfile(text_pad, outdesc); + padfile(text_pad, outstream); } /* @@ -2525,7 +2634,7 @@ copy_text(entry) entry->textrel, entry->ntextrel, entry, 0); /* Write the relocated text to the output file. */ - mywrite(bytes, 1, entry->header.a_text, outdesc); + mywrite(bytes, 1, entry->header.a_text, outstream); } /* @@ -2542,8 +2651,8 @@ write_data() fprintf(stderr, "Copying and relocating data:\n\n"); pos = N_DATOFF(outheader) + data_start - rrs_data_start; - if (lseek(outdesc, pos, L_SET) != pos) - errx(1, "write_data: lseek"); + if (fseek(outstream, pos, SEEK_SET) != 0) + errx(1, "write_data: fseek"); each_full_file(copy_data, 0); file_close(); @@ -2556,13 +2665,13 @@ write_data() if (set_vector_count) { swap_longs(set_vectors, set_symbol_count + 2*set_vector_count); mywrite(set_vectors, set_symbol_count + 2*set_vector_count, - sizeof (unsigned long), outdesc); + sizeof (unsigned long), outstream); } if (trace_files) fprintf(stderr, "\n"); - padfile(data_pad, outdesc); + padfile(data_pad, outstream); } /* @@ -2596,7 +2705,7 @@ copy_data(entry) perform_relocation(bytes, entry->header.a_data, entry->datarel, entry->ndatarel, entry, 1); - mywrite(bytes, 1, entry->header.a_data, outdesc); + mywrite(bytes, 1, entry->header.a_data, outstream); } /* @@ -2657,6 +2766,9 @@ perform_relocation(data, data_size, reloc, nreloc, entry, dataseg) get_file_name(entry)); sp = lsp->symbol; + if (sp == NULL) + errx(1, "%s: bogus relocation record", + get_file_name(entry)); if (sp->alias) sp = sp->alias; @@ -2697,6 +2809,9 @@ perform_relocation(data, data_size, reloc, nreloc, entry, dataseg) get_file_name(entry)); sp = entry->symbols[symindex].symbol; + if (sp == NULL) + errx(1, "%s: bogus relocation record", + get_file_name(entry)); if (sp->alias) sp = sp->alias; @@ -2761,11 +2876,11 @@ perform_relocation(data, data_size, reloc, nreloc, entry, dataseg) "symbol %s claims RRS in %s%s\n", sp->name, get_file_name(entry), (sp->so_defined == (N_TEXT+N_EXT) && - sp->jmpslot_offset != -1)? + sp->flags & GS_HASJMPSLOT)? " (JMPSLOT)":""); } if (sp->so_defined == (N_TEXT+N_EXT) && - sp->jmpslot_offset != -1) { + sp->flags & GS_HASJMPSLOT) { /* * Claim a jmpslot if one was allocated. * @@ -2781,8 +2896,10 @@ perform_relocation(data, data_size, reloc, nreloc, entry, dataseg) entry->data_start_address: entry->text_start_address; relocation = addend; - if (claim_rrs_reloc( - entry, r, sp, &relocation)) + if ((building_shared_object || + sp->so_defined) && + claim_rrs_reloc(entry, r, sp, + &relocation)) continue; } } @@ -3005,7 +3122,7 @@ coptxtrel(entry) } md_swapout_reloc(entry->textrel, entry->ntextrel); mywrite(entry->textrel, entry->ntextrel, - sizeof(struct relocation_info), outdesc); + sizeof(struct relocation_info), outstream); } static void @@ -3070,7 +3187,7 @@ copdatrel(entry) } md_swapout_reloc(entry->datarel, entry->ndatarel); mywrite(entry->datarel, entry->ndatarel, - sizeof(struct relocation_info), outdesc); + sizeof(struct relocation_info), outstream); } void write_file_syms __P((struct file_entry *, int *)); @@ -3078,15 +3195,15 @@ void write_string_table __P((void)); /* Offsets and current lengths of symbol and string tables in output file. */ -static int symbol_table_offset; -static int symbol_table_len; +static int symtab_offset; +static int symtab_len; /* Address in output file where string table starts. */ -static int string_table_offset; +static int strtab_offset; /* Offset within string table where the strings in `strtab_vector' should be written. */ -static int string_table_len; +static int strtab_len; /* Total size of string table strings allocated so far, including strings in `strtab_vector'. */ @@ -3121,8 +3238,6 @@ assign_string_table_index(name) return index; } -FILE *outstream = (FILE *)0; - /* * Write the contents of `strtab_vector' into the string table. This is done * once for each file's local&debugger symbols and once for the global @@ -3133,23 +3248,13 @@ write_string_table() { register int i; - if (lseek(outdesc, string_table_offset + string_table_len, 0) == - (off_t)-1) - err(1, "write_string_table: %s: lseek", output_filename); - - if (!outstream) - outstream = fdopen(outdesc, "w"); + if (fseek(outstream, strtab_offset + strtab_len, SEEK_SET) != 0) + err(1, "write_string_table: %s: fseek", output_filename); for (i = 0; i < strtab_index; i++) { - fwrite (strtab_vector[i], 1, strtab_lens[i], outstream); - string_table_len += strtab_lens[i]; + mywrite(strtab_vector[i], 1, strtab_lens[i], outstream); + strtab_len += strtab_lens[i]; } - - fflush(outstream); - - /* Report I/O error such as disk full. */ - if (ferror(outstream)) - err(1, "write_string_table: %s", output_filename); } /* Write the symbol table and string table of the output file. */ @@ -3173,10 +3278,10 @@ write_syms() /* Size of string table includes the bytes that store the size. */ strtab_size = sizeof strtab_size; - symbol_table_offset = N_SYMOFF(outheader); - symbol_table_len = 0; - string_table_offset = N_STROFF(outheader); - string_table_len = strtab_size; + symtab_offset = N_SYMOFF(outheader); + symtab_len = 0; + strtab_offset = N_STROFF(outheader); + strtab_len = strtab_size; if (strip_symbols == STRIP_ALL) return; @@ -3264,9 +3369,10 @@ write_syms() * these, symbol was discounted in digest_pass1() * (they are in the RRS symbol table). */ - if (!building_shared_object) + if (building_shared_object) + continue; + if (!(sp->flags & GS_WEAK)) warnx("symbol %s remains undefined", sp->name); - continue; } if (syms_written >= global_sym_count) @@ -3296,6 +3402,8 @@ write_syms() nl.n_value = sp->alias->value; nl.n_other = N_OTHER(0, sp->alias->aux); } else { + int bind = 0; + if (sp->defined == N_SIZE) nl.n_type = N_DATA | N_EXT; else @@ -3305,7 +3413,9 @@ write_syms() errx(1, "%s: N_INDR has value %#x", sp->name, sp->value); nl.n_value = sp->value; - nl.n_other = N_OTHER(0, sp->aux); + if (sp->def_lsp) + bind = N_BIND(&sp->def_lsp->nzlist.nlist); + nl.n_other = N_OTHER(bind, sp->aux); } } else if (sp->common_size) { @@ -3375,18 +3485,17 @@ printf("writesym(#%d): %s, type %x\n", syms_written, sp->name, sp->defined); } END_EACH_SYMBOL; if (syms_written != strtab_index || strtab_index != global_sym_count) - errx(1, "internal error:\ -wrong number (%d) of global symbols written into output file, should be %d", - syms_written, global_sym_count); + errx(1, "internal error: wrong number (%d) of global symbols " + "written into output file, should be %d", + syms_written, global_sym_count); /* Output the buffer full of `struct nlist's. */ - if (lseek(outdesc, symbol_table_offset + symbol_table_len, 0) == - (off_t)-1) - err(1, "write_syms: lseek"); + if (fseek(outstream, symtab_offset + symtab_len, SEEK_SET) != 0) + err(1, "write_syms: fseek"); md_swapout_symbols(buf, bufp - buf); - mywrite(buf, bufp - buf, sizeof(struct nlist), outdesc); - symbol_table_len += sizeof(struct nlist) * (bufp - buf); + mywrite(buf, bufp - buf, sizeof(struct nlist), outstream); + symtab_len += sizeof(struct nlist) * (bufp - buf); /* Write the strings for the global symbols. */ write_string_table(); @@ -3396,18 +3505,19 @@ wrong number (%d) of global symbols written into output file, should be %d", file_close(); if (syms_written != nsyms) - errx(1, "internal error:\ -wrong number of symbols (%d) written into output file, should be %d", - syms_written, nsyms); + errx(1, "internal error: wrong number of symbols (%d) " + "written into output file, should be %d", + syms_written, nsyms); - if (symbol_table_offset + symbol_table_len != string_table_offset) + if (symtab_offset + symtab_len != strtab_offset) errx(1, "internal error: inconsistent symbol table length: %d vs %s", - symbol_table_offset + symbol_table_len, string_table_offset); + symtab_offset + symtab_len, strtab_offset); - lseek(outdesc, string_table_offset, 0); + if (fseek(outstream, strtab_offset, SEEK_SET) != 0) + err(1, "write_syms: fseek"); strtab_size = md_swap_long(strtab_size); - mywrite(&strtab_size, sizeof(int), 1, outdesc); + mywrite(&strtab_size, sizeof(int), 1, outstream); } @@ -3507,10 +3617,11 @@ write_file_syms(entry, syms_written_addr) /* All the symbols are now in BUF; write them. */ - lseek(outdesc, symbol_table_offset + symbol_table_len, 0); + if (fseek(outstream, symtab_offset + symtab_len, SEEK_SET) != 0) + err(1, "write local symbols: fseek"); md_swapout_symbols(buf, bufp - buf); - mywrite(buf, bufp - buf, sizeof(struct nlist), outdesc); - symbol_table_len += sizeof(struct nlist) * (bufp - buf); + mywrite(buf, bufp - buf, sizeof(struct nlist), outstream); + symtab_len += sizeof(struct nlist) * (bufp - buf); /* * Write the string-table data for the symbols just written, using @@ -3546,18 +3657,11 @@ mywrite(buf, count, eltsize, fd) void *buf; int count; int eltsize; - int fd; + FILE *fd; { - register int val; - register int bytes = count * eltsize; - - while (bytes > 0) { - val = write(fd, buf, bytes); - if (val <= 0) - err(1, "write: %s", output_filename); - buf += val; - bytes -= val; - } + + if (fwrite(buf, eltsize, count, fd) != count) + err(1, "write"); } static void @@ -3565,10 +3669,10 @@ cleanup() { struct stat statbuf; - if (outdesc <= 0) + if (outstream == 0) return; - if (fstat(outdesc, &statbuf) == 0) { + if (fstat(fileno(outstream), &statbuf) == 0) { if (S_ISREG(statbuf.st_mode)) (void)unlink(output_filename); } @@ -3580,8 +3684,8 @@ cleanup() */ void padfile(padding, fd) - int padding; - int fd; + int padding; + FILE *fd; { register char *buf; if (padding <= 0) diff --git a/gnu/usr.bin/ld/ld.h b/gnu/usr.bin/ld/ld.h index 58e5c1e..6b4b7f5 100644 --- a/gnu/usr.bin/ld/ld.h +++ b/gnu/usr.bin/ld/ld.h @@ -1,5 +1,5 @@ /* - * $Id: ld.h,v 1.11 1994/06/15 22:39:46 rich Exp $ + * $Id: ld.h,v 1.12 1994/12/23 22:30:42 nate Exp $ */ /*- * This code is derived from software copyrighted by the Free Software @@ -151,6 +151,16 @@ extern int netzmagic; #define CHECK_GOT_RELOC(r) ((r)->r_pcrel) +#define RELOC_INIT_SEGMENT_RELOC(r) + +#endif + +#ifndef MAX_GOTOFF +#define MAX_GOTOFF (LONG_MAX) +#endif + +#ifndef MIN_GOTOFF +#define MIN_GOTOFF (LONG_MIN) #endif /* @@ -309,7 +319,6 @@ extern int netzmagic; #ifndef __GNU_STAB__ - /* Line number for the data section. This is to be used to describe the source location of a variable declaration. */ #ifndef N_DSLINE @@ -321,9 +330,10 @@ extern int netzmagic; #ifndef N_BSLINE #define N_BSLINE (N_SLINE+N_BSS-N_TEXT) #endif - #endif /* not __GNU_STAB__ */ - + +#define N_ISWEAK(p) (N_BIND(p) & BIND_WEAK) + typedef struct localsymbol { struct nzlist nzlist; /* n[z]list from file */ @@ -337,7 +347,7 @@ typedef struct localsymbol { #define LS_L_SYMBOL 1 /* Local symbol starts with an `L' */ #define LS_WRITE 2 /* Symbol goes in output symtable */ #define LS_RENAME 4 /* xlat name to `<file>.<name>' */ -#define LS_GOTSLOTCLAIMED 8 /* This symbol has a GOT entry */ +#define LS_HASGOTSLOT 8 /* This symbol has a GOT entry */ #define LS_WARNING 16 /* Second part of a N_WARNING duo */ } localsymbol_t; @@ -388,14 +398,15 @@ typedef struct glosym { long flags; -#define GS_DEFINED 1 /* Symbol has definition (notyetused)*/ -#define GS_REFERENCED 2 /* Symbol is referred to by something +#define GS_DEFINED 0x1 /* Symbol has definition (notyetused)*/ +#define GS_REFERENCED 0x2 /* Symbol is referred to by something interesting */ -#define GS_TRACE 4 /* Symbol will be traced */ -#define GS_JMPSLOTCLAIMED 8 /* */ -#define GS_GOTSLOTCLAIMED 0x10 /* Some state bits concerning */ +#define GS_TRACE 0x4 /* Symbol will be traced */ +#define GS_HASJMPSLOT 0x8 /* */ +#define GS_HASGOTSLOT 0x10 /* Some state bits concerning */ #define GS_CPYRELOCRESERVED 0x20 /* entries in GOT and PLT tables */ #define GS_CPYRELOCCLAIMED 0x40 /* */ +#define GS_WEAK 0x80 /* Symbol is weakly defined */ } symbol; @@ -415,6 +426,9 @@ extern symbol *symtab[]; /* # of global symbols referenced and not defined. */ extern int undefined_global_sym_count; +/* # of weak symbols referenced and not defined. */ +extern int undefined_weak_sym_count; + /* # of undefined symbols referenced by shared objects */ extern int undefined_shobj_sym_count; @@ -575,7 +589,7 @@ extern int link_mode; #define SHAREABLE 8 /* Build a shared object */ #define SILLYARCHIVE 16 /* Process .sa companions, if any */ -extern int outdesc; /* Output file descriptor. */ +extern FILE *outstream; /* Output file. */ extern struct exec outheader; /* Output file header. */ extern int magic; /* Output file magic. */ extern int oldmagic; @@ -601,8 +615,8 @@ int file_open __P((struct file_entry *)); void each_file __P((void (*)(), void *)); void each_full_file __P((void (*)(), void *)); unsigned long check_each_file __P((unsigned long (*)(), void *)); -void mywrite __P((void *, int, int, int)); -void padfile __P((int,int)); +void mywrite __P((void *, int, int, FILE *)); +void padfile __P((int, FILE *)); /* In warnings.c: */ void perror_name __P((char *)); diff --git a/gnu/usr.bin/ld/lib.c b/gnu/usr.bin/ld/lib.c index 737b526..25512bb 100644 --- a/gnu/usr.bin/ld/lib.c +++ b/gnu/usr.bin/ld/lib.c @@ -1,5 +1,5 @@ /* - * $Id: lib.c,v 1.10 1994/06/15 22:39:49 rich Exp $ - library routines + * $Id: lib.c,v 1.11 1994/12/23 22:30:45 nate Exp $ - library routines */ #include <sys/param.h> @@ -260,6 +260,12 @@ symdef_library(fd, entry, member_length) * be satisfied are 'common' references. This * prevents some problems with name pollution (e.g. a * global common 'utime' linked to a function). + * + * If we're not forcing the archive in then we don't + * need to bother if: we've never heard of the symbol, + * or if it is already defined. The last clause causes + * archive members to be searched for definitions + * satisfying undefined shared object symbols. */ if (!(link_mode & FORCEARCHIVE) && (!sp || sp->defined || @@ -501,6 +507,9 @@ subfile_wanted_p(entry) sp->defined = type; continue; } + if (sp->flags & GS_WEAK) + /* Weak symbols don't pull archive members */ + continue; if (write_map) { print_file_name(entry, stdout); fprintf(stdout, " needed due to %s\n", sp->name); @@ -542,8 +551,19 @@ subfile_wanted_p(entry) * a common; ignore it. */ continue; + + if (N_ISWEAK(&lsp->nzlist.nlist)) + /* Weak symbols don't pull archive members */ + continue; } + /* + * At this point, either the new symbol is a common + * and the shared object reference is undefined -- + * in which case we note the common -- or the shared + * object reference has a definition -- in which case + * the library member takes precedence. + */ if (iscommon) { /* * New symbol is common, just takes its @@ -565,8 +585,9 @@ subfile_wanted_p(entry) if (write_map) { print_file_name(entry, stdout); fprintf(stdout, - " needed due to shared lib ref %s\n", - sp->name); + " needed due to shared lib ref %s (%d)\n", + sp->name, + lsp ? lsp->nzlist.nlist.n_type : -1); } return 1; } diff --git a/gnu/usr.bin/ld/rrs.c b/gnu/usr.bin/ld/rrs.c index 93ad89b..2d1b3bc 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.12 1994/06/15 22:39:52 rich Exp $ + * $Id: rrs.c,v 1.13 1994/12/23 22:30:48 nate Exp $ */ #include <sys/param.h> @@ -64,8 +64,8 @@ static int reserved_rrs_relocs; static int claimed_rrs_relocs; static int discarded_rrs_relocs; -static int number_of_gotslots; -static int number_of_jmpslots; +static int number_of_gotslots = 1; +static int number_of_jmpslots = 1; static int number_of_rrs_hash_entries; static int number_of_rrs_symbols; static int rrs_strtab_size; @@ -73,10 +73,14 @@ static int rrs_symbol_size; static int current_jmpslot_offset; static int current_got_offset; +static int got_origin; static int current_reloc_offset; static int current_hash_index; int number_of_shobjs; +/* Convert a GOT offset into a table entry */ +#define GOTP(off) ((got_t *)((long)rrs_got + got_origin + (off))) + struct shobj { struct shobj *next; struct file_entry *entry; @@ -125,9 +129,10 @@ RRS data segment: | | | sdt | | | - +-------------------+ <-- _GLOBAL_OFFSET_TABLE_ (sdt_got) + +-------------------+ <-- sdt_got | | - | _GOT_ | + | _GOT_ | <-- _GLOBAL_OFFSET_TABLE_ + | | ( == sdt_got + got_origin) | | +-------------------+ <-- sdt_plt | | @@ -137,37 +142,12 @@ RRS data segment: */ /* - * Initialize RRS - */ - -void -init_rrs() -{ - reserved_rrs_relocs = 0; - claimed_rrs_relocs = 0; - discarded_rrs_relocs = 0; - - number_of_rrs_symbols = 0; - rrs_strtab_size = 0; - - /* First jmpslot reserved for run-time binder */ - current_jmpslot_offset = sizeof(jmpslot_t); - number_of_jmpslots = 1; - - /* First gotslot reserved for __DYNAMIC */ - current_got_offset = sizeof(got_t); - number_of_gotslots = 1; - - current_reloc_offset = 0; -} - -/* * Add NAME to the list of needed run-time objects. * Return 1 if ENTRY was added to the list. */ int rrs_add_shobj(entry) -struct file_entry *entry; + struct file_entry *entry; { struct shobj **p; @@ -184,8 +164,8 @@ struct file_entry *entry; void alloc_rrs_reloc(entry, sp) -struct file_entry *entry; -symbol *sp; + struct file_entry *entry; + symbol *sp; { #ifdef DEBUG printf("alloc_rrs_reloc: %s in %s\n", sp->name, get_file_name(entry)); @@ -195,8 +175,8 @@ printf("alloc_rrs_reloc: %s in %s\n", sp->name, get_file_name(entry)); void alloc_rrs_segment_reloc(entry, r) -struct file_entry *entry; -struct relocation_info *r; + struct file_entry *entry; + struct relocation_info *r; { #ifdef DEBUG printf("alloc_rrs_segment_reloc at %#x in %s\n", @@ -207,30 +187,31 @@ printf("alloc_rrs_segment_reloc at %#x in %s\n", void alloc_rrs_jmpslot(entry, sp) -struct file_entry *entry; -symbol *sp; + struct file_entry *entry; + symbol *sp; { - if (sp->jmpslot_offset == -1) { - sp->jmpslot_offset = current_jmpslot_offset; - current_jmpslot_offset += sizeof(jmpslot_t); - number_of_jmpslots++; - reserved_rrs_relocs++; - } + if (sp->flags & GS_HASJMPSLOT) + return; + + sp->flags |= GS_HASJMPSLOT; + number_of_jmpslots++; + reserved_rrs_relocs++; } void alloc_rrs_gotslot(entry, r, lsp) -struct file_entry *entry; -struct relocation_info *r; -struct localsymbol *lsp; + struct file_entry *entry; + struct relocation_info *r; + struct localsymbol *lsp; { symbol *sp = lsp->symbol; if (!RELOC_EXTERN_P(r)) { if (sp != NULL) { - warnx("%s: relocation for internal symbol expected at %#x", - get_file_name(entry), RELOC_ADDRESS(r)); + warnx("%s: relocation for internal symbol " + "expected at %#x", + get_file_name(entry), RELOC_ADDRESS(r)); return; } @@ -238,38 +219,37 @@ struct localsymbol *lsp; /* No need for a GOT slot */ return; - if (lsp->gotslot_offset == -1) { - lsp->gotslot_offset = current_got_offset; - current_got_offset += sizeof(got_t); - number_of_gotslots++; - reserved_rrs_relocs++; - } + if (lsp->flags & LS_HASGOTSLOT) + return; + + lsp->flags |= LS_HASGOTSLOT; } else { if (sp == NULL) { - warnx("%s: relocation must refer to global symbol at %#x", - get_file_name(entry), RELOC_ADDRESS(r)); + warnx("%s: relocation must refer " + "to global symbol at %#x", + get_file_name(entry), RELOC_ADDRESS(r)); return; } if (sp->alias) sp = sp->alias; - if (sp->gotslot_offset == -1) { - sp->gotslot_offset = current_got_offset; - current_got_offset += sizeof(got_t); - number_of_gotslots++; - reserved_rrs_relocs++; - } + if (sp->flags & GS_HASGOTSLOT) + return; + + sp->flags |= GS_HASGOTSLOT; } + number_of_gotslots++; + reserved_rrs_relocs++; } void alloc_rrs_cpy_reloc(entry, sp) -struct file_entry *entry; -symbol *sp; + struct file_entry *entry; + symbol *sp; { if (sp->flags & GS_CPYRELOCRESERVED) return; @@ -302,10 +282,10 @@ rrs_next_reloc() */ int claim_rrs_reloc(entry, rp, sp, relocation) -struct file_entry *entry; -struct relocation_info *rp; -symbol *sp; -long *relocation; + struct file_entry *entry; + struct relocation_info *rp; + symbol *sp; + long *relocation; { struct relocation_info *r = rrs_next_reloc(); @@ -322,7 +302,7 @@ printf("claim_rrs_reloc: %s in %s\n", sp->name, get_file_name(entry)); if (link_mode & SYMBOLIC) { if (!sp->defined) warnx("Cannot reduce symbol \"%s\" in %s", - sp->name, get_file_name(entry)); + sp->name, get_file_name(entry)); RELOC_EXTERN_P(r) = 0; *relocation += sp->value; (void) md_make_reloc(rp, r, RELTYPE_RELATIVE); @@ -338,28 +318,31 @@ printf("claim_rrs_reloc: %s in %s\n", sp->name, get_file_name(entry)); */ long claim_rrs_jmpslot(entry, rp, sp, addend) -struct file_entry *entry; -struct relocation_info *rp; -symbol *sp; -long addend; + struct file_entry *entry; + struct relocation_info *rp; + symbol *sp; + long addend; { struct relocation_info *r; - if (sp->flags & GS_JMPSLOTCLAIMED) + if (!(sp->flags & GS_HASJMPSLOT)) + errx(1, "internal error: " + "%s: claim_rrs_jmpslot: %s: no reservation", + get_file_name(entry), + sp->name); + + if (sp->jmpslot_offset != -1) return rrs_sdt.sdt_plt + sp->jmpslot_offset; + sp->jmpslot_offset = current_jmpslot_offset; + current_jmpslot_offset += sizeof(jmpslot_t); + #ifdef DEBUG printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x\n", get_file_name(entry), sp->name, sp->rrs_symbolnum, sp->jmpslot_offset); #endif - if (sp->jmpslot_offset == -1) - errx(1, - "internal error: %s: claim_rrs_jmpslot: %s: jmpslot_offset == -1\n", - get_file_name(entry), - sp->name); - if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) { if (!sp->defined) warnx("Cannot reduce symbol \"%s\" in %s", @@ -370,7 +353,6 @@ printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x\n", sp->value); if (rrs_section_type == RRS_PARTIAL || !JMPSLOT_NEEDS_RELOC) { /* PLT is self-contained */ - sp->flags |= GS_JMPSLOTCLAIMED; discarded_rrs_relocs++; return rrs_sdt.sdt_plt + sp->jmpslot_offset; } @@ -384,7 +366,6 @@ printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x\n", * Install a run-time relocation for this PLT entry. */ r = rrs_next_reloc(); - sp->flags |= GS_JMPSLOTCLAIMED; RELOC_SYMBOL(r) = sp->rrs_symbolnum; @@ -408,10 +389,10 @@ printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x\n", */ long claim_rrs_gotslot(entry, rp, lsp, addend) -struct file_entry *entry; -struct relocation_info *rp; -struct localsymbol *lsp; -long addend; + struct file_entry *entry; + struct relocation_info *rp; + struct localsymbol *lsp; + long addend; { struct relocation_info *r; symbol *sp = lsp->symbol; @@ -424,28 +405,42 @@ long addend; if (sp->alias) sp = sp->alias; -#ifdef DEBUG -printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", - sp->name, sp->rrs_symbolnum, sp->value, sp->gotslot_offset, addend); -#endif - if (sp->gotslot_offset == -1) - errx(1, - "internal error: %s: claim_rrs_gotslot: %s: gotslot_offset == -1\n", + if (!(sp->flags & GS_HASGOTSLOT)) + errx(1, "internal error: " + "%s: claim_rrs_gotslot: %s: no reservation", get_file_name(entry), sp->name); - if (sp->flags & GS_GOTSLOTCLAIMED) { -#ifdef DEBUG - if (*(long *)((long)rrs_got + sp->gotslot_offset) != addend + - (!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC)) - ?sp->value:0) - errx(1, "%s: %s: gotslot at %#x is multiple valued\n", + if (sp->gotslot_offset != -1) { +#ifdef DIAGNOSTIC + if (*GOTP(sp->gotslot_offset) != addend + + ((!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC)) + ? sp->value : 0)) + errx(1, "%s: %s: gotslot at %#x is multiple valued, " + "*got = %#x, addend = %#x, sp->value = %#x", get_file_name(entry), sp->name, - sp->gotslot_offset); + sp->gotslot_offset, + *GOTP(sp->gotslot_offset), addend, sp->value); #endif /* This symbol already passed here before. */ return sp->gotslot_offset; } + if (current_got_offset == 0) + /* GOT offset 0 is reserved */ + current_got_offset += sizeof(got_t); + + if (current_got_offset > MAX_GOTOFF) + errx(1, "%s: GOT overflow on symbol `%s' at %#x", + get_file_name(entry), sp->name, RELOC_ADDRESS(rp)); + + sp->gotslot_offset = current_got_offset; + current_got_offset += sizeof(got_t); + +#ifdef DEBUG +printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", + sp->name, sp->rrs_symbolnum, sp->value, sp->gotslot_offset, addend); +#endif + if (sp->defined && (!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))) { @@ -453,8 +448,7 @@ printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", * Reduce to just a base-relative translation. */ - *(got_t *)((long)rrs_got + sp->gotslot_offset) = - sp->value + addend; + *GOTP(sp->gotslot_offset) = sp->value + addend; reloc_type = RELTYPE_RELATIVE; } else if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) { @@ -464,7 +458,7 @@ printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", * so again all symbols must be known. */ warnx("Cannot reduce symbol \"%s\" in %s", - sp->name, get_file_name(entry)); + sp->name, get_file_name(entry)); } else { @@ -472,7 +466,7 @@ printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", * This gotslot will be updated with symbol value at run-time. */ - *(got_t *)((long)rrs_got + sp->gotslot_offset) = addend; + *GOTP(sp->gotslot_offset) = addend; } if (rrs_section_type == RRS_PARTIAL) { @@ -483,9 +477,8 @@ printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", */ if (!sp->defined) warnx("Cannot reduce symbol \"%s\" in %s", - sp->name, get_file_name(entry)); + sp->name, get_file_name(entry)); discarded_rrs_relocs++; - sp->flags |= GS_GOTSLOTCLAIMED; return sp->gotslot_offset; } @@ -498,8 +491,7 @@ printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", * as no symbol need be looked up at run-time. */ r = rrs_next_reloc(); - sp->flags |= GS_GOTSLOTCLAIMED; - r->r_address = rrs_sdt.sdt_got + sp->gotslot_offset; + r->r_address = got_symbol->value + sp->gotslot_offset; RELOC_SYMBOL(r) = sp->rrs_symbolnum; RELOC_EXTERN_P(r) = !(reloc_type == RELTYPE_RELATIVE); md_make_gotreloc(rp, r, reloc_type); @@ -515,40 +507,50 @@ printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n", */ long claim_rrs_internal_gotslot(entry, rp, lsp, addend) -struct file_entry *entry; -struct relocation_info *rp; -struct localsymbol *lsp; -long addend; + struct file_entry *entry; + struct relocation_info *rp; + struct localsymbol *lsp; + long addend; { struct relocation_info *r; addend += lsp->nzlist.nz_value; if (!RELOC_STATICS_THROUGH_GOT_P(r)) - return addend - rrs_sdt.sdt_got; - -#ifdef DEBUG -printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n", - get_file_name(entry), lsp->gotslot_offset, addend); -#endif + return addend - got_symbol->value; - if (lsp->gotslot_offset == -1) - errx(1, - "internal error: %s: claim_rrs_internal_gotslot at %#x: slot_offset == -1\n", + if (!(lsp->flags & LS_HASGOTSLOT)) + errx(1, "internal error: " + "%s: claim_rrs_internal_gotslot at %#x: no reservation", get_file_name(entry), RELOC_ADDRESS(rp)); - if (lsp->flags & LS_GOTSLOTCLAIMED) { - /* Already done */ - if (addend != *(long *)((long)rrs_got + lsp->gotslot_offset)) - errx(1, "%s: gotslot at %#x is multiple valued\n", + if (lsp->gotslot_offset != -1) { + /* Already claimed */ + if (*GOTP(lsp->gotslot_offset) != addend) + errx(1, "%s: gotslot at %#x is multiple valued", get_file_name(entry), lsp->gotslot_offset); return lsp->gotslot_offset; } - *(long *)((long)rrs_got + lsp->gotslot_offset) = addend; + if (current_got_offset == 0) + /* GOT offset 0 is reserved */ + current_got_offset += sizeof(got_t); + + if (current_got_offset > MAX_GOTOFF) + errx(1, "%s: GOT overflow for relocation at %#x", + get_file_name(entry), RELOC_ADDRESS(rp)); + + lsp->gotslot_offset = current_got_offset; + current_got_offset += sizeof(got_t); + + *GOTP(lsp->gotslot_offset) = addend; + +#ifdef DEBUG +printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n", + get_file_name(entry), lsp->gotslot_offset, addend); +#endif if (rrs_section_type == RRS_PARTIAL) { - lsp->flags |= LS_GOTSLOTCLAIMED; discarded_rrs_relocs++; return lsp->gotslot_offset; } @@ -557,8 +559,7 @@ printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n", * Relocation entry needed for this static GOT entry. */ r = rrs_next_reloc(); - lsp->flags |= LS_GOTSLOTCLAIMED; - r->r_address = rrs_sdt.sdt_got + lsp->gotslot_offset; + r->r_address = got_symbol->value + lsp->gotslot_offset; RELOC_EXTERN_P(r) = 0; md_make_gotreloc(rp, r, RELTYPE_RELATIVE); return lsp->gotslot_offset; @@ -566,9 +567,9 @@ printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n", void claim_rrs_cpy_reloc(entry, rp, sp) -struct file_entry *entry; -struct relocation_info *rp; -symbol *sp; + struct file_entry *entry; + struct relocation_info *rp; + symbol *sp; { struct relocation_info *r; @@ -576,8 +577,8 @@ symbol *sp; return; if (!(sp->flags & GS_CPYRELOCRESERVED)) - errx(1, - "internal error: %s: claim_cpy_reloc: %s: no reservation\n", + errx(1, "internal error: " + "%s: claim_cpy_reloc: %s: no reservation", get_file_name(entry), sp->name); #ifdef DEBUG @@ -595,8 +596,8 @@ printf("claim_rrs_copy: %s: %s -> %x\n", void claim_rrs_segment_reloc(entry, rp) -struct file_entry *entry; -struct relocation_info *rp; + struct file_entry *entry; + struct relocation_info *rp; { struct relocation_info *r = rrs_next_reloc(); @@ -618,8 +619,8 @@ printf("claim_rrs_segment_reloc: %s at %#x\n", */ void rrs_insert_hash(cp, index) -char *cp; -int index; + char *cp; + int index; { int hashval = 0; struct rrs_hash *hp; @@ -699,6 +700,8 @@ consider_rrs_section_lengths() if (rrs_section_type == RRS_NONE) { got_symbol->defined = 0; + if (reserved_rrs_relocs > 0) + errx(1, "internal error: empty RRS has reservations"); return; } @@ -781,7 +784,8 @@ consider_rrs_section_lengths() if (rrs_sdt.sdt_buckets < 4) rrs_sdt.sdt_buckets = 4; - number_of_rrs_hash_entries = rrs_sdt.sdt_buckets + number_of_rrs_symbols; + number_of_rrs_hash_entries = rrs_sdt.sdt_buckets + + number_of_rrs_symbols; rrs_hashtab = (struct rrs_hash *)xmalloc( number_of_rrs_hash_entries * sizeof(struct rrs_hash)); for (n = 0; n < rrs_sdt.sdt_buckets; n++) @@ -838,11 +842,32 @@ relocate_rrs_addresses() dynamic_symbol->value = 0; + /* + * Get ready to allocate linkage table offsets. + * First jmpslot is reserved for the run-time binder + * GOT entry at offset 0 is reserved for `__DYNAMIC'. + */ + current_jmpslot_offset = sizeof(jmpslot_t); + current_got_offset = 0; + + if (1 /* Not "-fPIC" seen */) { + int gotsize = number_of_gotslots * sizeof(got_t); + + if (gotsize + MIN_GOTOFF - (int)sizeof(got_t) > MAX_GOTOFF) + warnx("Global Offset Table overflow"); + if (gotsize > MAX_GOTOFF) + /* Position at "two-complements" origin */ + current_got_offset += MIN_GOTOFF; + } + + got_origin = -current_got_offset; + if (rrs_section_type == RRS_NONE) return; if (rrs_section_type == RRS_PARTIAL) { - got_symbol->value = rrs_sdt.sdt_got = rrs_data_start; + rrs_sdt.sdt_got = rrs_data_start; + got_symbol->value = rrs_sdt.sdt_got + got_origin; rrs_sdt.sdt_plt = rrs_sdt.sdt_got + number_of_gotslots * sizeof(got_t); return; @@ -889,12 +914,11 @@ relocate_rrs_addresses() rrs_sdt.sdt_filler2 = 0; /* - * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC - * &__DYNAMIC is also in the first GOT entry. + * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC. + * The value `&__DYNAMIC' is in the GOT table at offset 0. */ - got_symbol->value = rrs_sdt.sdt_got; - - *rrs_got = dynamic_symbol->value = rrs_data_start; + got_symbol->value = rrs_sdt.sdt_got + got_origin; + *GOTP(0) = dynamic_symbol->value = rrs_data_start; } @@ -907,36 +931,37 @@ write_rrs_data() return; pos = rrs_data_start + (N_DATOFF(outheader) - DATA_START(outheader)); - if (lseek(outdesc, pos, L_SET) != pos) - err(1, "write_rrs_data: lseek"); + if (fseek(outstream, pos, SEEK_SET) != 0) + err(1, "write_rrs_data: fseek"); if (rrs_section_type == RRS_PARTIAL) { /* * Only a GOT and PLT are needed. */ md_swapout_got(rrs_got, number_of_gotslots); - mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outdesc); + mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream); md_swapout_jmpslot(rrs_plt, number_of_jmpslots); - mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outdesc); + mywrite(rrs_plt, number_of_jmpslots, + sizeof(jmpslot_t), outstream); return; } md_swapout__dynamic(&rrs_dyn); - mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outdesc); + mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outstream); md_swapout_so_debug(&rrs_so_debug); - mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outdesc); + mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outstream); md_swapout_section_dispatch_table(&rrs_sdt); - mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outdesc); + mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outstream); md_swapout_got(rrs_got, number_of_gotslots); - mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outdesc); + mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream); md_swapout_jmpslot(rrs_plt, number_of_jmpslots); - mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outdesc); + mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outstream); } void @@ -949,23 +974,24 @@ write_rrs_text() int offset = 0; struct shobj *shp; struct sod *sodp; + int bind; if (rrs_section_type == RRS_PARTIAL) return; pos = rrs_text_start + (N_TXTOFF(outheader) - TEXT_START(outheader)); - if (lseek(outdesc, pos, L_SET) != pos) - err(1, "write_rrs_text: lseek"); + if (fseek(outstream, pos, SEEK_SET) != 0) + err(1, "write_rrs_text: fseek"); /* Write relocation records */ md_swapout_reloc(rrs_reloc, reserved_rrs_relocs); mywrite(rrs_reloc, reserved_rrs_relocs, - sizeof(struct relocation_info), outdesc); + sizeof(struct relocation_info), outstream); /* Write the RRS symbol hash tables */ md_swapout_rrs_hash(rrs_hashtab, number_of_rrs_hash_entries); mywrite(rrs_hashtab, number_of_rrs_hash_entries, - sizeof(struct rrs_hash), outdesc); + sizeof(struct rrs_hash), outstream); /* * Determine size of an RRS symbol entry, allocate space @@ -1028,8 +1054,8 @@ write_rrs_text() if ((long)nlp - (long)rrs_symbols >= number_of_rrs_symbols * rrs_symbol_size) - errx(1, - "internal error: rrs symbols exceed allocation %d ", + errx(1, "internal error: " + "rrs symbols exceed allocation %d", number_of_rrs_symbols); nlp->nz_desc = 0; @@ -1037,6 +1063,8 @@ write_rrs_text() if (LD_VERSION_NZLIST_P(soversion)) nlp->nz_size = 0; + bind = (sp->flags & GS_WEAK) ? BIND_WEAK : 0; + if (sp->defined > 1) { /* defined with known type */ if (!(link_mode & SHAREABLE) && @@ -1049,7 +1077,7 @@ write_rrs_text() */ nlp->nz_type = sp->alias->defined; nlp->nz_value = sp->alias->value; - nlp->nz_other = N_OTHER(0, sp->alias->aux); + nlp->nz_other = N_OTHER(bind, sp->alias->aux); } else if (sp->defined == N_SIZE) { /* * Make sure this symbol isn't going @@ -1060,35 +1088,38 @@ write_rrs_text() } else { nlp->nz_type = sp->defined; nlp->nz_value = sp->value; - nlp->nz_other = N_OTHER(0, sp->aux); + nlp->nz_other = N_OTHER(bind, sp->aux); } if (LD_VERSION_NZLIST_P(soversion)) nlp->nz_size = sp->size; } else if (sp->common_size) { /* - * a common definition + * A common definition. */ nlp->nz_type = N_UNDF | N_EXT; nlp->nz_value = sp->common_size; + nlp->nz_other = N_OTHER(bind, 0); } else if (!sp->defined) { /* undefined */ nlp->nz_type = N_UNDF | N_EXT; nlp->nz_value = 0; if (sp->so_defined && sp->jmpslot_offset != -1) { /* - * Define a "weak" function symbol. + * A PLT entry. The auxiliary type -- which + * must be AUX_FUNC -- is used by the run-time + * linker to unambiguously resolve function + * address references. */ if (sp->aux != AUX_FUNC) errx(1, "%s: non-function jmpslot", - sp->name); - nlp->nz_other = N_OTHER(0, sp->aux); + sp->name); + nlp->nz_other = N_OTHER(bind, sp->aux); nlp->nz_value = rrs_sdt.sdt_plt + sp->jmpslot_offset; } } else - errx(1, - "internal error: %s defined in mysterious way", - sp->name); + errx(1, "internal error: %s defined in mysterious way", + sp->name); /* Set symbol's name */ nlp->nz_strx = offset; @@ -1103,7 +1134,7 @@ write_rrs_text() int t = (nlp->nz_type == N_INDR + N_EXT); INCR_NLP(nlp); - nlp->nz_type = N_UNDF + t?N_EXT:0; + nlp->nz_type = N_UNDF + (t ? N_EXT : 0); nlp->nz_un.n_strx = offset; nlp->nz_value = 0; nlp->nz_other = 0; @@ -1118,8 +1149,8 @@ write_rrs_text() } END_EACH_SYMBOL; if (MALIGN(offset) != rrs_strtab_size) - errx(1, - "internal error: inconsistent RRS string table length: %d, expected %d", + errx(1, "internal error: " + "inconsistent RRS string table length: %d, expected %d", offset, rrs_strtab_size); /* Write the symbol table */ @@ -1127,10 +1158,10 @@ write_rrs_text() md_swapout_symbols(rrs_symbols, number_of_rrs_symbols); else md_swapout_zsymbols(rrs_symbols, number_of_rrs_symbols); - mywrite(rrs_symbols, symsize, 1, outdesc); + mywrite(rrs_symbols, symsize, 1, outstream); /* Write the strings */ - mywrite(rrs_strtab, rrs_strtab_size, 1, outdesc); + mywrite(rrs_strtab, rrs_strtab_size, 1, outstream); /* * Write the names of the shared objects needed at run-time @@ -1161,12 +1192,12 @@ write_rrs_text() } if (i < number_of_shobjs) - errx(1, - "internal error: # of link objects less then expected %d", + errx(1, "internal error: " + "# of link objects less then expected %d", number_of_shobjs); md_swapout_sod(sodp, number_of_shobjs); - mywrite(sodp, number_of_shobjs, sizeof(struct sod), outdesc); + mywrite(sodp, number_of_shobjs, sizeof(struct sod), outstream); for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) { char *name = shp->entry->local_sym_name; @@ -1175,7 +1206,7 @@ write_rrs_text() name += 2; } - mywrite(name, strlen(name) + 1, 1, outdesc); + mywrite(name, strlen(name) + 1, 1, outstream); } } @@ -1188,8 +1219,8 @@ write_rrs() */ if (rrs_section_type == RRS_NONE) { if (reserved_rrs_relocs > 1) - errx(1, - "internal error: RRS relocs in static program: %d", + errx(1, "internal error: " + "RRS relocs in static program: %d", reserved_rrs_relocs-1); return; } @@ -1202,8 +1233,8 @@ printf("rrs_relocs: reserved %d claimed %d discarded %d, gotslots %d jmpslots %d /* Final consistency check */ if (claimed_rrs_relocs + discarded_rrs_relocs != reserved_rrs_relocs) { - errx(1, - "internal error: reserved relocs(%d) != claimed(%d) + discarded(%d)", + errx(1, "internal error: " + "reserved relocs(%d) != claimed(%d) + discarded(%d)", reserved_rrs_relocs, claimed_rrs_relocs, discarded_rrs_relocs); diff --git a/gnu/usr.bin/ld/rtld/Makefile b/gnu/usr.bin/ld/rtld/Makefile index d8c9165..7c81145 100644 --- a/gnu/usr.bin/ld/rtld/Makefile +++ b/gnu/usr.bin/ld/rtld/Makefile @@ -1,10 +1,9 @@ -# $Id: Makefile,v 1.12 1994/08/28 18:48:32 bde Exp $ +# $Id: Makefile,v 1.13 1994/09/18 19:41:38 swallace Exp $ PROG= ld.so SRCS= mdprologue.S rtld.c malloc.c shlib.c etc.c md.c NOMAN= noman LDDIR?= $(.CURDIR)/.. -#PICFLAG=-pic PICFLAG=-fpic CFLAGS+=-I$(LDDIR) -I$(.CURDIR) -I$(LDDIR)/$(MACHINE) $(PICFLAG) -DRTLD LDFLAGS+=-Bshareable -Bsymbolic -assert nosymbolic @@ -14,18 +13,9 @@ LDADD+= -lc_pic -lgcc_pic BINDIR= /usr/libexec INSTALLFLAGS+= -fschg -.SUFFIXES: .S - .PATH: $(LDDIR) $(LDDIR)/$(MACHINE) $(PROG): ${OBJS} ${DPADD} - $(LD) -o $(PROG) $(LDFLAGS) $(OBJS) $(LDDESTDIR) $(LDADD) - -.S.o: -.if defined(DESTDIR) - ${CPP} -I${DESTDIR}/usr/include ${.IMPSRC} | ${AS} ${ASFLAGS} -o ${.TARGET} - -.else - ${CPP} ${.IMPSRC} | ${AS} ${ASFLAGS} -o ${.TARGET} - -.endif + $(LD) -o $(PROG) $(LDFLAGS) $(OBJS) $(LDADD) .include <bsd.prog.mk> diff --git a/gnu/usr.bin/ld/rtld/malloc.c b/gnu/usr.bin/ld/rtld/malloc.c index b5c54f8..0d94200 100644 --- a/gnu/usr.bin/ld/rtld/malloc.c +++ b/gnu/usr.bin/ld/rtld/malloc.c @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/ -static char *rcsid = "$Id: malloc.c,v 1.1 1994/02/13 20:44:09 jkh Exp $"; +static char *rcsid = "$Id: malloc.c,v 1.2 1994/06/15 22:41:13 rich Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -72,8 +72,7 @@ static int findbucket(); /* * Pre-allocate mmap'ed pages */ -#define getpagesize() NBPG -#define NPOOLPAGES (32*1024/NBPG) +#define NPOOLPAGES (32*1024/pagesz) static caddr_t pagepool_start, pagepool_end; static int morepages(); diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c index 6332911..c2e6021 100644 --- a/gnu/usr.bin/ld/rtld/rtld.c +++ b/gnu/usr.bin/ld/rtld/rtld.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: rtld.c,v 1.20 1995/01/12 19:12:29 joerg Exp $ + * $Id: rtld.c,v 1.21 1995/02/07 13:33:42 jkh Exp $ */ #include <sys/param.h> @@ -38,9 +38,8 @@ #include <sys/resource.h> #include <sys/errno.h> #include <sys/mman.h> -#ifndef BSD +#ifndef MAP_COPY #define MAP_COPY MAP_PRIVATE -#define MAP_ANON 0 #endif #include <err.h> #include <fcntl.h> @@ -58,8 +57,19 @@ #include "ld.h" -#ifndef BSD /* Need do better than this */ -#define NEED_DEV_ZERO 1 +#ifndef MAP_ANON +#define MAP_ANON 0 +#define anon_open() do { \ + if ((anon_fd = open("/dev/zero", O_RDWR, 0)) == -1) \ + err("open: %s", "/dev/zero"); \ +} while (0) +#define anon_close() do { \ + (void)close(anon_fd); \ + anon_fd = -1; \ +} while (0) +#else +#define anon_open() +#define anon_close() #endif /* @@ -135,6 +145,7 @@ static int careful; static char __main_progname[] = "main"; static char *main_progname = __main_progname; static char us[] = "/usr/libexec/ld.so"; +static int anon_fd = -1; struct so_map *link_map_head, *main_map; struct so_map **link_map_tail = &link_map_head; @@ -166,14 +177,15 @@ static void init_map __P((struct so_map *, char *)); static char *rtfindlib __P((char *, int, int, int *)); void binder_entry __P((void)); long binder __P((jmpslot_t *)); -static void maphints __P((void)); -static void unmaphints __P((void)); static struct nzlist *lookup __P((char *, struct so_map **, int)); static inline struct rt_symbol *lookup_rts __P((char *)); static struct rt_symbol *enter_rts __P((char *, long, int, caddr_t, long, struct so_map *)); static void generror __P((char *, ...)); +static void maphints __P((void)); +static void unmaphints __P((void)); + static inline int strcmp (register const char *s1, register const char *s2) { @@ -251,6 +263,7 @@ struct _dynamic *dp; if (getenv("LD_NOSTD_PATH") == NULL) std_search_path(); + anon_open(); /* Load required objects into the process address space */ load_objects(crtp, dp); @@ -301,11 +314,12 @@ struct _dynamic *dp; ddp->dd_sym_loaded = 1; } - /* Forget hints so that hints file can go away if it is unlinked */ + /* Close the hints file */ unmaphints(); /* Close our file descriptor */ (void)close(crtp->crt_ldfd); + anon_close(); return 0; } @@ -511,9 +525,9 @@ again: return NULL; } - if ((addr = mmap(0, hdr.a_text + hdr.a_data, - PROT_READ|PROT_EXEC, - MAP_COPY, fd, 0)) == (caddr_t)-1) { + if ((addr = mmap(0, hdr.a_text + hdr.a_data + hdr.a_bss, + PROT_READ|PROT_EXEC, + MAP_COPY, fd, 0)) == (caddr_t)-1) { generror ("mmap failed for \"%s\" : %s", path, strerror (errno)); (void)close(fd); @@ -528,29 +542,17 @@ again: return NULL; } - (void)close(fd); - - fd = -1; -#ifdef NEED_DEV_ZERO - if ((fd = open("/dev/zero", O_RDWR, 0)) == -1) { - generror ("open failed for \"/dev/zero\" : %s", - strerror (errno)); - return NULL; - } -#endif - if (hdr.a_bss && mmap(addr + hdr.a_text + hdr.a_data, hdr.a_bss, - PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_ANON|MAP_FIXED|MAP_COPY, - fd, hdr.a_text + hdr.a_data) == (caddr_t)-1) { + if (mmap(addr + hdr.a_text + hdr.a_data, hdr.a_bss, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_ANON|MAP_COPY|MAP_FIXED, + anon_fd, 0) == (caddr_t)-1) { generror ("mmap failed for \"%s\" : %s", path, strerror (errno)); (void)close(fd); return NULL; - } + } -#ifdef NEED_DEV_ZERO - close(fd); -#endif + (void)close(fd); /* Assume _DYNAMIC is the first data item */ dp = (struct _dynamic *)(addr+hdr.a_text); @@ -634,7 +636,7 @@ caddr_t addr; if (getenv("LD_SUPPRESS_WARNINGS") == NULL && getenv("LD_WARN_NON_PURE_CODE") != NULL) - warnx("ld.so: warning: non pure code in %s at %x (%s)\n", + warnx("warning: non pure code in %s at %x (%s)", smp->som_path, r->r_address, sym); if (smp->som_write == 0 && @@ -884,7 +886,7 @@ lookup(name, src_map, strong) * Search all maps for a definition of NAME */ for (smp = link_map_head; smp; smp = smp->som_next) { - int buckets = LD_BUCKETS(smp->som_dynamic); + int buckets; long hashval; struct rrs_hash *hp; char *cp; @@ -896,10 +898,13 @@ lookup(name, src_map, strong) char *stringbase; int symsize; - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) + if (*src_map && smp != *src_map) continue; - if (*src_map && smp != *src_map) + if ((buckets = LD_BUCKETS(smp->som_dynamic)) == 0) + continue; + + if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) continue; restart: @@ -1042,8 +1047,9 @@ binder(jsp) } +static int hfd; +static long hsize; static struct hints_header *hheader; -static long hmsize; static struct hints_bucket *hbuckets; static char *hstrtab; @@ -1053,52 +1059,47 @@ static char *hstrtab; maphints __P((void)) { caddr_t addr; - long msize; - int fd; - if ((fd = open(_PATH_LD_HINTS, O_RDONLY, 0)) == -1) { + if ((hfd = open(_PATH_LD_HINTS, O_RDONLY, 0)) == -1) { hheader = (struct hints_header *)-1; return; } - msize = PAGSIZ; - addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0); + hsize = PAGSIZ; + addr = mmap(0, hsize, PROT_READ, MAP_COPY, hfd, 0); if (addr == (caddr_t)-1) { - close(fd); + close(hfd); hheader = (struct hints_header *)-1; return; } hheader = (struct hints_header *)addr; if (HH_BADMAG(*hheader)) { - munmap(addr, msize); - close(fd); + munmap(addr, hsize); + close(hfd); hheader = (struct hints_header *)-1; return; } if (hheader->hh_version != LD_HINTS_VERSION_1) { - munmap(addr, msize); - close(fd); + munmap(addr, hsize); + close(hfd); hheader = (struct hints_header *)-1; return; } - hmsize = msize; - if (hheader->hh_ehints > msize) { - hmsize = hheader->hh_ehints; - if (mmap(addr+msize, hheader->hh_ehints - msize, + if (hheader->hh_ehints > hsize) { + if (mmap(addr+hsize, hheader->hh_ehints - hsize, PROT_READ, MAP_COPY|MAP_FIXED, - fd, msize) != (caddr_t)(addr+msize)) { + hfd, hsize) != (caddr_t)(addr+hsize)) { - munmap((caddr_t)hheader, msize); - close(fd); + munmap((caddr_t)hheader, hsize); + close(hfd); hheader = (struct hints_header *)-1; return; } } - close(fd); hbuckets = (struct hints_bucket *)(addr + hheader->hh_hashtab); hstrtab = (char *)(addr + hheader->hh_strtab); @@ -1107,8 +1108,10 @@ maphints __P((void)) static void unmaphints() { + if (HINTS_VALID) { - munmap((caddr_t)hheader, hmsize); + munmap((caddr_t)hheader, hsize); + close(hfd); hheader = NULL; } } @@ -1404,4 +1407,3 @@ char *fmt; (void)write(1, buf, strlen(buf)); va_end(ap); } - diff --git a/gnu/usr.bin/ld/shlib.c b/gnu/usr.bin/ld/shlib.c index 058689a..38cb2d1 100644 --- a/gnu/usr.bin/ld/shlib.c +++ b/gnu/usr.bin/ld/shlib.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: shlib.c,v 1.10 1994/12/23 22:30:51 nate Exp $ + * $Id: shlib.c,v 1.11 1995/01/05 02:36:29 swallace Exp $ */ #include <sys/param.h> @@ -54,7 +54,7 @@ char *strsep(); * Standard directories to search for files specified by -l. */ #ifndef STANDARD_SEARCH_DIRS -#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/X11R6/lib", "/usr/local/lib" +#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/local/lib" #endif /* diff --git a/gnu/usr.bin/ld/sparc/md.h b/gnu/usr.bin/ld/sparc/md.h index 3545d97..f83c1ff 100644 --- a/gnu/usr.bin/ld/sparc/md.h +++ b/gnu/usr.bin/ld/sparc/md.h @@ -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: md.h,v 1.5 1993/12/02 01:03:47 jkh Exp $ + * $Id: md.h,v 1.6 1994/02/13 20:43:07 jkh Exp $ */ /* @@ -106,11 +106,21 @@ #define RELOC_STATICS_THROUGH_GOT_P(r) (1) #define JMPSLOT_NEEDS_RELOC (1) +/* + * Define the range of usable Global Offset Table offsets + * when using sparc 13 bit relocation types (-4096 - 4092). + */ +#define MAX_GOTSIZE (8192) +#define MAX_GOTOFF (4092) +#define MIN_GOTOFF (-4096) + #define CHECK_GOT_RELOC(r) \ ((r)->r_type == RELOC_PC10 || (r)->r_type == RELOC_PC22) #define md_got_reloc(r) (-(r)->r_address) +#define RELOC_INIT_SEGMENT_RELOC(r) ((r)->r_type = RELOC_32) + #ifdef SUN_COMPAT /* * Sun plays games with `r_addend' diff --git a/gnu/usr.bin/ld/sparc/mdprologue.S b/gnu/usr.bin/ld/sparc/mdprologue.S index 0d006d0..d3236a3 100644 --- a/gnu/usr.bin/ld/sparc/mdprologue.S +++ b/gnu/usr.bin/ld/sparc/mdprologue.S @@ -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: mdprologue.S,v 1.2 1993/11/09 04:19:36 paul Exp $ + * $Id: mdprologue.S,v 1.3 1994/02/13 20:43:13 jkh Exp $ */ /* @@ -56,7 +56,7 @@ L.2B: add %i1, %fp, %i1 ! if so, adjust to absolute address 1: ld [%i1], %o3 ! load base address (crtp->crt_ba) - ld [%l7], %o2 ! get rtld's __DYNAMIC address + ld [%l7], %o2 ! get __DYNAMIC address ! from 1st GOT entry add %o2, %o3, %o2 ! relocate and make it 3rd arg. @@ -94,7 +94,7 @@ _binder_entry: restore ! get rid of our context jmp %g1 ! and go. - restore ! and the jmpslot's + restore ! and the jmpslot context nop .seg "data" ! [internal] diff --git a/gnu/usr.bin/ld/warnings.c b/gnu/usr.bin/ld/warnings.c index 0479344..3c65a22 100644 --- a/gnu/usr.bin/ld/warnings.c +++ b/gnu/usr.bin/ld/warnings.c @@ -1,5 +1,5 @@ /* - * $Id: warnings.c,v 1.8 1994/06/15 22:40:00 rich Exp $ + * $Id: warnings.c,v 1.9 1994/12/23 22:30:57 nate Exp $ */ #include <sys/param.h> @@ -25,6 +25,8 @@ #include "ld.h" +static int reported_undefineds; + /* * Print the filename of ENTRY on OUTFILE (a stdio stream), * and then a newline. @@ -101,18 +103,21 @@ print_symbols(outfile) fprintf(outfile, "\nGlobal symbols:\n\n"); FOR_EACH_SYMBOL(i, sp) { - if (sp->defined == (N_UNDF|N_EXT)) - fprintf(outfile, " %s: common, length %#x\n", - sp->name, sp->common_size); + fprintf(outfile, " %s: ", sp->name); if (!(sp->flags & GS_REFERENCED)) - fprintf(outfile, " %s: unreferenced\n", sp->name); + fprintf(outfile, "unreferenced"); else if (sp->so_defined) - fprintf(outfile, " %s: sodefined\n", sp->name); + fprintf(outfile, "sodefined"); else if (!sp->defined) - fprintf(outfile, " %s: undefined\n", sp->name); + fprintf(outfile, "undefined"); + else if (sp->defined == (N_UNDF|N_EXT)) + fprintf(outfile, "common: size %#x", sp->common_size); else - fprintf(outfile, " %s: %#x, size %#x\n", - sp->name, sp->value, sp->size); + fprintf(outfile, "type %d, value %#x, size %#x", + sp->defined, sp->value, sp->size); + if (sp->alias) + fprintf(outfile, ", aliased to %s", sp->alias->name); + fprintf(outfile, "\n"); } END_EACH_SYMBOL; each_file(list_file_locals, (void *)outfile); @@ -463,10 +468,11 @@ do_relocation_warnings(entry, data_segment, outfile, nlist_bitvector) /* Mark as being noted by relocation warning pass. */ SET_BIT(nlist_bitvector, lsp - start_of_syms); + if (g->undef_refs == 0) + reported_undefineds++; if (g->undef_refs >= MAX_UREFS_PRINTED) /* Listed too many */ continue; - /* Undefined symbol which we should mention */ if (++(g->undef_refs) == MAX_UREFS_PRINTED) { @@ -632,10 +638,28 @@ do_file_warnings (entry, outfile) line_number = -1; break; - default: -warnx("Unexpected multiple definitions of symbol `%s', type %#x\n", g->name, np->n_type); + case N_SIZE | N_EXT: + errfmt = + "Size element definition of symbol `%s' (multiply defined)"; + line_number = -1; + break; + + case N_INDR | N_EXT: + errfmt = + "Alias definition of symbol `%s' (multiply defined)"; + line_number = -1; + break; + + case N_UNDF | N_EXT: /* Don't print out multiple defs at references.*/ continue; + + default: + warnx("%s: unexpected multiple definitions " + "of symbol `%s', type %#x", + get_file_name(entry), + g->name, np->n_type); + break; } } else if (BIT_SET_P(nlist_bitvector, i)) { @@ -643,9 +667,10 @@ warnx("Unexpected multiple definitions of symbol `%s', type %#x\n", g->name, np- } else if (list_unresolved_refs && !g->defined && !g->so_defined) { + if (g->undef_refs == 0) + reported_undefineds++; if (g->undef_refs >= MAX_UREFS_PRINTED) continue; - if (++(g->undef_refs) == MAX_UREFS_PRINTED) errfmt = "More undefined `%s' refs follow"; else @@ -656,7 +681,7 @@ warnx("Unexpected multiple definitions of symbol `%s', type %#x\n", g->name, np- g->def_lsp->entry->flags & E_SECONDCLASS) { fprintf(outfile, "%s: Undefined symbol `%s' referenced (use %s ?)\n", - entry->filename, + get_file_name(entry), g->name, g->def_lsp->entry->local_sym_name); continue; @@ -678,7 +703,7 @@ warnx("Unexpected multiple definitions of symbol `%s', type %#x\n", g->name, np- continue; if (line_number == -1) - fprintf(outfile, "%s: ", entry->filename); + fprintf(outfile, "%s: ", get_file_name(entry)); else fprintf(outfile, "%s:%d: ", file_name, line_number); @@ -698,8 +723,11 @@ int do_warnings(outfile) FILE *outfile; { + list_unresolved_refs = !relocatable_output && - (undefined_global_sym_count || undefined_shobj_sym_count); + ( (undefined_global_sym_count - undefined_weak_sym_count) > 0 + || undefined_shobj_sym_count + ); list_multiple_defs = multiple_def_count != 0; if (!(list_unresolved_refs || @@ -714,6 +742,14 @@ do_warnings(outfile) each_file(do_file_warnings, (void *)outfile); + if (list_unresolved_refs && + reported_undefineds != + (undefined_global_sym_count - undefined_weak_sym_count)) + warnx("Spurious undefined symbols: " + "# undefined symbols %d, reported %d", + (undefined_global_sym_count - undefined_weak_sym_count), + reported_undefineds); + if (list_unresolved_refs || list_multiple_defs) return 0; |