#include "java.h"#include "reloc.h" /* * Manage run-time resolution information. */ typedef struct RTHash RTHash; struct RTHash{ RTClass *rtc; RTHash *next;}; static RTHash *rttbl[Hashsize]; /* hash table of referenced classes */static int nrtclasses; /* no. of classes referenced */ static voidrtappend(RTClass *rtc, RTReloc *rtr){ if(rtc->rtr == nil) rtc->rtr = rtr; else rtc->tail->next = rtr; rtc->tail = rtr;} static voidrtprepend(RTClass *rtc, RTReloc *rtr){ if(rtc->rtr == nil) rtc->tail = rtr; rtr->next = rtc->rtr; rtc->rtr = rtr;} /* * Add RTReloc entry. */ static RTReloc*addRTReloc(RTClass *rtc, char *field, char *sig, uint flags){ RTReloc *rtr; rtr = Malloc(sizeof(RTReloc)); rtr->field = field; rtr->sig = sig; rtr->flags = flags; rtr->ipatch = Mallocz(sizeof(Ipatch)); rtr->next = nil; if(field[0] == '@') /* these must go first in the list ! */ rtprepend(rtc, rtr); else rtappend(rtc, rtr); rtc->n += 1; return rtr;} /* * Allocate a RTClass structure. */ static RTClass*newRTClass(char *s){ RTClass *rtc; rtc = Malloc(sizeof(RTClass)); rtc->classname = s; rtc->rtr = nil; rtc->tail = nil; rtc->n = 0; rtc->off = 0; nrtclasses += 1; /* want the order: @mp, @np, @adt, @Class */ addRTReloc(rtc, RCLASS, nil, 0); addRTReloc(rtc, RADT, nil, 0); addRTReloc(rtc, RNP, nil, 0); addRTReloc(rtc, RMP, nil, 0); return rtc;} /* * Add RTClass entry for classname. */ static RTClass*addRTClass(char *classname){ uint h; RTHash *he; h = hashval(classname); he = Malloc(sizeof(RTHash)); he->rtc = newRTClass(classname); he->next = rttbl[h]; rttbl[h] = he; return he->rtc;} /* * Get RTClass entry for classname. */ RTClass*getRTClass(char *classname){ RTHash *he; for(he = rttbl[hashval(classname)]; he; he = he->next) { if(strcmp(classname, he->rtc->classname) == 0) return he->rtc; } return addRTClass(classname);} /* * Get RTReloc entry. Ignore signature if nil. */ RTReloc*getRTReloc(RTClass *rtc, char *field, char *sig, uint flags){ RTReloc *rtr; uint lowflags; lowflags = 0; for(rtr = rtc->rtr; rtr; rtr = rtr->next) { if(strcmp(rtr->field, field) == 0 && (sig == nil || strcmp(rtr->sig, sig) == 0)) { if(rtr->flags >> 16 == 0) { rtr->flags |= flags; return rtr; } else if(rtr->flags >> 16 == flags >> 16) return rtr; lowflags = rtr->flags & 0xffff; } } return addRTReloc(rtc, field, sig, flags|lowflags);} /* * Add instruction patch information to RTReloc rtr. */ voidRTIpatch(RTReloc *rtr, Inst *i, int operand, int patchkind){ addDreloc(i, operand, patchkind); addIpatch(rtr->ipatch, i, operand, patchkind, SAVEINST);} /* * Fix RTClass and RTReloc 'off' fields to prepare for instruction patch. */ voidRTfixoff(int off){ RTHash *he; int i; if(nrtclasses > 0) { for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he; he = he->next) { he->rtc->off = off; off += he->rtc->n * IBY2WD; } } }} /* * Patch instructions for run-time relocation. */ voiddoRTpatch(void){ Addr *a; RTHash *he; Ipatch *ip; RTReloc *rtr; int i, j; int off, ltsize; if(nrtclasses == 0) return; ltsize = LTrelocsize(); a = nil; for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he; he = he->next) { off = he->rtc->off - ltsize; for(rtr = he->rtc->rtr; rtr; rtr = rtr->next) { ip = rtr->ipatch; for(j = 0; j < ip->n; j++) { switch(ip->pinfo[j] & (0x3 << 2)) { case PSRC: a = &ip->i[j]->s; break; case PDST: a = &ip->i[j]->d; break; case PMID: a = &ip->i[j]->m; break; } switch(ip->pinfo[j] & 0x3) { case PIMM: a->u.ival = off; break; case PSIND: a->u.offset = off; break; case PDIND1: a->u.b.fi = off; break; case PDIND2: a->u.b.si = off; break; } } off += IBY2WD; } } }} /* * Size of Module Data space taken by run-time relocation information. */ intRTrelocsize(void){ int i; int n; RTHash *he; n = 0; if(nrtclasses > 0) { for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he; he = he->next) n += he->rtc->n; } } return n * IBY2WD;} /* * Fix type descriptor for run-time relocation information. */ static int RTReloctid; voidRTrelocdesc(uchar *map, int off){ int i; RTHash *he; RTReloc *rtr; if(nrtclasses == 0) return; RTReloctid = descid(3*IBY2WD, 1, (uchar*)"\xc0"); for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he; he = he->next) { setbit(map, off); /* @mp cell */ off += 4; setbit(map, off); /* @np cell */ off += 4; setbit(map, off); /* @adt cell */ off += 8; rtr = he->rtc->rtr->next->next->next->next; while(rtr) { if(rtr->flags & (Rspecialmp | Rstaticmp)) setbit(map, off); off += 4; rtr = rtr->next; } } }} /* * Write RTReloc array to .s file. */ static voidasmRTReloc(int off, RTClass *rtc){ RTReloc *rtr; int reloff; /* relative offset for array elements */ if(rtc->n <= 4) return; reloff = 0; asmarray(off, RTReloctid, rtc->n - 4, reloff); /* skip @mp @np @adt @Class */ rtr = rtc->rtr->next->next->next->next; while(rtr) { asmstring(reloff, rtr->field); reloff += IBY2WD; if(rtr->sig) asmstring(reloff, rtr->sig); reloff += IBY2WD; asmint(reloff, rtr->flags); reloff += IBY2WD; rtr = rtr->next; } Bprint(bout, "\tapop\n");} /* * Write RTClass information to .s file. */ intasmRTClass(int off){ RTHash *he; int i; int ltsize; if(nrtclasses > 0) { ltsize = LTrelocsize(); for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he; he = he->next) { off += IBY2WD; /* @mp cell */ asmstring(off, he->rtc->classname); off += IBY2WD; asmRTReloc(off, he->rtc); off += IBY2WD; asmint(off, he->rtc->off - ltsize); off += IBY2WD; /* account for fields beyond @Class */ off += (he->rtc->n - 4) * IBY2WD; } } } return off;} /* * Write RTReloc array to .dis file. */ static voiddisRTReloc(int off, RTClass *rtc){ RTReloc *rtr; int reloff; /* relative offset for array elements */ if(rtc->n <= 4) return; reloff = 0; disarray(off, RTReloctid, rtc->n - 4); /* skip @mp @np @adt @Class */ rtr = rtc->rtr->next->next->next->next; while(rtr) { disstring(reloff, rtr->field); reloff += IBY2WD; if(rtr->sig) disstring(reloff, rtr->sig); reloff += IBY2WD; disint(reloff, rtr->flags); reloff += IBY2WD; rtr = rtr->next; } disapop();} /* * Write RTClass information to .dis file. */ intdisRTClass(int off){ RTHash *he; int i; int ltsize; if(nrtclasses > 0) { ltsize = LTrelocsize(); for(i = 0; i < Hashsize; i++) { for(he = rttbl[i]; he; he = he->next) { off += IBY2WD; /* @mp cell */ disstring(off, he->rtc->classname); off += IBY2WD; disRTReloc(off, he->rtc); off += IBY2WD; disint(off, he->rtc->off - ltsize); off += IBY2WD; /* account for fields beyond @Class */ off += (he->rtc->n - 4) * IBY2WD; } } } return off;}
#include "java.h"
#include "reloc.h"
/*
* Manage run-time resolution information.
*/
typedef struct RTHash RTHash;
struct RTHash
{
RTClass *rtc;
RTHash *next;
};
static RTHash *rttbl[Hashsize]; /* hash table of referenced classes */
static int nrtclasses; /* no. of classes referenced */
static void
rtappend(RTClass *rtc, RTReloc *rtr)
{
if(rtc->rtr == nil)
rtc->rtr = rtr;
else
rtc->tail->next = rtr;
rtc->tail = rtr;
}
static void
rtprepend(RTClass *rtc, RTReloc *rtr)
{
if(rtc->rtr == nil)
rtc->tail = rtr;
rtr->next = rtc->rtr;
rtc->rtr = rtr;
}
/*
* Add RTReloc entry.
*/
static RTReloc*
addRTReloc(RTClass *rtc, char *field, char *sig, uint flags)
{
RTReloc *rtr;
rtr = Malloc(sizeof(RTReloc));
rtr->field = field;
rtr->sig = sig;
rtr->flags = flags;
rtr->ipatch = Mallocz(sizeof(Ipatch));
rtr->next = nil;
if(field[0] == '@') /* these must go first in the list ! */
rtprepend(rtc, rtr);
else
rtappend(rtc, rtr);
rtc->n += 1;
return rtr;
}
/*
* Allocate a RTClass structure.
*/
static RTClass*
newRTClass(char *s)
{
RTClass *rtc;
rtc = Malloc(sizeof(RTClass));
rtc->classname = s;
rtc->rtr = nil;
rtc->tail = nil;
rtc->n = 0;
rtc->off = 0;
nrtclasses += 1;
/* want the order: @mp, @np, @adt, @Class */
addRTReloc(rtc, RCLASS, nil, 0);
addRTReloc(rtc, RADT, nil, 0);
addRTReloc(rtc, RNP, nil, 0);
addRTReloc(rtc, RMP, nil, 0);
return rtc;
}
/*
* Add RTClass entry for classname.
*/
static RTClass*
addRTClass(char *classname)
{
uint h;
RTHash *he;
h = hashval(classname);
he = Malloc(sizeof(RTHash));
he->rtc = newRTClass(classname);
he->next = rttbl[h];
rttbl[h] = he;
return he->rtc;
}
/*
* Get RTClass entry for classname.
*/
RTClass*
getRTClass(char *classname)
{
RTHash *he;
for(he = rttbl[hashval(classname)]; he; he = he->next) {
if(strcmp(classname, he->rtc->classname) == 0)
return he->rtc;
}
return addRTClass(classname);
}
/*
* Get RTReloc entry. Ignore signature if nil.
*/
RTReloc*
getRTReloc(RTClass *rtc, char *field, char *sig, uint flags)
{
RTReloc *rtr;
uint lowflags;
lowflags = 0;
for(rtr = rtc->rtr; rtr; rtr = rtr->next) {
if(strcmp(rtr->field, field) == 0
&& (sig == nil || strcmp(rtr->sig, sig) == 0)) {
if(rtr->flags >> 16 == 0) {
rtr->flags |= flags;
return rtr;
} else if(rtr->flags >> 16 == flags >> 16)
return rtr;
lowflags = rtr->flags & 0xffff;
}
}
return addRTReloc(rtc, field, sig, flags|lowflags);
}
/*
* Add instruction patch information to RTReloc rtr.
*/
void
RTIpatch(RTReloc *rtr, Inst *i, int operand, int patchkind)
{
addDreloc(i, operand, patchkind);
addIpatch(rtr->ipatch, i, operand, patchkind, SAVEINST);
}
/*
* Fix RTClass and RTReloc 'off' fields to prepare for instruction patch.
*/
void
RTfixoff(int off)
{
RTHash *he;
int i;
if(nrtclasses > 0) {
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he; he = he->next) {
he->rtc->off = off;
off += he->rtc->n * IBY2WD;
}
}
}
}
/*
* Patch instructions for run-time relocation.
*/
void
doRTpatch(void)
{
Addr *a;
RTHash *he;
Ipatch *ip;
RTReloc *rtr;
int i, j;
int off, ltsize;
if(nrtclasses == 0)
return;
ltsize = LTrelocsize();
a = nil;
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he; he = he->next) {
off = he->rtc->off - ltsize;
for(rtr = he->rtc->rtr; rtr; rtr = rtr->next) {
ip = rtr->ipatch;
for(j = 0; j < ip->n; j++) {
switch(ip->pinfo[j] & (0x3 << 2)) {
case PSRC:
a = &ip->i[j]->s;
break;
case PDST:
a = &ip->i[j]->d;
break;
case PMID:
a = &ip->i[j]->m;
break;
}
switch(ip->pinfo[j] & 0x3) {
case PIMM:
a->u.ival = off;
break;
case PSIND:
a->u.offset = off;
break;
case PDIND1:
a->u.b.fi = off;
break;
case PDIND2:
a->u.b.si = off;
break;
}
}
off += IBY2WD;
}
}
}
}
/*
* Size of Module Data space taken by run-time relocation information.
*/
int
RTrelocsize(void)
{
int i;
int n;
RTHash *he;
n = 0;
if(nrtclasses > 0) {
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he; he = he->next)
n += he->rtc->n;
}
}
return n * IBY2WD;
}
/*
* Fix type descriptor for run-time relocation information.
*/
static int RTReloctid;
void
RTrelocdesc(uchar *map, int off)
{
int i;
RTHash *he;
RTReloc *rtr;
if(nrtclasses == 0)
return;
RTReloctid = descid(3*IBY2WD, 1, (uchar*)"\xc0");
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he; he = he->next) {
setbit(map, off); /* @mp cell */
off += 4;
setbit(map, off); /* @np cell */
off += 4;
setbit(map, off); /* @adt cell */
off += 8;
rtr = he->rtc->rtr->next->next->next->next;
while(rtr) {
if(rtr->flags & (Rspecialmp | Rstaticmp))
setbit(map, off);
off += 4;
rtr = rtr->next;
}
}
}
}
/*
* Write RTReloc array to .s file.
*/
static void
asmRTReloc(int off, RTClass *rtc)
{
RTReloc *rtr;
int reloff; /* relative offset for array elements */
if(rtc->n <= 4)
return;
reloff = 0;
asmarray(off, RTReloctid, rtc->n - 4, reloff);
/* skip @mp @np @adt @Class */
rtr = rtc->rtr->next->next->next->next;
while(rtr) {
asmstring(reloff, rtr->field);
reloff += IBY2WD;
if(rtr->sig)
asmstring(reloff, rtr->sig);
reloff += IBY2WD;
asmint(reloff, rtr->flags);
reloff += IBY2WD;
rtr = rtr->next;
}
Bprint(bout, "\tapop\n");
}
/*
* Write RTClass information to .s file.
*/
int
asmRTClass(int off)
{
RTHash *he;
int i;
int ltsize;
if(nrtclasses > 0) {
ltsize = LTrelocsize();
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he; he = he->next) {
off += IBY2WD; /* @mp cell */
asmstring(off, he->rtc->classname);
off += IBY2WD;
asmRTReloc(off, he->rtc);
off += IBY2WD;
asmint(off, he->rtc->off - ltsize);
off += IBY2WD;
/* account for fields beyond @Class */
off += (he->rtc->n - 4) * IBY2WD;
}
}
}
return off;
}
/*
* Write RTReloc array to .dis file.
*/
static void
disRTReloc(int off, RTClass *rtc)
{
RTReloc *rtr;
int reloff; /* relative offset for array elements */
if(rtc->n <= 4)
return;
reloff = 0;
disarray(off, RTReloctid, rtc->n - 4);
/* skip @mp @np @adt @Class */
rtr = rtc->rtr->next->next->next->next;
while(rtr) {
disstring(reloff, rtr->field);
reloff += IBY2WD;
if(rtr->sig)
disstring(reloff, rtr->sig);
reloff += IBY2WD;
disint(reloff, rtr->flags);
reloff += IBY2WD;
rtr = rtr->next;
}
disapop();
}
/*
* Write RTClass information to .dis file.
*/
int
disRTClass(int off)
{
RTHash *he;
int i;
int ltsize;
if(nrtclasses > 0) {
ltsize = LTrelocsize();
for(i = 0; i < Hashsize; i++) {
for(he = rttbl[i]; he; he = he->next) {
off += IBY2WD; /* @mp cell */
disstring(off, he->rtc->classname);
off += IBY2WD;
disRTReloc(off, he->rtc);
off += IBY2WD;
disint(off, he->rtc->off - ltsize);
off += IBY2WD;
/* account for fields beyond @Class */
off += (he->rtc->n - 4) * IBY2WD;
}
}
}
return off;
}