File:  [Research Unix] / researchv9 / jerq / sgs / ld / special2.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 3 months ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

static char ID[] = "@(#) special2.c: 1.12 9/23/83";

#include <stdio.h>

#include "system.h"
#include "aouthdr.h"
#include "structs.h"
#include "ldfcn.h"
#include "tv.h"
#include "slotvec.h"
#include "reloc.h"
#include "extrns.h"
#include "sgsmacros.h"
#include "list.h"
#include "sgs.h"

void
adjneed(need, osp, sap)

ADDRESS	*need;
OUTSECT	*osp;
ANODE	*sap;
{
	/*
	 * adjust amount of memory allocated for a particular
	 * section;  special processing step now used only
	 * for DMERT with TRVEC
	 */
}

void
undefine()
{
	/*
	 * for m32 version of ld01.c, the symbol "_start" does not
	 * need to be undefined
	 */
}

void
dfltsec()
{
/*
 * For the m32, the default action of nm32ld is to generate two m32
 * segments: one for the text and the other for the data (both
 * .data and .bss)
 */

	ADDRESS lint = 0x80000;
	ADDRESS *lptr = &lint;
	ACTITEM *aiptr, *grptr;

/*
 * If any SECTIONS directives have been input, they take priority,
 * and no default action is taken
 */

#if ONEPROC
	if( bldoutsc.head )
#else
	if( bldcnt)
#endif
		return;

#if PAGING
	bond_t_d = 1;	/* setting bond_t_d will tell pboslist to bind text
				and data to the needed addresses */
#endif

/*
 * Generate a series of action itmes, as if the following had been
 * input to m32ld:
 *
 *	SECTIONS {
 *		.text : {}
 *		GROUP ALIGN(0x80000) : {
 *					.data : {}
 *					.bss  : {}
 *		 }
 *
 *
 * Steps:
 *	1. Define background variables
 *	2. Process the .text definition
 *	3. Process the GROUP definition
 *	4. Process the .data definition
 *	5. Process the .bss definition
 *
 *
 * The logic used was obtained by simulating the action of the parser.
 */

	memorg = 0x80800000L;
	curfilnm = "*m32.default.file*";

	lineno = 2;
	aiptr = dfnscngrp( AIDFNSCN, NULL, NULL, NULL );
	aiptr->dfnscn.aisctype = STYP_REG;
	copy( aiptr->dfnscn.ainame, _TEXT, 8 );
	aiptr->dfnscn.aifill = 0;
	aiptr->dfnscn.aifillfg = 0;
	listadd( l_AI, &bldoutsc, aiptr );

	lineno = 3;
	grptr = dfnscngrp( AIDFNGRP, NULL, lptr, NULL );
	copy( grptr->dfnscn.ainame, "*group*", 7);

	lineno = 4;
	aiptr = dfnscngrp( AIDFNSCN, NULL, NULL, NULL );
	aiptr->dfnscn.aisctype = STYP_REG;
	copy( aiptr->dfnscn.ainame, _DATA, 8 );
	aiptr->dfnscn.aifill = 0;
	aiptr->dfnscn.aifillfg = 0;
	listadd( l_AI, &grptr->dfnscn.sectspec, aiptr );

	lineno = 5;
	aiptr = dfnscngrp( AIDFNSCN, NULL, NULL, NULL );
	aiptr->dfnscn.aisctype = STYP_REG;
	copy( aiptr->dfnscn.ainame, _BSS, 8 );
	aiptr->dfnscn.aifill = 0;
	aiptr->dfnscn.aifillfg = 0;
	listadd( l_AI, &grptr->dfnscn.sectspec, aiptr );
	 
	listadd( l_AI, &bldoutsc, grptr );

	return;
}

void
procspecobj(fdes, ap)
LDFILE *fdes;
ACTITEM *ap;
{
	/*
	 * No more additional files to check 
	 */

	lderror(1, ap->ldlbry.aiinlnno, ap->ldlbry.aiinflnm,
		"file %s is of unknown type: magic number = %06.1x",
		ap->ldlbry.aifilnam, TYPE(fdes));
}

void
adjsize(osp)
OUTSECT *osp;
{
	/*
	 * No special cases, no need to adjust size of output section
	 */
}

void
adjaout(aout)
AOUTHDR *aout;
{
	/*
	 * Indicate, via the MAGIC NUMBER, when the data segment starts
	 * on a m32 segment (512K bytes) boundary
	 */

	if( (aout->data_start & 0x7ffffL) == 0 )
		aout->magic = (short) AOUT2MAGIC;
}

