⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oxccl.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
	oxccl.c -- v1.430 architecture neutral format (anf) linker

	Copyright (c) 1995
	Norman D. Culver dba
	Oxbow Software
	1323 S.E. 17th Street #662
	Ft. Lauderdale, FL 33316
	(954) 463-4754
	ndc@icanect.net
	All rights reserved.

 * Redistribution and use in source and binary forms are permitted
 * provided that: (1) source distributions retain this entire copyright
 * notice and comment, and (2) distributions including binaries display
 * the following acknowledgement:  ``This product includes software
 * developed by Norman D. Culver dba Oxbow Software''
 * in the documentation or other materials provided with the distribution
 * and in all advertising materials mentioning features or use of this
 * software.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

*/
#define MAJOR_VERSION 1
#define MINOR_VERSION 433

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <setjmp.h>

#define NEED_FUNCTHUNK 1
#define NEED_ANFDEFS 1
#include "oxanf.h"

#define PROG oxccl
#define USING_FRAMEWORK 1
#define HOST_IS_LITTLE_ENDIAN 1
#define REALLY_NEED_OFFSETS 0

#define PRINTF printf
#define VFPRINTF(a,b) vfprintf(stderr,a,b)
#define PERROR prerror
#define PWARN prwarn
static void prerror(const char*, ...);
static void prwarn(const char*, ...);

#define FILEWRITE(buf, cnt)\
{if(!iv->errors){if(fwrite(buf, 1, cnt, iv->outfile) != cnt)iv->errors = 12;}}
#define ROUNDING(a,b) ((a+(b-1))&~(b-1))
#define ROUNDUP(a,b) a += ROUNDING(a,b)

/* ======================== CONCATENIZATION MACROS ==================== */

#define	_cat2_(a, b)	a##b
#define _cat_(a, b)	_cat2_(a, b)
#define Global(a) _cat_(PROG, a)

#define _pname2_(x)	#x
#define _pname1_(x)	_pname2_(x)
#define pName		_pname1_(PROG)


/* ============== ENDIAN MACROS (input format is litle endian) ==== */

#if HOST_IS_LITTLE_ENDIAN
#define GL(a) a
#define GS(a) a
#define PL(a) a
#define PS(a) a
#else
#endif

/* =================== INPUT DATA FORMATS ========================== */

#define INFILE_SYMNUM 1
#define OUTFILE_SYMNUM 2


/* ====================== STRUCTURES AND TYPEDEFS ======================== */

typedef struct _jl {
	struct _jl *next;
	void *p;
	char *q;
	long *plabelval;
	long offset;
} *PJL;

typedef struct _afile {
	unsigned char *file_p;
	PopI header_p;
	PopI size_p;
	unsigned char *symtext_p;
	unsigned char *prog_p;
	unsigned char *data_p;
	unsigned char *switch_p;
	unsigned char *decl_p;
	unsigned char *maxtemp_p;
	unsigned char *seg_p;
	unsigned char **symaddr;
	unsigned char **decladdr;
	unsigned long thunk_offset;
	unsigned long bss_offset;
	int maxtemp;
	int maxtempclass;
	void *datatbl;
	short *symtran;
	unsigned short *decltran;
	int filenum;
	int numsyms;
	int numdecls;
	int numrelocs;
	int numsegs;
} *Pafile;

typedef struct _iv {
	int category;
	FILE *outfile;
	int remove_infile;
	int argc;
	char **argv;
	unsigned char **symaddr;
	unsigned char **decladdr;
	int numfiles;
	int lastlabel;
	int errors;
	int numsyms;
	int numdecls;
	int numsegs;
	int maxtemp;
	int maxtempclass;
	unsigned long total_size;
	unsigned long thunk_offset;
	unsigned long bss_offset;
	long first_temp;
	long killop;
	void *reloctbl;
	void *extrntbl;
	void *gbltbl;
	void *symtbl;
	void *labeltbl;
	void *newlabeltbl;
	void *tmptbl;
	void *segtbl;
	int temps_written;
	unsigned char *obuf;
	unsigned char *obufstart;
	PJL jbuf;
	void *jbufstart;
	int jmpcnt;
	int jbufcnt;
	long obufcnt;
	long out_offset;
	long func_offset;
	int filenum;
	Pafile files[1024];
	char debug;
	char only_debug;
	char strip;
} *Piv;

struct _gloval {
	char *symname;
	unsigned char *p;
	Pafile pf;
	int symnum;
};


