sectindex = relo->or_sect - S_MIN;
emit = getemit(head, sects, sectindex);
}
- relocate(head, emit, names, relo);
+ relocate(head, emit, names, relo, 0L);
relo++;
}
} else {
for (sectindex = 0; sectindex < head->oh_nsect; sectindex++) {
if (sects[sectindex].os_flen) {
+ wrt_nulls(sectindex, zeros[sectindex]);
+ zeros[sectindex] = 0;
emit = getemit(head, sects, sectindex);
- nrelo = head->oh_nrelo; startrelo(head);
- while (nrelo--) {
+ if (emit) {
+ nrelo = head->oh_nrelo; startrelo(head);
+ while (nrelo--) {
relo = nextrelo();
if (relo->or_sect - S_MIN == sectindex) {
- relocate(head,emit,names,relo);
+ relocate(head,emit,names,relo,0L);
/*
* Write out the (probably changed)
* relocation information.
if (flagword & RFLAG)
wr_relo(relo, 1);
}
+ }
+ wrt_emit(emit, sectindex,
+ sects[sectindex].os_flen);
}
- wrt_nulls(sectindex, zeros[sectindex]);
- zeros[sectindex] = 0;
- wrt_emit(emit, sectindex, sects[sectindex].os_flen);
+ else {
+ long sz = sects[sectindex].os_flen;
+ long sf = 0;
+ long blksz;
+ char *getblk();
+
+ emit = getblk(sz, &blksz, sectindex);
+ while (sz) {
+ long sz2 = sz > blksz ? blksz : sz;
+
+ rd_emit(emit, sz2);
+ nrelo = head->oh_nrelo; startrelo(head);
+ while (nrelo--) {
+ relo = nextrelo();
+ if (relo->or_sect-S_MIN==sectindex
+ &&
+ relo->or_addr >= sf
+ &&
+ relo->or_addr < sf + sz2){
+ relocate(head,emit,names,relo,
+ sf);
+ /*
+ * Write out the (probably changed)
+ * relocation information.
+ */
+ if (flagword & RFLAG)
+ wr_relo(relo, 1);
+ }
+ }
+ wrt_emit(emit, sectindex, sz2);
+ sz -= sz2;
+ sf += sz2;
+ }
+ }
+ endemit(emit);
}
zeros[sectindex] += sects[sectindex].os_size -
sects[sectindex].os_flen;
- /*
- * XXX We should be able to free the emitted bytes.
- */
}
}
}
mems[ALLOMODL].mem_left = 32 * K;
mems[ALLORANL].mem_left = 4 * K;
#else
+#undef INCRSIZE
+#define INCRSIZE 256
mems[ALLOEMIT + 0].mem_left = 8 * K;
mems[ALLOEMIT + 1].mem_left = 2 * K;
mems[ALLOEMIT + 2].mem_left = 4 * K;
inc != incr ||
BASE + inc < BASE ||
(int) brk(BASE + inc) == -1) {
- refused = refused && refused > incr ? incr : refused;
+ if (!refused || refused > incr)
+ refused = incr;
return -1;
}
BASE = sbrk(0);
/*
* Allocate an extra block of `incr' bytes and move all pieces with index
- * higher than `piece' up with the size of the block. Return whether the
- * allocate succeeded.
+ * higher than `piece' up with the size of the block.
+ * Move up as much as possible, if "incr" fails.
*/
-static bool
+static ind_t
move_up(piece, incr)
register int piece;
register ind_t incr;
register struct memory *mem;
debug("move_up(%d, %d)\n", piece, (int)incr, 0, 0);
- if (sbreak(incr) == -1)
- return FALSE;
+ while (incr > 0 && sbreak(incr) == -1)
+ incr -= INCRSIZE;
+ if (incr <= 0) {
+ incr = 0;
+ return (ind_t) 0;
+ }
for (mem = &mems[NMEMS - 1]; mem > &mems[piece]; mem--)
copy_up(mem, incr);
mems[piece].mem_left += incr;
- return TRUE;
+ return incr;
}
extern int passnumber;
if (size != (ind_t)size)
return BADOFF;
- while (left + incr < size)
- incr += INCRSIZE;
-
+ if (size - left > 0)
+ incr = ((size - left + (INCRSIZE - 1)) / INCRSIZE) * INCRSIZE;
+
if (incr == 0 ||
- (incr < left + full && move_up(piece, left + full)) ||
- move_up(piece, incr) ||
+ (incr < left + full && (incr -= move_up(piece, left + full)) <= 0) ||
+ move_up(piece, incr) == incr ||
compact(piece, size, alloctype)) {
mems[piece].mem_full += size;
mems[piece].mem_left -= size;
{
register ind_t off;
- if ((off = alloc(piece, size)) == BADOFF)
- return (char *)0;
+ if ((off = alloc(piece, size)) == BADOFF) {
+ int sv = alloctype;
+
+ alloctype = FORCED;
+ off = alloc(piece, size);
+ alloctype = sv;
+ if (off == BADOFF)
+ return (char *)0;
+ }
return address(piece, off);
}
+core_free(piece, p)
+ int piece;
+ char *p;
+{
+ char *q = address(piece, mems[piece].mem_full);
+
+ assert(p < q);
+ mems[piece].mem_full -= ((ind_t)q - (ind_t)p);
+ mems[piece].mem_left += ((ind_t)q - (ind_t)p);
+}
+
/*
* Reset index into piece of memory for modules and
* take care that the allocated pieces will not be moved.
* which the header is pointed to by `head'. Relocation is relative to the
* names in `names'; `relo' tells how to relocate.
*/
-relocate(head, emit, names, relo)
+relocate(head, emit, names, relo, off)
struct outhead *head;
char *emit;
struct outname names[];
struct outrelo *relo;
+ long off;
{
long valu;
int sectindex = relo->or_sect - S_MIN;
/*
* Pick up previous value at location to be relocated.
*/
- valu = getvalu(emit + relo->or_addr, relo->or_type);
+ valu = getvalu(emit + (relo->or_addr - off), relo->or_type);
/*
* Or_nami is an index in the name table of the considered module.
* The name of which it is an index can be:
/*
* Now put the value back.
*/
- putvalu(valu, emit + relo->or_addr, relo->or_type);
+ putvalu(valu, emit + (relo->or_addr - off), relo->or_type);
/*
* We must change the offset within the section of the value to be
if (!incore) {
ret = core_alloc(ALLOMODL, sects[sectindex].os_flen);
if (ret == (char *)0)
- fatal("no space for section contents");
+ return 0;
rd_outsect(sectindex);
rd_emit(ret, sects[sectindex].os_flen);
return ret;
off = *((ind_t *)(modulbase + IND_EMIT(*head)) + sectindex);
return address(ALLOEMIT + sectindex, off);
}
+
+char *
+getblk(totalsz, pblksz, sectindex)
+ long totalsz;
+ long *pblksz;
+ int sectindex;
+{
+ char *ret;
+ long sz = (1L << 30);
+
+ assert(!incore);
+
+ while (sz >= totalsz) sz >>= 1;
+ while (sz) {
+ ret = core_alloc(ALLOMODL, sz);
+ if (ret != (char *) 0) {
+ rd_outsect(sectindex);
+ *pblksz = sz;
+ return ret;
+ }
+ sz >>= 1;
+ }
+ fatal("no space for section contents");
+ return (char *) 0;
+}
+
+endemit(emit)
+ char *emit;
+{
+ core_free(ALLOMODL, emit);
+}