Init
This commit is contained in:
54
lang/ld/MakeCommon
Normal file
54
lang/ld/MakeCommon
Normal file
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# @(#)MakeCommon 1.1 94/10/31 SMI
|
||||
#
|
||||
.KEEP_STATE:
|
||||
|
||||
arch-sun3 = SUN3
|
||||
arch-sun2 = SUN2
|
||||
arch-sun4 = SUN4
|
||||
arch-sun3x = SUN3
|
||||
arch-sun4c = SUN4
|
||||
TARGET=$(arch$(TARGET_ARCH))
|
||||
|
||||
cpu-sun2 = m68k
|
||||
cpu-sun3 = m68k
|
||||
cpu-sun3x = m68k
|
||||
cpu-sun4 = sparc
|
||||
cpu-sun4c = sparc
|
||||
CPU=$(cpu$(TARGET_ARCH))
|
||||
|
||||
#
|
||||
# Code browser changes:
|
||||
#
|
||||
# Comment out the next line to disable code browser.
|
||||
BROWSER = -DBROWSER
|
||||
CB_DIR = ../../browser/cblib
|
||||
CB_LIB = $(CB_DIR)/$(CPU)/libcb.a
|
||||
CB_LIBRARY-DBROWSER = $(CB_LIB)
|
||||
CB_DIRECTORY-DBROWSER = $(CB_DIR)/src
|
||||
CFLAGS += $(DBX) -DSUNPRO -I../../vroot -I$(CB_DIRECTORY$(BROWSER)) $(BROWSER)
|
||||
|
||||
VROOT_DIR = ../../vroot
|
||||
VROOT_LIB = $(VROOT_DIR)/vroot.a
|
||||
$(CB_LIB) $(VROOT_LIB): FRC
|
||||
(cd $(@D); $(MAKE) $(@F))
|
||||
|
||||
FRC:
|
||||
|
||||
HDRS = ../dynamic.h
|
||||
MID_SRCS = ../ld.c ../rtsetup.c ../incl.c ../libfind.c ../verscmp.c \
|
||||
../vroot.c ../extra.c
|
||||
MID_OBJS = $(MID_SRCS:../%.c=%.o)
|
||||
OBJS = ${MID_OBJS}
|
||||
LIBS = $(CB_LIBRARY$(BROWSER)) $(VROOT_LIB)
|
||||
|
||||
${MID_OBJS}: ../$$(@:.o=.c)
|
||||
$(CC) $(CFLAGS) -c ../$(@:.o=.c)
|
||||
|
||||
masterclean:
|
||||
rm -f ${PROGRAM} ${OBJS}
|
||||
|
||||
masterlint :
|
||||
lint $(LINTFLAGS) -I.. $(MID_SRCS)
|
||||
|
||||
|
||||
26
lang/ld/Makefile
Normal file
26
lang/ld/Makefile
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# @(#)Makefile 1.1 94/10/31 SMI
|
||||
#
|
||||
|
||||
DESTDIR=
|
||||
|
||||
all: FRC
|
||||
cd ${CPU}; make ${MFLAGS} CC="${CC}" AS="${AS}"
|
||||
|
||||
xm68k: FRC
|
||||
cd m68k; make ${MFLAGS} CC="${CC}" AS="${AS}"
|
||||
|
||||
xsparc: FRC
|
||||
cd sparc; make ${MFLAGS} CC="${CC}" AS="${AS}"
|
||||
|
||||
xall: FRC
|
||||
cd m68k; make ${MFLAGS} CC="${CC}" AS="${AS}"
|
||||
cd sparc; make ${MFLAGS} CC="${CC}" AS="${AS}"
|
||||
|
||||
install: FRC
|
||||
cd ${CPU}; make ${MFLAGS} DESTDIR=${DESTDIR} install
|
||||
|
||||
clean:
|
||||
cd ${CPU}; make ${MFLAGS} clean
|
||||
|
||||
FRC:
|
||||
143
lang/ld/dynamic.h
Normal file
143
lang/ld/dynamic.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/* @(#)dynamic.h 1.1 94/10/31 SMI; */
|
||||
|
||||
|
||||
#define LHSIZ 31
|
||||
#define RTHS 126
|
||||
#define MAXLIB 126
|
||||
|
||||
struct libentry {
|
||||
char *addr; /* address where lib is mapped to */
|
||||
char *name; /* path name of library */
|
||||
struct libentry *next;
|
||||
};
|
||||
|
||||
struct dynamic {
|
||||
struct libentry *lib_entry; /* ptr to list of libraries */
|
||||
int ds; /* size of data link table */
|
||||
int js; /* size of data jump table */
|
||||
int rs; /* size of relocation */
|
||||
int hs; /* size of symbol hash table */
|
||||
int ss; /* size of symbol */
|
||||
int sts; /* size of symbol strings */
|
||||
int ts; /* size of text aera */
|
||||
int lib; /* number of libraries */
|
||||
int libstr; /* lenght of libraries strings */
|
||||
int got_off; /* offset in GOT of 0'th entry */
|
||||
};
|
||||
|
||||
/*
|
||||
* +++++ for sun2 we need to fix the problem where
|
||||
* displacement (jb_un.jb.location) is greater than 64k
|
||||
*/
|
||||
#if TARGET==SUN4
|
||||
struct jbind {
|
||||
int jb_inst[3]; /* need 4 instructions for jump slot */
|
||||
};
|
||||
#endif
|
||||
#if TARGET==SUN3 || TARGET==SUN2
|
||||
struct jbind {
|
||||
unsigned short code;
|
||||
unsigned short cl_hi;
|
||||
unsigned short cl_low;
|
||||
short reloc_index;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct fshash {
|
||||
int fssymbno; /* ordinal symbol number */
|
||||
int next; /* index to the hash array pointed by fs_hash */
|
||||
};
|
||||
|
||||
#undef relocation_info
|
||||
#if TARGET== SUN4
|
||||
# define relocation_info reloc_info_sparc
|
||||
# define r_symbolnum r_index
|
||||
#else /* !sun4 , thus mc68000 */
|
||||
# define relocation_info reloc_info_68k
|
||||
#endif /* mc68000 */
|
||||
|
||||
|
||||
/*
|
||||
* this structure is used to build the hash and the symbol tables for
|
||||
* runtime linking.
|
||||
*/
|
||||
struct runtime {
|
||||
int *dt; /* pointer to data linkage table */
|
||||
struct jbind *jt; /* pointer to jump linkage table */
|
||||
struct relocation_info *rp; /* ptr to first runtime reloc entry */
|
||||
int rl; /* no of reloc needed for runtime */
|
||||
struct fshash *hp; /* first entry of hash table */
|
||||
struct nlist *sp; /* first entry of runtime symb table */
|
||||
struct fshash *hp_last; /* last entry of hash table */
|
||||
struct nlist *sp_last; /* last entry of symbol table */
|
||||
char *fsstr; /* pointer to strings aera */
|
||||
int hp_ind; /* index to the next hash entry */
|
||||
struct nlist *spp; /* ptr to next available symbol entry */
|
||||
int *dtp; /* ptr to next available data slot */
|
||||
struct jbind *jtp; /* ptr to next available jump slot */
|
||||
int dto; /* offset in bytes into data table */
|
||||
int jto; /* offset in bytes into jump table */
|
||||
struct relocation_info *rpp; /* ptr to next available reloc entry */
|
||||
struct dynamic *dp; /* ptr to dynamic structure */
|
||||
int fsoff; /* current offset to fast symbol aera */
|
||||
int fsalloc; /* space allocated for fast symbols */
|
||||
char *searchpath; /* search pathname */
|
||||
int spthlen; /* search pathname string len */
|
||||
int us; /* number of undefined symbols */
|
||||
char *libname; /* pointer to the shlib name list */
|
||||
int lko_i; /* index into lko array */
|
||||
long buckets; /* number of hash buckets needed */
|
||||
struct link_object lko[MAXLIB];/* link object array */
|
||||
};
|
||||
|
||||
struct dslot {
|
||||
int js; /* jump table slots */
|
||||
int ds; /* data table slots */
|
||||
int ss; /* static table slots */
|
||||
};
|
||||
|
||||
struct rl {
|
||||
int rl_d; /* total no of reloc for data segment */
|
||||
int rl_de; /* no of reloc to external symb in data segment */
|
||||
int rl_t; /* total no of non pic reloc for text segment */
|
||||
int rl_te; /* no of non pic reloc to external in text segment */
|
||||
};
|
||||
|
||||
struct ssymbol {
|
||||
struct ssymbol *ss_next; /* next symbol */
|
||||
char *ssp; /* pointer to symbol */
|
||||
int ssflag; /* object or process symbol */
|
||||
};
|
||||
|
||||
#if TARGET==SUN4
|
||||
#define SETHI 0x03000000 /* sethi %hi(val),%g1 */
|
||||
#define SETHIG0 0x01000000 /* sethi %hi(val),%g0 */
|
||||
#define ORIT 0x82106000 /* or %g1,val,%g1 */
|
||||
#define JMPI 0x81c06000 /* jmpl %g1 */
|
||||
#define NOP 0x01000000 /* nop */
|
||||
#define BA 0x10800000 /* branch always */
|
||||
#define TRAP 0x91d02001
|
||||
#define SAVE 0x9de3bfa0 /* save minimun frame */
|
||||
#define CALL 0x40000000 /* call instuction */
|
||||
#define lalign(i) (i%(sizeof (double)) ? i + ((sizeof (double))-(i%(sizeof (double)))) : i)
|
||||
|
||||
#endif
|
||||
#if TARGET==SUN3 || TARGET==SUN2
|
||||
|
||||
#define lalign(i) (i%(sizeof (long)) ? i + ((sizeof (long))-(i%(sizeof (long)))) : i)
|
||||
#define NOP 0x4e71
|
||||
#define JSR 0x4eb9
|
||||
#define JUMP 0x4ef9
|
||||
#define TRAP 0x4e4f
|
||||
#if TARGET==SUN2
|
||||
#define JBSR 0x6100
|
||||
#else
|
||||
#define JBSR 0x61ff
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define D_NAME "__DYNAMIC"
|
||||
#define LDPATH "LD_LIBRARY_PATH"
|
||||
|
||||
#define v1 ld_un.ld_1
|
||||
#define v2 ld_un.ld_2
|
||||
127
lang/ld/extra.c
Normal file
127
lang/ld/extra.c
Normal file
@@ -0,0 +1,127 @@
|
||||
#ident "@(#)extra.c 1.1 94/10/31"
|
||||
|
||||
#include <a.out.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* collect_extra_sections is called from load2() when it is
|
||||
* noticed that there is more stuff after the string table.
|
||||
* this is assumed to be the extra section stuff, which
|
||||
* is to be concatenated, each in its respective sections,
|
||||
* at the end of the output file. Because we don't know
|
||||
* how long the string table is going to turn out to be,
|
||||
* we cannot simply copy to the appropriate place in
|
||||
* that file. Instead, we use temp files, which have
|
||||
* to be copied at the end. Sad.
|
||||
*/
|
||||
|
||||
#define MAX_EXTRA_SECTIONS 2
|
||||
FILE * temp_file[MAX_EXTRA_SECTIONS] = { NULL, NULL };
|
||||
char * temp_file_name[MAX_EXTRA_SECTIONS] = { NULL, NULL };
|
||||
int n_extra_sections = 0;
|
||||
int total_size[MAX_EXTRA_SECTIONS];
|
||||
|
||||
void
|
||||
collect_extra_sections( iop, loc, offset, maxoff )
|
||||
void * iop; /* opaque-to-me pointer to an IO block. */
|
||||
long loc; /* offset in containing file (for archives) */
|
||||
int offset; /* where in the input file/element the string table ends */
|
||||
int maxoff; /* where the input file/element ends */
|
||||
{
|
||||
struct extra_sections xtra;
|
||||
int section_size[ MAX_EXTRA_SECTIONS];
|
||||
FILE * sect_fd;
|
||||
int secno, l, seclength;
|
||||
char buffer[512];
|
||||
|
||||
/* establish IO contact with the extra sections */
|
||||
dseek1( iop, loc+offset, maxoff-offset );
|
||||
/* read the header */
|
||||
mget( (char *)&xtra, sizeof(xtra), iop);
|
||||
if (xtra.extra_magic != EXTRA_MAGIC)
|
||||
error(1, "bad secondary magic number");
|
||||
if ( xtra.extra_nsects >= MAX_EXTRA_SECTIONS )
|
||||
error(1, "too many extra sections");
|
||||
/* read the section size table */
|
||||
mget( (char *)section_size, xtra.extra_nsects*sizeof(int), iop );
|
||||
/* open the temp files, as necessary */
|
||||
while ( n_extra_sections < xtra.extra_nsects ){
|
||||
create_section_temp( n_extra_sections++ );
|
||||
}
|
||||
|
||||
/* now shovel the stuff */
|
||||
for ( secno = 0 ; secno < xtra.extra_nsects ; secno += 1 ){
|
||||
seclength = 0;
|
||||
sect_fd = temp_file[secno];
|
||||
while ( (l = section_size[secno] - seclength) > 0 ){
|
||||
if ( l > sizeof(buffer) ) l = sizeof(buffer);
|
||||
mget( buffer, l, iop );
|
||||
fwrite( buffer, l, 1, sect_fd );
|
||||
seclength += l;
|
||||
}
|
||||
total_size[secno] += seclength;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
write_extra_sections( strout )
|
||||
void * strout; /* opaque-to-me pointer to an IO block. */
|
||||
{
|
||||
struct extra_sections xtra;
|
||||
FILE * sect_fd;
|
||||
int secno, l, seclength;
|
||||
char buffer[512];
|
||||
|
||||
if ( n_extra_sections == 0 ) return;
|
||||
|
||||
/* setup and write the header */
|
||||
xtra.extra_magic = EXTRA_MAGIC;
|
||||
xtra.extra_nsects = n_extra_sections;
|
||||
bwrite( &xtra, sizeof(xtra), strout );
|
||||
/* write segment size table */
|
||||
bwrite( &total_size[0], n_extra_sections*sizeof(total_size[0]), strout );
|
||||
|
||||
/* now shovel the stuff */
|
||||
for ( secno = 0 ; secno < xtra.extra_nsects ; secno += 1 ){
|
||||
seclength = 0;
|
||||
sect_fd = temp_file[secno];
|
||||
rewind( sect_fd );
|
||||
while ( (l = total_size[secno] - seclength) > 0 ){
|
||||
if ( l > sizeof(buffer) ) l = sizeof(buffer);
|
||||
if ( fread( buffer, 1, l, sect_fd ) != l )
|
||||
error(1, "ioerror in write_extra_sections");
|
||||
bwrite( buffer, l, strout );
|
||||
seclength += l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* junk routines for tmp file housekeeping.
|
||||
*/
|
||||
|
||||
create_section_temp( n ) /* called from collect_extra_sections() as needed */
|
||||
{
|
||||
char tmpprefix[23] ; /* random number */
|
||||
sprintf( tmpprefix, "ld.%d.", n );
|
||||
temp_file_name[n] = tempnam( NULL, tmpprefix );
|
||||
if ( (temp_file[n] = fopen( temp_file_name[n], "w+")) == NULL){
|
||||
error(1,"cannot create section temp files");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
delete_section_temps() /* called from delexit() */
|
||||
{
|
||||
|
||||
while (n_extra_sections > 0 ){
|
||||
fclose( temp_file[n_extra_sections-1] );
|
||||
if ( unlink( temp_file_name[n_extra_sections-1] ) != 0 ){
|
||||
error(1, "cannot remove section temp files");
|
||||
}
|
||||
free( temp_file_name[n_extra_sections-1] );
|
||||
n_extra_sections -= 1;
|
||||
}
|
||||
}
|
||||
318
lang/ld/incl.c
Normal file
318
lang/ld/incl.c
Normal file
@@ -0,0 +1,318 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)incl.c 1.1 94/10/31 Copyr 1991 Sun Micro";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986, 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <a.out.h>
|
||||
#include <stab.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* Info about each include file
|
||||
*/
|
||||
struct incl {
|
||||
char *name; /* Name of header file */
|
||||
int nstatic; /* # of statics in the file */
|
||||
int nsymbols; /* # of symbols in header file */
|
||||
int checksum; /* Checksum for header file */
|
||||
int ord; /* Ordinal # of header file */
|
||||
int exclude; /* Flag: include/exclude syms */
|
||||
struct incl *next; /* Linked Hash list */
|
||||
};
|
||||
|
||||
#define NINCL_STACK 10 /* Size of the include stack */
|
||||
#define INCL_HASH 64 /* Size of header file hash table */
|
||||
|
||||
static struct incl **incl_stack; /* Include file stack */
|
||||
static int stack_size; /* Size of incl_stack */
|
||||
static struct incl **stkp; /* Stack pointer */
|
||||
static struct incl *incl_table[INCL_HASH]; /* Table saved for pass 2 */
|
||||
static struct incl *cur_incl; /* Current header file */
|
||||
static int obj_ord; /* Saved value of header_num */
|
||||
|
||||
extern int ssize; /* Size of symbol section */
|
||||
extern int header_num; /* Ordinal value of next header file */
|
||||
|
||||
struct incl *find_ord();
|
||||
char *strcpy();
|
||||
char *mymalloc();
|
||||
char *realloc();
|
||||
|
||||
/*
|
||||
* Allocate the intial include file stack.
|
||||
* The stack will grow if necessary.
|
||||
*/
|
||||
alloc_inclstack()
|
||||
{
|
||||
if ((incl_stack = (struct incl **) mymalloc(NINCL_STACK*sizeof(struct incl *))) == 0)
|
||||
error(1, "ran out of memory (alloc_inclstack)");
|
||||
stkp = incl_stack;
|
||||
stack_size = NINCL_STACK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Beginning a new object file. Remember the ordinal number
|
||||
* of the next header file in case this object file is not
|
||||
* used and everything needs to be ripped out and thrown away.
|
||||
*/
|
||||
new_obj1()
|
||||
{
|
||||
obj_ord = header_num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter a new include file.
|
||||
* Stack the current one, if it is active.
|
||||
* Allocate a structure and initialize it.
|
||||
*/
|
||||
start_incl1(sym, ord)
|
||||
struct nlist *sym;
|
||||
int ord;
|
||||
{
|
||||
char *name;
|
||||
int n;
|
||||
register char *namespace;
|
||||
|
||||
if (stkp >= &incl_stack[stack_size]) {
|
||||
n = stkp - incl_stack;
|
||||
stack_size += NINCL_STACK;
|
||||
if ((incl_stack = (struct incl **) realloc(incl_stack,
|
||||
stack_size * sizeof(struct incl *))) == 0)
|
||||
error(1, "ran out of memory (start_incl1)");
|
||||
stkp = &incl_stack[n];
|
||||
}
|
||||
*stkp++ = cur_incl;
|
||||
name = sym->n_un.n_name;
|
||||
if ((cur_incl = (struct incl *) mymalloc(sizeof(struct incl))) == 0)
|
||||
error(1, "ran out of memory (start_incl1)");
|
||||
if ((namespace = mymalloc(strlen(name) + 1)) == 0)
|
||||
error(1, "ran out of memory (start_incl1)");
|
||||
cur_incl->name = strcpy(namespace, name);
|
||||
cur_incl->nstatic = 0;
|
||||
cur_incl->nsymbols = 0;
|
||||
cur_incl->checksum = 0;
|
||||
cur_incl->ord = ord;
|
||||
cur_incl->exclude = 0;
|
||||
cur_incl->next = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found the end of an include file.
|
||||
* Hash on its name and enter it into the
|
||||
* has table. Pass two will find it by
|
||||
* its name and ordinal number.
|
||||
* Also, pop one off of the stack.
|
||||
*/
|
||||
end_incl1()
|
||||
{
|
||||
int h;
|
||||
|
||||
h = hash(cur_incl->name);
|
||||
cur_incl->next = incl_table[h];
|
||||
incl_table[h] = cur_incl;
|
||||
cur_incl = *--stkp;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Found a dbx symbol in pass one.
|
||||
* If there is an active header file, include the info.
|
||||
* The checksum is the summation of all the characters except for
|
||||
* filenumbers which are digits immediately following an open
|
||||
* parenthesis in the n_name field of the nlist
|
||||
* structure.
|
||||
*/
|
||||
stab1(sym)
|
||||
struct nlist *sym;
|
||||
{
|
||||
register char *cp;
|
||||
|
||||
if (cur_incl == NULL) {
|
||||
return;
|
||||
}
|
||||
cur_incl->nsymbols++;
|
||||
if (sym->n_type == N_STSYM || sym->n_type == N_LCSYM || sym->n_type == N_EXCL ) {
|
||||
cur_incl->nstatic++;
|
||||
}
|
||||
cp = sym->n_un.n_name;
|
||||
if (sym->n_type != N_EXCL && cp != NULL) {
|
||||
while (*cp != '\0') {
|
||||
cur_incl->checksum += *cp;
|
||||
if (*cp == '(') {
|
||||
while (*++cp != '\0' && isdigit(*cp))
|
||||
;
|
||||
/*
|
||||
If no more symbols then return
|
||||
else continue at the top loop
|
||||
*/
|
||||
if (*cp == '\0')
|
||||
return;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* An object file was not used.
|
||||
* Must remove any header files it had from the hash table.
|
||||
*/
|
||||
incl_free()
|
||||
{
|
||||
struct incl *ip;
|
||||
struct incl *next;
|
||||
struct incl **ipp;
|
||||
struct incl **bpatch;
|
||||
int nhdrs;
|
||||
int removed;
|
||||
|
||||
if (obj_ord == header_num) {
|
||||
return;
|
||||
}
|
||||
removed = 0;
|
||||
nhdrs = header_num - obj_ord;
|
||||
for (ipp = incl_table; ipp < &incl_table[INCL_HASH]; ipp++) {
|
||||
bpatch = ipp;
|
||||
for (ip = *ipp; ip != NULL; ip = next) {
|
||||
next = ip->next;
|
||||
if (ip->ord >= obj_ord) {
|
||||
*bpatch = ip->next;
|
||||
free((char *) ip);
|
||||
removed++;
|
||||
} else {
|
||||
bpatch = &ip->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removed != nhdrs) {
|
||||
fprintf(stderr, "incl_free removed %d nhdrs %d\n",
|
||||
removed, nhdrs);
|
||||
}
|
||||
header_num = obj_ord;
|
||||
}
|
||||
|
||||
/*
|
||||
* See what header files can be excluded from the final output.
|
||||
* The important goal here is to determine how many symbols
|
||||
* will be excluded so that "ssize" can be adjusted. "Ssize"
|
||||
* determines the value that will be stored into the a_syms
|
||||
* field of the a.out header and also determines where the
|
||||
* string table will begin.
|
||||
*/
|
||||
merge_headers()
|
||||
{
|
||||
register struct incl *ip;
|
||||
register struct incl **ipp;
|
||||
|
||||
for (ipp = incl_table; ipp < &incl_table[INCL_HASH]; ipp++) {
|
||||
for (ip = *ipp; ip != NULL; ip = ip->next) {
|
||||
ip->exclude = find_prev(ip);
|
||||
if (ip->exclude) {
|
||||
ssize -= (ip->nsymbols + 1) *
|
||||
sizeof(struct nlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
cur_incl = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found the beginning of a header file in pass2.
|
||||
* Find the struct for the header file created in pass1.
|
||||
* See if there is an identical struct for a header file
|
||||
* with a lower ordinal value. If so, the symbols in this
|
||||
* file can be discarded.
|
||||
*/
|
||||
start_incl2(sym, ord)
|
||||
struct nlist *sym;
|
||||
int ord;
|
||||
{
|
||||
struct incl *ip;
|
||||
int r;
|
||||
|
||||
if (stkp > &incl_stack[stack_size]) {
|
||||
error(1, "include stack too deep");
|
||||
}
|
||||
*stkp++ = cur_incl;
|
||||
cur_incl = find_ord(sym, ord);
|
||||
sym->n_value = cur_incl->checksum;
|
||||
if (cur_incl->exclude) {
|
||||
sym->n_type = N_EXCL;
|
||||
}
|
||||
return(cur_incl->exclude);
|
||||
}
|
||||
|
||||
end_incl2()
|
||||
{
|
||||
cur_incl = *--stkp;
|
||||
return(cur_incl != NULL && cur_incl->exclude);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a header file with a given ordinal number.
|
||||
*/
|
||||
struct incl *
|
||||
find_ord(sym, ord)
|
||||
struct nlist *sym;
|
||||
int ord;
|
||||
{
|
||||
register struct incl *ip;
|
||||
int h;
|
||||
|
||||
h = hash(sym->n_un.n_name);
|
||||
for (ip = incl_table[h]; ip != NULL; ip = ip->next) {
|
||||
if (ip->ord == ord) {
|
||||
return(ip);
|
||||
}
|
||||
}
|
||||
error(1, "no include table entry for header file '%s'",
|
||||
sym->n_un.n_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find an identical header file with a lower ordinal number.
|
||||
*/
|
||||
find_prev(incl)
|
||||
register struct incl *incl;
|
||||
{
|
||||
register struct incl *ip;
|
||||
int h;
|
||||
|
||||
if (incl->nstatic > 0) {
|
||||
return(0);
|
||||
}
|
||||
h = hash(incl->name);
|
||||
for (ip = incl_table[h]; ip != NULL; ip = ip->next) {
|
||||
if (ip->nsymbols == incl->nsymbols &&
|
||||
ip->nstatic == 0 &&
|
||||
ip->checksum == incl->checksum &&
|
||||
ip->ord < incl->ord &&
|
||||
strcmp(incl->name, ip->name) == 0) {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute a hash from a string.
|
||||
* Simply sum the characters and mod.
|
||||
*/
|
||||
hash(str)
|
||||
char *str;
|
||||
{
|
||||
register int sum;
|
||||
register char *cp;
|
||||
|
||||
sum = 0;
|
||||
for (cp = str; *cp; cp++) {
|
||||
sum += *cp;
|
||||
}
|
||||
return(sum % INCL_HASH);
|
||||
}
|
||||
5395
lang/ld/ld.c
Normal file
5395
lang/ld/ld.c
Normal file
File diff suppressed because it is too large
Load Diff
106
lang/ld/libfind.c
Normal file
106
lang/ld/libfind.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/* @(#)libfind.c 1.1 94/10/31 */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <values.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
/*
|
||||
* At batch time if we have been asked which version number of some
|
||||
* library then we follow the search path until we found it else
|
||||
* if no version is found then we take the highest version in the
|
||||
* first directory where a macthing library is found.
|
||||
*/
|
||||
#define LIBSTR 255
|
||||
#define SPECIFIC 1
|
||||
|
||||
extern stol();
|
||||
extern char *calloc();
|
||||
|
||||
getshlib(dir, lib, mj, mn)
|
||||
char *dir;
|
||||
char *lib;
|
||||
int *mj;
|
||||
int *mn;
|
||||
{
|
||||
char *p;
|
||||
char *version;
|
||||
char *file;
|
||||
int len = 0;
|
||||
int lib_len = 0;
|
||||
DIR *dirp;
|
||||
register struct direct *dp;
|
||||
int maj = -MAXINT;
|
||||
int min = -MAXINT;
|
||||
int still_looking = 1;
|
||||
int cmp = 0;
|
||||
int flag = 0;
|
||||
int timeslooked =0;
|
||||
/*
|
||||
* determine whether a specific version of the library is wanted here.
|
||||
*/
|
||||
version = calloc(LIBSTR, 1);
|
||||
file = calloc(LIBSTR, 1);
|
||||
p = lib;
|
||||
while (*p != '\0') {
|
||||
len++;
|
||||
if (*p != '.')
|
||||
p++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (*p == '.') {
|
||||
if (strncmp(++p, "so", 2))
|
||||
error(1, "expected libx.so(.major.minor.xxx)\n");
|
||||
else {
|
||||
flag = SPECIFIC;
|
||||
lib_len = p - lib + 3;
|
||||
if (!stol(p + 3,'.', &p, &maj))
|
||||
error(1, "expected libx.so(.major.minor.xxx)\n");
|
||||
if (!stol(++p, '.', &p, &min))
|
||||
error(1, "expected libx.so(.major.minor.xxx)\n");
|
||||
}
|
||||
} else strcat(lib, ".so.");
|
||||
sprintf(version,"%d.%d", maj, min);
|
||||
len = strlen(lib);
|
||||
/*
|
||||
* open the directory
|
||||
*/
|
||||
dirp = opendir(dir);
|
||||
if (dirp == NULL)
|
||||
return (-1);
|
||||
|
||||
for (dp = readdir(dirp); dp != NULL && still_looking; dp = readdir(dirp)) {
|
||||
if (!strncmp(lib , dp->d_name, len)) {
|
||||
|
||||
if (flag == SPECIFIC) {
|
||||
strncpy(file, dp->d_name, lib_len);
|
||||
still_looking = 0;
|
||||
} else {
|
||||
if (((cmp = verscmp(dp->d_name + len, version)) > 0) ||
|
||||
((cmp == 0) && (*file == NULL))) {
|
||||
strncpy(file, dp->d_name, len);
|
||||
*version = '\0';
|
||||
strcpy(version, dp->d_name + len);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
if (file[0] != NULL) {
|
||||
strcat(dir, "/");
|
||||
strcat(dir, file);
|
||||
strcat(dir, version);
|
||||
stol(version, '.', &version, &maj);
|
||||
stol(++version, '.', &version, &min);
|
||||
*mj = maj;
|
||||
*mn = min;
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
19
lang/ld/reloc_info.h
Normal file
19
lang/ld/reloc_info.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* @(#)reloc_info.h 1.1 94/10/31 SMI; */
|
||||
|
||||
/* <a.out.h> must be included before this file. */
|
||||
|
||||
/* This is so the common linker code can refer to either the 68k or
|
||||
* SPARC relcation structure via the same name.
|
||||
*/
|
||||
|
||||
#undef relocation_info
|
||||
|
||||
#if (TARGET==SUN2) || (TARGET==SUN3)
|
||||
#define relocation_info reloc_info_68k
|
||||
#define MAX_GOT_SIZE 16384 /* XXX Should this be here? */
|
||||
#endif
|
||||
|
||||
#if (TARGET==SUN4)
|
||||
#define relocation_info reloc_info_sparc
|
||||
#define MAX_GOT_SIZE 2048 /* XXX Should this be here? */
|
||||
#endif
|
||||
277
lang/ld/rtsetup.c
Normal file
277
lang/ld/rtsetup.c
Normal file
@@ -0,0 +1,277 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rtsetup.c 1.1 94/10/31"; /* from UCB 5.4 85/11/26 */
|
||||
#endif not lint
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <a.out.h>
|
||||
#include <link.h>
|
||||
#include "dynamic.h"
|
||||
#include "reloc_info.h"
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
char *mymalloc();
|
||||
extern int picflag;
|
||||
|
||||
fs_init(rt, sb)
|
||||
register struct runtime *rt;
|
||||
register int sb; /* no of symbols for runtime linking */
|
||||
{
|
||||
register int i;
|
||||
long buckets;
|
||||
|
||||
/* buckets = sb/4; */
|
||||
buckets = (sb < 4 ? sb : sb/4);
|
||||
|
||||
rt->hp = (struct fshash *) mymalloc((buckets+sb)*sizeof(struct fshash));
|
||||
rt->sp = (struct nlist *) mymalloc(sb * sizeof (struct nlist));
|
||||
rt->hp_last = rt->hp + (buckets+sb);
|
||||
rt->sp_last = rt->sp + sb;
|
||||
rt->fsalloc = lalign(rt->fsalloc);
|
||||
rt->fsstr = (char *) calloc(rt->fsalloc, 1);
|
||||
if (rt->hp == 0 || rt->sp == 0 || rt->fsstr == 0)
|
||||
error(1, "out of memory in buildfs");
|
||||
rt->spp = rt->sp;
|
||||
for (i = 0; i < buckets; i++) {
|
||||
(rt->hp+i)->fssymbno = -1; /* mark it empty with -1 */
|
||||
(rt->hp+i)->next = 0; /* init with null index ptr */
|
||||
}
|
||||
rt->hp_ind = buckets;
|
||||
rt->buckets = buckets;
|
||||
}
|
||||
|
||||
/*
|
||||
* this routine does a bunch of initializations for runtime linking
|
||||
*/
|
||||
rt_init(rt)
|
||||
register struct runtime *rt;
|
||||
{
|
||||
register int i;
|
||||
|
||||
i = totalsymb();
|
||||
fs_init(rt, i);
|
||||
rt->rl = calcreloc();
|
||||
if ((rt->rp = (struct relocation_info *) calloc (rt->rl,
|
||||
sizeof (struct relocation_info))) == 0)
|
||||
error(1, "out of memory for dynamic relocation");
|
||||
rt->rpp = rt->rp;
|
||||
}
|
||||
|
||||
dp_init(rt)
|
||||
register struct runtime *rt;
|
||||
{
|
||||
register struct dynamic *dp = rt->dp;
|
||||
register int i;
|
||||
|
||||
i = totalsymb();
|
||||
dp->rs = rt->rl * sizeof (struct relocation_info);
|
||||
dp->ss = i * sizeof (struct nlist);
|
||||
dp->sts = rt->fsalloc;
|
||||
dp->hs = rt->hp_ind * sizeof (struct fshash);
|
||||
|
||||
/*
|
||||
* jump table entries needed to be on an even boundary
|
||||
*/
|
||||
dp->libstr = lalign(dp->libstr);
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize for data and jump linkage.
|
||||
*/
|
||||
dj_init(rt, slp, flag)
|
||||
register struct runtime *rt;
|
||||
register struct dslot *slp;
|
||||
register int flag; /* if nonzero then set it up for runtime linking */
|
||||
{
|
||||
register struct dynamic *dp = rt->dp;
|
||||
|
||||
/*
|
||||
* for runtime linking we need one extra slot in the data linkage
|
||||
* table to store the address of symbol __DYNAMIC. This is done
|
||||
* so that the runtime linker can find its own dynamic structure
|
||||
* before it can relocate itself.
|
||||
* We also need an extra slot in the jump linkage table which
|
||||
* contained the direct jump to the runtime binder (all the
|
||||
* jump entries do a pc relative jump to this slot).
|
||||
*/
|
||||
if (slp->ds || slp->ss || slp->js) {
|
||||
slp->ds += 1;
|
||||
slp->js += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the offset into the GOT storage area for the
|
||||
* GOT symbol itself. In some implementations, the GOT may
|
||||
* be accessed by a signed displacement, this fact is adjusted
|
||||
* for here.
|
||||
*/
|
||||
dp->got_off = slp->ds + slp->ss;
|
||||
if ((slp->ds + slp->ss) > MAX_GOT_SIZE) {
|
||||
if (picflag == 1)
|
||||
error(1,
|
||||
"GLOBAL_OFFSET_TABLE overflown: need to use -PIC");
|
||||
dp->got_off = 0;
|
||||
} else {
|
||||
if (dp->got_off > (MAX_GOT_SIZE / 2))
|
||||
dp->got_off = ((MAX_GOT_SIZE / 2) - dp->got_off) *
|
||||
sizeof (int);
|
||||
else
|
||||
dp->got_off = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* be careful here: the number of bytes for jump slots
|
||||
* are machine dependent. +++++++
|
||||
*/
|
||||
dp->ds = (slp->ds + slp->ss) * sizeof(int);
|
||||
dp->js = slp->js * sizeof(struct jbind);
|
||||
if ((rt->dt = (int *) calloc(dp->ds, sizeof(int))) == 0)
|
||||
error(1, "can't allocate space for data linkage table");
|
||||
rt->dtp = rt->dt;
|
||||
rt->dto = dp->got_off;
|
||||
if (dp->js != 0) {
|
||||
if ((rt->jt = (struct jbind *) calloc(dp->js,
|
||||
sizeof(struct jbind))) == 0)
|
||||
error(1, "can't allocate space for jump linkage table");
|
||||
if (flag) {
|
||||
rt->jtp = rt->jt + 1;
|
||||
rt->jto = sizeof(struct jbind);
|
||||
#if TARGET==SUN4
|
||||
setupjs(rt->jt, 0);
|
||||
#endif
|
||||
#if TARGET==SUN3 || TARGET==SUN2
|
||||
rt->jt->code = JUMP;
|
||||
#endif
|
||||
} else {
|
||||
rt->jtp = rt->jt;
|
||||
rt->jto = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init_lkd(lkdp, rt, ts, db)
|
||||
register struct link_dynamic *lkdp;
|
||||
register struct runtime *rt;
|
||||
int ts; /* text size */
|
||||
int db; /* database */
|
||||
{
|
||||
int off;
|
||||
int i;
|
||||
int j;
|
||||
int k = 0;
|
||||
char *cp = rt->libname;
|
||||
|
||||
lkdp->ld_version = 2;
|
||||
lkdp->v2->ld_got = db + sizeof(struct link_dynamic) +
|
||||
sizeof(struct ld_debug) + sizeof(struct link_dynamic_2);
|
||||
lkdp->v2->ld_plt = lkdp->v2->ld_got + rt->dp->ds;
|
||||
lkdp->v2->ld_got += abs(rt->dp->got_off);
|
||||
lkdp->v2->ld_plt_sz = rt->dp->js;
|
||||
|
||||
lkdp->v2->ld_rel = ts;
|
||||
lkdp->v2->ld_hash = lkdp->v2->ld_rel + rt->dp->rs;
|
||||
lkdp->v2->ld_stab = lkdp->v2->ld_hash + rt->dp->hs;
|
||||
lkdp->v2->ld_symbols = lkdp->v2->ld_stab + rt->dp->ss;
|
||||
if (rt->searchpath)
|
||||
lkdp->v2->ld_rules = lkdp->v2->ld_symbols + rt->fsalloc;
|
||||
lkdp->v2->ld_symb_size = rt->fsalloc;
|
||||
i = rt->dp->lib;
|
||||
if (i == 0)
|
||||
lkdp->v2->ld_need = 0;
|
||||
else {
|
||||
if (lkdp->v2->ld_rules)
|
||||
lkdp->v2->ld_need = lkdp->v2->ld_rules +
|
||||
lalign(rt->spthlen);
|
||||
else
|
||||
lkdp->v2->ld_need = lkdp->v2->ld_symbols + rt->fsalloc;
|
||||
off = lkdp->v2->ld_need + (i * sizeof(struct link_object));
|
||||
j = 0;
|
||||
while (i > 0) {
|
||||
rt->lko[j].lo_name = off + k;
|
||||
k += strlen(cp) + 1;
|
||||
cp = rt->libname + k;
|
||||
i--;
|
||||
if (i == 0)
|
||||
rt->lko[j].lo_next = 0;
|
||||
else
|
||||
rt->lko[j].lo_next = lkdp->v2->ld_need +
|
||||
((j+1)*sizeof(struct link_object));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define skipblank(cp) while ( *cp == ' ' || *cp == '\n' ) cp++;
|
||||
#define GLOB_SYMB "object global"
|
||||
|
||||
struct ssymbol *ssymbol_p;
|
||||
|
||||
/*
|
||||
* this routine read in symbols from a file of the following format:
|
||||
* object global s1, s2, s3, ...., sn;
|
||||
* any reference to theses symbols will then be reduced to a relative
|
||||
* relocation.
|
||||
*/
|
||||
int
|
||||
getsymb(filename)
|
||||
char *filename;
|
||||
{
|
||||
int fd;
|
||||
struct stat sb;
|
||||
char *buf;
|
||||
char *cp;
|
||||
char *cp1;
|
||||
struct ssymbol *nsp;
|
||||
struct ssymbol *csp;
|
||||
char sc;
|
||||
|
||||
|
||||
/*
|
||||
* open file
|
||||
*/
|
||||
if ((fd = open(filename, O_RDONLY)) == -1)
|
||||
error(1, "open symbol file %s failed", filename);
|
||||
if (fstat(fd, &sb) == -1)
|
||||
error(1, "fstat symbol file %s failed", filename);
|
||||
buf = mmap(0, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
|
||||
/*
|
||||
* look for key word "object global"
|
||||
*/
|
||||
cp = buf;
|
||||
while ( *cp == ' ' ) cp++;
|
||||
if (!strcmp(cp, GLOB_SYMB))
|
||||
error(1, "missing key word (object global) in symbol file");
|
||||
cp += strlen(GLOB_SYMB);
|
||||
skipblank(cp);
|
||||
|
||||
/*
|
||||
* loop until ";", the marker for the end of the list is found.
|
||||
*/
|
||||
csp = ssymbol_p;
|
||||
cp1 = cp;
|
||||
for (;;) {
|
||||
if (*cp != ',' && *cp != ';') {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
sc = *cp;
|
||||
*cp++ = '\0';
|
||||
nsp = (struct ssymbol *) malloc( sizeof(struct ssymbol));
|
||||
nsp->ssp = cp1;
|
||||
nsp->ss_next = 0;
|
||||
if (csp)
|
||||
csp->ss_next = nsp;
|
||||
else
|
||||
ssymbol_p = nsp;
|
||||
csp = nsp;
|
||||
skipblank(cp);
|
||||
cp1 = cp;
|
||||
if (sc == ';')
|
||||
break;
|
||||
}
|
||||
}
|
||||
27
lang/ld/sparc/Makefile
Normal file
27
lang/ld/sparc/Makefile
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# @(#)Makefile 1.1 94/10/31
|
||||
#
|
||||
xall : all
|
||||
include ../MakeCommon
|
||||
|
||||
DIR= ..
|
||||
CFLAGS += -O -DSUN2=0 -DSUN3=1 -DSUN4=2 -Dsun4 -DDEBUG -DTARGET=$(TARGET) -I..
|
||||
HDRS= dynamic.h reloc_info.h
|
||||
PROGRAM = ld
|
||||
|
||||
all: ${HDRS:%.h=$(DIR)/%.h} ${PROGRAM}
|
||||
|
||||
${PROGRAM}: ${LIBS} ${OBJS}
|
||||
${CC} -o ${PROGRAM} ${OBJS} ${LIBS}
|
||||
|
||||
install: ${PROGRAM}
|
||||
install -s ${PROGRAM} ${DESTDIR}/usr/bin/${PROGRAM}
|
||||
|
||||
clean: masterclean
|
||||
|
||||
tags:
|
||||
ctags $(MID_SRCS)
|
||||
|
||||
lint : masterlint
|
||||
|
||||
|
||||
310
lang/ld/sparc/incl.c
Normal file
310
lang/ld/sparc/incl.c
Normal file
@@ -0,0 +1,310 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)incl.c 1.1 94/10/31";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "a.out.h"
|
||||
#include <stab.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* Info about each include file
|
||||
*/
|
||||
struct incl {
|
||||
char *name; /* Name of header file */
|
||||
int nstatic; /* # of statics in the file */
|
||||
int nsymbols; /* # of symbols in header file */
|
||||
int checksum; /* Checksum for header file */
|
||||
int ord; /* Ordinal # of header file */
|
||||
int exclude; /* Flag: include/exclude syms */
|
||||
struct incl *next; /* Linked Hash list */
|
||||
};
|
||||
|
||||
#define NINCL_STACK 10 /* Size of the include stack */
|
||||
#define INCL_HASH 64 /* Size of header file hash table */
|
||||
|
||||
static struct incl **incl_stack; /* Include file stack */
|
||||
static int stack_size; /* Size of incl_stack */
|
||||
static struct incl **stkp; /* Stack pointer */
|
||||
static struct incl *incl_table[INCL_HASH]; /* Table saved for pass 2 */
|
||||
static struct incl *cur_incl; /* Current header file */
|
||||
static int obj_ord; /* Saved value of header_num */
|
||||
|
||||
extern int ssize; /* Size of symbol section */
|
||||
extern int header_num; /* Ordinal value of next header file */
|
||||
|
||||
struct incl *find_ord();
|
||||
char *strcpy();
|
||||
char *malloc();
|
||||
char *realloc();
|
||||
|
||||
/*
|
||||
* Allocate the intial include file stack.
|
||||
* The stack will grow if necessary.
|
||||
*/
|
||||
alloc_inclstack()
|
||||
{
|
||||
if ((incl_stack = (struct incl **) malloc(NINCL_STACK*sizeof(struct incl *))) == 0)
|
||||
error(1, "ran out of memory (alloc_inclstack)");
|
||||
stkp = incl_stack;
|
||||
stack_size = NINCL_STACK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Beginning a new object file. Remember the ordinal number
|
||||
* of the next header file in case this object file is not
|
||||
* used and everything needs to be ripped out and thrown away.
|
||||
*/
|
||||
new_obj1()
|
||||
{
|
||||
obj_ord = header_num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter a new include file.
|
||||
* Stack the current one, if it is active.
|
||||
* Allocate a structure and initialize it.
|
||||
*/
|
||||
start_incl1(sym, ord)
|
||||
struct nlist *sym;
|
||||
int ord;
|
||||
{
|
||||
char *name;
|
||||
int n;
|
||||
register char *namespace;
|
||||
|
||||
if (stkp > &incl_stack[stack_size]) {
|
||||
n = stkp - incl_stack;
|
||||
stack_size += NINCL_STACK;
|
||||
if ((incl_stack = (struct incl **) realloc(incl_stack,
|
||||
stack_size * sizeof(struct incl *))) == 0)
|
||||
error(1, "ran out of memory (start_incl1)");
|
||||
stkp = &incl_stack[n];
|
||||
}
|
||||
*stkp++ = cur_incl;
|
||||
name = sym->n_un.n_name;
|
||||
if ((cur_incl = (struct incl *) malloc(sizeof(struct incl))) == 0)
|
||||
error(1, "ran out of memory (start_incl1)");
|
||||
if ((namespace = malloc(strlen(name) + 1)) == 0)
|
||||
error(1, "ran out of memory (start_incl1)");
|
||||
cur_incl->name = strcpy(namespace, name);
|
||||
cur_incl->nstatic = 0;
|
||||
cur_incl->nsymbols = 0;
|
||||
cur_incl->checksum = 0;
|
||||
cur_incl->ord = ord;
|
||||
cur_incl->exclude = 0;
|
||||
cur_incl->next = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found the end of an include file.
|
||||
* Hash on its name and enter it into the
|
||||
* has table. Pass two will find it by
|
||||
* its name and ordinal number.
|
||||
* Also, pop one off of the stack.
|
||||
*/
|
||||
end_incl1()
|
||||
{
|
||||
int h;
|
||||
|
||||
h = hash(cur_incl->name);
|
||||
cur_incl->next = incl_table[h];
|
||||
incl_table[h] = cur_incl;
|
||||
cur_incl = *--stkp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found a dbx symbol in pass one.
|
||||
* If there is an active header file, include the info.
|
||||
* The checksum is the summation of all the letters, underscores,
|
||||
* and equals signs in the n_name field of the nlist
|
||||
* structure.
|
||||
*
|
||||
* The equals signs are counted because they are present whenever
|
||||
* new type is defined. We want to insure that each inclusion of
|
||||
* a header file defines the same number of types.
|
||||
*/
|
||||
stab1(sym)
|
||||
struct nlist *sym;
|
||||
{
|
||||
register char *cp;
|
||||
|
||||
if (cur_incl == NULL) {
|
||||
return;
|
||||
}
|
||||
cur_incl->nsymbols++;
|
||||
if (sym->n_type == N_STSYM || sym->n_type == N_LCSYM || sym->n_type == N_EXCL ) {
|
||||
cur_incl->nstatic++;
|
||||
}
|
||||
cp = sym->n_un.n_name;
|
||||
if (sym->n_type != N_EXCL && cp != NULL) {
|
||||
while (*cp != '\0') {
|
||||
if (isalpha(*cp) || *cp == '_' || *cp == '=') {
|
||||
cur_incl->checksum += *cp;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* An object file was not used.
|
||||
* Must remove any header files it had from the hash table.
|
||||
*/
|
||||
incl_free()
|
||||
{
|
||||
struct incl *ip;
|
||||
struct incl *next;
|
||||
struct incl **ipp;
|
||||
struct incl **bpatch;
|
||||
int nhdrs;
|
||||
int removed;
|
||||
|
||||
if (obj_ord == header_num) {
|
||||
return;
|
||||
}
|
||||
removed = 0;
|
||||
nhdrs = header_num - obj_ord;
|
||||
for (ipp = incl_table; ipp < &incl_table[INCL_HASH]; ipp++) {
|
||||
bpatch = ipp;
|
||||
for (ip = *ipp; ip != NULL; ip = next) {
|
||||
next = ip->next;
|
||||
if (ip->ord >= obj_ord) {
|
||||
*bpatch = ip->next;
|
||||
free((char *) ip);
|
||||
removed++;
|
||||
} else {
|
||||
bpatch = &ip->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removed != nhdrs) {
|
||||
fprintf(stderr, "incl_free removed %d nhdrs %d\n",
|
||||
removed, nhdrs);
|
||||
}
|
||||
header_num = obj_ord;
|
||||
}
|
||||
|
||||
/*
|
||||
* See what header files can be excluded from the final output.
|
||||
* The important goal here is to determine how many symbols
|
||||
* will be excluded so that "ssize" can be adjusted. "Ssize"
|
||||
* determines the value that will be stored into the a_syms
|
||||
* field of the a.out header and also determines where the
|
||||
* string table will begin.
|
||||
*/
|
||||
merge_headers()
|
||||
{
|
||||
register struct incl *ip;
|
||||
register struct incl **ipp;
|
||||
|
||||
for (ipp = incl_table; ipp < &incl_table[INCL_HASH]; ipp++) {
|
||||
for (ip = *ipp; ip != NULL; ip = ip->next) {
|
||||
ip->exclude = find_prev(ip);
|
||||
if (ip->exclude) {
|
||||
ssize -= (ip->nsymbols + 1) *
|
||||
sizeof(struct nlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
cur_incl = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Found the beginning of a header file in pass2.
|
||||
* Find the struct for the header file created in pass1.
|
||||
* See if there is an identical struct for a header file
|
||||
* with a lower ordinal value. If so, the symbols in this
|
||||
* file can be discarded.
|
||||
*/
|
||||
start_incl2(sym, ord)
|
||||
struct nlist *sym;
|
||||
int ord;
|
||||
{
|
||||
struct incl *ip;
|
||||
int r;
|
||||
|
||||
if (stkp > &incl_stack[NINCL_STACK]) {
|
||||
error(1, "include stack too deep");
|
||||
}
|
||||
*stkp++ = cur_incl;
|
||||
cur_incl = find_ord(sym, ord);
|
||||
sym->n_value = cur_incl->checksum;
|
||||
if (cur_incl->exclude) {
|
||||
sym->n_type = N_EXCL;
|
||||
}
|
||||
return(cur_incl->exclude);
|
||||
}
|
||||
|
||||
end_incl2()
|
||||
{
|
||||
cur_incl = *--stkp;
|
||||
return(cur_incl != NULL && cur_incl->exclude);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a header file with a given ordinal number.
|
||||
*/
|
||||
struct incl *
|
||||
find_ord(sym, ord)
|
||||
struct nlist *sym;
|
||||
int ord;
|
||||
{
|
||||
register struct incl *ip;
|
||||
int h;
|
||||
|
||||
h = hash(sym->n_un.n_name);
|
||||
for (ip = incl_table[h]; ip != NULL; ip = ip->next) {
|
||||
if (ip->ord == ord) {
|
||||
return(ip);
|
||||
}
|
||||
}
|
||||
error(1, "no include table entry for header file '%s'",
|
||||
sym->n_un.n_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find an identical header file with a lower ordinal number.
|
||||
*/
|
||||
find_prev(incl)
|
||||
register struct incl *incl;
|
||||
{
|
||||
register struct incl *ip;
|
||||
int h;
|
||||
|
||||
if (incl->nstatic > 0) {
|
||||
return(0);
|
||||
}
|
||||
h = hash(incl->name);
|
||||
for (ip = incl_table[h]; ip != NULL; ip = ip->next) {
|
||||
if (ip->nsymbols == incl->nsymbols &&
|
||||
ip->nstatic == 0 &&
|
||||
ip->checksum == incl->checksum &&
|
||||
ip->ord < incl->ord &&
|
||||
strcmp(incl->name, ip->name) == 0) {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute a hash from a string.
|
||||
* Simply sum the characters and mod.
|
||||
*/
|
||||
hash(str)
|
||||
char *str;
|
||||
{
|
||||
register int sum;
|
||||
register char *cp;
|
||||
|
||||
sum = 0;
|
||||
for (cp = str; *cp; cp++) {
|
||||
sum += *cp;
|
||||
}
|
||||
return(sum % INCL_HASH);
|
||||
}
|
||||
114
lang/ld/verscmp.c
Normal file
114
lang/ld/verscmp.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/* @(#)verscmp.c 1.1 94/10/31 */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#define SKIP_DOT(str) ((*str == '.') ? ++str : str)
|
||||
#define EMPTY(str) ((str == NULL) || (*str == '\0'))
|
||||
#define NULL 0
|
||||
#define isdigit(c) (((c) >= '0') && ((c) <= '9') ? 1:0)
|
||||
|
||||
int stol();
|
||||
|
||||
/*
|
||||
* Test whether the string is of digit[.digit]* format
|
||||
*/
|
||||
rest_ok(str)
|
||||
char *str; /* input string */
|
||||
{
|
||||
int dummy; /* integer place holder */
|
||||
int legal = 1; /* return flag */
|
||||
|
||||
while (!EMPTY(str)) {
|
||||
if (!stol(str, '.', &str, &dummy)) {
|
||||
legal = 0;
|
||||
break;
|
||||
};
|
||||
if (EMPTY(str))
|
||||
break;
|
||||
else SKIP_DOT(str);
|
||||
};
|
||||
return(legal);
|
||||
};
|
||||
|
||||
/*
|
||||
* Compare 2 strings and test whether they are of the form digit[.digit]*.
|
||||
* It will return -1, 0, or 1 depending on whether c1p is less, equal or
|
||||
* greater than c2p
|
||||
*/
|
||||
verscmp(c1p, c2p)
|
||||
char *c1p; /* input string */
|
||||
char *c2p; /* input string */
|
||||
{
|
||||
char *l_c1p = c1p; /* working copy of c1p */
|
||||
char *l_c2p = c2p; /* working copy of c2p */
|
||||
int l_c1p_ok = 0; /* is c1p a legal string */
|
||||
int c2p_dig = 0; /* int that c1p currently represents */
|
||||
int c1p_dig = 0; /* int that c2p currently represents */
|
||||
int result = 0;
|
||||
|
||||
while ((l_c1p_ok = stol(l_c1p,'.', &l_c1p, &c1p_dig)) &&
|
||||
stol(l_c2p,'.', &l_c2p, &c2p_dig) && (c2p_dig == c1p_dig)) {
|
||||
if (EMPTY(l_c1p) && EMPTY(l_c2p))
|
||||
return(0);
|
||||
else if (EMPTY(l_c1p) && !EMPTY(l_c2p) && rest_ok(SKIP_DOT(l_c2p)))
|
||||
return(-1);
|
||||
else if (EMPTY(l_c2p) && !EMPTY(l_c1p) && rest_ok(SKIP_DOT(l_c1p)))
|
||||
return(1);
|
||||
l_c1p++; l_c2p++;
|
||||
};
|
||||
if (!l_c1p_ok)
|
||||
return(-1);
|
||||
else if (c1p_dig < c2p_dig)
|
||||
return(-1);
|
||||
else if ((c1p_dig > c2p_dig) && rest_ok(SKIP_DOT(l_c1p)))
|
||||
return(1);
|
||||
else return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* "stol" attempts to interpret a collection of characters between delimiters
|
||||
* as a decimal digit. It stops interpreting when it reaches a delimiter or
|
||||
* when character does not represent a digit. In the first case it returns
|
||||
* success and the latter failure.
|
||||
*/
|
||||
int
|
||||
stol(cp, delimit, ptr, i)
|
||||
char *cp; /* ptr to input string */
|
||||
char delimit; /* delimiter */
|
||||
char **ptr; /* left pointing to next del. or illegal
|
||||
character */
|
||||
int *i; /* digit that the string represents */
|
||||
{
|
||||
int c = 0; /* current char */
|
||||
int n = 0; /* working copy of i */
|
||||
int neg = 0; /* is number negative */
|
||||
|
||||
if (ptr != (char **)0)
|
||||
*ptr = cp; /* in case no number is formed */
|
||||
|
||||
if (EMPTY(cp))
|
||||
return(0);
|
||||
|
||||
if (!isdigit(c = *cp) && (c == '-')) {
|
||||
neg++;
|
||||
c = *++cp;
|
||||
};
|
||||
if (EMPTY(cp) || !isdigit(c))
|
||||
return(0);
|
||||
|
||||
while (isdigit(c = *cp) && (*cp++ != '\0')) {
|
||||
n *= 10;
|
||||
n += c - '0';
|
||||
};
|
||||
if (ptr != (char **)0)
|
||||
*ptr = cp;
|
||||
|
||||
if ((*cp == '\0') || (*cp == delimit)) {
|
||||
*i = neg ? -n : n;
|
||||
return (1);
|
||||
};
|
||||
return (0);
|
||||
}
|
||||
101
lang/ld/vroot.c
Normal file
101
lang/ld/vroot.c
Normal file
@@ -0,0 +1,101 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)vroot.c 1.1 94/10/31";
|
||||
#endif not lint
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
static char *get_next_name();
|
||||
|
||||
extern char *getenv();
|
||||
extern char *malloc();
|
||||
|
||||
#define NDEFDIRS 3 /* number of default directories in dirs[] */
|
||||
|
||||
extern char *dirs[];
|
||||
extern int ndir;
|
||||
extern char *defaults_dir[];
|
||||
|
||||
/*
|
||||
* support virtual root for cross compiling
|
||||
*/
|
||||
dovroot()
|
||||
{
|
||||
char *vroot = getenv("VIRTUAL_ROOT");
|
||||
char *dn;
|
||||
int i;
|
||||
|
||||
char *vroot_copy;
|
||||
|
||||
if (vroot) {
|
||||
vroot_copy = malloc(strlen(vroot) + 1);
|
||||
strcpy(vroot_copy, vroot);
|
||||
while (dn = get_next_name(&vroot_copy))
|
||||
if (strcmp(dn, "/"))
|
||||
newvrt(dn);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
newvrt(dn)
|
||||
char *dn;
|
||||
{
|
||||
char *cp;
|
||||
int len = strlen(dn);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NDEFDIRS; i++) {
|
||||
dirs[ndir++] = cp = malloc(len + strlen(defaults_dir[i]) + 1);
|
||||
strcpy(cp, dn);
|
||||
strcat(cp, defaults_dir[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract list of directories needed from colon separated string.
|
||||
*/
|
||||
static char *
|
||||
get_next_name(list)
|
||||
char **list;
|
||||
{
|
||||
char *lp = *list;
|
||||
char *cp = *list;;
|
||||
|
||||
if (lp != NULL && *lp != '\0') {
|
||||
while (*lp != '\0' && *lp != ':')
|
||||
lp++;
|
||||
if (*lp == ':') {
|
||||
*lp = '\0';
|
||||
*list = lp + 1;
|
||||
} else
|
||||
*list = NULL;
|
||||
} else
|
||||
*list = NULL;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
char *
|
||||
stripvroot(path)
|
||||
char *path;
|
||||
{
|
||||
char *vroot = getenv("VIRTUAL_ROOT");
|
||||
char *dn;
|
||||
int i;
|
||||
|
||||
char *vroot_copy;
|
||||
static char buf[MAXPATHLEN+1];
|
||||
|
||||
if (vroot) {
|
||||
vroot_copy = malloc(strlen(vroot) + 1);
|
||||
strcpy(vroot_copy, vroot);
|
||||
while (dn = get_next_name(&vroot_copy)) {
|
||||
if(((i = strlen(dn)) != 0) && (strcmp(dn, "/") != 0))
|
||||
if (strncmp(dn, path, i) == 0) {
|
||||
(void)strcpy(buf, &path[i]);
|
||||
return(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(path);
|
||||
}
|
||||
Reference in New Issue
Block a user