void
relocate(ifd, rfd, infl, isp, osp, fdes, rdes, paddiff, relocfg, buf)
LDFILE *ifd, *rfd;
INFILE *infl;
INSECT *isp;
OUTSECT *osp;
FILE *fdes, *rdes;
long *paddiff;
register int *relocfg;
char *buf;
{
	/*
	 * Process the section
	 */

	int numbytes;
	long highaddr, vaddiff;
	register long rdif, ndx;
	union {
		long	 l;
		unsigned short u[2];
		short	 i[2];
		char	 c[4];
		} value;
	RELOC rentry;
	register SLOTVEC *svp;

#if RBO
	/*
	 * for reverse byte ordering, two longs must be read in at a time,
	 * as the field may span a word boundary, and the bytes will no longer
	 * be contiguous.
	 */
	union {
		long	l[2];
		char	c[8];
		} rbobuf;
	short buffered, pos, i;
	long nextbnd;
#endif

	highaddr = isp->ishdr.s_vaddr + isp->ishdr.s_size;
	vaddiff = isp->isnewvad - isp->ishdr.s_vaddr;
	*paddiff = isp->isnewpad - isp->ishdr.s_paddr;
#if RBO
	buffered = 0;
#endif

	for( ndx = isp->ishdr.s_vaddr; ndx < highaddr; ) {

		/*
		 * Read a relocation entry, if any left, and
		 * determine the size of the relocation field, in bytes
		 */
		if( *relocfg ) {
			if (fread(&rentry, RELSZ, 1, IOPTR(rfd)) != 1)
					lderror(2,0,NULL,"fail to read the reloc entries of section %.8s of %s",
				isp->ishdr.s_name,infl->flname);
			(*relocfg)--;
			switch (rentry.r_type) {

			case R_ABS:
				/*
				 * No relocation, so skip to the
				 * next entry
				 */
				if( rflag )
				    if( (svp = svread(rentry.r_symndx)) == NULL ) {
					lderror(1,0,NULL, "reloc entry (%10.1lx, %ld %d) found for non-relocatable symbol, in section %.8s of file %s",
						rentry, isp->ishdr.s_name, infl->flname);
					goto nextentry;
					}
				    else
					goto nullentry;
				goto nextentry;



			case R_DIR32:
			case R_DIR32S:
				break;


			default:
				lderror(2,0,NULL,
					"Illegal relocation type %d found in section %.8s in file %s",
					rentry.r_type, isp->ishdr.s_name, infl->flname);
			}
			}
		/*
		 * There are no (more) relocation entries, so 
		 * copy the rest of the section
		 */
		else {
#if RBO
			/*
			 * write out the contents of the reverse byte order
			 * buffer if necessary
			 */
			if (buffered) {
				buffered = 0;
				fwrite( &rbobuf.l[1], sizeof(long), 1, fdes);
				ndx += 4;
			}
#endif
			while( (rdif = highaddr - ndx) > 0 ) {
				rdif = min(BUFSIZ, rdif);
				if (FREAD(buf,(int) rdif,1,ifd) != 1 ||
				    fwrite(buf,(int) rdif,1,fdes) != 1)
					lderror(2,0,NULL,"fail to copy the rest of section %.8s of file %s",
					isp->ishdr.s_name,infl->flname);
				ndx += rdif;
				}
			continue;
			}

		/*
		 * Copy bytes that need no relocation
		 */
#if RBO
		pos = rentry.r_vaddr % 4;
		nextbnd = rentry.r_vaddr - pos;
		if ( ((nextbnd - ndx) > 0) && buffered) {
			buffered = 0;
			fwrite( &rbobuf.l[1], sizeof(long), 1, fdes );
			ndx += 4;
		}

		while ((rdif = nextbnd - ndx) > 0) {
#else
		while( (rdif = rentry.r_vaddr - ndx) > 0 ) {
#endif
			rdif = min(BUFSIZ, rdif);
			if (FREAD(buf,(int) rdif,1,ifd) != 1 ||
			    fwrite(buf,(int) rdif,1,fdes) != 1)
				lderror(2,0,NULL,"fail to copy the bytes that need no reloc of section %.8s of file %s",
				isp->ishdr.s_name,infl->flname);
			ndx += rdif;
			}

		if( rdif < 0 ) {
			lderror(2,0,NULL, "Reloc entries out of order in section %.8s of file %s",
				isp->ishdr.s_name, infl->flname);
			}

		if( (svp = svread(rentry.r_symndx)) == NULL ) {
			lderror(1,0,NULL, "No reloc entry found for symbol: index %ld, section %.8s, file %s",
				rentry.r_symndx, isp->ishdr.s_name, infl->flname);
				goto nextentry;
				}

		rdif = svp->svnvaddr - svp->svovaddr;

		/*
		 * Special processing for COPY sections:
		 *  do not touch the raw data (no relocation)
		 *  but process relocation entries and lineno
		 *  entries as usual
		 */

		if ( osp->oshdr.s_flags & STYP_COPY )
			goto nullentry;

		switch( rentry.r_type ) {

		case R_DIR32:
			if (FREAD( &value.l, sizeof(long), 1, ifd) != 1)
				lderror( 2,0,NULL, "fail to read the field to be relocated in section %.8s, file %s",
					isp->ishdr.s_name, infl->flname);
			value.l = swapb4( swapb4( value.l, 0 ) + rdif, 0);
			fwrite( &value.l, sizeof(long), 1, fdes );
			ndx += 4;
			break;

		case R_DIR32S:
#if RBO
			if ( !buffered )
				if (FREAD( &rbobuf.l[1], sizeof(long), 1, ifd ) != 1)
					lderror( 2,0,NULL, "fail to read the field to be relocated in section %.8s, file %s",
						isp->ishdr.s_name, infl->flname);
			if (FREAD( &rbobuf.l[0], sizeof(long), 1, ifd ) != 1)
				lderror( 2,0,NULL, "fail to read the field to be relocated in section %.8s, file %s",
					isp->ishdr.s_name, infl->flname);
			for ( i = 0; i <= 3; i ++ )
				value.c[i] = rbobuf.c[7 - (pos + i)];
#else
			if (FREAD( &value.l, sizeof(long), 1, ifd) != 1)
				lderror( 2,0,NULL, "fail to read the field to be relocated in section %.8s, file %s",
					isp->ishdr.s_name, infl->flname);
#endif

			value.l = swapb4( swapb4(value.l, 1) + rdif, 1 );

#if RBO
			for ( i = 0; i <= 3; i++ )
				rbobuf.c[7 - (pos + i)] = value.c[i];
			fwrite( &rbobuf.l[1], sizeof(long), 1, fdes );
			rbobuf.l[1] = rbobuf.l[0];
			buffered = 1;
#else
			fwrite( &value.l, sizeof(long), 1, fdes );
#endif
			ndx += 4;
			break;
		}

	nullentry:	/* 
		 	 * Preserve relocation entries
			 */
		if( rflag ) {
			rentry.r_vaddr += vaddiff;
			rentry.r_symndx = svp->svnewndx;
			fwrite(&rentry, RELSZ, 1, rdes);
			}

	nextentry:	;
	}

}

long
swapb4(val, type)
long val;
int type;
{
	register long result;


/*
 * Reorder the bytes of a long, converting to/from UNIX/M32 format
 *
 *	val	: w x y z
 *
 *	11/70	:0:	xwzy
 *		:1:	yzwx
 *	vax	:0:	zyxw
 *		:1:	no change
 *
 *	other	:0:	no change
 *		:1:	zyxw
 */

	if( type ) {
#if AR16WR || AR32W
		result = (val >> 16) & 0x0000FFFFL;
		result |= (val << 16) & 0xFFFF0000L;
#if AR32W
		val = result;
		result = (val >> 8) & 0x00FF00FFL;
		result |= (val << 8) & 0xFF00FF00L;
#endif
#else
		result = val;
#endif
		}
	else {
#if AR16WR || AR32WR
		result = (val >> 8) & 0x00FF00FFL;
		result |= (val << 8) & 0xFF00FF00L;
#if AR32WR
		val = result;
		result = (val >> 16) & 0x0000FFFFL;
		result |=(val << 16) & 0xFFFF0000L;
#endif
#else
		result = val;
#endif
		}

	return( result );

}

void
procext(tvndx, secnum, sltval1, sltval2, ovaddr, nvaddr, gsp, sm)
int *tvndx, secnum;
long *sltval1, *sltval2, *ovaddr, *nvaddr;
register SYMTAB *gsp;
register SYMENT *sm;
{
			if( secnum > 0 ) {
				*sltval1 = ovaddr[secnum];
				*sltval2 = nvaddr[secnum];
				}
			else  {
				*sltval1 = sm->n_value;
				*sltval2 = gsp->smnewvirt;
				}
}

void
proclocstat(sm, infd, segment, newscnum, tvndx, ovaddr, nvaddr, opaddr, npaddr, ndx, sltval1, sltval2, count)
register SYMENT *sm;
LDFILE *infd;
int *segment, *newscnum, *tvndx;
long *ovaddr, *nvaddr, *opaddr, *npaddr, ndx, *sltval1, *sltval2, count;
{

			*sltval1 = ovaddr[sm->n_scnum];
			*sltval2 = nvaddr[sm->n_scnum];
			svcreate(count, *sltval1, *sltval2, ndx, newscnum[sm->n_scnum],
				0);

}

void
setslot(pglob, psect, outslot)
SYMTAB *pglob;
SCNHDR *psect;
TVENTRY *outslot;
{
	/*
	 * no user defined transfer vector slot in tv.c for m32
	 */
}

void
slotassign(tvent, pglob)
TVENTRY *tvent;
SYMTAB *pglob;
{
	long	paddr;

	paddr = pglob->smnewval;

	/*
	 * do not need to assign value to transfer vector
	 * entry for global symbol in tv.c for m32
	 */
}

void
settventry(tvent, psym)
TVENTRY *tvent;
struct syment *psym;
{
	/*
	 * no values to assign to transfer vector entry for local
	 * symbol in tv.c for m32
	 */
}

void
filltvassign(psym)
SYMTAB *psym;
{
	/*
	 * no fill values to assign for transfer vector in tv.c for m32
	 */
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.