/* Internal User API */
static void *Cmalloc(int category, unsigned amount);
static void *Ccalloc(int category, unsigned nelems, unsigned elemsize);
static void *Crealloc(int category, void* buf, unsigned newsize);
static void Cfree(int category, void* buf);
static void Cfreecat(int category);
static int Cmemrange(int category, unsigned* minp, unsigned* maxp);
static int Cusedrange(int category, unsigned* minp, unsigned* maxp);
static void Ctotrange(unsigned* minp,unsigned* maxp);
static int Cnewcat(void);
static void Cguard(int category);
static void* NewSymTable(int category, int nbins);
static int SymFind(void *tbl, void *key, void *result);
static int SymFindRange(void *tbl, void *key, void *result);
static void *SymInsert(void *tbl, void *key, void *value, int datsiz);
static int StringInsert(void *tbl, char *string, void *result);
static int StringFind(void *tbl, char *string, void *result);
static void SymDelete(void *tbl, void *key);
static int SymHead(void *tbl);
static int SymNext(void *tbl);
static void SymGetMark(void *tbl, void *markptr);
static int SymMarkNext(void *tbl, void *mark);
static void SymSetMark(void *tbl, void *markptr);
static void SymKey(void *tbl, void *keyptr);
static void SymValue(void *tbl, void *datptr);
static void *seg_find(Piv iv, int id);
static char *filenameof(char *path);
static char *propernameof(Piv iv, char *name);

/* END: User API */

/* ====================== PUT UNIQUE CODE HERE ========================= */
/* ===================== LINKER OUTPUT GENERATOR ======================= */
static void
gen_infop3(Piv iv, int op, long a, long b, long c)
{
struct {
	unsigned char op[2];
	short pad;
	long next;
	long a;
	long b;
	long c;
}immed;

	immed.op[0] = op;
	immed.op[1] = OPIMMED3|12;
	immed.pad = 0;
	immed.next = sizeof(immed);
	immed.a = a;
	immed.b = b;
	immed.c = c;
	FILEWRITE(&immed, sizeof(immed))
}
static void
gen_infop1(Piv iv, int op, long a)
{
struct {
	unsigned char op[2];
	short pad;
	long next;
	long a;
}immed;

	immed.op[0] = op;
	immed.op[1] = OPIMMED1|4;
	immed.pad = 0;
	immed.next = sizeof(immed);
	immed.a = a;
	FILEWRITE(&immed, sizeof(immed))
}
static void
gen_infop0(Piv iv, int op)
{
struct {
	unsigned char op[2];
	short pad;
	long next;
}immed;

	immed.op[0] = op;
	immed.op[1] = 0;
	immed.pad = 0;
	immed.next = sizeof(immed);
	FILEWRITE(&immed, sizeof(immed))
}

static void
dump_header(Piv iv)
{
Pafile pf;
unsigned char *p, *next;
	pf = iv->files[0];
	p = pf->file_p;
	next = POP->next;
	PL(POP->next) = (void*)20;		/* unlink node */
	FILEWRITE(p, 20)
	PL(POP->next) = next;	/* relink node */
	gen_infop3(iv, dataop, iv->total_size, iv->thunk_offset, iv->bss_offset);
}
static void
dump_symbols(Piv iv)
{
extern void *Cmalloc();
int sym_offset = 0;
int pad;
int i;
int *symlens = Cmalloc(iv->category, sizeof(int)*iv->numsyms);

	/* Symbol Count */
	gen_infop1(iv, symbop, iv->numsyms);
	/* Symbol offsets */
	for(i = 0; i < iv->numsyms; ++i)
	{
		gen_infop1(iv, symoffsetop, sym_offset);
		symlens[i] = strlen(iv->symaddr[i])+1;
		sym_offset += symlens[i];
	}

	/* Contiguous block of symbol strings */
	gen_infop1(iv, symblockop,sym_offset);	
	for(i = 0; i < iv->numsyms; ++i) {
		FILEWRITE(iv->symaddr[i], symlens[i])
	}

	/* Alignment is 4 bytes */
	pad = (4-(sym_offset&3))&3;
	if(pad == 1)
		FILEWRITE("", 1)
	else if(pad == 2)
		FILEWRITE(" ", 2)
	else if(pad == 3)
		FILEWRITE("  ", 3)
}
static void
dump_files(Piv iv)
{
Pafile pf;
unsigned char *p, *next;
int i, dsize;

	/* Output could be neatened up by collecting various subgroups
		but it would require several passes over the files */
	
	for(i = 0; i < iv->numfiles; ++i)
	{
		pf = iv->files[i];
		p = pf->file_p;
		while(*p != endfileop)
		{
			next = POP->next;
			dsize = 0;

			switch(*p)
			{
				case	0:
				case	headerop:
				case	dataop:
				case	symoffsetop:
				case	symblockop:
				case	symbop:
					break;
				case	stringblockop:
				case	datablockop:
				case	mallocblockop:
				case	thunkblockop:
					dsize = GL(POP->data);
					dsize += ((4-(dsize&3))&3); /* alignment */
				/* FALL THROUGH */
				default:
				{
				size_t size = next - p;
					PL(POP->next) = (void*)(size - dsize);	/* unlink node */
					FILEWRITE(p, size)
					break;
				}
			}
			p = next;
		}
	}
}
static void
dump_trailer(Piv iv)
{
	gen_infop0(iv, endfileop);
	gen_infop0(iv, endallop);
}

