These files were moved elsewhere (sbin/ldconfig, libexec/rtld-aout,
usr.bin/ldd) as they stand alone and are under bsd-style license.
This commit is contained in:
parent
7ef7c681ba
commit
7b001f8ee5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=36569
@ -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.
|
||||
*
|
||||
* $Id: dynamic.h,v 1.3 1997/02/22 15:46:18 peter Exp $
|
||||
*/
|
||||
|
||||
#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 `<file>.<name>' */
|
||||
#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 a an archive */
|
||||
#define E_HEADER_VALID 2 /* File's header has been read */
|
||||
#define E_SEARCH_DIRS 4 /* Search directories for file */
|
||||
#define E_SEARCH_DYNAMIC 8 /* Search for shared libs allowed */
|
||||
#define E_JUST_SYMS 0x10 /* File is used for incremental load */
|
||||
#define E_DYNAMIC 0x20 /* File is a shared object */
|
||||
#define E_SCRAPPED 0x40 /* Ignore this file */
|
||||
#define E_SYMBOLS_USED 0x80 /* Symbols from this entry were used */
|
||||
#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 <md>.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__ */
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <a.out.h>
|
||||
#include <stab.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 */
|
@ -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.
|
||||
*
|
||||
* $Id: md.h,v 1.16 1997/02/22 15:46:34 peter Exp $
|
||||
*/
|
||||
|
||||
#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__ */
|
@ -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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* i386 run-time link editor entry points.
|
||||
*/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
.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
|
@ -1,13 +0,0 @@
|
||||
# $Id: Makefile,v 1.10 1997/02/22 15:46:37 peter Exp $
|
||||
|
||||
PROG= ldconfig
|
||||
SRCS= ldconfig.c shlib.c support.c
|
||||
LDDIR?= $(.CURDIR)/..
|
||||
CFLAGS+=-I$(LDDIR) -I$(.CURDIR) -I$(LDDIR)/$(MACHINE)
|
||||
NOSHARED?= yes
|
||||
BINDIR= /sbin
|
||||
MAN8= ldconfig.8
|
||||
|
||||
.PATH: $(LDDIR) $(LDDIR)/$(MACHINE)
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,147 +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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" $Id: ldconfig.8,v 1.14 1997/08/22 04:42:12 peter Exp $
|
||||
.\"
|
||||
.Dd October 3, 1993
|
||||
.Dt LDCONFIG 8
|
||||
.Os FreeBSD
|
||||
.Sh NAME
|
||||
.Nm ldconfig
|
||||
.Nd configure the shared library cache
|
||||
.Sh SYNOPSIS
|
||||
.Nm ldconfig
|
||||
.Op Fl Rmrsv
|
||||
.Op Fl f Ar hints_file
|
||||
.Op Ar directory | file Ar ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is used to prepare a set of
|
||||
.Dq hints
|
||||
for use by the run-time linker
|
||||
.Xr ld.so 1
|
||||
to facilitate quick lookup of shared libraries available in multiple
|
||||
directories. It scans a set of built-in system directories and any
|
||||
.Ar directories
|
||||
specified on the command line (in the given order) looking for shared
|
||||
libraries and stores the results in the file
|
||||
.Pa /var/run/ld.so.hints
|
||||
to forestall the overhead that would otherwise result from the
|
||||
directory search operations
|
||||
.Xr ld.so 1
|
||||
would have to perform to load the required shared libraries.
|
||||
.Pp
|
||||
Files named on the command line are expected to contain directories
|
||||
to scan for shared libraries. Each directory's pathname must start on a new
|
||||
line. Blank lines and lines starting with the comment character
|
||||
.Ql \&#
|
||||
are ignored. A standard name for this file is
|
||||
.Xr /etc/ld.so.conf.
|
||||
.Pp
|
||||
The shared libraries so found will be automatically available for loading
|
||||
if needed by the program being prepared for execution. This obviates the need
|
||||
for storing search paths within the executable.
|
||||
.Pp
|
||||
The
|
||||
.Ev LD_LIBRARY_PATH
|
||||
environment variable can be used to override the use of
|
||||
directories (or the order thereof) from the cache or to specify additional
|
||||
directories where shared libraries might be found.
|
||||
.Ev LD_LIBRARY_PATH
|
||||
is a
|
||||
.Sq \:
|
||||
separated list of directory paths which are searched by
|
||||
.Xr ld.so 1
|
||||
when it needs to load a shared library. It can be viewed as the run-time
|
||||
equivalent of the
|
||||
.Fl L
|
||||
switch of
|
||||
.Xr ld 1 .
|
||||
.Pp
|
||||
.Nm Ldconfig
|
||||
is typically run as part of the boot sequence.
|
||||
.Pp
|
||||
The following options recognized by
|
||||
.Nm ldconfig:
|
||||
.Bl -tag -width indent
|
||||
.It Fl R
|
||||
Rescan the previously configured directories. This opens the previous hints
|
||||
file and fetches the directory list from the header. Any additional pathnames
|
||||
on the command line are also processed.
|
||||
.It Fl f Ar hints_file
|
||||
Read and/or update the specified hints file, instead of
|
||||
.Pa /var/run/ld.so.hints .
|
||||
This option is provided primarily for testing.
|
||||
.It Fl m
|
||||
Instead of replacing the contents of the hints file
|
||||
with those found in the directories specified,
|
||||
.Dq merge
|
||||
in new entries.
|
||||
Directories recorded in the hints file by previous runs of
|
||||
.Nm
|
||||
are also rescanned for new shared libraries.
|
||||
.It Fl r
|
||||
List the current contents of the hints file
|
||||
on the standard output. The hints file is not modified. The list of
|
||||
directories stored in the hints file is included.
|
||||
.It Fl s
|
||||
Do not scan the built-in system directory
|
||||
.Pq Dq /usr/lib
|
||||
for shared libraries.
|
||||
.It Fl v
|
||||
Switch on verbose mode.
|
||||
.Sh Security
|
||||
Special care must be taken when loading shared libraries into the address
|
||||
space of
|
||||
.Ev set-user-Id
|
||||
programs. Whenever such a program is run,
|
||||
.Nm ld.so
|
||||
will only load shared libraries from the hints
|
||||
file. In particular, the
|
||||
.Ev LD_LIBRARY_PATH
|
||||
is not used to search for libraries. Thus, the role of ldconfig is dual. In
|
||||
addition to building a set of hints for quick lookup, it also serves to
|
||||
specify the trusted collection of directories from which shared objects can
|
||||
be safely loaded. It is presumed that the set of directories specified to
|
||||
.Nm ldconfig
|
||||
are under control of the system's administrator.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/run/ld.so.hintsxxx -compact
|
||||
.It Pa /var/run/ld.so.hints
|
||||
Default
|
||||
.Dq hints
|
||||
file.
|
||||
.Sh SEE ALSO
|
||||
.Xr ld 1 ,
|
||||
.Xr link 5
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility first appeared in SunOS 4.0, it appeared in its current form
|
||||
in FreeBSD 1.1.
|
@ -1,586 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1993,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 acknowledgement:
|
||||
* This product includes software developed by Paul Kranenburg.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ldconfig.c,v 1.20 1997/08/22 04:42:12 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <ar.h>
|
||||
#include <ranlib.h>
|
||||
#include <a.out.h>
|
||||
#include <stab.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <machine/param.h>
|
||||
|
||||
#include <link.h>
|
||||
#include "shlib.h"
|
||||
#include "support.h"
|
||||
|
||||
#if DEBUG
|
||||
/* test */
|
||||
#undef _PATH_LD_HINTS
|
||||
#define _PATH_LD_HINTS "./ld.so.hints"
|
||||
#endif
|
||||
|
||||
#undef major
|
||||
#undef minor
|
||||
|
||||
static int verbose;
|
||||
static int nostd;
|
||||
static int justread;
|
||||
static int merge;
|
||||
static int rescan;
|
||||
static char *hints_file = _PATH_LD_HINTS;
|
||||
|
||||
struct shlib_list {
|
||||
/* Internal list of shared libraries found */
|
||||
char *name;
|
||||
char *path;
|
||||
int dewey[MAXDEWEY];
|
||||
int ndewey;
|
||||
#define major dewey[0]
|
||||
#define minor dewey[1]
|
||||
struct shlib_list *next;
|
||||
};
|
||||
|
||||
static struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head;
|
||||
static char *dir_list;
|
||||
|
||||
static void enter __P((char *, char *, char *, int *, int));
|
||||
static int dodir __P((char *, int));
|
||||
static int buildhints __P((void));
|
||||
static int readhints __P((void));
|
||||
static void listhints __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i, c;
|
||||
int rval = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "Rf:mrsv")) != EOF) {
|
||||
switch (c) {
|
||||
case 'R':
|
||||
rescan = 1;
|
||||
break;
|
||||
case 'f':
|
||||
hints_file = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
merge = 1;
|
||||
break;
|
||||
case 'r':
|
||||
justread = 1;
|
||||
break;
|
||||
case 's':
|
||||
nostd = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
errx(1, "Usage: %s [-Rmrsv] [-f hints_file] "
|
||||
"[dir | file ...]", argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dir_list = strdup("");
|
||||
|
||||
if (justread || merge || rescan) {
|
||||
if ((rval = readhints()) != 0)
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (!nostd && !merge && !rescan)
|
||||
std_search_path();
|
||||
|
||||
/* Add any directories/files from the command line */
|
||||
if (!justread) {
|
||||
for (i = optind; i < argc; i++) {
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat(argv[i], &stbuf) == -1) {
|
||||
warn("%s", argv[i]);
|
||||
rval = -1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "/usr/lib")) {
|
||||
warnx("WARNING! '%s' can not be used", argv[i]);
|
||||
rval = -1;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* See if this is a directory-containing
|
||||
* file instead of a directory
|
||||
*/
|
||||
if (S_ISREG(stbuf.st_mode))
|
||||
rval |= dofile(argv[i], 0);
|
||||
else
|
||||
add_search_path(argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_search_dirs; i++) {
|
||||
char *cp = concat(dir_list, *dir_list?":":"", search_dirs[i]);
|
||||
free(dir_list);
|
||||
dir_list = cp;
|
||||
}
|
||||
|
||||
if (justread) {
|
||||
listhints();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_search_dirs; i++)
|
||||
rval |= dodir(search_dirs[i], 1);
|
||||
|
||||
rval |= buildhints();
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int
|
||||
dofile(fname, silent)
|
||||
char *fname;
|
||||
int silent;
|
||||
{
|
||||
FILE *hfp;
|
||||
char buf[MAXPATHLEN];
|
||||
int rval = 0;
|
||||
char *cp, *sp;
|
||||
|
||||
if ((hfp = fopen(fname, "r")) == NULL) {
|
||||
warn("%s", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), hfp)) {
|
||||
cp = buf;
|
||||
while (isspace(*cp))
|
||||
cp++;
|
||||
if (*cp == '#' || *cp == '\0')
|
||||
continue;
|
||||
sp = cp;
|
||||
while (!isspace(*cp) && *cp != '\0')
|
||||
cp++;
|
||||
|
||||
if (*cp != '\n') {
|
||||
*cp = '\0';
|
||||
warnx("%s: Trailing characters ignored", sp);
|
||||
}
|
||||
|
||||
*cp = '\0';
|
||||
|
||||
rval |= dodir(sp, silent);
|
||||
}
|
||||
|
||||
(void)fclose(hfp);
|
||||
return rval;
|
||||
}
|
||||
|
||||
int
|
||||
dodir(dir, silent)
|
||||
char *dir;
|
||||
int silent;
|
||||
{
|
||||
DIR *dd;
|
||||
struct dirent *dp;
|
||||
char name[MAXPATHLEN];
|
||||
int dewey[MAXDEWEY], ndewey;
|
||||
|
||||
if ((dd = opendir(dir)) == NULL) {
|
||||
if (silent && errno == ENOENT) /* Ignore the error */
|
||||
return 0;
|
||||
warn("%s", dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((dp = readdir(dd)) != NULL) {
|
||||
register int n;
|
||||
register char *cp;
|
||||
|
||||
/* Check for `lib' prefix */
|
||||
if (dp->d_name[0] != 'l' ||
|
||||
dp->d_name[1] != 'i' ||
|
||||
dp->d_name[2] != 'b')
|
||||
continue;
|
||||
|
||||
/* Copy the entry minus prefix */
|
||||
(void)strcpy(name, dp->d_name + 3);
|
||||
n = strlen(name);
|
||||
if (n < 4)
|
||||
continue;
|
||||
|
||||
/* Find ".so." in name */
|
||||
for (cp = name + n - 4; cp > name; --cp) {
|
||||
if (cp[0] == '.' &&
|
||||
cp[1] == 's' &&
|
||||
cp[2] == 'o' &&
|
||||
cp[3] == '.')
|
||||
break;
|
||||
}
|
||||
if (cp <= name)
|
||||
continue;
|
||||
|
||||
*cp = '\0';
|
||||
if (!isdigit(*(cp+4)))
|
||||
continue;
|
||||
|
||||
bzero((caddr_t)dewey, sizeof(dewey));
|
||||
ndewey = getdewey(dewey, cp + 4);
|
||||
enter(dir, dp->d_name, name, dewey, ndewey);
|
||||
}
|
||||
|
||||
closedir(dd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
enter(dir, file, name, dewey, ndewey)
|
||||
char *dir, *file, *name;
|
||||
int dewey[], ndewey;
|
||||
{
|
||||
struct shlib_list *shp;
|
||||
|
||||
for (shp = shlib_head; shp; shp = shp->next) {
|
||||
if (strcmp(name, shp->name) != 0 || major != shp->major)
|
||||
continue;
|
||||
|
||||
/* Name matches existing entry */
|
||||
if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) {
|
||||
|
||||
/* Update this entry with higher versioned lib */
|
||||
if (verbose)
|
||||
printf("Updating lib%s.%d.%d to %s/%s\n",
|
||||
shp->name, shp->major, shp->minor,
|
||||
dir, file);
|
||||
|
||||
free(shp->name);
|
||||
shp->name = strdup(name);
|
||||
free(shp->path);
|
||||
shp->path = concat(dir, "/", file);
|
||||
bcopy(dewey, shp->dewey, sizeof(shp->dewey));
|
||||
shp->ndewey = ndewey;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (shp)
|
||||
/* Name exists: older version or just updated */
|
||||
return;
|
||||
|
||||
/* Allocate new list element */
|
||||
if (verbose)
|
||||
printf("Adding %s/%s\n", dir, file);
|
||||
|
||||
shp = (struct shlib_list *)xmalloc(sizeof *shp);
|
||||
shp->name = strdup(name);
|
||||
shp->path = concat(dir, "/", file);
|
||||
bcopy(dewey, shp->dewey, MAXDEWEY);
|
||||
shp->ndewey = ndewey;
|
||||
shp->next = NULL;
|
||||
|
||||
*shlib_tail = shp;
|
||||
shlib_tail = &shp->next;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
buildhints()
|
||||
{
|
||||
struct hints_header hdr;
|
||||
struct hints_bucket *blist;
|
||||
struct shlib_list *shp;
|
||||
char *strtab;
|
||||
int i, n, str_index = 0;
|
||||
int strtab_sz = 0; /* Total length of strings */
|
||||
int nhints = 0; /* Total number of hints */
|
||||
int fd;
|
||||
char *tmpfile;
|
||||
|
||||
for (shp = shlib_head; shp; shp = shp->next) {
|
||||
strtab_sz += 1 + strlen(shp->name);
|
||||
strtab_sz += 1 + strlen(shp->path);
|
||||
nhints++;
|
||||
}
|
||||
|
||||
/* Fill hints file header */
|
||||
hdr.hh_magic = HH_MAGIC;
|
||||
hdr.hh_version = LD_HINTS_VERSION_2;
|
||||
hdr.hh_nbucket = 1 * nhints;
|
||||
n = hdr.hh_nbucket * sizeof(struct hints_bucket);
|
||||
hdr.hh_hashtab = sizeof(struct hints_header);
|
||||
hdr.hh_strtab = hdr.hh_hashtab + n;
|
||||
hdr.hh_dirlist = strtab_sz;
|
||||
strtab_sz += 1 + strlen(dir_list);
|
||||
hdr.hh_strtab_sz = strtab_sz;
|
||||
hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz;
|
||||
|
||||
if (verbose)
|
||||
printf("Totals: entries %d, buckets %ld, string size %d\n",
|
||||
nhints, hdr.hh_nbucket, strtab_sz);
|
||||
|
||||
/* Allocate buckets and string table */
|
||||
blist = (struct hints_bucket *)xmalloc(n);
|
||||
bzero((char *)blist, n);
|
||||
for (i = 0; i < hdr.hh_nbucket; i++)
|
||||
/* Empty all buckets */
|
||||
blist[i].hi_next = -1;
|
||||
|
||||
strtab = (char *)xmalloc(strtab_sz);
|
||||
|
||||
/* Enter all */
|
||||
for (shp = shlib_head; shp; shp = shp->next) {
|
||||
struct hints_bucket *bp;
|
||||
|
||||
bp = blist +
|
||||
(hinthash(shp->name, shp->major) % hdr.hh_nbucket);
|
||||
|
||||
if (bp->hi_pathx) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hdr.hh_nbucket; i++) {
|
||||
if (blist[i].hi_pathx == 0)
|
||||
break;
|
||||
}
|
||||
if (i == hdr.hh_nbucket) {
|
||||
warnx("Bummer!");
|
||||
return -1;
|
||||
}
|
||||
while (bp->hi_next != -1)
|
||||
bp = &blist[bp->hi_next];
|
||||
bp->hi_next = i;
|
||||
bp = blist + i;
|
||||
}
|
||||
|
||||
/* Insert strings in string table */
|
||||
bp->hi_namex = str_index;
|
||||
strcpy(strtab + str_index, shp->name);
|
||||
str_index += 1 + strlen(shp->name);
|
||||
|
||||
bp->hi_pathx = str_index;
|
||||
strcpy(strtab + str_index, shp->path);
|
||||
str_index += 1 + strlen(shp->path);
|
||||
|
||||
/* Copy versions */
|
||||
bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey));
|
||||
bp->hi_ndewey = shp->ndewey;
|
||||
}
|
||||
|
||||
/* Copy search directories */
|
||||
strcpy(strtab + str_index, dir_list);
|
||||
str_index += 1 + strlen(dir_list);
|
||||
|
||||
/* Sanity check */
|
||||
if (str_index != strtab_sz) {
|
||||
errx(1, "str_index(%d) != strtab_sz(%d)", str_index, strtab_sz);
|
||||
}
|
||||
|
||||
tmpfile = concat(hints_file, ".XXXXXX", "");
|
||||
if ((tmpfile = mktemp(tmpfile)) == NULL) {
|
||||
warn("%s", tmpfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
umask(0); /* Create with exact permissions */
|
||||
if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_TRUNC, 0444)) == -1) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write(fd, &hdr, sizeof(struct hints_header)) !=
|
||||
sizeof(struct hints_header)) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
if (write(fd, blist, hdr.hh_nbucket * sizeof(struct hints_bucket)) !=
|
||||
hdr.hh_nbucket * sizeof(struct hints_bucket)) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
if (write(fd, strtab, strtab_sz) != strtab_sz) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
if (close(fd) != 0) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Install it */
|
||||
if (unlink(hints_file) != 0 && errno != ENOENT) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rename(tmpfile, hints_file) != 0) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
readhints()
|
||||
{
|
||||
int fd;
|
||||
caddr_t addr;
|
||||
long msize;
|
||||
struct hints_header *hdr;
|
||||
struct hints_bucket *blist;
|
||||
char *strtab;
|
||||
struct shlib_list *shp;
|
||||
int i;
|
||||
|
||||
if ((fd = open(hints_file, O_RDONLY, 0)) == -1) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msize = PAGE_SIZE;
|
||||
addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0);
|
||||
|
||||
if (addr == (caddr_t)-1) {
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr = (struct hints_header *)addr;
|
||||
if (HH_BADMAG(*hdr)) {
|
||||
warnx("%s: Bad magic: %o",
|
||||
hints_file, hdr->hh_magic);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->hh_version != LD_HINTS_VERSION_1 &&
|
||||
hdr->hh_version != LD_HINTS_VERSION_2) {
|
||||
warnx("Unsupported version: %d", hdr->hh_version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hdr->hh_ehints > msize) {
|
||||
if (mmap(addr+msize, hdr->hh_ehints - msize,
|
||||
PROT_READ, MAP_COPY|MAP_FIXED,
|
||||
fd, msize) != (caddr_t)(addr+msize)) {
|
||||
|
||||
warn("%s", hints_file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
blist = (struct hints_bucket *)(addr + hdr->hh_hashtab);
|
||||
strtab = (char *)(addr + hdr->hh_strtab);
|
||||
|
||||
if (hdr->hh_version >= LD_HINTS_VERSION_2)
|
||||
add_search_path(strtab + hdr->hh_dirlist);
|
||||
else if (rescan)
|
||||
errx(1, "%s too old and does not contain the search path",
|
||||
hints_file);
|
||||
|
||||
if (rescan)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < hdr->hh_nbucket; i++) {
|
||||
struct hints_bucket *bp = &blist[i];
|
||||
|
||||
/* Sanity check */
|
||||
if (bp->hi_namex >= hdr->hh_strtab_sz) {
|
||||
warnx("Bad name index: %#x", bp->hi_namex);
|
||||
return -1;
|
||||
}
|
||||
if (bp->hi_pathx >= hdr->hh_strtab_sz) {
|
||||
warnx("Bad path index: %#x", bp->hi_pathx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate new list element */
|
||||
shp = (struct shlib_list *)xmalloc(sizeof *shp);
|
||||
shp->name = strdup(strtab + bp->hi_namex);
|
||||
shp->path = strdup(strtab + bp->hi_pathx);
|
||||
bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey));
|
||||
shp->ndewey = bp->hi_ndewey;
|
||||
shp->next = NULL;
|
||||
|
||||
*shlib_tail = shp;
|
||||
shlib_tail = &shp->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
listhints()
|
||||
{
|
||||
struct shlib_list *shp;
|
||||
int i;
|
||||
|
||||
printf("%s:\n", hints_file);
|
||||
printf("\tsearch directories: %s\n", dir_list);
|
||||
|
||||
for (i = 0, shp = shlib_head; shp; i++, shp = shp->next)
|
||||
printf("\t%d:-l%s.%d.%d => %s\n",
|
||||
i, shp->name, shp->major, shp->minor, shp->path);
|
||||
|
||||
return;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
# $Id: Makefile,v 1.6 1997/02/22 15:46:40 peter Exp $
|
||||
|
||||
PROG= ldd
|
||||
SRCS= ldd.c sods.c
|
||||
CFLAGS+= -Wall
|
||||
BINDIR= /usr/bin
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,47 +0,0 @@
|
||||
.Dd October 22, 1993
|
||||
.Dt LDD 1
|
||||
.Os FreeBSD
|
||||
.Sh NAME
|
||||
.Nm ldd
|
||||
.Nd list dynamic object dependencies
|
||||
.Sh SYNOPSIS
|
||||
.Nm ldd
|
||||
.Op Fl v
|
||||
.Op Fl f Ar format
|
||||
.Ar program ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm ldd
|
||||
displays all shared objects that are needed to run the given program.
|
||||
Contrary to nm(1), the list includes
|
||||
.Dq indirect
|
||||
dependencies that are the result of needed shared objects which themselves
|
||||
depend on yet other shared objects.
|
||||
.Pp
|
||||
Zero, one or two
|
||||
.Fl f
|
||||
options may be given. The argument is a format string passed to
|
||||
.Xr rtld 1
|
||||
and allows customization of
|
||||
.Nm ldd Ns 's
|
||||
output. See
|
||||
.Xr rtld 1
|
||||
for a list of recognized conversion characters.
|
||||
.Pp
|
||||
The
|
||||
.Fl v
|
||||
option displays an verbose listing of the dynamic linking headers
|
||||
encoded in the executable. See the source code and include
|
||||
files for the definitive meaning of all the fields.
|
||||
.Sh SEE ALSO
|
||||
.Xr ld 1 ,
|
||||
.Xr ld.so 1 ,
|
||||
.Xr nm 1
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm ldd
|
||||
utility first appeared in SunOS 4.0, it appeared in its current form
|
||||
in FreeBSD 1.1.
|
||||
.Pp
|
||||
The
|
||||
.Fl v
|
||||
support is based on code written by John Polstra <jdp@polstra.com>
|
@ -1,213 +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.
|
||||
*
|
||||
* $Id: ldd.c,v 1.14 1997/09/02 21:54:39 jdp Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <a.out.h>
|
||||
#include <elf.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern void dump_file __P((const char *));
|
||||
extern int error_count;
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: ldd [-v] [-f format] program ...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
char *fmt1 = NULL, *fmt2 = NULL;
|
||||
int rval;
|
||||
int c;
|
||||
int vflag = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "vf:")) != EOF) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
vflag++;
|
||||
break;
|
||||
case 'f':
|
||||
if (fmt1) {
|
||||
if (fmt2)
|
||||
errx(1, "Too many formats");
|
||||
fmt2 = optarg;
|
||||
} else
|
||||
fmt1 = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (vflag && fmt1)
|
||||
errx(1, "-v may not be used with -f");
|
||||
|
||||
if (argc <= 0) {
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if (vflag) {
|
||||
for (c = 0; c < argc; c++)
|
||||
dump_file(argv[c]);
|
||||
exit(error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* ld.so magic */
|
||||
setenv("LD_TRACE_LOADED_OBJECTS", "1", 1);
|
||||
if (fmt1)
|
||||
setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
|
||||
if (fmt2)
|
||||
setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
|
||||
|
||||
rval = 0;
|
||||
while (argc--) {
|
||||
int fd;
|
||||
struct exec hdr;
|
||||
int status;
|
||||
|
||||
if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
|
||||
warn("%s", *argv);
|
||||
rval |= 1;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
if (read(fd, &hdr, sizeof hdr) != sizeof hdr) {
|
||||
warnx("%s: can't read program header", *argv);
|
||||
(void)close(fd);
|
||||
rval |= 1;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!N_BADMAG(hdr)) {
|
||||
/* a.out file */
|
||||
if ((N_GETFLAG(hdr) & EX_DPMASK) != EX_DYNAMIC
|
||||
#if 1 /* Compatibility */
|
||||
|| hdr.a_entry < __LDPGSZ
|
||||
#endif
|
||||
) {
|
||||
warnx("%s: not a dynamic executable", *argv);
|
||||
(void)close(fd);
|
||||
rval |= 1;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
} else if (IS_ELF(*(Elf32_Ehdr*)&hdr)) {
|
||||
Elf32_Ehdr ehdr;
|
||||
Elf32_Phdr phdr;
|
||||
int dynamic = 0, i;
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
if (read(fd, &ehdr, sizeof ehdr) != sizeof ehdr) {
|
||||
warnx("%s: can't read program header", *argv);
|
||||
(void)close(fd);
|
||||
rval |= 1;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
lseek(fd, 0, ehdr.e_phoff);
|
||||
for (i = 0; i < ehdr.e_phnum; i++) {
|
||||
if (read(fd, &phdr, ehdr.e_phentsize)
|
||||
!= sizeof phdr) {
|
||||
warnx("%s: can't read program header", *argv);
|
||||
(void)close(fd);
|
||||
rval |= 1;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
if (phdr.p_type == PT_DYNAMIC)
|
||||
dynamic = 1;
|
||||
}
|
||||
if (!dynamic) {
|
||||
warnx("%s: not a dynamic executable", *argv);
|
||||
(void)close(fd);
|
||||
rval |= 1;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
(void)close(fd);
|
||||
|
||||
setenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
|
||||
if (fmt1 == NULL && fmt2 == NULL)
|
||||
/* Default formats */
|
||||
printf("%s:\n", *argv);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
err(1, "fork");
|
||||
break;
|
||||
default:
|
||||
if (wait(&status) <= 0) {
|
||||
warn("wait");
|
||||
rval |= 1;
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
fprintf(stderr, "%s: signal %d\n",
|
||||
*argv, WTERMSIG(status));
|
||||
rval |= 1;
|
||||
} else if (WIFEXITED(status) && WEXITSTATUS(status)) {
|
||||
fprintf(stderr, "%s: exit status %d\n",
|
||||
*argv, WEXITSTATUS(status));
|
||||
rval |= 1;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
rval |= execl(*argv, *argv, NULL) != 0;
|
||||
perror(*argv);
|
||||
_exit(1);
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
@ -1,554 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 1996-1997 John D. Polstra. 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 JOHN D. POLSTRA 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 JOHN D. POLSTRA 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.
|
||||
*
|
||||
* $Id: sods.c,v 1.6 1997/11/28 19:34:27 jdp Exp $
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <a.out.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
#include <stab.h>
|
||||
|
||||
#define PAGE_SIZE 4096 /* i386 specific */
|
||||
|
||||
#ifndef N_SETA
|
||||
#define N_SETA 0x14 /* Absolute set element symbol */
|
||||
#endif /* This is input to LD, in a .o file. */
|
||||
|
||||
#ifndef N_SETT
|
||||
#define N_SETT 0x16 /* Text set element symbol */
|
||||
#endif /* This is input to LD, in a .o file. */
|
||||
|
||||
#ifndef N_SETD
|
||||
#define N_SETD 0x18 /* Data set element symbol */
|
||||
#endif /* This is input to LD, in a .o file. */
|
||||
|
||||
#ifndef N_SETB
|
||||
#define N_SETB 0x1A /* Bss set element symbol */
|
||||
#endif /* This is input to LD, in a .o file. */
|
||||
|
||||
#ifndef N_SETV
|
||||
#define N_SETV 0x1C /* Pointer to set vector in data area. */
|
||||
#endif /* This is output from LD. */
|
||||
|
||||
#ifdef STANDALONE
|
||||
static
|
||||
#endif
|
||||
void dump_file(const char *);
|
||||
|
||||
static void dump_rels(const char *, const struct relocation_info *,
|
||||
unsigned long, const char *(*)(unsigned long), unsigned char *);
|
||||
static void dump_segs();
|
||||
static void dump_sods();
|
||||
static void dump_sym(const struct nlist *);
|
||||
static void dump_syms();
|
||||
|
||||
static void dump_rtsyms();
|
||||
|
||||
static void error(const char *, ...);
|
||||
static const char *rtsym_name(unsigned long);
|
||||
static const char *sym_name(unsigned long);
|
||||
|
||||
#ifdef STANDALONE
|
||||
static
|
||||
#endif
|
||||
int error_count;
|
||||
|
||||
/*
|
||||
* Variables ending in _base are pointers to things in our address space,
|
||||
* i.e., in the file itself.
|
||||
*
|
||||
* Variables ending in _addr are adjusted according to where things would
|
||||
* actually appear in memory if the file were loaded.
|
||||
*/
|
||||
static const char *file_base;
|
||||
static const char *text_base;
|
||||
static const char *data_base;
|
||||
static const struct relocation_info *rel_base;
|
||||
static const struct nlist *sym_base;
|
||||
static const char *str_base;
|
||||
|
||||
static const struct relocation_info *rtrel_base;
|
||||
static const struct nzlist *rtsym_base;
|
||||
static const char *rtstr_base;
|
||||
|
||||
static const struct exec *ex;
|
||||
static const struct _dynamic *dyn;
|
||||
static const struct section_dispatch_table *sdt;
|
||||
|
||||
static const char *text_addr;
|
||||
static const char *data_addr;
|
||||
|
||||
static unsigned long rel_count;
|
||||
static unsigned long sym_count;
|
||||
|
||||
static unsigned long rtrel_count;
|
||||
static unsigned long rtsym_count;
|
||||
|
||||
/* Dynamically allocated flags, 1 byte per symbol, to record whether each
|
||||
symbol was referenced by a relocation entry. */
|
||||
static unsigned char *sym_used;
|
||||
static unsigned char *rtsym_used;
|
||||
|
||||
static unsigned long origin; /* What values are relocated relative to */
|
||||
|
||||
#ifdef STANDALONE
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; ++i)
|
||||
dump_file(argv[i]);
|
||||
|
||||
return error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STANDALONE
|
||||
static
|
||||
#endif
|
||||
void
|
||||
dump_file(const char *fname)
|
||||
{
|
||||
int fd;
|
||||
struct stat sb;
|
||||
caddr_t objbase;
|
||||
|
||||
if (stat(fname, &sb) == -1) {
|
||||
error("Cannot stat \"%s\"", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sb.st_mode & S_IFMT) != S_IFREG) {
|
||||
error("\"%s\" is not a regular file", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fd = open(fname, O_RDONLY, 0)) == -1) {
|
||||
error("Cannot open \"%s\"", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
objbase = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (objbase == (caddr_t) -1) {
|
||||
error("Cannot mmap \"%s\"", fname);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
file_base = (const char *) objbase; /* Makes address arithmetic easier */
|
||||
|
||||
if (IS_ELF(*(Elf32_Ehdr*) file_base)) {
|
||||
error("%s: this is an ELF program; use objdump to examine.", fname);
|
||||
munmap(objbase, sb.st_size);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
ex = (const struct exec *) file_base;
|
||||
|
||||
printf("%s: a_midmag = 0x%lx\n", fname, ex->a_midmag);
|
||||
printf(" magic = 0x%lx = 0%lo, netmagic = 0x%lx = 0%lo\n",
|
||||
N_GETMAGIC(*ex), N_GETMAGIC(*ex),
|
||||
N_GETMAGIC_NET(*ex), N_GETMAGIC_NET(*ex));
|
||||
|
||||
if (N_BADMAG(*ex)) {
|
||||
error("%s: Bad magic number", fname);
|
||||
munmap(objbase, sb.st_size);
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" a_text = 0x%lx\n", ex->a_text);
|
||||
printf(" a_data = 0x%lx\n", ex->a_data);
|
||||
printf(" a_bss = 0x%lx\n", ex->a_bss);
|
||||
printf(" a_syms = 0x%lx\n", ex->a_syms);
|
||||
printf(" a_entry = 0x%lx\n", ex->a_entry);
|
||||
printf(" a_trsize = 0x%lx\n", ex->a_trsize);
|
||||
printf(" a_drsize = 0x%lx\n", ex->a_drsize);
|
||||
|
||||
text_base = file_base + N_TXTOFF(*ex);
|
||||
data_base = file_base + N_DATOFF(*ex);
|
||||
rel_base = (const struct relocation_info *) (file_base + N_RELOFF(*ex));
|
||||
sym_base = (const struct nlist *) (file_base + N_SYMOFF(*ex));
|
||||
str_base = file_base + N_STROFF(*ex);
|
||||
|
||||
rel_count = (ex->a_trsize + ex->a_drsize) / sizeof rel_base[0];
|
||||
assert(rel_count * sizeof rel_base[0] == ex->a_trsize + ex->a_drsize);
|
||||
sym_count = ex->a_syms / sizeof sym_base[0];
|
||||
assert(sym_count * sizeof sym_base[0] == ex->a_syms);
|
||||
|
||||
if (sym_count != 0) {
|
||||
sym_used = (unsigned char *) calloc(sym_count, sizeof(unsigned char));
|
||||
assert(sym_used != NULL);
|
||||
}
|
||||
|
||||
printf(" Entry = 0x%lx\n", ex->a_entry);
|
||||
printf(" Text offset = %x, address = %lx\n", N_TXTOFF(*ex),
|
||||
N_TXTADDR(*ex));
|
||||
printf(" Data offset = %lx, address = %lx\n", N_DATOFF(*ex),
|
||||
N_DATADDR(*ex));
|
||||
|
||||
/*
|
||||
* In an executable program file, everything is relocated relative to
|
||||
* the assumed run-time load address, i.e., N_TXTADDR(*ex), i.e., 0x1000.
|
||||
*
|
||||
* In a shared library file, everything is relocated relative to the
|
||||
* start of the file, i.e., N_TXTOFF(*ex), i.e., 0.
|
||||
*
|
||||
* The way to tell the difference is by looking at ex->a_entry. If it
|
||||
* is >= 0x1000, then we have an executable program. Otherwise, we
|
||||
* have a shared library.
|
||||
*
|
||||
* When a program is executed, the entire file is mapped into memory,
|
||||
* including the a.out header and so forth. But it is not mapped at
|
||||
* address 0; rather it is mapped at address 0x1000. The first page
|
||||
* of the user's address space is left unmapped in order to catch null
|
||||
* pointer dereferences.
|
||||
*
|
||||
* In this program, when we map in an executable program, we have to
|
||||
* simulate the empty page by decrementing our assumed base address by
|
||||
* a pagesize.
|
||||
*/
|
||||
|
||||
text_addr = text_base;
|
||||
data_addr = data_base;
|
||||
origin = 0;
|
||||
|
||||
if (ex->a_entry >= PAGE_SIZE) { /* Executable, not a shared library */
|
||||
/*
|
||||
* The fields in the object have already been relocated on the
|
||||
* assumption that the object will be loaded at N_TXTADDR(*ex).
|
||||
* We have to compensate for that.
|
||||
*/
|
||||
text_addr -= PAGE_SIZE;
|
||||
data_addr -= PAGE_SIZE;
|
||||
origin = PAGE_SIZE;
|
||||
printf(" Program, origin = %lx\n", origin);
|
||||
} else if (N_GETFLAG(*ex) & EX_DYNAMIC)
|
||||
printf(" Shared library, origin = %lx\n", origin);
|
||||
else
|
||||
printf(" Object file, origin = %lx\n", origin);
|
||||
|
||||
if (N_GETFLAG(*ex) & EX_DYNAMIC) {
|
||||
dyn = (const struct _dynamic *) data_base;
|
||||
printf(" Dynamic version = %d\n", dyn->d_version);
|
||||
|
||||
sdt = (const struct section_dispatch_table *)
|
||||
(text_addr + (unsigned long) dyn->d_un.d_sdt);
|
||||
|
||||
rtrel_base =
|
||||
(const struct relocation_info *) (text_addr + sdt->sdt_rel);
|
||||
rtrel_count = (sdt->sdt_hash - sdt->sdt_rel) / sizeof rtrel_base[0];
|
||||
assert(rtrel_count * sizeof rtrel_base[0] ==
|
||||
sdt->sdt_hash - sdt->sdt_rel);
|
||||
|
||||
rtsym_base = (const struct nzlist *) (text_addr + sdt->sdt_nzlist);
|
||||
rtsym_count = (sdt->sdt_strings - sdt->sdt_nzlist) /
|
||||
sizeof rtsym_base[0];
|
||||
assert(rtsym_count * sizeof rtsym_base[0] ==
|
||||
sdt->sdt_strings - sdt->sdt_nzlist);
|
||||
|
||||
if (rtsym_count != 0) {
|
||||
rtsym_used = (unsigned char *) calloc(rtsym_count,
|
||||
sizeof(unsigned char));
|
||||
assert(rtsym_used != NULL);
|
||||
}
|
||||
|
||||
rtstr_base = text_addr + sdt->sdt_strings;
|
||||
}
|
||||
|
||||
dump_segs();
|
||||
dump_sods();
|
||||
dump_rels("Relocations", rel_base, rel_count, sym_name, sym_used);
|
||||
dump_syms();
|
||||
|
||||
dump_rels("Run-time relocations", rtrel_base, rtrel_count, rtsym_name,
|
||||
rtsym_used);
|
||||
dump_rtsyms();
|
||||
|
||||
if (rtsym_used != NULL) {
|
||||
free(rtsym_used);
|
||||
rtsym_used = NULL;
|
||||
}
|
||||
if (sym_used != NULL) {
|
||||
free(sym_used);
|
||||
sym_used = NULL;
|
||||
}
|
||||
munmap(objbase, sb.st_size);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_rels(const char *label, const struct relocation_info *base,
|
||||
unsigned long count, const char *(*name)(unsigned long),
|
||||
unsigned char *sym_used_flags)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
printf(" %s:\n", label);
|
||||
for (i = 0; i < count; ++i) {
|
||||
const struct relocation_info *r = &base[i];
|
||||
unsigned int size;
|
||||
char contents[16];
|
||||
|
||||
size = 1u << r->r_length;
|
||||
|
||||
if (origin <= r->r_address
|
||||
&& r->r_address < origin + ex->a_text + ex->a_data
|
||||
&& 1 <= size && size <= 4) {
|
||||
/*
|
||||
* XXX - This can cause unaligned accesses. OK for the
|
||||
* i386, not so for other architectures.
|
||||
*/
|
||||
switch (size) {
|
||||
case 1:
|
||||
snprintf(contents, sizeof contents, " [%02x]",
|
||||
*(unsigned char *)(text_addr + r->r_address));
|
||||
break;
|
||||
case 2:
|
||||
snprintf(contents, sizeof contents, " [%04x]",
|
||||
*(unsigned short *)(text_addr + r->r_address));
|
||||
break;
|
||||
case 4:
|
||||
snprintf(contents, sizeof contents, "[%08lx]",
|
||||
*(unsigned long *)(text_addr + r->r_address));
|
||||
break;
|
||||
}
|
||||
} else
|
||||
snprintf(contents, sizeof contents, " ");
|
||||
|
||||
printf(" %6lu %8x/%u %s %c%c%c%c%c%c", i,
|
||||
r->r_address, size,
|
||||
contents,
|
||||
r->r_extern ? 'e' : '-',
|
||||
r->r_jmptable ? 'j' : '-',
|
||||
r->r_relative ? 'r' : '-',
|
||||
r->r_baserel ? 'b' : '-',
|
||||
r->r_pcrel ? 'p' : '-',
|
||||
r->r_copy ? 'c' : '-');
|
||||
|
||||
if (r->r_extern || r->r_baserel || r->r_jmptable || r->r_copy) {
|
||||
printf(" %4u %s", r->r_symbolnum, name(r->r_symbolnum));
|
||||
sym_used_flags[r->r_symbolnum] = 1;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_rtsyms()
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
printf(" Run-time symbols:\n");
|
||||
for (i = 0; i < rtsym_count; ++i) {
|
||||
printf(" %6lu%c ", i, rtsym_used[i] ? '*' : ' ');
|
||||
dump_sym(&rtsym_base[i].nlist);
|
||||
printf("/%-5ld %s\n", rtsym_base[i].nz_size, rtsym_name(i));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_segs()
|
||||
{
|
||||
printf(" Text segment starts at address %lx\n", origin + N_TXTOFF(*ex));
|
||||
if (N_GETFLAG(*ex) & EX_DYNAMIC) {
|
||||
printf(" rel starts at %lx\n", sdt->sdt_rel);
|
||||
printf(" hash starts at %lx\n", sdt->sdt_hash);
|
||||
printf(" nzlist starts at %lx\n", sdt->sdt_nzlist);
|
||||
printf(" strings starts at %lx\n", sdt->sdt_strings);
|
||||
}
|
||||
|
||||
printf(" Data segment starts at address %lx\n", origin + N_DATOFF(*ex));
|
||||
if (N_GETFLAG(*ex) & EX_DYNAMIC) {
|
||||
printf(" _dynamic starts at %lx\n", origin + N_DATOFF(*ex));
|
||||
printf(" so_debug starts at %lx\n", (unsigned long) dyn->d_debug);
|
||||
printf(" sdt starts at %lx\n", (unsigned long) dyn->d_un.d_sdt);
|
||||
printf(" got starts at %lx\n", sdt->sdt_got);
|
||||
printf(" plt starts at %lx\n", sdt->sdt_plt);
|
||||
printf(" rest of stuff starts at %lx\n",
|
||||
sdt->sdt_plt + sdt->sdt_plt_sz);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_sods()
|
||||
{
|
||||
long sod_offset;
|
||||
long paths_offset;
|
||||
|
||||
if (dyn == NULL) /* Not a shared object */
|
||||
return;
|
||||
|
||||
sod_offset = sdt->sdt_sods;
|
||||
printf(" Shared object dependencies:\n");
|
||||
while (sod_offset != 0) {
|
||||
const struct sod *sodp = (const struct sod *) (text_addr + sod_offset);
|
||||
const char *name = (const char *) (text_addr + sodp->sod_name);
|
||||
|
||||
if (sodp->sod_library)
|
||||
printf(" -l%-16s version %d.%d\n", name, sodp->sod_major,
|
||||
sodp->sod_minor);
|
||||
else
|
||||
printf(" %s\n", name);
|
||||
sod_offset = sodp->sod_next;
|
||||
}
|
||||
paths_offset = sdt->sdt_paths;
|
||||
printf(" Shared object additional paths:\n");
|
||||
if (paths_offset != 0) {
|
||||
char *path = (char *)(text_addr + paths_offset);
|
||||
printf(" %s\n", path);
|
||||
} else {
|
||||
printf(" (none)\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_sym(const struct nlist *np)
|
||||
{
|
||||
char type[8];
|
||||
char aux[8];
|
||||
char weak;
|
||||
char *p;
|
||||
|
||||
switch (np->n_type & ~N_EXT) {
|
||||
case N_UNDF: strcpy(type, "undf"); break;
|
||||
case N_ABS: strcpy(type, "abs"); break;
|
||||
case N_TEXT: strcpy(type, "text"); break;
|
||||
case N_DATA: strcpy(type, "data"); break;
|
||||
case N_BSS: strcpy(type, "bss"); break;
|
||||
case N_INDR: strcpy(type, "indr"); break;
|
||||
case N_SIZE: strcpy(type, "size"); break;
|
||||
case N_COMM: strcpy(type, "comm"); break;
|
||||
case N_SETA: strcpy(type, "seta"); break;
|
||||
case N_SETT: strcpy(type, "sett"); break;
|
||||
case N_SETD: strcpy(type, "setd"); break;
|
||||
case N_SETB: strcpy(type, "setb"); break;
|
||||
case N_SETV: strcpy(type, "setv"); break;
|
||||
case N_FN: strcpy(type, np->n_type&N_EXT ? "fn" : "warn"); break;
|
||||
case N_GSYM: strcpy(type, "gsym"); break;
|
||||
case N_FNAME: strcpy(type, "fname"); break;
|
||||
case N_FUN: strcpy(type, "fun"); break;
|
||||
case N_STSYM: strcpy(type, "stsym"); break;
|
||||
case N_LCSYM: strcpy(type, "lcsym"); break;
|
||||
case N_MAIN: strcpy(type, "main"); break;
|
||||
case N_PC: strcpy(type, "pc"); break;
|
||||
case N_RSYM: strcpy(type, "rsym"); break;
|
||||
case N_SLINE: strcpy(type, "sline"); break;
|
||||
case N_DSLINE: strcpy(type, "dsline"); break;
|
||||
case N_BSLINE: strcpy(type, "bsline"); break;
|
||||
case N_SSYM: strcpy(type, "ssym"); break;
|
||||
case N_SO: strcpy(type, "so"); break;
|
||||
case N_LSYM: strcpy(type, "lsym"); break;
|
||||
case N_BINCL: strcpy(type, "bincl"); break;
|
||||
case N_SOL: strcpy(type, "sol"); break;
|
||||
case N_PSYM: strcpy(type, "psym"); break;
|
||||
case N_EINCL: strcpy(type, "eincl"); break;
|
||||
case N_ENTRY: strcpy(type, "entry"); break;
|
||||
case N_LBRAC: strcpy(type, "lbrac"); break;
|
||||
case N_EXCL: strcpy(type, "excl"); break;
|
||||
case N_RBRAC: strcpy(type, "rbrac"); break;
|
||||
case N_BCOMM: strcpy(type, "bcomm"); break;
|
||||
case N_ECOMM: strcpy(type, "ecomm"); break;
|
||||
case N_ECOML: strcpy(type, "ecoml"); break;
|
||||
case N_LENG: strcpy(type, "leng"); break;
|
||||
default:
|
||||
snprintf(type, sizeof type, "%#02x", np->n_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (np->n_type & N_EXT && type[0] != '0')
|
||||
for (p = type; *p != '\0'; ++p)
|
||||
*p = toupper(*p);
|
||||
|
||||
switch (N_AUX(np)) {
|
||||
case 0: strcpy(aux, ""); break;
|
||||
case AUX_OBJECT: strcpy(aux, "objt"); break;
|
||||
case AUX_FUNC: strcpy(aux, "func"); break;
|
||||
default: snprintf(aux, sizeof aux, "%#01x", N_AUX(np)); break;
|
||||
}
|
||||
|
||||
weak = N_BIND(np) == BIND_WEAK ? 'w' : ' ';
|
||||
|
||||
printf("%c%-6s %-4s %8lx", weak, type, aux, np->n_value);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_syms()
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
printf(" Symbols:\n");
|
||||
for (i = 0; i < sym_count; ++i) {
|
||||
printf(" %6lu%c ", i, sym_used[i] ? '*' : ' ');
|
||||
dump_sym(&sym_base[i]);
|
||||
printf(" %s\n", sym_name(i));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
error(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
putc('\n', stderr);
|
||||
|
||||
++error_count;
|
||||
}
|
||||
|
||||
static const char *
|
||||
rtsym_name(unsigned long n)
|
||||
{
|
||||
assert(n < rtsym_count);
|
||||
if (rtsym_base[n].nz_strx == 0)
|
||||
return "";
|
||||
return rtstr_base + rtsym_base[n].nz_strx;
|
||||
}
|
||||
|
||||
static const char *
|
||||
sym_name(unsigned long n)
|
||||
{
|
||||
assert(n < sym_count);
|
||||
if (sym_base[n].n_un.n_strx == 0)
|
||||
return "";
|
||||
return str_base + sym_base[n].n_un.n_strx;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
# $Id: Makefile,v 1.24 1997/04/16 11:31:32 bde Exp $
|
||||
PROG= ld.so
|
||||
SRCS= mdprologue.S rtld.c shlib.c md.c support.c
|
||||
MAN1= rtld.1
|
||||
LDDIR?= $(.CURDIR)/..
|
||||
# As there is relocation going on behind GCC's back, don't cache function addresses.
|
||||
PICFLAG=-fpic -fno-function-cse
|
||||
CFLAGS+=-I$(LDDIR) -I$(.CURDIR) -I$(LDDIR)/$(MACHINE) $(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
|
||||
BINDIR= /usr/libexec
|
||||
INSTALLFLAGS+= -fschg -C # -C to install as atomically as possible
|
||||
MLINKS= rtld.1 ld.so.1
|
||||
|
||||
.PATH: $(LDDIR) $(LDDIR)/$(MACHINE)
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* rtld entry pseudo code - turn into assembler and tweak it
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/types.h>
|
||||
#include <a.out.h>
|
||||
#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)();
|
||||
}
|
@ -1,224 +0,0 @@
|
||||
.\" $Id: rtld.1,v 1.14 1997/05/27 13:46:40 max Exp $
|
||||
.\"
|
||||
.\" 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 FreeBSD
|
||||
.Sh NAME
|
||||
.Nm ld.so
|
||||
.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
|
||||
.Po
|
||||
see
|
||||
.Xr link 5
|
||||
.Pc
|
||||
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
|
||||
.Po
|
||||
see
|
||||
.Xr link 5
|
||||
for details
|
||||
.Pc \&.
|
||||
.Em crt0
|
||||
passes control to
|
||||
.Nm
|
||||
\&'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 filesystem,
|
||||
.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
|
||||
.Ao
|
||||
library-name, major-version-number, minor-version-number
|
||||
.Ac \&.
|
||||
.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 '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 -indent "LD_TRACE_LOADED_OBJECTS_FMT1 " -width "xxxx"
|
||||
.It \&%a
|
||||
The main program's name
|
||||
.Po also known as
|
||||
.Dq __progname
|
||||
.Pc .
|
||||
.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 filesystem 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
|
File diff suppressed because it is too large
Load Diff
@ -1,342 +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.
|
||||
*
|
||||
* $Id: shlib.c,v 1.18 1997/02/22 15:46:24 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/time.h>
|
||||
#include <a.out.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <link.h>
|
||||
#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)
|
||||
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 == 0) /* No version number */
|
||||
continue;
|
||||
|
||||
if(*majorp != -1) { /* Need exact match on major */
|
||||
if(cur_dewey[0] != *majorp)
|
||||
continue;
|
||||
if(*minorp != -1) { /* Need minor >= minimum */
|
||||
if(cur_ndewey < 2 ||
|
||||
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];
|
||||
if(best_ndewey >= 2)
|
||||
*minorp = best_dewey[1];
|
||||
return concat(dir, "/", dot_so_name);
|
||||
}
|
||||
|
||||
if(dot_a_name[0] != '\0')
|
||||
return concat(dir, "/", dot_a_name);
|
||||
|
||||
return 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.
|
||||
*-
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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((char *));
|
||||
char *search_lib_dir __P((char *, char *, int *, int *, int));
|
@ -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.
|
||||
*-
|
||||
* $Id$
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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.
|
||||
*-
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 *));
|
Loading…
Reference in New Issue
Block a user