265 lines
6.4 KiB
C
265 lines
6.4 KiB
C
|
/* $Id: exedump.c,v 1.1 1993/06/09 03:28:10 root Exp root $
|
|||
|
*/
|
|||
|
/*
|
|||
|
* Copyright Robert J. Amstadt, 1993
|
|||
|
*/
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <sys/types.h>
|
|||
|
#include <sys/stat.h>
|
|||
|
#include <fcntl.h>
|
|||
|
#include <unistd.h>
|
|||
|
#include <linux/unistd.h>
|
|||
|
#include <linux/head.h>
|
|||
|
#include <linux/mman.h>
|
|||
|
#include <linux/a.out.h>
|
|||
|
#include <linux/ldt.h>
|
|||
|
#include <errno.h>
|
|||
|
#include "neexe.h"
|
|||
|
#include "segmem.h"
|
|||
|
#include "prototypes.h"
|
|||
|
|
|||
|
struct segment_descriptor_s *SelectorTable;
|
|||
|
int SelectorTableLength;
|
|||
|
int EnvironmentSelectorIdx;
|
|||
|
int PSPSelectorIdx;
|
|||
|
unsigned short PSPSelector;
|
|||
|
|
|||
|
extern void KERNEL_Ordinal_102();
|
|||
|
extern void UNIXLIB_Ordinal_0();
|
|||
|
|
|||
|
|
|||
|
/**********************************************************************
|
|||
|
* GetDOSEnvironment
|
|||
|
*/
|
|||
|
void *
|
|||
|
GetDOSEnvironment()
|
|||
|
{
|
|||
|
return SelectorTable[EnvironmentSelectorIdx].base_addr;
|
|||
|
}
|
|||
|
|
|||
|
/**********************************************************************
|
|||
|
* CreateEnvironment
|
|||
|
*/
|
|||
|
void
|
|||
|
CreateEnvironment(int sel_idx, struct segment_descriptor_s *s, FILE *zfile)
|
|||
|
{
|
|||
|
char *p;
|
|||
|
|
|||
|
EnvironmentSelectorIdx = sel_idx;
|
|||
|
|
|||
|
/*
|
|||
|
* Create memory to hold environment.
|
|||
|
*/
|
|||
|
s->flags = NE_SEGFLAGS_DATA;
|
|||
|
s->selector = (sel_idx << 3) | 0x0007;
|
|||
|
s->length = PAGE_SIZE;
|
|||
|
s->base_addr = (void *) mmap((char *) (s->selector << 16),
|
|||
|
PAGE_SIZE,
|
|||
|
PROT_EXEC | PROT_READ | PROT_WRITE,
|
|||
|
MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
|
|||
|
|
|||
|
/*
|
|||
|
* Fill environment with meaningless babble.
|
|||
|
*/
|
|||
|
p = (char *) s->base_addr;
|
|||
|
strcpy(p, "PATH=C:\\WINDOWS");
|
|||
|
p += strlen(p) + 1;
|
|||
|
*p++ = '\0';
|
|||
|
*p++ = 11;
|
|||
|
*p++ = 0;
|
|||
|
strcpy(p, "C:\\TEST.EXE");
|
|||
|
|
|||
|
/*
|
|||
|
* Create entry in LDT for this segment.
|
|||
|
*/
|
|||
|
if (set_ldt_entry(sel_idx, (unsigned long) s->base_addr, s->length, 0,
|
|||
|
MODIFY_LDT_CONTENTS_DATA, 0, 0) < 0)
|
|||
|
{
|
|||
|
myerror("Could not create LDT entry for environment");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**********************************************************************
|
|||
|
* CreatePSP
|
|||
|
*/
|
|||
|
void
|
|||
|
CreatePSP(int sel_idx, struct segment_descriptor_s *s, FILE *zfile)
|
|||
|
{
|
|||
|
struct dos_psp_s *psp;
|
|||
|
unsigned short *usp;
|
|||
|
|
|||
|
PSPSelectorIdx = sel_idx;
|
|||
|
|
|||
|
/*
|
|||
|
* Create memory to hold PSP.
|
|||
|
*/
|
|||
|
s->flags = NE_SEGFLAGS_DATA;
|
|||
|
s->selector = (sel_idx << 3) | 0x0007;
|
|||
|
s->length = PAGE_SIZE;
|
|||
|
s->base_addr = (void *) mmap((char *) (s->selector << 16),
|
|||
|
PAGE_SIZE,
|
|||
|
PROT_EXEC | PROT_READ | PROT_WRITE,
|
|||
|
MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
|
|||
|
|
|||
|
/*
|
|||
|
* Fill PSP
|
|||
|
*/
|
|||
|
PSPSelector = s->selector;
|
|||
|
psp = (struct dos_psp_s *) s->base_addr;
|
|||
|
psp->pspInt20 = 0x20cd;
|
|||
|
psp->pspDispatcher[0] = 0x9a;
|
|||
|
usp = (unsigned short *) &psp->pspDispatcher[1];
|
|||
|
*usp = (unsigned short) KERNEL_Ordinal_102;
|
|||
|
*(usp + 1) = 0x23;
|
|||
|
psp->pspTerminateVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
|
|||
|
psp->pspControlCVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
|
|||
|
psp->pspCritErrorVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
|
|||
|
psp->pspEnvironment = SelectorTable[EnvironmentSelectorIdx].selector;
|
|||
|
psp->pspCommandTailCount = 1;
|
|||
|
strcpy(psp->pspCommandTail, "\r");
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Create entry in LDT for this segment.
|
|||
|
*/
|
|||
|
if (set_ldt_entry(sel_idx, (unsigned long) s->base_addr, s->length, 0,
|
|||
|
MODIFY_LDT_CONTENTS_DATA, 0, 0) < 0)
|
|||
|
{
|
|||
|
myerror("Could not create LDT entry for PSP");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**********************************************************************
|
|||
|
* CreateSelectors
|
|||
|
*/
|
|||
|
struct segment_descriptor_s *
|
|||
|
CreateSelectors(int fd, struct ne_segment_table_entry_s *seg_table,
|
|||
|
struct ne_header_s *ne_header)
|
|||
|
{
|
|||
|
struct segment_descriptor_s *selectors, *s;
|
|||
|
int contents, read_only;
|
|||
|
int i;
|
|||
|
int status;
|
|||
|
FILE * zfile;
|
|||
|
int old_length;
|
|||
|
|
|||
|
/*
|
|||
|
* Allocate memory for the table to keep track of all selectors.
|
|||
|
*/
|
|||
|
SelectorTableLength = ne_header->n_segment_tab + 2;
|
|||
|
selectors = malloc(SelectorTableLength * sizeof(*selectors));
|
|||
|
if (selectors == NULL)
|
|||
|
return NULL;
|
|||
|
SelectorTable = selectors;
|
|||
|
|
|||
|
/*
|
|||
|
* Step through the segment table in the exe header.
|
|||
|
*/
|
|||
|
s = selectors;
|
|||
|
zfile = fopen("/dev/zero","r");
|
|||
|
for (i = 0; i < ne_header->n_segment_tab; i++, s++)
|
|||
|
{
|
|||
|
/*
|
|||
|
* Store the flags in our table.
|
|||
|
*/
|
|||
|
s->flags = seg_table[i].seg_flags;
|
|||
|
s->selector = (i << 3) | 0x0007;
|
|||
|
|
|||
|
/*
|
|||
|
* Is there an image for this segment in the file?
|
|||
|
*/
|
|||
|
if (seg_table[i].seg_data_offset == 0)
|
|||
|
{
|
|||
|
/*
|
|||
|
* No image in exe file, let's allocate some memory for it.
|
|||
|
*/
|
|||
|
s->length = seg_table[i].min_alloc;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/*
|
|||
|
* Image in file, let's just point to the image in memory.
|
|||
|
*/
|
|||
|
s->length = seg_table[i].seg_data_length;
|
|||
|
}
|
|||
|
|
|||
|
if (s->length == 0)
|
|||
|
s->length = 0x10000;
|
|||
|
old_length = s->length;
|
|||
|
|
|||
|
/*
|
|||
|
* If this is the automatic data segment, its size must be adjusted.
|
|||
|
* First we need to check for local heap. Second we nee to see if
|
|||
|
* this is also the stack segment.
|
|||
|
*/
|
|||
|
if (i + 1 == ne_header->auto_data_seg)
|
|||
|
{
|
|||
|
s->length += ne_header->local_heap_length;
|
|||
|
|
|||
|
if (i + 1 == ne_header->ss)
|
|||
|
{
|
|||
|
s->length += ne_header->stack_length;
|
|||
|
ne_header->sp = s->length;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Is this a DATA or CODE segment?
|
|||
|
*/
|
|||
|
read_only = 0;
|
|||
|
if (s->flags & NE_SEGFLAGS_DATA)
|
|||
|
{
|
|||
|
contents = MODIFY_LDT_CONTENTS_DATA;
|
|||
|
if (s->flags & NE_SEGFLAGS_READONLY)
|
|||
|
read_only = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
contents = MODIFY_LDT_CONTENTS_CODE;
|
|||
|
if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
|
|||
|
read_only = 1;
|
|||
|
}
|
|||
|
s->base_addr =
|
|||
|
(void *) mmap((char *) (s->selector << 16),
|
|||
|
(s->length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
|
|||
|
PROT_EXEC | PROT_READ | PROT_WRITE,
|
|||
|
MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
|
|||
|
if (seg_table[i].seg_data_offset != 0)
|
|||
|
{
|
|||
|
/*
|
|||
|
* Image in file.
|
|||
|
*/
|
|||
|
status = lseek(fd, seg_table[i].seg_data_offset * 512, SEEK_SET);
|
|||
|
if(read(fd, s->base_addr, old_length) != old_length)
|
|||
|
myerror("Unable to read segment from file");
|
|||
|
}
|
|||
|
/*
|
|||
|
* Create entry in LDT for this segment.
|
|||
|
*/
|
|||
|
if (set_ldt_entry(i, (unsigned long) s->base_addr, s->length, 0,
|
|||
|
contents, read_only, 0) < 0)
|
|||
|
{
|
|||
|
free(selectors);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
/*
|
|||
|
* If this is the automatic data segment, then we must initialize
|
|||
|
* the local heap.
|
|||
|
*/
|
|||
|
if (i + 1 == ne_header->auto_data_seg)
|
|||
|
{
|
|||
|
HEAP_LocalInit(s->base_addr + old_length,
|
|||
|
ne_header->local_heap_length);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
CreateEnvironment(i++, s++, zfile);
|
|||
|
CreatePSP(i++, s++, zfile);
|
|||
|
|
|||
|
fclose(zfile);
|
|||
|
|
|||
|
return selectors;
|
|||
|
}
|