From 8af8fbaa5847be92efb3b7a8a5ffab367878585d Mon Sep 17 00:00:00 2001 From: trhodes Date: Tue, 11 Jan 2005 06:15:19 +0000 Subject: Remove a.out runtime linker. It doesn't build and was removed from the build over two years ago by peter. The binary a.out version of ld.so can be obtained from misc/compat22 or src/lib/compat/compat22. Discussed on: -arch Voted yes: jhb, ru, linimon, delphij --- libexec/rtld-aout/Makefile | 18 - libexec/rtld-aout/dynamic.h | 380 ----- libexec/rtld-aout/i386/md-static-funcs.c | 17 - libexec/rtld-aout/i386/md.c | 384 ----- libexec/rtld-aout/i386/md.h | 245 --- libexec/rtld-aout/i386/mdprologue.S | 93 -- libexec/rtld-aout/md-prologue.c | 39 - libexec/rtld-aout/rtld.1aout | 226 --- libexec/rtld-aout/rtld.c | 2550 ------------------------------ libexec/rtld-aout/shlib.c | 340 ---- libexec/rtld-aout/shlib.h | 43 - libexec/rtld-aout/support.c | 86 - libexec/rtld-aout/support.h | 35 - 13 files changed, 4456 deletions(-) delete mode 100644 libexec/rtld-aout/Makefile delete mode 100644 libexec/rtld-aout/dynamic.h delete mode 100644 libexec/rtld-aout/i386/md-static-funcs.c delete mode 100644 libexec/rtld-aout/i386/md.c delete mode 100644 libexec/rtld-aout/i386/md.h delete mode 100644 libexec/rtld-aout/i386/mdprologue.S delete mode 100644 libexec/rtld-aout/md-prologue.c delete mode 100644 libexec/rtld-aout/rtld.1aout delete mode 100644 libexec/rtld-aout/rtld.c delete mode 100644 libexec/rtld-aout/shlib.c delete mode 100644 libexec/rtld-aout/shlib.h delete mode 100644 libexec/rtld-aout/support.c delete mode 100644 libexec/rtld-aout/support.h diff --git a/libexec/rtld-aout/Makefile b/libexec/rtld-aout/Makefile deleted file mode 100644 index 9aa7d74..0000000 --- a/libexec/rtld-aout/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# $FreeBSD$ -PROG= ld.so -SRCS= mdprologue.S rtld.c shlib.c md.c support.c -MAN= rtld.1aout -# As there is relocation going on behind GCC's back, don't cache function addresses. -PICFLAG=-fpic -fno-function-cse -CFLAGS+=-I${.CURDIR} -I${.CURDIR}/${MACHINE_ARCH} ${PICFLAG} -DRTLD -Wall -LDFLAGS+=-nostdlib -Wl,-Bshareable,-Bsymbolic,-assert,nosymbolic -ASFLAGS+=-k -DPADD+= ${LIBC:S/c.a/c_pic.a/} ${LIBC:S/c.a/gcc_pic.a/} -LDADD+= -lc_pic -lgcc_pic -INSTALLFLAGS= -C # -C to install as atomically as possible -PRECIOUSPROG= -MLINKS= rtld.1aout ld.so.1aout - -.PATH: ${.CURDIR}/${MACHINE_ARCH} - -.include diff --git a/libexec/rtld-aout/dynamic.h b/libexec/rtld-aout/dynamic.h deleted file mode 100644 index 3c8bacd..0000000 --- a/libexec/rtld-aout/dynamic.h +++ /dev/null @@ -1,380 +0,0 @@ -/* - * 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. - * - * $FreeBSD$ - */ - -#ifndef __DYNAMIC_H__ -#define __DYNAMIC_H__ - -#define SUN_COMPAT - -#include "md.h" -#include "link.h" - -#ifndef RELOC_JMPTAB_P - -#define RELOC_JMPTAB_P(r) ((r)->r_jmptable) -#define RELOC_BASEREL_P(r) ((r)->r_baserel) -#define RELOC_RELATIVE_P(r) ((r)->r_relative) -#define RELOC_COPY_P(r) ((r)->r_copy) -#define RELOC_LAZY_P(r) ((r)->r_jmptable) - -#define CHECK_GOT_RELOC(r) ((r)->r_pcrel) -#define RELOC_PIC_TYPE(r) ((r)->r_baserel? \ - PIC_TYPE_LARGE:PIC_TYPE_NONE) -#endif - -#ifndef RELOC_INIT_SEGMENT_RELOC -#define RELOC_INIT_SEGMENT_RELOC(r) -#endif - -#ifndef MAX_GOTOFF -#define MAX_GOTOFF(x) (LONG_MAX) -#endif - -#ifndef MIN_GOTOFF -#define MIN_GOTOFF(x) (LONG_MIN) -#endif - -/* - * Internal representation of relocation types - */ -#define RELTYPE_EXTERN 1 -#define RELTYPE_JMPSLOT 2 -#define RELTYPE_BASEREL 4 -#define RELTYPE_RELATIVE 8 -#define RELTYPE_COPY 16 - -#define N_ISWEAK(p) (N_BIND(p) & BIND_WEAK) - -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_HASGOTSLOT 8 /* This symbol has a GOT entry */ -#define LS_WARNING 16 /* Second part of a N_WARNING duo */ -} localsymbol_t; - -/* - * Global symbol data is recorded in these structures, one for each global - * symbol. They are found via hashing in 'symtab', which points to a vector - * of buckets. Each bucket is a chain of these structures through the link - * field. - * - * Rewritten version to support extra info for dynamic linking. - */ - -struct glosym { - struct glosym *link; /* Next symbol hash bucket. */ - char *name; /* Name of this symbol. */ - long value; /* Value of this symbol */ - localsymbol_t *refs; /* Chain of local symbols from object - files pertaining to this global - symbol */ - localsymbol_t *sorefs;/* Same for local symbols from shared - object files. */ - - char *warning; /* message, from N_WARNING nlists */ - int common_size; /* Common size */ - int symbolnum; /* Symbol index in output symbol table */ - int rrs_symbolnum; /* Symbol index in RRS symbol table */ - - localsymbol_t *def_lsp; /* The local symbol that gave this - global symbol its definition */ - - char defined; /* Definition of this symbol */ - char so_defined; /* Definition of this symbol in a shared - object. These go into the RRS symbol table */ - u_char undef_refs; /* Count of number of "undefined" - messages printed for this symbol */ - u_char mult_defs; /* Same for "multiply defined" symbols */ - struct glosym *alias; /* For symbols of type N_INDR, this - points at the real symbol. */ - int setv_count; /* Number of elements in N_SETV symbols */ - int size; /* Size of this symbol (either from N_SIZE - symbols or a from shared object's RRS */ - int aux; /* Auxiliary type information conveyed in - the `n_other' field of nlists */ - - /* The offset into one of the RRS tables, -1 if not used */ - long jmpslot_offset; - long gotslot_offset; - - long flags; - -#define GS_DEFINED 0x1 /* Symbol has definition (notyetused)*/ -#define GS_REFERENCED 0x2 /* Symbol is referred to by something - interesting */ -#define GS_TRACE 0x4 /* Symbol will be traced */ -#define GS_HASJMPSLOT 0x8 /* */ -#define GS_HASGOTSLOT 0x10 /* Some state bits concerning */ -#define GS_CPYRELOCRESERVED 0x20 /* entries in GOT and PLT tables */ -#define GS_CPYRELOCCLAIMED 0x40 /* */ -#define GS_WEAK 0x80 /* Symbol is weakly defined */ - -}; -#ifndef __symbol_defined__ -#define __symbol_defined__ -typedef struct glosym symbol; -#endif - -/* 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 < SYMTABSIZE; i++) { \ - register symbol *sp; \ - for (sp = symtab[i]; sp; sp = sp->link) - -#define END_EACH_SYMBOL }} - -extern symbol *got_symbol; /* the symbol __GLOBAL_OFFSET_TABLE_ */ -extern symbol *dynamic_symbol; /* the symbol __DYNAMIC */ - -/* - * Each input file, and each library member ("subfile") being loaded, has a - * `file_entry' structure for it. - * - * For files specified by command args, these are contained in the vector which - * `file_table' points to. - * - * For library members, they are dynamically allocated, and chained through the - * `chain' field. The chain is found in the `subfiles' field of the - * `file_entry'. The `file_entry' objects for the members have `superfile' - * fields pointing to the one for the library. - * - * Rewritten version to support extra info for dynamic linking. - */ - -struct file_entry { - 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; - 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 */ - - /* - * Relation of this file's segments to the output file. - */ - 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 - 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 */ - - int flags; -#define E_IS_LIBRARY 1 /* File is 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 */ -#define E_SECONDCLASS 0x100 /* Shared object is a subsidiary */ -}; - -/* - * Runtime Relocation Section (RRS). - * This describes the data structures that go into the output text and data - * segments to support the run-time linker. The RRS can be empty (plain old - * static linking), or can just exist of GOT and PLT entries (in case of - * statically linked PIC code). - */ -extern int rrs_section_type; /* What's in the RRS section */ -#define RRS_NONE 0 -#define RRS_PARTIAL 1 -#define RRS_FULL 2 -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 */ -extern char *rrs_search_paths; /* `-L' RT paths */ - -/* Version number to put in __DYNAMIC (set by -V) */ -extern int soversion; -#ifndef DEFAULT_SOVERSION -#define DEFAULT_SOVERSION LD_VERSION_BSD -#endif - -extern int pc_relocation; /* Current PC reloc value */ - -extern int number_of_shobjs; /* # of shared objects linked in */ - -/* 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 */ -#define FORCEDYNAMIC 32 /* Force dynamic output even if no - shared libraries included */ -#define WARNRRSTEXT 64 /* Warn about rrs in text */ - -extern FILE *outstream; /* Output file. */ -extern struct exec outheader; /* Output file header. */ -extern int magic; /* Output file magic. */ -extern int oldmagic; -extern int relocatable_output; -extern int pic_type; -#define PIC_TYPE_NONE 0 -#define PIC_TYPE_SMALL 1 -#define PIC_TYPE_LARGE 2 - -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 *)); -int set_element_prefixed_p __P((char *)); -int text_offset __P((struct file_entry *)); -int file_open __P((struct file_entry *)); -void each_file __P((void (*)(), void *)); -void each_full_file __P((void (*)(), void *)); -unsigned long check_each_file __P((unsigned long (*)(), void *)); -void mywrite __P((void *, int, int, FILE *)); -void padfile __P((int, FILE *)); - -/* In warnings.c: */ -void perror_name __P((char *)); -void perror_file __P((struct file_entry *)); -void print_symbols __P((FILE *)); -char *get_file_name __P((struct file_entry *)); -void print_file_name __P((struct file_entry *, FILE *)); -void prline_file_name __P((struct file_entry *, FILE *)); -int do_warnings __P((FILE *)); - -/* In etc.c: */ -#include "support.h" - -/* In symbol.c: */ -void symtab_init __P((int)); -symbol *getsym __P((char *)), *getsym_soft __P((char *)); - -/* In lib.c: */ -void search_library __P((int, struct file_entry *)); -void read_shared_object __P((int, struct file_entry *)); -int findlib __P((struct file_entry *)); - -/* In shlib.c: */ -#include "shlib.h" - -/* In rrs.c: */ -void init_rrs __P((void)); -int rrs_add_shobj __P((struct file_entry *)); -void alloc_rrs_reloc __P((struct file_entry *, symbol *)); -void alloc_rrs_segment_reloc __P((struct file_entry *, struct relocation_info *)); -void alloc_rrs_jmpslot __P((struct file_entry *, symbol *)); -void alloc_rrs_gotslot __P((struct file_entry *, struct relocation_info *, localsymbol_t *)); -void alloc_rrs_cpy_reloc __P((struct file_entry *, symbol *)); - -int claim_rrs_reloc __P((struct file_entry *, struct relocation_info *, symbol *, long *)); -long claim_rrs_jmpslot __P((struct file_entry *, struct relocation_info *, symbol *, long)); -long claim_rrs_gotslot __P((struct file_entry *, struct relocation_info *, struct localsymbol *, long)); -long claim_rrs_internal_gotslot __P((struct file_entry *, struct relocation_info *, struct localsymbol *, long)); -void claim_rrs_cpy_reloc __P((struct file_entry *, struct relocation_info *, symbol *)); -void claim_rrs_segment_reloc __P((struct file_entry *, struct relocation_info *)); -void consider_rrs_section_lengths __P((void)); -void relocate_rrs_addresses __P((void)); -void write_rrs __P((void)); - -/* In .c */ -void md_init_header __P((struct exec *, int, int)); -long md_get_addend __P((struct relocation_info *, unsigned char *)); -void md_relocate __P((struct relocation_info *, long, unsigned char *, int)); -void md_make_jmpslot __P((jmpslot_t *, long, long)); -void md_fix_jmpslot __P((jmpslot_t *, long, u_long)); -int md_make_reloc __P((struct relocation_info *, struct relocation_info *, int)); -void md_make_jmpreloc __P((struct relocation_info *, struct relocation_info *, int)); -void md_make_gotreloc __P((struct relocation_info *, struct relocation_info *, int)); -void md_make_copyreloc __P((struct relocation_info *, struct relocation_info *)); -void md_set_breakpoint __P((long, long *)); - -#ifdef NEED_SWAP -/* In xbits.c: */ -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__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 - -#endif /* __DYNAMIC_H__ */ diff --git a/libexec/rtld-aout/i386/md-static-funcs.c b/libexec/rtld-aout/i386/md-static-funcs.c deleted file mode 100644 index 77c25c5..0000000 --- a/libexec/rtld-aout/i386/md-static-funcs.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * $FreeBSD$ - * - * 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; -long relocation; -char *addr; -{ - if (r->r_relative) - *(long *)addr += relocation; -} - diff --git a/libexec/rtld-aout/i386/md.c b/libexec/rtld-aout/i386/md.c deleted file mode 100644 index 63b9d17..0000000 --- a/libexec/rtld-aout/i386/md.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * 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. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dynamic.h" - -#if defined(RTLD) && defined(SUN_COMPAT) -#define REL_SIZE(r) (2) /* !!!!! Sun BUG compatible */ -#else -#define REL_SIZE(r) ((r)->r_length) -#endif - -/* - * Get relocation addend corresponding to relocation record RP - * from address ADDR - */ -long -md_get_addend(rp, addr) -struct relocation_info *rp; -unsigned char *addr; -{ - switch (REL_SIZE(rp)) { - case 0: - return get_byte(addr); - case 1: - return get_short(addr); - case 2: - return get_long(addr); - default: - errx(1, "Unsupported relocation size: %x", - REL_SIZE(rp)); - } -} - -/* - * Put RELOCATION at ADDR according to relocation record RP. - */ -void -md_relocate(rp, relocation, addr, relocatable_output) -struct relocation_info *rp; -long relocation; -unsigned char *addr; -int relocatable_output; -{ - switch (REL_SIZE(rp)) { - case 0: - put_byte(addr, relocation); - break; - case 1: - put_short(addr, relocation); - break; - case 2: - put_long(addr, relocation); - break; - default: - errx(1, "Unsupported relocation size: %x", - REL_SIZE(rp)); - } -} - -/* - * Machine dependent part of claim_rrs_reloc(). - * Set RRS relocation type. - */ -int -md_make_reloc(rp, r, type) -struct relocation_info *rp, *r; -int type; -{ - /* Relocation size */ - r->r_length = rp->r_length; - - if (rp->r_pcrel) - r->r_pcrel = 1; - - if (type & RELTYPE_RELATIVE) - r->r_relative = 1; - - if (type & RELTYPE_COPY) - r->r_copy = 1; - - return 0; -} - -/* - * Set up a transfer from jmpslot at OFFSET (relative to the PLT table) - * to the binder slot (which is at offset 0 of the PLT). - */ -void -md_make_jmpslot(sp, offset, index) -jmpslot_t *sp; -long offset; -long index; -{ - /* - * i386 PC-relative "fixed point" is located right after the - * instruction it pertains to. - */ - u_long fudge = - (sizeof(sp->opcode) + sizeof(sp->addr) + offset); - - sp->opcode = CALL; -#if 0 - sp->addr = fudge; -#else - sp->addr[0] = fudge & 0xffff; - sp->addr[1] = fudge >> 16; -#endif - sp->reloc_index = index; -} - -/* - * Set up a "direct" transfer (ie. not through the run-time binder) from - * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on, - * and by `ld.so' after resolving the symbol. - * On the i386, we use the JMP instruction which is PC relative, so no - * further RRS relocations will be necessary for such a jmpslot. - */ -void -md_fix_jmpslot(sp, offset, addr) -jmpslot_t *sp; -long offset; -u_long addr; -{ - u_long fudge = addr - (sizeof(sp->opcode) + sizeof(sp->addr) + offset); - - sp->opcode = JUMP; -#if 0 - sp->addr = fudge; -#else - sp->addr[0] = fudge & 0xffff; - sp->addr[1] = fudge >> 16; -#endif - sp->reloc_index = 0; -} - -/* - * Bind a jmpslot to its target address. TARGET is where the jmpslot - * should jump to, and WHERE is a pointer to the jmpslot's address field. - * This is called by the dynamic linker when LD_BIND_NOW is set in the - * environment. - */ -void -md_bind_jmpslot(target, where) -u_long target; -caddr_t where; -{ - jmpslot_t *sp = - (jmpslot_t *) (where - offsetof(jmpslot_t, addr[0])); - - md_fix_jmpslot(sp, (long) sp, target); -} - -/* - * Update the relocation record for a RRS jmpslot. - */ -void -md_make_jmpreloc(rp, r, type) -struct relocation_info *rp, *r; -int type; -{ - jmpslot_t *sp; - - /* - * Fix relocation address to point to the correct - * location within this jmpslot. - */ - r->r_address += sizeof(sp->opcode); - - /* Relocation size */ - r->r_length = 2; - - /* Set relocation type */ - r->r_jmptable = 1; - if (type & RELTYPE_RELATIVE) - r->r_relative = 1; - -} - -/* - * Set relocation type for a RRS GOT relocation. - */ -void -md_make_gotreloc(rp, r, type) -struct relocation_info *rp, *r; -int type; -{ - r->r_baserel = 1; - if (type & RELTYPE_RELATIVE) - r->r_relative = 1; - - /* Relocation size */ - r->r_length = 2; -} - -/* - * Set relocation type for a RRS copy operation. - */ -void -md_make_cpyreloc(rp, r) -struct relocation_info *rp, *r; -{ - /* Relocation size */ - r->r_length = 2; - - r->r_copy = 1; -} - -void -md_set_breakpoint(where, savep) -long where; -long *savep; -{ - *savep = *(long *)where; - *(char *)where = TRAP; -} - -#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)) - hp->a_entry = PAGSIZ; -} -#endif /* RTLD */ - - -#ifdef NEED_SWAP -/* - * Byte swap routines for cross-linking. - */ - -void -md_swapin_exec_hdr(h) -struct exec *h; -{ - int skip = 0; - - if (!N_BADMAG(*h)) - skip = 1; - - swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip); -} - -void -md_swapout_exec_hdr(h) -struct exec *h; -{ - /* NetBSD: Always leave magic alone */ - int skip = 1; -#if 0 - if (N_GETMAGIC(*h) == OMAGIC) - skip = 0; -#endif - - swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip); -} - - -void -md_swapin_reloc(r, n) -struct relocation_info *r; -int n; -{ - int bits; - - for (; n; n--, r++) { - r->r_address = md_swap_long(r->r_address); - bits = ((int *)r)[1]; - r->r_symbolnum = md_swap_long(bits) & 0x00ffffff; - r->r_pcrel = (bits & 1); - r->r_length = (bits >> 1) & 3; - r->r_extern = (bits >> 3) & 1; - r->r_baserel = (bits >> 4) & 1; - r->r_jmptable = (bits >> 5) & 1; - r->r_relative = (bits >> 6) & 1; -#ifdef N_SIZE - r->r_copy = (bits >> 7) & 1; -#endif - } -} - -void -md_swapout_reloc(r, n) -struct relocation_info *r; -int n; -{ - int bits; - - for (; n; n--, r++) { - r->r_address = md_swap_long(r->r_address); - bits = md_swap_long(r->r_symbolnum) & 0xffffff00; - bits |= (r->r_pcrel & 1); - bits |= (r->r_length & 3) << 1; - bits |= (r->r_extern & 1) << 3; - bits |= (r->r_baserel & 1) << 4; - bits |= (r->r_jmptable & 1) << 5; - bits |= (r->r_relative & 1) << 6; -#ifdef N_SIZE - bits |= (r->r_copy & 1) << 7; -#endif - ((int *)r)[1] = bits; - } -} - -void -md_swapout_jmpslot(j, n) -jmpslot_t *j; -int n; -{ - for (; n; n--, j++) { - j->opcode = md_swap_short(j->opcode); - j->addr[0] = md_swap_short(j->addr[0]); - j->addr[1] = md_swap_short(j->addr[1]); - j->reloc_index = md_swap_short(j->reloc_index); - } -} - -#endif /* NEED_SWAP */ diff --git a/libexec/rtld-aout/i386/md.h b/libexec/rtld-aout/i386/md.h deleted file mode 100644 index ef5b632..0000000 --- a/libexec/rtld-aout/i386/md.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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. - * - * $FreeBSD$ - */ - -#ifndef __MD_H__ -#define __MD_H__ - -#if defined(CROSS_LINKER) && defined(XHOST) && XHOST==sparc -#define NEED_SWAP -#endif - -#define MAX_ALIGNMENT (sizeof (long)) - -#ifdef NetBSD -#define PAGSIZ __LDPGSZ -#else -#define PAGSIZ 4096 -#endif - -#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 ? - */ -#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)) - -#define RELOC_STATICS_THROUGH_GOT_P(r) (0) -#define JMPSLOT_NEEDS_RELOC (0) - -#define md_got_reloc(r) (0) - -#define md_get_rt_segment_addend(r,a) md_get_addend(r,a) - -#define RELOC_INIT_SEGMENT_RELOC(r) ((r)->r_length = 2) - -/* Width of a Global Offset Table entry */ -#define GOT_ENTRY_SIZE 4 -typedef long got_t; - -typedef struct jmpslot { - u_short opcode; - u_short addr[2]; - u_short reloc_index; -#define JMPSLOT_RELOC_MASK 0xffff -} jmpslot_t; - -#define NOP 0x90 -#define CALL 0xe890 /* NOP + CALL opcode */ -#define JUMP 0xe990 /* NOP + JMP opcode */ -#define TRAP 0xcc /* INT 3 */ - -/* - * Byte swap defs for cross linking - */ - -#if !defined(NEED_SWAP) - -#define md_swapin_exec_hdr(h) -#define md_swapout_exec_hdr(h) -#define md_swapin_symbols(s,n) -#define md_swapout_symbols(s,n) -#define md_swapin_zsymbols(s,n) -#define md_swapout_zsymbols(s,n) -#define md_swapin_reloc(r,n) -#define md_swapout_reloc(r,n) -#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_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) -#define md_swapout_ranlib_hdr(h,n) - -#endif /* NEED_SWAP */ - -#ifdef CROSS_LINKER - -#define get_byte(p) ( ((unsigned char *)(p))[0] ) - -#define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \ - ( ((unsigned char *)(p))[1] ) \ - ) - -#define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \ - ( ((unsigned char *)(p))[1] << 16) | \ - ( ((unsigned char *)(p))[2] << 8 ) | \ - ( ((unsigned char *)(p))[3] ) \ - ) - -#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); } - -#define put_short(p, v) { ((unsigned char *)(p))[0] = \ - ((((unsigned long)(v)) >> 8) & 0xff); \ - ((unsigned char *)(p))[1] = \ - ((((unsigned long)(v)) ) & 0xff); } - -#define put_long(p, v) { ((unsigned char *)(p))[0] = \ - ((((unsigned long)(v)) >> 24) & 0xff); \ - ((unsigned char *)(p))[1] = \ - ((((unsigned long)(v)) >> 16) & 0xff); \ - ((unsigned char *)(p))[2] = \ - ((((unsigned long)(v)) >> 8) & 0xff); \ - ((unsigned char *)(p))[3] = \ - ((((unsigned long)(v)) ) & 0xff); } - -#ifdef NEED_SWAP - -/* Define IO byte swapping routines */ - -void md_swapin_exec_hdr __P((struct exec *)); -void md_swapout_exec_hdr __P((struct exec *)); -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__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) ) - -#define md_swap_long(x) ( (((x) >> 24) & 0xff ) | (((x) >> 8 ) & 0xff00 ) | \ - (((x) << 8 ) & 0xff0000) | (((x) << 24) & 0xff000000)) - -#else /* We need not swap, but must pay attention to alignment: */ - -#define md_swap_short(x) (x) -#define md_swap_long(x) (x) - -#endif /* NEED_SWAP */ - -#else /* Not a cross linker: use native */ - -#define md_swap_short(x) (x) -#define md_swap_long(x) (x) - -#define get_byte(where) (*(char *)(where)) -#define get_short(where) (*(short *)(where)) -#define get_long(where) (*(long *)(where)) - -#define put_byte(where,what) (*(char *)(where) = (what)) -#define put_short(where,what) (*(short *)(where) = (what)) -#define put_long(where,what) (*(long *)(where) = (what)) - -#endif /* CROSS_LINKER */ - -void md_init_header __P((struct exec *, int, int)); -long md_get_addend __P((struct relocation_info *, unsigned char *)); -void md_relocate __P((struct relocation_info *, long, unsigned char *, int)); -void md_make_jmpslot __P((jmpslot_t *, long, long)); -void md_fix_jmpslot __P((jmpslot_t *, long, u_long)); -void md_bind_jmpslot __P((u_long, caddr_t)); -int md_make_reloc __P((struct relocation_info *, struct relocation_info *, int)); -void md_make_jmpreloc __P((struct relocation_info *, struct relocation_info *, int)); -void md_make_gotreloc __P((struct relocation_info *, struct relocation_info *, int)); -void md_make_copyreloc __P((struct relocation_info *, struct relocation_info *)); -void md_set_breakpoint __P((long, long *)); - - -#endif /* __MD_H__ */ diff --git a/libexec/rtld-aout/i386/mdprologue.S b/libexec/rtld-aout/i386/mdprologue.S deleted file mode 100644 index f111bca..0000000 --- a/libexec/rtld-aout/i386/mdprologue.S +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - * - * $FreeBSD$ - */ - -/* - * i386 run-time link editor entry points. - */ - -#include - - .text - .globl _binder, _binder_entry - -/* - * _rtl(int version, struct crt_ldso *crtp) - */ - -_rtl: # crt0 calls us here - pushl %ebp # Allocate stack frame - movl %esp,%ebp - pushl %ebx - - call 1f # PIC function prologue -1: - popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx - - movl 12(%ebp),%eax # Extract data from interface structure - movl (%eax),%eax # base address of ld.so (first field) - # setup arguments for rtld() - movl (%ebx),%ecx # 1st entry in GOT is our __DYNAMIC - addl %eax,%ecx # add load address - pushl %ecx # 3rd arg - pushl 12(%ebp) # 2nd arg == &crt. - pushl 8(%ebp) # 1st arg == version - addl _rtld@GOT(%ebx),%eax # relocate address of function - call %eax # _rtld(version, crtp, DYNAMIC) - addl $12,%esp # pop arguments - - popl %ebx - leave # remove stack frame - ret - - # First call to a procedure generally comes through here for - # binding. - -_binder_entry: - pushl %ebp # setup a stack frame - movl %esp,%ebp - pusha # save all regs - - xorl %eax,%eax # clear - movl 4(%ebp),%esi # return address in PLT - movw (%esi),%ax # get hold of relocation number - subl $6,%esi # make it point to the jmpslot - - pushl %eax # pushd arguments - pushl %esi # - call _binder@PLT # _binder(rpc, index) - addl $8,%esp # pop arguments - movl %eax,4(%ebp) # return value from _binder() == actual - # address of function - popa # restore regs - leave # remove our stack frame - ret diff --git a/libexec/rtld-aout/md-prologue.c b/libexec/rtld-aout/md-prologue.c deleted file mode 100644 index dae455e..0000000 --- a/libexec/rtld-aout/md-prologue.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * rtld entry pseudo code - turn into assembler and tweak it - */ - -#include -#include -#include -#include "link.h" -#include "md.h" - -extern long _GOT_[]; -extern void (*rtld)(); -extern void (*binder())(); - -void -rtld_entry(version, crtp) -int version; -struct crt *crtp; -{ - register struct link_dynamic *dp; - register void (*f)(); - - /* __DYNAMIC is first entry in GOT */ - dp = (struct link_dynamic *) (_GOT_[0]+crtp->crt_ba); - - f = (void (*)())((long)rtld + crtp->crt_ba); - (*f)(version, crtp, dp); -} - -void -binder_entry() -{ - extern int PC; - struct jmpslot *sp; - void (*func)(); - - func = binder(PC, sp->reloc_index & 0x003fffff); - (*func)(); -} diff --git a/libexec/rtld-aout/rtld.1aout b/libexec/rtld-aout/rtld.1aout deleted file mode 100644 index f7bca31..0000000 --- a/libexec/rtld-aout/rtld.1aout +++ /dev/null @@ -1,226 +0,0 @@ -.\" $FreeBSD$ -.\" -.\" Copyright (c) 1995 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 acknowledgment: -.\" 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 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. -.\" -.Dd June 27, 1995 -.Dt RTLD 1 -.Os -.Sh NAME -.Nm ld.so , -.Nm rtld -.Nd run-time link-editor -.Sh DESCRIPTION -.Nm -is a self-contained, position independent program image providing run-time -support for loading and link-editing shared objects into a process' -address space. -It uses the data structures -(see -.Xr link 5 ) -contained within dynamically linked programs to determine which shared -libraries are needed and loads them at a convenient virtual address -using the -.Xr mmap 2 -system call. -.Pp -After all shared libraries have been successfully loaded, -.Nm -proceeds to resolve external references from both the main program and -all objects loaded. -A mechanism is provided for initialization routines -to be called, on a per-object basis, giving a shared object an opportunity -to perform any extra set-up, before execution of the program proper begins. -This is useful for C++ libraries that contain static constructors. -.Pp -.Nm -is itself a shared object that is initially loaded by the startup module -.Em crt0 . -Since -.Xr a.out 5 -formats do not provide easy access to the file header from within a running -process, -.Em crt0 -uses the special symbol -.Va _DYNAMIC -to determine whether a program is in fact dynamically linked or not. -Whenever -the linker -.Xr ld 1 -has relocated this symbol to a location other than 0, -.Em crt0 -assumes the services of -.Nm -are needed -(see -.Xr link 5 -for details). -.Em crt0 -passes control to -.Nm Ns 's -entry point before the program's -.Fn main -routine is called. -Thus, -.Nm -can complete the link-editing process before the dynamic program calls upon -services of any dynamic library. -.Pp -To quickly locate the required shared objects in the file system, -.Nm -may use a -.Dq hints -file, prepared by the -.Xr ldconfig 8 -utility, in which the full path specification of the shared objects can be -looked up by hashing on the 3-tuple -.Aq library-name , major-version-number , minor-version-number . -.Pp -.Nm -recognizes a number of environment variables that can be used to modify -its behaviour as follows: -.Pp -.Bl -tag -width "LD_IGNORE_MISSING_OBJECTS" -.It Ev LD_LIBRARY_PATH -A colon separated list of directories, overriding the default search path -for shared libraries. -This is ignored for set-user-ID and set-group-ID programs. -.It Ev LD_PRELOAD -A colon separated list of shared libraries, to be linked in before any -other shared libraries. -If the directory is not specified then -the directories specified by LD_LIBRARY_PATH will be searched first -followed by the set of built-in standard directories. -This is ignored for set-user-ID and set-group-ID programs. -.It Ev LD_BIND_NOW -When set to a nonempty string, causes -.Nm -to relocate all external function calls before starting execution of the -program. -Normally, function calls are bound lazily, at the first call -of each function. -.Ev LD_BIND_NOW -increases the start-up time of a program, but it avoids run-time -surprises caused by unexpectedly undefined functions. -.It Ev LD_WARN_NON_PURE_CODE -When set to a nonempty string, issue a warning whenever a link-editing -operation requires modification of the text segment of some loaded -object. -This is usually indicative of an incorrectly built library. -.It Ev LD_SUPPRESS_WARNINGS -When set to a nonempty string, no warning messages of any kind are -issued. -Normally, a warning is given if satisfactorily versioned -library could not be found. -.It Ev LD_IGNORE_MISSING_OBJECTS -When set to a nonempty string, makes it a nonfatal condition if -one or more required shared objects cannot be loaded. -Loading and execution proceeds using the objects that are -available. -A warning is produced for each missing object, unless the environment -variable -.Ev LD_SUPPRESS_WARNINGS -is set to a nonempty string. -.Pp -This is ignored for set-user-ID and set-group-ID programs. -.Pp -Missing shared objects can be ignored without errors if all the -following conditions hold: -.Bl -bullet -.It -They do not supply definitions for any required data symbols. -.It -No functions defined by them are called during program execution. -.It -The environment variable -.Ev LD_BIND_NOW -is unset or is set to the empty string. -.El -.It Ev LD_TRACE_LOADED_OBJECTS -When set to a nonempty string, causes -.Nm -to exit after loading the shared objects and printing a summary which includes -the absolute pathnames of all objects, to standard output. -.It Ev LD_TRACE_LOADED_OBJECTS_FMT1 -.It Ev LD_TRACE_LOADED_OBJECTS_FMT2 -When set, these variables are interpreted as format strings a la -.Xr printf 3 -to customize the trace output and are used by -.Xr ldd 1 Ns 's -.Fl f -option and allows -.Xr ldd 1 -to be operated as a filter more conveniently. -The following conversions can be used: -.Bl -tag -width "xxxx" -.It \&%a -The main program's name -(also known as -.Dq __progname ) . -.It \&%A -The value of the environment variable -.Ev LD_TRACE_LOADED_OBJECTS_PROGNAME -.It \&%o -The library name. -.It \&%m -The library's major version number. -.It \&%n -The library's minor version number. -.It \&%p -The full pathname as determined by -.Nm rtld Ns 's -library search rules. -.It \&%x -The library's load address. -.El -.Pp -Additionally, -.Sy \en -and -.Sy \et -are recognized and have their usual meaning. -.\" .It Ev LD_NO_INTERN_SEARCH -.\" When set, -.\" .Nm -.\" does not process any internal search paths that were recorded in the -.\" executable. -.\" .It Ev LD_NOSTD_PATH -.\" When set, do not include a set of built-in standard directory paths for -.\" searching. This might be useful when running on a system with a completely -.\" non-standard file system layout. -.El -.Pp -.Sh FILES -/var/run/ld.so.hints -.Pp -.Sh SEE ALSO -.Xr ld 1 , -.Xr link 5 , -.Xr ldconfig 8 -.Sh HISTORY -The shared library model employed first appeared in SunOS 4.0. diff --git a/libexec/rtld-aout/rtld.c b/libexec/rtld-aout/rtld.c deleted file mode 100644 index 8d165c1..0000000 --- a/libexec/rtld-aout/rtld.c +++ /dev/null @@ -1,2550 +0,0 @@ -/* - * 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. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef MAP_COPY -#define MAP_COPY MAP_PRIVATE -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "md.h" -#include "shlib.h" -#include "support.h" -#include "dynamic.h" - -#ifndef MAP_ANON -#define MAP_ANON 0 -#define anon_open() do { \ - if ((anon_fd = open(_PATH_DEVZERO, O_RDWR, 0)) == -1) \ - err("open: %s", _PATH_DEVZERO); \ -} while (0) -#define anon_close() do { \ - (void)close(anon_fd); \ - anon_fd = -1; \ -} while (0) -#else -#define anon_open() -#define anon_close() -#endif - -/* - * Structure for building a list of shared objects. - */ -struct so_list { - struct so_map *sol_map; /* Link map for shared object */ - struct so_list *sol_next; /* Next entry in the list */ -}; - -/* - * Loader private data, hung off ->som_spd - */ -struct somap_private { - int spd_version; - struct so_map *spd_parent; - struct so_list *spd_children; - struct so_map *spd_prev; - dev_t spd_dev; - ino_t spd_ino; - int spd_refcount; - int spd_flags; -#define RTLD_MAIN 0x01 -#define RTLD_RTLD 0x02 -#define RTLD_DL 0x04 -#define RTLD_INIT 0x08 - unsigned long a_text; /* text size, if known */ - unsigned long a_data; /* initialized data size */ - unsigned long a_bss; /* uninitialized data size */ - -#ifdef SUN_COMPAT - 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(smp) (LM_PRIVATE(smp)->spd_offset) -#else -#define LM_OFFSET(smp) (0) -#endif - -/* Base address for section_dispatch_table entries */ -#define LM_LDBASE(smp) (smp->som_addr + LM_OFFSET(smp)) - -/* Start of text segment */ -#define LM_TXTADDR(smp) (smp->som_addr == (caddr_t)0 ? PAGSIZ : 0) - -/* Start of run-time relocation_info */ -#define LM_REL(smp) ((struct relocation_info *) \ - (smp->som_addr + LM_OFFSET(smp) + LD_REL((smp)->som_dynamic))) - -/* Start of symbols */ -#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(smp) ((struct rrs_hash *) \ - ((smp)->som_addr + LM_OFFSET(smp) + LD_HASH((smp)->som_dynamic))) - -/* Start of strings */ -#define LM_STRINGS(smp) ((char *) \ - ((smp)->som_addr + LM_OFFSET(smp) + LD_STRINGS((smp)->som_dynamic))) - -/* Start of search paths */ -#define LM_PATHS(smp) ((char *) \ - ((smp)->som_addr + LM_OFFSET(smp) + LD_PATHS((smp)->som_dynamic))) - -/* End of text */ -#define LM_ETEXT(smp) ((char *) \ - ((smp)->som_addr + LM_TXTADDR(smp) + LD_TEXTSZ((smp)->som_dynamic))) - -/* Needed shared objects */ -#define LM_NEED(smp) ((struct sod *) \ - ((smp)->som_addr + LM_TXTADDR(smp) + LD_NEED((smp)->som_dynamic))) - -/* PLT is in data segment, so don't use LM_OFFSET here */ -#define LM_PLT(smp) ((jmpslot_t *) \ - ((smp)->som_addr + LD_PLT((smp)->som_dynamic))) - -/* Parent of link map */ -#define LM_PARENT(smp) (LM_PRIVATE(smp)->spd_parent) - -#ifndef RELOC_EXTERN_P -#define RELOC_EXTERN_P(s) ((s)->r_extern) -#endif - -#ifndef RELOC_SYMBOL -#define RELOC_SYMBOL(s) ((s)->r_symbolnum) -#endif - -#ifndef RELOC_PCREL_P -#define RELOC_PCREL_P(s) ((s)->r_pcrel) -#endif - -#define END_SYM "_end" - -static char __main_progname[] = "main"; -static char *main_progname = __main_progname; -static char us[] = "/usr/libexec/ld.so"; - -char **environ; -char *__progname; -int errno; - -static uid_t uid, euid; -static gid_t gid, egid; -static int careful; -static int anon_fd = -1; - -static char *ld_bind_now; -static char *ld_ignore_missing_objects; -static char *ld_library_path; -static char *ld_preload; -static char *ld_tracing; -static char *ld_suppress_warnings; -static char *ld_warn_non_pure_code; - -struct so_map *link_map_head; -struct so_map *link_map_tail; -struct rt_symbol *rt_symbol_head; - -static void *__dlopen __P((const char *, int)); -static int __dlclose __P((void *)); -static void *__dlsym __P((void *, const char *)); -static const char *__dlerror __P((void)); -static void __dlexit __P((void)); -static void *__dlsym3 __P((void *, const char *, void *)); -static int __dladdr __P((const void *, Dl_info *)); - -static struct ld_entry ld_entry = { - __dlopen, __dlclose, __dlsym, __dlerror, __dlexit, __dlsym3, __dladdr -}; - - void xprintf __P((char *, ...)); -static struct so_map *map_object __P(( const char *, - struct sod *, - struct so_map *)); -static int map_preload __P((void)); -static int map_sods __P((struct so_map *)); -static int reloc_dag __P((struct so_map *, int)); -static void unmap_object __P((struct so_map *, int)); -static struct so_map *alloc_link_map __P(( const char *, struct sod *, - struct so_map *, caddr_t, - struct _dynamic *)); -static void init_link_map __P(( struct so_map *, - struct somap_private *, - const char *, struct sod *, - struct so_map *, caddr_t, - struct _dynamic *)); -static void free_link_map __P((struct so_map *)); -static inline int check_text_reloc __P(( struct relocation_info *, - struct so_map *, - caddr_t)); -static int reloc_map __P((struct so_map *, int)); -static void reloc_copy __P((struct so_map *)); -static void init_dag __P((struct so_map *)); -static void init_sods __P((struct so_list *)); -static void init_internal_malloc __P((void)); -static void init_external_malloc __P((void)); -static int call_map __P((struct so_map *, char *)); -static char *findhint __P((char *, int, int *)); -static char *rtfindlib __P((char *, int, int, int)); -static char *rtfindfile __P((const char *)); -void binder_entry __P((void)); -long binder __P((jmpslot_t *)); -static struct nzlist *lookup __P((char *, struct so_map **, int)); -static inline struct rt_symbol *lookup_rts __P((char *, unsigned long)); -static struct nzlist *lookup_in_obj __P((char *, unsigned long, - struct so_map *, int)); -static struct rt_symbol *enter_rts __P((char *, unsigned long, long, int, - caddr_t, long, struct so_map *)); -static void *sym_addr __P((char *)); -static struct nzlist * lookup_errno_hack(char *, struct so_map **, int); -static void die __P((void)); -static void generror __P((char *, ...)); -static int maphints __P((void)); -static void unmaphints __P((void)); -static void ld_trace __P((struct so_map *)); -static void rt_readenv __P((void)); -static int hinthash __P((char *, int)); -int rtld __P((int, struct crt_ldso *, struct _dynamic *)); - -/* - * Compute a hash value for symbol tables. Don't change this -- the - * algorithm is dictated by the way the linker builds the symbol - * tables in the shared objects. - */ -static inline unsigned long -sym_hash(s) - const char *s; -{ - unsigned long h; - - h = 0; - while (*s != '\0') - h = (h << 1) + *s++; - return h & 0x7fffffffUL; -} - -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" - -/* - * Called from assembler stub that has set up crtp (passed from crt0) - * and dp (our __DYNAMIC). - */ -int -rtld(version, crtp, dp) -int version; -struct crt_ldso *crtp; -struct _dynamic *dp; -{ - struct relocation_info *reloc; - struct relocation_info *reloc_limit; /* End+1 of relocation */ - struct so_debug *ddp; - struct so_map *main_map; - struct so_map *smp; - char *add_paths; - char *main_path; - - /* Check version */ - if (version != CRT_VERSION_BSD_2 && - version != CRT_VERSION_BSD_3 && - version != CRT_VERSION_BSD_4 && - version != CRT_VERSION_BSD_5 && - version != CRT_VERSION_SUN) - return -1; - - /* Fixup __DYNAMIC structure */ - (long)dp->d_un.d_sdt += crtp->crt_ba; - - /* Relocate ourselves */ - reloc = (struct relocation_info *) (LD_REL(dp) + crtp->crt_ba); - reloc_limit = - (struct relocation_info *) ((char *) reloc + LD_RELSZ(dp)); - while(reloc < reloc_limit) { - /* - * Objects linked with "-Bsymbolic" (in particular, ld.so - * itself) can end up having unused relocation entries at - * the end. These can be detected by the fact that they - * have an address of 0. - */ - if(reloc->r_address == 0) /* We're done */ - break; - md_relocate_simple(reloc, crtp->crt_ba, - reloc->r_address + crtp->crt_ba); - ++reloc; - } - - if (version >= CRT_VERSION_BSD_4) - __progname = crtp->crt_ldso; - if (version >= CRT_VERSION_BSD_3) - main_progname = crtp->crt_prog; - main_path = version >= CRT_VERSION_BSD_5 ? crtp->crt_argv[0] : - main_progname; - - /* Some buggy versions of crt0.o have crt_ldso filled in as NULL. */ - if (__progname == NULL) - __progname = us; - - /* Fill in some fields in _DYNAMIC or crt structure */ - if (version >= CRT_VERSION_BSD_4) - crtp->crt_ldentry = &ld_entry; /* crt */ - else - crtp->crt_dp->d_entry = &ld_entry; /* _DYNAMIC */ - - /* Initialize our internal malloc package. */ - init_internal_malloc(); - - /* Setup out (private) environ variable */ - environ = crtp->crt_ep; - - /* Get user and group identifiers */ - uid = getuid(); euid = geteuid(); - gid = getgid(); egid = getegid(); - - careful = (uid != euid) || (gid != egid); - - rt_readenv(); - - anon_open(); - - /* Make a link map entry for the main program */ - main_map = alloc_link_map(main_path, - (struct sod *) NULL, (struct so_map *) NULL, - (caddr_t) 0, crtp->crt_dp); - LM_PRIVATE(main_map)->spd_refcount++; - LM_PRIVATE(main_map)->spd_flags |= RTLD_MAIN; - - /* Make a link map entry for ourselves */ - smp = alloc_link_map(us, - (struct sod *) NULL, (struct so_map *) NULL, - (caddr_t) crtp->crt_ba, dp); - LM_PRIVATE(smp)->spd_refcount++; - LM_PRIVATE(smp)->spd_flags |= RTLD_RTLD; - - /* - * Setup the executable's run path - */ - if (version >= CRT_VERSION_BSD_4) { - add_paths = LM_PATHS(main_map); - if (add_paths) - add_search_path(add_paths); - } - - /* - * Setup the directory search list for findshlib. We use only - * the standard search path. Any extra directories from - * LD_LIBRARY_PATH are searched explicitly, in rtfindlib. - */ - std_search_path(); - - /* Map in LD_PRELOADs before the main program's shared objects so we - can intercept those calls */ - if (ld_preload != NULL) { - if(map_preload() == -1) /* Failed */ - die(); - } - - /* Map all the shared objects that the main program depends upon */ - if(map_sods(main_map) == -1) - die(); - - if(ld_tracing) { /* We're done */ - ld_trace(link_map_head); - exit(0); - } - - crtp->crt_dp->d_un.d_sdt->sdt_loaded = link_map_head->som_next; - - /* Relocate all mapped objects. */ - if(reloc_dag(main_map, ld_bind_now != NULL) == -1) /* Failed */ - die(); - - /* - * Switch to the same malloc that the program uses. We do - * this before initializing the loaded objects, because their - * initialization functions may well call malloc, and it won't - * work right until we have set it up. - */ - init_external_malloc(); - - /* Initialize all mapped objects. */ - init_dag(main_map); - - 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) { - err(1, "Cannot set breakpoint (%s)", main_progname); - } - md_set_breakpoint((long)crtp->crt_bp, (long *)&ddp->dd_bpt_shadow); - if (mprotect(addr, PAGSIZ, PROT_READ|PROT_EXEC) == -1) { - err(1, "Cannot re-protect breakpoint (%s)", - main_progname); - } - - ddp->dd_bpt_addr = crtp->crt_bp; - if (link_map_head) - ddp->dd_sym_loaded = 1; - } - - /* Close the hints file */ - unmaphints(); - - /* Close our file descriptor */ - (void)close(crtp->crt_ldfd); - anon_close(); - - return LDSO_VERSION_HAS_DLADDR; -} - -void -ld_trace(smp) - struct so_map *smp; -{ - char *fmt1, *fmt2, *fmt, *main_local; - int c; - - if ((main_local = getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) - main_local = ""; - - if ((fmt1 = getenv("LD_TRACE_LOADED_OBJECTS_FMT1")) == NULL) - fmt1 = "\t-l%o.%m => %p (%x)\n"; - - if ((fmt2 = getenv("LD_TRACE_LOADED_OBJECTS_FMT2")) == NULL) - fmt2 = "\t%o (%x)\n"; - - for (; smp; smp = smp->som_next) { - struct sod *sodp; - char *name, *path; - - if ((sodp = smp->som_sod) == NULL) - continue; - - name = (char *)sodp->sod_name; - if (LM_PARENT(smp)) - name += (long)LM_LDBASE(LM_PARENT(smp)); - - if ((path = smp->som_path) == NULL) - path = "not found"; - - fmt = sodp->sod_library ? fmt1 : fmt2; - while ((c = *fmt++) != '\0') { - switch (c) { - default: - putchar(c); - continue; - case '\\': - switch (c = *fmt) { - case '\0': - continue; - case 'n': - putchar('\n'); - break; - case 't': - putchar('\t'); - break; - } - break; - case '%': - switch (c = *fmt) { - case '\0': - continue; - case '%': - default: - putchar(c); - break; - case 'A': - printf("%s", main_local); - break; - case 'a': - printf("%s", main_progname); - break; - case 'o': - printf("%s", name); - break; - case 'm': - printf("%d", sodp->sod_major); - break; - case 'n': - printf("%d", sodp->sod_minor); - break; - case 'p': - printf("%s", path); - break; - case 'x': - printf("%p", smp->som_addr); - break; - } - break; - } - ++fmt; - } - } -} - -/* - * Allocate a new link map and return a pointer to it. - * - * PATH is the pathname of the shared object. - * - * SODP is a pointer to the shared object dependency structure responsible - * for causing the new object to be loaded. PARENT is the shared object - * into which SODP points. Both can be NULL if the new object is not - * being loaded as a result of a shared object dependency. - * - * ADDR is the address at which the object has been mapped. DP is a pointer - * to its _dynamic structure. - */ -static struct so_map * -alloc_link_map(path, sodp, parent, addr, dp) - const char *path; - struct sod *sodp; - struct so_map *parent; - caddr_t addr; - struct _dynamic *dp; -{ - struct so_map *smp; - struct somap_private *smpp; - -#ifdef DEBUG /* { */ - xprintf("alloc_link_map: \"%s\" at %p\n", path, addr); -#endif /* } */ - - smp = (struct so_map *)xmalloc(sizeof(struct so_map)); - smpp = (struct somap_private *)xmalloc(sizeof(struct somap_private)); - init_link_map(smp, smpp, path, sodp, parent, addr, dp); - - /* Link the new entry into the list of link maps */ - smpp->spd_prev = link_map_tail; - if(link_map_tail == NULL) /* First link map entered into list */ - link_map_head = link_map_tail = smp; - else { /* Append to end of list */ - link_map_tail->som_next = smp; - link_map_tail = smp; - } - - return smp; -} - -/* - * Initialize a link map entry that has already been allocated. - */ -static void -init_link_map(smp, smpp, path, sodp, parent, addr, dp) - struct so_map *smp; - struct somap_private *smpp; - const char *path; - struct sod *sodp; - struct so_map *parent; - caddr_t addr; - struct _dynamic *dp; -{ - memset(smp, 0, sizeof *smp); - memset(smpp, 0, sizeof *smpp); - smp->som_spd = (caddr_t)smpp; - smp->som_addr = addr; - smp->som_path = path ? strdup(path) : NULL; - smp->som_sod = sodp; - smp->som_dynamic = dp; - smpp->spd_parent = parent; -#ifdef SUN_COMPAT - smpp->spd_offset = - (addr==0 && dp && dp->d_version==LD_VERSION_SUN) ? PAGSIZ : 0; -#endif -} - -/* - * Remove the specified link map entry from the list of link maps, and free - * the associated storage. - */ -static void -free_link_map(smp) - struct so_map *smp; -{ - struct somap_private *smpp = LM_PRIVATE(smp); - -#ifdef DEBUG /* { */ - xprintf("free_link_map: \"%s\"\n", smp->som_path); -#endif /* } */ - - if(smpp->spd_prev == NULL) /* Removing first entry in list */ - link_map_head = smp->som_next; - else /* Update link of previous entry */ - smpp->spd_prev->som_next = smp->som_next; - - if(smp->som_next == NULL) /* Removing last entry in list */ - link_map_tail = smpp->spd_prev; - else /* Update back link of next entry */ - LM_PRIVATE(smp->som_next)->spd_prev = smpp->spd_prev; - - if (smp->som_path != NULL) - free(smp->som_path); - free(smpp); - free(smp); -} - -/* - * Map the shared object specified by PATH into memory, if it is not - * already mapped. Increment the object's reference count, and return a - * pointer to its link map. - * - * As a special case, if PATH is NULL, it is taken to refer to the main - * program. - * - * SODP is a pointer to the shared object dependency structure that caused - * this object to be requested. PARENT is a pointer to the link map of - * the shared object containing that structure. For a shared object not - * being mapped as a result of a shared object dependency, these pointers - * should be NULL. An example of this is a shared object that is explicitly - * loaded via dlopen(). - * - * The return value is a pointer to the link map for the requested object. - * If the operation failed, the return value is NULL. In that case, an - * error message can be retrieved by calling dlerror(). - */ -static struct so_map * -map_object(path, sodp, parent) - const char *path; - struct sod *sodp; - struct so_map *parent; -{ - struct so_map *smp; - struct stat statbuf; - - if(path == NULL) /* Special case for the main program itself */ - smp = link_map_head; - else { - /* - * Check whether the shared object is already mapped. - * We check first for an exact match by pathname. That - * will detect the usual case. If no match is found by - * pathname, then stat the file, and check for a match by - * device and inode. That will detect the less common case - * involving multiple links to the same library. - */ - for(smp = link_map_head; smp != NULL; smp = smp->som_next) { - if(!(LM_PRIVATE(smp)->spd_flags & (RTLD_MAIN|RTLD_RTLD)) - && smp->som_path != NULL - && strcmp(smp->som_path, path) == 0) - break; - } - if(smp == NULL) { /* Check for a match by device and inode */ - if (stat(path, &statbuf) == -1) { - generror ("cannot stat \"%s\" : %s", - path, strerror(errno)); - return NULL; - } - for (smp = link_map_head; smp != NULL; - smp = smp->som_next) { - struct somap_private *smpp = LM_PRIVATE(smp); - - if (!(smpp->spd_flags & (RTLD_MAIN | RTLD_RTLD)) - && smpp->spd_ino == statbuf.st_ino - && smpp->spd_dev == statbuf.st_dev) - break; - } - } - } - - if (smp == NULL) { /* We must map the object */ - struct _dynamic *dp; - int fd; - caddr_t addr; - struct exec hdr; - struct somap_private *smpp; - - if ((fd = open(path, O_RDONLY, 0)) == -1) { - generror ("open failed for \"%s\" : %s", - path, strerror (errno)); - return NULL; - } - - if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - generror ("header read failed for \"%s\"", path); - (void)close(fd); - return NULL; - } - - if (N_BADMAG(hdr)) { - generror ("bad magic number in \"%s\"", path); - (void)close(fd); - return NULL; - } - - /* - * Map the entire address space of the object. It is - * tempting to map just the text segment at first, in - * order to avoid having to use mprotect to change the - * protections of the data segment. But that would not - * be correct. Mmap might find a group of free pages - * large enough to hold the text segment, but not large - * enough for the entire object. When we then mapped - * in the data and BSS segments, they would either be - * non-contiguous with the text segment (if we didn't - * specify MAP_FIXED), or they would map over some - * previously mapped region (if we did use MAP_FIXED). - * The only way we can be sure of getting a contigous - * region that is large enough is to map the entire - * region at once. - */ - if ((addr = mmap(0, hdr.a_text + hdr.a_data + hdr.a_bss, - PROT_READ|PROT_EXEC, - MAP_COPY, fd, 0)) == (caddr_t)-1) { - generror ("mmap failed for \"%s\" : %s", - path, strerror (errno)); - (void)close(fd); - return NULL; - } - - (void)close(fd); - - /* Change the data segment to writable */ - if (mprotect(addr + hdr.a_text, hdr.a_data, - PROT_READ|PROT_WRITE|PROT_EXEC) != 0) { - generror ("mprotect failed for \"%s\" : %s", - path, strerror (errno)); - (void)munmap(addr, hdr.a_text + hdr.a_data + hdr.a_bss); - return NULL; - } - - /* Map in pages of zeros for the BSS segment */ - if (mmap(addr + hdr.a_text + hdr.a_data, hdr.a_bss, - PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_ANON|MAP_COPY|MAP_FIXED, - anon_fd, 0) == (caddr_t)-1) { - generror ("mmap failed for \"%s\" : %s", - path, strerror (errno)); - (void)munmap(addr, hdr.a_text + hdr.a_data + hdr.a_bss); - return NULL; - } - - /* Assume _DYNAMIC is the first data item */ - dp = (struct _dynamic *)(addr+hdr.a_text); - - /* Fixup __DYNAMIC structure */ - (long)dp->d_un.d_sdt += (long)addr; - - smp = alloc_link_map(path, sodp, parent, addr, dp); - - /* save segment sizes for unmap. */ - smpp = LM_PRIVATE(smp); - smpp->a_text = hdr.a_text; - smpp->a_data = hdr.a_data; - smpp->a_bss = hdr.a_bss; - - /* - * Save the device and inode, so we can detect multiple links - * to the same library. Note, if we reach this point, then - * statbuf is guaranteed to have been filled in. - */ - smpp->spd_dev = statbuf.st_dev; - smpp->spd_ino = statbuf.st_ino; - } - - LM_PRIVATE(smp)->spd_refcount++; - if(LM_PRIVATE(smp)->spd_refcount == 1) { /* First use of object */ - /* - * Recursively map all of the shared objects that this - * one depends upon. - */ - if(map_sods(smp) == -1) { /* Failed */ - unmap_object(smp, 0); /* Clean up */ - return NULL; - } - } - - return smp; -} - -/* - * Map all the shared libraries named in the LD_PRELOAD environment - * variable. - * - * Returns 0 on success, -1 on failure. On failure, an error message can - * be gotten via dlerror(). - */ - static int -map_preload __P((void)) { - char *ld_name = ld_preload; - char *name; - - while ((name = strsep(&ld_name, ":")) != NULL) { - char *path = NULL; - struct so_map *smp = NULL; - - if (*name != '\0') { - path = (strchr(name, '/') != NULL) ? strdup(name) : - rtfindfile(name); - } - if (path == NULL) { - generror("Can't find LD_PRELOAD shared" - " library \"%s\"", name); - } else { - smp = map_object(path, (struct sod *) NULL, - (struct so_map *) NULL); - free(path); - } - if (ld_name != NULL) - *(ld_name - 1) = ':'; - if (smp == NULL) { - /* - * We don't bother to unmap already-loaded libraries - * on failure, because in that case the program is - * about to die anyway. - */ - return -1; - } - } - return 0; -} - -/* - * Map all of the shared objects that a given object depends upon. PARENT is - * a pointer to the link map for the shared object whose dependencies are - * to be mapped. - * - * Returns 0 on success. Returns -1 on failure. In that case, an error - * message can be retrieved by calling dlerror(). - */ -static int -map_sods(parent) - struct so_map *parent; -{ - struct somap_private *parpp = LM_PRIVATE(parent); - struct so_list **soltail = &parpp->spd_children; - long next = LD_NEED(parent->som_dynamic); - - while(next != 0) { - struct sod *sodp = - (struct sod *) (LM_LDBASE(parent) + next); - char *name = - (char *) (LM_LDBASE(parent) + sodp->sod_name); - char *path = NULL; - struct so_map *smp = NULL; - - if(sodp->sod_library) { - /* - * First try for a match with an adequate minor - * number. - */ - path = rtfindlib(name, sodp->sod_major, - sodp->sod_minor, 1); - /* - * If none was found, try for just a major version - * match. A warning is issued by rtfindlib in - * this case, since the minor version number isn't - * really high enough. - */ - if (path == NULL) - path = rtfindlib(name, sodp->sod_major, - sodp->sod_minor, 0); - if(path == NULL && !ld_tracing) { - generror ("Can't find shared library" - " \"lib%s.so.%d.%d\"", name, - sodp->sod_major, sodp->sod_minor); - } - } else { - if(careful && name[0] != '/') { - generror("Shared library path must start" - " with \"/\" for \"%s\"", name); - } else - path = strdup(name); - } - - if(path != NULL) { - smp = map_object(path, sodp, parent); - free(path); - } - - if(smp != NULL) { - struct so_list *solp = (struct so_list *) - xmalloc(sizeof(struct so_list)); - solp->sol_map = smp; - solp->sol_next = NULL; - *soltail = solp; - soltail = &solp->sol_next; - } else if(ld_tracing) { - /* - * Allocate a dummy map entry so that we will get the - * "not found" message. - */ - (void)alloc_link_map(NULL, sodp, parent, 0, 0); - } else if (ld_ignore_missing_objects) { - const char *msg; - /* - * Call __dlerror() even it we're not going to use - * the message, in order to clear the saved message. - */ - msg = __dlerror(); /* Should never be NULL */ - if (!ld_suppress_warnings) - warnx("warning: %s", msg); - } else /* Give up */ - break; - - next = sodp->sod_next; - } - - if(next != 0) { - /* - * Oh drat, we have to clean up a mess. - * - * We failed to load a shared object that we depend upon. - * So now we have to unload any dependencies that we had - * already successfully loaded prior to the error. - * - * Cleaning up doesn't matter so much for the initial - * loading of the program, since any failure is going to - * terminate the program anyway. But it is very important - * to clean up properly when something is being loaded - * via dlopen(). - */ - struct so_list *solp; - - while((solp = parpp->spd_children) != NULL) { - unmap_object(solp->sol_map, 0); - parpp->spd_children = solp->sol_next; - free(solp); - } - - return -1; - } - - return 0; -} - -/* - * Relocate the DAG of shared objects rooted at the given link map - * entry. Returns 0 on success, or -1 on failure. On failure, an - * error message can be retrieved via dlerror(). - */ -static int -reloc_dag(root, bind_now) - struct so_map *root; - int bind_now; -{ - struct so_map *smp; - - /* - * Relocate all newly-loaded objects. We avoid recursion for this - * step by taking advantage of a few facts. This function is called - * only when there are in fact some newly-loaded objects to process. - * Furthermore, all newly-loaded objects will have their link map - * entries at the end of the link map list. And, the root of the - * tree of objects just loaded will have been the first to be loaded - * and therefore the first new object in the link map list. Finally, - * we take advantage of the fact that we can relocate the newly-loaded - * objects in any order. - * - * All these facts conspire to let us simply loop over the tail - * portion of the link map list, relocating each object so - * encountered. - */ - for(smp = root; smp != NULL; smp = smp->som_next) { - if(!(LM_PRIVATE(smp)->spd_flags & RTLD_RTLD)) { - if(reloc_map(smp, bind_now) < 0) - return -1; - } - } - - /* - * Copy any relocated initialized data. Again, we can just loop - * over the appropriate portion of the link map list. - */ - for(smp = root; smp != NULL; smp = smp->som_next) { - if(!(LM_PRIVATE(smp)->spd_flags & RTLD_RTLD)) - reloc_copy(smp); - } - - return 0; -} - -/* - * Remove a reference to the shared object specified by SMP. If no - * references remain, unmap the object and, recursively, its descendents. - * This function also takes care of calling the finalization routines for - * objects that are removed. - * - * If KEEP is true, then the actual calls to munmap() are skipped, - * and the object is kept in memory. That is used only for finalization, - * from dlexit(), when the program is exiting. There are two reasons - * for it. First, the program is exiting and there is no point in - * spending the time to explicitly unmap its shared objects. Second, - * even after dlexit() has been called, there are still a couple of - * calls that are made to functions in libc. (This is really a bug - * in crt0.) So libc and the main program, at least, must remain - * mapped in that situation. - * - * Under no reasonable circumstances should this function fail. If - * anything goes wrong, we consider it an internal error, and report - * it with err(). - */ -static void -unmap_object(smp, keep) - struct so_map *smp; - int keep; -{ - struct somap_private *smpp = LM_PRIVATE(smp); - - smpp->spd_refcount--; - if(smpp->spd_refcount == 0) { /* Finished with this object */ - struct so_list *solp; - - if(smpp->spd_flags & RTLD_INIT) { /* Was initialized */ - /* - * Call the object's finalization routine. For - * backward compatibility, we first try to call - * ".fini". If that does not exist, we call - * "__fini". - */ - if(call_map(smp, ".fini") == -1) - call_map(smp, "__fini"); - } - - /* Recursively unreference the object's descendents */ - while((solp = smpp->spd_children) != NULL) { - unmap_object(solp->sol_map, keep); - smpp->spd_children = solp->sol_next; - free(solp); - } - - if(!keep) { /* Unmap the object from memory */ - if(munmap(smp->som_addr, - smpp->a_text + smpp->a_data + smpp->a_bss) < 0) - err(1, "internal error 1: munmap failed"); - - /* Unlink and free the object's link map entry */ - free_link_map(smp); - } - } -} - -static inline int -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 0; - - if (RELOC_EXTERN_P(r)) - sym = LM_STRINGS(smp) + - LM_SYMBOL(smp, RELOC_SYMBOL(r))->nz_strx; - else - sym = ""; - - if (!ld_suppress_warnings && ld_warn_non_pure_code) - warnx("warning: non pure code in %s at %x (%s)", - 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) { - generror ("mprotect failed for \"%s\" : %s", - smp->som_path, strerror (errno)); - return -1; - } - - smp->som_write = 1; - return 0; -} - -static int -reloc_map(smp, bind_now) - struct so_map *smp; - int bind_now; -{ - /* - * Caching structure for reducing the number of calls to - * lookup() during relocation. - * - * While relocating a given shared object, the dynamic linker - * maintains a caching vector that is directly indexed by - * the symbol number in the relocation entry. The first time - * a given symbol is looked up, the caching vector is - * filled in with a pointer to the symbol table entry, and - * a pointer to the so_map of the shared object in which the - * symbol was defined. On subsequent uses of the same symbol, - * that information is retrieved directly from the caching - * vector, without calling lookup() again. - * - * A symbol that is referenced in a relocation entry is - * typically referenced in many relocation entries, so this - * caching reduces the number of calls to lookup() - * dramatically. The overall improvement in the speed of - * dynamic linking is also dramatic -- as much as a factor - * of three for programs that use many shared libaries. - */ - struct cacheent { - struct nzlist *np; /* Pointer to symbol entry */ - struct so_map *src_map; /* Shared object that defined symbol */ - }; - - 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); - long numsyms = LD_STABSZ(dp) / symsize; - size_t cachebytes = numsyms * sizeof(struct cacheent); - struct cacheent *symcache = - (struct cacheent *) alloca(cachebytes); - - if(symcache == NULL) { - generror("Cannot allocate symbol caching vector for %s", - smp->som_path); - return -1; - } - bzero(symcache, cachebytes); - - if (LD_PLTSZ(dp)) - md_fix_jmpslot(LM_PLT(smp), - (long)LM_PLT(smp), (long)binder_entry); - - for (; r < rend; r++) { - char *sym; - caddr_t addr; - - /* - * Objects linked with "-Bsymbolic" can end up having unused - * relocation entries at the end. These can be detected by - * the fact that they have an address of 0. - */ - if(r->r_address == 0) /* Finished relocating this object */ - break; - - addr = smp->som_addr + r->r_address; - if (check_text_reloc(r, smp, addr) < 0) - return -1; - - if (RELOC_EXTERN_P(r)) { - struct so_map *src_map = NULL; - struct nzlist *p, *np; - long relocation; - - if (RELOC_JMPTAB_P(r) && !bind_now) - continue; - - p = (struct nzlist *) - (symbolbase + symsize * RELOC_SYMBOL(r)); - - if (p->nz_type == (N_SETV + N_EXT)) - src_map = smp; - - sym = stringbase + p->nz_strx; - - /* - * Look up the symbol, checking the caching - * vector first. - */ - np = symcache[RELOC_SYMBOL(r)].np; - if(np != NULL) /* Symbol already cached */ - src_map = symcache[RELOC_SYMBOL(r)].src_map; - else { /* Symbol not cached yet */ - np = lookup(sym, &src_map, RELOC_JMPTAB_P(r)); - /* - * Record the needed information about - * the symbol in the caching vector, - * so that we won't have to call - * lookup the next time we encounter - * the symbol. - */ - symcache[RELOC_SYMBOL(r)].np = np; - symcache[RELOC_SYMBOL(r)].src_map = src_map; - } - - if (np == NULL) { - generror ("Undefined symbol \"%s\" in %s:%s", - sym, main_progname, smp->som_path); - return -1; - } - - /* - * Found symbol definition. - * If it's in a link map, adjust value - * according to the load address of that map. - * Otherwise it's a run-time allocated common - * whose value is already up-to-date. - */ - relocation = np->nz_value; - if (src_map) - relocation += (long)src_map->som_addr; - - if (RELOC_JMPTAB_P(r)) { - md_bind_jmpslot(relocation, addr); - continue; - } - - relocation += md_get_addend(r, addr); - - if (RELOC_PCREL_P(r)) - relocation -= (long)smp->som_addr; - - if (RELOC_COPY_P(r) && src_map) { - (void)enter_rts(sym, sym_hash(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 (smp->som_write) { - if (mprotect(smp->som_addr + LM_TXTADDR(smp), - LD_TEXTSZ(smp->som_dynamic), - PROT_READ|PROT_EXEC) == -1) { - generror ("mprotect failed for \"%s\" : %s", - smp->som_path, strerror (errno)); - return -1; - } - smp->som_write = 0; - } - return 0; -} - -static void -reloc_copy(smp) - struct so_map *smp; -{ - struct rt_symbol *rtsp; - - for (rtsp = rt_symbol_head; rtsp; rtsp = rtsp->rt_next) - 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); - } -} - -/* - * Initialize the DAG of shared objects rooted at the given object. - */ -static void -init_dag(smp) - struct so_map *smp; -{ - struct somap_private *smpp = LM_PRIVATE(smp); - - if(!(smpp->spd_flags & RTLD_INIT)) { /* Not initialized yet */ - smpp->spd_flags |= RTLD_INIT; - - /* Make sure all the children are initialized */ - if(smpp->spd_children != NULL) - init_sods(smpp->spd_children); - - if(call_map(smp, ".init") == -1) - call_map(smp, "__init"); - } -} - -static void -init_sods(solp) - struct so_list *solp; -{ - /* Recursively initialize the rest of the list */ - if(solp->sol_next != NULL) - init_sods(solp->sol_next); - - /* Initialize the first element of the list */ - init_dag(solp->sol_map); -} - - -/* - * Call a function in a given shared object. SMP is the shared object, and - * SYM is the name of the function. - * - * Returns 0 on success, or -1 if the symbol was not found. Failure is not - * necessarily an error condition, so no error message is generated. - */ -static int -call_map(smp, sym) - struct so_map *smp; - char *sym; -{ - struct so_map *src_map = smp; - struct nzlist *np; - - np = lookup(sym, &src_map, 1); - if (np) { - (*(void (*)())(src_map->som_addr + np->nz_value))(); - return 0; - } - - return -1; -} - -/* - * Run-time common symbol table. - */ - -#define RTC_TABSIZE 57 -static struct rt_symbol *rt_symtab[RTC_TABSIZE]; - -/* - * Look up a symbol in the run-time common symbol table. For efficiency, - * the symbol's hash value must be passed in too. - */ -static inline struct rt_symbol * -lookup_rts(name, hash) - char *name; - unsigned long hash; -{ - register struct rt_symbol *rtsp; - - for (rtsp = rt_symtab[hash % RTC_TABSIZE]; rtsp; rtsp = rtsp->rt_link) - if (strcmp(name, rtsp->rt_sp->nz_name) == 0) - return rtsp; - - return NULL; -} - -/* - * Enter a symbol into the run-time common symbol table. For efficiency, - * the symbol's hash value must be passed in too. - */ -static struct rt_symbol * -enter_rts(name, hash, value, type, srcaddr, size, smp) - char *name; - unsigned long hash; - long value; - int type; - caddr_t srcaddr; - long size; - struct so_map *smp; -{ - register struct rt_symbol *rtsp, **rpp; - - /* Find end of bucket */ - for (rpp = &rt_symtab[hash % RTC_TABSIZE]; *rpp; rpp = &(*rpp)->rt_link) - continue; - - /* Allocate new common symbol */ - rtsp = (struct rt_symbol *)xmalloc(sizeof(struct rt_symbol)); - rtsp->rt_sp = (struct nzlist *)xmalloc(sizeof(struct nzlist)); - rtsp->rt_sp->nz_name = strdup(name); - rtsp->rt_sp->nz_value = value; - rtsp->rt_sp->nz_type = type; - rtsp->rt_sp->nz_size = size; - rtsp->rt_srcaddr = srcaddr; - rtsp->rt_smp = smp; - rtsp->rt_link = NULL; - - /* Link onto linear list as well */ - rtsp->rt_next = rt_symbol_head; - rt_symbol_head = rtsp; - - *rpp = rtsp; - - return rtsp; -} - - -/* - * Lookup NAME in the link maps. The link map producing a definition - * is returned in SRC_MAP. If SRC_MAP is not NULL on entry the search - * is confined to that map. - * - * REAL_DEF_ONLY is a boolean which specifies whether certain special - * symbols for functions should satisfy the lookup or not. The - * reasons behind it are somewhat complicated. They are motivated - * by the scenario in which the address of a single function is - * taken from several shared objects. The address should come out - * the same in all cases, because the application code might decide - * to use it in comparisons. To make this work, the linker creates - * a symbol entry for the function in the main executable, with a - * type of N_UNDF+N_EXT, an N_AUX of AUX_FUNC, and a value that - * refers to the PLT entry for the function in the main executable. - * If REAL_DEF_ONLY is false, then this kind of special symbol is - * considered a "definition" when lookup up the symbol. Since the - * main executable is at the beginning of the shared object search - * list, the result is that references from all shared objects will - * resolve to the main program's PLT entry, and thus the function - * addresses will compare equal as they should. - * - * When relocating the PLT entry itself, we obviously must match - * only the true defining symbol for the function. In that case, we - * set REAL_DEF_ONLY to true, which disables matching the special - * N_UNDF+N_EXT entries. - * - * It is not so clear how to set this flag for a lookup done from - * dlsym. If the lookup specifies a particular shared object other - * than the main executable, the flag makes no difference -- only the - * true definition will be matched. (That is because the special - * symbols are only present in the main executable, which will not - * be searched.) But when the lookup is over all the shared objects - * (i.e., dlsym's "fd" parameter is NULL), then the flag does have an - * effect. We elect to match only the true definition even in that - * case. - * - * The upshot of all this is the following rule of thumb: Set - * REAL_DEF_ONLY in all cases except when processing a non-PLT - * relocation. - */ -static struct nzlist * -lookup(name, src_map, real_def_only) - char *name; - struct so_map **src_map; /* IN/OUT */ - int real_def_only; -{ - unsigned long hash; - - hash = sym_hash(name); - - if (*src_map != NULL) /* Look in just one specific object */ - return lookup_in_obj(name, hash, *src_map, real_def_only); - else { /* Search runtime symbols and all loaded objects */ - unsigned long common_size; - struct so_map *smp; - struct rt_symbol *rtsp; - struct nzlist *np; - - if ((rtsp = lookup_rts(name, hash)) != NULL) - return rtsp->rt_sp; - - common_size = 0; - for (smp = link_map_head; smp; smp = smp->som_next) { - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - continue; - np = lookup_in_obj(name, hash, smp, real_def_only); - if (np == NULL) - continue; - /* We know that np->nz_value > 0 at this point. */ - if (np->nz_type == N_UNDF+N_EXT && - N_AUX(&np->nlist) != AUX_FUNC) { /* Common */ - if (common_size < np->nz_value) - common_size = np->nz_value; - continue; - } - - /* We found the symbol definition. */ - *src_map = smp; - return np; - } - if (common_size > 0) { /* It is a common symbol. */ - void *mem; - - mem = memset(xmalloc(common_size), 0, common_size); - rtsp = enter_rts(name, hash, (long)mem, N_UNDF + N_EXT, - 0, common_size, NULL); - return rtsp->rt_sp; - } - - /* - * Just before giving up, check for the __error() hack. - */ - np = lookup_errno_hack(name, src_map, real_def_only); - if (np != NULL) - return np; - - /* No definition was found for the symbol. */ - return NULL; - } -} - -/* - * Lookup a symbol in one specific shared object. The hash - * value is passed in for efficiency. For an explanation of the - * "real_def_only" flag, see the comment preceding the "lookup" - * function. - */ -static struct nzlist * -lookup_in_obj(name, hash, smp, real_def_only) - char *name; - unsigned long hash; - struct so_map *smp; - int real_def_only; -{ - unsigned long buckets; - struct rrs_hash *hp; - char *cp; - struct nzlist *np; - char *symbolbase; - struct rrs_hash *hashbase; - char *stringbase; - size_t symsize; - - if ((buckets = LD_BUCKETS(smp->som_dynamic)) == 0) - return NULL; - - hashbase = LM_HASH(smp); - -restart: - hp = &hashbase[hash % buckets]; - if (hp->rh_symbolnum == -1) - return NULL; - - symbolbase = (char *)LM_SYMBOL(smp, 0); - stringbase = LM_STRINGS(smp); - symsize = LD_VERSION_NZLIST_P(smp->som_dynamic->d_version)? - sizeof(struct nzlist) : sizeof(struct nlist); - for ( ; ; ) { - np = (struct nzlist *)(symbolbase + hp->rh_symbolnum*symsize); - cp = stringbase + np->nz_strx; - if (strcmp(cp, name) == 0) - break; - if (hp->rh_next == 0) /* End of hash chain */ - return NULL; - hp = hashbase + hp->rh_next; - } - - /* - * We have a symbol with the name we're looking for. - */ - if (np->nz_type == N_INDR+N_EXT) { - /* - * Next symbol gives the aliased name. Restart - * search with new name. - */ - name = stringbase + (++np)->nz_strx; - hash = sym_hash(name); - goto restart; - } - - if (np->nz_value == 0) /* It's not a definition */ - return NULL; - - if (real_def_only) /* Don't match special function symbols. */ - if (np->nz_type == N_UNDF+N_EXT && - N_AUX(&np->nlist) == AUX_FUNC) - return NULL; - - return np; -} - -/* - * Return the value of a symbol in the user's program. This is used - * internally for a few symbols which must exist. If the requested - * symbol is not found, this simply exits with a fatal error. - */ -static void * -sym_addr(name) - char *name; -{ - struct so_map *smp; - struct nzlist *np; - - smp = NULL; - np = lookup(name, &smp, 1); - if (np == NULL) - errx(1, "Program has no symbol \"%s\"", name); - return ((smp == NULL) ? NULL : smp->som_addr) + np->nz_value; -} - - -static int *p_errno; /* Pointer to errno variable in main program. */ - -/* - * Help old a.out binaries that are broken by the new errno macro. They - * can be missing __error() through no fault of their own. In particular, - * old a.out binaries can link against an old libc that does not contain - * __error(), yet still require __error() because of other libraries that - * have been recompiled since the errno change. This locates the backward - * compatible work-alike we have hidden here in ld.so. - */ -static struct nzlist * -lookup_errno_hack(sym, src_map, real_def_only) - char *sym; - struct so_map **src_map; - int real_def_only; -{ - struct so_map *smp; - struct nzlist *np; - - if (strcmp(sym, "___error") != 0) - return NULL; - - /* - * Locate errno in the main program. If it's not there, NULL - * will be returned by our __error() substitute, and a core dump - * will follow. That's impossible, of course, since crt0.o always - * supplies errno. - */ - smp = NULL; - np = lookup("_errno", &smp, 1); - if (np != NULL && smp != NULL) { - p_errno = (int *)(smp->som_addr + np->nz_value); -#ifdef DEBUG - xprintf(" HACK: _errno at %p in %s\n", p_errno, smp->som_path); -#endif - } - - /* - * Specifically find the ld.so link map because most routines - * skip over it during normal operation. - */ - for (smp = link_map_head; ; smp = smp->som_next) - if (LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - break; - - /* - * Find our __error() substitute stashed here in ld.so. - */ - np = lookup("___error_unthreaded_hack", &smp, real_def_only); - if (np != NULL) - *src_map = smp; - -#ifdef DEBUG - if (np == NULL) - xprintf(" HACK: %s fudge not found, oops\n", sym); - else - xprintf(" HACK: %s fudge in %s\n", sym, smp->som_path); -#endif - - return np; -} - - -/* - * Just like __error_unthreaded(), but for those poor orphaned a.out - * binaries from way back that are bamboozled by the new errno macro. - */ -int * -__error_unthreaded_hack() -{ - return p_errno; -} - - -/* - * 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) - errx(1, "Call to binder from unknown location: %p\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) - errx(1, "Undefined symbol \"%s\" called from %s:%s at %p", - 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; /* NULL means not mapped */ -static struct hints_bucket *hbuckets; -static char *hstrtab; - -/* - * Map the hints file into memory, if it is not already mapped. Returns - * 0 on success, or -1 on failure. - */ -static int -maphints __P((void)) -{ - static int hints_bad; /* TRUE if hints are unusable */ - static int paths_added; - int hfd; - struct hints_header hdr; - caddr_t addr; - - if (hheader != NULL) /* Already mapped */ - return 0; - - if (hints_bad) /* Known to be corrupt or unavailable */ - return -1; - - if ((hfd = open(_PATH_LD_HINTS, O_RDONLY, 0)) == -1) { - hints_bad = 1; - return -1; - } - - /* Read the header and check it */ - - if (read(hfd, &hdr, sizeof hdr) != sizeof hdr || - HH_BADMAG(hdr) || - (hdr.hh_version != LD_HINTS_VERSION_1 && - hdr.hh_version != LD_HINTS_VERSION_2)) { - close(hfd); - hints_bad = 1; - return -1; - } - - /* Map the hints into memory */ - - addr = mmap(0, hdr.hh_ehints, PROT_READ, MAP_SHARED, hfd, 0); - if (addr == (caddr_t)-1) { - close(hfd); - hints_bad = 1; - return -1; - } - - close(hfd); - - hheader = (struct hints_header *)addr; - hbuckets = (struct hints_bucket *)(addr + hheader->hh_hashtab); - hstrtab = (char *)(addr + hheader->hh_strtab); - /* pluck out the system ldconfig path */ - if (hheader->hh_version >= LD_HINTS_VERSION_2 && !paths_added) { - add_search_path(hstrtab + hheader->hh_dirlist); - paths_added = 1; - } - - return 0; -} - -/* - * Unmap the hints file, if it is currently mapped. - */ -static void -unmaphints() -{ - if (hheader != NULL) { - munmap((caddr_t)hheader, hheader->hh_ehints); - hheader = NULL; - } -} - -int -hinthash(cp, vmajor) - char *cp; - int vmajor; -{ - int k = 0; - - while (*cp) - k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; - - k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; - - return k; -} - -#undef major -#undef minor - -/* - * Search for a library in the hints generated by ldconfig. On success, - * returns the full pathname of the matching library. This string is - * always dynamically allocated on the heap. - * - * MINORP is an in/out parameter. If the incoming value of *MINORP is - * >= 0, then no library will be considered a match unless its minor - * version number is at least that large. Otherwise, only the major - * version number is checked. In any case, the minor number of the - * matching library is stored into *MINORP. - * - * Returns NULL if the library cannot be found. - */ -static char * -findhint(name, major, minorp) - char *name; - int major; - int *minorp; -{ - struct hints_bucket *bp = - hbuckets + (hinthash(name, major) % hheader->hh_nbucket); - - while (1) { - /* Sanity check */ - if (bp->hi_namex >= hheader->hh_strtab_sz) { - warnx("Bad name index: %#x\n", bp->hi_namex); - break; - } - if (bp->hi_pathx >= hheader->hh_strtab_sz) { - warnx("Bad path index: %#x\n", bp->hi_pathx); - break; - } - /* - * For a given major number, the hints file has only one - * entry -- namely, the one with the highest minor number. - * If we find an entry with a matching major number, we - * know it is the best one. - */ - if (strcmp(name, hstrtab + bp->hi_namex) == 0 && - bp->hi_major == major) { - struct stat s; - int realminor; - - realminor = bp->hi_ndewey >= 2 ? bp->hi_minor : 0; - if (realminor < *minorp) /* Not good enough */ - return NULL; - if (stat(hstrtab + bp->hi_pathx, &s) == -1) - return NULL; /* Doesn't actually exist */ - *minorp = realminor; - return strdup(hstrtab + bp->hi_pathx); - } - - if (bp->hi_next == -1) - break; - - /* Move on to next in bucket */ - bp = &hbuckets[bp->hi_next]; - } - - /* No hints available for name */ - return NULL; -} - -/* - * Search for the given shared library. On success, returns a string - * containing the full pathname for the library. This string is always - * dynamically allocated on the heap. - * - * Returns NULL if the library cannot be found. - */ -static char * -rtfindlib(name, major, minor, strictminor) - char *name; - int major, minor; - int strictminor; -{ - char *ld_path = ld_library_path; - char *path = NULL; - int realminor; - - realminor = strictminor ? minor : -1; - if (ld_path != NULL) { /* First, search the directories in ld_path */ - /* - * There is no point in trying to use the hints file for this. - */ - char *dir; - - while (path == NULL && (dir = strsep(&ld_path, ":")) != NULL) { - path = search_lib_dir(dir, name, &major, &realminor, 0); - if (ld_path != NULL) - *(ld_path - 1) = ':'; - } - } - - if (path == NULL && maphints() == 0) /* Search the hints file */ - path = findhint(name, major, &realminor); - - if (path == NULL) /* Search the standard directories */ - path = findshlib(name, &major, &realminor, 0); - - if (path != NULL && realminor < minor && !ld_suppress_warnings) { - warnx("warning: %s: minor version %d" - " older than expected %d, using it anyway", - path, realminor, minor); - } - - return path; -} - -/* - * Search for the given shared library file. This is similar to rtfindlib, - * except that the argument is the actual name of the desired library file. - * Thus there is no need to worry about version numbers. The return value - * is a string containing the full pathname for the library. This string - * is always dynamically allocated on the heap. - * - * Returns NULL if the library cannot be found. - */ -static char * -rtfindfile(name) - const char *name; -{ - char *ld_path = ld_library_path; - char *path = NULL; - - if (ld_path != NULL) { /* First, search the directories in ld_path */ - char *dir; - - while (path == NULL && (dir = strsep(&ld_path, ":")) != NULL) { - struct stat sb; - - path = concat(dir, "/", name); - if (lstat(path, &sb) == -1) { /* Does not exist */ - free(path); - path = NULL; - } - if (ld_path != NULL) - *(ld_path - 1) = ':'; - } - } - - /* - * We don't search the hints file. It is organized around major - * and minor version numbers, so it is not suitable for finding - * a specific file name. - */ - - if (path == NULL) /* Search the standard directories */ - path = find_lib_file(name); - - return path; -} - -/* - * Buffer for error messages and a pointer that is set to point to the buffer - * when an error occurs. It acts as a last error flag, being set to NULL - * after an error is returned. - */ -#define DLERROR_BUF_SIZE 512 -static char dlerror_buf [DLERROR_BUF_SIZE]; -static char *dlerror_msg = NULL; - - -static void * -__dlopen(path, mode) - const char *path; - int mode; -{ - struct so_map *old_tail = link_map_tail; - struct so_map *smp; - int bind_now = mode == RTLD_NOW; - char *name; - - /* - * path == NULL is handled by map_object() - */ - - anon_open(); - - name = (path && strchr(path, '/') == NULL) ? rtfindfile(path) : (char *)path; - - /* Map the object, and the objects on which it depends */ - smp = map_object(name, (struct sod *) NULL, (struct so_map *) NULL); - if (name != path) - free(name); - if(smp == NULL) /* Failed */ - return NULL; - LM_PRIVATE(smp)->spd_flags |= RTLD_DL; - - /* Relocate and initialize all newly-mapped objects */ - if(link_map_tail != old_tail) { /* We have mapped some new objects */ - if(reloc_dag(smp, bind_now) == -1) /* Failed */ - return NULL; - init_dag(smp); - } - - unmaphints(); - anon_close(); - - return smp; -} - -static int -__dlclose(fd) - void *fd; -{ - struct so_map *smp = (struct so_map *)fd; - struct so_map *scanp; - -#ifdef DEBUG - xprintf("dlclose(%s): refcount = %d\n", smp->som_path, - LM_PRIVATE(smp)->spd_refcount); -#endif - /* Check the argument for validity */ - for(scanp = link_map_head; scanp != NULL; scanp = scanp->som_next) - if(scanp == smp) /* We found the map in the list */ - break; - if(scanp == NULL || !(LM_PRIVATE(smp)->spd_flags & RTLD_DL)) { - generror("Invalid argument to dlclose"); - return -1; - } - - unmap_object(smp, 0); - - return 0; -} - -/* - * This form of dlsym is obsolete. Current versions of crt0 don't call - * it. It can still be called by old executables that were linked with - * old versions of crt0. - */ -static void * -__dlsym(fd, sym) - void *fd; - const char *sym; -{ - if (fd == RTLD_NEXT) { - generror("RTLD_NEXT not supported by this version of" - " crt0.o"); - return NULL; - } - return __dlsym3(fd, sym, NULL); -} - -static void * -resolvesym(fd, sym, retaddr) - void *fd; - char *sym; - void *retaddr; -{ - struct so_map *smp; - struct so_map *src_map; - struct nzlist *np; - long addr; - - if (fd == RTLD_NEXT) { - /* Find the shared object that contains the caller. */ - for (smp = link_map_head; smp != NULL; smp = smp->som_next) { - void *textbase = smp->som_addr + LM_TXTADDR(smp); - void *textlimit = LM_ETEXT(smp); - - if (textbase <= retaddr && retaddr < textlimit) - break; - } - if (smp == NULL) { - generror("Cannot determine caller's shared object"); - return NULL; - } - smp = smp->som_next; - if (smp != NULL && LM_PRIVATE(smp)->spd_flags & RTLD_RTLD) - smp = smp->som_next; - if (smp == NULL) { - generror("No next shared object for RTLD_NEXT"); - return NULL; - } - do { - src_map = smp; - np = lookup(sym, &src_map, 1); - } while (np == NULL && (smp = smp->som_next) != NULL); - } else { - smp = (struct so_map *)fd; - src_map = NULL; - - /* - * Restrict search to passed map if dlopen()ed. - */ - if (smp != NULL && LM_PRIVATE(smp)->spd_flags & RTLD_DL) - src_map = smp; - - np = lookup(sym, &src_map, 1); - } - - if (np == NULL) { - generror("Undefined symbol"); - return NULL; - } - - addr = np->nz_value; - if (src_map) - addr += (long)src_map->som_addr; - - return (void *)addr; -} - -static int -__dladdr(addr, dlip) - const void *addr; - Dl_info *dlip; -{ - struct _dynamic *dp; - struct so_map *smp; - char *stringbase; - long numsyms; - int symsize; - int i; - - /* Find the shared object that contains the address. */ - for (smp = link_map_head; smp != NULL; smp = smp->som_next) { - struct so_map *src_map; - struct somap_private *smpp; - struct nzlist *np; - - smpp = LM_PRIVATE(smp); - if (smpp->spd_flags & RTLD_RTLD) - continue; - - if ((void *)smp->som_addr > addr) - continue; - - src_map = smp; - if ((np = lookup(END_SYM, &src_map, 1)) == NULL) - continue; /* No "_end" symbol?! */ - if (addr < (void *)(smp->som_addr + np->nz_value)) - break; - } - if (smp == NULL) { - generror("No shared object contains address"); - return 0; - } - dlip->dli_fname = smp->som_path; - dlip->dli_fbase = smp->som_addr; - dlip->dli_saddr = (void *) 0; - dlip->dli_sname = NULL; - - dp = smp->som_dynamic; - symsize = LD_VERSION_NZLIST_P(dp->d_version) ? - sizeof(struct nzlist) : sizeof(struct nlist); - numsyms = LD_STABSZ(dp) / symsize; - stringbase = LM_STRINGS(smp); - - for (i = 0; i < numsyms; i++) { - struct nzlist *symp = LM_SYMBOL(smp, i); - unsigned long value; - - /* Reject all except definitions. */ - if (symp->nz_type != N_EXT + N_ABS && - symp->nz_type != N_EXT + N_TEXT && - symp->nz_type != N_EXT + N_DATA && - symp->nz_type != N_EXT + N_BSS) - continue; - - /* - * If the symbol is greater than the specified address, or - * if it is further away from addr than the current nearest - * symbol, then reject it. - */ - value = (unsigned long) (smp->som_addr + symp->nz_value); - if (value > (unsigned long) addr || - value < (unsigned long) dlip->dli_saddr) - continue; - - /* Update our idea of the nearest symbol. */ - dlip->dli_sname = stringbase + symp->nz_strx; - dlip->dli_saddr = (void *) value; - - if (dlip->dli_saddr == addr) /* Can't get any closer. */ - break; - } - /* - * Remove any leading underscore from the symbol name, to hide - * our a.out-ness. - */ - if (dlip->dli_sname != NULL && dlip->dli_sname[0] == '_') - dlip->dli_sname++; - return 1; -} - -static void * -__dlsym3(fd, sym, retaddr) - void *fd; - const char *sym; - void *retaddr; -{ - void *result; - - result = resolvesym(fd, sym, retaddr); - /* - * XXX - Ugly, but it makes the least impact on the run-time loader - * sources. We assume that most of the time the error is a - * undefined symbol error from above, so we try again. If it's - * not an undefined symbol we end up getting the same error twice, - * but that's acceptable. - */ - if (result == NULL) { - /* Prepend an underscore and try again */ - char *newsym = xmalloc(strlen(sym) + 2); - - newsym[0] = '_'; - strcpy(&newsym[1], sym); - result = resolvesym(fd, newsym, retaddr); - free(newsym); - } - return result; -} - -static const char * -__dlerror __P((void)) -{ - const char *err; - - err = dlerror_msg; - dlerror_msg = NULL; /* Next call will return NULL */ - - return err; -} - -static void -__dlexit __P((void)) -{ -#ifdef DEBUG -xprintf("__dlexit called\n"); -#endif - - unmap_object(link_map_head, 1); -} - -/* - * Print the current error message and exit with failure status. - */ -static void -die __P((void)) -{ - const char *msg; - - fprintf(stderr, "ld.so failed"); - if ((msg = __dlerror()) != NULL) - fprintf(stderr, ": %s", msg); - putc('\n', stderr); - _exit(1); -} - - -/* - * Generate an error message that can be later be retrieved via dlerror. - */ -static void -generror(char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsnprintf (dlerror_buf, DLERROR_BUF_SIZE, fmt, ap); - dlerror_msg = dlerror_buf; - - va_end(ap); -} - -void -xprintf(char *fmt, ...) -{ - char buf[256]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - (void)write(STDOUT_FILENO, buf, strlen(buf)); - va_end(ap); -} - -/* - * rt_readenv() etc. - * - * Do a sweep over the environment once only, pick up what - * looks interesting. - * - * This is pretty obscure, but is relatively simple. Simply - * look at each environment variable, if it starts with "LD_" then - * look closer at it. If it's in our table, set the variable - * listed. effectively, this is like: - * ld_preload = careful ? NULL : getenv("LD_PRELOAD"); - * except that the environment is scanned once only to pick up all - * known variables, rather than scanned multiple times for each - * variable. - * - * If an environment variable of interest is set to the empty string, we - * treat it as if it were unset. - */ - -#define L(n, u, v) { n, sizeof(n) - 1, u, v }, -struct env_scan_tab { - char *name; - int len; - int unsafe; - char **value; -} scan_tab[] = { - L("LD_LIBRARY_PATH=", 1, &ld_library_path) - L("LD_PRELOAD=", 1, &ld_preload) - L("LD_IGNORE_MISSING_OBJECTS=", 1, &ld_ignore_missing_objects) - L("LD_TRACE_LOADED_OBJECTS=", 0, &ld_tracing) - L("LD_BIND_NOW=", 0, &ld_bind_now) - L("LD_SUPPRESS_WARNINGS=", 0, &ld_suppress_warnings) - L("LD_WARN_NON_PURE_CODE=", 0, &ld_warn_non_pure_code) - { NULL, 0, 0, NULL } -}; -#undef L - -static void -rt_readenv() -{ - char **p = environ; - char *v; - struct env_scan_tab *t; - - /* for each string in the environment... */ - while ((v = *p++)) { - - /* check for LD_xxx */ - if (v[0] != 'L' || v[1] != 'D' || v[2] != '_') - continue; - - for (t = scan_tab; t->name; t++) { - if (careful && t->unsafe) - continue; /* skip for set[ug]id */ - if (strncmp(t->name, v, t->len) == 0) { - if (*(v + t->len) != '\0') /* Not empty */ - *t->value = v + t->len; - break; - } - } - } -} - -/* - * Malloc implementation for use within the dynamic linker. At first - * we do a simple allocation using sbrk. After the user's program - * has been loaded, we switch to using whatever malloc functions are - * defined there. - */ - -/* Symbols related to the sbrk and brk implementations. */ -#define CURBRK_SYM "curbrk" -#define MINBRK_SYM "minbrk" -#define END_SYM "_end" - -/* Symbols related to malloc. */ -#define FREE_SYM "_free" -#define MALLOC_SYM "_malloc" -#define REALLOC_SYM "_realloc" - -/* Hooks into the implementation of sbrk and brk. */ -extern char *curbrk __asm__(CURBRK_SYM); -extern char *minbrk __asm__(MINBRK_SYM); - -/* Pointers to the user program's malloc functions. */ -static void *(*p_malloc) __P((size_t)); -static void *(*p_realloc) __P((void *, size_t)); -static void (*p_free) __P((void *)); - -/* Upper limit of the memory allocated by our internal malloc. */ -static char *rtld_alloc_lev; - -/* - * Set up the internal malloc so that it will take its memory from the - * main program's sbrk arena. - */ -static void -init_internal_malloc __P((void)) -{ - const struct exec *hdr; - - /* - * Before anything calls sbrk or brk, we have to initialize - * its idea of the current break level to just beyond the main - * program's address space. Strictly speaking, the right - * way to do that is to look up the value of "_end" in the - * application's run time symbol table. - * - * That is what we used to do, and it works correctly for - * every valid program. Unfortunately, it doesn't work right - * for "unexec"ed versions of emacs. They are incorrectly - * generated with a wrong value for "_end". (xemacs gets it - * right.) - * - * To work around this, we peek at the exec header to get the - * sizes of the text, data, and bss segments. Luckily, the - * header is in memory at the start of the first mapped page. - * From the segment sizes, we can calculate a proper initial - * value for the break level. - */ - hdr = (const struct exec *)PAGSIZ; - if (N_BADMAG(*hdr)) /* Sanity check */ - errx(1, "Cannot find program's a.out header"); - rtld_alloc_lev = curbrk = minbrk = - (char *)hdr + hdr->a_text + hdr->a_data + hdr->a_bss; -} - -/* - * Set things up so that the dynamic linker can use the program's - * malloc functions. - */ -static void -init_external_malloc __P((void)) -{ - /* - * Patch the program's idea of the current break address to - * what it really is as a result of the allocations we have - * already done. - */ - *(char **)(sym_addr(CURBRK_SYM)) = curbrk; - - /* - * Set the minimum break level too. Otherwise, "unexec"ed - * emacs sets the break too low and wipes out our tables of - * shared objects. - */ - *(char **)(sym_addr(MINBRK_SYM)) = curbrk; - - /* - * Set up pointers to the program's allocation functions, so - * that we can use them from now on. - */ - p_malloc = (void *(*)(size_t))(sym_addr(MALLOC_SYM)); - p_free = (void (*)(void *))(sym_addr(FREE_SYM)); - p_realloc = (void *(*)(void *, size_t))(sym_addr(REALLOC_SYM)); -} - -void * -malloc(size) - size_t size; -{ - char *p; - - /* If we are far enough along, we can use the system malloc. */ - if (p_malloc != NULL) - return (*p_malloc)(size); - - /* - * Otherwise we use our simple built-in malloc. We get the - * memory from brk() in increments of one page. We store the - * allocated size in the first word, so that realloc can be - * made to work. - */ - if (rtld_alloc_lev == NULL) - errx(1, "Internal error: internal malloc called before" - " being initialized"); - - p = (char *)ALIGN(rtld_alloc_lev); - rtld_alloc_lev = p + sizeof(size_t) + size; - - if (rtld_alloc_lev > curbrk) { /* Get memory from system */ - char *newbrk; - - newbrk = (char *) - roundup2((unsigned long)rtld_alloc_lev, PAGSIZ); - if (brk(newbrk) == -1) - return NULL; - } - - *(size_t *)p = size; - return p + sizeof(size_t); -} - -void * -realloc(ptr, size) - void *ptr; - size_t size; -{ - size_t old_size; - void *new_ptr; - - if (ptr == NULL) - return malloc(size); - - /* - * If we are far enough along, and if the memory originally came - * from the system malloc, we can use the system realloc. - */ - if (p_realloc != NULL && (char *)ptr >= rtld_alloc_lev) - return (*p_realloc)(ptr, size); - - old_size = *((size_t *)ptr - 1); - if (old_size >= size) /* Not expanding the region */ - return ptr; - - new_ptr = malloc(size); - if (new_ptr != NULL) - memcpy(new_ptr, ptr, old_size); - return new_ptr; -} - -void -free(ptr) - void *ptr; -{ - if (ptr == NULL) - return; - - /* - * If we are far enough along, and if the memory originally came - * from the system malloc, we can use the system free. Otherwise - * we can't free the memory and we just let it go to waste. - */ - if (p_free != NULL && (char *)ptr >= rtld_alloc_lev) - (*p_free)(ptr); -} diff --git a/libexec/rtld-aout/shlib.c b/libexec/rtld-aout/shlib.c deleted file mode 100644 index 9fd2c66..0000000 --- a/libexec/rtld-aout/shlib.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * 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. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "shlib.h" -#include "support.h" - -/* - * Standard directories to search for files specified by -l. - */ -#ifndef STANDARD_SEARCH_DIRS -#define STANDARD_SEARCH_DIRS "/usr/lib/aout" -#endif - -/* - * Actual vector of library search directories, - * including `-L'ed and LD_LIBRARY_PATH spec'd ones. - */ -char **search_dirs; -int n_search_dirs; - -char *standard_search_dirs[] = { - STANDARD_SEARCH_DIRS -}; - - -void -add_search_dir(name) - char *name; -{ - int n; - - for (n = 0; n < n_search_dirs; n++) - if (strcmp(search_dirs[n], name) == 0) - return; - n_search_dirs++; - search_dirs = (char **) - xrealloc(search_dirs, n_search_dirs * sizeof search_dirs[0]); - search_dirs[n_search_dirs - 1] = strdup(name); -} - -void -add_search_path(path) -char *path; -{ - register char *cp, *dup; - - if (path == NULL) - return; - - /* Add search directories from `path' */ - path = dup = strdup(path); - while ((cp = strsep(&path, ":")) != NULL) - add_search_dir(cp); - free(dup); -} - -void -std_search_path() -{ - int i, n; - - /* Append standard search directories */ - n = sizeof standard_search_dirs / sizeof standard_search_dirs[0]; - for (i = 0; i < n; i++) - add_search_dir(standard_search_dirs[i]); -} - -/* - * Return true if CP points to a valid dewey number. - * Decode and leave the result in the array DEWEY. - * Return the number of decoded entries in DEWEY. - */ - -int -getdewey(dewey, cp) -int dewey[]; -char *cp; -{ - int i, n; - - for (n = 0, i = 0; i < MAXDEWEY; i++) { - if (*cp == '\0') - break; - - if (*cp == '.') cp++; - if (!isdigit(*cp)) - return 0; - - dewey[n++] = strtol(cp, &cp, 10); - } - - return n; -} - -/* - * Compare two dewey arrays. - * Return -1 if `d1' represents a smaller value than `d2'. - * Return 1 if `d1' represents a greater value than `d2'. - * Return 0 if equal. - */ -int -cmpndewey(d1, n1, d2, n2) -int d1[], d2[]; -int n1, n2; -{ - register int i; - - for (i = 0; i < n1 && i < n2; i++) { - if (d1[i] < d2[i]) - return -1; - if (d1[i] > d2[i]) - return 1; - } - - if (n1 == n2) - return 0; - - if (i == n1) - return -1; - - if (i == n2) - return 1; - - errx(1, "cmpndewey: cant happen"); - return 0; -} - -/* - * Search directories for a shared library matching the given - * major and minor version numbers. See search_lib_dir() below for - * the detailed matching rules. - * - * As soon as a directory with an acceptable match is found, the search - * terminates. Subsequent directories are not searched for a better - * match. This is in conformance with the SunOS searching rules. Also, - * it avoids a lot of directory searches that are virtually guaranteed to - * be fruitless. - * - * The return value is a full pathname to the matching library. The - * string is dynamically allocated. If no matching library is found, the - * function returns NULL. - */ - -char * -findshlib(name, majorp, minorp, do_dot_a) -char *name; -int *majorp, *minorp; -int do_dot_a; -{ - int i; - - for (i = 0; i < n_search_dirs; i++) { - char *path; - - path = search_lib_dir(search_dirs[i], name, majorp, minorp, - do_dot_a); - if(path != NULL) - return path; - } - - return NULL; -} - -/* - * Search library directories for a file with the given name. The - * return value is a full pathname to the matching file. The string - * is dynamically allocated. If no matching file is found, the function - * returns NULL. - */ - -char * -find_lib_file(name) - const char *name; -{ - int i; - - for (i = 0; i < n_search_dirs; i++) { - char *path = concat(search_dirs[i], "/", name); - struct stat sb; - - if (lstat(path, &sb) != -1) /* We found it */ - return path; - - free(path); - } - - return NULL; -} - -/* - * Search a given directory for a library (preferably shared) satisfying - * the given criteria. - * - * The matching rules are as follows: - * - * if(*majorp == -1) - * find the library with the highest major version; - * else - * insist on a major version identical to *majorp; - * - * Always find the library with the highest minor version; - * if(*minorp != -1) - * insist on a minor version >= *minorp; - * - * It is invalid to specify a specific minor number while wildcarding - * the major number. - * - * The actual major and minor numbers found are returned via the pointer - * arguments. - * - * A suitable shared library is always preferred over a static (.a) library. - * If do_dot_a is false, then a static library will not be accepted in - * any case. - * - * The return value is a full pathname to the matching library. The - * string is dynamically allocated. If no matching library is found, the - * function returns NULL. - */ - -char * -search_lib_dir(dir, name, majorp, minorp, do_dot_a) - char *dir; - char *name; - int *majorp; - int *minorp; - int do_dot_a; -{ - int namelen; - DIR *dd; - struct dirent *dp; - int best_dewey[MAXDEWEY]; - int best_ndewey; - char dot_a_name[MAXNAMLEN+1]; - char dot_so_name[MAXNAMLEN+1]; - - if((dd = opendir(dir)) == NULL) - return NULL; - - namelen = strlen(name); - best_ndewey = 0; - dot_a_name[0] = '\0'; - dot_so_name[0] = '\0'; - - while((dp = readdir(dd)) != NULL) { - char *extension; - - if(strlen(dp->d_name) < 3 + namelen + 2 || /* lib+xxx+.a */ - strncmp(dp->d_name, "lib", 3) != 0 || - strncmp(dp->d_name + 3, name, namelen) != 0 || - dp->d_name[3+namelen] != '.') - continue; - - extension = dp->d_name + 3 + namelen + 1; /* a or so.* */ - - if(strncmp(extension, "so.", 3) == 0) { - int cur_dewey[MAXDEWEY]; - int cur_ndewey; - - cur_ndewey = getdewey(cur_dewey, extension+3); - if(cur_ndewey < 2) /* Too few version numbers */ - continue; - - if(*majorp != -1) { /* Need exact match on major */ - if(cur_dewey[0] != *majorp) - continue; - if(*minorp != -1) { /* Need minor >= minimum */ - if(cur_dewey[1] < *minorp) - continue; - } - } - - if(cmpndewey(cur_dewey, cur_ndewey, best_dewey, - best_ndewey) <= 0) /* No better than prior match */ - continue; - - /* We found a better match */ - strcpy(dot_so_name, dp->d_name); - bcopy(cur_dewey, best_dewey, - cur_ndewey * sizeof best_dewey[0]); - best_ndewey = cur_ndewey; - } else if(do_dot_a && strcmp(extension, "a") == 0) - strcpy(dot_a_name, dp->d_name); - } - closedir(dd); - - if(dot_so_name[0] != '\0') { - *majorp = best_dewey[0]; - *minorp = best_dewey[1]; - return concat(dir, "/", dot_so_name); - } - - if(dot_a_name[0] != '\0') - return concat(dir, "/", dot_a_name); - - return NULL; -} diff --git a/libexec/rtld-aout/shlib.h b/libexec/rtld-aout/shlib.h deleted file mode 100644 index d05690f..0000000 --- a/libexec/rtld-aout/shlib.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (C) 1996 - * Peter Wemm. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - *- - * $FreeBSD$ - */ - -/* - * prototypes for shlib.c. Big deal. - */ - -extern char **search_dirs; -extern int n_search_dirs; - -void add_search_dir __P((char *)); -void add_search_path __P((char *)); -void std_search_path __P((void)); -int getdewey __P((int[], char *)); -int cmpndewey __P((int[], int, int[], int)); -char *findshlib __P((char *, int *, int *, int)); -char *find_lib_file __P((const char *)); -char *search_lib_dir __P((char *, char *, int *, int *, int)); diff --git a/libexec/rtld-aout/support.c b/libexec/rtld-aout/support.c deleted file mode 100644 index 71a84ff..0000000 --- a/libexec/rtld-aout/support.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Generic "support" routines to replace those obtained from libiberty for ld. - * - * I've collected these from random bits of (published) code I've written - * over the years, not that they are a big deal. peter@freebsd.org - *- - * Copyright (C) 1996 - * Peter Wemm. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - *- - * $FreeBSD$ - */ -#include -#include -#include -#include - -#include "support.h" - -char * -concat(s1, s2, s3) - const char *s1, *s2, *s3; -{ - int len = 1; - char *s; - if (s1) - len += strlen(s1); - if (s2) - len += strlen(s2); - if (s3) - len += strlen(s3); - s = xmalloc(len); - s[0] = '\0'; - if (s1) - strcat(s, s1); - if (s2) - strcat(s, s2); - if (s3) - strcat(s, s3); - return s; -} - -void * -xmalloc(n) - size_t n; -{ - char *p = malloc(n); - - if (p == NULL) - errx(1, "Could not allocate memory"); - - return p; -} - -void * -xrealloc(p, n) - void *p; - size_t n; -{ - p = realloc(p, n); - - if (p == NULL) - errx(1, "Could not allocate memory"); - - return p; -} diff --git a/libexec/rtld-aout/support.h b/libexec/rtld-aout/support.h deleted file mode 100644 index da03407..0000000 --- a/libexec/rtld-aout/support.h +++ /dev/null @@ -1,35 +0,0 @@ -/*- - * Copyright (C) 1996 - * Peter Wemm. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - *- - * $FreeBSD$ - */ - -/* - * prototypes for support.c. Big deal. - */ - -void *xmalloc __P((size_t)); -void *xrealloc __P((void *, size_t)); -char *concat __P((const char *, const char *, const char *)); -- cgit v1.1