static int
gen_output(Piv iv, char *outpath)
{/* Linker output */
char *cp;
int i;
char outname[256];

	strcpy(outname, outpath);
	if((cp = strrchr(outname, '.')))
	{
#if 0
		strcpy(cp, ".anf");
#endif
	}
	else
	{
		strcat(outname, ".anf");
	}
	for(i = 1; i < iv->argc; ++i)
	{
	  if(!strcmp(outname, iv->argv[i]))
	  {
		PERROR(pName ":ERROR output file `%s' is same as input file\n", outname);
	  }
	}
	if(!(iv->outfile = fopen(outname, "wb")))
	{
		PERROR(pName ":ERROR: Cannot open output file %s\n", outname);
	}
	dump_header(iv);
	dump_symbols(iv);
	dump_files(iv);
	dump_trailer(iv);
	fclose(iv->outfile);
	iv->outfile = 0;	
	return iv->errors;
}
/* ======================= END LINKER OUTPUT GENERATOR ==================== */

/* ===================== GENERIC CODE BELOW THIS POINT ================== */
static jmp_buf run_env;
static void
prerror(const char *fmt, ...)
{
	VFPRINTF(fmt, (char *)(((int *)(&fmt))+1));
	longjmp(run_env, 3);
}
static void
prwarn(const char *fmt, ...)
{
	VFPRINTF(fmt, (char *)(((int *)(&fmt))+1));
}
/* ========================= MULTI HEAP MALLOC ========================== */
#define LOCAL static

#if USING_FRAMEWORK
#define THEWELL(a) mallocC(local_category, a)
static int local_category;
static int num_instance;
extern void *mallocC(int, int);
extern void freecat(int);
extern void oxlink_clear_bss();
extern int NewMallocCategory();
#endif /* USING_FRAMEWORK */

#define BASE_CATEGORY 0
#define MEMORY_BUG 0
#define PRINT_RAWDATA 0

#if MEMORY_BUG == 1
#define MPRINTF printf
#else
#define MPRINTF(args...)
#endif

#define PAGESIZE (4096)	/* can use `pagesize' function in OS */
#define ALIGNMENTM (sizeof(unsigned long))
#define MAL_MAXLEVEL (12)
#define ROUNDINGM(a) ((a+(ALIGNMENTM-1))&~(ALIGNMENTM-1))
#define ALLOCSIZE (4096)
#define FRNTGUARD (0x544e5246UL)
#define BACKGUARD (0x48434142UL)
#ifndef THEWELL
#define THEWELL do_sbrk
#endif
#define NUMTYPES 3
#define SIZEH 0
#define FREEH 1
#define USEDH 2

#define SKIPVARS NodePM update[MAL_MAXLEVEL+1];NodePM node,prev;int level

