📄 oxccl.c
字号:
static int
setup_nodelinks(Piv iv, char *infile_name, void *inbuf, int insize)
{
unsigned char *p = inbuf;
unsigned char *endbuf = inbuf+insize;
Pafile pf=0;
long lastline = 0;
unsigned char *funcp;
unsigned char *nfuncp;
while(p < endbuf && *p != endallop)
{
unsigned char *q = p;
if(iv->debug)
{
PRINTF("OP(%d '%s' p=%p line=%ld)\n", *p, oxgenops[*p], p, lastline);
}
switch(*p)
{
case headerop:
if(iv->numfiles >= 1024) {
PERROR(pName ": Sorry, too many files\n");
return 1;
}
pf = iv->files[iv->numfiles] =
Ccalloc(iv->category, 1, sizeof(struct _afile));
pf->filenum = iv->numfiles++;
pf->file_p = p;
pf->header_p = POPI;
if(iv->strip)
{/* Gonna strip declarations and line numbers */
pf->header_p->hdr.target_debugger = 0;
}
break;
case dataop:
pf->size_p = POPI;
pf->thunk_offset = GL(POPI->dat.thunk_offset);
pf->bss_offset = GL(POPI->dat.bss_offset);
break;
case gfuncdefop:
case sfuncdefop:
if(pf->prog_p == 0)
pf->prog_p = p;
funcp = p;
break;
case funcexitop:
PS(((PopI)(funcp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
break;
case nestedfuncdefop:
nfuncp = p;
break;
case nestedfuncexitop:
PS(((PopI)(nfuncp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
break;
case segdefop:
if(pf->seg_p == 0)
pf->seg_p = p;
pf->numsegs += 1;
iv->numsegs += 1;
break;
case lineop:
lastline = GL( POPI->line.line );
if(iv->strip)
*p = 0; /* strip line numbers */
break;
case declop:
if(iv->strip)
{/* strip declarations */
do {
*p = 0;
q += (long)GL(POP->next);
POP->next = q;
p = q;
} while(*p != endop);
*p = 0;
}
else
{
if(pf->decl_p == 0)
pf->decl_p = p;
pf->numdecls += 1;
iv->numdecls += 1;
}
break;
case switchidop:
if(pf->switch_p == 0)
pf->switch_p = p;
/* FALL THROUGH */
case labelop:
PL( POP->data ) =
label_insert(iv, GL( POP->data ), pf->filenum);
break;
case symbop:
pf->numsyms = GL(POP->data);
iv->numsyms += pf->numsyms;
break;
case symblockop:
pf->symtext_p = p + 12;
goto blka;
case stringblockop:
case datablockop:
case mallocblockop:
case thunkblockop:
{
long size;
if(pf->data_p == 0)
pf->data_p = p;
blka:
size = GL(POP->data);
q += size+((4-(size&3))&3);
break;
}
case glofuncop:
case extfuncop:
case glodatop:
case globssop:
case extvarop:
case bssblockop:
if(pf->data_p == 0)
pf->data_p = p;
break;
case maxtempop:
pf->maxtemp = GL(POP->data);
pf->maxtempclass = GL(POP->data1);
pf->maxtemp_p = p;
break;
}
q += (long)GL(POP->next);
POP->next = q;
p = q;
}
if(*p != endallop)
{
PERROR(pName ":ERROR: Malformed input file: %s\n", infile_name);
return 1;
}
return 0;
}
static void
setup_syms_decls(Piv iv)
{
int i;
for(i = 0; i < iv->numfiles; ++i)
{
int symnum = 0;
Pafile pf = iv->files[i];
unsigned char *p = pf->file_p;
pf->symaddr = Ccalloc(iv->category, sizeof(void*), pf->numsyms);
pf->decladdr = Ccalloc(iv->category, sizeof(void*), pf->numdecls);
while(*p != endfileop)
{
switch(*p)
{
case symoffsetop:
pf->symaddr[symnum] = pf->symtext_p + GL(POP->data);
++symnum;
break;
case declop:
pf->decladdr[GS(POPI->dcl.declnum)] = p;
break;
case relocop:
case extlocop:
++pf->numrelocs;
reloc_insert(iv, i, p);
break;
case glodatop:
case globssop:
case glofuncop:
case extfuncop:
global_insert(iv, pf, p);
break;
case extvarop:
extern_insert(iv, p, i);
global_insert(iv, pf, p);
break;
case stringblockop:
case datablockop:
case mallocblockop:
case thunkblockop:
case bssblockop:
if(!pf->datatbl)
pf->datatbl = NewSymTable(iv->category, 0); /* sorted */
data_insert(pf->datatbl,GL(DATI.offset),GL(DATI.size),p);
if(*p == thunkblockop) {
PL(POP->data4) = label_find(iv, GL(POP->data4),i);
}
break;
case jmploopop:
case jmpcontinueop:
case jmpbreakop:
case jmpgotoop:
case jmptrueop:
case jmpfalseop:
PL(POP->data) = label_find(iv, GL(POP->data), i);
break;
case switchidop:
if(GL(POP->data1))
PL(POP->data1) = label_find(iv, GL(POP->data1), i);
break;
case switchop:
PL(POP->data) = label_find(iv, GL(POP->data), i);
PL(POP->data1) = label_find(iv, GL(POP->data1), i);
break;
case casevalop:
PL(POP->data1) = label_find(iv, GL(POP->data1), i);
break;
}
p = POP->next;
}
}
}
static int
sym_insert(Piv iv, char *symname, int symnum)
{/* Used only for combining symbols in link phase */
struct {
char *symname;
int symnum;
} *valp;
if(StringInsert(iv->symtbl, symname, &valp))
return -valp->symnum; /* MATCH */
valp->symnum = symnum;
return symnum;
}
static void
combine_syms_decls(Piv iv)
{
int i,j;
Pafile pf;
int numsyms;
int numdecls;
/* COMBINE SYMBOLS */
pf = iv->files[0];
numsyms = pf->numsyms;
pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms);
memcpy(iv->symaddr, pf->symaddr, sizeof(void*) * numsyms);
for(i = 0; i < numsyms; ++i)
{/* file 0 */
sym_insert(iv, pf->symaddr[i], i);
pf->symtran[i] = i;
}
for(i = 1; i < iv->numfiles; ++i)
{
int start;
pf = iv->files[i];
pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms);
if(pf->header_p->hdr.target_debugger)
start = 1;
else
start = 3;
for(j = start; j < pf->numsyms; ++j)
{
int k;
if((k = sym_insert(iv, pf->symaddr[j], numsyms)) > 0)
{ /* new entry */
iv->symaddr[numsyms++] = pf->symaddr[j];
pf->symtran[j] = k;
}
else pf->symtran[j] = -k;
}
}
iv->numsyms = numsyms;
/* COMBINE DECLARATIONS */
pf = iv->files[0];
numdecls = pf->numdecls;
pf->decltran = Ccalloc(iv->category, sizeof(short), pf->numdecls);
memcpy(iv->decladdr, pf->decladdr, sizeof(void*) * numdecls);
for(i = 0; i < numdecls; ++i)
{/* file 0 */
pf->decltran[i] = i;
}
for(i = 1; i < iv->numfiles; ++i)
{
pf = iv->files[i];
pf->decltran = Ccalloc(iv->category, sizeof(short), pf->numdecls);
if(pf->numdecls < 21)
continue;
for(j = 1; j <= 21; ++j)
pf->decltran[j] = j;
for(j = 22; j < pf->numdecls; ++j) {
iv->decladdr[numdecls] = pf->decladdr[j];
pf->decltran[j] = numdecls++;
}
}
iv->numdecls = numdecls;
}
static void
link_dups(Piv iv, int dupcnt, struct _gloval *valp[])
{
int i;
int vars[5] = {0,0,0,0,0};
unsigned long cdsize = 0;
unsigned long cdoffset = 0;
short cdfile = 0;
int cdnum = 0;
short segid = 0;
#define GDAT vars[0]
#define GBSS vars[1]
#define GFUNC vars[2]
#define EVAR vars[3]
#define EFUNC vars[4]
/* Count the types of matches */
for(i = 0; i <= dupcnt; ++i)
vars[*(valp[i]->p) - glodatop] += 1;
/* Check for errors */
if( GDAT > 1
|| GFUNC > 1
|| (GFUNC && (GDAT || GBSS || EVAR))
|| (EFUNC && (GDAT || GBSS || EVAR)))
{
++iv->errors;
for(i = 0; i < dupcnt; ++i)
{
PWARN(pName ": Symbol `%s' multiply defined or mistyped.\n",
valp[i]->symname);
PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
}
return;
}
if(EFUNC && GFUNC)
{/* match up functions */
Pop dp;
for(i = 0; i <= dupcnt; ++i)
if(*(valp[i]->p) == glofuncop)
break;
dp = (Pop)((Pop)valp[i]->p)->next; /* points to thunkblockop */
cdoffset = GL(dp->data1); /* save this offset */
cdfile = valp[i]->pf->filenum; /* save this file */
for(i = 0; i <= dupcnt; ++i)
{
if(*(valp[i]->p) == extfuncop)
{
*(valp[i]->p) = 0; /* convert to nilop */
dp = (Pop)((Pop)valp[i]->p)->next; /* points to thunkblockop */
/* Kill the functhunk */
*((char*)dp) = 0;
PL(dp->data4) = cdoffset; /* use this offset for access */
PS(((short*)dp)[1]) = cdfile; /* fileno to unused slots */
}
}
}
else if(EFUNC)
{/* multiple references to external function */
Pop dp = (Pop)((Pop)valp[0]->p)->next; /* points to first thunkblockop */
cdoffset = GL(dp->data1); /* save first offset */
cdfile = valp[0]->pf->filenum; /* save first file */
for(i = 1; i <= dupcnt; ++i)
{/* Kill all thunkblocks except the first */
*(valp[i]->p) = 0; /* convert to nilop */
dp = (Pop)((Pop)valp[i]->p)->next; /* points to thunkblockop */
*((char*)dp) = 0;
PL(dp->data4) = cdoffset; /* use this offset for access */
PS(((short*)dp)[1]) = cdfile; /* fileno to unused slots */
}
}
else if(GBSS)
{/* comdefs */
int multsize = 0;
/* PICK THE BIGGEST GLOBAL BSS (comdef) */
for(i = 0; i <= dupcnt; ++i)
{
Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to bssblockop */
if((short)dp->data4 && segid == 0)
{
segid = (short)dp->data4;
}
else if((short)dp->data4 && (short)dp->data4 != segid)
{
++iv->errors;
PWARN(pName, ": Variable `%s' defined in multiple segments.\n",
valp[i]->symname);
PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
}
if(*(valp[i]->p) == globssop)
{
long size = GL(dp->data);
if(cdsize && size != cdsize)
multsize = 1;
if(size > cdsize) {
cdsize = size;
cdoffset = GL(dp->data1);
cdfile = valp[i]->pf->filenum;
cdnum = i;
}
}
}
if(GDAT)
{
/* INITIALIZED DATA WILL ALWAYS OVERRIDE BSS */
for(i = 0; i <= dupcnt; ++i)
{
if(*(valp[i]->p) == glodatop)
{
Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to datablockop */
long size = GL(dp->data);
if(cdsize && size != cdsize)
multsize = 1;
if(size < cdsize)
{
++iv->errors;
PWARN(pName ": Initialized variable `%s' of size (%d)\n",
valp[i]->symname, size);
PWARN(pName ": In file: `%s'\n",
valp[i]->pf->symaddr[INFILE_SYMNUM]);
PWARN(pName ": Is incommensurate with common size (%d).\n",
cdsize);
}
else
{
cdsize = size;
cdoffset = GL(dp->data1);
cdfile = valp[i]->pf->filenum;
cdnum = i;
}
}
}
}
if(multsize)
{
PWARN(pName ":warning: Common Variable `%s' has multiple sizes.\n",
valp[0]->symname);
for(i = 0; i <= dupcnt; ++i)
{
unsigned char opcode = *(valp[i]->p);
if(opcode == globssop || opcode == glodatop)
{
PWARN(pName ": Size=%d in file: `%s'\n",
GL(((Pop)((Pop)valp[i]->p)->next)->data),
valp[i]->pf->symaddr[INFILE_SYMNUM]);
}
}
}
/* FINALLY, LINK COMMONS TO THE CHOSEN ONE */
for(i = 0; i <= dupcnt; ++i)
{
if(i != cdnum && *(valp[i]->p) == globssop)
{
Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to bssblockop */
*(valp[i]->p) = 0; /* globssop becomes nilop */
*((char*)dp) = 0; /* bssblockop becomes nilop */
PL(dp->data1) = cdoffset; /* use this new offset for access */
PS(((short*)dp)[1]) = cdfile; /* put fileno in unused slots */
}
}
}
else if(GDAT)
{
for(i = 0; i <= dupcnt; ++i)
{
Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to datablockop */
if((short)dp->data4 && segid == 0)
{
segid = (short)dp->data4;
}
else if((short)dp->data4 && (short)dp->data4 != segid)
{
++iv->errors;
PWARN(pName, ": Variable `%s' defined in multiple segments.\n",
valp[i]->symname);
PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
}
if(*(valp[i]->p) == glodatop)
{
cdsize = GL(dp->data);
cdoffset = GL(dp->data1);
cdfile = valp[i]->pf->filenum;
cdnum = i;
break;
}
}
}
if(EVAR && (GDAT || GBSS))
{/* match up variables */
/* LINK EXTERNS TO THE CHOSEN ONE */
for(i = 0; i <= dupcnt; ++i)
{
if(*(valp[i]->p) == extvarop)
{
Pop dp = (Pop)valp[i]->p;
*((char*)dp) = 0; /* extvarop becomes nilop */
PL(dp->data1) = cdoffset; /* use this new offset for access */
PS(((short*)dp)[1]) = cdfile; /* put fileno in unused slots */
PS(dp->data4) = segid;
break;
}
}
}
#undef GDAT
#undef GBSS
#undef GFUNC
#undef EVAR
#undef EFUNC
}
static void
link_globals(Piv iv)
{
if(SymHead(iv->gbltbl))
{
struct _gloval *valp[1024]; /* pointers to symtable value structs */
/* Pass over the sorted symbol table and process duplicate entries */
while(SymNext(iv->gbltbl))
{
unsigned long *key;
long mark[2]; /* Table position saver */
int dupcnt = 0;
SymKey(iv->gbltbl, &key); /* Pointer to first key */
SymValue(iv->gbltbl, &valp[0]); /* Pointer to first value */
while(SymMarkNext(iv->gbltbl, mark))
{/* Look forward for duplicates */
unsigned long *key1;
SymKey(iv->gbltbl, &key1); /* Pointer to next key */
if(KEYEQ(key, key1))
{/* Hashed keys match, check the strings */
SymValue(iv->gbltbl, &valp[dupcnt+1]); /* Pointer to next value */
if(!strcmp(valp[dupcnt]->symname, valp[dupcnt+1]->symname))
{/* Duplicate entry found */
++dupcnt;
continue;
}
}
break;
}
if(dupcnt > 0)
{/* Process a collection of duplicate symbol names */
link_dups(iv, dupcnt, valp);
}
SymSetMark(iv->gbltbl, mark);
}/* END: while(SymNext) */
}/* END: if(SymHead) */
}
static void
realloc_data(Piv iv)
{
int i;
Pafile pf;
unsigned char *p;
unsigned long offset = 0;
for(i = 0; i < iv->numfiles; ++i)
{
pf = iv->files[i];
p = pf->data_p;
while(*p != endfileop)
{
if( *p == datablockop
|| *p == mallocblockop
|| *p == stringblockop)
{
PL(POP->data1) = offset;
offset += GL(POP->data);
ROUNDUP(offset, 4);
}
p = POP->next;
}
}
iv->thunk_offset = offset;
for(i = 0; i < iv->numfiles; ++i)
{
pf = iv->files[i];
p = pf->data_p;
while(*p != endfileop)
{
if(*p == thunkblockop) {
PL(POP->data1) = offset;
offset += GL(POP->data);
ROUNDUP(offset,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -