80 lines
1.9 KiB
C
80 lines
1.9 KiB
C
#include <system.h>
|
|
#include <out.h>
|
|
#include "back.h"
|
|
|
|
/* Solve the local references.
|
|
*/
|
|
|
|
#define seg_index( s) ( nname - SEGBSS - 1 + s)
|
|
|
|
long get4();
|
|
extern short get2();
|
|
extern char get1();
|
|
|
|
|
|
do_local_relocation()
|
|
|
|
/* Check if this reference is solvable. External references contain
|
|
* -1 in 'on_valu'.
|
|
* Also remove useless relocation structures.
|
|
*/
|
|
{
|
|
register struct outrelo *rp;
|
|
int diff = 0;
|
|
|
|
for ( rp = reloc_info; rp < relo; rp++) {
|
|
register struct outname *np = &symbol_table[rp->or_nami];
|
|
int olddiff = diff;
|
|
|
|
if ( np->on_valu != -1 && ! (np->on_type & S_COM)) {
|
|
register long oldval,newval;
|
|
register char *sect;
|
|
|
|
switch( rp->or_sect - S_MIN) {
|
|
case SEGTXT:
|
|
sect = text_area;
|
|
if ((rp->or_type & RELPC) &&
|
|
(np->on_type & S_TYP) - S_MIN == SEGTXT) {
|
|
diff++;
|
|
}
|
|
break;
|
|
case SEGCON:
|
|
sect = data_area;
|
|
break;
|
|
default:
|
|
fprint( STDERR,
|
|
"do_local_relo(): bad section %d\n",
|
|
rp->or_sect - S_MIN);
|
|
break;
|
|
}
|
|
|
|
if ( rp->or_type & RELO4) {
|
|
oldval = get4( sect, rp->or_addr);
|
|
newval = oldval + np->on_valu;
|
|
put4( sect, rp->or_addr, newval);
|
|
}
|
|
else if ( rp->or_type & RELO2) {
|
|
oldval = (long) get2( sect, rp->or_addr);
|
|
newval = oldval + np->on_valu;
|
|
put2( sect, rp->or_addr, (int) newval);
|
|
}
|
|
else if ( rp->or_type & RELO1) {
|
|
oldval = (long) get1( sect, rp->or_addr);
|
|
newval = oldval + np->on_valu;
|
|
put1( sect, rp->or_addr, (char) newval);
|
|
}
|
|
else
|
|
print( STDERR, "do_relo() : bad relocation size\n");
|
|
rp->or_nami = seg_index((np->on_type & S_TYP) - S_MIN);
|
|
/* print(
|
|
"reloc %s adrr=%ld sect=%ld oldval=%ld newval=%ld def = %ld\n",
|
|
np->on_foff+string_area, rp->or_addr, rp->or_sect-S_MIN, oldval, newval, np->on_valu);
|
|
*/
|
|
}
|
|
if (diff && diff == olddiff) {
|
|
rp[-diff] = rp[0];
|
|
}
|
|
}
|
|
relo -= diff;
|
|
}
|