source: trunk/kLdr/kLdrModLX.c@ 2880

Last change on this file since 2880 was 2880, checked in by bird, 19 years ago

Loading of LX bits, including exepack and exepack2 decompression.

  • Property svn:keywords set to Id
File size: 48.8 KB
RevLine 
[2826]1/* $Id: kLdrModLX.c 2880 2006-11-13 20:20:19Z bird $ */
[2821]2/** @file
3 *
[2879]4 * kLdr - The Module Interpreter for the Linear eXecutable (LX) Format.
[2821]5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
[2827]27
[2879]28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <kLdr.h>
32#include "kLdrHlp.h"
33#include "kLdrInternal.h"
34#include "kLdrModLX.h"
35
36
37/*******************************************************************************
38* Defined Constants And Macros *
39*******************************************************************************/
40/** @def KLDRMODLX_STRICT
41 * Define KLDRMODLX_STRICT to enabled strict checks in KLDRMODLX. */
42#define KLDRMODLX_STRICT 1
43
44/** @def KLDRMODLX_ASSERT
45 * Assert that an expression is true when KLDR_STRICT is defined.
46 */
47#ifdef KLDRMODLX_STRICT
48# define KLDRMODLX_ASSERT(expr) kldrHlpAssert(expr)
49#else
50# define KLDRMODLX_ASSERT(expr) do {} while (0)
51#endif
52
53
54/*******************************************************************************
55* Structures and Typedefs *
56*******************************************************************************/
57/**
58 * Instance data for the LX module interpreter.
59 */
60typedef struct KLDRMODLX
61{
62 /** Pointer to the module. (Follows the section table.) */
63 PKLDRMOD pMod;
64 /** Pointer to the user mapping. */
65 const void *pvMapping;
66 /** The size of the mapped LX image. */
67 size_t cbMapped;
68 /** Reserved flags. */
69 uint32_t f32Reserved;
70
71 /** The offset of the LX header. */
72 off_t offHdr;
73 /** Copy of the LX header. */
74 struct e32_exe Hdr;
75
76 /** Pointer to the loader section.
77 * Allocated together with this strcture. */
78 const uint8_t *pbLoaderSection;
79 /** Pointer to the last byte in the loader section. */
80 const uint8_t *pbLoaderSectionLast;
81 /** Pointer to the object table in the loader section. */
82 const struct o32_obj *paObjs;
83 /** Pointer to the object page map table in the loader section. */
84 const struct o32_map *paPageMappings;
85 /** Pointer to the resource table in the loader section. */
86 const struct rsrc32 *paRsrcs;
87 /** Pointer to the resident name table in the loader section. */
88 const uint8_t *pbResNameTab;
89 /** Pointer to the entry table in the loader section. */
90 const uint8_t *pbEntryTab;
91
92 /** Pointer to the non-resident name table. */
93 uint8_t *pbNonResNameTab;
94 /** Pointer to the last byte in the non-resident name table. */
95 const uint8_t *pbNonResNameTabLast;
96
97 /** Pointer to the fixup section. */
98 uint8_t *pbFixupSection;
99 /** Pointer to the last byte in the fixup section. */
100 const uint8_t *pbFixupSectionLast;
101 /** Pointer to the fixup page table within pvFixupSection. */
102 const uint32_t *paoffPageFixups;
103 /** Pointer to the fixup record table within pvFixupSection. */
104 const uint8_t *pbFixupRecs;
105 /** Pointer to the import module name table within pvFixupSection. */
106 const uint8_t *pbImportMods;
107 /** Pointer to the import module name table within pvFixupSection. */
108 const uint8_t *pbImportProcs;
109} KLDRMODLX, *PKLDRMODLX;
110
111
112/*******************************************************************************
113* Internal Functions *
114*******************************************************************************/
115static int kldrModLXHasDbgInfo(PKLDRMOD pMod, const void *pvBits);
116static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
117 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
118static int kldrModLXDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODLX *ppModLX);
119static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits);
[2880]120static int kldrModLXDoIterDataUnpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc);
121static int kldrModLXDoIterData2Unpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc);
122static void kLdrModLXMemCopyW(uint8_t *pbDst, const uint8_t *pbSrc, int cb);
[2879]123static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect);
124static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, unsigned uOp, uintptr_t uHandle);
125static int32_t kldrModLXDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved);
126
127
128/**
129 * Create a loader module instance interpreting the executable image found
130 * in the specified file provider instance.
131 *
132 * @returns 0 on success and *ppMod pointing to a module instance.
133 * On failure, a non-zero OS specific error code is returned.
134 * @param pOps Pointer to the registered method table.
135 * @param pRdr The file provider instance to use.
136 * @param offNewHdr The offset of the new header in MZ files. -1 if not found.
137 * @param ppMod Where to store the module instance pointer.
138 */
139static int kldrModLXCreate(PCKLDRMODOPS pOps, PKLDRRDR pRdr, off_t offNewHdr, PPKLDRMOD ppMod)
140{
141 PKLDRMODLX pModLX;
142 int rc;
143
144 /*
145 * Create the instance data and do a minimal header validation.
146 */
147 rc = kldrModLXDoCreate(pRdr, offNewHdr, &pModLX);
148 if (!rc)
149 {
150 pModLX->pMod->pOps = pOps;
151 pModLX->pMod->u32Magic = KLDRMOD_MAGIC;
152 *ppMod = pModLX->pMod;
153 return 0;
154 }
155 kldrHlpFree(pModLX);
156 return rc;
157}
158
159
160/**
161 * Separate function for reading creating the LX module instance to
162 * simplify cleanup on failure.
163 */
164static int kldrModLXDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODLX *ppModLX)
165{
166 struct e32_exe Hdr;
167 PKLDRMODLX pModLX;
168 PKLDRMOD pMod;
169 size_t cb;
170 size_t cchFilename;
171 uint32_t off, offEnd;
172 uint32_t i;
173 int rc;
174 *ppModLX = NULL;
175
176 /*
177 * Read the signature and file header.
178 */
179 rc = kLdrRdrRead(pRdr, &Hdr, sizeof(Hdr), offNewHdr > 0 ? offNewHdr : 0);
180 if (rc)
181 return rc;
182 if (Hdr.e32_magic[0] != E32MAGIC1 || Hdr.e32_magic[0] != E32MAGIC2)
183 return KLDR_ERR_UNKNOWN_FORMAT;
184
185 /* We're not interested in anything but x86 images. */
186 if ( Hdr.e32_level != E32LEVEL
187 || Hdr.e32_border != E32LEBO
188 || Hdr.e32_worder != E32LEWO
189 || Hdr.e32_cpu < E32CPU286
190 || Hdr.e32_cpu > E32CPU486
191 || Hdr.e32_pagesize != OBJPAGELEN
192 )
193 return KLDR_ERR_LX_BAD_HEADER;
194
195 /* Some rough sanity checks. */
196 offEnd = kLdrRdrSize(pRdr) >= (off_t)~(uint32_t)16 ? ~(uint32_t)16 : (uint32_t)kLdrRdrSize(pRdr);
197 if ( Hdr.e32_itermap > offEnd
198 || Hdr.e32_datapage > offEnd
199 || Hdr.e32_nrestab > offEnd
200 || Hdr.e32_nrestab + Hdr.e32_cbnrestab > offEnd
201 || Hdr.e32_ldrsize > offEnd - offNewHdr - sizeof(Hdr)
202 || Hdr.e32_fixupsize > offEnd - offNewHdr - sizeof(Hdr)
203 || Hdr.e32_fixupsize + Hdr.e32_ldrsize > offEnd - offNewHdr - sizeof(Hdr))
204 return KLDR_ERR_LX_BAD_HEADER;
205
206 /* Verify the loader section. */
207 offEnd = Hdr.e32_objtab + Hdr.e32_ldrsize;
208 if (Hdr.e32_objtab < sizeof(Hdr))
209 return KLDR_ERR_LX_BAD_LOADER_SECTION;
210 off = Hdr.e32_objtab + sizeof(struct o32_obj) * Hdr.e32_objcnt;
211 if (off > offEnd)
212 return KLDR_ERR_LX_BAD_LOADER_SECTION;
213 if ( Hdr.e32_objmap
214 && (Hdr.e32_objmap < off || Hdr.e32_objmap > offEnd))
215 return KLDR_ERR_LX_BAD_LOADER_SECTION;
216 if ( Hdr.e32_rsrccnt
217 && ( Hdr.e32_rsrctab < off
218 || Hdr.e32_rsrctab > offEnd
219 || Hdr.e32_rsrctab + sizeof(struct rsrc32) * Hdr.e32_rsrccnt > offEnd))
220 return KLDR_ERR_LX_BAD_LOADER_SECTION;
221 if ( Hdr.e32_restab
222 && (Hdr.e32_restab < off || Hdr.e32_restab > offEnd - 2))
223 return KLDR_ERR_LX_BAD_LOADER_SECTION;
224 if ( Hdr.e32_enttab
225 && (Hdr.e32_enttab < off || Hdr.e32_enttab > offEnd - 2))
226 return KLDR_ERR_LX_BAD_LOADER_SECTION;
227 if ( Hdr.e32_dircnt
228 && (Hdr.e32_dirtab < off || Hdr.e32_dirtab > offEnd))
229 return KLDR_ERR_LX_BAD_LOADER_SECTION;
230
231 /* Verify the fixup section. */
232 off = offEnd;
233 offEnd = off + Hdr.e32_fixupsize;
234 if ( Hdr.e32_fpagetab
235 && (Hdr.e32_fpagetab < off || Hdr.e32_fpagetab > offEnd))
236 return KLDR_ERR_LX_BAD_FIXUP_SECTION;
237 if ( Hdr.e32_frectab
238 && (Hdr.e32_frectab < off || Hdr.e32_frectab > offEnd))
239 return KLDR_ERR_LX_BAD_FIXUP_SECTION;
240 if ( Hdr.e32_impmod
241 && (Hdr.e32_impmod < off || Hdr.e32_impmod > offEnd || Hdr.e32_impmod + Hdr.e32_impmodcnt > offEnd))
242 return KLDR_ERR_LX_BAD_FIXUP_SECTION;
243 if ( Hdr.e32_impproc
244 && (Hdr.e32_impproc < off || Hdr.e32_impproc > offEnd))
245 return KLDR_ERR_LX_BAD_FIXUP_SECTION;
246
247 /*
248 * Calc the instance size, allocate and initialize it.
249 */
250 cchFilename = kLdrHlpStrLen(kLdrRdrName(pRdr));
251 cb = KLDR_ALIGN_Z(sizeof(KLDRMODLX), 8)
252 + KLDR_ALIGN_Z(KLDR_OFFSETOF(KLDRMOD, aSegments[Hdr.e32_objcnt + 1]), 8)
253 + KLDR_ALIGN_Z(cchFilename + 1, 8),
254 + Hdr.e32_ldrsize;
255 pModLX = (PKLDRMODLX)kldrHlpAlloc(cb);
256 if (!pModLX)
257 return KLDR_ERR_NO_MEMORY;
258 *ppModLX = pModLX;
259
260 /* KLDRMOD */
261 pMod = (PKLDRMOD)((uint8_t *)pModLX + KLDR_ALIGN_Z(sizeof(KLDRMODLX), 8));
262 pMod->pvData = pModLX;
263 pMod->pRdr = pRdr;
264 pMod->pOps = NULL; /* set upon success. */
265 pMod->cSegments = Hdr.e32_objcnt;
266 pMod->cchFilename = cchFilename;
267 pMod->pszFilename = (char *)KLDR_ALIGN_P(&pMod->aSegments[pMod->cSegments], 8);
268 kLdrHlpMemCopy((char *)pMod->pszFilename, kLdrRdrName(pRdr), cchFilename + 1);
269 pMod->pszName = NULL; /* finalized further down */
270 pMod->cchName = 0;
271 switch (Hdr.e32_cpu)
272 {
273 case E32CPU286:
274 pMod->enmCpu = KLDRCPU_I80286;
275 pMod->enmArch = KLDRARCH_X86_16;
276 break;
277 case E32CPU386:
278 pMod->enmCpu = KLDRCPU_I386;
279 pMod->enmArch = KLDRARCH_X86_32;
280 break;
281 case E32CPU486:
282 pMod->enmCpu = KLDRCPU_I486;
283 pMod->enmArch = KLDRARCH_X86_32;
284 break;
285 }
286 pMod->enmEndian = KLDRENDIAN_LITTLE;
287 pMod->enmFmt = KLDRFMT_LX;
288 switch (Hdr.e32_mflags & E32MODMASK)
289 {
290 case E32MODEXE:
291 pMod->enmType = !(Hdr.e32_mflags & E32NOINTFIX)
292 ? KLDRTYPE_EXECUTABLE_RELOCATABLE
293 : KLDRTYPE_EXECUTABLE_FIXED;
294 break;
295
296 case E32MODDLL:
297 case E32PROTDLL:
298 case E32MODPROTDLL:
299 pMod->enmType = !(Hdr.e32_mflags & E32SYSDLL)
300 ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
301 : KLDRTYPE_SHARED_LIBRARY_FIXED;
302 break;
303
304 case E32MODPDEV:
305 case E32MODVDEV:
306 pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE;
307 break;
308 }
309 pMod->u32Magic = 0; /* set upon success. */
310
311 /* KLDRMODLX */
312 pModLX->pMod = pMod;
313 pModLX->pvMapping = 0;
314 pModLX->cbMapped = Hdr.e32_mpages * Hdr.e32_pagesize;
315 pModLX->f32Reserved = 0;
316
317 pModLX->offHdr = offNewHdr >= 0 ? offNewHdr : 0;
318 pModLX->Hdr = Hdr;
319
320 pModLX->pbLoaderSection = KLDR_ALIGN_P(pMod->pszFilename + pMod->cchFilename + 1, 16);
321 pModLX->pbLoaderSectionLast = pModLX->pbLoaderSection + pModLX->Hdr.e32_ldrsize;
322 pModLX->paObjs = NULL;
323 pModLX->paPageMappings = NULL;
324 pModLX->paRsrcs = NULL;
325 pModLX->pbResNameTab = NULL;
326 pModLX->pbEntryTab = NULL;
327
328 pModLX->pbNonResNameTab = NULL;
329 pModLX->pbNonResNameTabLast = NULL;
330
331 pModLX->pbFixupSection = NULL;
332 pModLX->pbFixupSectionLast = NULL;
333 pModLX->paoffPageFixups = NULL;
334 pModLX->pbFixupRecs = NULL;
335 pModLX->pbImportMods = NULL;
336 pModLX->pbImportProcs = NULL;
337
338 /*
339 * Read the loader data.
340 */
341 rc = kLdrRdrRead(pRdr, (void *)pModLX->pbLoaderSection, pModLX->Hdr.e32_ldrsize, pModLX->Hdr.e32_objtab + pModLX->offHdr);
342 if (rc)
343 return rc;
344 if (pModLX->Hdr.e32_objcnt)
345 pModLX->paObjs = (const struct o32_obj *)pModLX->pbLoaderSection;
346 if (pModLX->Hdr.e32_objmap)
347 pModLX->paPageMappings = (const struct o32_map *)(pModLX->pbLoaderSection + pModLX->Hdr.e32_objmap - pModLX->Hdr.e32_objtab);
348 if (pModLX->Hdr.e32_rsrccnt)
349 pModLX->paRsrcs = (const struct rsrc32 *)(pModLX->pbLoaderSection + pModLX->Hdr.e32_rsrctab - pModLX->Hdr.e32_objtab);
350 if (pModLX->Hdr.e32_restab)
351 pModLX->pbResNameTab = pModLX->pbLoaderSection + pModLX->Hdr.e32_restab - pModLX->Hdr.e32_objtab;
352 if (pModLX->Hdr.e32_enttab)
353 pModLX->pbEntryTab = pModLX->pbLoaderSection + pModLX->Hdr.e32_enttab - pModLX->Hdr.e32_objtab;
354
355 /*
356 * Get the soname from the resident name table.
357 */
358 /** @todo */
359
360 /*
361 * Quick validation of the object table.
362 */
363 cb = 0;
364 for (i = 0; i < pMod->cSegments; i++)
365 {
366 if (pModLX->paObjs[i].o32_base & (OBJPAGELEN - 1))
367 return KLDR_ERR_LX_BAD_OBJECT_TABLE;
368 if (pModLX->paObjs[i].o32_base + pModLX->paObjs[i].o32_size <= pModLX->paObjs[i].o32_base)
369 return KLDR_ERR_LX_BAD_OBJECT_TABLE;
370 if (pModLX->paObjs[i].o32_mapsize > pModLX->paObjs[i].o32_size / OBJPAGELEN)
371 return KLDR_ERR_LX_BAD_OBJECT_TABLE;
372 if ( pModLX->paObjs[i].o32_mapsize
373 && ( (uint8_t *)&pModLX->paPageMappings[pModLX->paObjs[i].o32_pagemap] > pModLX->pbLoaderSectionLast
374 || (uint8_t *)&pModLX->paPageMappings[pModLX->paObjs[i].o32_pagemap + pModLX->paObjs[i].o32_mapsize]
375 > pModLX->pbLoaderSectionLast))
376 return KLDR_ERR_LX_BAD_OBJECT_TABLE;
377 if (i > 0)
378 {
379 if (pModLX->paObjs[i].o32_base <= pModLX->paObjs[i - 1].o32_base)
380 return KLDR_ERR_LX_BAD_OBJECT_TABLE;
381 if (pModLX->paObjs[i].o32_base < pModLX->paObjs[i - 1].o32_base + pModLX->paObjs[i - 1].o32_mapsize)
382 return KLDR_ERR_LX_BAD_OBJECT_TABLE;
383 }
384 }
385 pModLX->cbMapped = pMod->cSegments
386 ? pModLX->paObjs[pMod->cSegments - 1].o32_base + pModLX->paObjs[pMod->cSegments - 1].o32_size
387 - pModLX->paObjs[pMod->cSegments - 1].o32_size
388 : 0;
389
390 /*
391 * Setup the KLDRMOD segment array.
392 */
393 for (i = 0; i < pMod->cSegments; i++)
394 {
395 /* unused */
396 pMod->aSegments[i].pvUser = NULL;
397 pMod->aSegments[i].MapAddress = 0;
398 pMod->aSegments[i].pchName = NULL;
399 pMod->aSegments[i].cchName = 0;
400 pMod->aSegments[i].offFile = -1;
401 pMod->aSegments[i].cbFile = 0;
402
403 /* size and addresses */
404 pMod->aSegments[i].Alignment = OBJPAGELEN;
405 pMod->aSegments[i].cb = pModLX->paObjs[i].o32_size;
406 pMod->aSegments[i].LinkAddress = pModLX->paObjs[i].o32_base;
407 pMod->aSegments[i].RVA = pModLX->paObjs[i].o32_base - pModLX->paObjs[0].o32_base;
408 pMod->aSegments[i].cbMapped = KLDR_ALIGN_Z(pModLX->paObjs[i].o32_size, 16);
409 if (i + 1 < pMod->cSegments)
410 pMod->aSegments[i].cbMapped = pModLX->paObjs[i + 1].o32_base - pModLX->paObjs[i].o32_base;
411
412 /* protection */
413 switch ( pModLX->paObjs[i].o32_flags
414 & (OBJSHARED | OBJREAD | OBJWRITE | OBJEXEC))
415 {
416 case 0:
417 case OBJSHARED:
418 pMod->aSegments[i].enmProt = KLDRPROT_NOACCESS;
419 break;
420 case OBJREAD:
421 case OBJREAD | OBJSHARED:
422 pMod->aSegments[i].enmProt = KLDRPROT_READONLY;
423 break;
424 case OBJWRITE:
425 case OBJWRITE | OBJREAD:
426 pMod->aSegments[i].enmProt = KLDRPROT_WRITECOPY;
427 break;
428 case OBJWRITE | OBJSHARED:
429 case OBJWRITE | OBJSHARED | OBJREAD:
430 pMod->aSegments[i].enmProt = KLDRPROT_READWRITE;
431 break;
432 case OBJEXEC:
433 case OBJEXEC | OBJSHARED:
434 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE;
435 break;
436 case OBJEXEC | OBJREAD:
437 case OBJEXEC | OBJREAD | OBJSHARED:
438 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE_READ;
439 break;
440 case OBJEXEC | OBJWRITE:
441 case OBJEXEC | OBJWRITE | OBJREAD:
442 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE_WRITECOPY;
443 break;
444 case OBJEXEC | OBJWRITE | OBJSHARED:
445 case OBJEXEC | OBJWRITE | OBJSHARED | OBJREAD:
446 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE_READWRITE;
447 break;
448 }
449 if ((pModLX->paObjs[i].o32_flags & (OBJREAD | OBJWRITE | OBJEXEC | OBJRSRC)) == OBJRSRC)
450 pMod->aSegments[i].enmProt = KLDRPROT_READONLY;
451 //pMod->aSegments[i].f16bit = !(pModLX->paObjs[i].o32_flags & OBJBIGDEF)
452 //pMod->aSegments[i].fIOPL = !(pModLX->paObjs[i].o32_flags & OBJIOPL)
453 //pMod->aSegments[i].fConforming = !(pModLX->paObjs[i].o32_flags & OBJCONFORM)
454 }
455
456 /*
457 * We're done.
458 */
459 *ppModLX = pModLX;
460 return 0;
461}
462
463
464/** @copydoc KLDRMODOPS::pfnDestroy */
465static int kldrModLXDestroy(PKLDRMOD pMod)
466{
467 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
468 int rc = 0;
469 KLDRMODLX_ASSERT(pModLX->pvMapping);
470
471 if (pMod->pRdr)
472 {
473 rc = kLdrRdrClose(pMod->pRdr);
474 pMod->pRdr = NULL;
475 }
476 if (pModLX->pbNonResNameTab)
477 {
478 kldrHlpFree(pModLX->pbNonResNameTab);
479 pModLX->pbNonResNameTab = NULL;
480 }
481 if (pModLX->pbFixupSection)
482 {
483 kldrHlpFree(pModLX->pbFixupSection);
484 pModLX->pbFixupSection = NULL;
485 }
486 if (pMod->pszName)
487 {
488 kldrHlpFree((void *)pMod->pszName);
489 pMod->pszName = NULL;
490 }
491 pMod->u32Magic = 0;
492 pMod->pOps = NULL;
493 kldrHlpFree(pModLX);
494 return rc;
495}
496
497
498/**
499 * Resolved base address aliases.
500 *
501 * @param pModLX The interpreter module instance
502 * @param pBaseAddress The base address, IN & OUT.
503 */
504static void kldrModLXResolveBaseAddress(PKLDRMODLX pModLX, PKLDRADDR pBaseAddress)
505{
506 if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP)
507 *pBaseAddress = pModLX->pMod->aSegments[0].MapAddress;
508 else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK)
509 *pBaseAddress = pModLX->pMod->aSegments[0].LinkAddress;
510}
511
512
513/** @copydoc kLdrModQuerySymbol */
514static int kldrModLXQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t iSymbol,
515 const char *pszSymbol, PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser,
516 PKLDRADDR puValue, uint32_t *pfKind)
517{
518 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
519 //int rc;
520
521 kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
522
523 return -1;
524}
525
526
527/** @copydoc kLdrModEnumSymbols */
528static int kldrModLXEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
529 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
530{
531 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
532// int rc;
533
534 kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
535
536 return -1;
537}
538
539
540/** @copydoc kLdrModGetImport */
541static int kldrModLXGetImport(PKLDRMOD pMod, const void *pvBits, uint32_t iImport, char *pszName, size_t cchName)
542{
543 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
544 const uint8_t * pb = NULL;
545 int rc;
546
547 /** @todo */
548
549 if (*pb < cchName)
550 {
551 kLdrHlpMemCopy(pszName, pb + 1, *pb);
552 pszName[*pb] = '\0';
553 rc = 0;
554 }
555 else
556 {
557 kLdrHlpMemCopy(pszName, pb + 1, cchName);
558 if (cchName)
559 pszName[cchName - 1] = '\0';
560 rc = KLDR_ERR_BUFFER_OVERFLOW;
561 }
562
563 return rc;
564}
565
566
567/** @copydoc kLdrModNumberOfImports */
568static int32_t kldrModLXNumberOfImports(PKLDRMOD pMod, const void *pvBits)
569{
570 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
571 return pModLX->Hdr.e32_impmodcnt;
572}
573
574
575/** @copydoc kLdrModGetStackInfo */
576static int kldrModLXGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
577{
578 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
579 const uint32_t i = pModLX->Hdr.e32_stackobj;
580
581 if ( i
582 && i <= pMod->cSegments
583 && pModLX->Hdr.e32_esp <= pMod->aSegments[i - 1].LinkAddress + pMod->aSegments[i - 1].cb
584 && pModLX->Hdr.e32_stacksize
585 && pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize >= pMod->aSegments[i - 1].LinkAddress)
586 {
587
588 kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
589 pStackInfo->LinkAddress = pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize;
590 pStackInfo->Address = BaseAddress
591 + pMod->aSegments[i - 1].RVA
592 + pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize - pMod->aSegments[i - 1].LinkAddress;
593 }
594 else
595 {
596 pStackInfo->Address = NIL_KLDRADDR;
597 pStackInfo->LinkAddress = NIL_KLDRADDR;
598 }
599 pStackInfo->cbStack = pModLX->Hdr.e32_stacksize;
600 pStackInfo->cbStackThread = 0;
601
602 return 0;
603}
604
605
606/** @copydoc kLdrModQueryMainEntrypoint */
607static int kldrModLXQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
608{
609 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
610
611 /*
612 * Convert the address from the header.
613 */
614 kldrModLXResolveBaseAddress(pModLX, &BaseAddress);
615 *pMainEPAddress = pModLX->Hdr.e32_startobj
616 && pModLX->Hdr.e32_startobj <= pMod->cSegments
617 && pModLX->Hdr.e32_eip < pMod->aSegments[pModLX->Hdr.e32_startobj - 1].cb
618 ? BaseAddress + pMod->aSegments[pModLX->Hdr.e32_startobj - 1].RVA + pModLX->Hdr.e32_eip
619 : NIL_KLDRADDR;
620 return 0;
621}
622
623
624/** @copydoc kLdrModEnumDbgInfo */
625static int kldrModLXEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
626{
627 //PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
628
629 /*
630 * Quit immediately if no debug info.
631 */
632 if (kldrModLXHasDbgInfo(pMod, pvBits))
633 return 0;
634#if 0
635 /*
636 * Read the debug info and look for familiar magics and structures.
637 */
638 /** @todo */
639#endif
640
641 return 0;
642}
643
644
645/** @copydoc kLdrModHasDbgInfo */
646static int kldrModLXHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
647{
648 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
649
650 /*
651 * Don't curretnly bother with linkers which doesn't advertise it in the header.
652 */
653 if ( !pModLX->Hdr.e32_debuginfo
654 || !pModLX->Hdr.e32_debuglen)
655 return KLDR_ERR_NO_DEBUG_INFO;
656 return 0;
657}
658
659
660/** @copydoc kLdrModMap */
661static int kldrModLXMap(PKLDRMOD pMod)
662{
663 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
664 unsigned fFixed;
665 void *pvBase;
666 int rc;
667
668 /*
669 * Already mapped?
670 */
671 if (pModLX->pvMapping)
672 return KLDR_ERR_ALREADY_MAPPED;
673
674 /*
675 * Allocate memory for it.
676 */
677 /* fixed image? */
678 fFixed = pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED
679 || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED;
680 if (!fFixed)
681 pvBase = NULL;
682 else
683 {
684 pvBase = (void *)(uintptr_t)pMod->aSegments[0].LinkAddress;
685 if ((uintptr_t)pvBase != pMod->aSegments[0].LinkAddress)
686 return KLDR_ERR_ADDRESS_OVERFLOW;
687 }
688 rc = kldrHlpPageAlloc(&pvBase, pModLX->cbMapped, KLDRPROT_EXECUTE_READWRITE, fFixed);
689 if (rc)
690 return rc;
691
692 /*
693 * Load the bits, apply page protection, and update the segment table.
694 */
695 rc = kldrModLXDoLoadBits(pModLX, pvBase);
696 if (!rc)
697 rc = kldrModLXDoProtect(pModLX, pvBase, 0 /* protect */);
698 if (!rc)
699 {
700 uint32_t i;
701 for (i = 0; i < pMod->cSegments; i++)
702 {
703 if (pMod->aSegments[i].RVA != NIL_KLDRADDR)
704 pMod->aSegments[i].MapAddress = (uintptr_t)pvBase + (uintptr_t)pMod->aSegments[i].RVA;
705 }
706 pModLX->pvMapping = pvBase;
707 }
708 else
709 kldrHlpPageFree(pvBase, pModLX->cbMapped);
710 return rc;
711}
712
713
714/**
715 * Loads the LX pages into the specified memory mapping.
716 *
717 * @returns 0 on success.
718 * @returns non-zero kLdr or OS status code on failure.
719 *
720 * @param pModLX The LX module interpreter instance.
721 * @param pvBits Where to load the bits.
722 */
723static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits)
724{
[2880]725 const PKLDRRDR pRdr = pModLX->pMod->pRdr;
726 uint8_t *pbTmpPage = NULL;
727 int rc = 0;
728 uint32_t i;
[2879]729
[2880]730 /*
731 * Iterate the segments.
732 */
733 for (i = 0; i < pModLX->Hdr.e32_objcnt; i++)
734 {
735 const struct o32_obj * const pObj = &pModLX->paObjs[i];
736 const uint32_t cPages = pModLX->pMod->aSegments[i].cbMapped / OBJPAGELEN;
737 uint32_t iPage;
738 uint8_t *pbPage = (uint8_t *)pvBits + (uintptr_t)pModLX->pMod->aSegments[i].RVA;
739
740 /*
741 * Iterate the page map pages.
742 */
743 for (iPage = 0; !rc && iPage < pObj->o32_mapsize; iPage++, pbPage += OBJPAGELEN)
744 {
745 const struct o32_map *pMap = &pModLX->paPageMappings[iPage + pObj->o32_pagemap - 1];
746 switch (pMap->o32_pageflags)
747 {
748 case VALID:
749 if (pMap->o32_pagesize == OBJPAGELEN)
750 rc = kLdrRdrRead(pRdr, pbPage, OBJPAGELEN, pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift);
751 else if (pMap->o32_pagesize < OBJPAGELEN)
752 {
753 rc = kLdrRdrRead(pRdr, pbPage, pMap->o32_pagesize, pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift);
754 kLdrHlpMemSet(pbPage + pMap->o32_pagesize, 0, OBJPAGELEN - pMap->o32_pagesize);
755 }
756 else
757 rc = KLDR_ERR_LX_BAD_PAGE_MAP;
758 break;
759
760 case ITERDATA:
761 case ITERDATA2:
762 /* make sure we've got a temp page .*/
763 if (!pbTmpPage)
764 {
765 pbTmpPage = kldrHlpAlloc(OBJPAGELEN + 256);
766 if (!pbTmpPage)
767 break;
768 }
769 /* validate the size. */
770 if (pMap->o32_pagesize > OBJPAGELEN + 252)
771 {
772 rc = KLDR_ERR_LX_BAD_PAGE_MAP;
773 break;
774 }
775
776 /* read it and ensure 4 extra zero bytes. */
777 rc = kLdrRdrRead(pRdr, pbTmpPage, pMap->o32_pagesize, pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift);
778 if (rc)
779 break;
780 kLdrHlpMemSet(pbTmpPage + pMap->o32_pagesize, 0, 4);
781
782 /* unpack it into the image page. */
783 if (pMap->o32_pageflags == ITERDATA2)
784 rc = kldrModLXDoIterData2Unpacking(pbPage, pbTmpPage, pMap->o32_pagesize);
785 else
786 rc = kldrModLXDoIterDataUnpacking(pbPage, pbTmpPage, pMap->o32_pagesize);
787 break;
788
789 case INVALID: /* we're probably not dealing correctly with INVALID pages... */
790 case ZEROED:
791 kLdrHlpMemSet(pbPage, 0, OBJPAGELEN);
792 break;
793
794 case RANGE:
795 KLDRMODLX_ASSERT(!"RANGE");
796 default:
797 rc = KLDR_ERR_LX_BAD_PAGE_MAP;
798 break;
799 }
800 }
801 if (rc)
802 break;
803
804 /*
805 * Zero the remaining pages.
806 */
807 if (iPage < cPages)
808 kLdrHlpMemSet(pbPage, 0, (cPages - iPage) * OBJPAGELEN);
809 }
810
811 if (pbTmpPage)
812 kldrHlpFree(pbTmpPage);
813 return rc;
[2879]814}
815
816
817/**
[2880]818 * Unpacks iterdata (aka EXEPACK).
819 *
820 * @returns 0 on success, non-zero kLdr status code on failure.
821 * @param pbDst Where to put the uncompressed data. (Assumes OBJPAGELEN size.)
822 * @param pbSrc The compressed source data.
823 * @param cbSrc The file size of the compressed data. The source buffer
824 * contains 4 additional zero bytes.
825 */
826static int kldrModLXDoIterDataUnpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc)
827{
828 const struct LX_Iter *pIter = (const struct LX_Iter *)pbSrc;
829 int cbDst = OBJPAGELEN;
830
831 /* Validate size of data. */
832 if (cbSrc >= OBJPAGELEN - 2)
833 return KLDR_ERR_LX_BAD_ITERDATA;
834
835 /*
836 * Expand the page.
837 */
838 while (cbSrc > 0 && pIter->LX_nIter)
839 {
840 if (pIter->LX_nBytes == 1)
841 {
842 /*
843 * Special case - one databyte.
844 */
845 cbDst -= pIter->LX_nIter;
846 if (cbDst < 0)
847 return KLDR_ERR_LX_BAD_ITERDATA;
848
849 cbSrc -= 4 + 1;
850 if (cbSrc < -4)
851 return KLDR_ERR_LX_BAD_ITERDATA;
852
853 kLdrHlpMemSet(pbDst, pIter->LX_Iterdata, pIter->LX_nIter);
854 pbDst += pIter->LX_nIter;
855 pIter++;
856 }
857 else
858 {
859 /*
860 * General.
861 */
862 int i;
863
864 cbDst -= pIter->LX_nIter * pIter->LX_nBytes;
865 if (cbDst < 0)
866 return KLDR_ERR_LX_BAD_ITERDATA;
867
868 cbSrc -= 4 + pIter->LX_nBytes;
869 if (cbSrc < -4)
870 return KLDR_ERR_LX_BAD_ITERDATA;
871
872 for (i = pIter->LX_nIter; i > 0; i--, pbDst += pIter->LX_nBytes)
873 memcpy(pbDst, &pIter->LX_Iterdata, pIter->LX_nBytes);
874 pIter = (struct LX_Iter *)((char*)pIter + 4 + pIter->LX_nBytes);
875 }
876 }
877
878 /*
879 * Zero remainder of the page.
880 */
881 if (cbDst > 0)
882 kLdrHlpMemSet(pbDst, 0, cbDst);
883
884 return 0;
885}
886
887
888/**
889 * Unpacks iterdata (aka EXEPACK).
890 *
891 * @returns 0 on success, non-zero kLdr status code on failure.
892 * @param pbDst Where to put the uncompressed data. (Assumes OBJPAGELEN size.)
893 * @param pbSrc The compressed source data.
894 * @param cbSrc The file size of the compressed data. The source buffer
895 * contains 4 additional zero bytes.
896 */
897static int kldrModLXDoIterData2Unpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc)
898{
899 int cbDst = OBJPAGELEN;
900
901 while (cbSrc > 0)
902 {
903 /*
904 * Bit 0 and 1 is the encoding type.
905 */
906 switch (*pbSrc & 0x03)
907 {
908 /*
909 *
910 * 0 1 2 3 4 5 6 7
911 * type | |
912 * ----------------
913 * cb <cb bytes of data>
914 *
915 * Bits 2-7 is, if not zero, the length of an uncompressed run
916 * starting at the following byte.
917 *
918 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
919 * type | | | | | |
920 * ---------------- ---------------------- -----------------------
921 * zero cb char to multiply
922 *
923 * If the bits are zero, the following two bytes describes a 1 byte interation
924 * run. First byte is count, second is the byte to copy. A count of zero is
925 * means end of data, and we simply stops. In that case the rest of the data
926 * should be zero.
927 */
928 case 0:
929 {
930 if (*pbSrc)
931 {
932 const int cb = *pbSrc >> 2;
933 cbDst -= cb;
934 if (cbDst < 0)
935 return KLDR_ERR_LX_BAD_ITERDATA2;
936 cbSrc -= cb;
937 if (cbSrc < 0)
938 return KLDR_ERR_LX_BAD_ITERDATA2;
939 kLdrHlpMemCopy(pbDst, ++pbSrc, cb);
940 pbDst += cb;
941 pbSrc += cb;
942 }
943 else if (cbSrc < 2)
944 return KLDR_ERR_LX_BAD_ITERDATA2;
945 else
946 {
947 const int cb = pbSrc[1];
948 if (!cb)
949 goto l_endloop;
950 cbDst -= cb;
951 if (cbDst < 0)
952 return KLDR_ERR_LX_BAD_ITERDATA2;
953 cbSrc -= 3;
954 if (cbSrc < 0)
955 return KLDR_ERR_LX_BAD_ITERDATA2;
956 memset(pbDst, pbSrc[2], cb);
957 pbDst += cb;
958 pbSrc += 3;
959 }
960 break;
961 }
962
963
964 /*
965 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
966 * type | | | | | |
967 * ---- ------- -------------------------
968 * cb1 cb2 - 3 offset <cb1 bytes of data>
969 *
970 * Two bytes layed out as described above, followed by cb1 bytes of data to be copied.
971 * The cb2(+3) and offset describes an amount of data to be copied from the expanded
972 * data relative to the current position. The data copied as you would expect it to be.
973 */
974 case 1:
975 {
976 cbSrc -= 2;
977 if (cbSrc < 0)
978 return KLDR_ERR_LX_BAD_ITERDATA2;
979 else
980 {
981 const unsigned off = ((unsigned)pbSrc[1] << 1) | (*pbSrc >> 7);
982 const int cb1 = (*pbSrc >> 2) & 3;
983 const int cb2 = ((*pbSrc >> 4) & 7) + 3;
984
985 pbSrc += 2;
986 cbSrc -= cb1;
987 if (cbSrc < 0)
988 return KLDR_ERR_LX_BAD_ITERDATA2;
989 cbDst -= cb1;
990 if (cbDst < 0)
991 return KLDR_ERR_LX_BAD_ITERDATA2;
992 kLdrHlpMemCopy(pbDst, pbSrc, cb1);
993 pbDst += cb1;
994
995 if (off > OBJPAGELEN - cbDst)
996 return KLDR_ERR_LX_BAD_ITERDATA2;
997 cbDst -= cb2;
998 if (cbDst < 0)
999 return KLDR_ERR_LX_BAD_ITERDATA2;
1000 kLdrHlpMemMove(pbDst, pbDst - off, cb2);
1001 pbDst += cb2;
1002 }
1003 break;
1004 }
1005
1006
1007 /*
1008 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1009 * type | | | |
1010 * ---- ----------------------------------
1011 * cb-3 offset
1012 *
1013 * Two bytes layed out as described above.
1014 * The cb(+3) and offset describes an amount of data to be copied from the expanded
1015 * data relative to the current position.
1016 *
1017 * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
1018 */
1019 case 2:
1020 {
1021 cbSrc -= 2;
1022 if (cbSrc < 0)
1023 return KLDR_ERR_LX_BAD_ITERDATA2;
1024 else
1025 {
1026 const unsigned off = ((unsigned)pbSrc[2] << 4) | (*pbSrc >> 4);
1027 const int cb = ((*pbSrc >> 2) & 3) + 3;
1028
1029 pbSrc += 2;
1030 if (off > OBJPAGELEN - cbDst)
1031 return KLDR_ERR_LX_BAD_ITERDATA2;
1032 cbDst -= cb;
1033 if (cbDst < 0)
1034 return KLDR_ERR_LX_BAD_ITERDATA2;
1035 kLdrModLXMemCopyW(pbDst, pbDst - off, cb);
1036 pbDst += cb;
1037 }
1038 break;
1039 }
1040
1041
1042 /*
1043 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
1044 * type | | | | | |
1045 * ---------- ---------------- ----------------------------------
1046 * cb1 cb2 offset <cb1 bytes of data>
1047 *
1048 * Three bytes layed out as described above, followed by cb1 bytes of data to be copied.
1049 * The cb2 and offset describes an amount of data to be copied from the expanded
1050 * data relative to the current position.
1051 *
1052 * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
1053 */
1054 case 3:
1055 {
1056 cbSrc -= 3;
1057 if (cbSrc < 0)
1058 return KLDR_ERR_LX_BAD_ITERDATA2;
1059 else
1060 {
1061 const int cb1 = (*pbSrc >> 2) & 0xf;
1062 const int cb2 = ((pbSrc[1] & 0xf) << 2) | (*pbSrc >> 6);
1063 const unsigned off = ((unsigned)pbSrc[2] << 4) | (pbSrc[1] >> 4);
1064
1065 pbSrc += 3;
1066 cbSrc -= cb1;
1067 if (cbSrc < 0)
1068 return KLDR_ERR_LX_BAD_ITERDATA2;
1069 cbDst -= cb1;
1070 if (cbDst < 0)
1071 return KLDR_ERR_LX_BAD_ITERDATA2;
1072 kLdrHlpMemCopy(pbDst, pbSrc, cb1);
1073 pbDst += cb1;
1074
1075 if (off > OBJPAGELEN - cbDst)
1076 return KLDR_ERR_LX_BAD_ITERDATA2;
1077 cbDst -= cb2;
1078 if (cbDst < 0)
1079 return KLDR_ERR_LX_BAD_ITERDATA2;
1080 kLdrModLXMemCopyW(pbDst, pbDst - off, cb2);
1081 pbDst += cb2;
1082 }
1083 break;
1084 }
1085 } /* type switch. */
1086 } /* unpack loop */
1087
1088l_endloop:
1089
1090
1091 /*
1092 * Zero remainder of the page.
1093 */
1094 if (cbDst > 0)
1095 kLdrHlpMemSet(pbDst, 0, cbDst);
1096
1097 return 0;
1098}
1099
1100
1101/**
1102 * Special memcpy employed by the iterdata2 algorithm.
1103 *
1104 * Emulate a 16-bit memcpy (copying 16-bit at a time) and the effects this
1105 * has if src is very close to the destination.
1106 *
1107 * @param pbDst Destination pointer.
1108 * @param pbSrc Source pointer. Will always be <= pbDst.
1109 * @param cb Amount of data to be copied.
1110 * @remark This assumes that unaligned word and dword access is fine.
1111 */
1112static void kLdrModLXMemCopyW(uint8_t *pbDst, const uint8_t *pbSrc, int cb)
1113{
1114 switch (pbDst - pbSrc)
1115 {
1116 case 0:
1117 case 1:
1118 case 2:
1119 case 3:
1120 /* 16-bit copy (unaligned) */
1121 if (cb & 1)
1122 *pbDst++ = *pbDst++;
1123 for (cb >>= 1; cb > 0; cb--, pbDst += 2, pbSrc += 2)
1124 *(uint16_t *)pbDst = *(const uint16_t *)pbSrc;
1125 break;
1126
1127 default:
1128 /* 32-bit copy (unaligned) */
1129 if (cb & 1)
1130 *pbDst++ = *pbDst++;
1131 if (cb & 2)
1132 {
1133 *(uint16_t *)pbDst = *(const uint16_t *)pbSrc;
1134 pbDst += 2;
1135 pbSrc += 2;
1136 }
1137 for (cb >>= 2; cb > 0; cb--, pbDst += 4, pbSrc += 4)
1138 *(uint32_t *)pbDst = *(const uint32_t *)pbSrc;
1139 break;
1140 }
1141}
1142
1143
1144/**
[2879]1145 * Unprotects or protects the specified image mapping.
1146 *
1147 * @returns 0 on success.
1148 * @returns non-zero kLdr or OS status code on failure.
1149 *
1150 * @param pModLX The LX module interpreter instance.
1151 * @param pvBits The mapping to protect.
1152 * @param UnprotectOrProtect If 1 unprotect (i.e. make all writable), otherwise
1153 * protect according to the object table.
1154 */
1155static int kldrModLXDoProtect(PKLDRMODLX pMod, void *pvBits, unsigned fUnprotectOrProtect)
1156{
1157 return -1;
1158}
1159
1160
1161/** @copydoc kLdrModUnmap */
1162static int kldrModLXUnmap(PKLDRMOD pMod)
1163{
1164 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1165 uint32_t i;
1166 int rc;
1167
1168 /*
1169 * Mapped?
1170 */
1171 if (!pModLX->pvMapping)
1172 return KLDR_ERR_NOT_MAPPED;
1173
1174 /*
1175 * Free the mapping and update the segments.
1176 */
1177 rc = kldrHlpPageFree((void *)pModLX->pvMapping, pModLX->cbMapped);
1178 KLDRMODLX_ASSERT(!rc);
1179 pModLX->pvMapping = NULL;
1180
1181 for (i = 0; i < pMod->cSegments; i++)
1182 pMod->aSegments[i].MapAddress = 0;
1183
1184 return rc;
1185}
1186
1187
1188/** @copydoc kLdrModAllocTLS */
1189static int kldrModLXAllocTLS(PKLDRMOD pMod)
1190{
1191 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1192
1193 /* just do the error checking. */
1194 if (!pModLX->pvMapping)
1195 return KLDR_ERR_NOT_MAPPED;
1196 return 0;
1197}
1198
1199
1200/** @copydoc kLdrModFreeTLS */
1201static void kldrModLXFreeTLS(PKLDRMOD pMod)
1202{
1203}
1204
1205
1206/** @copydoc kLdrModReload */
1207static int kldrModLXReload(PKLDRMOD pMod)
1208{
1209 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1210
1211 /*
1212 * Mapped?
1213 */
1214 if (!pModLX->pvMapping)
1215 return KLDR_ERR_NOT_MAPPED;
1216
1217 /* the file provider does it all */
1218 return kLdrRdrRefresh(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments);
1219}
1220
1221
1222/** @copydoc kLdrModFixupMapping */
1223static int kldrModLXFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1224{
1225 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1226 int rc, rc2;
1227
1228 /*
1229 * Mapped?
1230 */
1231 if (!pModLX->pvMapping)
1232 return KLDR_ERR_NOT_MAPPED;
1233
1234 /*
1235 * Before doing anything we'll have to make all pages writable.
1236 */
1237 rc = kLdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
1238 if (rc)
1239 return rc;
1240
1241 /*
1242 * Apply fixups and resolve imports.
1243 */
1244 rc = kldrModLXRelocateBits(pMod, (void *)pModLX->pvMapping, (uintptr_t)pModLX->pvMapping,
1245 pMod->aSegments[0].LinkAddress, pfnGetImport, pvUser);
1246
1247 /*
1248 * Restore protection.
1249 */
1250 rc2 = kLdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
1251 if (!rc && rc2)
1252 rc = rc2;
1253 return rc;
1254}
1255
1256
1257/** @copydoc kLdrModCallInit */
1258static int kldrModLXCallInit(PKLDRMOD pMod, uintptr_t uHandle)
1259{
1260 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1261 int rc;
1262
1263 /*
1264 * Mapped?
1265 */
1266 if (!pModLX->pvMapping)
1267 return KLDR_ERR_NOT_MAPPED;
1268
1269 /*
1270 * Do TLS callbacks first and then call the init/term function if it's a DLL.
1271 */
1272 if ((pModLX->Hdr.e32_mflags & E32MODMASK) == E32MODDLL)
1273 rc = kldrModLXDoCallDLL(pModLX, 0 /* attach */, uHandle);
1274 else
1275 rc = 0;
1276 return rc;
1277}
1278
1279
1280/**
1281 * Call the DLL entrypoint.
1282 *
1283 * @returns 0 on success.
1284 * @returns KLDR_ERR_MODULE_INIT_FAILED or KLDR_ERR_THREAD_ATTACH_FAILED on failure.
1285 * @param pModLX The LX module interpreter instance.
1286 * @param uOp The operation (DLL_*).
1287 * @param uHandle The module handle to present.
1288 */
1289static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, unsigned uOp, uintptr_t uHandle)
1290{
1291 int rc;
1292
1293 /*
1294 * If no entrypoint there isn't anything to be done.
1295 */
1296 if ( !pModLX->Hdr.e32_startobj
1297 || pModLX->Hdr.e32_startobj > pModLX->Hdr.e32_objcnt)
1298 return 0;
1299
1300 /*
1301 * Invoke the entrypoint and convert the boolean result to a kLdr status code.
1302 */
1303 rc = kldrModLXDoCall((uintptr_t)pModLX->pvMapping
1304 + (uintptr_t)pModLX->pMod->aSegments[pModLX->Hdr.e32_startobj - 1].RVA
1305 + pModLX->Hdr.e32_eip,
1306 uHandle, uOp, NULL);
1307 if (rc)
1308 rc = 0;
1309 else if (uOp == 0 /* attach */)
1310 rc = KLDR_ERR_MODULE_INIT_FAILED;
1311 else /* detach: ignore failures */
1312 rc = 0;
1313 return rc;
1314}
1315
1316
1317/**
1318 * Do a 3 parameter callback.
1319 *
1320 * @returns 32-bit callback return.
1321 * @param uEntrypoint The address of the function to be called.
1322 * @param uHandle The first argument, the module handle.
1323 * @param uOp The second argumnet, the reason we're calling.
1324 * @param pvReserved The third argument, reserved argument. (figure this one out)
1325 */
1326static int32_t kldrModLXDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved)
1327{
1328#if defined(__X86__) || defined(__i386__) || defined(_M_IX86)
1329 int32_t rc;
1330/** @todo try/except */
1331
1332 /*
1333 * Paranoia.
1334 */
1335# ifdef __GNUC__
1336 __asm__ __volatile__(
1337 "pushl %2\n\t"
1338 "pushl %1\n\t"
1339 "pushl %0\n\t"
1340 "lea 12(%%esp), %2\n\t"
1341 "call *%3\n\t"
1342 "movl %2, %%esp\n\t"
1343 : "=a" (rc)
1344 : "d" (uOp),
1345 "S" (0),
1346 "c" (uEntrypoint),
1347 "0" (uHandle));
1348# elif defined(_MSC_VER)
1349 __asm {
1350 mov eax, [uHandle]
1351 mov edx, [uOp]
1352 mov ecx, 0
1353 mov ebx, [uEntrypoint]
1354 push edi
1355 mov edi, esp
1356 push ecx
1357 push edx
1358 push eax
1359 call ebx
1360 mov esp, edi
1361 pop edi
1362 mov [rc], eax
1363 }
1364# else
1365# error "port me!"
1366# endif
1367 return rc;
1368
1369#else
1370 return KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE;
1371#endif
1372}
1373
1374
1375/** @copydoc kLdrModCallTerm */
1376static int kldrModLXCallTerm(PKLDRMOD pMod, uintptr_t uHandle)
1377{
1378 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1379
1380 /*
1381 * Mapped?
1382 */
1383 if (!pModLX->pvMapping)
1384 return KLDR_ERR_NOT_MAPPED;
1385
1386 /*
1387 * Do the call.
1388 */
1389 if ((pModLX->Hdr.e32_mflags & E32MODMASK) == E32MODDLL)
1390 kldrModLXDoCallDLL(pModLX, 1 /* detach */, uHandle);
1391
1392 return 0;
1393}
1394
1395
1396/** @copydoc kLdrModCallThread */
1397static int kldrModLXCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
1398{
1399 return 0;
1400}
1401
1402
1403/** @copydoc kLdrModSize */
1404static KLDRADDR kldrModLXSize(PKLDRMOD pMod)
1405{
1406 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1407 return pModLX->cbMapped;
1408}
1409
1410
1411/** @copydoc kLdrModGetBits */
1412static int kldrModLXGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1413{
1414 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1415 int rc;
1416
1417 /*
1418 * Load the image bits.
1419 */
1420 rc = kldrModLXDoLoadBits(pModLX, pvBits);
1421 if (rc)
1422 return rc;
1423
1424 /*
1425 * Perform relocations.
1426 */
1427 return kldrModLXRelocateBits(pMod, pvBits, BaseAddress, pMod->aSegments[0].LinkAddress, pfnGetImport, pvUser);
1428
1429}
1430
1431
1432/** @copydoc kLdrModRelocateBits */
1433static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
1434 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1435{
1436 //PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData;
1437 //int rc;
1438
1439 /** @todo Implement this. */
1440
1441 return -1;
1442}
1443
1444
1445/**
1446 * The LX module interpreter method table.
1447 */
1448KLDRMODOPS g_kLdrModLXOps =
1449{
1450 "LX",
1451 NULL,
1452 kldrModLXCreate,
1453 kldrModLXDestroy,
1454 kldrModLXQuerySymbol,
1455 kldrModLXEnumSymbols,
1456 kldrModLXGetImport,
1457 kldrModLXNumberOfImports,
1458 NULL /* can execute one is optional */,
1459 kldrModLXGetStackInfo,
1460 kldrModLXQueryMainEntrypoint,
1461 kldrModLXEnumDbgInfo,
1462 kldrModLXHasDbgInfo,
1463 kldrModLXMap,
1464 kldrModLXUnmap,
1465 kldrModLXAllocTLS,
1466 kldrModLXFreeTLS,
1467 kldrModLXReload,
1468 kldrModLXFixupMapping,
1469 kldrModLXCallInit,
1470 kldrModLXCallTerm,
1471 kldrModLXCallThread,
1472 kldrModLXSize,
1473 kldrModLXGetBits,
1474 kldrModLXRelocateBits,
1475 42 /* the end */
1476};
1477
Note: See TracBrowser for help on using the repository browser.