source: trunk/kLdr/kLdrModMachO.c@ 2952

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

Mach-O in process (very early).

File size: 59.7 KB
Line 
1/* $Id: $ */
2/** @file
3 *
4 * kLdr - The Module Interpreter for the MACH-O format.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@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
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <kLdr.h>
32#include "kLdrHlp.h"
33#include "kLdrInternal.h"
34#include "kLdrModMachO.h"
35
36
37/*******************************************************************************
38* Defined Constants And Macros *
39*******************************************************************************/
40/** @def KLDRMODMACHO_STRICT
41 * Define KLDRMODMACHO_STRICT to enabled strict checks in KLDRMODMACHO. */
42#define KLDRMODMACHO_STRICT 1
43
44/** @def KLDRMODMACHO_ASSERT
45 * Assert that an expression is true when KLDR_STRICT is defined.
46 */
47#ifdef KLDRMODMACHO_STRICT
48# define KLDRMODMACHO_ASSERT(expr) kldrHlpAssert(expr)
49#else
50# define KLDRMODMACHO_ASSERT(expr) do {} while (0)
51#endif
52
53/** @def KLDRMODMACHO_RVA2TYPE
54 * Converts a RVA to a pointer of the specified type.
55 * @param pvBits The bits (image base).
56 * @param uRVA The image relative virtual address.
57 * @param type The type to cast to.
58 */
59#define KLDRMODMACHO_RVA2TYPE(pvBits, uRVA, type) \
60 ( (type) ((uintptr_t)(pvBits) + (uintptr_t)(uRVA)) )
61
62/** @def KLDRMODMACHO_VALID_RVA
63 * Checks that the specified RVA value is non-zero and within the bounds of the image.
64 * @returns true/false.
65 * @param pModPE The PE module interpreter instance.
66 * @param uRVA The RVA to validate.
67 */
68#define KLDRMODMACHO_VALID_RVA(pModPE, uRVA) \
69 ( (uRVA) && (uRVA) < (pModPE)->Hdrs.OptionalHeader.SizeOfImage )
70
71
72
73/*******************************************************************************
74* Structures and Typedefs *
75*******************************************************************************/
76/**
77 * Instance data for the MACH-O MH_OBJECT module interpreter.
78 * @todo interpret the other MH_* formats.
79 */
80typedef struct KLDRMODMACHO
81{
82 /** Pointer to the module. (Follows the section table.) */
83 PKLDRMOD pMod;
84 /** Pointer to the RDR mapping of the raw file bits. NULL if not mapped. */
85 const void *pvBits;
86 /** Pointer to the user mapping. */
87 const void *pvMapping;
88
89 /** The link address. */
90 KLDRADDR LinkAddress;
91
92 /** Pointer to the load commands. (endian converted) */
93 uint8_t *pbLoadCommands;
94 /** The Mach-O header. (endian converted)
95 * @remark The reserved field is only valid for real 64-bit headers. */
96 mach_header_64_t Hdr;
97
98 /** The offset of the symbol table. */
99 off_t offSymbols;
100 /** The number of symbols. */
101 uint32_t cSymbols;
102 /** The pointer to the loaded symbol table. */
103 void *paSymbols;
104 /** The offset of the string table. */
105 off_t offStrings;
106 /** The size of the of the string table. */
107 uint32_t cbStrings;
108 /** Pointer to the loaded string table. */
109 char *pbStrings;
110} KLDRMODMACHO, *PKLDRMODMACHO;
111
112
113/*******************************************************************************
114* Internal Functions *
115*******************************************************************************/
116#if 0
117static int32_t kldrModMachONumberOfImports(PKLDRMOD pMod, const void *pvBits);
118static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
119 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
120#endif
121
122static int kldrModMachODoCreate(PKLDRRDR pRdr, PKLDRMODMACHO *ppMod);
123static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr,
124 uint32_t *pcSegments, uint32_t *pcbStringPool);
125static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool);
126
127#if 0
128/*static void kldrModMachODoLoadConfigConversion(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg); */
129static int kLdrModPEDoOptionalHeaderValidation(PKLDRMODMACHO pModMachO);
130static int kLdrModPEDoSectionHeadersValidation(PKLDRMODMACHO pModMachO);
131static int kldrModMachODoForwarderQuery(PKLDRMODMACHO pModMachO, const void *pvBits, const char *pszForwarder,
132 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind);
133static int kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
134static int kldrModMachODoImports32Bit(PKLDRMODMACHO pModMachO, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
135 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
136static int kldrModMachODoImports64Bit(PKLDRMODMACHO pModMachO, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
137 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
138static int kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
139static int kldrModMachODoCallDLL(PKLDRMODMACHO pModMachO, unsigned uOp, uintptr_t uHandle);
140static int kldrModMachODoCallTLS(PKLDRMODMACHO pModMachO, unsigned uOp, uintptr_t uHandle);
141static int32_t kldrModMachODoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved);
142#endif
143
144
145/**
146 * Create a loader module instance interpreting the executable image found
147 * in the specified file provider instance.
148 *
149 * @returns 0 on success and *ppMod pointing to a module instance.
150 * On failure, a non-zero OS specific error code is returned.
151 * @param pOps Pointer to the registered method table.
152 * @param pRdr The file provider instance to use.
153 * @param offNewHdr The offset of the new header in MZ files. -1 if not found.
154 * @param ppMod Where to store the module instance pointer.
155 */
156static int kldrModMachOCreate(PCKLDRMODOPS pOps, PKLDRRDR pRdr, off_t offNewHdr, PPKLDRMOD ppMod)
157{
158 PKLDRMODMACHO pModMachO;
159 int rc;
160
161 /*
162 * Create the instance data and do a minimal header validation.
163 */
164 rc = kldrModMachODoCreate(pRdr, &pModMachO);
165 if (!rc)
166 {
167 pModMachO->pMod->pOps = pOps;
168 pModMachO->pMod->u32Magic = KLDRMOD_MAGIC;
169 *ppMod = pModMachO->pMod;
170 return 0;
171 }
172 if (pModMachO)
173 {
174 kldrHlpFree(pModMachO->pbLoadCommands);
175 kldrHlpFree(pModMachO);
176 }
177 return rc;
178}
179
180
181/**
182 * Separate function for reading creating the PE module instance to
183 * simplify cleanup on failure.
184 */
185static int kldrModMachODoCreate(PKLDRRDR pRdr, PKLDRMODMACHO *ppModMachO)
186{
187 union
188 {
189 mach_header_32_t Hdr32;
190 mach_header_64_t Hdr64;
191 } s;
192 PKLDRMODMACHO pModMachO;
193 PKLDRMOD pMod;
194 uint8_t *pbLoadCommands;
195 uint32_t cSegments;
196 uint32_t cbStringPool;
197 size_t cchFilename;
198 size_t cb;
199 int rc;
200 *ppModMachO = NULL;
201
202 /*
203 * Read the Mach-O header.
204 */
205 rc = kLdrRdrRead(pRdr, &s, sizeof(s), 0);
206 if (rc)
207 return rc;
208 if (s.Hdr32.magic != IMAGE_MACHO32_SIGNATURE)
209 {
210 if ( s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE
211 || s.Hdr32.magic == IMAGE_MACHO64_SIGNATURE_OE)
212 return KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED;
213 if (s.Hdr32.magic == IMAGE_MACHO64_SIGNATURE)
214 return KLDR_ERR_MACHO_64BIT_NOT_SUPPORTED;
215 return KLDR_ERR_UNKNOWN_FORMAT;
216 }
217
218 /* sanity checks. */
219 if ( s.Hdr32.sizeofcmds > kLdrRdrSize(pRdr) - sizeof(mach_header_32_t)
220 || s.Hdr32.sizeofcmds < sizeof(load_command_t) * s.Hdr32.ncmds
221 || (s.Hdr32.flags & ~MH_VALID_FLAGS))
222 return KLDR_ERR_MACHO_BAD_HEADER;
223 switch (s.Hdr32.cputype)
224 {
225 case CPU_TYPE_X86:
226 case CPU_TYPE_X86_64:
227 break;
228 default:
229 return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
230 }
231 if (s.Hdr32.filetype != MH_OBJECT)
232 return KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE;
233
234 /*
235 * Read and pre-parse the load commands to figure out how many segments we'll be needing.
236 */
237 pbLoadCommands = kldrHlpAlloc(s.Hdr32.sizeofcmds);
238 if (!pbLoadCommands)
239 return KLDR_ERR_NO_MEMORY;
240 rc = kLdrRdrRead(pRdr, pbLoadCommands, s.Hdr32.sizeofcmds,
241 s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE
242 || s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE
243 ? sizeof(mach_header_32_t) : sizeof(mach_header_64_t));
244 if (!rc)
245 rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, &cSegments, &cbStringPool);
246 if (rc)
247 {
248 kldrHlpFree(pbLoadCommands);
249 return rc;
250 }
251
252
253 /*
254 * Calc the instance size, allocate and initialize it.
255 */
256 cchFilename = kLdrHlpStrLen(kLdrRdrName(pRdr));
257 cb = KLDR_ALIGN_Z(sizeof(KLDRMODMACHO), 16)
258 + KLDR_OFFSETOF(KLDRMOD, aSegments[cSegments])
259 + cchFilename + 1
260 + cbStringPool;
261 pModMachO = (PKLDRMODMACHO)kldrHlpAlloc(cb);
262 if (!pModMachO)
263 return KLDR_ERR_NO_MEMORY;
264 *ppModMachO = pModMachO;
265 pModMachO->pbLoadCommands = pbLoadCommands;
266
267 /* KLDRMOD */
268 pMod = (PKLDRMOD)((uint8_t *)pModMachO + KLDR_ALIGN_Z(sizeof(KLDRMODMACHO), 16));
269 pMod->pvData = pModMachO;
270 pMod->pRdr = pRdr;
271 pMod->pOps = NULL; /* set upon success. */
272 pMod->cSegments = cSegments;
273 pMod->cchFilename = cchFilename;
274 pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments];
275 kLdrHlpMemCopy((char *)pMod->pszFilename, kLdrRdrName(pRdr), cchFilename + 1);
276 pMod->pszName = kldrHlpGetFilename(pMod->pszFilename);
277 pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename);
278 switch (s.Hdr32.cputype)
279 {
280 case CPU_TYPE_X86:
281 pMod->enmArch = KLDRARCH_X86_32;
282 pMod->enmEndian = KLDRENDIAN_LITTLE;
283 switch (s.Hdr32.cpusubtype)
284 {
285 case CPU_SUBTYPE_I386_ALL: pMod->enmCpu = KLDRCPU_X86_32_BLEND; break;
286 /*case CPU_SUBTYPE_386: ^^ pMod->enmCpu = KLDRCPU_I386; break;*/
287 case CPU_SUBTYPE_486: pMod->enmCpu = KLDRCPU_I486; break;
288 case CPU_SUBTYPE_486SX: pMod->enmCpu = KLDRCPU_I486SX; break;
289 /*case CPU_SUBTYPE_586: vv */
290 case CPU_SUBTYPE_PENT: pMod->enmCpu = KLDRCPU_I586; break;
291 case CPU_SUBTYPE_PENTPRO:
292 case CPU_SUBTYPE_PENTII_M3:
293 case CPU_SUBTYPE_PENTII_M5:
294 case CPU_SUBTYPE_CELERON:
295 case CPU_SUBTYPE_CELERON_MOBILE:
296 case CPU_SUBTYPE_PENTIUM_3:
297 case CPU_SUBTYPE_PENTIUM_3_M:
298 case CPU_SUBTYPE_PENTIUM_3_XEON: pMod->enmCpu = KLDRCPU_I686; break;
299 case CPU_SUBTYPE_PENTIUM_M:
300 case CPU_SUBTYPE_PENTIUM_4:
301 case CPU_SUBTYPE_PENTIUM_4_M:
302 case CPU_SUBTYPE_XEON:
303 case CPU_SUBTYPE_XEON_MP: pMod->enmCpu = KLDRCPU_P4; break;
304 break;
305 default:
306 return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
307 }
308 break;
309
310 case CPU_TYPE_X86_64:
311 pMod->enmArch = KLDRARCH_AMD64;
312 pMod->enmEndian = KLDRENDIAN_LITTLE;
313 switch (s.Hdr32.cpusubtype)
314 {
315 case CPU_SUBTYPE_X86_64_ALL: pMod->enmCpu = KLDRCPU_AMD64_BLEND; break;
316 default:
317 return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
318 }
319 break;
320
321 default:
322 return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
323 }
324
325 pMod->enmFmt = KLDRFMT_MACHO;
326 switch (s.Hdr32.filetype)
327 {
328 case MH_OBJECT:
329 pMod->enmType = KLDRTYPE_OBJECT;
330 break;
331 default:
332 return KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE;
333 }
334 pMod->u32Magic = 0; /* set upon success. */
335
336 /* KLDRMODMACHO */
337 pModMachO->pMod = pMod;
338 pModMachO->pvBits = NULL;
339 pModMachO->pvMapping = NULL;
340 pModMachO->Hdr = s.Hdr64;
341 if ( s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE
342 || s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE)
343 pModMachO->Hdr.reserved = 0;
344 pModMachO->LinkAddress = 0;
345 pModMachO->offSymbols = 0;
346 pModMachO->cSymbols = 0;
347 pModMachO->paSymbols = NULL;
348 pModMachO->offStrings = 0;
349 pModMachO->cbStrings = 0;
350 pModMachO->pbStrings = NULL;
351
352 /*
353 * Setup the KLDRMOD segment array.
354 */
355 rc = kldrModMachOParseLoadCommands(pModMachO, (char *)pMod->pszFilename + pMod->cchFilename + 1, cbStringPool);
356 if (rc)
357 return rc;
358
359 /*
360 * We're done.
361 */
362 return 0;
363}
364
365
366/**
367 * Converts, validates and preparses the load commands before we carve
368 * out the module instance.
369 *
370 * The conversion that's preformed is format endian to host endian.
371 * The preparsing has to do with segment counting and string pool sizing.
372 *
373 * @returns 0 on success.
374 * @returns KLDR_ERR_MACHO_* on failure.
375 * @param pbLoadCommands The load commands to parse.
376 * @param pHdr The header.
377 * @param pcSegments Where to store the segment count.
378 * @param pcbStringPool Where to store the string pool size.
379 */
380static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr,
381 uint32_t *pcSegments, uint32_t *pcbStringPool)
382{
383 *pcSegments = 0;
384 *pcbStringPool = 0;
385 return 0;
386}
387
388
389/**
390 * Parses the load commands after we've carved out the module instance.
391 *
392 * This fills in the segment table and perhaps some other properties.
393 *
394 * @returns 0 on success.
395 * @returns KLDR_ERR_MACHO_* on failure.
396 * @param pModMachO The module.
397 * @param pbStringPool The string pool
398 * @param cbStringPool The size of the string pool.
399 */
400static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool)
401{
402 return 0;
403}
404
405
406/** @copydoc KLDRMODOPS::pfnDestroy */
407static int kldrModMachODestroy(PKLDRMOD pMod)
408{
409 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
410 int rc = 0;
411 KLDRMODMACHO_ASSERT(!pModMachO->pvMapping);
412
413 if (pMod->pRdr)
414 {
415 rc = kLdrRdrClose(pMod->pRdr);
416 pMod->pRdr = NULL;
417 }
418 pMod->u32Magic = 0;
419 pMod->pOps = NULL;
420 kldrHlpFree(pModMachO->pbLoadCommands);
421 pModMachO->pbLoadCommands = NULL;
422 kldrHlpFree(pModMachO->pbStrings);
423 pModMachO->pbStrings = NULL;
424 kldrHlpFree(pModMachO->paSymbols);
425 pModMachO->paSymbols = NULL;
426 kldrHlpFree(pModMachO);
427 return rc;
428}
429
430
431/**
432 * Performs the mapping of the image.
433 *
434 * This can be used to do the internal mapping as well as the
435 * user requested mapping. fForReal indicates which is desired.
436 *
437 * @returns 0 on success, non-zero OS or kLdr status code on failure.
438 * @param pModMachO The interpreter module instance
439 * @param fForReal If set, do the user mapping. if clear, do the internal mapping.
440 */
441static int kldrModMachODoMap(PKLDRMODMACHO pModMachO, unsigned fForReal)
442{
443#if 0
444 PKLDRMOD pMod = pModMachO->pMod;
445 unsigned fFixed;
446 void *pvBase;
447 int rc;
448 uint32_t i;
449
450 /*
451 * Map it.
452 */
453 /* fixed image? */
454 fFixed = fForReal
455 && ( pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED
456 || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED);
457 if (!fFixed)
458 pvBase = NULL;
459 else
460 {
461 pvBase = (void *)(uintptr_t)pMod->aSegments[0].LinkAddress;
462 if ((uintptr_t)pvBase != pMod->aSegments[0].LinkAddress)
463 return KLDR_ERR_ADDRESS_OVERFLOW;
464 }
465
466 /* try do the prepare */
467 rc = kLdrRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed);
468 if (rc)
469 return rc;
470
471 /*
472 * Update the segments with their map addresses.
473 */
474 if (fForReal)
475 {
476 for (i = 0; i < pMod->cSegments; i++)
477 {
478 if (pMod->aSegments[i].RVA != NIL_KLDRADDR)
479 pMod->aSegments[i].MapAddress = (uintptr_t)pvBase + (uintptr_t)pMod->aSegments[i].RVA;
480 }
481 pModMachO->pvMapping = pvBase;
482 }
483 else
484 pModMachO->pvBits = pvBase;
485#endif
486 return 0;
487}
488
489
490/**
491 * Unmaps a image mapping.
492 *
493 * This can be used to do the internal mapping as well as the
494 * user requested mapping. fForReal indicates which is desired.
495 *
496 * @returns 0 on success, non-zero OS or kLdr status code on failure.
497 * @param pModMachO The interpreter module instance
498 * @param pvMapping The mapping to unmap.
499 */
500static int kldrModMachODoUnmap(PKLDRMODMACHO pModMachO, const void *pvMapping)
501{
502#if 0
503 PKLDRMOD pMod = pModMachO->pMod;
504 int rc;
505 uint32_t i;
506
507 /*
508 * Try unmap the image.
509 */
510 rc = kLdrRdrUnmap(pMod->pRdr, (void *)pvMapping, pMod->cSegments, pMod->aSegments);
511 if (rc)
512 return rc;
513
514 /*
515 * Update the segments to reflect that they aren't mapped any longer.
516 */
517 if (pModMachO->pvMapping == pvMapping)
518 {
519 pModMachO->pvMapping = NULL;
520 for (i = 0; i < pMod->cSegments; i++)
521 pMod->aSegments[i].MapAddress = 0;
522 }
523 if (pModMachO->pvBits == pvMapping)
524 pModMachO->pvBits = NULL;
525#endif
526
527 return 0;
528}
529
530
531/**
532 * Gets usable bits and the right base address.
533 *
534 * @returns 0 on success.
535 * @returns A non-zero status code if the BaseAddress isn't right or some problem is encountered
536 * featch in a temp mapping the bits.
537 * @param pModMachO The interpreter module instance
538 * @param ppvBits The bits address, IN & OUT.
539 * @param pBaseAddress The base address, IN & OUT. Optional.
540 */
541static int kldrModMachOBitsAndBaseAddress(PKLDRMODMACHO pModMachO, const void **ppvBits, PKLDRADDR pBaseAddress)
542{
543 int rc = 0;
544
545 /*
546 * Correct the base address.
547 *
548 * We don't use the base address for interpreting the bits in this
549 * interpreter, which makes things relativly simple.
550 */
551 if (pBaseAddress)
552 {
553 if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP)
554 *pBaseAddress = pModMachO->pMod->aSegments[0].MapAddress;
555 else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK)
556 *pBaseAddress = pModMachO->LinkAddress;
557 }
558
559 /*
560 * Get bits.
561 */
562 if (ppvBits && !*ppvBits)
563 {
564 if (pModMachO->pvMapping)
565 *ppvBits = pModMachO->pvMapping;
566 else if (pModMachO->pvBits)
567 *ppvBits = pModMachO->pvBits;
568 else
569 {
570 /* create an internal mapping. */
571 rc = kldrModMachODoMap(pModMachO, 0 /* not for real */);
572 if (rc)
573 return rc;
574 KLDRMODMACHO_ASSERT(pModMachO->pvBits);
575 *ppvBits = pModMachO->pvBits;
576 }
577 }
578
579 return 0;
580}
581
582
583/** @copydoc kLdrModQuerySymbol */
584static int kldrModMachOQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t iSymbol,
585 const char *pchSymbol, size_t cchSymbol, const char *pszVersion,
586 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind)
587
588{
589#if 0
590 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
591 const uint32_t *paExportRVAs;
592 const IMAGE_EXPORT_DIRECTORY *pExpDir;
593 uint32_t iExpOrd;
594 uint32_t uRVA;
595 int rc;
596
597 /*
598 * Make sure we've got mapped bits and resolve any base address aliases.
599 */
600 rc = kldrModMachOBitsAndBaseAddress(pModMachO, &pvBits, &BaseAddress);
601 if (rc)
602 return rc;
603 if ( pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
604 < sizeof(IMAGE_EXPORT_DIRECTORY))
605 return KLDR_ERR_SYMBOL_NOT_FOUND;
606 if (pszVersion && *pszVersion)
607 return KLDR_ERR_SYMBOL_NOT_FOUND;
608
609 pExpDir = KLDRMODMACHO_RVA2TYPE(pvBits,
610 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
611 PIMAGE_EXPORT_DIRECTORY);
612 if (!pchSymbol)
613 {
614 /*
615 * Simple, calculate the unbased ordinal and bounds check it.
616 */
617 iExpOrd = iSymbol - pExpDir->Base;
618 if (iExpOrd >= KLDR_MAX(pExpDir->NumberOfNames, pExpDir->NumberOfFunctions))
619 return KLDR_ERR_SYMBOL_NOT_FOUND;
620 }
621 else
622 {
623 /*
624 * Do a binary search for the name.
625 * (The name table is sorted in ascending ordered by the linker.)
626 */
627 const uint32_t *paRVANames = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNames, const uint32_t *);
628 const uint16_t *paOrdinals = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNameOrdinals, const uint16_t *);
629 int32_t iStart = 1; /* one based binary searching is simpler. */
630 int32_t iEnd = pExpDir->NumberOfNames;
631
632 for (;;)
633 {
634 int32_t i;
635 int diff;
636 const char *pszName;
637
638 /* done? */
639 if (iStart > iEnd)
640 {
641#ifdef KLDRMODMACHO_STRICT /* Make sure the linker and we both did our job right. */
642 for (i = 0; i < (int32_t)pExpDir->NumberOfNames; i++)
643
644 {
645 pszName = KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[i], const char *);
646 KLDRMODMACHO_ASSERT(kLdrHlpStrNComp(pszName, pchSymbol, cchSymbol) || pszName[cchSymbol]);
647 KLDRMODMACHO_ASSERT(i == 0 || kLdrHlpStrComp(pszName, KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[i - 1], const char *)));
648 }
649#endif
650 return KLDR_ERR_SYMBOL_NOT_FOUND;
651 }
652
653 i = (iEnd - iStart) / 2 + iStart;
654 pszName = KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[i - 1], const char *);
655 diff = kLdrHlpStrNComp(pszName, pchSymbol, cchSymbol);
656 if (!diff)
657 diff = pszName[cchSymbol] - 0;
658 if (diff < 0)
659 iStart = i + 1; /* The symbol must be after the current name. */
660 else if (diff)
661 iEnd = i - 1; /* The symbol must be before the current name. */
662 else
663 {
664 iExpOrd = paOrdinals[i - 1]; /* match! */
665 break;
666 }
667 }
668 }
669
670 /*
671 * Lookup the address in the 'symbol' table.
672 */
673 paExportRVAs = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfFunctions, const uint32_t *);
674 uRVA = paExportRVAs[iExpOrd];
675 if ( uRVA - pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
676 < pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
677 return kldrModMachODoForwarderQuery(pModMachO, pvBits, KLDRMODMACHO_RVA2TYPE(pvBits, uRVA, const char *),
678 pfnGetForwarder, pvUser, puValue, pfKind);
679
680 /*
681 * Set the return value.
682 */
683 if (puValue)
684 *puValue = BaseAddress + uRVA;
685 if (pfKind)
686 *pfKind = (pModMachO->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
687 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
688 | KLDRSYMKIND_NO_TYPE;
689#endif
690 return 0;
691}
692
693
694/** @copydoc kLdrModEnumSymbols */
695static int kldrModMachOEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
696 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
697{
698#if 0
699 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
700 const uint32_t *paFunctions;
701 const IMAGE_EXPORT_DIRECTORY *pExpDir;
702 const uint32_t *paRVANames;
703 const uint16_t *paOrdinals;
704 uint32_t iFunction;
705 uint32_t cFunctions;
706 uint32_t cNames;
707 int rc;
708
709 /*
710 * Make sure we've got mapped bits and resolve any base address aliases.
711 */
712 rc = kldrModMachOBitsAndBaseAddress(pModMachO, &pvBits, &BaseAddress);
713 if (rc)
714 return rc;
715
716 if ( pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
717 < sizeof(IMAGE_EXPORT_DIRECTORY))
718 return 0; /* no exports to enumerate, return success. */
719
720 pExpDir = KLDRMODMACHO_RVA2TYPE(pvBits,
721 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
722 PIMAGE_EXPORT_DIRECTORY);
723
724 /*
725 * Enumerate the ordinal exports.
726 */
727 paRVANames = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNames, const uint32_t *);
728 paOrdinals = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNameOrdinals, const uint16_t *);
729 paFunctions = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfFunctions, const uint32_t *);
730 cFunctions = pExpDir->NumberOfFunctions;
731 cNames = pExpDir->NumberOfNames;
732 for (iFunction = 0; iFunction < cFunctions; iFunction++)
733 {
734 unsigned fFoundName;
735 uint32_t iName;
736 const uint32_t uRVA = paFunctions[iFunction];
737 const KLDRADDR uValue = BaseAddress + uRVA;
738 uint32_t fKind = (pModMachO->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
739 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
740 | KLDRSYMKIND_NO_TYPE;
741 if ( uRVA - pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
742 < pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
743 fKind |= KLDRSYMKIND_FORWARDER;
744
745 /*
746 * Any symbol names?
747 */
748 fFoundName = 0;
749 for (iName = 0; iName < cNames; iName++)
750 {
751 const char *pszName;
752 if (paOrdinals[iName] != iFunction)
753 continue;
754 fFoundName = 1;
755 pszName = KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[iName], const char *);
756 rc = pfnCallback(pMod, iFunction + pExpDir->Base, pszName, kLdrHlpStrLen(pszName), NULL,
757 uValue, fKind, pvUser);
758 if (rc)
759 return rc;
760 }
761
762 /*
763 * If no names, call once with the ordinal only.
764 */
765 if (!fFoundName)
766 {
767 rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, 0, NULL, uValue, fKind, pvUser);
768 if (rc)
769 return rc;
770 }
771 }
772#endif
773 return 0;
774}
775
776
777/** @copydoc kLdrModGetImport */
778static int kldrModMachOGetImport(PKLDRMOD pMod, const void *pvBits, uint32_t iImport, char *pszName, size_t cchName)
779{
780#if 0
781 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
782 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
783 const char *pszImportName;
784 size_t cchImportName;
785 int rc;
786
787 /*
788 * Make sure we've got mapped bits and resolve any base address aliases.
789 */
790 rc = kldrModMachOBitsAndBaseAddress(pModMachO, &pvBits, NULL);
791 if (rc)
792 return rc;
793
794 /*
795 * Simple bounds check.
796 */
797 if (iImport >= (uint32_t)kldrModMachONumberOfImports(pMod, pvBits))
798 return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
799
800 /*
801 * Get the name.
802 */
803 pImpDesc = KLDRMODMACHO_RVA2TYPE(pvBits,
804 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
805 + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport,
806 const IMAGE_IMPORT_DESCRIPTOR *);
807 pszImportName = KLDRMODMACHO_RVA2TYPE(pvBits, pImpDesc->Name, const char *);
808 cchImportName = kLdrHlpStrLen(pszImportName);
809 if (cchImportName < cchName)
810 {
811 kLdrHlpMemCopy(pszName, pszImportName, cchImportName + 1);
812 rc = 0;
813 }
814 else
815 {
816 kLdrHlpMemCopy(pszName, pszImportName, cchName);
817 if (cchName)
818 pszName[cchName - 1] = '\0';
819 rc = KLDR_ERR_BUFFER_OVERFLOW;
820 }
821
822 return rc;
823#else
824 return -1;
825#endif
826}
827
828
829/** @copydoc kLdrModNumberOfImports */
830static int32_t kldrModMachONumberOfImports(PKLDRMOD pMod, const void *pvBits)
831{
832#if 0
833 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
834 if (pModMachO->cImportModules == ~(uint32_t)0)
835 {
836 /*
837 * We'll have to walk the import descriptors to figure out their number.
838 * First, make sure we've got mapped bits.
839 */
840 if (kldrModMachOBitsAndBaseAddress(pModMachO, &pvBits, NULL))
841 return -1;
842 pModMachO->cImportModules = 0;
843 if ( pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
844 && pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
845 {
846 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
847
848 pImpDesc = KLDRMODMACHO_RVA2TYPE(pvBits,
849 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
850 const IMAGE_IMPORT_DESCRIPTOR *);
851 while (pImpDesc->Name && pImpDesc->FirstThunk)
852 {
853 pModMachO->cImportModules++;
854 pImpDesc++;
855 }
856 }
857 }
858 return pModMachO->cImportModules;
859#else
860 return 0;
861#endif
862}
863
864
865/** @copydoc kLdrModGetStackInfo */
866static int kldrModMachOGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
867{
868 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
869
870 pStackInfo->Address = NIL_KLDRADDR;
871 pStackInfo->LinkAddress = NIL_KLDRADDR;
872 pStackInfo->cbStack = pStackInfo->cbStackThread = 0;//pModMachO->Hdrs.OptionalHeader.SizeOfStackReserve;
873
874 return 0;
875}
876
877
878/** @copydoc kLdrModQueryMainEntrypoint */
879static int kldrModMachOQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
880{
881#if 0
882 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
883 int rc;
884
885 /*
886 * Resolve base address alias if any.
887 */
888 rc = kldrModMachOBitsAndBaseAddress(pModMachO, NULL, &BaseAddress);
889 if (rc)
890 return rc;
891
892 /*
893 * Convert the address from the header.
894 */
895 *pMainEPAddress = pModMachO->Hdrs.OptionalHeader.AddressOfEntryPoint
896 ? BaseAddress + pModMachO->Hdrs.OptionalHeader.AddressOfEntryPoint
897 : NIL_KLDRADDR;
898#else
899 *pMainEPAddress = NIL_KLDRADDR;
900#endif
901 return 0;
902}
903
904
905/** @copydoc kLdrModEnumDbgInfo */
906static int kldrModMachOEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
907{
908#if 0
909 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
910 const IMAGE_DEBUG_DIRECTORY *pDbgDir;
911 uint32_t iDbgInfo;
912 uint32_t cb;
913 int rc;
914
915 /*
916 * Check that there is a debug directory first.
917 */
918 cb = pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
919 if ( cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
920 || !pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
921 return 0;
922
923 /*
924 * Make sure we've got mapped bits.
925 */
926 rc = kldrModMachOBitsAndBaseAddress(pModMachO, &pvBits, NULL);
927 if (rc)
928 return rc;
929
930 /*
931 * Enumerate the debug directory.
932 */
933 pDbgDir = KLDRMODMACHO_RVA2TYPE(pvBits,
934 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
935 const IMAGE_DEBUG_DIRECTORY *);
936 for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY))
937 {
938 KLDRDBGINFOTYPE enmDbgInfoType;
939
940 /* convert the type. */
941 switch (pDbgDir->Type)
942 {
943 case IMAGE_DEBUG_TYPE_UNKNOWN:
944 case IMAGE_DEBUG_TYPE_FPO:
945 case IMAGE_DEBUG_TYPE_COFF: /*stabs dialect??*/
946 case IMAGE_DEBUG_TYPE_MISC:
947 case IMAGE_DEBUG_TYPE_EXCEPTION:
948 case IMAGE_DEBUG_TYPE_FIXUP:
949 case IMAGE_DEBUG_TYPE_BORLAND:
950 default:
951 enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN;
952 break;
953 case IMAGE_DEBUG_TYPE_CODEVIEW:
954 enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW;
955 break;
956 }
957
958 rc = pfnCallback(pMod, iDbgInfo,
959 enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion,
960 pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1,
961 pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR,
962 pDbgDir->SizeOfData,
963 NULL,
964 pvUser);
965 if (rc)
966 break;
967
968 /* next */
969 if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY))
970 break;
971 }
972
973 return rc;
974#else
975 return 0;
976#endif
977}
978
979
980/** @copydoc kLdrModHasDbgInfo */
981static int kldrModMachOHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
982{
983 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
984
985#if 0
986 /*
987 * Base this entirely on the presence of a debug directory.
988 */
989 if ( pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
990 < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
991 || !pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
992 return KLDR_ERR_NO_DEBUG_INFO;
993 return 0;
994#else
995 return KLDR_ERR_NO_DEBUG_INFO;
996#endif
997}
998
999
1000/** @copydoc kLdrModMap */
1001static int kldrModMachOMap(PKLDRMOD pMod)
1002{
1003 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1004 int rc;
1005
1006 /*
1007 * Already mapped?
1008 */
1009 if (pModMachO->pvMapping)
1010 return KLDR_ERR_ALREADY_MAPPED;
1011
1012 /*
1013 * We've got a common worker which does this.
1014 */
1015 rc = kldrModMachODoMap(pModMachO, 1 /* the real thing */);
1016 if (rc)
1017 return rc;
1018 KLDRMODMACHO_ASSERT(pModMachO->pvMapping);
1019 return 0;
1020}
1021
1022
1023/** @copydoc kLdrModUnmap */
1024static int kldrModMachOUnmap(PKLDRMOD pMod)
1025{
1026 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1027 int rc;
1028
1029 /*
1030 * Mapped?
1031 */
1032 if (!pModMachO->pvMapping)
1033 return KLDR_ERR_NOT_MAPPED;
1034
1035 /*
1036 * We've got a common worker which does this.
1037 */
1038 rc = kldrModMachODoUnmap(pModMachO, pModMachO->pvMapping);
1039 if (rc)
1040 return rc;
1041 KLDRMODMACHO_ASSERT(pModMachO->pvMapping);
1042 return 0;
1043
1044}
1045
1046
1047/** @copydoc kLdrModAllocTLS */
1048static int kldrModMachOAllocTLS(PKLDRMOD pMod)
1049{
1050 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1051
1052 /*
1053 * Mapped?
1054 */
1055 if (!pModMachO->pvMapping)
1056 return KLDR_ERR_NOT_MAPPED;
1057
1058 return 0;
1059}
1060
1061
1062/** @copydoc kLdrModFreeTLS */
1063static void kldrModMachOFreeTLS(PKLDRMOD pMod)
1064{
1065}
1066
1067
1068/** @copydoc kLdrModReload */
1069static int kldrModMachOReload(PKLDRMOD pMod)
1070{
1071 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1072
1073 /*
1074 * Mapped?
1075 */
1076 if (!pModMachO->pvMapping)
1077 return KLDR_ERR_NOT_MAPPED;
1078
1079 /* the file provider does it all */
1080 return kLdrRdrRefresh(pMod->pRdr, (void *)pModMachO->pvMapping, pMod->cSegments, pMod->aSegments);
1081}
1082
1083
1084/** @copydoc kLdrModFixupMapping */
1085static int kldrModMachOFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1086{
1087 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1088 int rc, rc2;
1089
1090 /*
1091 * Mapped?
1092 */
1093 if (!pModMachO->pvMapping)
1094 return KLDR_ERR_NOT_MAPPED;
1095
1096 /*
1097 * Before doing anything we'll have to make all pages writable.
1098 */
1099 rc = kLdrRdrProtect(pMod->pRdr, (void *)pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
1100 if (rc)
1101 return rc;
1102
1103#if 0
1104 /*
1105 * Apply base relocations.
1106 */
1107 rc = kldrModMachODoFixups(pModMachO, (void *)pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping,
1108 pModMachO->Hdrs.OptionalHeader.ImageBase);
1109
1110 /*
1111 * Resolve imports.
1112 */
1113 if (!rc)
1114 rc = kldrModMachODoImports(pModMachO, (void *)pModMachO->pvMapping, pfnGetImport, pvUser);
1115#endif
1116
1117 /*
1118 * Restore protection.
1119 */
1120 rc2 = kLdrRdrProtect(pMod->pRdr, (void *)pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
1121 if (!rc && rc2)
1122 rc = rc2;
1123 return rc;
1124}
1125
1126
1127/**
1128 * Applies base relocations to a (unprotected) image mapping.
1129 *
1130 * @returns 0 on success, non-zero kLdr status code on failure.
1131 * @param pModMachO The PE module interpreter instance.
1132 * @param pvMapping The mapping to fixup.
1133 * @param NewBaseAddress The address to fixup the mapping to.
1134 * @param OldBaseAddress The address the mapping is currently fixed up to.
1135 */
1136static int kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress)
1137{
1138#if 0
1139 const KLDRADDR Delta = NewBaseAddress - OldBaseAddress;
1140 uint32_t cbLeft = pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1141 const IMAGE_BASE_RELOCATION *pBR, *pFirstBR;
1142
1143 /*
1144 * Don't don anything if the delta is 0 or there aren't any relocations.
1145 */
1146 if ( !Delta
1147 || !cbLeft
1148 || !pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
1149 return 0;
1150
1151 /*
1152 * Process the fixups block by block.
1153 * (These blocks appears to be 4KB on all archs despite the native page size.)
1154 */
1155 pBR = pFirstBR = KLDRMODMACHO_RVA2TYPE(pvMapping,
1156 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
1157 const IMAGE_BASE_RELOCATION *);
1158 while ( cbLeft > sizeof(IMAGE_BASE_RELOCATION)
1159 && pBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION) /* paranoia */)
1160 {
1161 union
1162 {
1163 uint8_t *pu8;
1164 uint16_t *pu16;
1165 uint32_t *pu32;
1166 uint64_t *pu64;
1167 } uChunk,
1168 u;
1169 const uint16_t *poffFixup = (const uint16_t *)(pBR + 1);
1170 const uint32_t cbBlock = KLDR_MIN(cbLeft, pBR->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION); /* more caution... */
1171 uint32_t cFixups = cbBlock / sizeof(poffFixup[0]);
1172 uChunk.pu8 = KLDRMODMACHO_RVA2TYPE(pvMapping, pBR->VirtualAddress, uint8_t *);
1173
1174 /*
1175 * Loop thru the fixups in this chunk.
1176 */
1177 while (cFixups > 0)
1178 {
1179 u.pu8 = uChunk.pu8 + (*poffFixup & 0xfff);
1180 switch (*poffFixup >> 12) /* ordered by value. */
1181 {
1182 /* 0 - Alignment placeholder. */
1183 case IMAGE_REL_BASED_ABSOLUTE:
1184 break;
1185
1186 /* 1 - 16-bit, add 2nd 16-bit part of the delta. (rare) */
1187 case IMAGE_REL_BASED_HIGH:
1188 *u.pu16 += (uint16_t)(Delta >> 16);
1189 break;
1190
1191 /* 2 - 16-bit, add 1st 16-bit part of the delta. (rare) */
1192 case IMAGE_REL_BASED_LOW:
1193 *u.pu16 += (uint16_t)Delta;
1194 break;
1195
1196 /* 3 - 32-bit, add delta. (frequent in 32-bit images) */
1197 case IMAGE_REL_BASED_HIGHLOW:
1198 *u.pu32 += (uint32_t)Delta;
1199 break;
1200
1201 /* 4 - 16-bit, add 2nd 16-bit of the delta, sign adjust for the lower 16-bit. one arg. (rare) */
1202 case IMAGE_REL_BASED_HIGHADJ:
1203 {
1204 int32_t i32;
1205 if (cFixups <= 1)
1206 return KLDR_ERR_PE_BAD_FIXUP;
1207
1208 i32 = (uint32_t)*u.pu16 << 16;
1209 i32 |= *++poffFixup; cFixups--; /* the addend argument */
1210 i32 += (uint32_t)Delta;
1211 i32 += 0x8000;
1212 *u.pu16 = (uint16_t)(i32 >> 16);
1213 break;
1214 }
1215
1216 /* 5 - 32-bit MIPS JMPADDR, no implemented. */
1217 case IMAGE_REL_BASED_MIPS_JMPADDR:
1218 *u.pu32 = (*u.pu32 & 0xc0000000)
1219 | ((uint32_t)((*u.pu32 << 2) + (uint32_t)Delta) >> 2);
1220 break;
1221
1222 /* 6 - Intra section? Reserved value in later specs. Not implemented. */
1223 case IMAGE_REL_BASED_SECTION:
1224 KLDRMODMACHO_ASSERT(!"SECTION");
1225 return KLDR_ERR_PE_BAD_FIXUP;
1226
1227 /* 7 - Relative intra section? Reserved value in later specs. Not implemented. */
1228 case IMAGE_REL_BASED_REL32:
1229 KLDRMODMACHO_ASSERT(!"SECTION");
1230 return KLDR_ERR_PE_BAD_FIXUP;
1231
1232 /* 8 - reserved according to binutils... */
1233 case 8:
1234 KLDRMODMACHO_ASSERT(!"RESERVERED8");
1235 return KLDR_ERR_PE_BAD_FIXUP;
1236
1237 /* 9 - IA64_IMM64 (/ MIPS_JMPADDR16), no specs nor need to support the platform yet.
1238 * Bet this requires more code than all the other fixups put together in good IA64 spirit :-) */
1239 case IMAGE_REL_BASED_IA64_IMM64:
1240 KLDRMODMACHO_ASSERT(!"IA64_IMM64 / MIPS_JMPADDR16");
1241 return KLDR_ERR_PE_BAD_FIXUP;
1242
1243 /* 10 - 64-bit, add delta. (frequently in 64-bit images) */
1244 case IMAGE_REL_BASED_DIR64:
1245 *u.pu64 += (uint64_t)Delta;
1246 break;
1247
1248 /* 11 - 16-bit, add 3rd 16-bit of the delta, sign adjust for the lower 32-bit. two args. (rare) */
1249 case IMAGE_REL_BASED_HIGH3ADJ:
1250 {
1251 int64_t i64;
1252 if (cFixups <= 2)
1253 return KLDR_ERR_PE_BAD_FIXUP;
1254
1255 i64 = (uint64_t)*u.pu16 << 32
1256 | ((uint32_t)poffFixup[2] << 16)
1257 | poffFixup[1];
1258 i64 += Delta;
1259 i64 += 0x80008000UL;
1260 *u.pu16 = (uint16_t)(i64 >> 32);
1261 /* skip the addends arguments */
1262 poffFixup += 2;
1263 cFixups -= 2;
1264 break;
1265 }
1266
1267 /* the rest are yet to be defined.*/
1268 default:
1269 return KLDR_ERR_PE_BAD_FIXUP;
1270 }
1271
1272 /*
1273 * Next relocation.
1274 */
1275 poffFixup++;
1276 cFixups--;
1277 }
1278
1279
1280 /*
1281 * Next block.
1282 */
1283 cbLeft -= pBR->SizeOfBlock;
1284 pBR = (PIMAGE_BASE_RELOCATION)((uintptr_t)pBR + pBR->SizeOfBlock);
1285 }
1286
1287#endif
1288 return 0;
1289}
1290
1291
1292
1293/**
1294 * Resolves imports.
1295 *
1296 * @returns 0 on success, non-zero kLdr status code on failure.
1297 * @param pModMachO The PE module interpreter instance.
1298 * @param pvMapping The mapping which imports should be resolved.
1299 * @param pfnGetImport The callback for resolving an imported symbol.
1300 * @param pvUser User argument to the callback.
1301 */
1302static int kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1303{
1304#if 0
1305 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
1306
1307 /*
1308 * If no imports, there is nothing to do.
1309 */
1310 kldrModMachONumberOfImports(pModMachO->pMod, pvMapping);
1311 if (!pModMachO->cImportModules)
1312 return 0;
1313
1314 pImpDesc = KLDRMODMACHO_RVA2TYPE(pvMapping,
1315 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
1316 const IMAGE_IMPORT_DESCRIPTOR *);
1317 if (pModMachO->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
1318 return kldrModMachODoImports32Bit(pModMachO, pvMapping, pImpDesc, pfnGetImport, pvUser);
1319 return kldrModMachODoImports64Bit(pModMachO, pvMapping, pImpDesc, pfnGetImport, pvUser);
1320#else
1321 return 0;
1322#endif
1323}
1324
1325
1326#if 0
1327/**
1328 * Resolves imports, 32-bit image.
1329 *
1330 * @returns 0 on success, non-zero kLdr status code on failure.
1331 * @param pModMachO The PE module interpreter instance.
1332 * @param pvMapping The mapping which imports should be resolved.
1333 * @param pImpDesc Pointer to the first import descriptor.
1334 * @param pfnGetImport The callback for resolving an imported symbol.
1335 * @param pvUser User argument to the callback.
1336 */
1337static int kldrModMachODoImports32Bit(PKLDRMODMACHO pModMachO, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
1338 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1339{
1340 PKLDRMOD pMod = pModMachO->pMod;
1341 uint32_t iImp;
1342
1343 /*
1344 * Iterate the import descriptors.
1345 */
1346 for (iImp = 0; iImp < pModMachO->cImportModules; iImp++, pImpDesc++)
1347 {
1348 PIMAGE_THUNK_DATA32 pFirstThunk = KLDRMODMACHO_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, PIMAGE_THUNK_DATA32);
1349 const IMAGE_THUNK_DATA32 *pThunk = pImpDesc->u.OriginalFirstThunk
1350 ? KLDRMODMACHO_RVA2TYPE(pvMapping, pImpDesc->u.OriginalFirstThunk, const IMAGE_THUNK_DATA32 *)
1351 : KLDRMODMACHO_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, const IMAGE_THUNK_DATA32 *);
1352
1353 /* Iterate the thunks. */
1354 while (pThunk->u1.Ordinal != 0)
1355 {
1356 KLDRADDR Value;
1357 uint32_t fKind;
1358 int rc;
1359
1360 /* Ordinal or name import? */
1361 if (IMAGE_SNAP_BY_ORDINAL32(pThunk->u1.Ordinal))
1362 rc = pfnGetImport(pMod, iImp, IMAGE_ORDINAL32(pThunk->u1.Ordinal), NULL, 0, NULL, &Value, &fKind, pvUser);
1363 else if (KLDRMODMACHO_VALID_RVA(pModMachO, pThunk->u1.Ordinal))
1364 {
1365 const IMAGE_IMPORT_BY_NAME *pName = KLDRMODMACHO_RVA2TYPE(pvMapping, pThunk->u1.Ordinal, const IMAGE_IMPORT_BY_NAME *);
1366 rc = pfnGetImport(pMod, iImp, NIL_KLDRMOD_SYM_ORDINAL, (const char *)pName->Name,
1367 kLdrHlpStrLen((const char *)pName->Name), NULL, &Value, &fKind, pvUser);
1368 }
1369 else
1370 {
1371 KLDRMODMACHO_ASSERT(!"bad 32-bit import");
1372 return KLDR_ERR_PE_BAD_IMPORT;
1373 }
1374
1375 /* Apply it. */
1376 pFirstThunk->u1.Function = (uint32_t)Value;
1377 if (pFirstThunk->u1.Function != Value)
1378 {
1379 KLDRMODMACHO_ASSERT(!"overflow");
1380 return KLDR_ERR_ADDRESS_OVERFLOW;
1381 }
1382
1383 /* next */
1384 pThunk++;
1385 pFirstThunk++;
1386 }
1387 }
1388 return 0;
1389}
1390
1391
1392/**
1393 * Resolves imports, 64-bit image.
1394 *
1395 * @returns 0 on success, non-zero kLdr status code on failure.
1396 * @param pModMachO The PE module interpreter instance.
1397 * @param pvMapping The mapping which imports should be resolved.
1398 * @param pImpDesc Pointer to the first import descriptor.
1399 * @param pfnGetImport The callback for resolving an imported symbol.
1400 * @param pvUser User argument to the callback.
1401 */
1402static int kldrModMachODoImports64Bit(PKLDRMODMACHO pModMachO, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
1403 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1404{
1405 PKLDRMOD pMod = pModMachO->pMod;
1406 uint32_t iImp;
1407
1408 /*
1409 * Iterate the import descriptors.
1410 */
1411 for (iImp = 0; iImp < pModMachO->cImportModules; iImp++, pImpDesc++)
1412 {
1413 PIMAGE_THUNK_DATA64 pFirstThunk = KLDRMODMACHO_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, PIMAGE_THUNK_DATA64);
1414 const IMAGE_THUNK_DATA64 *pThunk = pImpDesc->u.OriginalFirstThunk
1415 ? KLDRMODMACHO_RVA2TYPE(pvMapping, pImpDesc->u.OriginalFirstThunk, const IMAGE_THUNK_DATA64 *)
1416 : KLDRMODMACHO_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, const IMAGE_THUNK_DATA64 *);
1417
1418 /* Iterate the thunks. */
1419 while (pThunk->u1.Ordinal != 0)
1420 {
1421 KLDRADDR Value;
1422 uint32_t fKind;
1423 int rc;
1424
1425 /* Ordinal or name import? */
1426 if (IMAGE_SNAP_BY_ORDINAL64(pThunk->u1.Ordinal))
1427 rc = pfnGetImport(pMod, iImp, (uint32_t)IMAGE_ORDINAL64(pThunk->u1.Ordinal), NULL, 0, NULL, &Value, &fKind, pvUser);
1428 else if (KLDRMODMACHO_VALID_RVA(pModMachO, pThunk->u1.Ordinal))
1429 {
1430 const IMAGE_IMPORT_BY_NAME *pName = KLDRMODMACHO_RVA2TYPE(pvMapping, pThunk->u1.Ordinal, const IMAGE_IMPORT_BY_NAME *);
1431 rc = pfnGetImport(pMod, iImp, NIL_KLDRMOD_SYM_ORDINAL, (const char *)pName->Name,
1432 kLdrHlpStrLen((const char *)pName->Name), NULL, &Value, &fKind, pvUser);
1433 }
1434 else
1435 {
1436 KLDRMODMACHO_ASSERT(!"bad 64-bit import");
1437 return KLDR_ERR_PE_BAD_IMPORT;
1438 }
1439
1440 /* Apply it. */
1441 pFirstThunk->u1.Function = Value;
1442
1443 /* next */
1444 pThunk++;
1445 pFirstThunk++;
1446 }
1447 }
1448 return 0;
1449}
1450
1451#endif
1452
1453
1454/** @copydoc kLdrModCallInit */
1455static int kldrModMachOCallInit(PKLDRMOD pMod, uintptr_t uHandle)
1456{
1457#if 0
1458 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1459 int rc;
1460
1461 /*
1462 * Mapped?
1463 */
1464 if (!pModMachO->pvMapping)
1465 return KLDR_ERR_NOT_MAPPED;
1466
1467 /*
1468 * Do TLS callbacks first and then call the init/term function if it's a DLL.
1469 */
1470 rc = kldrModMachODoCallTLS(pModMachO, DLL_PROCESS_ATTACH, uHandle);
1471 if ( !rc
1472 && (pModMachO->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL))
1473 {
1474 rc = kldrModMachODoCallDLL(pModMachO, DLL_PROCESS_ATTACH, uHandle);
1475 if (rc)
1476 kldrModMachODoCallTLS(pModMachO, DLL_PROCESS_DETACH, uHandle);
1477 }
1478
1479 return rc;
1480#else
1481 return 0;
1482#endif
1483}
1484
1485
1486/**
1487 * Call the DLL entrypoint.
1488 *
1489 * @returns 0 on success.
1490 * @returns KLDR_ERR_MODULE_INIT_FAILED or KLDR_ERR_THREAD_ATTACH_FAILED on failure.
1491 * @param pModMachO The PE module interpreter instance.
1492 * @param uOp The operation (DLL_*).
1493 * @param uHandle The module handle to present.
1494 */
1495static int kldrModMachODoCallDLL(PKLDRMODMACHO pModMachO, unsigned uOp, uintptr_t uHandle)
1496{
1497#if 0
1498 int rc;
1499
1500 /*
1501 * If no entrypoint there isn't anything to be done.
1502 */
1503 if (!pModMachO->Hdrs.OptionalHeader.AddressOfEntryPoint)
1504 return 0;
1505
1506 /*
1507 * Invoke the entrypoint and convert the boolean result to a kLdr status code.
1508 */
1509 rc = kldrModMachODoCall((uintptr_t)pModMachO->pvMapping + pModMachO->Hdrs.OptionalHeader.AddressOfEntryPoint,
1510 uHandle, uOp, NULL);
1511 if (rc)
1512 rc = 0;
1513 else if (uOp == DLL_PROCESS_ATTACH)
1514 rc = KLDR_ERR_MODULE_INIT_FAILED;
1515 else if (uOp == DLL_THREAD_ATTACH)
1516 rc = KLDR_ERR_THREAD_ATTACH_FAILED;
1517 else /* detach: ignore failures */
1518 rc = 0;
1519 return rc;
1520#else
1521 return 0;
1522#endif
1523}
1524
1525
1526/**
1527 * Call the TLS entrypoints.
1528 *
1529 * @returns 0 on success.
1530 * @returns KLDR_ERR_THREAD_ATTACH_FAILED on failure.
1531 * @param pModMachO The PE module interpreter instance.
1532 * @param uOp The operation (DLL_*).
1533 * @param uHandle The module handle to present.
1534 */
1535static int kldrModMachODoCallTLS(PKLDRMODMACHO pModMachO, unsigned uOp, uintptr_t uHandle)
1536{
1537 /** @todo implement TLS support. */
1538 return 0;
1539}
1540
1541
1542/**
1543 * Do a 3 parameter callback.
1544 *
1545 * @returns 32-bit callback return.
1546 * @param uEntrypoint The address of the function to be called.
1547 * @param uHandle The first argument, the module handle.
1548 * @param uOp The second argumnet, the reason we're calling.
1549 * @param pvReserved The third argument, reserved argument. (figure this one out)
1550 */
1551static int32_t kldrModMachODoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved)
1552{
1553#if 0
1554 int32_t rc;
1555
1556/** @todo try/except */
1557#if defined(__X86__) || defined(__i386__) || defined(_M_IX86)
1558 /*
1559 * Be very careful.
1560 * Not everyone will have got the calling convention right.
1561 */
1562# ifdef __GNUC__
1563 __asm__ __volatile__(
1564 "pushl %2\n\t"
1565 "pushl %1\n\t"
1566 "pushl %0\n\t"
1567 "lea 12(%%esp), %2\n\t"
1568 "call *%3\n\t"
1569 "movl %2, %%esp\n\t"
1570 : "=a" (rc)
1571 : "d" (uOp),
1572 "S" (0),
1573 "c" (uEntrypoint),
1574 "0" (uHandle));
1575# elif defined(_MSC_VER)
1576 __asm {
1577 mov eax, [uHandle]
1578 mov edx, [uOp]
1579 mov ecx, 0
1580 mov ebx, [uEntrypoint]
1581 push edi
1582 mov edi, esp
1583 push ecx
1584 push edx
1585 push eax
1586 call ebx
1587 mov esp, edi
1588 pop edi
1589 mov [rc], eax
1590 }
1591# else
1592# error "port me!"
1593# endif
1594
1595#elif defined(__AMD64__) || defined(__x86_64__) || defined(_M_IX86)
1596 /*
1597 * For now, let's just get the work done...
1598 */
1599 /** @todo Deal with GCC / MSC differences in some sensible way. */
1600 int (*pfn)(uintptr_t uHandle, uint32_t uOp, void *pvReserved);
1601 pfn = (int (*)(uintptr_t uHandle, uint32_t uOp, void *pvReserved))uEntrypoint;
1602 rc = pfn(uHandle, uOp, NULL);
1603
1604#else
1605# error "port me"
1606#endif
1607
1608 return rc;
1609#else
1610 return 0;
1611#endif
1612}
1613
1614
1615/** @copydoc kLdrModCallTerm */
1616static int kldrModMachOCallTerm(PKLDRMOD pMod, uintptr_t uHandle)
1617{
1618#if 0
1619 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1620
1621 /*
1622 * Mapped?
1623 */
1624 if (!pModMachO->pvMapping)
1625 return KLDR_ERR_NOT_MAPPED;
1626
1627 /*
1628 * Do TLS callbacks first.
1629 */
1630 kldrModMachODoCallTLS(pModMachO, DLL_PROCESS_DETACH, uHandle);
1631 if (pModMachO->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL)
1632 kldrModMachODoCallDLL(pModMachO, DLL_PROCESS_DETACH, uHandle);
1633#endif
1634
1635 return 0;
1636}
1637
1638
1639/** @copydoc kLdrModCallThread */
1640static int kldrModMachOCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
1641{
1642#if 0
1643 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1644 unsigned uOp = fAttachingOrDetaching ? DLL_THREAD_ATTACH : DLL_THREAD_DETACH;
1645 int rc;
1646
1647 /*
1648 * Do TLS callbacks first and then call the init/term function if it's a DLL.
1649 */
1650 rc = kldrModMachODoCallTLS(pModMachO, uOp, uHandle);
1651 if (!fAttachingOrDetaching)
1652 rc = 0;
1653 if ( !rc
1654 && (pModMachO->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL))
1655 {
1656 rc = kldrModMachODoCallDLL(pModMachO, uOp, uHandle);
1657 if (!fAttachingOrDetaching)
1658 rc = 0;
1659 if (rc)
1660 kldrModMachODoCallTLS(pModMachO, uOp, uHandle);
1661 }
1662 return rc;
1663#else
1664 return 0;
1665#endif
1666}
1667
1668
1669/** @copydoc kLdrModSize */
1670static KLDRADDR kldrModMachOSize(PKLDRMOD pMod)
1671{
1672#if 0
1673 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1674 return pModMachO->Hdrs.OptionalHeader.SizeOfImage;
1675#else
1676 return 0;
1677#endif
1678}
1679
1680
1681/** @copydoc kLdrModGetBits */
1682static int kldrModMachOGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1683{
1684#if 0
1685 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1686 uint32_t i;
1687 int rc;
1688
1689 /*
1690 * Zero the entire buffer first to simplify things.
1691 */
1692 kLdrHlpMemSet(pvBits, 0, pModMachO->Hdrs.OptionalHeader.SizeOfImage);
1693
1694 /*
1695 * Iterate the segments and read the data within them.
1696 */
1697 for (i = 0; i < pMod->cSegments; i++)
1698 {
1699 /* skip it? */
1700 if ( pMod->aSegments[i].cbFile == -1
1701 || pMod->aSegments[i].offFile == -1
1702 || pMod->aSegments[i].LinkAddress == NIL_KLDRADDR
1703 || !pMod->aSegments[i].Alignment)
1704 continue;
1705 rc = kLdrRdrRead(pMod->pRdr,
1706 (uint8_t *)pvBits + (pMod->aSegments[i].LinkAddress - pModMachO->Hdrs.OptionalHeader.ImageBase),
1707 pMod->aSegments[i].cbFile,
1708 pMod->aSegments[i].offFile);
1709 if (rc)
1710 return rc;
1711 }
1712
1713 /*
1714 * Perform relocations.
1715 */
1716 return kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->Hdrs.OptionalHeader.ImageBase, pfnGetImport, pvUser);
1717#else
1718 return 0;
1719#endif
1720}
1721
1722
1723/** @copydoc kLdrModRelocateBits */
1724static int kldrModMachORelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
1725 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1726{
1727 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
1728 int rc;
1729
1730 /*
1731 * Call workers to do the jobs.
1732 */
1733 rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress);
1734 if (!rc)
1735 rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser);
1736
1737 return rc;
1738}
1739
1740
1741/**
1742 * The PE module interpreter method table.
1743 */
1744KLDRMODOPS g_kLdrModPEOps =
1745{
1746 "PE",
1747 NULL,
1748 kldrModMachOCreate,
1749 kldrModMachODestroy,
1750 kldrModMachOQuerySymbol,
1751 kldrModMachOEnumSymbols,
1752 kldrModMachOGetImport,
1753 kldrModMachONumberOfImports,
1754 NULL /* can execute one is optional */,
1755 kldrModMachOGetStackInfo,
1756 kldrModMachOQueryMainEntrypoint,
1757 NULL,
1758 NULL,
1759 kldrModMachOEnumDbgInfo,
1760 kldrModMachOHasDbgInfo,
1761 kldrModMachOMap,
1762 kldrModMachOUnmap,
1763 kldrModMachOAllocTLS,
1764 kldrModMachOFreeTLS,
1765 kldrModMachOReload,
1766 kldrModMachOFixupMapping,
1767 kldrModMachOCallInit,
1768 kldrModMachOCallTerm,
1769 kldrModMachOCallThread,
1770 kldrModMachOSize,
1771 kldrModMachOGetBits,
1772 kldrModMachORelocateBits,
1773 NULL, /** @todo mostly done */
1774 42 /* the end */
1775};
1776
Note: See TracBrowser for help on using the repository browser.