summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--elf2exe/elf2exe.c73
-rw-r--r--elf2exe/rel32.asm18
2 files changed, 72 insertions, 19 deletions
diff --git a/elf2exe/elf2exe.c b/elf2exe/elf2exe.c
index ba0e5f8..c2204b1 100644
--- a/elf2exe/elf2exe.c
+++ b/elf2exe/elf2exe.c
@@ -1,6 +1,8 @@
#include "elf2exe.h"
#include "elf32.h"
+#define REL32_MIN_STACK 256
+
const char *_progname;
static inline const void *dptr(const struct fileinfo *in, Elf32_Off off)
@@ -335,7 +337,7 @@ static int process_file(const char *infile, const char *outfile)
Elf32_Half e_machine;
struct dyninfo di;
struct mzhdr *mzhdr;
- size_t hdrsize, filesize, datasize, bssmem, reqmem;
+ size_t hdrsize, filesize, datasize, endmem, reqmem;
struct exe_relocs er[3];
size_t i;
@@ -417,15 +419,10 @@ static int process_file(const char *infile, const char *outfile)
filesize = (filesize + 15) & ~15;
/*
- * This is how much loaded data is actually present in the file;
- * this may be larger than e2e_filesize/e2e_memsize due to padding
- * or added stubs.
+ * End of mandatory and requested memory allocations, respectively.
*/
- datasize = filesize - hdrsize;
- bssmem = (di.e2e_memsize < datasize) ? 0 : di.e2e_memsize - datasize;
- reqmem = di.e2e_optmem + bssmem;
- if (reqmem > 0xffff0)
- reqmem = 0xffff0; /* Can't ask for more than this... */
+ endmem = di.e2e_memsize;
+ reqmem = endmem + di.e2e_optmem;
/* Open output file */
out = map_file(outfile, filesize);
@@ -439,8 +436,6 @@ static int process_file(const char *infile, const char *outfile)
putle(&mzhdr->blocks, (filesize + 0x1ff) >> 9);
putle(&mzhdr->nrelocs, er[0].nrelocs);
putle(&mzhdr->hdrparas, hdrsize >> 4);
- putle(&mzhdr->bssparas, (bssmem + 15) >> 4);
- putle(&mzhdr->maxparas, (reqmem + 15) >> 4);
putle(&mzhdr->ss, di.e2e_stkseg >> 4);
putle(&mzhdr->sp, di.e2e_stkbase + di.e2e_stksize - di.e2e_stkseg);
putle(&mzhdr->ip, getle(eh->e_entry) - di.e2e_entseg);
@@ -452,11 +447,16 @@ static int process_file(const char *infile, const char *outfile)
struct rel32_hdr {
uint16_t ip;
uint16_t cs;
+ uint16_t sp;
+ uint16_t ss;
uint16_t nrelocs;
} *hdr;
size_t where = er[1].fileoffs - rel32_size;
+ size_t totalsize = rel32_size +
+ er[1].nrelocs * sizeof(uint32_t);
+ size_t minstackptr;
- if (rel32_size + er[1].nrelocs * sizeof(uint32_t) > 0x19999) {
+ if (totalsize > 0x10000) {
fprintf(stderr,
"%s: %s: fatal: too many R_386_RELATIVE relocations for loader stub\n",
_progname, infile);
@@ -467,14 +467,57 @@ static int process_file(const char *infile, const char *outfile)
- 1;
memcpy((char *)out->wr + where, rel32_code, rel32_size);
- hdr->ip = mzhdr->ip; /* Already littleendian */
- hdr->cs = mzhdr->cs; /* Already littleendian */
- putle(&hdr->nrelocs, er[1].nrelocs);
+ /* These values are already littleendian */
+ hdr->ip = mzhdr->ip;
+ hdr->cs = mzhdr->cs;
+ hdr->sp = mzhdr->sp;
+ hdr->ss = mzhdr->ss;
+ putle(&hdr->nrelocs, er[1].nrelocs);
putle(&mzhdr->ip, 0);
putle(&mzhdr->cs, (where - hdrsize) >> 4);
+
+ /* Watch out: are we clobbering the default stack? */
+ minstackptr = where - hdrsize + totalsize + REL32_MIN_STACK;
+ if (minstackptr > di.e2e_stkbase + di.e2e_stksize) {
+ uint32_t stkbase, stksize;
+
+ minstackptr = (minstackptr + 15) & ~15;
+ if (endmem < minstackptr)
+ endmem = minstackptr;
+
+ stkbase = minstackptr - REL32_MIN_STACK;
+ stksize = REL32_MIN_STACK;
+
+ putle(&mzhdr->ss, stkbase >> 4);
+ putle(&mzhdr->sp, stksize);
+ }
}
+ /*
+ * This is how much loaded data is actually present in the file;
+ * this may be larger than e2e_filesize/e2e_memsize due to padding
+ * or added stubs.
+ */
+ datasize = filesize - hdrsize;
+
+ if (endmem < datasize)
+ endmem = datasize;
+ endmem = (endmem + 15) & ~15;
+ if (endmem > 0xffff0) {
+ fprintf(stderr, "%s: %s: output file too big\n",
+ _progname, infile);
+ goto err;
+ }
+ putle(&mzhdr->bssparas, (endmem - datasize) >> 4);
+
+ if (reqmem < endmem)
+ reqmem = endmem;
+ reqmem = (reqmem + 15) & ~15;
+ if (reqmem > 0xffff0)
+ reqmem = 0xffff0; /* Can't ask for more than this... */
+ putle(&mzhdr->maxparas, (reqmem - datasize) >> 4);
+
/* Copy relocations */
for (i = 0; er[i].r_type != R_386_NONE; i++) {
memcpy((char *)out->wr + er[i].fileoffs,
diff --git a/elf2exe/rel32.asm b/elf2exe/rel32.asm
index 2b743ac..4939b32 100644
--- a/elf2exe/rel32.asm
+++ b/elf2exe/rel32.asm
@@ -29,10 +29,11 @@ _start:
mov ax,10h
mov bx,es ; = PSP segment
add bx,ax ; = load base segment
- add [si+(entry.cs - reloc_tbl)],bx
+ add [si+entry.cs-reloc_tbl],bx
+ add [si+stack.ss-reloc_tbl],bx
mul bx ; Convert to a linear addr in DX:AX
- mov cx,[si+(nrelocs - reloc_tbl)]
+ mov cx,[si+nrelocs-reloc_tbl]
; DX:AX = absolute base address
; BX = segment base address
@@ -71,16 +72,25 @@ _start:
pop ds
; This aligns the following instruction to an address which
- ; is congruent with 1 mod 4
- times (1 - ($ - $$)) & 3 nop
+ ; is congruent with 3 mod 4
+ times (3 - ($ - $$)) & 3 nop
+
+ mov ss,[cs:stack.ss]
+ mov sp,[cs:stack.sp]
jmp 0:0
; This is the short header than needs to be filled in
entry: ; Real entry point (vs load address)
.ip: equ $-4
.cs: equ $-2
+stack: ; Program stack, may differ ours
+.sp: dw 0
+.ss: dw 0
nrelocs: ; Relocation count
dw 0
; This address will be aligned by 4
+%if ($ - $$) & 3
+ %error "reloc_tbl alignment error"
+%endif
reloc_tbl: ; Follows...