diff --git a/gnu/usr.bin/ld/etc.c b/gnu/usr.bin/ld/etc.c index 22fdfd8f1603..2ddd50a87b5c 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 2cd0768ea9bf..47416856e4e9 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 f78c6ccfb4e6..311a5f6d4cf2 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 7286a7412503..bbb28f221af7 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 06855d87d052..3295282b1dca 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.1aout b/gnu/usr.bin/ld/ld.1aout index 06855d87d052..3295282b1dca 100644 --- a/gnu/usr.bin/ld/ld.1aout +++ b/gnu/usr.bin/ld/ld.1aout @@ -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 ad6f9a6488f2..1d63c822050e 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 +/* 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; -int building_shared_object; - -/* 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. */ -/* Magic number to use for the output file, set by switch. */ -int magic; +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. */ + +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) - continue; - - if (SET_ELEMENT_P (type)) { - /* - * This occurs even if global. These types of - * symbols are never written globally, though - * they are stored globally. - */ - lsp->write = relocatable_output; - - } else if (!(type & (N_STAB | N_EXT))) { - - /* - * Ordinary local symbol - */ - lsp->write = (lsp->rename || ( - discard_locals != DISCARD_ALL && - !(discard_locals == DISCARD_L && - lsp->is_L_symbol))); - if (lsp->write) - local_sym_count++; - - } else if (!(type & N_EXT)) { - - /* - * Debugger symbol - */ - lsp->write = (strip_symbols == STRIP_NONE); - if (lsp->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++; - } - -/* Write the output file */ +/* + * 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 (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, *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; + + /* + * 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; + + 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); + } + } + + /* + * Reverse the vector. + */ + 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; + } + + + 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 */ 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 1cee37a04b2e..a43eac8739ba 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; + 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. */ - /* - * For symbols of type N_INDR, this points at the real symbol. - */ - struct glosym *alias; + 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 */ - /* - * Count number of elements in set vector if symbol is of type N_SETV - */ - int setv_count; + struct nlist *def_nlist; /* The local symbol that gave this + global symbol its definition */ - /* 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; + 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; +/* # of global symbols referenced and not defined. */ +extern int undefined_global_sym_count; -/* Count number of nlist entries for global symbols */ -int global_sym_count; +/* # of undefined symbols referenced by shared objects */ +extern int undefined_shobj_sym_count; -/* Count number of N_SIZE nlist entries for output (relocatable_output only) */ -int size_sym_count; +/* # of multiply defined symbols. */ +extern int multiple_def_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; +/* # of common symbols. */ +extern int common_defined_global_count; -/* Count number of nlist entries that are for local symbols - whose names don't start with L. */ -int non_L_local_sym_count; +/* # of warning symbols encountered. */ +extern int warning_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. */ +/* + * 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; + char *str; + struct string_list_element *next; }; -struct string_list_element *set_element_prefixes; +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 */ -/* Count the number of warning symbols encountered. */ -int warning_count; - -/* 1 => write load map. */ -int write_map; - -/* 1 => write relocation into output file so can re-input it later. */ -int relocatable_output; - -/* Nonzero means ptr to symbol entry for symbol to use as start addr. - -e sets this. */ -symbol *entry_symbol; - -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 */ - - /* * 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) */ + /* + * Next two used only if `relocatable_output' or if needed for + * output of undefined reference line numbers. + */ + struct relocation_info *textrel; /* Text relocations */ + int ntextrel; /* # of text relocations */ + struct relocation_info *datarel; /* Data relocations */ + int ndatarel; /* # of data relocations */ /* - * 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. + * Relation of this file's segments to the output file. */ - 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; - - /* - * 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. - */ - 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 + int lib_major, lib_minor; /* Version numbers of a shared object */ - /* 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 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; +extern int soversion; +#ifndef DEFAULT_SOVERSION +#define DEFAULT_SOVERSION LD_VERSION_BSD +#endif -/* When loading the text and data, we can avoid doing a close - and another open between members of the same library. +extern int pc_relocation; /* Current PC reloc value */ - These two variables remember the file that is currently open. - Both are zero if no file is open. +extern int number_of_shobjs; /* # of shared objects linked in */ - See `each_file' and `file_close'. */ +/* 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 */ -struct file_entry *input_file; -int input_desc; +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; -/* The name of the file to write; "a.out" by default. */ +/* Size of a page. */ +extern int page_size; -char *output_filename; +extern char **search_dirs; /* Directories to search for libraries. */ +extern int n_search_dirs; /* Length of above. */ -/* Descriptor for writing that file with `mywrite'. */ +extern int write_map; /* write a load map (`-M') */ -int outdesc; +extern void (*fatal_cleanup_hook)__P((void)); -/* 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; - - -/* Record most of the command options. */ - -/* 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; - -/* Offset of default entry-pc within the text section. */ -int entry_offset; - -/* Address we decide the data section will be loaded at. */ -int data_start; -int bss_start; - -/* 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; - -/* - * Actual vector of directories to search; this contains those specified with - * -L plus the standard ones. - */ -char **search_dirs; - -/* Length of the vector `search_dirs'. */ -int n_search_dirs; - -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 d27f9b7eea17..f565cf1fa4bc 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 78439e5f669f..170b6183eb87 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 899539de21f8..fafe176dd34e 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 0c3b5e42d732..f5a6abadcf49 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 65b0bc176eed..7fba989b1631 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 eaa0f55d96e1..78d337e7319f 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) - continue; /* 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; + } + + /* + * 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 @@ struct file_entry *p; 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 6de17b9ba45f..6c042d956cdc 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 1a76c51aa76f..0fbf2b2006bc 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 e02fef6ea242..72ab49e732c2 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,352 +498,179 @@ struct link_map *lmp; 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; + (long)dp->d_un.d_sdt += (long)addr; - alloc_link_map(path, lop, lmp, addr, dp); + return alloc_link_map(path, sodp, smp, addr, dp); +} +static void inline +check_text_reloc(r, smp, addr) +struct relocation_info *r; +struct so_map *smp; +caddr_t addr; +{ + char *sym; + + if (addr >= LM_ETEXT(smp)) + return; + + if (RELOC_EXTERN_P(r)) + sym = LM_STRINGS(smp) + + LM_SYMBOL(smp, RELOC_SYMBOL(r))->nz_strx; + else + sym = ""; + + 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); + + if (smp->som_write == 0 && + mprotect(smp->som_addr + LM_TXTADDR(smp), + LD_TEXTSZ(smp->som_dynamic), + PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { + + perror("mprotect"), + fatal("Cannot enable writes to %s:%s\n", + main_progname, smp->som_path); + } + + smp->som_write = 1; } static void -reloc_maps() +reloc_map(smp) + struct so_map *smp; { - struct link_map *lmp; + 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); - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { + if (LD_PLTSZ(dp)) + md_fix_jmpslot(LM_PLT(smp), + (long)LM_PLT(smp), (long)binder_entry); - struct link_dynamic *dp = lmp->lm_ld; - struct relocation_info *r = LM_REL(lmp); - struct relocation_info *rend = r + LD_RELSZ(dp)/sizeof(*r); + for (; r < rend; r++) { + char *sym; + caddr_t addr = smp->som_addr + r->r_address; - if (LD_PLTSZ(dp)) - md_fix_jmpslot(LM_PLT(lmp), - (long)LM_PLT(lmp), (long)binder_entry); + check_text_reloc(r, smp, addr); - for (; r < rend; r++) { - char *sym; - caddr_t addr = lmp->lm_addr + r->r_address; + if (RELOC_EXTERN_P(r)) { + struct so_map *src_map = NULL; + struct nzlist *p, *np; + long relocation = md_get_addend(r, addr); - check_text_reloc(r, lmp, addr); + if (RELOC_LAZY_P(r)) + continue; - if (RELOC_EXTERN_P(r)) { - struct link_map *src_map = NULL; - struct nzlist *p, *np; - long relocation = md_get_addend(r, addr); + p = (struct nzlist *) + (symbolbase + symsize * RELOC_SYMBOL(r)); - if (RELOC_LAZY_P(r)) - continue; + if (p->nz_type == (N_SETV + N_EXT)) + src_map = smp; - p = LM_SYMBOL(lmp,RELOC_SYMBOL(r)); - if (p->nz_type == (N_SETV + N_EXT)) - src_map = lmp; + sym = stringbase + p->nz_strx; - sym = LM_STRINGS(lmp) + 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); - np = lookup(sym, &src_map, 0/*XXX-jumpslots!*/); - if (np == NULL) - fatal("Undefined symbol \"%s\" in %s\n", - sym, lmp->lm_name); + /* + * 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; - /* - * 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; + if (RELOC_PCREL_P(r)) + relocation -= (long)smp->som_addr; - if (RELOC_PCREL_P(r)) - relocation -= (long)lmp->lm_addr; - - 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); - - } 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, -#ifdef SUN_COMPAT - md_get_rt_segment_addend(r, addr) -#else - md_get_addend(r, addr) -#endif - + (long)lmp->lm_addr, addr, 0); + 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 { + md_relocate(r, +#ifdef SUN_COMPAT + md_get_rt_segment_addend(r, addr) +#else + md_get_addend(r, addr) +#endif + + (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; - - if (addr >= LM_ETEXT(lmp)) - return; - - if (RELOC_EXTERN_P(r)) - sym = LM_STRINGS(lmp) + - LM_SYMBOL(lmp, RELOC_SYMBOL(r))->nz_strx; - else - sym = ""; - -#ifdef DEBUG - fprintf(stderr, "ld.so: warning: non pure code in %s at %x (%s)\n", - lmp->lm_name, r->r_address, sym); -#endif - - if (lmp->lm_rwt == 0 && - mprotect(lmp->lm_addr + LM_TXTADDR(lmp), - LD_TEXTSZ(lmp->lm_ld), - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - - perror("mprotect"), - fatal("Cannot enable writes to %s\n", lmp->lm_name); - } - - lmp->lm_rwt = 1; -} - -static void -init_maps() -{ - struct link_map *lmp, *src_map; + struct so_map *src_map = smp; struct nzlist *np; - void (*func)(); - - 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)(); - } - } -} - -/* - * 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 * -lookup(name, src_map, strong) -char *name; -struct link_map **src_map; /* IN/OUT */ -int strong; -{ - long common_size = 0; - struct link_map *lmp; - struct rt_symbol *rtsp; - - if ((rtsp = lookup_rts(name)) != NULL) - return rtsp->rt_sp; - - /* - * 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); - long hashval = 0; - struct rrs_hash *hp; - char *cp; - struct nzlist *np; - - if (*src_map && lmp != *src_map) - continue; - - /* - * Compute bucket in which the symbol might be found. - */ - for (cp = name; *cp; cp++) - hashval = (hashval << 1) + *cp; - - hashval = (hashval & 0x7fffffff) % buckets; - - hp = LM_HASH(lmp) + hashval; - if (hp->rh_symbolnum == -1) - /* Nothing in this bucket */ - continue; - - while (hp) { - np = LM_SYMBOL(lmp, hp->rh_symbolnum); - cp = LM_STRINGS(lmp) + np->nz_strx; - if (strcmp(cp, name) == 0) - break; - if (hp->rh_next == 0) - hp = NULL; - else - hp = LM_HASH(lmp) + hp->rh_next; - } - if (hp == NULL) - /* Nothing in this bucket */ - continue; - - /* - * We have a symbol with the name we're looking for. - */ - - if (np->nz_value == 0) - /* It's not a definition */ - continue; - - if (np->nz_type == N_UNDF+N_EXT && np->nz_value != 0) { - if (np->nz_other == RRS_FUNC) { - /* It's a weak function definition */ - if (strong) - continue; - } else { - /* It's a common, note value and continue search */ - if (common_size < np->nz_value) - common_size = np->nz_value; - continue; - } - } - - *src_map = lmp; - return np; - } - - if (common_size == 0) - /* Not found */ - return NULL; - - /* - * 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); - -#if DEBUG -xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value); -#endif - - return rtsp->rt_sp; -} - - -/* - * This routine is called from the jumptable to resolve - * procedure calls to shared objects. - */ -long -binder(jsp) -jmpslot_t *jsp; -{ - struct link_map *lmp, *src_map = NULL; - long addr; - char *sym; - struct nzlist *np; - int index; - - /* - * 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)) - break; - } - - if (lmp == 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; np = lookup(sym, &src_map, 1); - if (np == NULL) - fatal("Undefined symbol \"%s\" called from %s at %#x", sym, - lmp->lm_name, jsp); - - /* Fixup jmpslot so future calls transfer directly to target */ - addr = np->nz_value; - if (src_map) - addr += (long)src_map->lm_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); -#endif - return addr; + if (np) + (*(void (*)())(src_map->som_addr + np->nz_value))(); } - /* * Run-time common symbol table. */ @@ -755,7 +681,7 @@ static struct rt_symbol *rt_symtab[RTC_TABSIZE]; /* * Compute hash value for run-time symbol table */ -static int + static int inline hash_string(key) char *key; { @@ -774,7 +700,7 @@ hash_string(key) * Lookup KEY in the run-time common symbol table. */ -static struct rt_symbol * + static inline struct rt_symbol * lookup_rts(key) char *key; { @@ -794,13 +720,14 @@ lookup_rts(key) return NULL; } -static struct rt_symbol * -enter_rts(name, value, type, srcaddr, size) - char *name; - long value; - int type; - caddr_t srcaddr; - long size; + 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; @@ -820,6 +747,7 @@ enter_rts(name, value, type, srcaddr, size) 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 */ @@ -831,13 +759,183 @@ enter_rts(name, value, type, srcaddr, size) 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 * +lookup(name, src_map, strong) + char *name; + struct so_map **src_map; /* IN/OUT */ + int strong; +{ + long common_size = 0; + struct so_map *smp; + struct rt_symbol *rtsp; + + if ((rtsp = lookup_rts(name)) != NULL) + return rtsp->rt_sp; + + /* + * Search all maps for a definition of NAME + */ + for (smp = link_map_head; smp; smp = smp->som_next) { + int buckets = LD_BUCKETS(smp->som_dynamic); + long hashval = 0; + struct rrs_hash *hp; + char *cp; + struct nzlist *np; + + /* 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; + + /* + * Compute bucket in which the symbol might be found. + */ + for (cp = name; *cp; cp++) + hashval = (hashval << 1) + *cp; + + hashval = (hashval & 0x7fffffff) % buckets; + + 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 = (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 = hashbase + hp->rh_next; + } + if (hp == NULL) + /* Nothing in this bucket */ + continue; + + /* + * We have a symbol with the name we're looking for. + */ + + if (np->nz_value == 0) + /* It's not a definition */ + continue; + + if (np->nz_type == N_UNDF+N_EXT && np->nz_value != 0) { + if (np->nz_other == AUX_FUNC) { + /* It's a weak function definition */ + if (strong) + continue; + } else { + /* It's a common, note value and continue search */ + if (common_size < np->nz_value) + common_size = np->nz_value; + continue; + } + } + + *src_map = smp; + return np; + } + + if (common_size == 0) + /* Not found */ + return NULL; + + /* + * 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, NULL); + +#if DEBUG +xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value); +#endif + + return rtsp->rt_sp; +} + + +/* + * This routine is called from the jumptable to resolve + * procedure calls to shared objects. + */ + long +binder(jsp) + jmpslot_t *jsp; +{ + struct so_map *smp, *src_map = NULL; + long addr; + char *sym; + struct nzlist *np; + int index; + + /* + * Find the PLT map that contains 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 (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(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:%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->som_addr; + + md_fix_jmpslot(jsp, (long)jsp, addr); + +#if DEBUG +xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr, src_map->som_path); +#endif + return addr; +} + + 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 0bfc373ad33f..38ec051ab2e7 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 3ae54e30e9ab..15281cc37c79 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 c3e9064085e7..3545d97d92d8 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 8ad60b0571b1..0d006d0c0dac 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 d789a3a54bb6..af182a9dc802 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 210be2447760..d98516aa0b7b 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 4f85db143a68..6374bebe23c5 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; } } diff --git a/libexec/rtld-aout/Makefile b/libexec/rtld-aout/Makefile index 1a76c51aa76f..0fbf2b2006bc 100644 --- a/libexec/rtld-aout/Makefile +++ b/libexec/rtld-aout/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/libexec/rtld-aout/i386/md-static-funcs.c b/libexec/rtld-aout/i386/md-static-funcs.c index 2cd0768ea9bf..47416856e4e9 100644 --- a/libexec/rtld-aout/i386/md-static-funcs.c +++ b/libexec/rtld-aout/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/libexec/rtld-aout/i386/md.c b/libexec/rtld-aout/i386/md.c index f78c6ccfb4e6..311a5f6d4cf2 100644 --- a/libexec/rtld-aout/i386/md.c +++ b/libexec/rtld-aout/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/libexec/rtld-aout/i386/md.h b/libexec/rtld-aout/i386/md.h index 7286a7412503..bbb28f221af7 100644 --- a/libexec/rtld-aout/i386/md.h +++ b/libexec/rtld-aout/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/libexec/rtld-aout/rtld.c b/libexec/rtld-aout/rtld.c index e02fef6ea242..72ab49e732c2 100644 --- a/libexec/rtld-aout/rtld.c +++ b/libexec/rtld-aout/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,352 +498,179 @@ struct link_map *lmp; 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; + (long)dp->d_un.d_sdt += (long)addr; - alloc_link_map(path, lop, lmp, addr, dp); + return alloc_link_map(path, sodp, smp, addr, dp); +} +static void inline +check_text_reloc(r, smp, addr) +struct relocation_info *r; +struct so_map *smp; +caddr_t addr; +{ + char *sym; + + if (addr >= LM_ETEXT(smp)) + return; + + if (RELOC_EXTERN_P(r)) + sym = LM_STRINGS(smp) + + LM_SYMBOL(smp, RELOC_SYMBOL(r))->nz_strx; + else + sym = ""; + + 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); + + if (smp->som_write == 0 && + mprotect(smp->som_addr + LM_TXTADDR(smp), + LD_TEXTSZ(smp->som_dynamic), + PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { + + perror("mprotect"), + fatal("Cannot enable writes to %s:%s\n", + main_progname, smp->som_path); + } + + smp->som_write = 1; } static void -reloc_maps() +reloc_map(smp) + struct so_map *smp; { - struct link_map *lmp; + 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); - for (lmp = link_map_head; lmp; lmp = lmp->lm_next) { + if (LD_PLTSZ(dp)) + md_fix_jmpslot(LM_PLT(smp), + (long)LM_PLT(smp), (long)binder_entry); - struct link_dynamic *dp = lmp->lm_ld; - struct relocation_info *r = LM_REL(lmp); - struct relocation_info *rend = r + LD_RELSZ(dp)/sizeof(*r); + for (; r < rend; r++) { + char *sym; + caddr_t addr = smp->som_addr + r->r_address; - if (LD_PLTSZ(dp)) - md_fix_jmpslot(LM_PLT(lmp), - (long)LM_PLT(lmp), (long)binder_entry); + check_text_reloc(r, smp, addr); - for (; r < rend; r++) { - char *sym; - caddr_t addr = lmp->lm_addr + r->r_address; + if (RELOC_EXTERN_P(r)) { + struct so_map *src_map = NULL; + struct nzlist *p, *np; + long relocation = md_get_addend(r, addr); - check_text_reloc(r, lmp, addr); + if (RELOC_LAZY_P(r)) + continue; - if (RELOC_EXTERN_P(r)) { - struct link_map *src_map = NULL; - struct nzlist *p, *np; - long relocation = md_get_addend(r, addr); + p = (struct nzlist *) + (symbolbase + symsize * RELOC_SYMBOL(r)); - if (RELOC_LAZY_P(r)) - continue; + if (p->nz_type == (N_SETV + N_EXT)) + src_map = smp; - p = LM_SYMBOL(lmp,RELOC_SYMBOL(r)); - if (p->nz_type == (N_SETV + N_EXT)) - src_map = lmp; + sym = stringbase + p->nz_strx; - sym = LM_STRINGS(lmp) + 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); - np = lookup(sym, &src_map, 0/*XXX-jumpslots!*/); - if (np == NULL) - fatal("Undefined symbol \"%s\" in %s\n", - sym, lmp->lm_name); + /* + * 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; - /* - * 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; + if (RELOC_PCREL_P(r)) + relocation -= (long)smp->som_addr; - if (RELOC_PCREL_P(r)) - relocation -= (long)lmp->lm_addr; - - 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); - - } 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, -#ifdef SUN_COMPAT - md_get_rt_segment_addend(r, addr) -#else - md_get_addend(r, addr) -#endif - + (long)lmp->lm_addr, addr, 0); + 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 { + md_relocate(r, +#ifdef SUN_COMPAT + md_get_rt_segment_addend(r, addr) +#else + md_get_addend(r, addr) +#endif + + (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; - - if (addr >= LM_ETEXT(lmp)) - return; - - if (RELOC_EXTERN_P(r)) - sym = LM_STRINGS(lmp) + - LM_SYMBOL(lmp, RELOC_SYMBOL(r))->nz_strx; - else - sym = ""; - -#ifdef DEBUG - fprintf(stderr, "ld.so: warning: non pure code in %s at %x (%s)\n", - lmp->lm_name, r->r_address, sym); -#endif - - if (lmp->lm_rwt == 0 && - mprotect(lmp->lm_addr + LM_TXTADDR(lmp), - LD_TEXTSZ(lmp->lm_ld), - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - - perror("mprotect"), - fatal("Cannot enable writes to %s\n", lmp->lm_name); - } - - lmp->lm_rwt = 1; -} - -static void -init_maps() -{ - struct link_map *lmp, *src_map; + struct so_map *src_map = smp; struct nzlist *np; - void (*func)(); - - 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)(); - } - } -} - -/* - * 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 * -lookup(name, src_map, strong) -char *name; -struct link_map **src_map; /* IN/OUT */ -int strong; -{ - long common_size = 0; - struct link_map *lmp; - struct rt_symbol *rtsp; - - if ((rtsp = lookup_rts(name)) != NULL) - return rtsp->rt_sp; - - /* - * 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); - long hashval = 0; - struct rrs_hash *hp; - char *cp; - struct nzlist *np; - - if (*src_map && lmp != *src_map) - continue; - - /* - * Compute bucket in which the symbol might be found. - */ - for (cp = name; *cp; cp++) - hashval = (hashval << 1) + *cp; - - hashval = (hashval & 0x7fffffff) % buckets; - - hp = LM_HASH(lmp) + hashval; - if (hp->rh_symbolnum == -1) - /* Nothing in this bucket */ - continue; - - while (hp) { - np = LM_SYMBOL(lmp, hp->rh_symbolnum); - cp = LM_STRINGS(lmp) + np->nz_strx; - if (strcmp(cp, name) == 0) - break; - if (hp->rh_next == 0) - hp = NULL; - else - hp = LM_HASH(lmp) + hp->rh_next; - } - if (hp == NULL) - /* Nothing in this bucket */ - continue; - - /* - * We have a symbol with the name we're looking for. - */ - - if (np->nz_value == 0) - /* It's not a definition */ - continue; - - if (np->nz_type == N_UNDF+N_EXT && np->nz_value != 0) { - if (np->nz_other == RRS_FUNC) { - /* It's a weak function definition */ - if (strong) - continue; - } else { - /* It's a common, note value and continue search */ - if (common_size < np->nz_value) - common_size = np->nz_value; - continue; - } - } - - *src_map = lmp; - return np; - } - - if (common_size == 0) - /* Not found */ - return NULL; - - /* - * 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); - -#if DEBUG -xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value); -#endif - - return rtsp->rt_sp; -} - - -/* - * This routine is called from the jumptable to resolve - * procedure calls to shared objects. - */ -long -binder(jsp) -jmpslot_t *jsp; -{ - struct link_map *lmp, *src_map = NULL; - long addr; - char *sym; - struct nzlist *np; - int index; - - /* - * 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)) - break; - } - - if (lmp == 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; np = lookup(sym, &src_map, 1); - if (np == NULL) - fatal("Undefined symbol \"%s\" called from %s at %#x", sym, - lmp->lm_name, jsp); - - /* Fixup jmpslot so future calls transfer directly to target */ - addr = np->nz_value; - if (src_map) - addr += (long)src_map->lm_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); -#endif - return addr; + if (np) + (*(void (*)())(src_map->som_addr + np->nz_value))(); } - /* * Run-time common symbol table. */ @@ -755,7 +681,7 @@ static struct rt_symbol *rt_symtab[RTC_TABSIZE]; /* * Compute hash value for run-time symbol table */ -static int + static int inline hash_string(key) char *key; { @@ -774,7 +700,7 @@ hash_string(key) * Lookup KEY in the run-time common symbol table. */ -static struct rt_symbol * + static inline struct rt_symbol * lookup_rts(key) char *key; { @@ -794,13 +720,14 @@ lookup_rts(key) return NULL; } -static struct rt_symbol * -enter_rts(name, value, type, srcaddr, size) - char *name; - long value; - int type; - caddr_t srcaddr; - long size; + 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; @@ -820,6 +747,7 @@ enter_rts(name, value, type, srcaddr, size) 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 */ @@ -831,13 +759,183 @@ enter_rts(name, value, type, srcaddr, size) 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 * +lookup(name, src_map, strong) + char *name; + struct so_map **src_map; /* IN/OUT */ + int strong; +{ + long common_size = 0; + struct so_map *smp; + struct rt_symbol *rtsp; + + if ((rtsp = lookup_rts(name)) != NULL) + return rtsp->rt_sp; + + /* + * Search all maps for a definition of NAME + */ + for (smp = link_map_head; smp; smp = smp->som_next) { + int buckets = LD_BUCKETS(smp->som_dynamic); + long hashval = 0; + struct rrs_hash *hp; + char *cp; + struct nzlist *np; + + /* 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; + + /* + * Compute bucket in which the symbol might be found. + */ + for (cp = name; *cp; cp++) + hashval = (hashval << 1) + *cp; + + hashval = (hashval & 0x7fffffff) % buckets; + + 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 = (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 = hashbase + hp->rh_next; + } + if (hp == NULL) + /* Nothing in this bucket */ + continue; + + /* + * We have a symbol with the name we're looking for. + */ + + if (np->nz_value == 0) + /* It's not a definition */ + continue; + + if (np->nz_type == N_UNDF+N_EXT && np->nz_value != 0) { + if (np->nz_other == AUX_FUNC) { + /* It's a weak function definition */ + if (strong) + continue; + } else { + /* It's a common, note value and continue search */ + if (common_size < np->nz_value) + common_size = np->nz_value; + continue; + } + } + + *src_map = smp; + return np; + } + + if (common_size == 0) + /* Not found */ + return NULL; + + /* + * 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, NULL); + +#if DEBUG +xprintf("Allocating common: %s size %d at %#x\n", name, common_size, rtsp->rt_sp->nz_value); +#endif + + return rtsp->rt_sp; +} + + +/* + * This routine is called from the jumptable to resolve + * procedure calls to shared objects. + */ + long +binder(jsp) + jmpslot_t *jsp; +{ + struct so_map *smp, *src_map = NULL; + long addr; + char *sym; + struct nzlist *np; + int index; + + /* + * Find the PLT map that contains 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 (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(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:%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->som_addr; + + md_fix_jmpslot(jsp, (long)jsp, addr); + +#if DEBUG +xprintf(" BINDER: %s located at = %#x in %s\n", sym, addr, src_map->som_path); +#endif + return addr; +} + + 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/libexec/rtld-aout/shlib.c b/libexec/rtld-aout/shlib.c index 0bfc373ad33f..38ec051ab2e7 100644 --- a/libexec/rtld-aout/shlib.c +++ b/libexec/rtld-aout/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/sbin/ldconfig/Makefile b/sbin/ldconfig/Makefile index d27f9b7eea17..f565cf1fa4bc 100644 --- a/sbin/ldconfig/Makefile +++ b/sbin/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/sbin/ldconfig/ldconfig.8 b/sbin/ldconfig/ldconfig.8 index 78439e5f669f..170b6183eb87 100644 --- a/sbin/ldconfig/ldconfig.8 +++ b/sbin/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/sbin/ldconfig/ldconfig.c b/sbin/ldconfig/ldconfig.c index 899539de21f8..fafe176dd34e 100644 --- a/sbin/ldconfig/ldconfig.c +++ b/sbin/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/usr.bin/ldd/ldd.1 b/usr.bin/ldd/ldd.1 index 0c3b5e42d732..f5a6abadcf49 100644 --- a/usr.bin/ldd/ldd.1 +++ b/usr.bin/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/usr.bin/ldd/ldd.c b/usr.bin/ldd/ldd.c index 65b0bc176eed..7fba989b1631 100644 --- a/usr.bin/ldd/ldd.c +++ b/usr.bin/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: