From: Jordan K. Hubbard Date: Sun, 13 Feb 1994 20:43:13 +0000 (+0000) Subject: This is Paul K's latest set of ld changes. A commit was necessary at this X-Git-Tag: FreeBSD-release/1.1~90 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/6a61ea881132f5a2eaea6fef8c71209efb37c4a4 This is Paul K's latest set of ld changes. A commit was necessary at this late stage due to the fact that link.h was copyright Sun Microsystems. This version of ld sync's us up with NetBSD's ld and supports compatablily with NetBSD's -[zZ] flags (which we had reversed). Compiling with this new ld will give you RRS warnings for libraries which do not contain .type infomation - these wsarnings are harmless and will go away as soon as you recompile your libraries (cd /usr/src; make libraries). --- diff --git a/gnu/usr.bin/ld/etc.c b/gnu/usr.bin/ld/etc.c index 22fdfd8f16..2ddd50a87b 100644 --- a/gnu/usr.bin/ld/etc.c +++ b/gnu/usr.bin/ld/etc.c @@ -1,5 +1,5 @@ /* - * $Id: etc.c,v 1.5 1993/12/04 00:52:55 jkh Exp $ + * $Id: etc.c,v 1.6 1993/12/11 11:58:22 jkh Exp $ */ #include @@ -48,6 +48,7 @@ error(fmt, va_alist) va_end(ap); } +void (*fatal_cleanup_hook)__P((void)); /* * Report a fatal error. */ @@ -72,8 +73,8 @@ fatal(fmt, va_alist) (void)fprintf(stderr, "\n"); va_end(ap); - if (outdesc >= 0) - unlink(output_filename); + if (fatal_cleanup_hook) + (*fatal_cleanup_hook)(); exit(1); } @@ -148,50 +149,3 @@ xrealloc(ptr, size) return result; } - - - -/* These must move */ - -#ifndef RTLD -/* - * Output COUNT*ELTSIZE bytes of data at BUF to the descriptor DESC. - */ -void -mywrite (buf, count, eltsize, desc) - char *buf; - int count; - int eltsize; - int desc; -{ - register int val; - register int bytes = count * eltsize; - - while (bytes > 0) { - val = write (desc, buf, bytes); - if (val <= 0) - perror(output_filename); - buf += val; - bytes -= val; - } -} - -/* - * Output PADDING zero-bytes to descriptor OUTDESC. - * PADDING may be negative; in that case, do nothing. - */ - -void -padfile (padding, outdesc) - int padding; - int outdesc; -{ - register char *buf; - if (padding <= 0) - return; - - buf = (char *) alloca (padding); - bzero (buf, padding); - mywrite (buf, padding, 1, outdesc); -} -#endif diff --git a/gnu/usr.bin/ld/i386/md-static-funcs.c b/gnu/usr.bin/ld/i386/md-static-funcs.c index 2cd0768ea9..47416856e4 100644 --- a/gnu/usr.bin/ld/i386/md-static-funcs.c +++ b/gnu/usr.bin/ld/i386/md-static-funcs.c @@ -1,8 +1,10 @@ - /* + * $Id: md-static-funcs.c,v 1.2 1993/12/08 10:14:44 pk Exp $ + * * Called by ld.so when onanating. * This *must* be a static function, so it is not called through a jmpslot. */ + static void md_relocate_simple(r, relocation, addr) struct relocation_info *r; diff --git a/gnu/usr.bin/ld/i386/md.c b/gnu/usr.bin/ld/i386/md.c index f78c6ccfb4..311a5f6d4c 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.7 1994/01/03 18:35:35 davidg Exp $ + * $Id: md.c,v 1.8 1994/01/19 15:00:37 davidg Exp $ */ #include @@ -41,8 +41,6 @@ #include "ld.h" -int netzmagic = 0; - /* * Get relocation addend corresponding to relocation record RP * from address ADDR @@ -89,29 +87,6 @@ unsigned char *addr; } } -/* - * Initialize (output) exec header such that useful values are - * obtained from subsequent N_*() macro evaluations. - */ -void -md_init_header(hp, magic, flags) -struct exec *hp; -int magic, flags; -{ - if (!netzmagic && (magic == ZMAGIC)) { - hp->a_midmag = magic; - } else { - if (netzmagic) - N_SETMAGIC_NET((*hp), magic, MID_I386, flags); - else - N_SETMAGIC((*hp), magic, MID_I386, flags); - } - - /* TEXT_START depends on the value of outheader.a_entry. */ - if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */ - hp->a_entry = PAGSIZ; -} - /* * Machine dependent part of claim_rrs_reloc(). * Set RRS relocation type. @@ -251,8 +226,44 @@ long *savep; *(char *)where = TRAP; } -#ifdef NEED_SWAP +#ifndef RTLD + +#ifdef FreeBSD +int netzmagic; +#endif +/* + * Initialize (output) exec header such that useful values are + * obtained from subsequent N_*() macro evaluations. + */ +void +md_init_header(hp, magic, flags) +struct exec *hp; +int magic, flags; +{ +#ifdef NetBSD + if (oldmagic || magic == QMAGIC) + hp->a_midmag = magic; + else + N_SETMAGIC((*hp), magic, MID_I386, flags); +#endif +#ifdef FreeBSD + if (oldmagic) + hp->a_midmag = magic; + else if (netzmagic) + N_SETMAGIC_NET((*hp), magic, MID_I386, flags); + else + N_SETMAGIC((*hp), magic, MID_I386, flags); +#endif + + /* TEXT_START depends on the value of outheader.a_entry. */ + if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */ + hp->a_entry = PAGSIZ; +} +#endif /* RTLD */ + + +#ifdef NEED_SWAP /* * Byte swap routines for cross-linking. */ diff --git a/gnu/usr.bin/ld/i386/md.h b/gnu/usr.bin/ld/i386/md.h index 7286a74125..bbb28f221a 100644 --- a/gnu/usr.bin/ld/i386/md.h +++ b/gnu/usr.bin/ld/i386/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.7 1994/01/03 18:35:36 davidg Exp $ + * $Id: md.h,v 1.8 1994/01/19 15:00:37 davidg Exp $ */ @@ -45,17 +45,41 @@ #define PAGSIZ 4096 #endif -#define N_SET_FLAG(ex,f) (netzmagic ? \ - N_SETMAGIC_NET(ex,N_GETMAGIC_NET(ex), MID_MACHINE, \ - N_GETFLAG_NET(ex)|(f)) : \ - N_GETMAGIC(ex) == ZMAGIC ? \ - N_SETMAGIC(ex,ZMAGIC,0,N_GETFLAG(ex)|(f)) : \ - N_SETMAGIC(ex,N_GETMAGIC(ex), MID_MACHINE, \ - N_GETFLAG(ex)|(f))) - -#define N_IS_DYNAMIC(ex) ((N_GETMAGIC_NET(ex) == ZMAGIC) ? \ - ((N_GETFLAG_NET(ex) & EX_DYNAMIC)) : \ - ((N_GETFLAG(ex) & EX_DYNAMIC))) +#if defined(NetBSD) || defined(CROSS_LINKER) + +#define N_SET_FLAG(ex,f) (oldmagic || N_GETMAGIC(ex)==QMAGIC ? (0) : \ + N_SETMAGIC(ex, \ + N_GETMAGIC(ex), \ + MID_MACHINE, \ + N_GETFLAG(ex)|(f))) + +#define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC)) + +#define N_BADMID(ex) \ + (N_GETMID(ex) != 0 && N_GETMID(ex) != MID_MACHINE) + +#endif + +/* + * FreeBSD does it differently + */ +#ifdef FreeBSD +#define N_SET_FLAG(ex,f) (oldmagic ? (0) : \ + (netzmagic == 0 ? \ + N_SETMAGIC(ex, \ + N_GETMAGIC(ex), \ + MID_MACHINE, \ + N_GETFLAG(ex)|(f)) : \ + N_SETMAGIC_NET(ex, \ + N_GETMAGIC_NET(ex), \ + MID_MACHINE, \ + N_GETFLAG_NET(ex)|(f)) )) + +#define N_IS_DYNAMIC(ex) ((N_GETMAGIC_NET(ex) == ZMAGIC) ? \ + ((N_GETFLAG_NET(ex) & EX_DYNAMIC)) : \ + ((N_GETFLAG(ex) & EX_DYNAMIC) )) +#define N_BADMID(ex) 0 +#endif /* * Should be handled by a.out.h ? @@ -101,16 +125,16 @@ typedef struct jmpslot { #define md_swapout_zsymbols(s,n) #define md_swapin_reloc(r,n) #define md_swapout_reloc(r,n) -#define md_swapin_link_dynamic(l) -#define md_swapout_link_dynamic(l) -#define md_swapin_link_dynamic_2(l) -#define md_swapout_link_dynamic_2(l) -#define md_swapin_ld_debug(d) -#define md_swapout_ld_debug(d) +#define md_swapin__dynamic(l) +#define md_swapout__dynamic(l) +#define md_swapin_section_dispatch_table(l) +#define md_swapout_section_dispatch_table(l) +#define md_swapin_so_debug(d) +#define md_swapout_so_debug(d) #define md_swapin_rrs_hash(f,n) #define md_swapout_rrs_hash(f,n) -#define md_swapin_link_object(l,n) -#define md_swapout_link_object(l,n) +#define md_swapin_sod(l,n) +#define md_swapout_sod(l,n) #define md_swapout_jmpslot(j,n) #define md_swapout_got(g,n) #define md_swapin_ranlib_hdr(h,n) @@ -130,23 +154,23 @@ void md_swapin_reloc __P((struct relocation_info *, int)); void md_swapout_reloc __P((struct relocation_info *, int)); void md_swapout_jmpslot __P((jmpslot_t *, int)); -#define md_swapin_symbols(s,n) swap_symbols(s,n) -#define md_swapout_symbols(s,n) swap_symbols(s,n) -#define md_swapin_zsymbols(s,n) swap_zsymbols(s,n) -#define md_swapout_zsymbols(s,n) swap_zsymbols(s,n) -#define md_swapin_link_dynamic(l) swap_link_dynamic(l) -#define md_swapout_link_dynamic(l) swap_link_dynamic(l) -#define md_swapin_link_dynamic_2(l) swap_link_dynamic_2(l) -#define md_swapout_link_dynamic_2(l) swap_link_dynamic_2(l) -#define md_swapin_ld_debug(d) swap_ld_debug(d) -#define md_swapout_ld_debug(d) swap_ld_debug(d) -#define md_swapin_rrs_hash(f,n) swap_rrs_hash(f,n) -#define md_swapout_rrs_hash(f,n) swap_rrs_hash(f,n) -#define md_swapin_link_object(l,n) swapin_link_object(l,n) -#define md_swapout_link_object(l,n) swapout_link_object(l,n) -#define md_swapout_got(g,n) swap_longs((long*)(g),n) -#define md_swapin_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) -#define md_swapout_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) +#define md_swapin_symbols(s,n) swap_symbols(s,n) +#define md_swapout_symbols(s,n) swap_symbols(s,n) +#define md_swapin_zsymbols(s,n) swap_zsymbols(s,n) +#define md_swapout_zsymbols(s,n) swap_zsymbols(s,n) +#define md_swapin__dynamic(l) swap__dynamic(l) +#define md_swapout__dynamic(l) swap__dynamic(l) +#define md_swapin_section_dispatch_table(l) swap_section_dispatch_table(l) +#define md_swapout_section_dispatch_table(l) swap_section_dispatch_table(l) +#define md_swapin_so_debug(d) swap_so_debug(d) +#define md_swapout_so_debug(d) swap_so_debug(d) +#define md_swapin_rrs_hash(f,n) swap_rrs_hash(f,n) +#define md_swapout_rrs_hash(f,n) swap_rrs_hash(f,n) +#define md_swapin_sod(l,n) swapin_sod(l,n) +#define md_swapout_sod(l,n) swapout_sod(l,n) +#define md_swapout_got(g,n) swap_longs((long*)(g),n) +#define md_swapin_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) +#define md_swapout_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) #define md_swap_short(x) ( (((x) >> 8) & 0xff) | (((x) & 0xff) << 8) ) diff --git a/gnu/usr.bin/ld/ld.1 b/gnu/usr.bin/ld/ld.1 index 06855d87d0..3295282b1d 100644 --- a/gnu/usr.bin/ld/ld.1 +++ b/gnu/usr.bin/ld/ld.1 @@ -14,7 +14,7 @@ .\" must display the following acknowledgement: .\" This product includes software developed by Paul Kranenburg. .\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software withough specific prior written permission +.\" derived from this software without 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 @@ -27,11 +27,11 @@ .\" (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: ld.1,v 1.3 1994/01/03 23:52:35 jkh Exp $ +.\" $Id: ld.1,v 1.5 1994/01/29 02:03:04 jtc Exp $ .\" .Dd October 14, 1993 .Dt LD 8 -.Os FreeBSD +.Os FreeBSD 1.1 .Sh NAME .Nm ld .Nd link editor @@ -69,7 +69,7 @@ The options are as follows: .It Fl A Ar symbol-file The the symbol-file is taken as a base for link-editing the object files on the command line. -.It \-assert Ar keyword +.It Fl a\&ssert Ar keyword This option has currently no effect. It is here for compatibility with SunOS ld. All conditions which would cause a Sun assertion to fail will currently always cause error or warning messages from @@ -85,7 +85,7 @@ found a traditional archive is looked for. This options can appear anywhere on the command line and is complementary to -Bstatic. .It Fl B Ar static -The counterpart of -Bdynamic. This options turns off dynamic linking for +The counterpart of -Bdynamic. This option turns off dynamic linking for all library specifiers until a -Bdynamic is once again given. Any explicitly mentioned shared object encountered on the command line while this option is in effect is flagged as an error. @@ -170,27 +170,30 @@ Discard local symbols in the input files that start with the letter .Dq L .It Fl x Discard all local symbols in the input files. -.It Fl y symbol +.It Fl y Ar symbol Trace the manipulations inflicted on .Ar symbol -.It Fl Z -Make a NetBSD 0.9 ZMAGIC output file. .It Fl z -Make a ZMAGIC output file. This is the older 386BSD / FreeBSD 1.0 format. +Make a NetBSD 0.9 ZMAGIC output file. .Sh FILES - .Sh SEE ALSO .Xr ldconfig 1 , .Xr link 5 -.Sh BUGS -Spurious -.Dq undefined symbols errors -may be reported for symbols originating in shared libraries. This occurs -when there is also at least one genuine undefined symbol to report. .Sh CAVEATS An entry point must now explicitly be given if the output is intended to be a normal executable program. This was not the case for the previous version of .Nm ld\&. +.Sh BUGS +Shared objects are not properly checked for undefined symbols. +.Pp +Cascading of shared object defeats the +.Dq -Bstatic +option. +.Pp +All shared objects presented to +.Nm ld +are marked for run-time loading in the output file, even if no symbols +are needed from them. .Sh HISTORY The shared library model employed by .Nm ld diff --git a/gnu/usr.bin/ld/ld.c b/gnu/usr.bin/ld/ld.c index ad6f9a6488..1d63c82205 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.18 1994/01/03 18:35:14 davidg Exp $ + * $Id: ld.c,v 1.19 1994/01/19 15:00:27 davidg Exp $ */ /* Define how to initialize system-dependent header fields. */ @@ -55,17 +55,18 @@ 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; +/* Vector of entries for input files specified by arguments. + These are all the input files except for members of specified libraries. */ +struct file_entry *file_table; +int number_of_files; -/* 1 => write relocation into output file so can re-input it later. */ +/* 1 => write relocation into output file so can re-input it later. */ int relocatable_output; -/* Non zero means to create the output executable. */ -/* Cleared by nonfatal errors. */ +/* 1 => building a shared object, set by `-Bshareable'. */ +int building_shared_object; + +/* 1 => create the output executable. */ int make_executable; /* Force the executable to be output, even if there are non-fatal errors */ @@ -81,9 +82,72 @@ int force_alias_definition; if `relocatable_output'. */ int pic_code_seen; +/* 1 => segments must be page aligned (ZMAGIC, QMAGIC) */ +int page_align_segments; + /* 1 => data segment must be page aligned, even if `-n' or `-N' */ int page_align_data; +/* Version number to put in __DYNAMIC (set by -V) */ +int soversion; + +int text_size; /* total size of text. */ +int text_start; /* start of text */ +int text_pad; /* clear space between text and data */ +int data_size; /* total size of data. */ +int data_start; /* start of data */ +int data_pad; /* part of bss segment as part of data */ + +int bss_size; /* total size of bss. */ +int bss_start; /* start of bss */ + +int text_reloc_size; /* total size of text relocation. */ +int data_reloc_size; /* total size of data relocation. */ + +int rrs_section_type; /* What's in the RRS section */ +int rrs_text_size; /* Size of RRS text additions */ +int rrs_text_start; /* Location of above */ +int rrs_data_size; /* Size of RRS data additions */ +int rrs_data_start; /* Location of above */ + +/* Specifications of start and length of the area reserved at the end + of the data segment for the set vectors. Computed in 'digest_symbols' */ +int set_sect_start; /* start of set element vectors */ +int set_sect_size; /* size of above */ + +int link_mode; /* Current link mode */ + +/* + * When loading the text and data, we can avoid doing a close + * and another open between members of the same library. + * + * These two variables remember the file that is currently open. + * Both are zero if no file is open. + * + * See `each_file' and `file_close'. + */ +struct file_entry *input_file; +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. */ +struct exec outheader; /* Output file header. */ +int magic; /* Output file magic. */ +int oldmagic; +int relocatable_output; /* `-r'-ed output */ + +symbol *entry_symbol; +int entry_offset; + +int page_size; /* Size of a page (machine dependent) */ + +/* Keep a list of any symbols referenced from the command line (so + that error messages for these guys can be generated). This list is + zero terminated. */ +struct glosym **cmdline_references; +int cl_refs_allocated; + /* * Which symbols should be stripped (omitted from the output): none, all, or * debugger symbols. @@ -100,11 +164,33 @@ enum { DISCARD_NONE, DISCARD_ALL, DISCARD_L } discard_locals; -/* Nonzero means print names of input files as processed. */ -int trace_files; +int global_sym_count; /* # of nlist entries for global symbols */ +int size_sym_count; /* # of N_SIZE nlist entries for output + (relocatable_output only) */ +int local_sym_count; /* # of nlist entries for local symbols. */ +int non_L_local_sym_count; /* # of nlist entries for non-L symbols */ +int debugger_sym_count; /* # of nlist entries for debugger info. */ +int undefined_global_sym_count; /* # of global symbols referenced and + not defined. */ +int undefined_shobj_sym_count; /* # of undefined symbols referenced + by shared objects */ +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 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. + */ +int global_alias_count; /* # of aliased symbols */ +int set_symbol_count; /* # of N_SET* symbols. */ +int set_vector_count; /* # of set vectors in output. */ +int warning_count; /* # of warning symbols encountered. */ -/* Magic number to use for the output file, set by switch. */ -int magic; +struct string_list_element *set_element_prefixes; + +int trace_files; /* print names of input files as processed (`-t'). */ +int write_map; /* write a load map (`-M') */ /* * `text-start' address is normally this much plus a page boundary. @@ -137,6 +223,7 @@ 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 load_symbols __P((void)); static void enter_global_ref __P((struct localsymbol *, char *, struct file_entry *)); static void digest_symbols __P((void)); @@ -144,6 +231,7 @@ 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 consider_local_symbols __P((struct file_entry *)); static void perform_relocation __P((char *, int, struct relocation_info *, int, struct file_entry *, int)); @@ -151,7 +239,15 @@ 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 write_output __P((void)); +static void write_header __P((void)); +static void write_text __P((void)); +static void write_data __P((void)); +static void write_rel __P((void)); +static void write_syms __P((void)); static void assign_symbolnums __P((struct file_entry *, int *)); +static void myfatal __P((void)); + int main(argc, argv) @@ -189,6 +285,7 @@ main(argc, argv) data_pad = 0; text_pad = 0; + page_align_segments = 0; page_align_data = 0; /* Initialize the data about options. */ @@ -251,6 +348,9 @@ main(argc, argv) * of system and on the output format selected. */ + if (magic == ZMAGIC || magic == QMAGIC) + page_align_segments = 1; + md_init_header(&outheader, magic, 0); text_size = sizeof(struct exec); @@ -430,15 +530,15 @@ decode_command(argc, argv) fatal("-A specified before an input file other than the first"); p->filename = string; p->local_sym_name = string; - p->just_syms_flag = 1; + p->flags |= E_JUST_SYMS; p++; } if (argv[i][1] == 'l') { p->filename = string; p->local_sym_name = concat("-l", string, ""); - p->search_dirs_flag = 1; + p->flags |= E_SEARCH_DIRS; if (link_mode & DYNAMIC && !relocatable_output) - p->search_dynamic_flag = 1; + p->flags |= E_SEARCH_DYNAMIC; p++; } i += code - 1; @@ -446,8 +546,8 @@ decode_command(argc, argv) /* Now check some option settings for consistency. */ - if ((magic != OMAGIC) - && (text_start - text_start_alignment) & (page_size - 1)) + if (page_align_segments + && (text_start - text_start_alignment) & (page_size - 1)) fatal("-T argument not multiple of page size, with sharable output"); /* Append the standard search directories to the user-specified ones. */ @@ -456,9 +556,9 @@ decode_command(argc, argv) void add_cmdline_ref(sp) - struct glosym *sp; + symbol *sp; { - struct glosym **ptr; + symbol **ptr; for (ptr = cmdline_references; ptr < cmdline_references + cl_refs_allocated && *ptr; @@ -474,7 +574,7 @@ add_cmdline_ref(sp) ptr = cmdline_references + diff; } *ptr++ = sp; - *ptr = (struct glosym *) 0; + *ptr = (symbol *) 0; } int @@ -505,7 +605,6 @@ static void decode_option(swt, arg) register char *swt, *arg; { - /* We get Bstatic from gcc on suns. */ if (!strcmp(swt + 1, "Bstatic")) return; if (!strcmp(swt + 1, "Bdynamic")) @@ -558,9 +657,10 @@ decode_option(swt, arg) case 'e': entry_symbol = getsym(arg); - if (!entry_symbol->defined && !entry_symbol->referenced) + if (!entry_symbol->defined && + !(entry_symbol->flags & GS_REFERENCED)) undefined_global_sym_count++; - entry_symbol->referenced = 1; + entry_symbol->flags |= GS_REFERENCED; add_cmdline_ref(entry_symbol); return; @@ -579,19 +679,9 @@ decode_option(swt, arg) magic = OMAGIC; return; -#ifdef NMAGIC case 'n': magic = NMAGIC; return; -#endif - - case 'Q': - magic = QMAGIC; - return; - case 'Z': - magic = ZMAGIC; - netzmagic = 1; - return; case 'o': output_filename = arg; @@ -601,6 +691,12 @@ decode_option(swt, arg) page_align_data = 1; return; +#ifdef QMAGIC + case 'Q': + magic = QMAGIC; + return; +#endif + case 'r': relocatable_output = 1; magic = OMAGIC; @@ -628,9 +724,9 @@ decode_option(swt, arg) { register symbol *sp = getsym(arg); - if (!sp->defined && !sp->referenced) + if (!sp->defined && !(sp->flags & GS_REFERENCED)) undefined_global_sym_count++; - sp->referenced = 1; + sp->flags |= GS_REFERENCED; add_cmdline_ref(sp); } return; @@ -652,12 +748,17 @@ decode_option(swt, arg) case 'y': { register symbol *sp = getsym(&swt[2]); - sp->trace = 1; + sp->flags |= GS_TRACE; } return; case 'z': magic = ZMAGIC; + oldmagic = 0; + return; + + case 'Z': + magic = oldmagic = ZMAGIC; return; default: @@ -686,15 +787,15 @@ each_file(function, arg) register struct file_entry *entry = &file_table[i]; register struct file_entry *subentry; - if (entry->scrapped) + if (entry->flags & E_SCRAPPED) continue; - if (!entry->library_flag) + if (!(entry->flags & E_IS_LIBRARY)) (*function) (entry, arg); subentry = entry->subfiles; for (; subentry; subentry = subentry->chain) { - if (subentry->scrapped) + if (subentry->flags & E_SCRAPPED) continue; (*function) (subentry, arg); } @@ -702,15 +803,15 @@ each_file(function, arg) #ifdef SUN_COMPAT if (entry->silly_archive) { - if (!entry->is_dynamic) + if (!(entry->flags & E_DYNAMIC)) error("Silly"); - if (!entry->silly_archive->library_flag) + if (!(entry->silly_archive->flags & E_IS_LIBRARY)) error("Sillier"); subentry = entry->silly_archive->subfiles; for (; subentry; subentry = subentry->chain) { - if (subentry->scrapped) + if (subentry->flags & E_SCRAPPED) continue; (*function) (subentry, arg); } @@ -738,12 +839,12 @@ check_each_file(function, arg) for (i = 0; i < number_of_files; i++) { register struct file_entry *entry = &file_table[i]; - if (entry->scrapped) + if (entry->flags & E_SCRAPPED) continue; - if (entry->library_flag) { + if (entry->flags & E_IS_LIBRARY) { register struct file_entry *subentry = entry->subfiles; for (; subentry; subentry = subentry->chain) { - if (subentry->scrapped) + if (subentry->flags & E_SCRAPPED) continue; if (return_val = (*function) (subentry, arg)) return return_val; @@ -767,35 +868,35 @@ each_full_file(function, arg) register struct file_entry *entry = &file_table[i]; register struct file_entry *subentry; - if (entry->scrapped || entry->just_syms_flag) + if (entry->flags & (E_SCRAPPED | E_JUST_SYMS)) continue; #ifdef SUN_COMPAT if (entry->silly_archive) { - if (!entry->is_dynamic) + if (!(entry->flags & E_DYNAMIC)) error("Silly"); - if (!entry->silly_archive->library_flag) + if (!(entry->silly_archive->flags & E_IS_LIBRARY)) error("Sillier"); subentry = entry->silly_archive->subfiles; for (; subentry; subentry = subentry->chain) { - if (subentry->scrapped) + if (subentry->flags & E_SCRAPPED) continue; (*function) (subentry, arg); } } #endif - if (entry->is_dynamic) + if (entry->flags & E_DYNAMIC) continue; - if (!entry->library_flag) + if (!(entry->flags & E_IS_LIBRARY)) (*function) (entry, arg); subentry = entry->subfiles; for (; subentry; subentry = subentry->chain) { - if (subentry->scrapped) + if (subentry->flags & E_SCRAPPED) continue; (*function) (subentry, arg); } @@ -824,7 +925,7 @@ file_open (entry) { register int desc; - if (entry->superfile && entry->superfile->library_flag) + if (entry->superfile && (entry->superfile->flags & E_IS_LIBRARY)) return file_open (entry->superfile); if (entry == input_file) @@ -832,7 +933,7 @@ file_open (entry) if (input_file) file_close (); - if (entry->search_dirs_flag) { + if (entry->flags & E_SEARCH_DIRS) { desc = findlib(entry); } else desc = open (entry->filename, O_RDONLY, 0); @@ -853,8 +954,8 @@ text_offset (entry) { return entry->starting_offset + N_TXTOFF (entry->header); } - -/* Medium-level input routines for rel files. */ + +/*---------------------------------------------------------------------------*/ /* * Read a file's header into the proper place in the file_entry. DESC is the @@ -865,8 +966,7 @@ read_header (desc, entry) int desc; register struct file_entry *entry; { - register int len; - struct exec *loc = (struct exec *) &entry->header; + register int len, mid; if (lseek (desc, entry->starting_offset, L_SET) != entry->starting_offset) @@ -878,10 +978,13 @@ read_header (desc, entry) md_swapin_exec_hdr(&entry->header); - if (N_BADMAG (*loc)) + if (N_BADMAG (entry->header)) fatal_with_file ("bad magic number in ", entry); - entry->header_read_flag = 1; + if (N_BADMID(entry->header)) + fatal_with_file ("non-native input file ", entry); + + entry->flags |= E_HEADER_VALID; } /* @@ -899,7 +1002,7 @@ read_entry_symbols (desc, entry) struct nlist *np; int i; - if (!entry->header_read_flag) + if (!(entry->flags & E_HEADER_VALID)) read_header (desc, entry); np = (struct nlist *) alloca (entry->header.a_syms); @@ -921,11 +1024,9 @@ read_entry_symbols (desc, entry) entry->symbols[i].nzlist.nz_size = 0; entry->symbols[i].symbol = NULL; entry->symbols[i].next = NULL; + entry->symbols[i].entry = entry; entry->symbols[i].gotslot_offset = -1; - entry->symbols[i].gotslot_claimed = 0; - entry->symbols[i].write = 0; - entry->symbols[i].is_L_symbol = 0; - entry->symbols[i].rename = 0; + entry->symbols[i].flags = 0; } entry->strings_offset = N_STROFF(entry->header) + @@ -949,7 +1050,7 @@ read_entry_strings (desc, entry) { int buffer; - if (!entry->header_read_flag || !entry->strings_offset) + if (!(entry->flags & E_HEADER_VALID) || !entry->strings_offset) fatal_with_file("internal error: cannot read string table for ", entry); @@ -963,14 +1064,6 @@ read_entry_strings (desc, entry) return; } -/* DEAD - Read in all of the relocation information */ - -void -read_relocation () -{ - each_full_file (read_entry_relocation, 0); -} - /* Read in the relocation sections of ENTRY if necessary */ void @@ -1026,23 +1119,24 @@ read_entry_relocation (desc, entry) } } - -/* Read in the symbols of all input files. */ - +/*---------------------------------------------------------------------------*/ -void +/* + * Read in the symbols of all input files. + */ +static void load_symbols () { register int i; - if (trace_files) fprintf (stderr, "Loading symbols:\n\n"); + if (trace_files) + fprintf(stderr, "Loading symbols:\n\n"); - for (i = 0; i < number_of_files; i++) { - register struct file_entry *entry = &file_table[i]; - read_file_symbols (entry); - } + for (i = 0; i < number_of_files; i++) + read_file_symbols(&file_table[i]); - if (trace_files) fprintf (stderr, "\n"); + if (trace_files) + fprintf (stderr, "\n"); } /* @@ -1068,18 +1162,18 @@ read_file_symbols (entry) md_swapin_exec_hdr(&hdr); if (!N_BADMAG (hdr)) { - if (N_IS_DYNAMIC(hdr)) { + if (N_IS_DYNAMIC(hdr) && !(entry->flags & E_JUST_SYMS)) { if (relocatable_output) { fatal_with_file( "-r and shared objects currently not supported ", entry); return; } - entry->is_dynamic = 1; + entry->flags |= E_DYNAMIC; if (entry->superfile || rrs_add_shobj(entry)) read_shared_object(desc, entry); else - entry->scrapped = 1; + entry->flags |= E_SCRAPPED; } else { read_entry_symbols (desc, entry); entry->strings = (char *) alloca (entry->string_size); @@ -1096,14 +1190,17 @@ read_file_symbols (entry) strncmp (armag, ARMAG, SARMAG)) fatal_with_file( "malformed input file (not rel or archive) ", entry); - entry->library_flag = 1; + entry->flags |= E_IS_LIBRARY; search_library (desc, entry); } file_close (); } - -/* Enter the external symbol defs and refs of ENTRY in the hash table. */ + + +/* + * Enter the external symbol defs and refs of ENTRY in the hash table. + */ void enter_file_symbols (entry) @@ -1160,7 +1257,7 @@ enter_file_symbols (entry) p->n_un.n_strx + entry->strings, entry); } else if (p->n_un.n_strx && (p->n_un.n_strx + entry->strings)[0] == LPREFIX) - lsp->is_L_symbol = 1; + lsp->flags |= LS_L_SYMBOL; } } @@ -1190,9 +1287,9 @@ enter_global_ref (lsp, name, entry) register struct nzlist *nzp = &lsp->nzlist; register symbol *sp = getsym (name); register int type = nzp->nz_type; - int oldref = sp->referenced; + int oldref = (sp->flags & GS_REFERENCED); int olddef = sp->defined; - int com = sp->defined && sp->max_common_size; + int com = sp->defined && sp->common_size; if (type == (N_INDR | N_EXT)) { sp->alias = getsym(entry->strings + (lsp + 1)->nzlist.nz_strx); @@ -1208,7 +1305,7 @@ enter_global_ref (lsp, name, entry) } } - if (entry->is_dynamic) { + if (entry->flags & E_DYNAMIC) { lsp->next = sp->sorefs; sp->sorefs = lsp; @@ -1223,11 +1320,17 @@ enter_global_ref (lsp, name, entry) if (oldref) undefined_global_sym_count--; common_defined_global_count++; - sp->max_common_size = nzp->nz_value; + sp->common_size = nzp->nz_value; sp->defined = N_UNDF | N_EXT; - } else if (com && sp->max_common_size < nzp->nz_value) { - sp->max_common_size = nzp->nz_value; + } else if (com && sp->common_size < nzp->nz_value) { + sp->common_size = nzp->nz_value; } + } else if (type != (N_UNDF | N_EXT) && !oldref) { + /* + * This is an ex common... + */ + sp->common_size = 0; + sp->defined = 0; } /* @@ -1244,10 +1347,10 @@ enter_global_ref (lsp, name, entry) sp->refs = lsp; lsp->symbol = sp; - sp->referenced = 1; + sp->flags |= GS_REFERENCED; if (sp == dynamic_symbol || sp == got_symbol) { - if (type != (N_UNDF | N_EXT) && !entry->just_syms_flag) + if (type != (N_UNDF | N_EXT) && !(entry->flags & E_JUST_SYMS)) fatal("Linker reserved symbol %s defined as type %x ", name, type); return; @@ -1281,33 +1384,38 @@ enter_global_ref (lsp, name, entry) * First definition and it's common. */ common_defined_global_count++; - sp->max_common_size = nzp->nz_value; + sp->common_size = nzp->nz_value; } else if (com && type != (N_UNDF | N_EXT)) { /* * It used to be common and we're defining * it as something else. */ common_defined_global_count--; - sp->max_common_size = 0; + sp->common_size = 0; } else if (com && type == (N_UNDF | N_EXT) - && sp->max_common_size < nzp->nz_value) + && sp->common_size < nzp->nz_value) /* * It used to be common and this is a new common entry * to which we need to pay attention. */ - sp->max_common_size = nzp->nz_value; + sp->common_size = nzp->nz_value; if (SET_ELEMENT_P(type) && (!olddef || com)) set_vector_count++; - } else if (!oldref) + } else if (!oldref && !com) + /* + * An unreferenced symbol can already be defined + * as common by shared objects. + */ undefined_global_sym_count++; - if (sp == end_symbol && entry->just_syms_flag && !T_flag_specified) + if (sp == end_symbol && (entry->flags & E_JUST_SYMS) && + !T_flag_specified) text_start = nzp->nz_value; - if (sp->trace) { + if (sp->flags & GS_TRACE) { register char *reftype; switch (type & N_TYPE) { case N_UNDF: @@ -1343,7 +1451,7 @@ enter_global_ref (lsp, name, entry) } /* - * This return 0 if the given file entry's symbol table does *not* contain + * This returns 0 if the given file entry's symbol table does *not* contain * the nlist point entry, and it returns the files entry pointer (cast to * unsigned long) if it does. */ @@ -1391,7 +1499,6 @@ contains_symbol (entry, np) * */ - static void digest_symbols () { @@ -1419,6 +1526,8 @@ digest_symbols () each_full_file(consider_relocation, 0); /* Text */ each_full_file(consider_relocation, 1); /* Data */ + each_file(consider_local_symbols, 0); + /* * Compute total size of sections. * RRS data is the first output data section, RRS text is the last @@ -1437,7 +1546,7 @@ digest_symbols () * the padding in the text segment size. */ - if (magic == ZMAGIC || magic == QMAGIC || page_align_data) { + if (page_align_segments || page_align_data) { int text_end = text_size + N_TXTOFF(outheader); text_pad = PALIGN(text_end, page_size) - text_end; text_size += text_pad; @@ -1490,7 +1599,7 @@ printf("bssstart = %#x, bsssize = %#x\n", if (specified_data_size && specified_data_size > data_size) data_pad = specified_data_size - data_size; - if (magic == ZMAGIC || magic == QMAGIC) + if (page_align_segments) data_pad = PALIGN(data_pad + data_size, page_size) - data_size; bss_size -= data_pad; @@ -1506,10 +1615,10 @@ printf("bssstart = %#x, bsssize = %#x\n", global_sym_count = defined_global_sym_count + undefined_global_sym_count; - if (dynamic_symbol->referenced) + if (dynamic_symbol->flags & GS_REFERENCED) global_sym_count++; - if (got_symbol->referenced) + if (got_symbol->flags & GS_REFERENCED) global_sym_count++; if (relocatable_output || building_shared_object) @@ -1529,12 +1638,15 @@ debug symbols: %d, set_symbols %d\n", #endif } +/* + * Determine the definition of each global symbol. + */ static void digest_pass1() { /* - * Now, for each symbol, verify that it is defined globally at most + * For each symbol, verify that it is defined globally at most * once within relocatable files (except when building a shared lib). * and set the `defined' field if there is a definition. * @@ -1546,7 +1658,7 @@ digest_pass1() struct localsymbol *lsp; int defs = 0; - if (!sp->referenced) { + if (!(sp->flags & GS_REFERENCED)) { #if 0 /* Check for undefined symbols in shared objects */ int type; @@ -1580,7 +1692,7 @@ digest_pass1() sp->value = setv_fill_count++ * sizeof(long); } else if ((sp->defined & N_TYPE) != N_SETV) { - sp->multiply_defined = 1; + sp->mult_defs = 1; multiple_def_count++; } /* Keep count and remember symbol */ @@ -1588,6 +1700,12 @@ digest_pass1() set_vectors[setv_fill_count++] = (long)p; if (building_shared_object) { struct relocation_info reloc; + + /* + * Make sure to relocate the contents + * of this set vector. + */ + bzero(&reloc, sizeof(reloc)); RELOC_ADDRESS(&reloc) = setv_fill_count * sizeof(long); alloc_rrs_segment_reloc(NULL, &reloc); @@ -1598,12 +1716,14 @@ digest_pass1() && (type & N_TYPE) != N_SIZE) { /* non-common definition */ if (defs++ && sp->value != p->n_value - && entry_symbol) { - sp->multiply_defined = 1; + && entry_symbol/*XXX*/) { + sp->mult_defs = 1; multiple_def_count++; } sp->def_nlist = p; + lsp->entry->flags |= E_SYMBOLS_USED; sp->defined = type; + sp->aux = N_AUX(p); } } @@ -1645,15 +1765,17 @@ digest_pass1() && (type & N_TYPE) != N_FN) { /* non-common definition */ sp->def_nlist = p; + lsp->entry->flags |= E_SYMBOLS_USED; sp->so_defined = type; - if (sp->referenced) + sp->aux = N_AUX(p); + if (sp->flags & GS_REFERENCED) undefined_global_sym_count--; else - sp->referenced = 1; + sp->flags |= GS_REFERENCED; #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) { + if (sp->alias && !(sp->alias->flags & GS_REFERENCED)) { sp = sp->alias; goto again; } @@ -1668,159 +1790,10 @@ doesn't match actual (%d)", set_sect_size/sizeof(long), setv_fill_count); } -static void -digest_pass2() -{ - /* - * Assign each symbol its final value. - * If not -r'ing, allocate common symbols in the BSS section. - */ - - FOR_EACH_SYMBOL(i, sp) { - int size; - int align = sizeof(int); - - 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 - * at end. Reverse the vector itself to put it in - * file order. - */ - unsigned long i, tmp; - unsigned long length_word_index = - sp->value / sizeof(long); - - /* Relocate symbol value */ - sp->value += set_sect_start; - - set_vectors[length_word_index] = sp->setv_count; - - /* - * Relocate vector to final address. - */ - for (i = 0; i < sp->setv_count; i++) { - struct nlist *p = (struct nlist *) - set_vectors[1+i+length_word_index]; - - set_vectors[1+i+length_word_index] = p->n_value; - if (building_shared_object) { - struct relocation_info reloc; - RELOC_ADDRESS(&reloc) = - (1 + i + length_word_index) * - sizeof(long) - + set_sect_start; - RELOC_TYPE(&reloc) = - (sp->defined & N_TYPE); - claim_rrs_segment_reloc(NULL, &reloc); - } - } - - /* - * Reverse the vector. - */ - for (i = 1; i < (sp->setv_count - 1)/2 + 1; i++) { - - tmp = set_vectors[length_word_index + i]; - set_vectors[length_word_index + i] = - set_vectors[length_word_index + sp->setv_count + 1 - i]; - set_vectors[length_word_index + sp->setv_count + 1 - i] = tmp; - } - - /* Clear terminating entry */ - set_vectors[length_word_index + sp->setv_count + 1] = 0; - continue; - } - - - if (sp->defined && sp->def_nlist && - ((sp->defined & ~N_EXT) != N_SETV)) - sp->value = sp->def_nlist->n_value; - - if (building_shared_object && !(link_mode & SYMBOLIC)) - /* No common allocation in shared objects */ - continue; - - if ((size = sp->max_common_size) != 0) { - /* - * It's a common. - */ - if (sp->defined != (N_UNDF + N_EXT)) - fatal("%s: common isn't", sp->name); - - } else if ((size = sp->size) != 0 && sp->defined == N_SIZE) { - /* - * It's data from shared object with size info. - */ - if (!sp->so_defined) - fatal("%s: Bogus N_SIZE item", sp->name); - - } else - /* - * It's neither - */ - continue; - - - if (relocatable_output && !force_common_definition) { - sp->defined = 0; - undefined_global_sym_count++; - defined_global_sym_count--; - continue; - } - - /* - * Round up to nearest sizeof (int). I don't know whether - * this is necessary or not (given that alignment is taken - * care of later), but it's traditional, so I'll leave it in. - * Note that if this size alignment is ever removed, ALIGN - * above will have to be initialized to 1 instead of sizeof - * (int). - */ - - size = PALIGN(size, sizeof(int)); - - while (!(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); - - sp->value = rrs_data_start + data_size + bss_size; - if (sp->defined == (N_UNDF | N_EXT)) - sp->defined = N_BSS | N_EXT; - else { - sp->so_defined = 0; - defined_global_sym_count++; - } - bss_size += size; - if (write_map) - printf("Allocating %s %s: %x at %x\n", - sp->defined==(N_BSS|N_EXT)?"common":"data", - sp->name, size, sp->value); - - } END_EACH_SYMBOL; -} - /* - * Scan relocation info in ENTRY for contributions to the dynamic section of - * the output file. + * Scan relocation info in ENTRY for contributions to the RRS section + * of the output file. */ static void consider_relocation (entry, dataseg) @@ -1848,7 +1821,7 @@ consider_relocation (entry, dataseg) if (RELOC_BASEREL_P(reloc)) { pic_code_seen = 1; if (!RELOC_EXTERN_P(reloc)) - lsp->rename = 1; + lsp->flags |= LS_RENAME; } continue; } @@ -1939,39 +1912,20 @@ consider_relocation (entry, dataseg) continue; } - /* - * Only allocate an alias for function calls. Use - * sp->size here as a heuristic to discriminate - * between function definitions and data residing - * in the text segment. - * NOTE THAT THE COMPILER MUST NOT GENERATE ".size" - * DIRECTIVES FOR FUNCTIONS. - * In the future we might go for ".type" directives. - */ - if (force_alias_definition && sp->size == 0 && - sp->so_defined == N_TEXT + N_EXT) { + if (force_alias_definition && sp->so_defined && + sp->aux == AUX_FUNC) { /* Call to shared library procedure */ alloc_rrs_jmpslot(entry, sp); -#define EXPERIMENTAL -#ifdef EXPERIMENTAL - if (!RELOC_PCREL_P(reloc)) { -#ifdef DEBUG -printf("%s: FUNC flag set\n", sp->name); -#endif - sp->aux = RRS_FUNC; - } -#endif - } else if (sp->size && - (sp->so_defined == N_DATA + N_EXT || - sp->so_defined == N_TEXT + N_EXT)) { + } else if (sp->size && sp->so_defined && + sp->aux == AUX_OBJECT) { /* Reference to shared library data */ alloc_rrs_cpy_reloc(entry, sp); sp->defined = N_SIZE; - } else if (!sp->defined && sp->max_common_size == 0) + } else if (!sp->defined && sp->common_size == 0) alloc_rrs_reloc(entry, sp); } else { @@ -1987,6 +1941,76 @@ printf("%s: FUNC flag set\n", sp->name); } } +/* + * Determine the disposition of each local symbol. + */ +static void +consider_local_symbols(entry) + register struct file_entry *entry; +{ + register struct localsymbol *lsp, *lspend; + + if (entry->flags & E_DYNAMIC) + return; + + lspend = entry->symbols + entry->nsymbols; + + /* + * For each symbol determine whether it should go + * in the output symbol table. + */ + + for (lsp = entry->symbols; lsp < lspend; lsp++) { + register struct nlist *p = &lsp->nzlist.nlist; + register int type = p->n_type; + + if (type == N_WARNING) + continue; + + if (SET_ELEMENT_P (type)) { + /* + * This occurs even if global. These types of + * symbols are never written globally, though + * they are stored globally. + */ + if (relocatable_output) + lsp->flags |= LS_WRITE; + + } else if (!(type & (N_STAB | N_EXT))) { + + /* + * Ordinary local symbol + */ + if ((lsp->flags & LS_RENAME) || ( + discard_locals != DISCARD_ALL && + !(discard_locals == DISCARD_L && + (lsp->flags & LS_L_SYMBOL))) ) { + + lsp->flags |= LS_WRITE; + local_sym_count++; + } + + } else if (!(type & N_EXT)) { + + /* + * Debugger symbol + */ + if (strip_symbols == STRIP_NONE) { + lsp->flags |= LS_WRITE; + debugger_sym_count++; + } + } + } + + /* + * Count one for the local symbol that we generate, + * whose name is the file's name (usually) and whose address + * is the start of the file's text. + */ + if (discard_locals != DISCARD_ALL) + local_sym_count++; +} + /* * Accumulate the section sizes of input file ENTRY into the section sizes of * the output file. @@ -1995,8 +2019,6 @@ static void consider_file_section_lengths (entry) register struct file_entry *entry; { - if (entry->just_syms_flag) - return; entry->text_start_address = text_size; /* If there were any vectors, we need to chop them off */ @@ -2013,9 +2035,7 @@ consider_file_section_lengths (entry) /* * Determine where the sections of ENTRY go into the output file, * whose total section sizes are already known. - * Also relocate the addresses of the file's local and debugger symbols - * and determine which of the local symbols will make it into the - * output symbol table. + * Also relocate the addresses of the file's local and debugger symbols. */ static void relocate_file_addresses (entry) @@ -2072,57 +2092,165 @@ printf("%s: datastart: %#x, bss %#x\n", get_file_name(entry), break; } - /* - * See if this symbol should be in the output symbol table. - */ + } - if (type == N_WARNING) +} + +/* + * Assign a value to each global symbol. + */ +static void +digest_pass2() +{ + FOR_EACH_SYMBOL(i, sp) { + int size; + int align = sizeof(int); + + if (!(sp->flags & GS_REFERENCED)) continue; - if (SET_ELEMENT_P (type)) { + if (sp->alias && + (relocatable_output || building_shared_object || + (sp->alias->defined && !sp->alias->so_defined))) /* - * This occurs even if global. These types of - * symbols are never written globally, though - * they are stored globally. + * 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. */ - lsp->write = relocatable_output; + defined_global_sym_count++; - } else if (!(type & (N_STAB | N_EXT))) { + if ((sp->defined & N_TYPE) == N_SETV) { + /* + * Set length word at front of vector and zero byte + * at end. Reverse the vector itself to put it in + * file order. + */ + unsigned long i, *p, *q; + unsigned long length_word_index = + sp->value / sizeof(long); + + /* Relocate symbol value */ + sp->value += set_sect_start; + + set_vectors[length_word_index] = sp->setv_count; /* - * Ordinary local symbol + * Relocate vector to final address. */ - lsp->write = (lsp->rename || ( - discard_locals != DISCARD_ALL && - !(discard_locals == DISCARD_L && - lsp->is_L_symbol))); - if (lsp->write) - local_sym_count++; + for (i = 0; i < sp->setv_count; i++) { + struct nlist *p = (struct nlist *) + set_vectors[1+i+length_word_index]; - } else if (!(type & N_EXT)) { + set_vectors[1+i+length_word_index] = p->n_value; + if (building_shared_object) { + struct relocation_info reloc; + + bzero(&reloc, sizeof(reloc)); + RELOC_ADDRESS(&reloc) = + (1 + i + length_word_index) * + sizeof(long) + + set_sect_start; + RELOC_TYPE(&reloc) = + (p->n_type - (N_SETA - N_ABS)) & N_TYPE; + claim_rrs_segment_reloc(NULL, &reloc); + } + } /* - * Debugger symbol + * Reverse the vector. */ - lsp->write = (strip_symbols == STRIP_NONE); - if (lsp->write) - debugger_sym_count++; + p = &set_vectors[length_word_index + 1]; + q = &set_vectors[length_word_index + sp->setv_count]; + while (p < q) { + unsigned long tmp = *p; + *p++ = *q; + *q-- = tmp; + } + /* Clear terminating entry */ + set_vectors[length_word_index + sp->setv_count + 1] = 0; + continue; } - } - /* - * Count one for the local symbol that we generate, - * whose name is the file's name (usually) and whose address - * is the start of the file's text. - */ - if (discard_locals != DISCARD_ALL) - local_sym_count++; + if (sp->defined && sp->def_nlist && + ((sp->defined & ~N_EXT) != N_SETV)) + sp->value = sp->def_nlist->n_value; + + /* + * If not -r'ing, allocate common symbols in the BSS section. + */ + if (building_shared_object && !(link_mode & SYMBOLIC)) + /* No common allocation in shared objects */ + continue; + + if ((size = sp->common_size) != 0) { + /* + * It's a common. + */ + if (sp->defined != (N_UNDF + N_EXT)) + fatal("%s: common isn't", sp->name); + + } else if ((size = sp->size) != 0 && sp->defined == N_SIZE) { + /* + * It's data from shared object with size info. + */ + if (!sp->so_defined) + fatal("%s: Bogus N_SIZE item", sp->name); + + } else + /* + * It's neither + */ + continue; + + + if (relocatable_output && !force_common_definition) { + sp->defined = 0; + undefined_global_sym_count++; + defined_global_sym_count--; + continue; + } + + /* + * Round up to nearest sizeof (int). I don't know whether + * this is necessary or not (given that alignment is taken + * care of later), but it's traditional, so I'll leave it in. + * Note that if this size alignment is ever removed, ALIGN + * above will have to be initialized to 1 instead of sizeof + * (int). + */ + + size = PALIGN(size, sizeof(int)); + + while (!(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); + + sp->value = rrs_data_start + data_size + bss_size; + if (sp->defined == (N_UNDF | N_EXT)) + sp->defined = N_BSS | N_EXT; + else { + sp->so_defined = 0; + defined_global_sym_count++; + } + bss_size += size; + if (write_map) + printf("Allocating %s %s: %x at %x\n", + sp->defined==(N_BSS|N_EXT)?"common":"data", + sp->name, size, sp->value); + + } END_EACH_SYMBOL; } - -/* Write the output file */ + +/* -------------------------------------------------------------------*/ + +/* Write the output file */ void write_output () { @@ -2138,6 +2266,8 @@ write_output () if (outdesc < 0) perror_name (output_filename); + fatal_cleanup_hook = myfatal; + if (fstat (outdesc, &statbuf) < 0) perror_name (output_filename); @@ -2176,6 +2306,9 @@ write_header () { int flags = (rrs_section_type == RRS_FULL) ? EX_DYNAMIC : 0; + if (oldmagic && (flags & EX_DYNAMIC)) + error("Cannot set flag in old magic headers\n"); + N_SET_FLAG (outheader, flags); outheader.a_text = text_size; @@ -2339,7 +2472,7 @@ copy_data (entry) mywrite (bytes, 1, entry->header.a_data, outdesc); } - + /* * Relocate ENTRY's text or data section contents. DATA is the address of the * contents, in core. DATA_SIZE is the length of the contents. PC_RELOCATION @@ -2347,6 +2480,10 @@ copy_data (entry) * and its address in the input file. RELOC is the address of the * relocation info, in core. NRELOC says how many there are. */ + +/* HACK: md.c may need access to this */ +int pc_relocation; + void perform_relocation(data, data_size, reloc, nreloc, entry, dataseg) char *data; @@ -2356,12 +2493,13 @@ perform_relocation(data, data_size, reloc, nreloc, entry, dataseg) struct file_entry *entry; int dataseg; { - register struct relocation_info *r = reloc; - struct relocation_info *end = reloc + nreloc; - text_relocation = entry->text_start_address; - data_relocation = entry->data_start_address - entry->header.a_text; - bss_relocation = entry->bss_start_address - + register struct relocation_info *r = reloc; + struct relocation_info *end = reloc + nreloc; + + int text_relocation = entry->text_start_address; + int data_relocation = entry->data_start_address - entry->header.a_text; + int bss_relocation = entry->bss_start_address - entry->header.a_text - entry->header.a_data; pc_relocation = dataseg? entry->data_start_address - entry->header.a_text: @@ -2616,10 +2754,10 @@ write_rel () /* BLECH - Assign number 0 to __DYNAMIC (!! Sun compatibility) */ - if (dynamic_symbol->referenced) + if (dynamic_symbol->flags & GS_REFERENCED) dynamic_symbol->symbolnum = count++; FOR_EACH_SYMBOL(i, sp) { - if (sp != dynamic_symbol && sp->referenced) { + if (sp != dynamic_symbol && (sp->flags & GS_REFERENCED)) { sp->symbolnum = count++; if (sp->size) count++; @@ -2664,7 +2802,7 @@ assign_symbolnums(entry, countp) n++; for (lsp = entry->symbols; lsp < lspend; lsp++) { - if (lsp->write) + if (lsp->flags & LS_WRITE) lsp->symbolnum = n++; } *countp = n; @@ -2729,10 +2867,11 @@ coptxtrel(entry) * If we aren't going to be adding in the * value in memory on the next pass of the * loader, then we need to add it in from the - * relocation entry. Otherwise the work we + * relocation entry, unless the symbol remains + * external in our output. Otherwise the work we * did in this pass is lost. */ - if (!RELOC_MEMORY_ADD_P(r)) + if (!RELOC_MEMORY_ADD_P(r) && !RELOC_EXTERN_P(r)) RELOC_ADD_EXTRA(r) += sp->value; #endif } else @@ -2794,7 +2933,7 @@ copdatrel(entry) symtype = sp->defined & N_TYPE; - if (!pic_code_seen && (force_common_definition || + if (!pic_code_seen && ( symtype == N_BSS || symtype == N_DATA || symtype == N_TEXT || symtype == N_ABS)) { @@ -2939,7 +3078,7 @@ write_syms() * If defined (ie. not relocatable_output), make it look * like an internal symbol. */ - if (dynamic_symbol->referenced) { + if (dynamic_symbol->flags & GS_REFERENCED) { nl.n_other = 0; nl.n_desc = 0; nl.n_type = dynamic_symbol->defined; @@ -2961,7 +3100,7 @@ write_syms() /* Already dealt with above */ continue; - if (!sp->referenced) + if (!(sp->flags & GS_REFERENCED)) /* Came from shared object but was not used */ continue; @@ -3009,6 +3148,7 @@ write_syms() */ nl.n_type = sp->alias->defined; nl.n_value = sp->alias->value; + nl.n_other = N_OTHER(0, sp->alias->aux); } else { if (sp->defined == N_SIZE) nl.n_type = N_DATA | N_EXT; @@ -3019,9 +3159,10 @@ write_syms() fatal("%s: N_INDR has value %#x", sp->name, sp->value); nl.n_value = sp->value; + nl.n_other = N_OTHER(0, sp->aux); } - } else if (sp->max_common_size) { + } else if (sp->common_size) { /* * defined as common but not allocated, * happens only with -r and not -d, write out @@ -3032,7 +3173,7 @@ write_syms() * undefined in digest_symbols. */ nl.n_type = N_UNDF | N_EXT; - nl.n_value = sp->max_common_size; + nl.n_value = sp->common_size; } else if (!sp->defined) { /* undefined -- legit only if -r */ nl.n_type = N_UNDF | N_EXT; @@ -3053,6 +3194,9 @@ write_syms() *bufp++ = nl; syms_written++; + /* + * Write second symbol of an alias pair. + */ if (nl.n_type == N_INDR + N_EXT) { if (sp->alias == NULL) fatal("internal error: alias in hyperspace"); @@ -3066,6 +3210,9 @@ write_syms() syms_written++; } + /* + * Write N_SIZE symbol for a symbol with a known size. + */ if (relocatable_output && sp->size) { nl.n_type = N_SIZE + N_EXT; nl.n_un.n_strx = assign_string_table_index(sp->name); @@ -3144,7 +3291,7 @@ write_file_syms(entry, syms_written_addr) register struct nlist *bufp = buf; - if (entry->is_dynamic) + if (entry->flags & E_DYNAMIC) return; /* @@ -3168,9 +3315,6 @@ write_file_syms(entry, syms_written_addr) nl.n_other = 0; *bufp++ = nl; (*syms_written_addr)++; -#if 0 - entry->local_syms_offset = *syms_written_addr * sizeof(struct nlist); -#endif } /* Read the file's string table. */ @@ -3185,12 +3329,12 @@ write_file_syms(entry, syms_written_addr) register int write = 0; char *name; - if (! lsp->write) + if (!(lsp->flags & LS_WRITE)) continue; if (p->n_un.n_strx == 0) name = NULL; - else if (lsp->rename == 0) + else if (!(lsp->flags & LS_RENAME)) name = p->n_un.n_strx + entry->strings; else { char *cp = p->n_un.n_strx + entry->strings; @@ -3229,3 +3373,50 @@ write_file_syms(entry, syms_written_addr) write_string_table(); entry->strings = 0; /* Since it will disappear anyway. */ } + +/* + * Output COUNT*ELTSIZE bytes of data at BUF to the descriptor DESC. + */ +void +mywrite (buf, count, eltsize, desc) + void *buf; + int count; + int eltsize; + int desc; +{ + register int val; + register int bytes = count * eltsize; + + while (bytes > 0) { + val = write (desc, buf, bytes); + if (val <= 0) + perror(output_filename); + buf += val; + bytes -= val; + } +} + +static void +myfatal() +{ + if (outdesc > 0) + unlink(output_filename); +} + +/* + * Output PADDING zero-bytes to descriptor OUTDESC. + * PADDING may be negative; in that case, do nothing. + */ +void +padfile (padding, outdesc) + int padding; + int outdesc; +{ + register char *buf; + if (padding <= 0) + return; + + buf = (char *) alloca (padding); + bzero (buf, padding); + mywrite (buf, padding, 1, outdesc); +} diff --git a/gnu/usr.bin/ld/ld.h b/gnu/usr.bin/ld/ld.h index 1cee37a04b..a43eac8739 100644 --- a/gnu/usr.bin/ld/ld.h +++ b/gnu/usr.bin/ld/ld.h @@ -1,4 +1,6 @@ -/* $Id: ld.h,v 1.8 1993/12/11 11:58:26 jkh Exp $ */ +/* + * $Id: ld.h,v 1.8 1994/01/28 20:56:24 pk Exp $ + */ /*- * This code is derived from software copyrighted by the Free Software * Foundation. @@ -29,6 +31,10 @@ #define alloca __builtin_alloca #endif +#ifdef __FreeBSD__ +#define FreeBSD +#endif + #include "md.h" #include "link.h" @@ -41,23 +47,21 @@ /* Align to machine dependent boundary */ #define MALIGN(x) PALIGN(x,MAX_ALIGNMENT) -/* Size of a page; obtained from the operating system. */ - -int page_size; - /* Name this program was invoked by. */ +char *progname; -char *progname; - /* System dependencies */ /* Define this to specify the default executable format. */ #ifndef DEFAULT_MAGIC +#ifdef FreeBSD #define DEFAULT_MAGIC QMAGIC +extern int netzmagic; +#else +#define DEFAULT_MAGIC ZMAGIC +#endif #endif - -extern netzmagic; /* @@ -181,7 +185,7 @@ extern netzmagic; #ifndef DATA_START #define DATA_START(x) N_DATADDR(x) #endif - + /* If a this type of symbol is encountered, its name is a warning message to print each time the symbol referenced by the next symbol table entry is referenced. @@ -330,6 +334,22 @@ extern netzmagic; #endif /* not __GNU_STAB__ */ + +typedef struct localsymbol { + struct nzlist nzlist; /* n[z]list from file */ + struct glosym *symbol; /* Corresponding global symbol, + if any */ + struct localsymbol *next; /* List of definitions */ + struct file_entry *entry; /* Backpointer to file */ + long gotslot_offset; /* Position in GOT, if any */ + int symbolnum; /* Position in output nlist */ + int flags; +#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 `.' */ +#define LS_GOTSLOTCLAIMED 8 /* This symbol has a GOT entry */ +} localsymbol_t; + /* Symbol table */ /* @@ -340,225 +360,102 @@ extern netzmagic; */ typedef struct glosym { - /* Pointer to next symbol in this symbol's hash bucket. */ - struct glosym *link; - /* Name of this symbol. */ - char *name; - /* Value of this symbol as a global symbol. */ - long value; - /* - * Chain of external 'nlist's in files for this symbol, both defs and - * refs. - */ - struct localsymbol *refs; - /* - * Any warning message that might be associated with this symbol from - * an N_WARNING symbol encountered. - */ - char *warning; - /* - * Nonzero means definitions of this symbol as common have been seen, - * and the value here is the largest size specified by any of them. - */ - int max_common_size; - /* - * For relocatable_output, records the index of this global sym in - * the symbol table to be written, with the first global sym given - * index 0. - */ - int symbolnum; - /* - * For dynamically linked output, records the index in the RRS - * symbol table. - */ - int rrs_symbolnum; - /* - * Nonzero means a definition of this global symbol is known to - * exist. Library members should not be loaded on its account. - */ - char defined; - /* - * Nonzero means a reference to this global symbol has been seen in a - * file that is surely being loaded. A value higher than 1 is the - * n_type code for the symbol's definition. - */ - char referenced; - /* - * A count of the number of undefined references printed for a - * specific symbol. If a symbol is unresolved at the end of - * digest_symbols (and the loading run is supposed to produce - * relocatable output) do_file_warnings keeps track of how many - * unresolved reference error messages have been printed for each - * symbol here. When the number hits MAX_UREFS_PRINTED, messages - * stop. - */ - unsigned char undef_refs; - /* - * 1 means that this symbol has multiple definitions. 2 means that - * it has multiple definitions, and some of them are set elements, - * one of which has been printed out already. - */ - unsigned char multiply_defined; - /* Nonzero means print a message at all refs or defs of this symbol */ - char trace; - - /* - * For symbols of type N_INDR, this points at the real symbol. - */ - struct glosym *alias; - - /* - * Count number of elements in set vector if symbol is of type N_SETV - */ - int setv_count; - - /* Dynamic lib support */ - - /* - * Nonzero means a definition of this global symbol has been found - * in a shared object. These symbols do not go into the symbol - * section of the resulting a.out file. They *do* go into the - * dynamic link information segment. - */ - char so_defined; - - /* Size of symbol as determined by N_SIZE symbols in object files */ - int size; - - /* Auxialiary info to put in the `nz_other' field of the - * RRS symbol table. Used by the run-time linker to resolve - * references to function addresses from within shared objects. - */ - int aux; -#define RRS_FUNC 2 - - /* - * Chain of external 'nlist's in shared objects for this symbol, both - * defs and refs. - */ - struct localsymbol *sorefs; + struct glosym *link; /* Next symbol hash bucket. */ + char *name; /* Name of this symbol. */ + long value; /* Value of this symbol */ + localsymbol_t *refs; /* Chain of local symbols from object + files pertaining to this global + symbol */ + localsymbol_t *sorefs;/* Same for local symbols from shared + object files. */ + + char *warning; /* message, from N_WARNING nlists */ + int common_size; /* Common size */ + int symbolnum; /* Symbol index in output symbol table */ + int rrs_symbolnum; /* Symbol index in RRS symbol table */ + + struct nlist *def_nlist; /* The local symbol that gave this + global symbol its definition */ + + char defined; /* Definition of this symbol */ + char so_defined; /* Definition of this symbol in a shared + object. These go into the RRS symbol table */ + u_char undef_refs; /* Count of number of "undefined" + messages printed for this symbol */ + u_char mult_defs; /* Same for "multiply defined" symbols */ + struct glosym *alias; /* For symbols of type N_INDR, this + points at the real symbol. */ + int setv_count; /* Number of elements in N_SETV symbols */ + int size; /* Size of this symbol (either from N_SIZE + symbols or a from shared object's RRS */ + int aux; /* Auxiliary type information conveyed in + the `n_other' field of nlists */ /* The offset into one of the RRS tables, -1 if not used */ - long jmpslot_offset; - char jmpslot_claimed; + long jmpslot_offset; + long gotslot_offset; - long gotslot_offset; - char gotslot_claimed; + long flags; - char cpyreloc_reserved; - char cpyreloc_claimed; +#define GS_DEFINED 1 /* Symbol has definition (notyetused)*/ +#define GS_REFERENCED 2 /* 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_CPYRELOCRESERVED 0x20 /* entries in GOT and PLT tables */ +#define GS_CPYRELOCCLAIMED 0x40 /* */ - /* The local symbol that gave this global symbol its definition */ - struct nlist *def_nlist; } symbol; /* Number of buckets in symbol hash table */ -#define TABSIZE 1009 +#define SYMTABSIZE 1009 -/* The symbol hash table: a vector of TABSIZE pointers to struct glosym. */ -symbol *symtab[TABSIZE]; +/* The symbol hash table: a vector of SYMTABSIZE pointers to struct glosym. */ +extern symbol *symtab[]; #define FOR_EACH_SYMBOL(i,sp) { \ int i; \ - for (i = 0; i < TABSIZE; i++) { \ + for (i = 0; i < SYMTABSIZE; i++) { \ register symbol *sp; \ for (sp = symtab[i]; sp; sp = sp->link) #define END_EACH_SYMBOL }} -/* Number of symbols in symbol hash table. */ -int num_hash_tab_syms; - -/* Count number of nlist entries for global symbols */ -int global_sym_count; - -/* Count number of N_SIZE nlist entries for output (relocatable_output only) */ -int size_sym_count; - -/* Count the number of nlist entries that are for local symbols. - This count and the three following counts - are incremented as as symbols are entered in the symbol table. */ -int local_sym_count; - -/* Count number of nlist entries that are for local symbols - whose names don't start with L. */ -int non_L_local_sym_count; - -/* Count the number of nlist entries for debugger info. */ -int debugger_sym_count; - -/* Count the number of global symbols referenced and not defined. */ -int undefined_global_sym_count; - -/* Count the number of symbols referenced from shared objects and not defined */ -int undefined_shobj_sym_count; - -/* Count the number of global symbols multiply defined. */ -int multiple_def_count; - -/* Count the number of defined global symbols. - Each symbol is counted only once - regardless of how many different nlist entries refer to it, - since the output file will need only one nlist entry for it. - This count is computed by `digest_symbols'; - it is undefined while symbols are being loaded. */ -int defined_global_sym_count; - -/* Count the number of symbols defined through common declarations. - This count is kept in symdef_library, linear_library, and - enter_global_ref. It is incremented when the defined flag is set - in a symbol because of a common definition, and decremented when - the symbol is defined "for real" (ie. by something besides a common - definition). */ -int common_defined_global_count; - -/* Count the number 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 */ -int special_sym_count; - -/* Count number of aliased symbols */ -int global_alias_count; - -/* Count number of set element type symbols and the number of separate - vectors which these symbols will fit into */ -int set_symbol_count; -int set_vector_count; - -/* Define a linked list of strings which define symbols which should - be treated as set elements even though they aren't. Any symbol - with a prefix matching one of these should be treated as a set - element. - - This is to make up for deficiencies in many assemblers which aren't - willing to pass any stabs through to the loader which they don't - understand. */ -struct string_list_element { - char *str; - struct string_list_element *next; -}; +/* # of global symbols referenced and not defined. */ +extern int undefined_global_sym_count; -struct string_list_element *set_element_prefixes; +/* # of undefined symbols referenced by shared objects */ +extern int undefined_shobj_sym_count; -/* Count the number of warning symbols encountered. */ -int warning_count; +/* # of multiply defined symbols. */ +extern int multiple_def_count; -/* 1 => write load map. */ -int write_map; +/* # of common symbols. */ +extern int common_defined_global_count; -/* 1 => write relocation into output file so can re-input it later. */ -int relocatable_output; +/* # of warning symbols encountered. */ +extern int warning_count; -/* Nonzero means ptr to symbol entry for symbol to use as start addr. - -e sets this. */ -symbol *entry_symbol; +/* + * Define a linked list of strings which define symbols which should be + * treated as set elements even though they aren't. Any symbol with a prefix + * matching one of these should be treated as a set element. + * + * This is to make up for deficiencies in many assemblers which aren't willing + * to pass any stabs through to the loader which they don't understand. + */ +struct string_list_element { + char *str; + struct string_list_element *next; +}; -symbol *edata_symbol; /* the symbol _edata */ -symbol *etext_symbol; /* the symbol _etext */ -symbol *end_symbol; /* the symbol _end */ -symbol *got_symbol; /* the symbol __GLOBAL_OFFSET_TABLE_ */ -symbol *dynamic_symbol; /* the symbol __DYNAMIC */ +extern symbol *entry_symbol; /* the entry symbol, if any */ +extern symbol *edata_symbol; /* the symbol _edata */ +extern symbol *etext_symbol; /* the symbol _etext */ +extern symbol *end_symbol; /* the symbol _end */ +extern symbol *got_symbol; /* the symbol __GLOBAL_OFFSET_TABLE_ */ +extern symbol *dynamic_symbol; /* the symbol __DYNAMIC */ - /* * Each input file, and each library member ("subfile") being loaded, has a * `file_entry' structure for it. @@ -573,160 +470,82 @@ symbol *dynamic_symbol; /* the symbol __DYNAMIC */ */ struct file_entry { - /* Name of this file. */ - char *filename; - + char *filename; /* Name of this file. */ /* * Name to use for the symbol giving address of text start Usually * the same as filename, but for a file spec'd with -l this is the -l * switch itself rather than the filename. */ - char *local_sym_name; - - /* Describe the layout of the contents of the file */ - - /* The file's a.out header. */ - struct exec header; -#if 0 - /* Offset in file of GDB symbol segment, or 0 if there is none. */ - int symseg_offset; -#endif - - /* Describe data from the file loaded into core */ - + char *local_sym_name; + struct exec header; /* The file's a.out header. */ + localsymbol_t *symbols; /* Symbol table of the file. */ + int nsymbols; /* Number of symbols in above array. */ + int string_size; /* Size in bytes of string table. */ + char *strings; /* Pointer to the string table when + in core, NULL otherwise */ + int strings_offset; /* Offset of string table, + (normally N_STROFF() + 4) */ /* - * Symbol table of the file. - * We need access to the global symbol early, ie. before - * symbols are asssigned there final values. gotslot_offset is - * here because GOT entries may be generated for local symbols. + * Next two used only if `relocatable_output' or if needed for + * output of undefined reference line numbers. */ - struct localsymbol { - struct nzlist nzlist; - struct glosym *symbol; - struct localsymbol *next; - long gotslot_offset; - char gotslot_claimed; - char write; - char is_L_symbol; - char rename; - int symbolnum; - } *symbols; - - /* Number of symbols in above array. */ - int nsymbols; - - /* Size in bytes of string table. */ - int string_size; + struct relocation_info *textrel; /* Text relocations */ + int ntextrel; /* # of text relocations */ + struct relocation_info *datarel; /* Data relocations */ + int ndatarel; /* # of data relocations */ /* - * Pointer to the string table. The string table is not kept in core - * all the time, but when it is in core, its address is here. + * Relation of this file's segments to the output file. */ - char *strings; - - /* Offset of string table (normally N_STROFF() + 4) */ - int strings_offset; - - /* Next two used only if `relocatable_output' or if needed for */ - /* output of undefined reference line numbers. */ - - /* Text reloc info saved by `write_text' for `coptxtrel'. */ - struct relocation_info *textrel; - int ntextrel; - - /* Data reloc info saved by `write_data' for `copdatrel'. */ - struct relocation_info *datarel; - int ndatarel; - - /* Relation of this file's segments to the output file */ - - /* Start of this file's text seg in the output file core image. */ - int text_start_address; - - /* Start of this file's data seg in the output file core image. */ - int data_start_address; - - /* Start of this file's bss seg in the output file core image. */ - int bss_start_address; -#if 0 - /* - * Offset in bytes in the output file symbol table of the first local - * symbol for this file. Set by `write_file_symbols'. - */ - int local_syms_offset; -#endif - - /* For library members only */ - - /* For a library, points to chain of entries for the library members. */ - struct file_entry *subfiles; - - /* - * For a library member, offset of the member within the archive. - * Zero for files that are not library members. - */ - int starting_offset; - - /* Size of contents of this file, if library member. */ - int total_size; - - /* For library member, points to the library's own entry. */ - struct file_entry *superfile; - - /* For library member, points to next entry for next member. */ - struct file_entry *chain; - + int text_start_address; /* Start of this file's text segment + in the output file core image. */ + int data_start_address; /* Start of this file's data segment + in the output file core image. */ + int bss_start_address; /* Start of this file's bss segment + in the output file core image. */ + struct file_entry *subfiles; /* For a library, points to chain of + entries for the library members. */ + struct file_entry *superfile; /* For library member, points to the + library's own entry. */ + struct file_entry *chain; /* For library member, points to next + entry for next member. */ + int starting_offset; /* For a library member, offset of the + member within the archive. Zero for + files that are not library members.*/ + int total_size; /* Size of contents of this file, + if library member. */ #ifdef SUN_COMPAT - /* For shared libraries which have a .sa companion */ - struct file_entry *silly_archive; + struct file_entry *silly_archive;/* For shared libraries which have + a .sa companion */ #endif - - /* 1 if file is a library. */ - char library_flag; - - /* 1 if file's header has been read into this structure. */ - char header_read_flag; - - /* 1 means search a set of directories for this file. */ - char search_dirs_flag; - - /* - * 1 means this is base file of incremental load. Do not load this - * file's text or data. Also default text_start to after this file's - * bss. - */ - char just_syms_flag; - - /* 1 means search for dynamic libraries (dependent on -B switch) */ - char search_dynamic_flag; - - /* version numbers of selected shared library */ - int lib_major, lib_minor; - - /* This entry is a shared object */ - char is_dynamic; - - /* 1 if this entry is not a major player anymore */ - char scrapped; + int lib_major, lib_minor; /* Version numbers of a shared object */ + + int flags; +#define E_IS_LIBRARY 1 /* File is a an archive */ +#define E_HEADER_VALID 2 /* File's header has been read */ +#define E_SEARCH_DIRS 4 /* Search directories for file */ +#define E_SEARCH_DYNAMIC 8 /* Search for shared libs allowed */ +#define E_JUST_SYMS 0x10 /* File is used for incremental load */ +#define E_DYNAMIC 0x20 /* File is a shared object */ +#define E_SCRAPPED 0x40 /* Ignore this file */ +#define E_SYMBOLS_USED 0x80 /* Symbols from this entry were used */ }; -typedef struct localsymbol localsymbol_t; +/* + * Section start addresses. + */ +extern int text_size; /* total size of text. */ +extern int text_start; /* start of text */ +extern int text_pad; /* clear space between text and data */ +extern int data_size; /* total size of data. */ +extern int data_start; /* start of data */ +extern int data_pad; /* part of bss segment within data */ -/* Vector of entries for input files specified by arguments. - These are all the input files except for members of specified libraries. */ -struct file_entry *file_table; +extern int bss_size; /* total size of bss. */ +extern int bss_start; /* start of bss */ -/* Length of that vector. */ -int number_of_files; - -/* Current link mode */ -#define DYNAMIC 1 /* Consider shared libraries */ -#define SYMBOLIC 2 /* Force symbolic resolution */ -#define FORCEARCHIVE 4 /* Force inclusion of all members - of archives */ -#define SHAREABLE 8 /* Build a shared object */ -#define SILLYARCHIVE 16 /* Process .sa companions, if any */ -int link_mode; +extern int text_reloc_size; /* total size of text relocation. */ +extern int data_reloc_size; /* total size of data relocation. */ /* * Runtime Relocation Section (RRS). @@ -735,115 +554,57 @@ int link_mode; * static linking), or can just exist of GOT and PLT entries (in case of * statically linked PIC code). */ - -int rrs_section_type; +extern int rrs_section_type; /* What's in the RRS section */ #define RRS_NONE 0 #define RRS_PARTIAL 1 #define RRS_FULL 2 - -int rrs_text_size; -int rrs_data_size; -int rrs_text_start; -int rrs_data_start; +extern int rrs_text_size; /* Size of RRS text additions */ +extern int rrs_text_start; /* Location of above */ +extern int rrs_data_size; /* Size of RRS data additions */ +extern int rrs_data_start; /* Location of above */ /* Version number to put in __DYNAMIC (set by -V) */ -int soversion; - -/* When loading the text and data, we can avoid doing a close - and another open between members of the same library. - - These two variables remember the file that is currently open. - Both are zero if no file is open. - - See `each_file' and `file_close'. */ - -struct file_entry *input_file; -int input_desc; - -/* The name of the file to write; "a.out" by default. */ - -char *output_filename; - -/* Descriptor for writing that file with `mywrite'. */ - -int outdesc; - -/* Header for that file (filled in by `write_header'). */ - -struct exec outheader; - -/* The following are computed by `digest_symbols'. */ - -int text_size; /* total size of text of all input files. */ -int data_size; /* total size of data of all input files. */ -int bss_size; /* total size of bss of all input files. */ -int text_reloc_size; /* total size of text relocation of all input files. */ -int data_reloc_size; /* total size of data relocation of all input files. */ - -/* Relocation offsets set by perform_relocation(). Defined globaly here - because some of the RRS routines need access to them */ -int text_relocation; -int data_relocation; -int bss_relocation; -int pc_relocation; - -/* Specifications of start and length of the area reserved at the end - of the data segment for the set vectors. Computed in 'digest_symbols' */ -int set_sect_start; -int set_sect_size; - -/* Amount of cleared space to leave between the text and data segments. */ -int text_pad; - -/* Amount of bss segment to include as part of the data segment. */ -int data_pad; +extern int soversion; +#ifndef DEFAULT_SOVERSION +#define DEFAULT_SOVERSION LD_VERSION_BSD +#endif +extern int pc_relocation; /* Current PC reloc value */ -/* Record most of the command options. */ +extern int number_of_shobjs; /* # of shared objects linked in */ -/* Address we assume the text section will be loaded at. - We relocate symbols and text and data for this, but we do not - write any padding in the output file for it. */ -int text_start; +/* Current link mode */ +extern int link_mode; +#define DYNAMIC 1 /* Consider shared libraries */ +#define SYMBOLIC 2 /* Force symbolic resolution */ +#define FORCEARCHIVE 4 /* Force inclusion of all members + of archives */ +#define SHAREABLE 8 /* Build a shared object */ +#define SILLYARCHIVE 16 /* Process .sa companions, if any */ -/* Offset of default entry-pc within the text section. */ -int entry_offset; +extern int outdesc; /* Output file descriptor. */ +extern struct exec outheader; /* Output file header. */ +extern int magic; /* Output file magic. */ +extern int oldmagic; +extern int relocatable_output; -/* Address we decide the data section will be loaded at. */ -int data_start; -int bss_start; +/* Size of a page. */ +extern int page_size; -/* Keep a list of any symbols referenced from the command line (so - that error messages for these guys can be generated). This list is - zero terminated. */ -struct glosym **cmdline_references; -int cl_refs_allocated; +extern char **search_dirs; /* Directories to search for libraries. */ +extern int n_search_dirs; /* Length of above. */ -/* - * Actual vector of directories to search; this contains those specified with - * -L plus the standard ones. - */ -char **search_dirs; +extern int write_map; /* write a load map (`-M') */ -/* Length of the vector `search_dirs'. */ -int n_search_dirs; +extern void (*fatal_cleanup_hook)__P((void)); -void load_symbols __P((void)); 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)); -void write_data __P((void)); -void write_rel __P((void)); -void write_syms __P((void)); -void write_symsegs __P((void)); -void mywrite (); +void mywrite __P((void *, int, int, int)); /* In warnings.c: */ void perror_name __P((char *)); @@ -917,10 +678,10 @@ void swap_longs __P((long *, int)); void swap_symbols __P((struct nlist *, int)); void swap_zsymbols __P((struct nzlist *, int)); void swap_ranlib_hdr __P((struct ranlib *, int)); -void swap_link_dynamic __P((struct link_dynamic *)); -void swap_link_dynamic_2 __P((struct link_dynamic_2 *)); -void swap_ld_debug __P((struct ld_debug *)); -void swapin_link_object __P((struct link_object *, int)); -void swapout_link_object __P((struct link_object *, int)); +void swap__dynamic __P((struct link_dynamic *)); +void swap_section_dispatch_table __P((struct section_dispatch_table *)); +void swap_so_debug __P((struct so_debug *)); +void swapin_sod __P((struct sod *, int)); +void swapout_sod __P((struct sod *, int)); void swapout_fshash __P((struct fshash *, int)); #endif diff --git a/gnu/usr.bin/ld/ldconfig/Makefile b/gnu/usr.bin/ld/ldconfig/Makefile index d27f9b7eea..f565cf1fa4 100644 --- a/gnu/usr.bin/ld/ldconfig/Makefile +++ b/gnu/usr.bin/ld/ldconfig/Makefile @@ -1,12 +1,12 @@ -# $Id: Makefile,v 1.4 1993/11/09 20:39:46 paul Exp $ +# $Id: Makefile,v 1.7 1993/12/10 05:10:22 mycroft Exp $ PROG= ldconfig SRCS= ldconfig.c shlib.c etc.c LDDIR?= $(.CURDIR)/.. -LDFLAGS += -static -CFLAGS += -I$(LDDIR) -I$(.CURDIR) -I$(LDDIR)/$(MACHINE) -O -BINDIR= /sbin -MAN8 = ldconfig.8 +CFLAGS+=-I$(LDDIR) -I$(.CURDIR) -I$(LDDIR)/$(MACHINE) +LDSTATIC=-static +BINDIR= /sbin +MAN8= ldconfig.8 .PATH: $(LDDIR) $(LDDIR)/$(MACHINE) diff --git a/gnu/usr.bin/ld/ldconfig/ldconfig.8 b/gnu/usr.bin/ld/ldconfig/ldconfig.8 index 78439e5f66..170b6183eb 100644 --- a/gnu/usr.bin/ld/ldconfig/ldconfig.8 +++ b/gnu/usr.bin/ld/ldconfig/ldconfig.8 @@ -1,6 +1,6 @@ .Dd October 3, 1993 .Dt LDCONFIG 8 -.Os FreeBSD +.Os FreeBSD 1.1 .Sh NAME .Nm ldconfig .Nd configure the shared library cache diff --git a/gnu/usr.bin/ld/ldconfig/ldconfig.c b/gnu/usr.bin/ld/ldconfig/ldconfig.c index 899539de21..fafe176dd3 100644 --- a/gnu/usr.bin/ld/ldconfig/ldconfig.c +++ b/gnu/usr.bin/ld/ldconfig/ldconfig.c @@ -14,7 +14,7 @@ * 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 + * derived from this software without 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 @@ -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: ldconfig.c,v 1.2 1993/11/09 04:19:22 paul Exp $ + * $Id: ldconfig.c,v 1.4 1993/12/02 01:03:16 jkh Exp $ */ #include @@ -72,7 +72,7 @@ struct shlib_list { static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; static void enter __P((char *, char *, char *, int *, int)); -static int dodir __P((char *)); +static int dodir __P((char *, int)); static int build_hints __P((void)); int @@ -114,10 +114,10 @@ char *argv[]; std_search_dirs(NULL); for (i = 0; i < n_search_dirs; i++) - rval |= dodir(search_dirs[i]); + rval |= dodir(search_dirs[i], 1); for (i = optind; i < argc; i++) - rval |= dodir(argv[i]); + rval |= dodir(argv[i], 0); rval |= build_hints(); @@ -125,8 +125,9 @@ char *argv[]; } int -dodir(dir) +dodir(dir, silent) char *dir; +int silent; { DIR *dd; struct dirent *dp; @@ -134,7 +135,8 @@ char *dir; int dewey[MAXDEWEY], ndewey; if ((dd = opendir(dir)) == NULL) { - perror(dir); + if (!silent || errno != ENOENT) + perror(dir); return -1; } @@ -314,16 +316,26 @@ build_hints() return -1; } - mywrite(&hdr, 1, sizeof(struct hints_header), fd); - mywrite(blist, hdr.hh_nbucket, sizeof(struct hints_bucket), fd); - mywrite(strtab, strtab_sz, 1, fd); - + if (write(fd, &hdr, sizeof(struct hints_header)) != + sizeof(struct hints_header)) { + perror(_PATH_LD_HINTS); + return -1; + } + if (write(fd, blist, hdr.hh_nbucket * sizeof(struct hints_bucket)) != + hdr.hh_nbucket * sizeof(struct hints_bucket)) { + perror(_PATH_LD_HINTS); + return -1; + } + if (write(fd, strtab, strtab_sz) != strtab_sz) { + perror(_PATH_LD_HINTS); + return -1; + } if (close(fd) != 0) { perror(_PATH_LD_HINTS); return -1; } - /* Now, install real file */ + /* Install it */ if (unlink(_PATH_LD_HINTS) != 0 && errno != ENOENT) { perror(_PATH_LD_HINTS); return -1; diff --git a/gnu/usr.bin/ld/ldd/ldd.1 b/gnu/usr.bin/ld/ldd/ldd.1 index 0c3b5e42d7..f5a6abadcf 100644 --- a/gnu/usr.bin/ld/ldd/ldd.1 +++ b/gnu/usr.bin/ld/ldd/ldd.1 @@ -1,6 +1,6 @@ .Dd October 22, 1993 .Dt LDD 1 -.Os FreeBSD +.Os FreeBSD 1.1 .Sh NAME .Nm ldd .Nd list dynamic object dependencies diff --git a/gnu/usr.bin/ld/ldd/ldd.c b/gnu/usr.bin/ld/ldd/ldd.c index 65b0bc176e..7fba989b16 100644 --- a/gnu/usr.bin/ld/ldd/ldd.c +++ b/gnu/usr.bin/ld/ldd/ldd.c @@ -14,7 +14,7 @@ * 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 + * derived from this software without 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 @@ -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: ldd.c,v 1.3 1993/10/31 14:54:29 pk Exp $ + * $Id: ldd.c,v 1.2 1993/11/09 04:19:27 paul Exp $ */ #include @@ -107,6 +107,7 @@ char *argv[]; (void)close(fd); printf("%s:\n", *argv); + fflush(stdout); switch (fork()) { case -1: diff --git a/gnu/usr.bin/ld/lib.c b/gnu/usr.bin/ld/lib.c index eaa0f55d96..78d337e731 100644 --- a/gnu/usr.bin/ld/lib.c +++ b/gnu/usr.bin/ld/lib.c @@ -1,5 +1,5 @@ /* - * $Id: lib.c,v 1.7 1993/12/11 11:58:27 jkh Exp $ - library routines + * $Id: lib.c,v 1.8 1993/12/22 23:28:11 jkh Exp $ - library routines */ #include @@ -19,13 +19,11 @@ #include "ld.h" -char **search_dirs; - -/* Length of the vector `search_dirs'. */ -int n_search_dirs; - -struct file_entry *decode_library_subfile(); -void linear_library(), symdef_library(); +static void linear_library __P((int, struct file_entry *)); +static void symdef_library __P((int, struct file_entry *, int)); +static struct file_entry *decode_library_subfile __P((int, + struct file_entry *, + int, int *)); /* * Search the library ENTRY, already open on descriptor DESC. This means @@ -69,7 +67,7 @@ search_library(desc, entry) * We store the length of the member into *LENGTH_LOC. */ -struct file_entry * +static struct file_entry * decode_library_subfile(desc, library_entry, subfile_offset, length_loc) int desc; struct file_entry *library_entry; @@ -113,12 +111,10 @@ decode_library_subfile(desc, library_entry, subfile_offset, length_loc) * 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]))) { + if (strncmp(hdr1.ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && + isdigit(hdr1.ar_name[sizeof(AR_EFMT1) - 1])) { - namelen = atoi(&hdr1.ar_name[3]); + namelen = atoi(&hdr1.ar_name[sizeof(AR_EFMT1) - 1]); name = (char *)xmalloc(namelen + 1); if (read(desc, name, namelen) != namelen) fatal_with_file( @@ -143,10 +139,8 @@ decode_library_subfile(desc, library_entry, subfile_offset, length_loc) subentry->subfiles = 0; 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->flags = 0; subentry->total_size = content_length; (*length_loc) = member_length; @@ -154,7 +148,7 @@ decode_library_subfile(desc, library_entry, subfile_offset, length_loc) return subentry; } -int subfile_wanted_p(); +static int subfile_wanted_p __P((struct file_entry *)); /* * Search a library that has a __.SYMDEF member. DESC is a descriptor on @@ -163,7 +157,7 @@ int subfile_wanted_p(); * length of the __.SYMDEF data. */ -void +static void symdef_library(desc, entry, member_length) int desc; struct file_entry *entry; @@ -172,7 +166,7 @@ symdef_library(desc, entry, member_length) int *symdef_data = (int *) xmalloc(member_length); register struct ranlib *symdef_base; char *sym_name_base; - int number_of_symdefs; + int nsymdefs; int length_of_strings; int not_finished; int bytes_read; @@ -184,24 +178,24 @@ symdef_library(desc, entry, member_length) if (bytes_read != member_length) fatal_with_file("malformatted __.SYMDEF in ", entry); - number_of_symdefs = md_swap_long(*symdef_data) / sizeof(struct ranlib); - if (number_of_symdefs < 0 || - number_of_symdefs * sizeof(struct ranlib) + 2 * sizeof(int) > member_length) + nsymdefs = md_swap_long(*symdef_data) / sizeof(struct ranlib); + if (nsymdefs < 0 || + nsymdefs * sizeof(struct ranlib) + 2 * sizeof(int) > member_length) fatal_with_file("malformatted __.SYMDEF in ", entry); symdef_base = (struct ranlib *) (symdef_data + 1); - length_of_strings = md_swap_long(*(int *) (symdef_base + number_of_symdefs)); + length_of_strings = md_swap_long(*(int *) (symdef_base + nsymdefs)); if (length_of_strings < 0 - || number_of_symdefs * sizeof(struct ranlib) + length_of_strings + || nsymdefs * sizeof(struct ranlib) + length_of_strings + 2 * sizeof(int) > member_length) fatal_with_file("malformatted __.SYMDEF in ", entry); - sym_name_base = sizeof(int) + (char *) (symdef_base + number_of_symdefs); + sym_name_base = sizeof(int) + (char *) (symdef_base + nsymdefs); /* Check all the string indexes for validity. */ - md_swapin_ranlib_hdr(symdef_base, number_of_symdefs); - for (i = 0; i < number_of_symdefs; i++) { + md_swapin_ranlib_hdr(symdef_base, nsymdefs); + for (i = 0; i < nsymdefs; i++) { register int index = symdef_base[i].ran_un.ran_strx; if (index < 0 || index >= length_of_strings || (index && *(sym_name_base + index - 1))) @@ -224,7 +218,7 @@ symdef_library(desc, entry, member_length) * symbols. */ - for (i = 0; (i < number_of_symdefs && + for (i = 0; (i < nsymdefs && ((link_mode & FORCEARCHIVE) || undefined_global_sym_count || common_defined_global_count)); i++) { @@ -256,8 +250,9 @@ symdef_library(desc, entry, member_length) * global common 'utime' linked to a function). */ if (!(link_mode & FORCEARCHIVE) && - (!sp || sp->defined || - (!sp->referenced && !sp->sorefs)) ) + (!sp || sp->defined || + (!(sp->flags & GS_REFERENCED) && + !sp->sorefs))) continue; /* @@ -277,10 +272,11 @@ symdef_library(desc, entry, member_length) entry, offset, &junk); if (subentry == 0) fatal( - "invalid offset for %s in symbol table of %s", + "invalid offset for %s in symbol table of %s", sym_name_base + symdef_base[i].ran_un.ran_strx, entry->filename); + read_entry_symbols(desc, subentry); subentry->strings = (char *) malloc(subentry->string_size); @@ -320,7 +316,7 @@ symdef_library(desc, entry, member_length) * waste time on them. */ - for (j = 0; j < number_of_symdefs; j++) { + for (j = 0; j < nsymdefs; j++) { if (symdef_base[j].ran_off == offset) symdef_base[j].ran_un.ran_strx = -1; } @@ -343,7 +339,7 @@ symdef_library(desc, entry, member_length) * DESC is the descriptor it is open on. */ -void +static void linear_library(desc, entry) int desc; struct file_entry *entry; @@ -354,11 +350,11 @@ linear_library(desc, entry) while ((link_mode & FORCEARCHIVE) || undefined_global_sym_count || common_defined_global_count) { - int member_length; - register struct file_entry *subentry; + int member_length; + register struct file_entry *subentry; - subentry = decode_library_subfile(desc, entry, this_subfile_offset, - &member_length); + subentry = decode_library_subfile(desc, entry, + this_subfile_offset, &member_length); if (!subentry) return; @@ -395,7 +391,7 @@ linear_library(desc, entry) * core, but not entered. Return nonzero if we ought to load this member. */ -int +static int subfile_wanted_p(entry) struct file_entry *entry; { @@ -408,9 +404,9 @@ subfile_wanted_p(entry) for (lsp = entry->symbols; lsp < lspend; lsp++) { register struct nlist *p = &lsp->nzlist.nlist; - register int type = p->n_type; - register char *name = p->n_un.n_strx + entry->strings; - register symbol *sp = getsym_soft(name); + register int type = p->n_type; + register char *name = p->n_un.n_strx + entry->strings; + register symbol *sp = getsym_soft(name); /* * If the symbol has an interesting definition, we could @@ -437,7 +433,7 @@ subfile_wanted_p(entry) dollar_cond = 1; if (!sp) continue; - if (sp->referenced) { + if (sp->flags & SP_REFERENCED) { if (write_map) { print_file_name(entry, stdout); fprintf(stdout, " needed due to $-conditional %s\n", name); @@ -461,7 +457,7 @@ subfile_wanted_p(entry) * common reference (see explanation above in * symdef_library()). */ - if (sp->referenced && !sp->defined) { + if ((sp->flags & GS_REFERENCED) && !sp->defined) { /* * This is a symbol we are looking for. It * is either not yet defined or defined as a @@ -482,11 +478,11 @@ subfile_wanted_p(entry) * If it didn't used to be common, up * the count of common symbols. */ - if (!sp->max_common_size) + if (!sp->common_size) common_defined_global_count++; - if (sp->max_common_size < p->n_value) - sp->max_common_size = p->n_value; + if (sp->common_size < p->n_value) + sp->common_size = p->n_value; if (!sp->defined) undefined_global_sym_count--; sp->defined = type; @@ -498,22 +494,59 @@ subfile_wanted_p(entry) } return 1; } else { + /* + * Check for undefined symbols or commons + * in shared objects. + */ struct localsymbol *lsp; - int defs = 0; + int wascommon = sp->defined && sp->common_size; + int iscommon = type == (N_UNDF|N_EXT) && p->n_value; + + if (wascommon) { + /* + * sp was defined as common by shared object. + */ + if (iscommon && p->n_value < sp->common_size) + sp->common_size = p->n_value; + continue; + } - /* 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; + int type = lsp->nzlist.nlist.n_type; if ( (type & N_EXT) && (type & N_STAB) == 0 && type != (N_UNDF | N_EXT)) - break; /* We need it */ + break; /* We don't need it */ + } + if (lsp != NULL) { + /* There's a real definition */ + if (iscommon) + /* + * But this member wants it to be + * a common; ignore it. + continue; + } + + if (iscommon) { + /* + * New symbol is common, just takes its + * size, but don't load. + */ + sp->common_size = p->n_value; + sp->defined = type; + continue; } - if (lsp != NULL) - continue; /* We don't need it */ + + /* + * THIS STILL MISSES the case where one shared + * object defines a common and the next defines + * more strongly; fix this someday by making + * `struct glosym' and enter_global_ref() more + * symmetric. + */ if (write_map) { print_file_name(entry, stdout); @@ -535,13 +568,13 @@ read_shared_object (desc, entry) struct file_entry *entry; int desc; { - struct link_dynamic dyn; - struct link_dynamic_2 dyn2; - struct nlist *np; - struct nzlist *nzp; - int n, i, has_nz = 0; + struct _dynamic dyn; + struct section_dispatch_table sdt; + struct nlist *np; + struct nzlist *nzp; + int n, i, has_nz = 0; - if (!entry->header_read_flag) + if (!(entry->flags & E_HEADER_VALID)) read_header (desc, entry); /* Read DYNAMIC structure (first in data segment) */ @@ -552,10 +585,10 @@ read_shared_object (desc, entry) fatal_with_file ( "premature eof in data segment of ", entry); } - md_swapin_link_dynamic(&dyn); + md_swapin__dynamic(&dyn); /* Check version */ - switch (dyn.ld_version) { + switch (dyn.d_version) { default: fatal_with_file( "unsupported _DYNAMIC version ", entry); break; @@ -566,26 +599,29 @@ read_shared_object (desc, entry) break; } - /* Read link_dynamic_2 struct (from data segment) */ + /* Read Section Dispatch Table (from data segment) */ lseek (desc, - text_offset(entry) + dyn.ld_un.ld_2, + text_offset(entry) + (long)dyn.d_un.d_sdt - + (DATA_START(entry->header) - N_DATOFF(entry->header)), L_SET); - if (read(desc, &dyn2, sizeof dyn2) != sizeof dyn2) { + if (read(desc, &sdt, sizeof sdt) != sizeof sdt) { fatal_with_file( "premature eof in data segment of ", entry); } - md_swapin_link_dynamic_2(&dyn2); + md_swapin_section_dispatch_table(&sdt); /* Read symbols (text segment) */ - n = dyn2.ld_strings - dyn2.ld_symbols; + n = sdt.sdt_strings - sdt.sdt_nzlist; entry->nsymbols = n / (has_nz ? sizeof(struct nzlist) : sizeof(struct nlist)); nzp = (struct nzlist *)(np = (struct nlist *) alloca (n)); entry->symbols = (struct localsymbol *) xmalloc(entry->nsymbols * sizeof(struct localsymbol)); - lseek(desc, text_offset (entry) + dyn2.ld_symbols, L_SET); + lseek(desc, text_offset(entry) + (long)sdt.sdt_nzlist - + (TEXT_START(entry->header) - N_TXTOFF(entry->header)), + L_SET); if (read(desc, (char *)nzp, n) != n) { fatal_with_file( - "premature eof while reading dyn syms ", entry); + "premature eof while reading object symbols ", entry); } if (has_nz) md_swapin_zsymbols(nzp, entry->nsymbols); @@ -602,21 +638,21 @@ read_shared_object (desc, entry) } entry->symbols[i].symbol = NULL; entry->symbols[i].next = NULL; + entry->symbols[i].entry = entry; entry->symbols[i].gotslot_offset = -1; - entry->symbols[i].gotslot_claimed = 0; - entry->symbols[i].write = 0; - entry->symbols[i].is_L_symbol = 0; - entry->symbols[i].rename = 0; + entry->symbols[i].flags = 0; } /* Read strings (text segment) */ - n = entry->string_size = dyn2.ld_str_sz; + n = entry->string_size = sdt.sdt_str_sz; entry->strings = (char *) alloca(n); - entry->strings_offset = text_offset (entry) + dyn2.ld_strings; - lseek(desc, entry->strings_offset, L_SET); + entry->strings_offset = text_offset(entry) + sdt.sdt_strings; + lseek(desc, entry->strings_offset - + (TEXT_START(entry->header) - N_TXTOFF(entry->header)), + L_SET); if (read(desc, entry->strings, n) != n) { fatal_with_file( - "premature eof while reading dyn strings ", entry); + "premature eof while reading object strings ", entry); } enter_file_symbols (entry); entry->strings = 0; @@ -624,39 +660,43 @@ read_shared_object (desc, entry) /* * Load any subsidiary shared objects. */ - if (dyn2.ld_need) { - struct link_object lobj; + if (sdt.sdt_sods) { + struct sod sod; off_t offset; - struct file_entry *subentry, *prev = NULL; + struct file_entry *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; + offset = (off_t)sdt.sdt_sods; while (1) { + struct file_entry *subentry; char *libname, name[MAXPATHLEN]; /*XXX*/ - lseek(desc, offset, L_SET); - if (read(desc, &lobj, sizeof(lobj)) != sizeof(lobj)) { + subentry = (struct file_entry *) + xmalloc(sizeof(struct file_entry)); + bzero(subentry, sizeof(struct file_entry)); + subentry->superfile = entry; + + lseek(desc, offset - + (TEXT_START(entry->header) - N_TXTOFF(entry->header)), + L_SET); + if (read(desc, &sod, sizeof(sod)) != sizeof(sod)) { fatal_with_file( - "premature eof while reading link objects ", + "premature eof while reading sod ", entry); } - md_swapin_link_object(&lobj, 1); - (void)lseek(desc, (off_t)lobj.lo_name, L_SET); + md_swapin_sod(&sod, 1); + (void)lseek(desc, (off_t)sod.sod_name - + (TEXT_START(entry->header) - N_TXTOFF(entry->header)), + 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; + if (sod.sod_library) { + int sod_major = sod.sod_major; + int sod_minor = sod.sod_minor; libname = findshlib(name, - &lo_major, &lo_minor, 0); + &sod_major, &sod_minor, 0); if (libname == NULL) fatal("no shared -l%s.%d.%d available", - name, lobj.lo_major, lobj.lo_minor); + name, sod.sod_major, sod.sod_minor); subentry->filename = libname; subentry->local_sym_name = concat("-l", name, ""); } else { @@ -671,7 +711,7 @@ read_shared_object (desc, entry) entry->subfiles = subentry; prev = subentry; desc = file_open(entry); - if ((offset = (off_t)lobj.lo_next) == 0) + if ((offset = (off_t)sod.sod_next) == 0) break; } } @@ -719,7 +759,7 @@ read_shared_object (desc, entry) subentry->superfile = entry; subentry->filename = sa_name; subentry->local_sym_name = sa_name; - subentry->library_flag = 1; + subentry->flags |= E_IS_LIBRARY; search_library(file_open(subentry), subentry); out: ; @@ -740,7 +780,7 @@ struct file_entry *p; int major = -1, minor = -1; char *cp, *fname = NULL; - if (p->search_dynamic_flag == 0) + if (!(p->flags & E_SEARCH_DYNAMIC)) goto dot_a; fname = findshlib(p->filename, &major, &minor, 1); @@ -749,13 +789,13 @@ struct file_entry *p; p->filename = fname; p->lib_major = major; p->lib_minor = minor; - p->search_dirs_flag = 0; + p->flags &= ~E_SEARCH_DIRS; return desc; } free (fname); dot_a: - p->search_dynamic_flag = 0; + p->flags &= ~E_SEARCH_DYNAMIC; if (cp = strrchr(p->filename, '/')) { *cp++ = '\0'; fname = concat(concat(p->filename, "/lib", cp), ".a", ""); @@ -769,7 +809,7 @@ dot_a: desc = open (string, O_RDONLY, 0); if (desc > 0) { p->filename = string; - p->search_dirs_flag = 0; + p->flags &= ~E_SEARCH_DIRS; break; } free (string); diff --git a/gnu/usr.bin/ld/rrs.c b/gnu/usr.bin/ld/rrs.c index 6de17b9ba4..6c042d956c 100644 --- a/gnu/usr.bin/ld/rrs.c +++ b/gnu/usr.bin/ld/rrs.c @@ -14,7 +14,7 @@ * 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 + * derived from this software without 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 @@ -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.9 1993/12/04 00:53:00 jkh Exp $ + * $Id: rrs.c,v 1.10 1993/12/11 11:58:28 jkh Exp $ */ #include @@ -48,9 +48,9 @@ #include "ld.h" -static struct link_dynamic rrs_dyn; /* defined in link.h */ -static struct ld_debug rrs_ld_debug; /* defined in link.h */ -static struct link_dynamic_2 rrs_dyn2; /* defined in link.h */ +static struct _dynamic rrs_dyn; /* defined in link.h */ +static struct so_debug rrs_so_debug; /* defined in link.h */ +static struct section_dispatch_table rrs_sdt; /* defined in link.h */ static got_t *rrs_got; static jmpslot_t *rrs_plt; /* defined in md.h */ static struct relocation_info *rrs_reloc; @@ -73,7 +73,7 @@ static int current_jmpslot_offset; static int current_got_offset; static int current_reloc_offset; static int current_hash_index; -static int number_of_shobjs; +int number_of_shobjs; struct shobj { struct shobj *next; @@ -82,29 +82,29 @@ struct shobj { /* RRS text segment: - +-------------------+ <-- ld_rel (rrs_text_start) + +-------------------+ <-- sdt_rel (rrs_text_start) | | | relocation | | | - +-------------------+ <-- .ld_hash + +-------------------+ <-- .sdt_hash | | | hash buckets | | | - +-------------------+ <-- .ld_stab + +-------------------+ <-- .sdt_nzlist | | | symbols | | | - +-------------------+ <-- .ld_strings + +-------------------+ <-- .sdt_strings | | | strings | | | - +-------------------+ <-- .ld_need + +-------------------+ <-- .sdt_sods | | | shobjs | | | +-------------------+ | | - | shobjs strings | <-- .lo_name + | shobjs strings | <-- .sod_name | | +-------------------+ @@ -113,21 +113,21 @@ RRS data segment: +-------------------+ <-- __DYNAMIC (rrs_data_start) | | - | link_dymamic | + | _dymamic | | | - +-------------------+ <-- __DYNAMIC.ldd + +-------------------+ <-- __DYNAMIC.d_debug | | - | ld_debug | + | so_debug | | | - +-------------------+ <-- __DYNAMIC.ld_un.ld_2 + +-------------------+ <-- __DYNAMIC.d_un.d_sdt | | - | link_dymamic_2 | + | sdt | | | - +-------------------+ <-- _GLOBAL_OFFSET_TABLE_ (ld_got) + +-------------------+ <-- _GLOBAL_OFFSET_TABLE_ (sdt_got) | | | _GOT_ | | | - +-------------------+ <-- ld_plt + +-------------------+ <-- sdt_plt | | | PLT | | | @@ -280,12 +280,12 @@ alloc_rrs_cpy_reloc(entry, sp) struct file_entry *entry; symbol *sp; { - if (sp->cpyreloc_reserved) + if (sp->flags & GS_CPYRELOCRESERVED) return; #ifdef DEBUG printf("alloc_rrs_copy: %s in %s\n", sp->name, get_file_name(entry)); #endif - sp->cpyreloc_reserved = 1; + sp->flags |= GS_CPYRELOCRESERVED; reserved_rrs_relocs++; } @@ -318,11 +318,11 @@ long *relocation; { struct relocation_info *r = rrs_next_reloc(); -#ifdef DEBUG if (rp->r_address < text_start + text_size) error("%s: RRS text relocation at %#x for \"%s\"", get_file_name(entry), rp->r_address, sp->name); +#ifdef DEBUG printf("claim_rrs_reloc: %s in %s\n", sp->name, get_file_name(entry)); #endif r->r_address = rp->r_address; @@ -354,8 +354,8 @@ long addend; { struct relocation_info *r; - if (sp->jmpslot_claimed) - return rrs_dyn2.ld_plt + sp->jmpslot_offset; + if (sp->flags & GS_JMPSLOTCLAIMED) + return rrs_sdt.sdt_plt + sp->jmpslot_offset; #ifdef DEBUG printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x (textreloc %#x)\n", @@ -375,30 +375,30 @@ printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x (textreloc %#x)\n", sp->name, get_file_name(entry)); md_fix_jmpslot( rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t), - rrs_dyn2.ld_plt + sp->jmpslot_offset, + rrs_sdt.sdt_plt + sp->jmpslot_offset, sp->value); if (!JMPSLOT_NEEDS_RELOC) { - return rrs_dyn2.ld_plt + sp->jmpslot_offset; + return rrs_sdt.sdt_plt + sp->jmpslot_offset; } } else { - md_make_jmpslot( rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t), + md_make_jmpslot(rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t), sp->jmpslot_offset, claimed_rrs_relocs); } if (rrs_section_type == RRS_PARTIAL) /* PLT is self-contained */ - return rrs_dyn2.ld_plt + sp->jmpslot_offset; + return rrs_sdt.sdt_plt + sp->jmpslot_offset; /* * Install a run-time relocation for this PLT entry. */ r = rrs_next_reloc(); - sp->jmpslot_claimed = 1; + sp->flags |= GS_JMPSLOTCLAIMED; RELOC_SYMBOL(r) = sp->rrs_symbolnum; - r->r_address = (long)rrs_dyn2.ld_plt + sp->jmpslot_offset; + r->r_address = (long)rrs_sdt.sdt_plt + sp->jmpslot_offset; if (link_mode & SYMBOLIC) { RELOC_EXTERN_P(r) = 0; @@ -408,7 +408,7 @@ printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x (textreloc %#x)\n", md_make_jmpreloc(rp, r, 0); } - return rrs_dyn2.ld_plt + sp->jmpslot_offset; + return rrs_sdt.sdt_plt + sp->jmpslot_offset; } /* @@ -443,7 +443,7 @@ printf("claim_rrs_gotslot: %s(%d) slot offset %#x, addend %#x\n", "internal error: %s: claim_rrs_gotslot: %s: gotslot_offset == -1\n", get_file_name(entry), sp->name); - if (sp->gotslot_claimed) + if (sp->flags & GS_GOTSLOTCLAIMED) /* This symbol already passed here before. */ return sp->gotslot_offset; @@ -497,8 +497,8 @@ printf("claim_rrs_gotslot: %s(%d) slot offset %#x, addend %#x\n", * as no symbol need be looked up at run-time. */ r = rrs_next_reloc(); - sp->gotslot_claimed = 1; - r->r_address = rrs_dyn2.ld_got + sp->gotslot_offset; + sp->flags |= GS_GOTSLOTCLAIMED; + r->r_address = rrs_sdt.sdt_got + sp->gotslot_offset; RELOC_SYMBOL(r) = sp->rrs_symbolnum; RELOC_EXTERN_P(r) = !(reloc_type == RELTYPE_RELATIVE); md_make_gotreloc(rp, r, reloc_type); @@ -524,7 +524,7 @@ long addend; addend += lsp->nzlist.nz_value; if (!RELOC_STATICS_THROUGH_GOT_P(r)) - return addend - rrs_dyn2.ld_got; + return addend - rrs_sdt.sdt_got; #ifdef DEBUG printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n", @@ -536,7 +536,7 @@ printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n", "internal error: %s: claim_rrs_internal_gotslot at %#x: slot_offset == -1\n", get_file_name(entry), RELOC_ADDRESS(rp)); - if (lsp->gotslot_claimed) + if (lsp->flags & LS_GOTSLOTCLAIMED) /* Already done */ return lsp->gotslot_offset; @@ -549,8 +549,8 @@ 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->gotslot_claimed = 1; - r->r_address = rrs_dyn2.ld_got + lsp->gotslot_offset; + lsp->flags |= LS_GOTSLOTCLAIMED; + r->r_address = rrs_sdt.sdt_got + lsp->gotslot_offset; RELOC_EXTERN_P(r) = 0; md_make_gotreloc(rp, r, RELTYPE_RELATIVE); return lsp->gotslot_offset; @@ -564,10 +564,10 @@ symbol *sp; { struct relocation_info *r; - if (sp->cpyreloc_claimed) + if (sp->flags & GS_CPYRELOCCLAIMED) return; - if (!sp->cpyreloc_reserved) + if (!(sp->flags & GS_CPYRELOCRESERVED)) fatal("internal error: %s: claim_cpy_reloc: %s: no reservation\n", get_file_name(entry), sp->name); @@ -577,7 +577,7 @@ printf("claim_rrs_copy: %s: %s -> %x\n", #endif r = rrs_next_reloc(); - sp->cpyreloc_claimed = 1; + sp->flags |= GS_CPYRELOCCLAIMED; r->r_address = rp->r_address; RELOC_SYMBOL(r) = sp->rrs_symbolnum; RELOC_EXTERN_P(r) = RELOC_EXTERN_P(rp); @@ -617,7 +617,7 @@ int index; for (; *cp; cp++) hashval = (hashval << 1) + *cp; - hashval = (hashval & 0x7fffffff) % rrs_dyn2.ld_buckets; + hashval = (hashval & 0x7fffffff) % rrs_sdt.sdt_buckets; /* Get to the bucket */ hp = rrs_hashtab + hashval; @@ -651,11 +651,27 @@ void consider_rrs_section_lengths() { int n; - struct shobj *shp; + struct shobj *shp, **shpp; int symbolsize; - /* First, determine what of the RRS we want */ +#ifdef notyet +/* We run into trouble with this as long as shared object symbols + are not checked for definitions */ + /* + * First, determine the real number of shared objects we need. + */ + for (shpp = &rrs_shobjs; *shpp; shpp = &(*shpp)->next) { + while (*shpp && !((*shpp)->entry->flags & E_SYMBOLS_USED)) { + if (--number_of_shobjs < 0) + fatal("internal error: number_of_shobjs < 0"); + *shpp = (*shpp)->next; + } + if (*shpp == NULL) + break; + } +#endif + /* First, determine what of the RRS we want */ if (relocatable_output) rrs_section_type = RRS_NONE; else if (link_mode & SHAREABLE) @@ -685,13 +701,14 @@ consider_rrs_section_lengths() * from crt0), as this is the method used to determine whether the * run-time linker must be called. */ - if (!(link_mode & SHAREABLE) && !dynamic_symbol->referenced) + if (!(link_mode & SHAREABLE) && + !(dynamic_symbol->flags & GS_REFERENCED)) fatal("No reference to __DYNAMIC"); - dynamic_symbol->referenced = 1; + dynamic_symbol->flags |= GS_REFERENCED; if (number_of_gotslots > 1) - got_symbol->referenced = 1; + got_symbol->flags |= GS_REFERENCED; /* Next, allocate relocs, got and plt */ @@ -722,7 +739,7 @@ consider_rrs_section_lengths() */ dynamic_symbol->rrs_symbolnum = number_of_rrs_symbols++; FOR_EACH_SYMBOL(i ,sp) { - if (sp->referenced) { + if (sp->flags & GS_REFERENCED) { rrs_strtab_size += 1 + strlen(sp->name); if (sp != dynamic_symbol) sp->rrs_symbolnum = number_of_rrs_symbols++; @@ -743,16 +760,16 @@ consider_rrs_section_lengths() * Now that we know how many RRS symbols there are going to be, * allocate and initialize the RRS symbol hash table. */ - rrs_dyn2.ld_buckets = number_of_rrs_symbols/4; - if (rrs_dyn2.ld_buckets < 4) - rrs_dyn2.ld_buckets = 4; + rrs_sdt.sdt_buckets = number_of_rrs_symbols/4; + if (rrs_sdt.sdt_buckets < 4) + rrs_sdt.sdt_buckets = 4; - number_of_rrs_hash_entries = rrs_dyn2.ld_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_dyn2.ld_buckets; n++) + for (n = 0; n < rrs_sdt.sdt_buckets; n++) rrs_hashtab[n].rh_symbolnum = -1; - current_hash_index = rrs_dyn2.ld_buckets; + current_hash_index = rrs_sdt.sdt_buckets; /* * Get symbols into hash table now, so we can fine tune the size @@ -760,7 +777,7 @@ consider_rrs_section_lengths() * to the number of hash link slots actually used. */ FOR_EACH_SYMBOL(i ,sp) { - if (sp->referenced) + if (sp->flags & GS_REFERENCED) rrs_insert_hash(sp->name, sp->rrs_symbolnum); } END_EACH_SYMBOL; number_of_rrs_hash_entries = current_hash_index; @@ -768,9 +785,9 @@ consider_rrs_section_lengths() /* * Calculate RRS section sizes. */ - rrs_data_size = sizeof(struct link_dynamic); - rrs_data_size += sizeof(struct ld_debug); - rrs_data_size += sizeof(struct link_dynamic_2); + rrs_data_size = sizeof(struct _dynamic); + rrs_data_size += sizeof(struct so_debug); + rrs_data_size += sizeof(struct section_dispatch_table); rrs_data_size += number_of_gotslots * sizeof(got_t); rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t); rrs_data_size = MALIGN(rrs_data_size); @@ -790,7 +807,7 @@ consider_rrs_section_lengths() if (*name == '-' && *(name+1) == 'l') name += 2; - rrs_text_size += sizeof(struct link_object); + rrs_text_size += sizeof(struct sod); rrs_text_size += 1 + strlen(name); } @@ -808,8 +825,8 @@ relocate_rrs_addresses() return; if (rrs_section_type == RRS_PARTIAL) { - got_symbol->value = rrs_dyn2.ld_got = rrs_data_start; - rrs_dyn2.ld_plt = rrs_dyn2.ld_got + + got_symbol->value = rrs_sdt.sdt_got = rrs_data_start; + rrs_sdt.sdt_plt = rrs_sdt.sdt_got + number_of_gotslots * sizeof(got_t); return; } @@ -817,48 +834,48 @@ relocate_rrs_addresses() /* * RRS data relocations. */ - rrs_dyn.ld_version = soversion; - rrs_dyn.ldd = (struct ld_debug *) - (rrs_data_start + sizeof(struct link_dynamic)); - rrs_dyn.ld_un.ld_2 = (struct link_dynamic_2 *) - ((long)rrs_dyn.ldd + sizeof(struct ld_debug)); + rrs_dyn.d_version = soversion; + rrs_dyn.d_debug = (struct so_debug *) + (rrs_data_start + sizeof(struct _dynamic)); + rrs_dyn.d_un.d_sdt = (struct section_dispatch_table *) + ((long)rrs_dyn.d_debug + sizeof(struct so_debug)); - rrs_dyn2.ld_got = (long)rrs_dyn.ld_un.ld_2 + - sizeof(struct link_dynamic_2); - rrs_dyn2.ld_plt = rrs_dyn2.ld_got + number_of_gotslots*sizeof(got_t); + rrs_sdt.sdt_got = (long)rrs_dyn.d_un.d_sdt + + sizeof(struct section_dispatch_table); + rrs_sdt.sdt_plt = rrs_sdt.sdt_got + number_of_gotslots*sizeof(got_t); /* * RRS text relocations. */ - rrs_dyn2.ld_rel = rrs_text_start; + rrs_sdt.sdt_rel = rrs_text_start; /* * Sun BUG compatibility alert. * Main program's RRS text values are relative to TXTADDR? WHY?? */ #ifdef SUN_COMPAT if (soversion == LD_VERSION_SUN && !(link_mode & SHAREABLE)) - rrs_dyn2.ld_rel -= N_TXTADDR(outheader); + rrs_sdt.sdt_rel -= N_TXTADDR(outheader); #endif - rrs_dyn2.ld_hash = rrs_dyn2.ld_rel + + rrs_sdt.sdt_hash = rrs_sdt.sdt_rel + reserved_rrs_relocs * sizeof(struct relocation_info); - rrs_dyn2.ld_symbols = rrs_dyn2.ld_hash + + rrs_sdt.sdt_nzlist = rrs_sdt.sdt_hash + number_of_rrs_hash_entries * sizeof(struct rrs_hash); - rrs_dyn2.ld_strings = rrs_dyn2.ld_symbols + + rrs_sdt.sdt_strings = rrs_sdt.sdt_nzlist + number_of_rrs_symbols * rrs_symbol_size; - rrs_dyn2.ld_str_sz = rrs_strtab_size; - rrs_dyn2.ld_text_sz = text_size; - rrs_dyn2.ld_plt_sz = number_of_jmpslots * sizeof(jmpslot_t); + rrs_sdt.sdt_str_sz = rrs_strtab_size; + rrs_sdt.sdt_text_sz = text_size; + rrs_sdt.sdt_plt_sz = number_of_jmpslots * sizeof(jmpslot_t); - rrs_dyn2.ld_need = rrs_shobjs ? rrs_dyn2.ld_strings+rrs_strtab_size : 0; - rrs_dyn2.ld_stab_hash = 0; - rrs_dyn2.ld_rules = 0; + rrs_sdt.sdt_sods = rrs_shobjs ? rrs_sdt.sdt_strings+rrs_strtab_size : 0; + rrs_sdt.sdt_filler1 = 0; + rrs_sdt.sdt_filler2 = 0; /* * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC * &__DYNAMIC is also in the first GOT entry. */ - got_symbol->value = rrs_dyn2.ld_got; + got_symbol->value = rrs_sdt.sdt_got; *rrs_got = dynamic_symbol->value = rrs_data_start; @@ -896,14 +913,14 @@ write_rrs_data() return; } - md_swapout_link_dynamic(&rrs_dyn); - mywrite(&rrs_dyn, 1, sizeof(struct link_dynamic), outdesc); + md_swapout__dynamic(&rrs_dyn); + mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outdesc); - md_swapout_ld_debug(&rrs_ld_debug); - mywrite(&rrs_ld_debug, 1, sizeof(struct ld_debug), outdesc); + md_swapout_so_debug(&rrs_so_debug); + mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outdesc); - md_swapout_link_dynamic_2(&rrs_dyn2); - mywrite(&rrs_dyn2, 1, sizeof(struct link_dynamic_2), outdesc); + md_swapout_section_dispatch_table(&rrs_sdt); + mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outdesc); md_swapout_got(rrs_got, number_of_gotslots); mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outdesc); @@ -921,7 +938,7 @@ write_rrs_text() struct nzlist *nlp; int offset = 0; struct shobj *shp; - struct link_object *lo; + struct sod *sodp; if (rrs_section_type == RRS_PARTIAL) return; @@ -967,7 +984,7 @@ write_rrs_text() */ FOR_EACH_SYMBOL(i, sp) { - if (!sp->referenced || sp == dynamic_symbol) + if (!(sp->flags & GS_REFERENCED) || sp == dynamic_symbol) continue; if ((long)nlp - (long)rrs_symbols >= @@ -993,6 +1010,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); } else if (sp->defined == N_SIZE) { /* * Make sure this symbol isn't going @@ -1003,47 +1021,36 @@ write_rrs_text() } else { nlp->nz_type = sp->defined; nlp->nz_value = sp->value; + nlp->nz_other = N_OTHER(0, sp->aux); } if (LD_VERSION_NZLIST_P(soversion)) nlp->nz_size = sp->size; - } else if (sp->max_common_size) { + } else if (sp->common_size) { /* * a common definition */ nlp->nz_type = N_UNDF | N_EXT; - nlp->nz_value = sp->max_common_size; + nlp->nz_value = sp->common_size; } 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. + */ + if (sp->aux != AUX_FUNC) + fatal("%s: non-function jmpslot", + sp->name); + nlp->nz_other = N_OTHER(0, sp->aux); + nlp->nz_value = + rrs_sdt.sdt_plt + sp->jmpslot_offset; + } } else fatal( "internal error: %s defined in mysterious way", sp->name); - /* Handle auxialiary type qualifiers */ - switch (sp->aux) { - case 0: - break; - case RRS_FUNC: - if (sp->so_defined != (N_TEXT+N_EXT)) - fatal("internal error: %s: other but not text", - sp->name); - if (sp->jmpslot_offset == -1) - fatal( - "internal error: %s has no jmpslot but other", - sp->name); - nlp->nz_other = sp->aux; - nlp->nz_value = - rrs_dyn2.ld_plt + sp->jmpslot_offset; - break; - default: - fatal( - "internal error: %s: unsupported other value: %x", - sp->name, sp->aux); - break; - } - /* Set symbol's name */ nlp->nz_strx = offset; strcpy(rrs_strtab + offset, sp->name); @@ -1089,9 +1096,8 @@ write_rrs_text() /* * Write the names of the shared objects needed at run-time */ - pos = rrs_dyn2.ld_need + number_of_shobjs * sizeof(struct link_object); - lo = (struct link_object *)alloca( - number_of_shobjs * sizeof(struct link_object)); + pos = rrs_sdt.sdt_sods + number_of_shobjs * sizeof(struct sod); + sodp = (struct sod *)alloca( number_of_shobjs * sizeof(struct sod)); for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) { char *name = shp->entry->local_sym_name; @@ -1100,27 +1106,27 @@ write_rrs_text() fatal("internal error: # of link objects exceeds %d", number_of_shobjs); - lo[i].lo_name = pos; - lo[i].lo_major = shp->entry->lib_major; - lo[i].lo_minor = shp->entry->lib_minor; + sodp[i].sod_name = pos; + sodp[i].sod_major = shp->entry->lib_major; + sodp[i].sod_minor = shp->entry->lib_minor; if (*name == '-' && *(name+1) == 'l') { name += 2; - lo[i].lo_library = 1; + sodp[i].sod_library = 1; } else - lo[i].lo_library = 0; + sodp[i].sod_library = 0; pos += 1 + strlen(name); - lo[i].lo_next = (i == number_of_shobjs - 1) ? 0 : - (rrs_dyn2.ld_need + (i+1)*sizeof(struct link_object)); + sodp[i].sod_next = (i == number_of_shobjs - 1) ? 0 : + (rrs_sdt.sdt_sods + (i+1)*sizeof(struct sod)); } 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); + md_swapout_sod(sodp, number_of_shobjs); + mywrite(sodp, number_of_shobjs, sizeof(struct sod), outdesc); for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) { char *name = shp->entry->local_sym_name; diff --git a/gnu/usr.bin/ld/rtld/Makefile b/gnu/usr.bin/ld/rtld/Makefile index 1a76c51aa7..0fbf2b2006 100644 --- a/gnu/usr.bin/ld/rtld/Makefile +++ b/gnu/usr.bin/ld/rtld/Makefile @@ -1,25 +1,25 @@ -# $Id: Makefile,v 1.7 1993/12/11 21:05:59 jkh Exp $ +# $Id: Makefile,v 1.8 1994/01/28 21:01:20 pk Exp $ PROG= ld.so -SRCS= mdprologue.S sbrk.c rtld.c shlib.c etc.c md.c +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) -O $(PICFLAG) -DRTLD -LDFLAGS = -Bshareable -Bsymbolic -assert nosymbolic -Z -LIBS = -lc_pic -lgcc_pic +CFLAGS+=-I$(LDDIR) -I$(.CURDIR) -I$(LDDIR)/$(MACHINE) $(PICFLAG) -DRTLD +LDFLAGS+=-Bshareable -Bsymbolic -assert nosymbolic +ASFLAGS+=-k +LDADD+= -lc_pic BINDIR= /usr/libexec -ASFLAGS = -k - -.PATH: $(LDDIR) $(LDDIR)/$(MACHINE) .SUFFIXES: .S +.PATH: $(LDDIR) $(LDDIR)/$(MACHINE) + $(PROG): - $(LD) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIBS) $(LDADD) + $(LD) -o $(PROG) $(LDFLAGS) $(OBJS) $(LDADD) .S.o: - $(CPP) $(.IMPSRC) | $(AS) $(ASFLAGS) -o $(.TARGET) - + ${CPP} ${.IMPSRC} | ${AS} ${ASFLAGS} -o ${.TARGET} - .include diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c index e02fef6ea2..72ab49e732 100644 --- a/gnu/usr.bin/ld/rtld/rtld.c +++ b/gnu/usr.bin/ld/rtld/rtld.c @@ -14,7 +14,7 @@ * 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 + * derived from this software without 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 @@ -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.13 1994/01/12 23:16:19 jkh Exp $ + * $Id: rtld.c,v 1.14 1994/01/14 11:47:00 jkh Exp $ */ #include @@ -39,6 +39,7 @@ #include #include #include +#include #include #ifndef BSD #define MAP_COPY MAP_PRIVATE @@ -62,92 +63,115 @@ #endif /* - * Loader private data, hung off link_map->lm_lpd + * Loader private data, hung off ->som_spd */ -struct lm_private { - int lpd_version; - struct link_map *lpd_parent; +struct somap_private { + int spd_version; + struct so_map *spd_parent; + int spd_refcount; + int spd_flags; +#define RTLD_MAIN 1 +#define RTLD_RTLD 2 +#define RTLD_DL 4 + #ifdef SUN_COMPAT - long lpd_offset; /* Correction for Sun main programs */ + long spd_offset; /* Correction for Sun main programs */ #endif }; +#define LM_PRIVATE(smp) ((struct somap_private *)(smp)->som_spd) + #ifdef SUN_COMPAT -#define LM_OFFSET(lmp) (((struct lm_private *)((lmp)->lm_lpd))->lpd_offset) +#define LM_OFFSET(smp) (LM_PRIVATE(smp)->spd_offset) #else -#define LM_OFFSET(lmp) (0) +#define LM_OFFSET(smp) (0) #endif -/* Base address for link_dynamic_2 entries */ -#define LM_LDBASE(lmp) (lmp->lm_addr + LM_OFFSET(lmp)) +/* Base address for section_dispatch_table entries */ +#define LM_LDBASE(smp) (smp->som_addr + LM_OFFSET(smp)) /* Start of text segment */ -#define LM_TXTADDR(lmp) (lmp->lm_addr == (caddr_t)0 ? PAGSIZ : 0) +#define LM_TXTADDR(smp) (smp->som_addr == (caddr_t)0 ? PAGSIZ : 0) /* Start of run-time relocation_info */ -#define LM_REL(lmp) ((struct relocation_info *) \ - (lmp->lm_addr + LM_OFFSET(lmp) + LD_REL((lmp)->lm_ld))) +#define LM_REL(smp) ((struct relocation_info *) \ + (smp->som_addr + LM_OFFSET(smp) + LD_REL((smp)->som_dynamic))) /* Start of symbols */ -#define LM_SYMBOL(lmp, i) ((struct nzlist *) \ - (lmp->lm_addr + LM_OFFSET(lmp) + LD_SYMBOL((lmp)->lm_ld) + \ - i * (LD_VERSION_NZLIST_P(lmp->lm_ld->ld_version) ? \ - sizeof(struct nzlist) : sizeof(struct nlist)))) +#define LM_SYMBOL(smp, i) ((struct nzlist *) \ + (smp->som_addr + LM_OFFSET(smp) + LD_SYMBOL((smp)->som_dynamic) + \ + i * (LD_VERSION_NZLIST_P(smp->som_dynamic->d_version) ? \ + sizeof(struct nzlist) : sizeof(struct nlist)))) /* Start of hash table */ -#define LM_HASH(lmp) ((struct rrs_hash *) \ - (lmp->lm_addr + LM_OFFSET(lmp) + LD_HASH((lmp)->lm_ld))) +#define LM_HASH(smp) ((struct rrs_hash *) \ + ((smp)->som_addr + LM_OFFSET(smp) + LD_HASH((smp)->som_dynamic))) /* Start of strings */ -#define LM_STRINGS(lmp) ((char *) \ - (lmp->lm_addr + LM_OFFSET(lmp) + LD_STRINGS((lmp)->lm_ld))) +#define LM_STRINGS(smp) ((char *) \ + ((smp)->som_addr + LM_OFFSET(smp) + LD_STRINGS((smp)->som_dynamic))) /* End of text */ -#define LM_ETEXT(lmp) ((char *) \ - (lmp->lm_addr + LM_TXTADDR(lmp) + LD_TEXTSZ((lmp)->lm_ld))) +#define LM_ETEXT(smp) ((char *) \ + ((smp)->som_addr + LM_TXTADDR(smp) + LD_TEXTSZ((smp)->som_dynamic))) /* PLT is in data segment, so don't use LM_OFFSET here */ -#define LM_PLT(lmp) ((jmpslot_t *) \ - (lmp->lm_addr + LD_PLT((lmp)->lm_ld))) +#define LM_PLT(smp) ((jmpslot_t *) \ + ((smp)->som_addr + LD_PLT((smp)->som_dynamic))) /* Parent of link map */ -#define LM_PARENT(lmp) (((struct lm_private *)((lmp)->lm_lpd))->lpd_parent) +#define LM_PARENT(smp) (LM_PRIVATE(smp)->spd_parent) char **environ; int errno; -uid_t uid, euid; -gid_t gid, egid; -int careful; +static uid_t uid, euid; +static gid_t gid, egid; +static int careful; +static char *main_progname = "main"; -struct link_map *link_map_head, *main_map; -struct link_map **link_map_tail = &link_map_head; +struct so_map *link_map_head, *main_map; +struct so_map **link_map_tail = &link_map_head; struct rt_symbol *rt_symbol_head; -static int dlopen(), dlclose(), dlsym(); +static void *dlopen __P((char *, int)); +static int dlclose __P((void *)); +static void *dlsym __P((void *, char *)); +static int dlctl __P((void *, int, void *)); static struct ld_entry ld_entry = { - dlopen, dlclose, dlsym + dlopen, dlclose, dlsym, dlctl }; -void xprintf __P((char *, ...)); + void xprintf __P((char *, ...)); static void init_brk __P((void)); -static void load_maps __P((struct crt_ldso *)); -static void map_object __P((struct link_object *, struct link_map *)); -static void alloc_link_map __P(( char *, struct link_object *, - struct link_map *, caddr_t, - struct link_dynamic *)); -static void check_text_reloc __P(( struct relocation_info *, - struct link_map *, +static void load_objects __P(( struct crt_ldso *, + struct _dynamic *)); +static struct so_map *map_object __P((struct sod *, struct so_map *)); +static struct so_map *alloc_link_map __P(( char *, struct sod *, + struct so_map *, caddr_t, + struct _dynamic *)); +static void inline check_text_reloc __P(( struct relocation_info *, + struct so_map *, caddr_t)); -static void reloc_maps __P((void)); -static void reloc_copy __P((void)); -static void init_maps __P((void)); +static void reloc_map __P((struct so_map *)); +static void reloc_copy __P((struct so_map *)); +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 struct nzlist *lookup __P((char *, struct link_map **, int)); -static struct rt_symbol *lookup_rts __P((char *)); -static struct rt_symbol *enter_rts __P((char *, long, int, caddr_t, long)); +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 inline int +strcmp (register const char *s1, register const char *s2) +{ + while (*s1 == *s2++) + if (*s1++ == 0) + return (0); + return (*(unsigned char *)s1 - *(unsigned char *)--s2); +} #include "md-static-funcs.c" @@ -155,34 +179,36 @@ static struct rt_symbol *enter_rts __P((char *, long, int, caddr_t, long)); * Called from assembler stub that has set up crtp (passed from crt0) * and dp (our __DYNAMIC). */ -void +int rtld(version, crtp, dp) int version; struct crt_ldso *crtp; -struct link_dynamic *dp; +struct _dynamic *dp; { int n; int nreloc; /* # of ld.so relocations */ struct relocation_info *reloc; char **envp; - struct ld_debug *ldp; + struct so_debug *ddp; + struct so_map *smp; /* Check version */ - if (version != CRT_VERSION_BSD && version != CRT_VERSION_SUN) - return; + if ( version != CRT_VERSION_BSD_2 && + version != CRT_VERSION_BSD_3 && + version != CRT_VERSION_SUN) + return -1; /* Fixup __DYNAMIC structure */ - (long)dp->ld_un.ld_2 += crtp->crt_ba; + (long)dp->d_un.d_sdt += crtp->crt_ba; - /* Be careful not to use .div routine from library */ + /* Divide by hand to avoid possible use of library division routine */ for ( nreloc = 0, n = LD_RELSZ(dp); n > 0; n -= sizeof(struct relocation_info) ) nreloc++; /* Relocate ourselves */ - for ( reloc = (struct relocation_info *) - (dp->ld_un.ld_2->ld_rel + crtp->crt_ba); + for ( reloc = (struct relocation_info *)(LD_REL(dp) + crtp->crt_ba); nreloc; nreloc--, reloc++) { @@ -192,6 +218,8 @@ struct link_dynamic *dp; } progname = "ld.so"; + if (version >= CRT_VERSION_BSD_3) + main_progname = crtp->crt_prog; /* Setup out (private) environ variable */ environ = crtp->crt_ep; @@ -212,89 +240,134 @@ struct link_dynamic *dp; std_search_dirs(getenv("LD_LIBRARY_PATH")); /* Load required objects into the process address space */ - load_maps(crtp); + load_objects(crtp, dp); /* Relocate all loaded objects according to their RRS segments */ - reloc_maps(); - reloc_copy(); - init_maps(); + for (smp = link_map_head; smp; smp = smp->som_next) { + if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) + continue; + reloc_map(smp); + } + + /* Copy any relocated initialized data. */ + for (smp = link_map_head; smp; smp = smp->som_next) { + if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) + continue; + reloc_copy(smp); + } + + /* Call any object initialization routines. */ + for (smp = link_map_head; smp; smp = smp->som_next) { + if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) + continue; + init_map(smp, ".init"); + } /* Fill in some field in main's __DYNAMIC structure */ - crtp->crt_dp->ld_entry = &ld_entry; + crtp->crt_dp->d_entry = &ld_entry; + crtp->crt_dp->d_un.d_sdt->sdt_loaded = link_map_head->som_next; - ldp = crtp->crt_dp->ldd; - ldp->ldd_cp = rt_symbol_head; - if (ldp->ldd_in_debugger) { + ddp = crtp->crt_dp->d_debug; + ddp->dd_cc = rt_symbol_head; + if (ddp->dd_in_debugger) { caddr_t addr = (caddr_t)((long)crtp->crt_bp & (~(PAGSIZ - 1))); /* Set breakpoint for the benefit of debuggers */ if (mprotect(addr, PAGSIZ, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { perror("mprotect"), - fatal("Cannot set breakpoint\n"); + fatal("Cannot set breakpoint (%s)\n", main_progname); } - md_set_breakpoint(crtp->crt_bp, &ldp->ldd_bp_inst); + md_set_breakpoint(crtp->crt_bp, &ddp->dd_bpt_shadow); if (mprotect(addr, PAGSIZ, PROT_READ|PROT_EXEC) == -1) { perror("mprotect"); } - ldp->ldd_bp_addr = crtp->crt_bp; + ddp->dd_bpt_addr = crtp->crt_bp; if (link_map_head) - ldp->ldd_sym_loaded = 1; + ddp->dd_sym_loaded = 1; } - crtp->crt_dp->ld_un.ld_2->ld_loaded = link_map_head->lm_next; + /* Close our file descriptor */ (void)close(crtp->crt_ldfd); + return 0; } static void -load_maps(crtp) +load_objects(crtp, dp) struct crt_ldso *crtp; +struct _dynamic *dp; { - struct link_map *lmp; - int tracing = (int)getenv("LD_TRACE_LOADED_OBJECTS"); + struct so_map *smp; + int tracing = (int)getenv("LD_TRACE_LOADED_OBJECTS"); /* Handle LD_PRELOAD's here */ /* Make an entry for the main program */ - alloc_link_map("main", (struct link_object *)0, (struct link_map *)0, + smp = alloc_link_map(main_progname, (struct sod *)0, (struct so_map *)0, (caddr_t)0, crtp->crt_dp); + LM_PRIVATE(smp)->spd_refcount++; + LM_PRIVATE(smp)->spd_flags |= RTLD_MAIN; - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { - struct link_object *lop; - long next = 0; + /* Make an entry for ourselves */ + smp = alloc_link_map("/usr/libexec/ld.so", (struct sod *)0, (struct so_map *)0, + (caddr_t)crtp->crt_ba, dp); + LM_PRIVATE(smp)->spd_refcount++; + LM_PRIVATE(smp)->spd_flags |= RTLD_RTLD; - if (lmp->lm_ld) - next = LD_NEED(lmp->lm_ld); + for (smp = link_map_head; smp; smp = smp->som_next) { + struct sod *sodp; + long next = 0; + + if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) + continue; + + if (smp->som_dynamic) + next = LD_NEED(smp->som_dynamic); while (next) { - lop = (struct link_object *) (LM_LDBASE(lmp) + next); - map_object(lop, lmp); - next = lop->lo_next; + struct so_map *newmap; + + sodp = (struct sod *)(LM_LDBASE(smp) + next); + if ((newmap = map_object(sodp, smp)) == NULL) { + if (!tracing) { + char *name = (char *) + (sodp->sod_name + LM_LDBASE(smp)); + char *fmt = sodp->sod_library ? + "%s: lib%s.so.%d.%d: %s\n" : + "%s: %s: %s\n"; + fatal(fmt, main_progname, name, + sodp->sod_major, + sodp->sod_minor, + strerror(errno)); + } + newmap = alloc_link_map(NULL, sodp, smp, 0, 0); + } + LM_PRIVATE(newmap)->spd_refcount++; + next = sodp->sod_next; } } if (! tracing) return; - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { - struct link_object *lop; - char *name, *path; + for (smp = link_map_head; smp; smp = smp->som_next) { + struct sod *sodp; + char *name, *path; - if ((lop = lmp->lm_lop) == NULL) + if ((sodp = smp->som_sod) == NULL) continue; + name = sodp->sod_name + LM_LDBASE(LM_PARENT(smp)); - name = lop->lo_name + LM_LDBASE(LM_PARENT(lmp)); - - if ((path = lmp->lm_name) == NULL) + if ((path = smp->som_path) == NULL) path = "not found"; - if (lop->lo_library) + if (sodp->sod_library) printf("\t-l%s.%d => %s (%#x)\n", name, - lop->lo_major, path, lmp->lm_addr); + sodp->sod_major, path, smp->som_addr); else - printf("\t%s => %s (%#x)\n", name, path, lmp->lm_addr); + printf("\t%s => %s (%#x)\n", name, path, smp->som_addr); } exit(0); @@ -304,94 +377,120 @@ struct crt_ldso *crtp; * Allocate a new link map for an shared object NAME loaded at ADDR as a * result of the presence of link object LOP in the link map PARENT. */ -static void -alloc_link_map(name, lop, parent, addr, dp) -char *name; -struct link_map *parent; -struct link_object *lop; -caddr_t addr; -struct link_dynamic *dp; + static struct so_map * +alloc_link_map(path, sodp, parent, addr, dp) + char *path; + struct sod *sodp; + struct so_map *parent; + caddr_t addr; + struct _dynamic *dp; { - struct link_map *lmp; - struct lm_private *lmpp; + struct so_map *smp; + struct somap_private *smpp; - lmpp = (struct lm_private *)xmalloc(sizeof(struct lm_private)); - lmp = (struct link_map *)xmalloc(sizeof(struct link_map)); - lmp->lm_next = NULL; - *link_map_tail = lmp; - link_map_tail = &lmp->lm_next; + smpp = (struct somap_private *)xmalloc(sizeof(struct somap_private)); + smp = (struct so_map *)xmalloc(sizeof(struct so_map)); + smp->som_next = NULL; + *link_map_tail = smp; + link_map_tail = &smp->som_next; - lmp->lm_addr = addr; - lmp->lm_name = name; - lmp->lm_lop = lop; - lmp->lm_ld = dp; - lmp->lm_lpd = (caddr_t)lmpp; + smp->som_addr = addr; + smp->som_path = path; + smp->som_sod = sodp; + smp->som_dynamic = dp; + smp->som_spd = (caddr_t)smpp; -/*XXX*/ if (addr == 0) main_map = lmp; +/*XXX*/ if (addr == 0) main_map = smp; - lmpp->lpd_parent = parent; + smpp->spd_refcount = 0; + smpp->spd_flags = 0; + smpp->spd_parent = parent; #ifdef SUN_COMPAT - lmpp->lpd_offset = - (addr == 0 && dp->ld_version == LD_VERSION_SUN) ? PAGSIZ : 0; + smpp->spd_offset = + (addr==0 && dp && dp->d_version==LD_VERSION_SUN) ? PAGSIZ : 0; #endif + return smp; } /* * Map object identified by link object LOP which was found * in link map LMP. */ -static void -map_object(lop, lmp) -struct link_object *lop; -struct link_map *lmp; + static struct so_map * +map_object(sodp, smp) + struct sod *sodp; + struct so_map *smp; { - struct link_dynamic *dp; - char *path, *name = (char *)(lop->lo_name + LM_LDBASE(lmp)); + struct _dynamic *dp; + char *path, *name = (char *)(sodp->sod_name + LM_LDBASE(smp)); int fd; caddr_t addr; struct exec hdr; int usehints = 0; + struct so_map *p; - if (lop->lo_library) { + if (sodp->sod_library) { usehints = 1; again: - path = rtfindlib(name, lop->lo_major, lop->lo_minor, &usehints); - if (path == NULL) - fatal("Cannot find lib%s.so.%d.%d\n", - name, lop->lo_major, lop->lo_minor); + path = rtfindlib(name, sodp->sod_major, + sodp->sod_minor, &usehints); + if (path == NULL) { + errno = ENOENT; + return NULL; + } } else { + if (careful && *name != '/') { + errno = EACCES; + return NULL; + } path = name; } - fd = open(path, O_RDONLY, 0); - if (fd == -1) { + /* Check if already loaded */ + for (p = link_map_head; p; p = p->som_next) + if (p->som_path && strcmp(p->som_path, path) == 0) + break; + + if (p != NULL) + return p; + + if ((fd = open(path, O_RDONLY, 0)) == -1) { if (usehints) { usehints = 0; goto again; } - fatal("%s not found", path); + return NULL; } if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - fatal("%s: Cannot read exec header", path); + (void)close(fd); + /*errno = x;*/ + return NULL; } - if (N_BADMAG(hdr)) - fatal("%s: Incorrect format", path); + if (N_BADMAG(hdr)) { + (void)close(fd); + errno = EFTYPE; + return NULL; + } if ((addr = mmap(0, hdr.a_text + hdr.a_data, PROT_READ|PROT_EXEC, - MAP_FILE|MAP_COPY, fd, 0)) == (caddr_t)-1) - fatal("Cannot map %s text\n", path); + MAP_FILE|MAP_COPY, fd, 0)) == (caddr_t)-1) { + (void)close(fd); + return NULL; + } if (mmap(addr + hdr.a_text, hdr.a_data, - PROT_READ|PROT_WRITE, + PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FILE|MAP_FIXED|MAP_COPY, - fd, hdr.a_text) == (caddr_t)-1) - fatal("Cannot map %s data", path); + fd, hdr.a_text) == (caddr_t)-1) { + (void)close(fd); + return NULL; + } - close(fd); + (void)close(fd); fd = -1; #ifdef NEED_DEV_ZERO @@ -399,213 +498,282 @@ again: perror("/dev/zero"); #endif if (hdr.a_bss && mmap(addr + hdr.a_text + hdr.a_data, hdr.a_bss, - PROT_READ|PROT_WRITE, + PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_COPY, fd, hdr.a_text + hdr.a_data) == (caddr_t)-1) - fatal("Cannot map %s bss", path); + return NULL; #ifdef NEED_DEV_ZERO close(fd); #endif /* Assume _DYNAMIC is the first data item */ - dp = (struct link_dynamic *)(addr+hdr.a_text); + dp = (struct _dynamic *)(addr+hdr.a_text); /* Fixup __DYNAMIC structure */ - (long)dp->ld_un.ld_2 += (long)addr; - - alloc_link_map(path, lop, lmp, addr, dp); + (long)dp->d_un.d_sdt += (long)addr; + return alloc_link_map(path, sodp, smp, addr, dp); } -static void -reloc_maps() +static void inline +check_text_reloc(r, smp, addr) +struct relocation_info *r; +struct so_map *smp; +caddr_t addr; { - struct link_map *lmp; - - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { - - struct link_dynamic *dp = lmp->lm_ld; - struct relocation_info *r = LM_REL(lmp); - struct relocation_info *rend = r + LD_RELSZ(dp)/sizeof(*r); - - if (LD_PLTSZ(dp)) - md_fix_jmpslot(LM_PLT(lmp), - (long)LM_PLT(lmp), (long)binder_entry); - - for (; r < rend; r++) { - char *sym; - caddr_t addr = lmp->lm_addr + r->r_address; - - check_text_reloc(r, lmp, addr); + char *sym; - if (RELOC_EXTERN_P(r)) { - struct link_map *src_map = NULL; - struct nzlist *p, *np; - long relocation = md_get_addend(r, addr); + if (addr >= LM_ETEXT(smp)) + return; - if (RELOC_LAZY_P(r)) - continue; + if (RELOC_EXTERN_P(r)) + sym = LM_STRINGS(smp) + + LM_SYMBOL(smp, RELOC_SYMBOL(r))->nz_strx; + else + sym = ""; - p = LM_SYMBOL(lmp,RELOC_SYMBOL(r)); - if (p->nz_type == (N_SETV + N_EXT)) - src_map = lmp; + if (getenv("LD_WARN_NON_PURE_CODE") != NULL) + fprintf(stderr, + "ld.so: warning: non pure code in %s at %x (%s)\n", + smp->som_path, r->r_address, sym); - sym = LM_STRINGS(lmp) + p->nz_strx; + if (smp->som_write == 0 && + mprotect(smp->som_addr + LM_TXTADDR(smp), + LD_TEXTSZ(smp->som_dynamic), + PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - np = lookup(sym, &src_map, 0/*XXX-jumpslots!*/); - if (np == NULL) - fatal("Undefined symbol \"%s\" in %s\n", - sym, lmp->lm_name); + perror("mprotect"), + fatal("Cannot enable writes to %s:%s\n", + main_progname, smp->som_path); + } - /* - * Found symbol definition. - * If it's in a link map, adjust value - * according to the load address of that map. - * Otherwise it's a run-time allocated common - * whose value is already up-to-date. - */ - relocation += np->nz_value; - if (src_map) - relocation += (long)src_map->lm_addr; + smp->som_write = 1; +} - if (RELOC_PCREL_P(r)) - relocation -= (long)lmp->lm_addr; +static void +reloc_map(smp) + struct so_map *smp; +{ + struct _dynamic *dp = smp->som_dynamic; + struct relocation_info *r = LM_REL(smp); + struct relocation_info *rend = r + LD_RELSZ(dp)/sizeof(*r); + long symbolbase = (long)LM_SYMBOL(smp, 0); + char *stringbase = LM_STRINGS(smp); + int symsize = LD_VERSION_NZLIST_P(dp->d_version) ? + sizeof(struct nzlist) : + sizeof(struct nlist); + + if (LD_PLTSZ(dp)) + md_fix_jmpslot(LM_PLT(smp), + (long)LM_PLT(smp), (long)binder_entry); + + for (; r < rend; r++) { + char *sym; + caddr_t addr = smp->som_addr + r->r_address; + + check_text_reloc(r, smp, addr); + + if (RELOC_EXTERN_P(r)) { + struct so_map *src_map = NULL; + struct nzlist *p, *np; + long relocation = md_get_addend(r, addr); + + if (RELOC_LAZY_P(r)) + continue; - if (RELOC_COPY_P(r) && src_map) { -#if DEBUG -xprintf("RELOCATE(%s) copy: from %s at %#x(%#x+%#x) to %s at %#x, reloc = %#x, size %d\n", -lmp->lm_name, src_map->lm_name, src_map->lm_addr + np->nz_value, -src_map->lm_addr, np->nz_value, sym, addr, relocation, np->nz_size); -#endif - (void)enter_rts(sym, - (long)addr, - N_DATA + N_EXT, - src_map->lm_addr + np->nz_value, - np->nz_size); - continue; - } -#if DEBUG -if (sym[2]=='_'&&(sym[3]=='C'||sym[3]=='D')&&sym[4]=='T') -xprintf("RELOCATE(%s) external: %s at %#x, reloc = %#x in %s\n", -lmp->lm_name, sym, addr, relocation, src_map?src_map->lm_name:"(NUL)"); -#endif - md_relocate(r, relocation, addr, 0); + p = (struct nzlist *) + (symbolbase + symsize * RELOC_SYMBOL(r)); + + if (p->nz_type == (N_SETV + N_EXT)) + src_map = smp; + + sym = stringbase + p->nz_strx; + + np = lookup(sym, &src_map, 0/*XXX-jumpslots!*/); + if (np == NULL) + fatal("Undefined symbol \"%s\" in %s:%s\n", + sym, main_progname, smp->som_path); + + /* + * Found symbol definition. + * If it's in a link map, adjust value + * according to the load address of that map. + * Otherwise it's a run-time allocated common + * whose value is already up-to-date. + */ + relocation += np->nz_value; + if (src_map) + relocation += (long)src_map->som_addr; + + if (RELOC_PCREL_P(r)) + relocation -= (long)smp->som_addr; + + if (RELOC_COPY_P(r) && src_map) { + (void)enter_rts(sym, + (long)addr, + N_DATA + N_EXT, + src_map->som_addr + np->nz_value, + np->nz_size, src_map); + continue; + } + md_relocate(r, relocation, addr, 0); - } else { -#if DEBUG -xprintf("RELOCATE(%s) internal at %#x, reloc = %#x\n", lmp->lm_name, addr, md_get_rt_segment_addend(r,addr)); -#endif - md_relocate(r, + } else { + md_relocate(r, #ifdef SUN_COMPAT - md_get_rt_segment_addend(r, addr) + md_get_rt_segment_addend(r, addr) #else - md_get_addend(r, addr) + md_get_addend(r, addr) #endif - + (long)lmp->lm_addr, addr, 0); - } - + + (long)smp->som_addr, addr, 0); } - if (lmp->lm_rwt) { - if (mprotect(lmp->lm_addr + LM_TXTADDR(lmp), - LD_TEXTSZ(lmp->lm_ld), + } + + if (smp->som_write) { + if (mprotect(smp->som_addr + LM_TXTADDR(smp), + LD_TEXTSZ(smp->som_dynamic), PROT_READ|PROT_EXEC) == -1) { - perror("mprotect"), - fatal("Cannot disable writes to %s\n", lmp->lm_name); - } - lmp->lm_rwt = 0; + perror("mprotect"), + fatal("Cannot disable writes to %s:%s\n", + main_progname, smp->som_path); } - + smp->som_write = 0; } } static void -reloc_copy() +reloc_copy(smp) + struct so_map *smp; { struct rt_symbol *rtsp; for (rtsp = rt_symbol_head; rtsp; rtsp = rtsp->rt_next) - if (rtsp->rt_sp->nz_type == N_DATA + N_EXT) { -#ifdef DEBUG -xprintf("reloc_copy: from %#x to %#x, size %d\n", -rtsp->rt_srcaddr, rtsp->rt_sp->nz_value, rtsp->rt_sp->nz_size); -#endif + if ((rtsp->rt_smp == NULL || rtsp->rt_smp == smp) && + rtsp->rt_sp->nz_type == N_DATA + N_EXT) { bcopy(rtsp->rt_srcaddr, (caddr_t)rtsp->rt_sp->nz_value, rtsp->rt_sp->nz_size); } } static void -check_text_reloc(r, lmp, addr) -struct relocation_info *r; -struct link_map *lmp; -caddr_t addr; +init_map(smp, sym) + struct so_map *smp; + char *sym; { - char *sym; + struct so_map *src_map = smp; + struct nzlist *np; - if (addr >= LM_ETEXT(lmp)) - return; + np = lookup(sym, &src_map, 1); + if (np) + (*(void (*)())(src_map->som_addr + np->nz_value))(); +} - if (RELOC_EXTERN_P(r)) - sym = LM_STRINGS(lmp) + - LM_SYMBOL(lmp, RELOC_SYMBOL(r))->nz_strx; - else - sym = ""; +/* + * Run-time common symbol table. + */ -#ifdef DEBUG - fprintf(stderr, "ld.so: warning: non pure code in %s at %x (%s)\n", - lmp->lm_name, r->r_address, sym); -#endif +#define RTC_TABSIZE 57 +static struct rt_symbol *rt_symtab[RTC_TABSIZE]; - if (lmp->lm_rwt == 0 && - mprotect(lmp->lm_addr + LM_TXTADDR(lmp), - LD_TEXTSZ(lmp->lm_ld), - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { +/* + * Compute hash value for run-time symbol table + */ + static int inline +hash_string(key) + char *key; +{ + register char *cp; + register int k; - perror("mprotect"), - fatal("Cannot enable writes to %s\n", lmp->lm_name); - } + cp = key; + k = 0; + while (*cp) + k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; - lmp->lm_rwt = 1; + return k; } -static void -init_maps() +/* + * Lookup KEY in the run-time common symbol table. + */ + + static inline struct rt_symbol * +lookup_rts(key) + char *key; { - struct link_map *lmp, *src_map; - struct nzlist *np; - void (*func)(); + register int hashval; + register struct rt_symbol *rtsp; - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { - src_map = lmp; - np = lookup("___init", &src_map, 1); -#if DEBUG -if (np) -xprintf("Calling __init in %s at %#x\n", src_map->lm_name, np->nz_value+src_map->lm_addr); -#endif - if (np) { - func = (void (*)())(src_map->lm_addr + np->nz_value); - (*func)(); - } - } + /* Determine which bucket. */ + + hashval = hash_string(key) % RTC_TABSIZE; + + /* Search the bucket. */ + + for (rtsp = rt_symtab[hashval]; rtsp; rtsp = rtsp->rt_link) + if (strcmp(key, rtsp->rt_sp->nz_name) == 0) + return rtsp; + + return NULL; } + static struct rt_symbol * +enter_rts(name, value, type, srcaddr, size, smp) + char *name; + long value; + int type; + caddr_t srcaddr; + long size; + struct so_map *smp; +{ + register int hashval; + register struct rt_symbol *rtsp, **rpp; + + /* Determine which bucket */ + hashval = hash_string(name) % RTC_TABSIZE; + + /* Find end of bucket */ + for (rpp = &rt_symtab[hashval]; *rpp; rpp = &(*rpp)->rt_link) + ; + + /* Allocate new common symbol */ + rtsp = (struct rt_symbol *)malloc(sizeof(struct rt_symbol)); + rtsp->rt_sp = (struct nzlist *)malloc(sizeof(struct nzlist)); + rtsp->rt_sp->nz_name = strdup(name); + rtsp->rt_sp->nz_value = value; + rtsp->rt_sp->nz_type = type; + rtsp->rt_sp->nz_size = size; + rtsp->rt_srcaddr = srcaddr; + rtsp->rt_smp = smp; + rtsp->rt_link = NULL; + + /* Link onto linear list as well */ + rtsp->rt_next = rt_symbol_head; + rt_symbol_head = rtsp; + + *rpp = rtsp; + + return rtsp; +} + + /* * Lookup NAME in the link maps. The link map producing a definition * is returned in SRC_MAP. If SRC_MAP is not NULL on entry the search is * confined to that map. If STRONG is set, the symbol returned must * have a proper type (used by binder()). */ -static struct nzlist * + static struct nzlist * lookup(name, src_map, strong) -char *name; -struct link_map **src_map; /* IN/OUT */ -int strong; + char *name; + struct so_map **src_map; /* IN/OUT */ + int strong; { long common_size = 0; - struct link_map *lmp; + struct so_map *smp; struct rt_symbol *rtsp; if ((rtsp = lookup_rts(name)) != NULL) @@ -614,14 +782,23 @@ int strong; /* * Search all maps for a definition of NAME */ - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { - int buckets = LD_BUCKETS(lmp->lm_ld); + for (smp = link_map_head; smp; smp = smp->som_next) { + int buckets = LD_BUCKETS(smp->som_dynamic); long hashval = 0; struct rrs_hash *hp; char *cp; struct nzlist *np; - if (*src_map && lmp != *src_map) + /* Some local caching */ + long symbolbase; + struct rrs_hash *hashbase; + char *stringbase; + int symsize; + + if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) + continue; + + if (*src_map && smp != *src_map) continue; /* @@ -632,20 +809,27 @@ int strong; hashval = (hashval & 0x7fffffff) % buckets; - hp = LM_HASH(lmp) + hashval; + hashbase = LM_HASH(smp); + hp = hashbase + hashval; if (hp->rh_symbolnum == -1) /* Nothing in this bucket */ continue; + symbolbase = (long)LM_SYMBOL(smp, 0); + stringbase = LM_STRINGS(smp); + symsize = LD_VERSION_NZLIST_P(smp->som_dynamic->d_version)? + sizeof(struct nzlist) : + sizeof(struct nlist); while (hp) { - np = LM_SYMBOL(lmp, hp->rh_symbolnum); - cp = LM_STRINGS(lmp) + np->nz_strx; + np = (struct nzlist *) + (symbolbase + hp->rh_symbolnum * symsize); + cp = stringbase + np->nz_strx; if (strcmp(cp, name) == 0) break; if (hp->rh_next == 0) hp = NULL; else - hp = LM_HASH(lmp) + hp->rh_next; + hp = hashbase + hp->rh_next; } if (hp == NULL) /* Nothing in this bucket */ @@ -660,7 +844,7 @@ int strong; continue; if (np->nz_type == N_UNDF+N_EXT && np->nz_value != 0) { - if (np->nz_other == RRS_FUNC) { + if (np->nz_other == AUX_FUNC) { /* It's a weak function definition */ if (strong) continue; @@ -672,7 +856,7 @@ int strong; } } - *src_map = lmp; + *src_map = smp; return np; } @@ -684,7 +868,7 @@ int strong; * It's a common, enter into run-time common symbol table. */ rtsp = enter_rts(name, (long)calloc(1, common_size), - N_UNDF + N_EXT, 0, common_size); + N_UNDF + N_EXT, 0, common_size, NULL); #if DEBUG xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value); @@ -698,11 +882,11 @@ xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp * This routine is called from the jumptable to resolve * procedure calls to shared objects. */ -long + long binder(jsp) -jmpslot_t *jsp; + jmpslot_t *jsp; { - struct link_map *lmp, *src_map = NULL; + struct so_map *smp, *src_map = NULL; long addr; char *sym; struct nzlist *np; @@ -711,133 +895,47 @@ jmpslot_t *jsp; /* * Find the PLT map that contains JSP. */ - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { - if (LM_PLT(lmp) < jsp && - jsp < LM_PLT(lmp) + LD_PLTSZ(lmp->lm_ld)/sizeof(*jsp)) + for (smp = link_map_head; smp; smp = smp->som_next) { + if (LM_PLT(smp) < jsp && + jsp < LM_PLT(smp) + LD_PLTSZ(smp->som_dynamic)/sizeof(*jsp)) break; } - if (lmp == NULL) + if (smp == NULL) fatal("Call to binder from unknown location: %#x\n", jsp); index = jsp->reloc_index & JMPSLOT_RELOC_MASK; /* Get the local symbol this jmpslot refers to */ - sym = LM_STRINGS(lmp) + - LM_SYMBOL(lmp,RELOC_SYMBOL(&LM_REL(lmp)[index]))->nz_strx; + sym = LM_STRINGS(smp) + + LM_SYMBOL(smp,RELOC_SYMBOL(&LM_REL(smp)[index]))->nz_strx; np = lookup(sym, &src_map, 1); if (np == NULL) - fatal("Undefined symbol \"%s\" called from %s at %#x", sym, - lmp->lm_name, jsp); + fatal("Undefined symbol \"%s\" called from %s:%s at %#x", + sym, main_progname, smp->som_path, jsp); /* Fixup jmpslot so future calls transfer directly to target */ addr = np->nz_value; if (src_map) - addr += (long)src_map->lm_addr; + addr += (long)src_map->som_addr; md_fix_jmpslot(jsp, (long)jsp, addr); #if DEBUG -xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr, src_map->lm_name); +xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr, src_map->som_path); #endif return addr; } -/* - * Run-time common symbol table. - */ - -#define RTC_TABSIZE 57 -static struct rt_symbol *rt_symtab[RTC_TABSIZE]; - -/* - * Compute hash value for run-time symbol table - */ -static int -hash_string(key) - char *key; -{ - register char *cp; - register int k; - - cp = key; - k = 0; - while (*cp) - k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; - - return k; -} - -/* - * Lookup KEY in the run-time common symbol table. - */ - -static struct rt_symbol * -lookup_rts(key) - char *key; -{ - register int hashval; - register struct rt_symbol *rtsp; - - /* Determine which bucket. */ - - hashval = hash_string(key) % RTC_TABSIZE; - - /* Search the bucket. */ - - for (rtsp = rt_symtab[hashval]; rtsp; rtsp = rtsp->rt_link) - if (strcmp(key, rtsp->rt_sp->nz_name) == 0) - return rtsp; - - return NULL; -} - -static struct rt_symbol * -enter_rts(name, value, type, srcaddr, size) - char *name; - long value; - int type; - caddr_t srcaddr; - long size; -{ - register int hashval; - register struct rt_symbol *rtsp, **rpp; - - /* Determine which bucket */ - hashval = hash_string(name) % RTC_TABSIZE; - - /* Find end of bucket */ - for (rpp = &rt_symtab[hashval]; *rpp; rpp = &(*rpp)->rt_link) - ; - - /* Allocate new common symbol */ - rtsp = (struct rt_symbol *)malloc(sizeof(struct rt_symbol)); - rtsp->rt_sp = (struct nzlist *)malloc(sizeof(struct nzlist)); - rtsp->rt_sp->nz_name = strdup(name); - rtsp->rt_sp->nz_value = value; - rtsp->rt_sp->nz_type = type; - rtsp->rt_sp->nz_size = size; - rtsp->rt_srcaddr = srcaddr; - rtsp->rt_link = NULL; - - /* Link onto linear list as well */ - rtsp->rt_next = rt_symbol_head; - rt_symbol_head = rtsp; - - *rpp = rtsp; - - return rtsp; -} - static struct hints_header *hheader; static struct hints_bucket *hbuckets; static char *hstrtab; #define HINTS_VALID (hheader != NULL && hheader != (struct hints_header *)-1) -static void + static void maphints() { caddr_t addr; @@ -886,10 +984,10 @@ maphints() hstrtab = (char *)(addr + hheader->hh_strtab); } -int + int hinthash(cp, vmajor, vminor) -char *cp; -int vmajor, vminor; + char *cp; + int vmajor, vminor; { int k = 0; @@ -905,11 +1003,11 @@ int vmajor, vminor; #undef major #undef minor -static char * + static char * findhint(name, major, minor, preferred_path) -char *name; -int major, minor; -char *preferred_path; + char *name; + int major, minor; + char *preferred_path; { struct hints_bucket *bp; @@ -949,11 +1047,11 @@ char *preferred_path; return NULL; } -static char * + static char * rtfindlib(name, major, minor, usehints) -char *name; -int major, minor; -int *usehints; + char *name; + int major, minor; + int *usehints; { char *hint; char *cp, *ld_path = getenv("LD_LIBRARY_PATH"); @@ -988,29 +1086,131 @@ int *usehints; return (char *)findshlib(name, &major, &minor, 0); } -static int +static struct somap_private dlmap_private = { + 0, + (struct so_map *)0, + 0, +#ifdef SUN_COMPAT + 0, +#endif +}; + +static struct so_map dlmap = { + (caddr_t)0, + "internal", + (struct so_map *)0, + (struct sod *)0, + (caddr_t)0, + (u_int)0, + (struct _dynamic *)0, + (caddr_t)&dlmap_private +}; +static int dlerrno; + + static void * dlopen(name, mode) -char *name; -int mode; + char *name; + int mode; { - xprintf("dlopen(%s, %x)\n", name, mode); - return -1; + struct sod *sodp; + struct so_map *smp; + + /* + * A NULL argument returns the current set of mapped objects. + */ + if (name == NULL) + return link_map_head; + + if ((sodp = (struct sod *)malloc(sizeof(struct sod))) == NULL) { + dlerrno = ENOMEM; + return NULL; + } + + sodp->sod_name = (long)name; + sodp->sod_library = 0; + sodp->sod_major = sodp->sod_minor = 0; + + if ((smp = map_object(sodp, &dlmap)) == NULL) { +#ifdef DEBUG +xprintf("%s: %s\n", name, strerror(errno)); +#endif + dlerrno = errno; + return NULL; + } + if (LM_PRIVATE(smp)->spd_refcount++ == 0) { + LM_PRIVATE(smp)->spd_flags |= RTLD_DL; + reloc_map(smp); + reloc_copy(smp); + init_map(smp, ".init"); + init_map(smp, "_init"); + } + + return smp; } -static int + static int dlclose(fd) -int fd; + void *fd; { - xprintf("dlclose(%d)\n", fd); - return -1; + struct so_map *smp = (struct so_map *)fd; + +#ifdef DEBUG +xprintf("dlclose(%s): refcount = %d\n", smp->som_path, LM_PRIVATE(smp)->spd_refcount); +#endif + if (--LM_PRIVATE(smp)->spd_refcount != 0) + return 0; + + /* Dismantle shared object map and descriptor */ + init_map(smp, "_fini"); +#if 0 + unmap_object(smp); + free(smp->som_sod); + free(smp); +#endif + + return 0; } -static int + static void * dlsym(fd, sym) -int fd; -char *sym; + void *fd; + char *sym; { - xprintf("dlsym(%d, %s)\n", fd, sym); + struct so_map *smp = (struct so_map *)fd, *src_map = NULL; + struct nzlist *np; + long addr; + + /* + * Restrict search to passed map if dlopen()ed. + */ + if (LM_PRIVATE(smp)->spd_flags & RTLD_DL) + src_map = smp; + + np = lookup(sym, &src_map, 1); + if (np == NULL) + return NULL; + + /* Fixup jmpslot so future calls transfer directly to target */ + addr = np->nz_value; + if (src_map) + addr += (long)src_map->som_addr; + + return (void *)addr; +} + + static int +dlctl(fd, cmd, arg) + void *fd, *arg; + int cmd; +{ + switch (cmd) { + case DL_GETERRNO: + *(int *)arg = dlerrno; + return 0; + default: + dlerrno = EOPNOTSUPP; + return -1; + } return 0; } diff --git a/gnu/usr.bin/ld/shlib.c b/gnu/usr.bin/ld/shlib.c index 0bfc373ad3..38ec051ab2 100644 --- a/gnu/usr.bin/ld/shlib.c +++ b/gnu/usr.bin/ld/shlib.c @@ -1,5 +1,33 @@ /* - * $Id: shlib.c,v 1.6 1993/12/11 11:58:29 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 without 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: shlib.c,v 1.9 1994/01/29 02:03:15 jtc Exp $ */ #include @@ -25,14 +53,20 @@ char *strsep(); * Standard directories to search for files specified by -l. */ #ifndef STANDARD_SEARCH_DIRS -#define STANDARD_SEARCH_DIRS "/usr/lib" +#define STANDARD_SEARCH_DIRS "/usr/lib", "/usr/X386/lib", "/usr/local/lib" #endif +/* + * Actual vector of library search directories, + * including `-L'ed and LD_LIBARAY_PATH spec'd ones. + */ +char **search_dirs; +int n_search_dirs; + char *standard_search_dirs[] = { STANDARD_SEARCH_DIRS }; -int n_search_dirs; void add_search_dir(name) diff --git a/gnu/usr.bin/ld/sparc/md.c b/gnu/usr.bin/ld/sparc/md.c index 3ae54e30e9..15281cc37c 100644 --- a/gnu/usr.bin/ld/sparc/md.c +++ b/gnu/usr.bin/ld/sparc/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.6 1993/12/08 10:29:02 pk Exp $ + * $Id: md.c,v 1.6 1993/12/11 12:02:10 jkh Exp $ */ #include @@ -109,6 +109,7 @@ int relocatable_output; { register unsigned long mask; +#ifndef RTLD if (relocatable_output) { /* * Non-PC relative relocations which are absolute or @@ -129,6 +130,7 @@ int relocatable_output; RELOC_ADD_EXTRA(r) -= pc_relocation; return; } +#endif relocation >>= RELOC_VALUE_RIGHTSHIFT(r); @@ -167,33 +169,7 @@ int relocatable_output; } } -/* - * Initialize (output) exec header such that useful values are - * obtained from subsequent N_*() macro evaluations. - */ -void -md_init_header(hp, magic, flags) -struct exec *hp; -int magic, flags; -{ -#ifdef NetBSD - N_SETMAGIC((*hp), magic, MID_MACHINE, flags); - - /* TEXT_START depends on the value of outheader.a_entry. */ - if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */ - hp->a_entry = PAGSIZ; -#else - hp->a_magic = magic; - hp->a_machtype = M_SPARC; - hp->a_toolversion = 1; - hp->a_dynamic = ((flags) & EX_DYNAMIC); - - /* SunOS 4.1 N_TXTADDR depends on the value of outheader.a_entry. */ - if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */ - hp->a_entry = N_PAGSIZ(*hp); -#endif -} - +#ifndef RTLD /* * Machine dependent part of claim_rrs_reloc(). * On the Sparc the relocation offsets are stored in the r_addend member. @@ -224,6 +200,7 @@ int type; return 1; } +#endif /* * Set up a transfer from jmpslot at OFFSET (relative to the PLT table) @@ -327,3 +304,46 @@ long *savep; *(long *)where = TRAP; } +#ifndef RTLD +/* + * Initialize (output) exec header such that useful values are + * obtained from subsequent N_*() macro evaluations. + */ +void +md_init_header(hp, magic, flags) +struct exec *hp; +int magic, flags; +{ +#ifdef NetBSD + N_SETMAGIC((*hp), magic, MID_MACHINE, flags); + + /* TEXT_START depends on the value of outheader.a_entry. */ + if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */ + hp->a_entry = PAGSIZ; +#else + hp->a_magic = magic; + hp->a_machtype = M_SPARC; + hp->a_toolversion = 1; + hp->a_dynamic = ((flags) & EX_DYNAMIC); + + /* SunOS 4.1 N_TXTADDR depends on the value of outheader.a_entry. */ + if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */ + hp->a_entry = N_PAGSIZ(*hp); +#endif +} + +/* + * Check for acceptable foreign machine Ids + */ +int +md_midcompat(hp) +struct exec *hp; +{ +#ifdef NetBSD +#define SUN_M_SPARC 3 + return (((md_swap_long(hp->a_midmag)&0x00ff0000) >> 16) == SUN_M_SPARC); +#else + return hp->a_machtype == M_SPARC; +#endif +} +#endif /* RTLD */ diff --git a/gnu/usr.bin/ld/sparc/md.h b/gnu/usr.bin/ld/sparc/md.h index c3e9064085..3545d97d92 100644 --- a/gnu/usr.bin/ld/sparc/md.h +++ b/gnu/usr.bin/ld/sparc/md.h @@ -14,7 +14,7 @@ * 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 + * derived from this software without 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 @@ -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.3 1993/11/22 19:05:31 jkh Exp $ + * $Id: md.h,v 1.5 1993/12/02 01:03:47 jkh Exp $ */ /* @@ -44,6 +44,13 @@ MID_MACHINE, N_GETFLAG(ex)|(f)) #define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC)) +/* + * Should be handled by a.out.h ? + */ +#define N_ADJUST(ex) (((ex).a_entry < PAGSIZ) ? -PAGSIZ : 0) +#define TEXT_START(ex) (N_TXTADDR(ex) + N_ADJUST(ex)) +#define DATA_START(ex) (N_DATADDR(ex) + N_ADJUST(ex)) + #else /* Get the SunOS a.out and relocation nomenclature */ @@ -60,6 +67,10 @@ #define r_symbolnum r_index #endif /* NetBSD */ +#define N_BADMID(ex) \ + (N_GETMID(ex) != 0 && N_GETMID(ex) != MID_MACHINE && \ + !md_midcompat(&(ex))) + /* Sparc (Sun 4) macros */ #define RELOC_ADDRESS(r) ((r)->r_address) #define RELOC_EXTERN_P(r) ((r)->r_extern) @@ -139,16 +150,16 @@ typedef struct jmpslot { #define md_swapout_zsymbols(s,n) #define md_swapin_reloc(r,n) #define md_swapout_reloc(r,n) -#define md_swapin_link_dynamic(l) -#define md_swapout_link_dynamic(l) -#define md_swapin_link_dynamic_2(l) -#define md_swapout_link_dynamic_2(l) -#define md_swapin_ld_debug(d) -#define md_swapout_ld_debug(d) +#define md_swapin__dynamic(l) +#define md_swapout__dynamic(l) +#define md_swapin_section_dispatch_table(l) +#define md_swapout_section_dispatch_table(l) +#define md_swapin_so_debug(d) +#define md_swapout_so_debug(d) #define md_swapin_rrs_hash(f,n) #define md_swapout_rrs_hash(f,n) -#define md_swapin_link_object(l,n) -#define md_swapout_link_object(l,n) +#define md_swapin_sod(l,n) +#define md_swapout_sod(l,n) #define md_swapout_jmpslot(j,n) #define md_swapout_got(g,n) #define md_swapin_ranlib_hdr(h,n) @@ -168,23 +179,23 @@ void md_swapin_reloc __P((struct relocation_info *, int)); void md_swapout_reloc __P((struct relocation_info *, int)); void md_swapout_jmpslot __P((jmpslot_t *, int)); -#define md_swapin_symbols(s,n) swap_symbols(s,n) -#define md_swapout_symbols(s,n) swap_symbols(s,n) -#define md_swapin_zsymbols(s,n) swap_zsymbols(s,n) -#define md_swapout_zsymbols(s,n) swap_zsymbols(s,n) -#define md_swapin_link_dynamic(l) swap_link_dynamic(l) -#define md_swapout_link_dynamic(l) swap_link_dynamic(l) -#define md_swapin_link_dynamic_2(l) swap_link_dynamic_2(l) -#define md_swapout_link_dynamic_2(l) swap_link_dynamic_2(l) -#define md_swapin_ld_debug(d) swap_ld_debug(d) -#define md_swapout_ld_debug(d) swap_ld_debug(d) -#define md_swapin_rrs_hash(f,n) swap_rrs_hash(f,n) -#define md_swapout_rrs_hash(f,n) swap_rrs_hash(f,n) -#define md_swapin_link_object(l,n) swapin_link_object(l,n) -#define md_swapout_link_object(l,n) swapout_link_object(l,n) -#define md_swapout_got(g,n) swap_longs((long*)(g),n) -#define md_swapin_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) -#define md_swapout_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) +#define md_swapin_symbols(s,n) swap_symbols(s,n) +#define md_swapout_symbols(s,n) swap_symbols(s,n) +#define md_swapin_zsymbols(s,n) swap_zsymbols(s,n) +#define md_swapout_zsymbols(s,n) swap_zsymbols(s,n) +#define md_swapin__dynamic(l) swap__dynamic(l) +#define md_swapout__dynamic(l) swap__dynamic(l) +#define md_swapin_section_dispatch_table(l) swap_section_dispatch_table(l) +#define md_swapout_section_dispatch_table(l) swap_section_dispatch_table(l) +#define md_swapin_so_debug(d) swap_so_debug(d) +#define md_swapout_so_debug(d) swap_so_debug(d) +#define md_swapin_rrs_hash(f,n) swap_rrs_hash(f,n) +#define md_swapout_rrs_hash(f,n) swap_rrs_hash(f,n) +#define md_swapin_sod(l,n) swapin_sod(l,n) +#define md_swapout_sod(l,n) swapout_sod(l,n) +#define md_swapout_got(g,n) swap_longs((long*)(g),n) +#define md_swapin_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) +#define md_swapout_ranlib_hdr(h,n) swap_ranlib_hdr(h,n) #define md_swap_short(x) ( (((x) >> 8) & 0xff) | (((x) & 0xff) << 8) ) diff --git a/gnu/usr.bin/ld/sparc/mdprologue.S b/gnu/usr.bin/ld/sparc/mdprologue.S index 8ad60b0571..0d006d0c0d 100644 --- a/gnu/usr.bin/ld/sparc/mdprologue.S +++ b/gnu/usr.bin/ld/sparc/mdprologue.S @@ -14,7 +14,7 @@ * 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 + * derived from this software without 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 @@ -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.1 1993/10/16 21:54:36 pk Exp $ + * $Id: mdprologue.S,v 1.2 1993/11/09 04:19:36 paul Exp $ */ /* diff --git a/gnu/usr.bin/ld/symbol.c b/gnu/usr.bin/ld/symbol.c index d789a3a54b..af182a9dc8 100644 --- a/gnu/usr.bin/ld/symbol.c +++ b/gnu/usr.bin/ld/symbol.c @@ -1,5 +1,5 @@ /* - * $Id: symbol.c,v 1.2 1993/11/09 04:19:04 paul Exp $ - symbol table routines + * $Id: symbol.c,v 1.3 1993/11/22 19:04:45 jkh Exp $ - symbol table routines */ /* Create the symbol table entries for `etext', `edata' and `end'. */ @@ -15,6 +15,15 @@ #include "ld.h" +symbol *symtab[SYMTABSIZE]; /* The symbol table. */ +int num_hash_tab_syms; /* Number of symbols in symbol hash table. */ + +symbol *edata_symbol; /* the symbol _edata */ +symbol *etext_symbol; /* the symbol _etext */ +symbol *end_symbol; /* the symbol _end */ +symbol *got_symbol; /* the symbol __GLOBAL_OFFSET_TABLE_ */ +symbol *dynamic_symbol; /* the symbol __DYNAMIC */ + void symtab_init (relocatable_output) int relocatable_output; @@ -22,36 +31,40 @@ int relocatable_output; /* * Put linker reserved symbols into symbol table. */ +#ifndef nounderscore +#define ETEXT_SYM "_etext" +#define EDATA_SYM "_edata" +#define END_SYM "_end" +#define DYN_SYM "__DYNAMIC" +#define GOT_SYM "__GLOBAL_OFFSET_TABLE_" +#else +#define ETEXT_SYM "etext" +#define EDATA_SYM "edata" +#define END_SYM "end" +#define DYN_SYM "_DYNAMIC" +#define GOT_SYM "_GLOBAL_OFFSET_TABLE_" +#endif - dynamic_symbol = getsym ("__DYNAMIC"); + dynamic_symbol = getsym (DYN_SYM); dynamic_symbol->defined = relocatable_output?N_UNDF:(N_DATA | N_EXT); - dynamic_symbol->referenced = 0; - dynamic_symbol->value = 0; - got_symbol = getsym ("__GLOBAL_OFFSET_TABLE_"); + got_symbol = getsym (GOT_SYM); got_symbol->defined = N_DATA | N_EXT; - got_symbol->referenced = 0; - got_symbol->value = 0; if (relocatable_output) return; -#ifndef nounderscore - edata_symbol = getsym ("_edata"); - etext_symbol = getsym ("_etext"); - end_symbol = getsym ("_end"); -#else - edata_symbol = getsym ("edata"); - etext_symbol = getsym ("etext"); - end_symbol = getsym ("end"); -#endif - edata_symbol->defined = N_DATA | N_EXT; + etext_symbol = getsym (ETEXT_SYM); + edata_symbol = getsym (EDATA_SYM); + end_symbol = getsym (END_SYM); + etext_symbol->defined = N_TEXT | N_EXT; + edata_symbol->defined = N_DATA | N_EXT; end_symbol->defined = N_BSS | N_EXT; - edata_symbol->referenced = 1; - etext_symbol->referenced = 1; - end_symbol->referenced = 1; + etext_symbol->flags |= GS_REFERENCED; + edata_symbol->flags |= GS_REFERENCED; + end_symbol->flags |= GS_REFERENCED; } /* Compute the hash code for symbol name KEY. */ @@ -82,7 +95,7 @@ getsym(key) register symbol *bp; /* Determine the proper bucket. */ - hashval = hash_string (key) % TABSIZE; + hashval = hash_string (key) % SYMTABSIZE; /* Search the bucket. */ for (bp = symtab[hashval]; bp; bp = bp->link) @@ -91,17 +104,15 @@ getsym(key) /* Nothing was found; create a new symbol table entry. */ bp = (symbol *) xmalloc (sizeof (symbol)); - bp->refs = 0; bp->name = (char *) xmalloc (strlen (key) + 1); strcpy (bp->name, key); + bp->refs = 0; bp->defined = 0; - bp->referenced = 0; - bp->trace = 0; bp->value = 0; - bp->max_common_size = 0; + bp->common_size = 0; bp->warning = 0; bp->undef_refs = 0; - bp->multiply_defined = 0; + bp->mult_defs = 0; bp->alias = 0; bp->setv_count = 0; bp->symbolnum = 0; @@ -114,10 +125,7 @@ getsym(key) bp->def_nlist = 0; bp->jmpslot_offset = -1; bp->gotslot_offset = -1; - bp->jmpslot_claimed = 0; - bp->gotslot_claimed = 0; - bp->cpyreloc_reserved = 0; - bp->cpyreloc_claimed = 0; + bp->flags = 0; /* Add the entry to the bucket. */ bp->link = symtab[hashval]; @@ -139,7 +147,7 @@ getsym_soft (key) /* Determine which bucket. */ - hashval = hash_string (key) % TABSIZE; + hashval = hash_string (key) % SYMTABSIZE; /* Search the bucket. */ diff --git a/gnu/usr.bin/ld/warnings.c b/gnu/usr.bin/ld/warnings.c index 210be24477..d98516aa0b 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/12/22 23:28:12 jkh Exp $ + * $Id: warnings.c,v 1.5 1994/01/12 23:14:07 jkh Exp $ */ #include @@ -47,6 +47,10 @@ print_file_name (entry, outfile) struct file_entry *entry; FILE *outfile; { + if (entry == NULL) { + fprintf (outfile, "NULL"); + } + if (entry->superfile) { print_file_name (entry->superfile, outfile); fprintf (outfile, "(%s)", entry->filename); @@ -65,7 +69,7 @@ get_file_name (entry) char *result, *supfile; if (entry == NULL) { - return (xmalloc("NULL")); + return (char *)strdup("NULL"); } if (entry->superfile) { @@ -155,30 +159,24 @@ void print_symbols(outfile) FILE *outfile; { - register int i; - fprintf(outfile, "\nFiles:\n\n"); - each_file(describe_file_sections, outfile); fprintf(outfile, "\nGlobal symbols:\n\n"); - - for (i = 0; i < TABSIZE; i++) { - register symbol *sp; - for (sp = symtab[i]; sp; sp = sp->link) { - if (sp->defined == (N_UNDF|N_EXT)) - fprintf(outfile, " %s: common, length %#x\n", - sp->name, sp->max_common_size); - if (!sp->referenced) - fprintf(outfile, " %s: unreferenced\n", - sp->name); - else if (!sp->defined) - fprintf(outfile, " %s: undefined\n", sp->name); - else - fprintf(outfile, " %s: %#x, size %#x\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); + if (!(sp->flags & GS_REFERENCED)) + fprintf(outfile, " %s: unreferenced\n", sp->name); + else if (sp->so_defined) + fprintf(outfile, " %s: sodefined\n", 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); - } - } + } END_EACH_SYMBOL; each_file(list_file_locals, outfile); } @@ -190,7 +188,7 @@ describe_file_sections(entry, outfile) { fprintf(outfile, " "); print_file_name(entry, outfile); - if (entry->just_syms_flag || entry->is_dynamic) + if (entry->flags & (E_JUST_SYMS | E_DYNAMIC)) fprintf(outfile, " symbols only\n", 0); else fprintf(outfile, " text %x(%x), data %x(%x), bss %x(%x) hex\n", @@ -602,7 +600,7 @@ do_file_warnings (entry, outfile) read_entry_strings (desc, entry); } - if (! entry->is_dynamic) { + if (!(entry->flags & E_DYNAMIC)) { /* Do text warnings based on a scan through the relocation info. */ do_relocation_warnings (entry, 0, outfile, nlist_bitvector); @@ -618,7 +616,7 @@ do_file_warnings (entry, outfile) for (i = 0; i < number_of_syms; i++) { struct nlist *s; - struct glosym *g; + symbol *g; g = entry->symbols[i].symbol; s = &entry->symbols[i].nzlist.nlist; @@ -626,14 +624,14 @@ do_file_warnings (entry, outfile) if (!(s->n_type & N_EXT)) continue; - if (!g->referenced) { + if (!(g->flags & GS_REFERENCED)) { #if 0 /* Check for undefined shobj symbols */ struct localsymbol *lsp; register int type; - for (lsp = g->dynrefs; lsp; lsp = lsp->next) { - type = lsp->nlist.n_type; + for (lsp = g->sorefs; lsp; lsp = lsp->next) { + type = lsp->nzlist.nz_type; if ((type & N_EXT) && type != (N_UNDF | N_EXT)) { break; @@ -651,7 +649,7 @@ do_file_warnings (entry, outfile) dont_allow_symbol_name = 0; - if (list_multiple_defs && g->multiply_defined) { + if (list_multiple_defs && g->mult_defs) { errfmt = "Definition of symbol %s (multiply defined)"; switch (s->n_type) { @@ -669,13 +667,13 @@ do_file_warnings (entry, outfile) case N_SETT | N_EXT: case N_SETD | N_EXT: case N_SETB | N_EXT: - if (g->multiply_defined == 2) + if (g->mult_defs == 2) continue; errfmt = "First set element definition of symbol %s (multiply defined)"; break; default: -printf("Multiple def: %s, type %#x\n", g->name, s->n_type); +printf("multiply defined: %s, type %#x\n", g->name, s->n_type); /* Don't print out multiple defs at references.*/ continue; } diff --git a/gnu/usr.bin/ld/xbits.c b/gnu/usr.bin/ld/xbits.c index 4f85db143a..6374bebe23 100644 --- a/gnu/usr.bin/ld/xbits.c +++ b/gnu/usr.bin/ld/xbits.c @@ -14,7 +14,7 @@ * 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 + * derived from this software without 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 @@ -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: xbits.c,v 1.1 1993/10/16 21:52:37 pk Exp $ + * $Id: xbits.c,v 1.2 1993/11/09 04:19:08 paul Exp $ */ /* @@ -96,60 +96,61 @@ int n; } void -swap_link_dynamic(dp) -struct link_dynamic *dp; +swap__dynamic(dp) +struct _dynamic *dp; { - dp->ld_version = md_swap_long(dp->ld_version); - dp->ldd = (struct ld_debug *)md_swap_long((long)dp->ldd); - dp->ld_un.ld_2 = (struct link_dynamic_2 *)md_swap_long((long)dp->ld_un.ld_2); - dp->ld_entry = (struct ld_entry *)md_swap_long((long)dp->ld_entry); + dp->d_version = md_swap_long(dp->d_version); + dp->d_debug = (struct so_debug *)md_swap_long((long)dp->d_debug); + dp->d_un.d_sdt = (struct section_dispatch_table *) + md_swap_long((long)dp->d_un.d_sdt); + dp->d_entry = (struct ld_entry *)md_swap_long((long)dp->d_entry); } void -swap_link_dynamic_2(ldp) -struct link_dynamic_2 *ldp; +swap_section_dispatch_table(sdp) +struct section_dispatch_table *sdp; { - swap_longs((long *)ldp, sizeof(*ldp)/sizeof(long)); + swap_longs((long *)sdp, sizeof(*sdp)/sizeof(long)); } void -swap_ld_debug(lddp) -struct ld_debug *lddp; +swap_so_debug(ddp) +struct so_debug *ddp; { - swap_longs((long *)lddp, sizeof(*lddp)/sizeof(long)); + swap_longs((long *)ddp, sizeof(*ddp)/sizeof(long)); } void -swapin_link_object(lop, n) -struct link_object *lop; +swapin_sod(sodp, n) +struct sod *sodp; int n; { unsigned long bits; - for (; n; n--, lop++) { - lop->lo_name = md_swap_long(lop->lo_name); - lop->lo_major = md_swap_short(lop->lo_major); - lop->lo_minor = md_swap_short(lop->lo_minor); - lop->lo_next = md_swap_long(lop->lo_next); - bits = ((unsigned long *)lop)[1]; - lop->lo_library = ((bits >> 24) & 1); + for (; n; n--, sodp++) { + sodp->sod_name = md_swap_long(sodp->sod_name); + sodp->sod_major = md_swap_short(sodp->sod_major); + sodp->sod_minor = md_swap_short(sodp->sod_minor); + sodp->sod_next = md_swap_long(sodp->sod_next); + bits = ((unsigned long *)sodp)[1]; + sodp->sod_library = ((bits >> 24) & 1); } } void -swapout_link_object(lop, n) -struct link_object *lop; +swapout_sod(sodp, n) +struct sod *sodp; int n; { unsigned long bits; - for (; n; n--, lop++) { - lop->lo_name = md_swap_long(lop->lo_name); - lop->lo_major = md_swap_short(lop->lo_major); - lop->lo_minor = md_swap_short(lop->lo_minor); - lop->lo_next = md_swap_long(lop->lo_next); - bits = (unsigned long)(lop->lo_library) << 24; - ((unsigned long *)lop)[1] = bits; + for (; n; n--, sodp++) { + sodp->sod_name = md_swap_long(sodp->sod_name); + sodp->sod_major = md_swap_short(sodp->sod_major); + sodp->sod_minor = md_swap_short(sodp->sod_minor); + sodp->sod_next = md_swap_long(sodp->sod_next); + bits = (unsigned long)(sodp->sod_library) << 24; + ((unsigned long *)sodp)[1] = bits; } }