📄 oxccl.c
字号:
/*
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 + -