Changeset 2879 for trunk/kLdr/kLdrModLX.c
- Timestamp:
- Nov 12, 2006, 6:21:16 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModLX.c
r2827 r2879 2 2 /** @file 3 3 * 4 * kLdr - The Dynamic Loader, LX Image.4 * kLdr - The Module Interpreter for the Linear eXecutable (LX) Format. 5 5 * 6 6 * Copyright (c) 2006 knut st. osmundsen <bird@anduin.net> … … 25 25 */ 26 26 27 #include "kLdr.h" 28 27 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 */ 60 typedef 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 *******************************************************************************/ 115 static int kldrModLXHasDbgInfo(PKLDRMOD pMod, const void *pvBits); 116 static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 117 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 118 static int kldrModLXDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODLX *ppModLX); 119 static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits); 120 static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect); 121 static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, unsigned uOp, uintptr_t uHandle); 122 static int32_t kldrModLXDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved); 123 124 125 /** 126 * Create a loader module instance interpreting the executable image found 127 * in the specified file provider instance. 128 * 129 * @returns 0 on success and *ppMod pointing to a module instance. 130 * On failure, a non-zero OS specific error code is returned. 131 * @param pOps Pointer to the registered method table. 132 * @param pRdr The file provider instance to use. 133 * @param offNewHdr The offset of the new header in MZ files. -1 if not found. 134 * @param ppMod Where to store the module instance pointer. 135 */ 136 static int kldrModLXCreate(PCKLDRMODOPS pOps, PKLDRRDR pRdr, off_t offNewHdr, PPKLDRMOD ppMod) 137 { 138 PKLDRMODLX pModLX; 139 int rc; 140 141 /* 142 * Create the instance data and do a minimal header validation. 143 */ 144 rc = kldrModLXDoCreate(pRdr, offNewHdr, &pModLX); 145 if (!rc) 146 { 147 pModLX->pMod->pOps = pOps; 148 pModLX->pMod->u32Magic = KLDRMOD_MAGIC; 149 *ppMod = pModLX->pMod; 150 return 0; 151 } 152 kldrHlpFree(pModLX); 153 return rc; 154 } 155 156 157 /** 158 * Separate function for reading creating the LX module instance to 159 * simplify cleanup on failure. 160 */ 161 static int kldrModLXDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODLX *ppModLX) 162 { 163 struct e32_exe Hdr; 164 PKLDRMODLX pModLX; 165 PKLDRMOD pMod; 166 size_t cb; 167 size_t cchFilename; 168 uint32_t off, offEnd; 169 uint32_t i; 170 int rc; 171 *ppModLX = NULL; 172 173 /* 174 * Read the signature and file header. 175 */ 176 rc = kLdrRdrRead(pRdr, &Hdr, sizeof(Hdr), offNewHdr > 0 ? offNewHdr : 0); 177 if (rc) 178 return rc; 179 if (Hdr.e32_magic[0] != E32MAGIC1 || Hdr.e32_magic[0] != E32MAGIC2) 180 return KLDR_ERR_UNKNOWN_FORMAT; 181 182 /* We're not interested in anything but x86 images. */ 183 if ( Hdr.e32_level != E32LEVEL 184 || Hdr.e32_border != E32LEBO 185 || Hdr.e32_worder != E32LEWO 186 || Hdr.e32_cpu < E32CPU286 187 || Hdr.e32_cpu > E32CPU486 188 || Hdr.e32_pagesize != OBJPAGELEN 189 ) 190 return KLDR_ERR_LX_BAD_HEADER; 191 192 /* Some rough sanity checks. */ 193 offEnd = kLdrRdrSize(pRdr) >= (off_t)~(uint32_t)16 ? ~(uint32_t)16 : (uint32_t)kLdrRdrSize(pRdr); 194 if ( Hdr.e32_itermap > offEnd 195 || Hdr.e32_datapage > offEnd 196 || Hdr.e32_nrestab > offEnd 197 || Hdr.e32_nrestab + Hdr.e32_cbnrestab > offEnd 198 || Hdr.e32_ldrsize > offEnd - offNewHdr - sizeof(Hdr) 199 || Hdr.e32_fixupsize > offEnd - offNewHdr - sizeof(Hdr) 200 || Hdr.e32_fixupsize + Hdr.e32_ldrsize > offEnd - offNewHdr - sizeof(Hdr)) 201 return KLDR_ERR_LX_BAD_HEADER; 202 203 /* Verify the loader section. */ 204 offEnd = Hdr.e32_objtab + Hdr.e32_ldrsize; 205 if (Hdr.e32_objtab < sizeof(Hdr)) 206 return KLDR_ERR_LX_BAD_LOADER_SECTION; 207 off = Hdr.e32_objtab + sizeof(struct o32_obj) * Hdr.e32_objcnt; 208 if (off > offEnd) 209 return KLDR_ERR_LX_BAD_LOADER_SECTION; 210 if ( Hdr.e32_objmap 211 && (Hdr.e32_objmap < off || Hdr.e32_objmap > offEnd)) 212 return KLDR_ERR_LX_BAD_LOADER_SECTION; 213 if ( Hdr.e32_rsrccnt 214 && ( Hdr.e32_rsrctab < off 215 || Hdr.e32_rsrctab > offEnd 216 || Hdr.e32_rsrctab + sizeof(struct rsrc32) * Hdr.e32_rsrccnt > offEnd)) 217 return KLDR_ERR_LX_BAD_LOADER_SECTION; 218 if ( Hdr.e32_restab 219 && (Hdr.e32_restab < off || Hdr.e32_restab > offEnd - 2)) 220 return KLDR_ERR_LX_BAD_LOADER_SECTION; 221 if ( Hdr.e32_enttab 222 && (Hdr.e32_enttab < off || Hdr.e32_enttab > offEnd - 2)) 223 return KLDR_ERR_LX_BAD_LOADER_SECTION; 224 if ( Hdr.e32_dircnt 225 && (Hdr.e32_dirtab < off || Hdr.e32_dirtab > offEnd)) 226 return KLDR_ERR_LX_BAD_LOADER_SECTION; 227 228 /* Verify the fixup section. */ 229 off = offEnd; 230 offEnd = off + Hdr.e32_fixupsize; 231 if ( Hdr.e32_fpagetab 232 && (Hdr.e32_fpagetab < off || Hdr.e32_fpagetab > offEnd)) 233 return KLDR_ERR_LX_BAD_FIXUP_SECTION; 234 if ( Hdr.e32_frectab 235 && (Hdr.e32_frectab < off || Hdr.e32_frectab > offEnd)) 236 return KLDR_ERR_LX_BAD_FIXUP_SECTION; 237 if ( Hdr.e32_impmod 238 && (Hdr.e32_impmod < off || Hdr.e32_impmod > offEnd || Hdr.e32_impmod + Hdr.e32_impmodcnt > offEnd)) 239 return KLDR_ERR_LX_BAD_FIXUP_SECTION; 240 if ( Hdr.e32_impproc 241 && (Hdr.e32_impproc < off || Hdr.e32_impproc > offEnd)) 242 return KLDR_ERR_LX_BAD_FIXUP_SECTION; 243 244 /* 245 * Calc the instance size, allocate and initialize it. 246 */ 247 cchFilename = kLdrHlpStrLen(kLdrRdrName(pRdr)); 248 cb = KLDR_ALIGN_Z(sizeof(KLDRMODLX), 8) 249 + KLDR_ALIGN_Z(KLDR_OFFSETOF(KLDRMOD, aSegments[Hdr.e32_objcnt + 1]), 8) 250 + KLDR_ALIGN_Z(cchFilename + 1, 8), 251 + Hdr.e32_ldrsize; 252 pModLX = (PKLDRMODLX)kldrHlpAlloc(cb); 253 if (!pModLX) 254 return KLDR_ERR_NO_MEMORY; 255 *ppModLX = pModLX; 256 257 /* KLDRMOD */ 258 pMod = (PKLDRMOD)((uint8_t *)pModLX + KLDR_ALIGN_Z(sizeof(KLDRMODLX), 8)); 259 pMod->pvData = pModLX; 260 pMod->pRdr = pRdr; 261 pMod->pOps = NULL; /* set upon success. */ 262 pMod->cSegments = Hdr.e32_objcnt; 263 pMod->cchFilename = cchFilename; 264 pMod->pszFilename = (char *)KLDR_ALIGN_P(&pMod->aSegments[pMod->cSegments], 8); 265 kLdrHlpMemCopy((char *)pMod->pszFilename, kLdrRdrName(pRdr), cchFilename + 1); 266 pMod->pszName = NULL; /* finalized further down */ 267 pMod->cchName = 0; 268 switch (Hdr.e32_cpu) 269 { 270 case E32CPU286: 271 pMod->enmCpu = KLDRCPU_I80286; 272 pMod->enmArch = KLDRARCH_X86_16; 273 break; 274 case E32CPU386: 275 pMod->enmCpu = KLDRCPU_I386; 276 pMod->enmArch = KLDRARCH_X86_32; 277 break; 278 case E32CPU486: 279 pMod->enmCpu = KLDRCPU_I486; 280 pMod->enmArch = KLDRARCH_X86_32; 281 break; 282 } 283 pMod->enmEndian = KLDRENDIAN_LITTLE; 284 pMod->enmFmt = KLDRFMT_LX; 285 switch (Hdr.e32_mflags & E32MODMASK) 286 { 287 case E32MODEXE: 288 pMod->enmType = !(Hdr.e32_mflags & E32NOINTFIX) 289 ? KLDRTYPE_EXECUTABLE_RELOCATABLE 290 : KLDRTYPE_EXECUTABLE_FIXED; 291 break; 292 293 case E32MODDLL: 294 case E32PROTDLL: 295 case E32MODPROTDLL: 296 pMod->enmType = !(Hdr.e32_mflags & E32SYSDLL) 297 ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE 298 : KLDRTYPE_SHARED_LIBRARY_FIXED; 299 break; 300 301 case E32MODPDEV: 302 case E32MODVDEV: 303 pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE; 304 break; 305 } 306 pMod->u32Magic = 0; /* set upon success. */ 307 308 /* KLDRMODLX */ 309 pModLX->pMod = pMod; 310 pModLX->pvMapping = 0; 311 pModLX->cbMapped = Hdr.e32_mpages * Hdr.e32_pagesize; 312 pModLX->f32Reserved = 0; 313 314 pModLX->offHdr = offNewHdr >= 0 ? offNewHdr : 0; 315 pModLX->Hdr = Hdr; 316 317 pModLX->pbLoaderSection = KLDR_ALIGN_P(pMod->pszFilename + pMod->cchFilename + 1, 16); 318 pModLX->pbLoaderSectionLast = pModLX->pbLoaderSection + pModLX->Hdr.e32_ldrsize; 319 pModLX->paObjs = NULL; 320 pModLX->paPageMappings = NULL; 321 pModLX->paRsrcs = NULL; 322 pModLX->pbResNameTab = NULL; 323 pModLX->pbEntryTab = NULL; 324 325 pModLX->pbNonResNameTab = NULL; 326 pModLX->pbNonResNameTabLast = NULL; 327 328 pModLX->pbFixupSection = NULL; 329 pModLX->pbFixupSectionLast = NULL; 330 pModLX->paoffPageFixups = NULL; 331 pModLX->pbFixupRecs = NULL; 332 pModLX->pbImportMods = NULL; 333 pModLX->pbImportProcs = NULL; 334 335 /* 336 * Read the loader data. 337 */ 338 rc = kLdrRdrRead(pRdr, (void *)pModLX->pbLoaderSection, pModLX->Hdr.e32_ldrsize, pModLX->Hdr.e32_objtab + pModLX->offHdr); 339 if (rc) 340 return rc; 341 if (pModLX->Hdr.e32_objcnt) 342 pModLX->paObjs = (const struct o32_obj *)pModLX->pbLoaderSection; 343 if (pModLX->Hdr.e32_objmap) 344 pModLX->paPageMappings = (const struct o32_map *)(pModLX->pbLoaderSection + pModLX->Hdr.e32_objmap - pModLX->Hdr.e32_objtab); 345 if (pModLX->Hdr.e32_rsrccnt) 346 pModLX->paRsrcs = (const struct rsrc32 *)(pModLX->pbLoaderSection + pModLX->Hdr.e32_rsrctab - pModLX->Hdr.e32_objtab); 347 if (pModLX->Hdr.e32_restab) 348 pModLX->pbResNameTab = pModLX->pbLoaderSection + pModLX->Hdr.e32_restab - pModLX->Hdr.e32_objtab; 349 if (pModLX->Hdr.e32_enttab) 350 pModLX->pbEntryTab = pModLX->pbLoaderSection + pModLX->Hdr.e32_enttab - pModLX->Hdr.e32_objtab; 351 352 /* 353 * Get the soname from the resident name table. 354 */ 355 /** @todo */ 356 357 /* 358 * Quick validation of the object table. 359 */ 360 cb = 0; 361 for (i = 0; i < pMod->cSegments; i++) 362 { 363 if (pModLX->paObjs[i].o32_base & (OBJPAGELEN - 1)) 364 return KLDR_ERR_LX_BAD_OBJECT_TABLE; 365 if (pModLX->paObjs[i].o32_base + pModLX->paObjs[i].o32_size <= pModLX->paObjs[i].o32_base) 366 return KLDR_ERR_LX_BAD_OBJECT_TABLE; 367 if (pModLX->paObjs[i].o32_mapsize > pModLX->paObjs[i].o32_size / OBJPAGELEN) 368 return KLDR_ERR_LX_BAD_OBJECT_TABLE; 369 if ( pModLX->paObjs[i].o32_mapsize 370 && ( (uint8_t *)&pModLX->paPageMappings[pModLX->paObjs[i].o32_pagemap] > pModLX->pbLoaderSectionLast 371 || (uint8_t *)&pModLX->paPageMappings[pModLX->paObjs[i].o32_pagemap + pModLX->paObjs[i].o32_mapsize] 372 > pModLX->pbLoaderSectionLast)) 373 return KLDR_ERR_LX_BAD_OBJECT_TABLE; 374 if (i > 0) 375 { 376 if (pModLX->paObjs[i].o32_base <= pModLX->paObjs[i - 1].o32_base) 377 return KLDR_ERR_LX_BAD_OBJECT_TABLE; 378 if (pModLX->paObjs[i].o32_base < pModLX->paObjs[i - 1].o32_base + pModLX->paObjs[i - 1].o32_mapsize) 379 return KLDR_ERR_LX_BAD_OBJECT_TABLE; 380 } 381 } 382 pModLX->cbMapped = pMod->cSegments 383 ? pModLX->paObjs[pMod->cSegments - 1].o32_base + pModLX->paObjs[pMod->cSegments - 1].o32_size 384 - pModLX->paObjs[pMod->cSegments - 1].o32_size 385 : 0; 386 387 /* 388 * Setup the KLDRMOD segment array. 389 */ 390 for (i = 0; i < pMod->cSegments; i++) 391 { 392 /* unused */ 393 pMod->aSegments[i].pvUser = NULL; 394 pMod->aSegments[i].MapAddress = 0; 395 pMod->aSegments[i].pchName = NULL; 396 pMod->aSegments[i].cchName = 0; 397 pMod->aSegments[i].offFile = -1; 398 pMod->aSegments[i].cbFile = 0; 399 400 /* size and addresses */ 401 pMod->aSegments[i].Alignment = OBJPAGELEN; 402 pMod->aSegments[i].cb = pModLX->paObjs[i].o32_size; 403 pMod->aSegments[i].LinkAddress = pModLX->paObjs[i].o32_base; 404 pMod->aSegments[i].RVA = pModLX->paObjs[i].o32_base - pModLX->paObjs[0].o32_base; 405 pMod->aSegments[i].cbMapped = KLDR_ALIGN_Z(pModLX->paObjs[i].o32_size, 16); 406 if (i + 1 < pMod->cSegments) 407 pMod->aSegments[i].cbMapped = pModLX->paObjs[i + 1].o32_base - pModLX->paObjs[i].o32_base; 408 409 /* protection */ 410 switch ( pModLX->paObjs[i].o32_flags 411 & (OBJSHARED | OBJREAD | OBJWRITE | OBJEXEC)) 412 { 413 case 0: 414 case OBJSHARED: 415 pMod->aSegments[i].enmProt = KLDRPROT_NOACCESS; 416 break; 417 case OBJREAD: 418 case OBJREAD | OBJSHARED: 419 pMod->aSegments[i].enmProt = KLDRPROT_READONLY; 420 break; 421 case OBJWRITE: 422 case OBJWRITE | OBJREAD: 423 pMod->aSegments[i].enmProt = KLDRPROT_WRITECOPY; 424 break; 425 case OBJWRITE | OBJSHARED: 426 case OBJWRITE | OBJSHARED | OBJREAD: 427 pMod->aSegments[i].enmProt = KLDRPROT_READWRITE; 428 break; 429 case OBJEXEC: 430 case OBJEXEC | OBJSHARED: 431 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE; 432 break; 433 case OBJEXEC | OBJREAD: 434 case OBJEXEC | OBJREAD | OBJSHARED: 435 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE_READ; 436 break; 437 case OBJEXEC | OBJWRITE: 438 case OBJEXEC | OBJWRITE | OBJREAD: 439 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE_WRITECOPY; 440 break; 441 case OBJEXEC | OBJWRITE | OBJSHARED: 442 case OBJEXEC | OBJWRITE | OBJSHARED | OBJREAD: 443 pMod->aSegments[i].enmProt = KLDRPROT_EXECUTE_READWRITE; 444 break; 445 } 446 if ((pModLX->paObjs[i].o32_flags & (OBJREAD | OBJWRITE | OBJEXEC | OBJRSRC)) == OBJRSRC) 447 pMod->aSegments[i].enmProt = KLDRPROT_READONLY; 448 //pMod->aSegments[i].f16bit = !(pModLX->paObjs[i].o32_flags & OBJBIGDEF) 449 //pMod->aSegments[i].fIOPL = !(pModLX->paObjs[i].o32_flags & OBJIOPL) 450 //pMod->aSegments[i].fConforming = !(pModLX->paObjs[i].o32_flags & OBJCONFORM) 451 } 452 453 /* 454 * We're done. 455 */ 456 *ppModLX = pModLX; 457 return 0; 458 } 459 460 461 /** @copydoc KLDRMODOPS::pfnDestroy */ 462 static int kldrModLXDestroy(PKLDRMOD pMod) 463 { 464 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 465 int rc = 0; 466 KLDRMODLX_ASSERT(pModLX->pvMapping); 467 468 if (pMod->pRdr) 469 { 470 rc = kLdrRdrClose(pMod->pRdr); 471 pMod->pRdr = NULL; 472 } 473 if (pModLX->pbNonResNameTab) 474 { 475 kldrHlpFree(pModLX->pbNonResNameTab); 476 pModLX->pbNonResNameTab = NULL; 477 } 478 if (pModLX->pbFixupSection) 479 { 480 kldrHlpFree(pModLX->pbFixupSection); 481 pModLX->pbFixupSection = NULL; 482 } 483 if (pMod->pszName) 484 { 485 kldrHlpFree((void *)pMod->pszName); 486 pMod->pszName = NULL; 487 } 488 pMod->u32Magic = 0; 489 pMod->pOps = NULL; 490 kldrHlpFree(pModLX); 491 return rc; 492 } 493 494 495 /** 496 * Resolved base address aliases. 497 * 498 * @param pModLX The interpreter module instance 499 * @param pBaseAddress The base address, IN & OUT. 500 */ 501 static void kldrModLXResolveBaseAddress(PKLDRMODLX pModLX, PKLDRADDR pBaseAddress) 502 { 503 if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP) 504 *pBaseAddress = pModLX->pMod->aSegments[0].MapAddress; 505 else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK) 506 *pBaseAddress = pModLX->pMod->aSegments[0].LinkAddress; 507 } 508 509 510 /** @copydoc kLdrModQuerySymbol */ 511 static int kldrModLXQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t iSymbol, 512 const char *pszSymbol, PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, 513 PKLDRADDR puValue, uint32_t *pfKind) 514 { 515 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 516 //int rc; 517 518 kldrModLXResolveBaseAddress(pModLX, &BaseAddress); 519 520 return -1; 521 } 522 523 524 /** @copydoc kLdrModEnumSymbols */ 525 static int kldrModLXEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, 526 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) 527 { 528 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 529 // int rc; 530 531 kldrModLXResolveBaseAddress(pModLX, &BaseAddress); 532 533 return -1; 534 } 535 536 537 /** @copydoc kLdrModGetImport */ 538 static int kldrModLXGetImport(PKLDRMOD pMod, const void *pvBits, uint32_t iImport, char *pszName, size_t cchName) 539 { 540 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 541 const uint8_t * pb = NULL; 542 int rc; 543 544 /** @todo */ 545 546 if (*pb < cchName) 547 { 548 kLdrHlpMemCopy(pszName, pb + 1, *pb); 549 pszName[*pb] = '\0'; 550 rc = 0; 551 } 552 else 553 { 554 kLdrHlpMemCopy(pszName, pb + 1, cchName); 555 if (cchName) 556 pszName[cchName - 1] = '\0'; 557 rc = KLDR_ERR_BUFFER_OVERFLOW; 558 } 559 560 return rc; 561 } 562 563 564 /** @copydoc kLdrModNumberOfImports */ 565 static int32_t kldrModLXNumberOfImports(PKLDRMOD pMod, const void *pvBits) 566 { 567 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 568 return pModLX->Hdr.e32_impmodcnt; 569 } 570 571 572 /** @copydoc kLdrModGetStackInfo */ 573 static int kldrModLXGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo) 574 { 575 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 576 const uint32_t i = pModLX->Hdr.e32_stackobj; 577 578 if ( i 579 && i <= pMod->cSegments 580 && pModLX->Hdr.e32_esp <= pMod->aSegments[i - 1].LinkAddress + pMod->aSegments[i - 1].cb 581 && pModLX->Hdr.e32_stacksize 582 && pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize >= pMod->aSegments[i - 1].LinkAddress) 583 { 584 585 kldrModLXResolveBaseAddress(pModLX, &BaseAddress); 586 pStackInfo->LinkAddress = pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize; 587 pStackInfo->Address = BaseAddress 588 + pMod->aSegments[i - 1].RVA 589 + pModLX->Hdr.e32_esp - pModLX->Hdr.e32_stacksize - pMod->aSegments[i - 1].LinkAddress; 590 } 591 else 592 { 593 pStackInfo->Address = NIL_KLDRADDR; 594 pStackInfo->LinkAddress = NIL_KLDRADDR; 595 } 596 pStackInfo->cbStack = pModLX->Hdr.e32_stacksize; 597 pStackInfo->cbStackThread = 0; 598 599 return 0; 600 } 601 602 603 /** @copydoc kLdrModQueryMainEntrypoint */ 604 static int kldrModLXQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress) 605 { 606 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 607 608 /* 609 * Convert the address from the header. 610 */ 611 kldrModLXResolveBaseAddress(pModLX, &BaseAddress); 612 *pMainEPAddress = pModLX->Hdr.e32_startobj 613 && pModLX->Hdr.e32_startobj <= pMod->cSegments 614 && pModLX->Hdr.e32_eip < pMod->aSegments[pModLX->Hdr.e32_startobj - 1].cb 615 ? BaseAddress + pMod->aSegments[pModLX->Hdr.e32_startobj - 1].RVA + pModLX->Hdr.e32_eip 616 : NIL_KLDRADDR; 617 return 0; 618 } 619 620 621 /** @copydoc kLdrModEnumDbgInfo */ 622 static int kldrModLXEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser) 623 { 624 //PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 625 626 /* 627 * Quit immediately if no debug info. 628 */ 629 if (kldrModLXHasDbgInfo(pMod, pvBits)) 630 return 0; 631 #if 0 632 /* 633 * Read the debug info and look for familiar magics and structures. 634 */ 635 /** @todo */ 636 #endif 637 638 return 0; 639 } 640 641 642 /** @copydoc kLdrModHasDbgInfo */ 643 static int kldrModLXHasDbgInfo(PKLDRMOD pMod, const void *pvBits) 644 { 645 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 646 647 /* 648 * Don't curretnly bother with linkers which doesn't advertise it in the header. 649 */ 650 if ( !pModLX->Hdr.e32_debuginfo 651 || !pModLX->Hdr.e32_debuglen) 652 return KLDR_ERR_NO_DEBUG_INFO; 653 return 0; 654 } 655 656 657 /** @copydoc kLdrModMap */ 658 static int kldrModLXMap(PKLDRMOD pMod) 659 { 660 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 661 unsigned fFixed; 662 void *pvBase; 663 int rc; 664 665 /* 666 * Already mapped? 667 */ 668 if (pModLX->pvMapping) 669 return KLDR_ERR_ALREADY_MAPPED; 670 671 /* 672 * Allocate memory for it. 673 */ 674 /* fixed image? */ 675 fFixed = pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED 676 || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED; 677 if (!fFixed) 678 pvBase = NULL; 679 else 680 { 681 pvBase = (void *)(uintptr_t)pMod->aSegments[0].LinkAddress; 682 if ((uintptr_t)pvBase != pMod->aSegments[0].LinkAddress) 683 return KLDR_ERR_ADDRESS_OVERFLOW; 684 } 685 rc = kldrHlpPageAlloc(&pvBase, pModLX->cbMapped, KLDRPROT_EXECUTE_READWRITE, fFixed); 686 if (rc) 687 return rc; 688 689 /* 690 * Load the bits, apply page protection, and update the segment table. 691 */ 692 rc = kldrModLXDoLoadBits(pModLX, pvBase); 693 if (!rc) 694 rc = kldrModLXDoProtect(pModLX, pvBase, 0 /* protect */); 695 if (!rc) 696 { 697 uint32_t i; 698 for (i = 0; i < pMod->cSegments; i++) 699 { 700 if (pMod->aSegments[i].RVA != NIL_KLDRADDR) 701 pMod->aSegments[i].MapAddress = (uintptr_t)pvBase + (uintptr_t)pMod->aSegments[i].RVA; 702 } 703 pModLX->pvMapping = pvBase; 704 } 705 else 706 kldrHlpPageFree(pvBase, pModLX->cbMapped); 707 return rc; 708 } 709 710 711 /** 712 * Loads the LX pages into the specified memory mapping. 713 * 714 * @returns 0 on success. 715 * @returns non-zero kLdr or OS status code on failure. 716 * 717 * @param pModLX The LX module interpreter instance. 718 * @param pvBits Where to load the bits. 719 */ 720 static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits) 721 { 722 //E32NOLOAD 723 724 return -1; 725 } 726 727 728 /** 729 * Unprotects or protects the specified image mapping. 730 * 731 * @returns 0 on success. 732 * @returns non-zero kLdr or OS status code on failure. 733 * 734 * @param pModLX The LX module interpreter instance. 735 * @param pvBits The mapping to protect. 736 * @param UnprotectOrProtect If 1 unprotect (i.e. make all writable), otherwise 737 * protect according to the object table. 738 */ 739 static int kldrModLXDoProtect(PKLDRMODLX pMod, void *pvBits, unsigned fUnprotectOrProtect) 740 { 741 return -1; 742 } 743 744 745 /** @copydoc kLdrModUnmap */ 746 static int kldrModLXUnmap(PKLDRMOD pMod) 747 { 748 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 749 uint32_t i; 750 int rc; 751 752 /* 753 * Mapped? 754 */ 755 if (!pModLX->pvMapping) 756 return KLDR_ERR_NOT_MAPPED; 757 758 /* 759 * Free the mapping and update the segments. 760 */ 761 rc = kldrHlpPageFree((void *)pModLX->pvMapping, pModLX->cbMapped); 762 KLDRMODLX_ASSERT(!rc); 763 pModLX->pvMapping = NULL; 764 765 for (i = 0; i < pMod->cSegments; i++) 766 pMod->aSegments[i].MapAddress = 0; 767 768 return rc; 769 } 770 771 772 /** @copydoc kLdrModAllocTLS */ 773 static int kldrModLXAllocTLS(PKLDRMOD pMod) 774 { 775 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 776 777 /* just do the error checking. */ 778 if (!pModLX->pvMapping) 779 return KLDR_ERR_NOT_MAPPED; 780 return 0; 781 } 782 783 784 /** @copydoc kLdrModFreeTLS */ 785 static void kldrModLXFreeTLS(PKLDRMOD pMod) 786 { 787 } 788 789 790 /** @copydoc kLdrModReload */ 791 static int kldrModLXReload(PKLDRMOD pMod) 792 { 793 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 794 795 /* 796 * Mapped? 797 */ 798 if (!pModLX->pvMapping) 799 return KLDR_ERR_NOT_MAPPED; 800 801 /* the file provider does it all */ 802 return kLdrRdrRefresh(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments); 803 } 804 805 806 /** @copydoc kLdrModFixupMapping */ 807 static int kldrModLXFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 808 { 809 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 810 int rc, rc2; 811 812 /* 813 * Mapped? 814 */ 815 if (!pModLX->pvMapping) 816 return KLDR_ERR_NOT_MAPPED; 817 818 /* 819 * Before doing anything we'll have to make all pages writable. 820 */ 821 rc = kLdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */); 822 if (rc) 823 return rc; 824 825 /* 826 * Apply fixups and resolve imports. 827 */ 828 rc = kldrModLXRelocateBits(pMod, (void *)pModLX->pvMapping, (uintptr_t)pModLX->pvMapping, 829 pMod->aSegments[0].LinkAddress, pfnGetImport, pvUser); 830 831 /* 832 * Restore protection. 833 */ 834 rc2 = kLdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */); 835 if (!rc && rc2) 836 rc = rc2; 837 return rc; 838 } 839 840 841 /** @copydoc kLdrModCallInit */ 842 static int kldrModLXCallInit(PKLDRMOD pMod, uintptr_t uHandle) 843 { 844 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 845 int rc; 846 847 /* 848 * Mapped? 849 */ 850 if (!pModLX->pvMapping) 851 return KLDR_ERR_NOT_MAPPED; 852 853 /* 854 * Do TLS callbacks first and then call the init/term function if it's a DLL. 855 */ 856 if ((pModLX->Hdr.e32_mflags & E32MODMASK) == E32MODDLL) 857 rc = kldrModLXDoCallDLL(pModLX, 0 /* attach */, uHandle); 858 else 859 rc = 0; 860 return rc; 861 } 862 863 864 /** 865 * Call the DLL entrypoint. 866 * 867 * @returns 0 on success. 868 * @returns KLDR_ERR_MODULE_INIT_FAILED or KLDR_ERR_THREAD_ATTACH_FAILED on failure. 869 * @param pModLX The LX module interpreter instance. 870 * @param uOp The operation (DLL_*). 871 * @param uHandle The module handle to present. 872 */ 873 static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, unsigned uOp, uintptr_t uHandle) 874 { 875 int rc; 876 877 /* 878 * If no entrypoint there isn't anything to be done. 879 */ 880 if ( !pModLX->Hdr.e32_startobj 881 || pModLX->Hdr.e32_startobj > pModLX->Hdr.e32_objcnt) 882 return 0; 883 884 /* 885 * Invoke the entrypoint and convert the boolean result to a kLdr status code. 886 */ 887 rc = kldrModLXDoCall((uintptr_t)pModLX->pvMapping 888 + (uintptr_t)pModLX->pMod->aSegments[pModLX->Hdr.e32_startobj - 1].RVA 889 + pModLX->Hdr.e32_eip, 890 uHandle, uOp, NULL); 891 if (rc) 892 rc = 0; 893 else if (uOp == 0 /* attach */) 894 rc = KLDR_ERR_MODULE_INIT_FAILED; 895 else /* detach: ignore failures */ 896 rc = 0; 897 return rc; 898 } 899 900 901 /** 902 * Do a 3 parameter callback. 903 * 904 * @returns 32-bit callback return. 905 * @param uEntrypoint The address of the function to be called. 906 * @param uHandle The first argument, the module handle. 907 * @param uOp The second argumnet, the reason we're calling. 908 * @param pvReserved The third argument, reserved argument. (figure this one out) 909 */ 910 static int32_t kldrModLXDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved) 911 { 912 #if defined(__X86__) || defined(__i386__) || defined(_M_IX86) 913 int32_t rc; 914 /** @todo try/except */ 915 916 /* 917 * Paranoia. 918 */ 919 # ifdef __GNUC__ 920 __asm__ __volatile__( 921 "pushl %2\n\t" 922 "pushl %1\n\t" 923 "pushl %0\n\t" 924 "lea 12(%%esp), %2\n\t" 925 "call *%3\n\t" 926 "movl %2, %%esp\n\t" 927 : "=a" (rc) 928 : "d" (uOp), 929 "S" (0), 930 "c" (uEntrypoint), 931 "0" (uHandle)); 932 # elif defined(_MSC_VER) 933 __asm { 934 mov eax, [uHandle] 935 mov edx, [uOp] 936 mov ecx, 0 937 mov ebx, [uEntrypoint] 938 push edi 939 mov edi, esp 940 push ecx 941 push edx 942 push eax 943 call ebx 944 mov esp, edi 945 pop edi 946 mov [rc], eax 947 } 948 # else 949 # error "port me!" 950 # endif 951 return rc; 952 953 #else 954 return KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; 955 #endif 956 } 957 958 959 /** @copydoc kLdrModCallTerm */ 960 static int kldrModLXCallTerm(PKLDRMOD pMod, uintptr_t uHandle) 961 { 962 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 963 964 /* 965 * Mapped? 966 */ 967 if (!pModLX->pvMapping) 968 return KLDR_ERR_NOT_MAPPED; 969 970 /* 971 * Do the call. 972 */ 973 if ((pModLX->Hdr.e32_mflags & E32MODMASK) == E32MODDLL) 974 kldrModLXDoCallDLL(pModLX, 1 /* detach */, uHandle); 975 976 return 0; 977 } 978 979 980 /** @copydoc kLdrModCallThread */ 981 static int kldrModLXCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching) 982 { 983 return 0; 984 } 985 986 987 /** @copydoc kLdrModSize */ 988 static KLDRADDR kldrModLXSize(PKLDRMOD pMod) 989 { 990 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 991 return pModLX->cbMapped; 992 } 993 994 995 /** @copydoc kLdrModGetBits */ 996 static int kldrModLXGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 997 { 998 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 999 int rc; 1000 1001 /* 1002 * Load the image bits. 1003 */ 1004 rc = kldrModLXDoLoadBits(pModLX, pvBits); 1005 if (rc) 1006 return rc; 1007 1008 /* 1009 * Perform relocations. 1010 */ 1011 return kldrModLXRelocateBits(pMod, pvBits, BaseAddress, pMod->aSegments[0].LinkAddress, pfnGetImport, pvUser); 1012 1013 } 1014 1015 1016 /** @copydoc kLdrModRelocateBits */ 1017 static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 1018 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 1019 { 1020 //PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 1021 //int rc; 1022 1023 /** @todo Implement this. */ 1024 1025 return -1; 1026 } 1027 1028 1029 /** 1030 * The LX module interpreter method table. 1031 */ 1032 KLDRMODOPS g_kLdrModLXOps = 1033 { 1034 "LX", 1035 NULL, 1036 kldrModLXCreate, 1037 kldrModLXDestroy, 1038 kldrModLXQuerySymbol, 1039 kldrModLXEnumSymbols, 1040 kldrModLXGetImport, 1041 kldrModLXNumberOfImports, 1042 NULL /* can execute one is optional */, 1043 kldrModLXGetStackInfo, 1044 kldrModLXQueryMainEntrypoint, 1045 kldrModLXEnumDbgInfo, 1046 kldrModLXHasDbgInfo, 1047 kldrModLXMap, 1048 kldrModLXUnmap, 1049 kldrModLXAllocTLS, 1050 kldrModLXFreeTLS, 1051 kldrModLXReload, 1052 kldrModLXFixupMapping, 1053 kldrModLXCallInit, 1054 kldrModLXCallTerm, 1055 kldrModLXCallThread, 1056 kldrModLXSize, 1057 kldrModLXGetBits, 1058 kldrModLXRelocateBits, 1059 42 /* the end */ 1060 }; 1061
Note:
See TracChangeset
for help on using the changeset viewer.