1 /* $Id: exedump.c,v 1.1 1993/06/09 03:28:10 root Exp root $
4 * Copyright Robert J. Amstadt, 1993
13 #include <linux/unistd.h>
14 #include <linux/head.h>
15 #include <linux/mman.h>
16 #include <linux/a.out.h>
17 #include <linux/ldt.h>
21 #include "prototypes.h"
23 struct segment_descriptor_s *SelectorTable;
24 int SelectorTableLength;
25 int EnvironmentSelectorIdx;
27 unsigned short PSPSelector;
29 extern void KERNEL_Ordinal_102();
30 extern void UNIXLIB_Ordinal_0();
33 /**********************************************************************
39 return SelectorTable[EnvironmentSelectorIdx].base_addr;
42 /**********************************************************************
46 CreateEnvironment(int sel_idx, struct segment_descriptor_s *s, FILE *zfile)
50 EnvironmentSelectorIdx = sel_idx;
53 * Create memory to hold environment.
55 s->flags = NE_SEGFLAGS_DATA;
56 s->selector = (sel_idx << 3) | 0x0007;
57 s->length = PAGE_SIZE;
58 s->base_addr = (void *) mmap((char *) (s->selector << 16),
60 PROT_EXEC | PROT_READ | PROT_WRITE,
61 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
64 * Fill environment with meaningless babble.
66 p = (char *) s->base_addr;
67 strcpy(p, "PATH=C:\\WINDOWS");
72 strcpy(p, "C:\\TEST.EXE");
75 * Create entry in LDT for this segment.
77 if (set_ldt_entry(sel_idx, (unsigned long) s->base_addr, s->length, 0,
78 MODIFY_LDT_CONTENTS_DATA, 0, 0) < 0)
80 myerror("Could not create LDT entry for environment");
84 /**********************************************************************
88 CreatePSP(int sel_idx, struct segment_descriptor_s *s, FILE *zfile)
90 struct dos_psp_s *psp;
93 PSPSelectorIdx = sel_idx;
96 * Create memory to hold PSP.
98 s->flags = NE_SEGFLAGS_DATA;
99 s->selector = (sel_idx << 3) | 0x0007;
100 s->length = PAGE_SIZE;
101 s->base_addr = (void *) mmap((char *) (s->selector << 16),
103 PROT_EXEC | PROT_READ | PROT_WRITE,
104 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
109 PSPSelector = s->selector;
110 psp = (struct dos_psp_s *) s->base_addr;
111 psp->pspInt20 = 0x20cd;
112 psp->pspDispatcher[0] = 0x9a;
113 usp = (unsigned short *) &psp->pspDispatcher[1];
114 *usp = (unsigned short) KERNEL_Ordinal_102;
116 psp->pspTerminateVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
117 psp->pspControlCVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
118 psp->pspCritErrorVector = 0x00230000 | ((int) UNIXLIB_Ordinal_0 & 0xffff);
119 psp->pspEnvironment = SelectorTable[EnvironmentSelectorIdx].selector;
120 psp->pspCommandTailCount = 1;
121 strcpy(psp->pspCommandTail, "\r");
125 * Create entry in LDT for this segment.
127 if (set_ldt_entry(sel_idx, (unsigned long) s->base_addr, s->length, 0,
128 MODIFY_LDT_CONTENTS_DATA, 0, 0) < 0)
130 myerror("Could not create LDT entry for PSP");
134 /**********************************************************************
137 struct segment_descriptor_s *
138 CreateSelectors(int fd, struct ne_segment_table_entry_s *seg_table,
139 struct ne_header_s *ne_header)
141 struct segment_descriptor_s *selectors, *s;
142 int contents, read_only;
149 * Allocate memory for the table to keep track of all selectors.
151 SelectorTableLength = ne_header->n_segment_tab + 2;
152 selectors = malloc(SelectorTableLength * sizeof(*selectors));
153 if (selectors == NULL)
155 SelectorTable = selectors;
158 * Step through the segment table in the exe header.
161 zfile = fopen("/dev/zero","r");
162 for (i = 0; i < ne_header->n_segment_tab; i++, s++)
165 * Store the flags in our table.
167 s->flags = seg_table[i].seg_flags;
168 s->selector = (i << 3) | 0x0007;
171 * Is there an image for this segment in the file?
173 if (seg_table[i].seg_data_offset == 0)
176 * No image in exe file, let's allocate some memory for it.
178 s->length = seg_table[i].min_alloc;
183 * Image in file, let's just point to the image in memory.
185 s->length = seg_table[i].seg_data_length;
190 old_length = s->length;
193 * If this is the automatic data segment, its size must be adjusted.
194 * First we need to check for local heap. Second we nee to see if
195 * this is also the stack segment.
197 if (i + 1 == ne_header->auto_data_seg)
199 s->length += ne_header->local_heap_length;
201 if (i + 1 == ne_header->ss)
203 s->length += ne_header->stack_length;
204 ne_header->sp = s->length;
209 * Is this a DATA or CODE segment?
212 if (s->flags & NE_SEGFLAGS_DATA)
214 contents = MODIFY_LDT_CONTENTS_DATA;
215 if (s->flags & NE_SEGFLAGS_READONLY)
220 contents = MODIFY_LDT_CONTENTS_CODE;
221 if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
225 (void *) mmap((char *) (s->selector << 16),
226 (s->length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
227 PROT_EXEC | PROT_READ | PROT_WRITE,
228 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
229 if (seg_table[i].seg_data_offset != 0)
234 status = lseek(fd, seg_table[i].seg_data_offset * 512, SEEK_SET);
235 if(read(fd, s->base_addr, old_length) != old_length)
236 myerror("Unable to read segment from file");
239 * Create entry in LDT for this segment.
241 if (set_ldt_entry(i, (unsigned long) s->base_addr, s->length, 0,
242 contents, read_only, 0) < 0)
248 * If this is the automatic data segment, then we must initialize
251 if (i + 1 == ne_header->auto_data_seg)
253 HEAP_LocalInit(s->base_addr + old_length,
254 ne_header->local_heap_length);
258 CreateEnvironment(i++, s++, zfile);
259 CreatePSP(i++, s++, zfile);