/* ---------------------------------------------------------------------- */ /* Copyright (C) 1991 by Natrlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ #define LINKER 1 #include "defines.h" #include #include OSBIND #include "nasm.h" #include "debug.h" #include "ldebug.h" #include NMALLOC_H #include "object.h" #include "process.h" #include "code.h" #if ! VERSION extern char x1[], x2[], x3[], x4[], x5[], x6[]; #endif byte huge *pb; e_dropped huge *pe; s_dropped huge *ps; linksymbol huge *py; i_dropped huge *pi; r_dropped huge *pr; f_dropped huge *pf; lword magic, bytes, sbytes, ibytes, rbytes, ebytes, ybytes, fbytes; lword ysize; /* hack for backwards compatibility */ static obj_h l; word version, alignment; #if ! VERSION static word revision; #endif static void fix_version(), fix_sizes(); #if ! DISASM extern int relocatable, bootable, verbose, pageflag; extern word diff, head_off, endpc, origin, mv_offset; extern byte huge *ptohead; #endif char trc_loss[] = "File is truncated"; #if VERSION # define the_10seek( x, y) #else void the_10seek( fd, x) char *x; { unsigned long foo; static char chkbuf[11]; if( (foo = Fread( fd, 10L, chkbuf)) < 10L) { fprintf( stderr, "FOO = %ld\n", foo); ngferror( foo, trc_loss); } if( strcmp( chkbuf, x)) nferror("Not a good object file"); } #endif void do_load( fd) { long foo; ENTER("do_load"); INTEGRITY_CHECK(); if( Fread( fd, sizeof( obj_h), &l) != sizeof( obj_h)) nferror("File is too short to be an object file"); IMESS("Sizeof( obj_h) = %ld", sizeof( obj_h), 4); magic = lbeek( &l.magic); version = dbeek( &l.version); #if ! VERSION revision = dbeek( &l.revision); #endif alignment= dbeek( &l.alignment); bytes = (lword) dbeek( &l.codesize); sbytes = lbeek( &l.segsize); ibytes = lbeek( &l.immsize); rbytes = lbeek( &l.relsize); ebytes = lbeek( &l.expsize); ybytes = ysize = lbeek( &l.symsize); fbytes = lbeek( &l.fixsize); if( magic != OBJMAGIC) nferror("This is not an object file"); if( version < (word) OBJ_READ_COMP) nferror("Object file was created with an obsolete version"); if( version > DVERSION) nferror("I am too oldfashioned to understand this object format"); #if ! VERSION if( revision != ASMREVISION) nferror("Object was created by a different revision"); #endif if( version != DVERSION) fix_sizes( version); #if ! DISASM if( __p - __program + bytes >= MAXMODULE) nferror("Objects overflow the program buffer"); #endif MESS("[ 0] --- Fread ---"); pb = nmalloc( bytes); if( (foo = Fread( fd, bytes, pb)) != bytes) ngferror( foo, trc_loss); MESS("[ 1] --- Fseek ---"); the_10seek( fd, x1); INTEGRITY_CHECK(); MESS("[ 2] --- Sbytes ---"); if( sbytes) { ps = nmalloc( sbytes); if( (foo = Fread( fd, sbytes, ps)) != sbytes) ngferror( foo, trc_loss); } MESS("[ 3] --- Fseek ---"); INTEGRITY_CHECK(); the_10seek( fd, x2); MESS("[ 4] --- Ibytes ---"); if( ibytes) { pi = nmalloc( ibytes); if( (foo = Fread( fd, ibytes, pi)) != ibytes) ngferror( foo, trc_loss); } MESS("[ 5] --- Fseek ---"); INTEGRITY_CHECK(); the_10seek( fd, x3); MESS("[ 6] --- Rbytes ---"); if( rbytes) { pr = nmalloc( rbytes); if( (foo = Fread( fd, rbytes, pr)) != rbytes) ngferror( foo, trc_loss); } MESS("[ 7] --- Fseek ---"); INTEGRITY_CHECK(); the_10seek( fd, x4); MESS("[ 8] --- Ebytes ---"); if( ebytes) { pe = nmalloc( ebytes); if( (foo = Fread( fd, ebytes, pe)) != ebytes) ngferror( foo, trc_loss); } MESS("[ 9] --- Fseek ---"); the_10seek( fd, x5); MESS("[10] --- Ybytes ---"); if( ybytes) { py = nmalloc( ysize); if( (foo = Fread( fd, ybytes, py)) != ybytes) ngferror( foo, trc_loss); } the_10seek( fd, x6); INTEGRITY_CHECK(); MESS("[11] --- Fbytes ---"); if( fbytes) { pf = nmalloc( fbytes); if( (foo = Fread( fd, fbytes, pf)) != fbytes) ngferror( foo, trc_loss); } ADD_WATCH( &pb, sizeof( char *), "pb"); ADD_WATCH( &pe, sizeof( char *), "pe"); ADD_WATCH( &ps, sizeof( char *), "ps"); ADD_WATCH( &py, sizeof( char *), "py"); ADD_WATCH( &pi, sizeof( char *), "pi"); ADD_WATCH( &pr, sizeof( char *), "pr"); ADD_WATCH( &pf, sizeof( char *), "pf"); if( version != DVERSION) { fix_version( version); /* fix up old style object files */ } ybytes /= sizeof( linksymbol); ebytes /= sizeof( e_dropped); sbytes /= sizeof( s_dropped); ibytes /= sizeof( i_dropped); rbytes /= sizeof( r_dropped); fbytes /= sizeof( f_dropped); INTEGRITY_CHECK(); # if BIGENDIAN flipstructs(); # endif INTEGRITY_CHECK(); #if ! DISASM { word oldpc, val = 0; diff = __pc - DEFORG + mv_offset; oldpc = __pc; if( alignment) if( ! pageflag && relocatable) nferror("Conflict between -m option and requested alignment"); else if( val = __pc & alignment) { dpoke( ptohead, __pc - 1); __pc += (val = (~val & alignment) + 1); diff += val; if( bootable) { register int i; for( i = val; i; i--) *__p++ = 0; } else { dpoke( __p, __pc); _advance( 4); ptohead = __p - 2; } } endpc = DEFORG; INTEGRITY_CHECK(); seg_link(); INTEGRITY_CHECK(); MESS("code_reloc"); code_reloc(); INTEGRITY_CHECK(); MESS("imm_link"); imm_link(); INTEGRITY_CHECK(); MESS("ref_link"); ref_link(); INTEGRITY_CHECK(); MESS("exp_link"); exp_link(); INTEGRITY_CHECK(); MESS("sym_link"); sym_link(); INTEGRITY_CHECK(); MESS("sym2_link"); sym2_link(); INTEGRITY_CHECK(); DEL_WATCH( &pb); DEL_WATCH( &pe); DEL_WATCH( &ps); DEL_WATCH( &py); DEL_WATCH( &pi); DEL_WATCH( &pr); DEL_WATCH( &pf); wrapup(); if( verbose) if( alignment) printf("Start: $%04X Size:%5ld bytes Alignment loss: %3d bytes\n", oldpc, (lword) __pc - oldpc, val); else printf("Start: $%04X Size:%5ld bytes\n", oldpc, bytes); } #endif LEAVE(); } #if BIGENDIAN void flipstructs() { register word huge *q; register lword i; { register linksymbol huge *p; for( p = py, i = ybytes; i--; p++) { q = (word huge *) p; dswap( q); q++; dswap( q); q++; dswap( q); q += 2; lswap( q); POINTER_CHECK( q); } } { for( q = (word huge *) pe, i = ebytes; i--;) { dswap( q); q++; /* val */ dswap( q); q++; /* aux */ dswap( q); /* label */ q += 2; /* op & fix */ dswap( q); q++; /* t */ dswap( q); q++; /* l */ POINTER_CHECK( q); dswap( q); q++; /* r */ } } { for( q = (word huge *) pi, i = ibytes; i--;) { dswap( q); q++; /* block */ dswap( q); q++; /* type */ dswap( q); q++; /* offset*/ POINTER_CHECK( q); dswap( q); q++; /* val */ } } { for( q = (word huge *) ps, i = sbytes; i--;) { dswap( q); q++; /* type */ dswap( q); q++; /* index */ POINTER_CHECK( q); dswap( q); q++; /* size */ } } { for( q = (word huge *) pf, i = fbytes; i--;) { dswap( q); q++; /* poof */ dswap( q); q++; /* imm */ POINTER_CHECK( q); dswap( q); q++; /* index */ } } { register r_dropped huge *p; for( p = pr, i = rbytes; i--; p++) { dswap( p); POINTER_CHECK( p); } } } #endif #if VERSION == 2 || VERSION == 0 # define V1_SIGNIFICANT 8 # define V1_SIGNDIFF (SIGNIFICANT - V1_SIGNIFICANT) # define V1_L_DIFF (V1_SIGNDIFF + sizeof( word)) # define V1_SIZE (sizeof( linksymbol) - V1_L_DIFF) #endif static void fix_sizes( version) { switch( version) { #if VERSION == 2 || VERSION == 0 case 1 : ysize = ybytes / V1_SIZE * sizeof( linksymbol); break; #endif default : nferror( "Sorry, but that's an object file version I can't cope with"); } } static void fix_version( version) { switch( version) { #if VERSION == 2 || VERSION == 0 case 1 : { word huge *p; linksymbol huge *q; register word i, j; register char huge *dst; i = ybytes /= V1_SIZE; /* calc # symbols */ q = &py[ i]; /* move to end of */ p = (word huge *) ((char huge *) q - i * V1_L_DIFF); while( --q, i--) { for( dst = &q->name[ j = SIGNIFICANT]; j-- > V1_SIGNIFICANT;) *--dst = 0; # if PHILOSOPHICAL_PROBLEM do { p = (word huge *) ((char huge *) p - 1); *--dst = *p; } while( j--); p -= sizeof( lword) / sizeof( word); q->refs = (ref huge *) *(lword huge *)p; # else do *--dst = *--(char huge *)p; while( j--); q->refs = (ref huge *) *(--(lword huge *)p); # endif q->type = *--p; q->no = *--p; q->val = *--p; POINTER_CHECK( p); POINTER_CHECK( q); } ybytes *= sizeof( linksymbol); break; } #endif default : nferror( "Sorry, but that's an object file version I can't cope with"); } }