#define DELETENODE(TYPE) \
{for(level=0;level<=bp->TYPE##level; level++)\
{if(update[level]->fptr[level] == node)\
update[level]->fptr[level] = node->fptr[level];else break;}\
while(bp->TYPE##level>0 && bp->TYPE##header->fptr[bp->TYPE##level]==_NILLL)\
bp->TYPE##level--;free_Mnode(bp,node,TYPE);}

#define INSERT() \
{while(level >= 0){\
node->fptr[level] = update[level]->fptr[level];\
update[level]->fptr[level] = node;level--;}}

#define SETLEVEL(TYPE) \
{level = getMlevel(bp, bp->TYPE##level);\
while(bp->TYPE##level < level)update[++bp->TYPE##level]=bp->TYPE##header;}

#define FINDKEY(TYPE, KEYVAL)\
{node = bp->TYPE##header;\
for(level = bp->TYPE##level; level >= 0; level--){\
while(node->fptr[level]->key < KEYVAL)\
node = node->fptr[level];\
update[level] = node;}prev=node;node=node->fptr[0];}

#define DETACH(SN)\
{SN->bptr->fptr=SN->fptr;if(SN->fptr)SN->fptr->bptr=SN->bptr;}

#define UNLINK(SN, N)\
{if(!sp->fptr&&sp->bptr->bptr<=(AddrP)(MAL_MAXLEVEL+1))dsize[N]=sp->size;\
DETACH(SN);free_addr(bp,SN);}

#define CHECKGUARDS(MSG)\
{if(bp->guarded){\
unsigned *p2;\
p2 = (void*)((char*)address+cursize-ALIGNMENTM);\
if(*address != FRNTGUARD)\
PERROR(pName #MSG ":%d: corrupted at 0x%x\n", bp->bincat, addr);\
if(*p2 != BACKGUARD)\
PERROR(pName #MSG ":%d: corrupted by 0x%x\n", bp->bincat, addr);}}

#if MEMORY_BUG == 1
#define HEAPCHECK \
{void *lastaddr;\
if(category > 0){\
Cguard(category);\
if((lastaddr = Cheapcheck(category, NULL))){\
FINDKEY(USEDH, (unsigned)lastaddr-ALIGNMENTM)\
MPRINTF("bad heap at %x c:%u size=%u\n", lastaddr, category, node->value);\
(void)print_rawdata(lastaddr-ALIGNMENTM, node->value);\
abort();}}}
#else
#define HEAPCHECK
#endif

struct _catlocs {
	void *addr;
	struct _catlocs *fptr;
};

typedef struct _nodeM
{
	unsigned key;
	unsigned value;
	unsigned levels;	/* must always be after value */
	struct _nodeM *fptr[1];
} NodeM, *NodePM;

typedef struct _addr
{
	struct _addr *fptr;
	struct _addr *bptr;
	NodePM maddr;
	unsigned size;
} *AddrP;

struct _bins {
	unsigned bits;
	unsigned nbits;
	NodePM SIZEHheader;
	int SIZEHlevel;
	NodePM FREEHheader;
	int FREEHlevel; 
	NodePM USEDHheader;
	int USEDHlevel;

	unsigned bincat;
	unsigned maxloc;
	unsigned minloc;
	struct _catlocs *catlocs;
	struct _bins *fptr;
	NodePM freenodes[NUMTYPES][MAL_MAXLEVEL+2];
	struct _addr *freeaddrlocs;
	char *chunkbase[NUMTYPES];
	int chunksize[NUMTYPES];
	int guarded;
	int addrbump;
};

static struct _bins zbp;
static struct _bins *hmap[1009];
static struct _nodeM _nilll = {0xffffffff,0,0,{0}};
static struct _nodeM *_NILLL = &_nilll;
static unsigned maxloc;
static unsigned minloc;
static struct _bins *freebinlocs;
static struct _catlocs *freecatlocs;
static char *binbase;
static int binsize;
static int chunksizes[] = {ALLOCSIZE,3*ALLOCSIZE,2*ALLOCSIZE};


static long randtbl[32]	= { 0L,
	0x9a319039L, 0x32d9c024L, 0x9b663182L, 0x5da1f342L, 
	0xde3b81e0L, 0xdf0a6fb5L, 0xf103bc02L, 0x48f340fbL, 
	0x7449e56bL, 0xbeb1dbb0L, 0xab5c5918L, 0x946554fdL, 
	0x8c2e680fL, 0xeb3d799fL, 0xb11ee0b7L, 0x2d436b86L, 
	0xda672e2aL, 0x1588ca88L, 0xe369735dL, 0x904f35f7L, 
	0xd7158fd6L, 0x6fa6f051L, 0x616e6b96L, 0xac94efdcL, 
	0x36413f93L, 0xc622c298L, 0xf5a42ab8L, 0x8a88d77bL, 
	0xf5ad9d0eL, 0x8999220bL, 0x27fb47b9L
};

static  long *fptr	= &randtbl[4];
static  long *rptr	= &randtbl[1];

/* ======================== START OF CODE =========================== */
#if PRINT_RAWDATA == 1
static char
hexbyte(unsigned int c)
{
char x = c & 0xf;

	return x + ((x>9) ? 55 : 48);
}
static void
print_rawdata(void *rawdata, long size)
{
unsigned long vaddr = 0;
unsigned char *d = rawdata;
int i,j;
char addr[9];
char hex1[24];
char hex2[24];
char side1[9];
char side2[9];

	addr[8] = 0;
	hex1[23] = 0;
	hex2[23] = 0;
	side1[8] = 0;
	side2[8] = 0;
	while(size > 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -