Skip to content

Commit

Permalink
Deal with NE binaries with a stack size of zero.
Browse files Browse the repository at this point in the history
Microsoft C 5.1's CL.EXE does this. This is valid in the NE spec.
  • Loading branch information
icculus committed Jun 8, 2018
1 parent d82dd93 commit 36dedda
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib2ine.h
Expand Up @@ -288,6 +288,7 @@ typedef struct LxLoaderState
int trace_native;
int trace_events;
uint8 main_tib_selector;
uint32 mainstacksize;
uint16 original_cs;
uint16 original_ds;
uint16 original_es;
Expand Down
16 changes: 12 additions & 4 deletions lx_loader.c
Expand Up @@ -916,7 +916,7 @@ static __attribute__((noreturn)) void runNeModule(LxModule *lxmod)
// The stack at startup should have, pushed in this order: cmdline offset, env segment, far* to top of stack, far* to bottom of stack.
// Microsoft C 5.1 wants things in registers (maybe Watcom does too, elsewhere, and I'm reading it wrong?),
// so we do both.
const uint16 stacksize = lxmod->header.ne.stack_size ? lxmod->header.ne.stack_size : 0x10000;
const uint16 stacksize = (uint16) GLoaderState.mainstacksize;
const uint16 ss = (lxmod->esp >> 16) & 0xFFFF; // stack segment
const uint32 env1616 = lxConvert32to1616(GLoaderState.pib.pib_pchenv); // this is meant to be aligned to a segment.
const uint16 cmdlineoffset = env1616 & 0xFFFF;
Expand Down Expand Up @@ -1771,6 +1771,7 @@ static LxModule *loadLxModule(const char *fname, const uint8 *origexe, uint8 *ex
const uint32 stackbase = (uint32) ((size_t)lxmmap->addr);
const uint32 stacksize = (uint32) lxmmap->size;
retval->esp = lx->esp + stackbase;
GLoaderState.mainstacksize = stacksize;

// This needs to be set up now, so it's available to any library
// init code that runs in LX land.
Expand Down Expand Up @@ -2219,8 +2220,6 @@ static LxModule *loadNeModule(const char *fname, const uint8 *origexe, uint8 *ex
retval->eip = (lxSelectorToSegment(retval->mmaps[ne->reg_cs-1].alias) << 16) | ne->reg_ip;

if (!isDLL) {
FIXME("ne->stack_size can be zero if there's a separate stack segment defined"); assert(ne->stack_size != 0);

/* "If SS equals the automatic data segment and SP equals
zero, the stack pointer is set to the top of the automatic data
segment just below the additional heap area." */
Expand All @@ -2233,10 +2232,19 @@ static LxModule *loadNeModule(const char *fname, const uint8 *origexe, uint8 *ex
}
retval->esp = (lxSelectorToSegment(retval->mmaps[ne->reg_ss-1].alias) << 16) | (sp ? sp : 0xFFFF);

uint16 stacksize = ne->stack_size;
if (stacksize == 0) {
stacksize = sp;
if (sp && (ne->reg_ss == ne->auto_data_segment)) {
stacksize -= autodataseg->size;
}
}
GLoaderState.mainstacksize = stacksize;

// This needs to be set up now, so it's available to any library
// init code that runs in LX land.
void *topofstack = (void *) (((size_t) retval->mmaps[ne->reg_ss].addr) + sp);
GLoaderState.initOs2Tib(GLoaderState.main_tibspace, topofstack, ne->stack_size, 0);
GLoaderState.initOs2Tib(GLoaderState.main_tibspace, topofstack, stacksize, 0);
GLoaderState.main_tib_selector = GLoaderState.setOs2Tib(GLoaderState.main_tibspace);
} // if

Expand Down

0 comments on commit 36dedda

Please sign in to comment.