summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2019-08-05 11:27:53 -0700
committerH. Peter Anvin <hpa@zytor.com>2019-08-05 11:27:53 -0700
commitcb218472ac69610b1054e3639fe97a6e1a5330f5 (patch)
tree46a7343b8a285a61e9d6091d631bc068b166f36a
parentbb0215d7a6e2de0aa751487cd91538846f540728 (diff)
downloadsamples-cb218472ac69610b1054e3639fe97a6e1a5330f5.tar.gz
samples-cb218472ac69610b1054e3639fe97a6e1a5330f5.tar.xz
samples-cb218472ac69610b1054e3639fe97a6e1a5330f5.zip
elf2exe: when adding the 32-bit relocation stub, check the stackHEADmaster
When adding the 32-bit relocation stub, we might end up overlapping the intended stack segment. In that case, set up a temporary stack just beyond the end of the relocation data, and possibly adjust the memory sizes accordingly. Move the memory size calculations down and make them uniformly addresses, not incremental numbers, as it turns out subtraction at the end is way easier in the end. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-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...