]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IONDRVSupport/IOPEFInternals.c
13c8cc0513fa93f68d683dd7158dce8a6ae64c7b
[apple/xnu.git] / iokit / Families / IONDRVSupport / IOPEFInternals.c
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1997 Apple Computer, Inc.
24 *
25 *
26 * HISTORY
27 *
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 21 July 98 - start IOKit
30 */
31
32
33
34 /*
35 File: PEFLoader.c
36
37 Contains: PEF loader implementation.
38
39 Version: Maxwell
40
41 Copyright: © 1994-1996 by Apple Computer, Inc., all rights reserved.
42
43 File Ownership:
44
45 DRI: Alan Lillich
46
47 Other Contact: <<unknown>>
48
49 Technology: Core Runtime
50
51 Writers:
52
53 (AWL) Alan Lillich
54 (ELE) Erik Eidt
55
56 Change History (most recent first):
57
58 <26> 10/4/96 AWL Disable partial unpacking tests.
59 <25> 9/26/96 AWL Fix assertions to have the right polarity.
60 <24> 9/18/96 AWL Simplify UnpackPartialSection.
61 <23> 8/27/96 AWL Support partial unpacking in PEF_UnpackSection.
62 <22> 8/23/96 AWL (1379028) Propagate changes from CodeFragmentContainerPriv.
63 <21> 8/16/96 AWL Isolate memory utilities to work with both CFM and ProtoCFM.
64 <20> 4/18/96 AWL (1342167) Fix problems with relocations for in-place sections.
65 <19> 4/2/96 AWL (1336962) Fix checks for missing optional parameters.
66 <18> 3/7/96 AWL Remove unused variable in PEF_UnpackSection.
67 <17> 2/28/96 AWL Adapt for new container handler model.
68 <16> 1/19/96 AWL Changes for D11.
69 <15> 10/10/95 AWL Minor cleanup for CodeWarrior's strict checking.
70 <14> 6/14/95 AWL Pick up flags from CFMWhere ASAP.
71 <13> 5/23/95 AWL Introduce temporary hack to workaround build problem for 68K
72 ModernOS booting code. *** THIS BREAKS REAL 68K BUILDS! ***
73 <12> 2/8/95 AWL Update debug output calls.
74 <11> 12/14/94 AWL Changes for Maxwell D4 build.
75 <10> 12/2/94 AWL Disable reexported import optimization because of problems with
76 missing weak libraries. It could be put back later with the
77 addition of a "resolvedImports" bit vector.
78 <9> 9/9/94 AWL Switch to the "real" API and SPI headers.
79 <8> 9/2/94 AWL Error codes are now in Errors.h.
80 <7> 7/28/94 AWL Return cfragSymbolNotFound instead of paramErr from
81 PLFindExportInfo. (#1177313)
82 <6> 7/12/94 AWL Fix load-in-place processing in SetRegionAddress.
83 <5> 6/20/94 AWL Allow the CFL info pointer to be NULL for a "get procs" call to
84 OpenContainer.
85 <4> 5/9/94 AWL Change PLGetSpecialSectionInfo to handle some of the wierdness
86 in nonloaded sections.
87 <3> 4/28/94 AWL Simplify cross address space use for booting. Fix problem with
88 load in place, should not require SetRegionAddress.
89 <2> 2/25/94 AWL Update for Q&D solution to loading across address spaces.
90 Fix problem in PLGetSpecialSectionInfo switch statement.
91 <1> 2/15/94 AWL Initial checkin for kernel based CFM.
92
93 ------------------------------------------------------------------------------------
94
95 <31> 09/15/93 AWL (&ELE) Add CFL prefix to hash functions.
96 <30> 09/08/93 ELE (&AWL) Fix sneaky little typo that causes load failure.
97 <29> 08/30/93 AWL Add declaration so that 68K native CFM compiles.
98 <28> 08/26/93 AWL Move CFTypes.h and CFLoader.h up with other Apple private
99 headers.
100 <26> 07/08/93 AWL (&ELE) Fixed version field names in import file IDs.
101 Remove version < 0 checks as versions are unsigned.
102 <25> 06/16/93 ELE ELE & AWL Change to New Pool allocation.
103 <24> 06/09/93 ELE ELE & AWL Fix bug in GetSpecialSection for debugger.
104 <23> 06/09/93 JRG ELE & AWL Changes:
105 <22> 06/08/93 ELE (&AWL) Shift to allocation bottleneck. Added support for
106 packed data sections. Switched to new CFLoader section
107 attribute bits.
108 <21> 02/15/93 ELE Changed NewPtr->NewPtrSys
109 <20> 02/03/93 ELE Added architecture pass thru to GetVersion per CFL Spec.
110 <19> 12/23/92 ELE Fixed bug where init routine was being returned for the
111 term routine.
112 <17> 10/29/92 ELE GetVersion - added dateStamp.
113 <16> 10/01/92 ELE fix bug in use in place, update of header!
114 <15> 10/01/92 ELE fix bug in use in place!
115 <14> 09/28/92 ELE needed to update field expIndex from Find/GetExportInfo.
116 <13> 09/23/92 ELE updated to new PEF format, updated to new CF Loader SPI.
117 <12> 09/23/92 ELE Latest version.
118
119 */
120
121
122 #include "IOPEFInternals.h"
123
124 // ===========================================================================================
125
126 #define PEF_Assert(a) if( !(a)) kprintf("PEF_Assert:")
127 #define PEF_BlockMove(src,dst,len) memcpy(dst,src,len)
128 #define PEF_BlockClear(dst,len) memset(dst,0,len)
129 extern Boolean PCFM_CompareBytes ( const Byte * left,
130 const Byte * right,
131 ByteCount count );
132 #define PEF_CompareBytes(a,b,c) PCFM_CompareBytes(a,b,c)
133
134 #define EnableCFMDebugging 0
135
136 // ===========================================================================================
137
138
139 enum {
140 kPEFHandlerProcCount = 18
141 };
142
143 static CFContHandlerProcs PEFHandlerProcs = {
144 kPEFHandlerProcCount,
145 kCFContHandlerABIVersion,
146
147 PEF_OpenContainer, // 1
148 PEF_CloseContainer, // 2
149 PEF_GetContainerInfo, // 3
150
151 PEF_GetSectionCount, // 4
152 PEF_GetSectionInfo, // 5
153 PEF_FindSectionInfo, // 6
154 PEF_SetSectionAddress, // 7
155
156 PEF_GetAnonymousSymbolLocations, // 8
157
158 PEF_GetExportedSymbolCount, // 9
159 PEF_GetExportedSymbolInfo, // 10
160 PEF_FindExportedSymbolInfo, // 11
161
162 PEF_GetImportCounts, // 12
163 PEF_GetImportedLibraryInfo, // 13
164 PEF_GetImportedSymbolInfo, // 14
165 PEF_SetImportedSymbolAddress, // 15
166
167 PEF_UnpackSection, // 16
168 PEF_RelocateSection, // 17
169 PEF_RelocateImportsOnly, // 18
170 };
171
172
173 #if EnableCFMDebugging
174 static char gDebugMessage [256];
175 #endif
176
177 // ===========================================================================================
178
179 const unsigned char opcode [128] = {
180 krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT,
181 krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT,
182 krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT,
183 krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT,
184
185 krCODE,krDATA,krDESC,krDSC2, krVTBL,krSYMR,krXXXX,krXXXX,
186 krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX,
187 krSYMB,krCDIS,krDTIS,krSECN, krXXXX,krXXXX,krXXXX,krXXXX,
188 krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX,
189
190 krDELT,krDELT,krDELT,krDELT, krDELT,krDELT,krDELT,krDELT,
191 krRPT ,krRPT ,krRPT ,krRPT , krRPT ,krRPT ,krRPT ,krRPT ,
192 krLABS,krLABS,krLSYM,krLSYM, krXXXX,krXXXX,krXXXX,krXXXX,
193 krLRPT,krLRPT,krLSEC,krLSEC, krXXXX,krXXXX,krXXXX,krXXXX,
194
195 krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX,
196 krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX,
197 krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX,
198 krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX,
199 };
200
201 // ¤
202 // ===========================================================================================
203 // GetNameLength ()
204 // ================
205
206
207 static ByteCount GetNameLength ( BytePtr nameStart )
208 {
209 BytePtr nameEnd = nameStart;
210
211
212 if ( nameStart != NULL ) {
213 while ( *nameEnd != 0 ) nameEnd += 1;
214 }
215
216 return (nameEnd - nameStart);
217
218
219 } // GetNameLength ()
220
221
222 // ¤
223 // ===========================================================================================
224 // FindRelocationInfo ()
225 // =====================
226
227
228 static LoaderRelExpHeader * FindRelocationInfo ( PEFPrivateInfo * pefPrivate,
229 ItemCount sectionIndex )
230 {
231 LoaderRelExpHeader * relocInfo = NULL;
232 const ItemCount loopLimit = pefPrivate->ldrHeader->numSections;
233 ItemCount relocIndex;
234
235
236 for ( relocIndex = 0; relocIndex < loopLimit; relocIndex += 1 ) {
237 relocInfo = &pefPrivate->ldrSections[relocIndex];
238 if ( sectionIndex == relocInfo->sectionNumber ) return relocInfo;
239 }
240 return NULL;
241
242
243 } // FindRelocationInfo ()
244
245
246 // ¤
247 // ===========================================================================================
248 // GetSectionName ()
249 // =================
250
251
252 static void GetSectionName ( PEFPrivateInfo * pefPrivate,
253 SectionHeader * sectionHeader,
254 CFContHashedName * sectionName )
255 {
256 CFContStringHash nameHash = 0;
257 BytePtr nameText = NULL;
258 ByteCount nameLength;
259
260
261 if ( sectionHeader->sectionName != -1 ) {
262 nameText = pefPrivate->stringTable + sectionHeader->sectionName;
263 nameLength = GetNameLength ( nameText );
264 nameHash = CFContHashName ( nameText, nameLength );
265 }
266
267 sectionName->nameHash = nameHash;
268 sectionName->nameText = nameText;
269
270
271 } // GetSectionName ()
272
273
274 // ¤
275 // ===========================================================================================
276 // PEF_OpenContainer ()
277 // ====================
278
279
280 OSStatus PEF_OpenContainer ( LogicalAddress mappedAddress,
281 LogicalAddress runningAddress,
282 ByteCount containerLength,
283 KernelProcessID runningProcessID,
284 const CFContHashedName * cfragName,
285 CFContOpenOptions options,
286 CFContAllocateMem Allocate,
287 CFContReleaseMem Release,
288 CFContHandlerRef * containerRef,
289 CFContHandlerProcsPtr * handlerProcs )
290 {
291 #pragma unused ( containerLength )
292 #pragma unused ( runningProcessID )
293 #pragma unused ( cfragName )
294
295 OSStatus err = -1;//cfragCFMInternalErr;
296 FileHeader * fileHeader = (FileHeader *) mappedAddress;
297 PEFPrivateInfo * pefPrivate = NULL;
298 SectionHeader * loaderSection = NULL;
299 SInt32 sectionIndex;
300
301
302 if ( (sizeof ( PEF_SBits32 ) != 4) | (sizeof ( PEF_UBits32 ) != 4) ) goto InternalError; // ! Is "int" 32 bits?
303
304 if ( (Allocate == NULL) ||
305 (Release == NULL) ||
306 (containerRef == NULL) ||
307 (handlerProcs == NULL) ) goto ParameterError;
308
309 *containerRef = NULL; // Clear for errors, only set on OK path.
310 *handlerProcs = NULL;
311
312
313 // ---------------------------------------------------------------------------------
314 // Allow the container address to be null as a special case to get the loader procs.
315 // Otherwise validate the header as acceptable PEF.
316
317 if ( mappedAddress == NULL ) goto OK;
318
319 if ( (fileHeader->magic1 != kPEFMagic1) ||
320 (fileHeader->magic2 != kPEFMagic2) ||
321 (fileHeader->fileTypeID != kPEFTypeID) ||
322 (fileHeader->versionNumber != kPEFVersion) ) goto FragmentFormatError;
323
324
325 // -----------------------------------------------
326 // Allocate and initialize the private info block.
327
328 pefPrivate = (PEFPrivateInfo *) ((*Allocate) ( sizeof ( PEFPrivateInfo ) ));
329 if ( pefPrivate == NULL ) goto PrivateMemoryError;
330
331 PEF_BlockClear ( pefPrivate, sizeof ( *pefPrivate ) );
332
333 pefPrivate->Allocate = Allocate;
334 pefPrivate->Release = Release;
335 pefPrivate->mappedContainer = (BytePtr) mappedAddress;
336 pefPrivate->runningContainer = (BytePtr) runningAddress;
337 pefPrivate->sectionCount = fileHeader->loadableSections;
338 pefPrivate->sections = (SectionHeader *) (fileHeader + 1);
339 pefPrivate->stringTable = (BytePtr) (&pefPrivate->sections[fileHeader->numberSections]);
340 pefPrivate->loadInPlace = ((options & kCFContPrepareInPlaceMask) != 0);
341
342 // -----------------------------------------------------
343 // Find the loader section and extract important fields.
344
345 for ( sectionIndex = 0; sectionIndex < fileHeader->numberSections; sectionIndex += 1 ) {
346 loaderSection = & pefPrivate->sections[sectionIndex];
347 if ( loaderSection->regionKind == kPEFLoaderSection ) break;
348 }
349 if ( sectionIndex == fileHeader->numberSections ) goto FragmentCorruptError;
350
351 pefPrivate->ldrSectionNo = sectionIndex;
352 pefPrivate->ldrHeader = (LoaderHeader *) ((BytePtr)mappedAddress + loaderSection->containerOffset);
353 pefPrivate->ldrStringTable = (BytePtr)pefPrivate->ldrHeader + pefPrivate->ldrHeader->stringsOffset;
354
355 pefPrivate->ldrImportFiles = (LoaderImportFileID *) (pefPrivate->ldrHeader + 1);
356 pefPrivate->ldrImportSymbols = (LoaderImport *) (pefPrivate->ldrImportFiles + pefPrivate->ldrHeader->numImportFiles);
357 pefPrivate->ldrSections = (LoaderRelExpHeader *) (pefPrivate->ldrImportSymbols + pefPrivate->ldrHeader->numImportSyms);
358 pefPrivate->ldrRelocations = (BytePtr)pefPrivate->ldrHeader + pefPrivate->ldrHeader->relocationsOffset;
359
360 pefPrivate->ldrHashSlot = (HashSlotEntry *) ((BytePtr)pefPrivate->ldrHeader + pefPrivate->ldrHeader->hashSlotTable);
361 pefPrivate->ldrHashChain = (HashChainEntry *) (pefPrivate->ldrHashSlot + (1 << pefPrivate->ldrHeader->hashSlotTabSize));
362 pefPrivate->ldrExportSymbols = (LoaderExport *) (pefPrivate->ldrHashChain + pefPrivate->ldrHeader->numExportSyms);
363
364 // ----------------------------------------------------
365 // Set up the array to store resolved import addresses.
366
367 if ( pefPrivate->ldrHeader->numImportSyms > 0 ) {
368 pefPrivate->imports = (BytePtr *) ((*Allocate) ( pefPrivate->ldrHeader->numImportSyms * sizeof ( BytePtr ) ));
369 if ( pefPrivate->imports == NULL ) goto PrivateMemoryError;
370 }
371
372 // -----------------------------------------------------------------
373 // Set up the pointers to the arrays of section origins and offsets.
374
375 if (pefPrivate->sectionCount <= kBuiltinSectionArraySize) {
376 pefPrivate->mappedOrigins = & pefPrivate->originArray[0];
377 pefPrivate->runningOffsets = & pefPrivate->offsetArray[0];
378 } else {
379 pefPrivate->mappedOrigins = (BytePtr *) ((*Allocate) ( pefPrivate->sectionCount * sizeof ( BytePtr ) ));
380 if ( pefPrivate->mappedOrigins == NULL ) goto PrivateMemoryError;
381 pefPrivate->runningOffsets = (ByteCount *) ((*Allocate) ( pefPrivate->sectionCount * sizeof ( ByteCount ) ));
382 if ( pefPrivate->runningOffsets == NULL ) goto PrivateMemoryError;
383 }
384
385 // ---------------------------------------------------------------------------------------
386 // Fill in the origin and offset arrays. The origin array gives the base address of the
387 // section instance as visible in the loader's address space. I.e. it tells the loader
388 // where it can access the loaded section contents. The offset array tells what to add
389 // for relocations refering to that section. So it must be based on running addresses and
390 // must "remove" the presumed running address. If the section will be used in place we
391 // must compute the final values here. Otherwise SetRegionAddress will be called later to
392 // provide the mapped and running addresses. Validate load in place restrictions too.
393
394 // ??? We really ought to consider getting rid of the preset for in-place usage and make
395 // ??? that case as close as possible to the normal case.
396
397 // ! Note that although the ByteCount type used in the offset arrays is unsigned, ignoring
398 // ! overflow lets things work right for a full -4GB to +4GB offset range.
399
400 for ( sectionIndex = 0; sectionIndex < pefPrivate->sectionCount; sectionIndex += 1 ) {
401
402 SectionHeader * section = & pefPrivate->sections[sectionIndex];
403
404 pefPrivate->mappedOrigins[sectionIndex] = (BytePtr) -1; // ! Just a diagnostic tag.
405 pefPrivate->runningOffsets[sectionIndex] = - ((ByteCount) section->sectionAddress); // Subtract the presumed address.
406
407 if ( pefPrivate->loadInPlace ) {
408 if ( (section->regionKind == kPEFPIDataSection) || (section->execSize != section->rawSize) ) goto FragmentUsageError;
409 section->sectionAddress = pefPrivate->runningContainer + section->containerOffset;
410 pefPrivate->mappedOrigins[sectionIndex] = pefPrivate->mappedContainer + section->containerOffset;
411 pefPrivate->runningOffsets[sectionIndex] += (ByteCount) section->sectionAddress; // Add in the new address.
412 }
413
414 }
415
416 if ( options & kCFContPrepareInPlaceMask ) fileHeader->memoryAddress = runningAddress;
417
418
419 OK:
420 err = noErr;
421 *handlerProcs = &PEFHandlerProcs;
422 *containerRef = (CFContHandlerRef) pefPrivate;
423
424 EXIT:
425 return err;
426
427 ERROR:
428 (void) PEF_CloseContainer ( (CFContHandlerRef) pefPrivate, kNilOptions );
429 goto EXIT;
430
431 InternalError:
432 err = cfragCFMInternalErr;
433 goto ERROR;
434
435 ParameterError:
436 err = paramErr;
437 goto ERROR;
438
439 FragmentFormatError:
440 err = cfragFragmentFormatErr;
441 goto ERROR;
442
443 PrivateMemoryError:
444 err = cfragNoPrivateMemErr;
445 goto ERROR;
446
447 FragmentCorruptError:
448 err = cfragFragmentCorruptErr;
449 goto ERROR;
450
451 FragmentUsageError:
452 err = cfragFragmentUsageErr;
453 goto ERROR;
454
455
456 } // PEF_OpenContainer ()
457
458
459 // ¤
460 // ===========================================================================================
461 // PEF_CloseContainer ()
462 // =====================
463
464
465 OSStatus PEF_CloseContainer ( CFContHandlerRef containerRef,
466 CFContCloseOptions options )
467 {
468 OSStatus err = cfragCFMInternalErr;
469 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
470 CFContReleaseMem Release = NULL;
471
472
473 if ( pefPrivate == NULL ) goto OK; // Simplifies error cleanup from PEF_OpenContainer.
474
475
476 Release = pefPrivate->Release;
477
478 if ( pefPrivate->sectionCount > kBuiltinSectionArraySize ) {
479 if ( pefPrivate->mappedOrigins != NULL ) {
480 (*Release) ( pefPrivate->mappedOrigins );
481 pefPrivate->mappedOrigins = NULL;
482 }
483 if ( pefPrivate->runningOffsets != NULL ) {
484 (*Release) ( pefPrivate->runningOffsets );
485 pefPrivate->runningOffsets = NULL;
486 }
487 }
488
489 if ( pefPrivate->imports != NULL ) {
490 (*Release) ( pefPrivate->imports );
491 pefPrivate->imports = NULL;
492 }
493
494 pefPrivate->resolved = 0; // ! Disables reexported import optimization.
495
496 if ( ! (options & kCFContPartialCloseMask) ) (*Release) ( pefPrivate );
497
498
499 OK:
500 err = noErr;
501 return err;
502
503 } // PEF_CloseContainer ()
504
505
506 // ¤
507 // ===========================================================================================
508 // PEF_GetContainerInfo ()
509 // =======================
510
511
512 OSStatus PEF_GetContainerInfo ( CFContHandlerRef containerRef,
513 PBVersion infoVersion,
514 CFContContainerInfo * containerInfo )
515 {
516 OSStatus err = cfragCFMInternalErr;
517 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
518 FileHeader * fileHeader = NULL;
519
520
521 if ( (pefPrivate == NULL) || (containerInfo == NULL) ) goto ParameterError;
522 if ( infoVersion != kCFContContainerInfoVersion ) goto ParameterError;
523
524
525 fileHeader = (FileHeader *) pefPrivate->mappedContainer;
526
527 containerInfo->cfragName.nameHash = 0; // PEF does not have an embedded name.
528 containerInfo->cfragName.nameText = NULL;
529
530 containerInfo->modDate = fileHeader->dateTimeStamp;
531 containerInfo->architecture = fileHeader->architectureID;
532 containerInfo->currentVersion = fileHeader->currentVersion;
533 containerInfo->oldImpVersion = fileHeader->oldImpVersion;
534 containerInfo->oldDefVersion = fileHeader->oldDefVersion;
535
536 err = noErr;
537
538 EXIT:
539 return err;
540
541 ERROR:
542 goto EXIT;
543
544 ParameterError:
545 err = paramErr;
546 goto ERROR;
547
548
549 } // PEF_GetContainerInfo ()
550
551
552 // ¤
553 // ===========================================================================================
554 // PEF_GetSectionCount ()
555 // ======================
556
557
558 OSStatus PEF_GetSectionCount ( CFContHandlerRef containerRef,
559 ItemCount * sectionCount )
560 {
561 OSStatus err = cfragCFMInternalErr;
562 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
563
564
565 if ( (pefPrivate == NULL) || (sectionCount == NULL) ) goto ParameterError;
566
567 *sectionCount = pefPrivate->sectionCount;
568
569 err = noErr;
570
571 EXIT:
572 return err;
573
574 ERROR:
575 goto EXIT;
576
577 ParameterError:
578 err = paramErr;
579 goto ERROR;
580
581
582 } // PEF_GetSectionCount ()
583
584
585 // ¤
586 // ===========================================================================================
587 // PEF_GetSectionInfo ()
588 // =====================
589
590
591 OSStatus PEF_GetSectionInfo ( CFContHandlerRef containerRef,
592 ItemCount sectionIndex,
593 PBVersion infoVersion,
594 CFContSectionInfo * sectionInfo )
595 {
596 OSStatus err = cfragCFMInternalErr;
597 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
598 SectionHeader * sectionHeader = NULL;
599
600
601 if ( (pefPrivate == NULL) || (sectionInfo == NULL) ) goto ParameterError;
602 if ( infoVersion != kCFContSectionInfoVersion ) goto ParameterError;
603 if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError;
604
605
606 sectionHeader = &pefPrivate->sections[sectionIndex];
607
608 GetSectionName ( pefPrivate, sectionHeader, &sectionInfo->sectionName );
609
610 sectionInfo->sharing = sectionHeader->shareKind;
611 sectionInfo->alignment = sectionHeader->alignment;
612 sectionInfo->reservedA = 0;
613 sectionInfo->containerOffset = sectionHeader->containerOffset;
614 sectionInfo->containerLength = sectionHeader->rawSize;
615 sectionInfo->unpackedLength = sectionHeader->initSize;
616 sectionInfo->totalLength = sectionHeader->execSize;
617 sectionInfo->defaultAddress = sectionHeader->sectionAddress;
618
619 sectionInfo->options = kNilOptions;
620 if ( FindRelocationInfo ( pefPrivate, sectionIndex ) != NULL ) sectionInfo->options |= kRelocatedCFContSectionMask;
621
622 switch ( pefPrivate->sections[sectionIndex].regionKind ) {
623 case kPEFCodeSection :
624 sectionInfo->access = kCFContNormalCode;
625 break;
626 case kPEFDataSection :
627 sectionInfo->access = kCFContWriteableData;
628 break;
629 case kPEFPIDataSection :
630 sectionInfo->access = kCFContWriteableData;
631 sectionInfo->options |= kPackedCFContSectionMask;
632 break;
633 case kPEFConstantSection :
634 sectionInfo->access = kCFContReadOnlyData;
635 break;
636 case kPEFExecDataSection :
637 sectionInfo->access = kCFContWriteableData | kCFContMemExecuteMask;
638 break;
639 default :
640 sectionInfo->access = kCFContReadOnlyData; // ! Not necessarily right, but safe.
641 break;
642 }
643
644 err = noErr;
645
646 EXIT:
647 return err;
648
649 ERROR:
650 goto EXIT;
651
652 ParameterError:
653 err = paramErr;
654 goto ERROR;
655
656
657 } // PEF_GetSectionInfo ()
658
659
660 // ¤
661 // ===========================================================================================
662 // PEF_FindSectionInfo ()
663 // ======================
664
665
666 OSStatus PEF_FindSectionInfo ( CFContHandlerRef containerRef,
667 const CFContHashedName * sectionName,
668 PBVersion infoVersion,
669 ItemCount * sectionIndex, // May be null.
670 CFContSectionInfo * sectionInfo ) // May be null.
671 {
672 OSStatus err = cfragCFMInternalErr;
673 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
674 SectionHeader * sectionHeader = NULL;
675 CFContHashedName hashedName;
676
677 ItemCount tempIndex;
678 CFContSectionInfo tempInfo;
679
680
681 if ( pefPrivate == NULL ) goto ParameterError;
682 if ( (sectionInfo != NULL) && (infoVersion != kCFContSectionInfoVersion) ) goto ParameterError;
683
684 if ( sectionIndex == NULL ) sectionIndex = &tempIndex;
685 if ( sectionInfo == NULL ) sectionInfo = &tempInfo;
686
687
688 for ( tempIndex = 0; tempIndex < pefPrivate->sectionCount; tempIndex += 1 ) {
689 sectionHeader = &pefPrivate->sections[tempIndex];
690 GetSectionName ( pefPrivate, sectionHeader, &hashedName );
691 if ( (hashedName.nameHash == sectionName->nameHash) &&
692 (PEF_CompareBytes ( hashedName.nameText, sectionName->nameText, CFContStringHashLength ( hashedName.nameHash ) )) ) break;
693 }
694 if ( tempIndex == pefPrivate->sectionCount ) goto NoSectionError;
695 *sectionIndex = tempIndex;
696
697 err = PEF_GetSectionInfo ( containerRef, tempIndex, infoVersion, sectionInfo );
698 if ( err != noErr ) goto ERROR;
699
700 err = noErr;
701
702 EXIT:
703 return err;
704
705 ERROR:
706 goto EXIT;
707
708 ParameterError:
709 err = paramErr;
710 goto ERROR;
711
712 NoSectionError:
713 err = cfragNoSectionErr;
714 goto ERROR;
715
716
717 } // PEF_FindSectionInfo ()
718
719
720 // ¤
721 // ===========================================================================================
722 // PEF_SetSectionAddress ()
723 // ========================
724
725
726 OSStatus PEF_SetSectionAddress ( CFContHandlerRef containerRef,
727 ItemCount sectionIndex,
728 LogicalAddress mappedAddress,
729 LogicalAddress runningAddress )
730 {
731 OSErr err = cfragCFMInternalErr;
732 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
733 SectionHeader * section = NULL;
734
735
736 if ( (pefPrivate == NULL) || (sectionIndex >= pefPrivate->sectionCount) ) goto ParameterError;
737
738
739 // --------------------------------------------------------------------------------------
740 // For a load in place usage we've already set the addresses, make sure these match.
741 // Otherwise set both addresses. Note that the "presumed" address is already subtracted.
742
743 section = & pefPrivate->sections[sectionIndex];
744
745 if ( ! pefPrivate->loadInPlace ) {
746
747 pefPrivate->mappedOrigins[sectionIndex] = (BytePtr) mappedAddress;
748 pefPrivate->runningOffsets[sectionIndex] += (ByteCount) runningAddress;
749
750 } else {
751
752 if ( (runningAddress != section->sectionAddress) ||
753 (mappedAddress != pefPrivate->mappedOrigins[sectionIndex]) ) goto UsageError;
754
755 }
756
757 err = noErr;
758
759 EXIT:
760 return err;
761
762 ERROR:
763 goto EXIT;
764
765 ParameterError:
766 err = paramErr;
767 goto ERROR;
768
769 UsageError:
770 err = cfragFragmentUsageErr;
771 goto ERROR;
772
773
774 } // PEF_SetSectionAddress ()
775
776
777 // ¤
778 // ===========================================================================================
779 // PEF_GetAnonymousSymbolLocations ()
780 // ==================================
781
782
783 extern OSStatus PEF_GetAnonymousSymbolLocations ( CFContHandlerRef containerRef,
784 CFContLogicalLocation * mainLocation, // May be null.
785 CFContLogicalLocation * initLocation, // May be null.
786 CFContLogicalLocation * termLocation ) // May be null.
787 {
788 OSStatus err = cfragCFMInternalErr;
789 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
790 LoaderHeader * ldrHeader = NULL;
791
792 CFContLogicalLocation tempLocation;
793
794
795 if ( (pefPrivate == NULL) ) goto ParameterError;
796
797 if ( mainLocation == NULL ) mainLocation = &tempLocation;
798 if ( initLocation == NULL ) initLocation = &tempLocation;
799 if ( termLocation == NULL ) termLocation = &tempLocation;
800
801
802 ldrHeader = pefPrivate->ldrHeader;
803
804 mainLocation->section = ldrHeader->entryPointSection;
805 mainLocation->offset = ldrHeader->entryPointOffset;
806
807 initLocation->section = ldrHeader->initPointSection;
808 initLocation->offset = ldrHeader->initPointOffset;
809
810 termLocation->section = ldrHeader->termPointSection;
811 termLocation->offset = ldrHeader->termPointOffset;
812
813 err = noErr;
814
815 EXIT:
816 return err;
817
818 ERROR:
819 goto EXIT;
820
821 ParameterError:
822 err = paramErr;
823 goto ERROR;
824
825
826 } // PEF_GetAnonymousSymbolLocations ()
827
828
829 // ¤
830 // ===========================================================================================
831 // PEF_GetExportedSymbolCount ()
832 // =============================
833
834
835 extern OSStatus PEF_GetExportedSymbolCount ( CFContHandlerRef containerRef,
836 ItemCount * exportCount )
837 {
838 OSStatus err = cfragCFMInternalErr;
839 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
840
841
842 if ( (pefPrivate == NULL) || (exportCount == NULL) ) goto ParameterError;
843
844 *exportCount = pefPrivate->ldrHeader->numExportSyms;
845
846 err = noErr;
847
848 EXIT:
849 return err;
850
851 ERROR:
852 goto EXIT;
853
854 ParameterError:
855 err = paramErr;
856 goto ERROR;
857
858
859 } // PEF_GetExportedSymbolCount ()
860
861
862 // ¤
863 // ===========================================================================================
864 // PEF_GetExportedSymbolInfo ()
865 // ============================
866
867
868 OSStatus PEF_GetExportedSymbolInfo ( CFContHandlerRef containerRef,
869 CFContSignedIndex exportIndex,
870 PBVersion infoVersion,
871 CFContExportedSymbolInfo * exportInfo )
872 {
873 OSStatus err = cfragCFMInternalErr;
874 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
875 LoaderExport * exportedSymbol = NULL;
876
877
878 if ( (pefPrivate == NULL) || (exportInfo == NULL) ) goto ParameterError;
879 if ( exportIndex >= pefPrivate->ldrHeader->numExportSyms ) goto ParameterError;
880 if ( infoVersion != kCFContExportedSymbolInfoVersion ) goto ParameterError;
881
882
883 if ( exportIndex >= 0 ) {
884
885 exportedSymbol = &pefPrivate->ldrExportSymbols[exportIndex];
886
887 exportInfo->symbolName.nameHash = pefPrivate->ldrHashChain[exportIndex].hashword;
888 exportInfo->symbolName.nameText = &pefPrivate->ldrStringTable[exportedSymbol->nameOffset];
889
890 exportInfo->symbolClass = exportedSymbol->symClass;
891 exportInfo->reservedA = 0;
892 exportInfo->reservedB = 0;
893 exportInfo->options = kNilOptions;
894
895 exportInfo->location.section = exportedSymbol->sectionNumber;
896
897 #if 1 // *** Disable the reexported import optimization.
898 exportInfo->location.offset = exportedSymbol->offset;
899 #else
900 // This is the buggy optimization. It has problems with missing weak libraries.
901 // Addition of a "resolvedImports" bit vector is probably the way to fix it, but it
902 // may not be much of an optimization then.
903 if ( (! pefPrivate->resolved) || (exportedSymbol->sectionNumber != kReExportImport) ) {
904 exportInfo->location.offset = exportedSymbol->address;
905 } else {
906 exportInfo->location.section = kPhysicalExport;
907 exportInfo->location.offset = pefPrivate->imports[exportedSymbol->address];
908 }
909 #endif
910
911 } else {
912
913 CFContLogicalLocation mainLocation;
914 CFContLogicalLocation initLocation;
915 CFContLogicalLocation termLocation;
916
917 err = PEF_GetAnonymousSymbolLocations ( containerRef, &mainLocation, &initLocation, &termLocation );
918 if ( err != noErr ) goto ERROR;
919
920 switch ( exportIndex ) {
921 case kMainCFragSymbolIndex :
922 exportInfo->location = mainLocation;
923 exportInfo->symbolClass = 0xFF; // !!! Ought to have a kUnknownCFragSymbol constant.
924 break;
925 case kInitCFragSymbolIndex :
926 exportInfo->location = initLocation;
927 exportInfo->symbolClass = kTVectorCFragSymbol; // ! Very well better be!
928 break;
929 case kTermCFragSymbolIndex :
930 exportInfo->location = termLocation;
931 exportInfo->symbolClass = kTVectorCFragSymbol; // ! Very well better be!
932 break;
933 default :
934 goto ParameterError;
935 }
936
937 exportInfo->symbolName.nameHash = 0;
938 exportInfo->symbolName.nameText = NULL;
939
940 exportInfo->reservedA = 0;
941 exportInfo->reservedB = 0;
942 exportInfo->options = kNilOptions;
943
944 }
945
946 err = noErr;
947
948 EXIT:
949 return err;
950
951 ERROR:
952 goto EXIT;
953
954 ParameterError:
955 err = paramErr;
956 goto ERROR;
957
958
959 } // PEF_GetExportedSymbolInfo ()
960
961
962 // ¤
963 // ===========================================================================================
964 // PEF_FindExportedSymbolInfo ()
965 // =============================
966
967
968 OSStatus PEF_FindExportedSymbolInfo ( CFContHandlerRef containerRef,
969 const CFContHashedName * exportName,
970 PBVersion infoVersion,
971 ItemCount * exportIndex_o, // May be null.
972 CFContExportedSymbolInfo * exportInfo ) // May be null.
973 {
974 OSStatus err = cfragCFMInternalErr;
975 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
976 LoaderExport * exportedSymbol = NULL;
977 CFContStringHash * hashwordList = NULL;
978 CFContStringHash * nextHashword = NULL;
979 HashSlotEntry * hashSlot = NULL;
980 ByteCount nameLength = CFContStringHashLength ( exportName->nameHash );
981 ItemCount exportIndex;
982 ItemCount slotIndex;
983 ItemCount chainLimit;
984 Boolean nameMatch;
985
986
987 if ( pefPrivate == NULL ) goto ParameterError;
988 if ( infoVersion != kCFContExportedSymbolInfoVersion ) goto ParameterError;
989
990
991 hashwordList = &pefPrivate->ldrHashChain[0].hashword;
992
993 slotIndex = GetPEFHashSlot ( exportName->nameHash, pefPrivate->ldrHeader->hashSlotTabSize );
994 hashSlot = &pefPrivate->ldrHashSlot[slotIndex];
995
996 exportIndex = hashSlot->chainIndex;
997 chainLimit = exportIndex + hashSlot->chainCount;
998 nextHashword = &hashwordList[exportIndex];
999
1000 while ( exportIndex < chainLimit ) {
1001
1002 if ( *nextHashword == exportName->nameHash ) {
1003 exportedSymbol = &pefPrivate->ldrExportSymbols[exportIndex];
1004 nameMatch = PEF_CompareBytes ( exportName->nameText,
1005 &pefPrivate->ldrStringTable[exportedSymbol->nameOffset],
1006 nameLength );
1007 if ( nameMatch ) goto Found;
1008 }
1009
1010 exportIndex += 1;
1011 nextHashword += 1; // ! Pointer arithmetic.
1012 }
1013 goto NotFoundError;
1014
1015 Found:
1016 if ( exportIndex_o != NULL ) *exportIndex_o = exportIndex;
1017 if ( exportInfo != NULL ) {
1018 err = PEF_GetExportedSymbolInfo ( containerRef, exportIndex, infoVersion, exportInfo );
1019 if ( err != noErr ) goto ERROR;
1020 }
1021
1022 err = noErr;
1023
1024 EXIT:
1025 return err;
1026
1027 ERROR:
1028 goto EXIT;
1029
1030 ParameterError:
1031 err = paramErr;
1032 goto ERROR;
1033
1034 NotFoundError:
1035 err = cfragNoSymbolErr;
1036 goto ERROR;
1037
1038
1039 } // PEF_FindExportedSymbolInfo ()
1040
1041
1042 // ¤
1043 // ===========================================================================================
1044 // PEF_GetImportCounts ()
1045 // ======================
1046
1047
1048 OSStatus PEF_GetImportCounts ( CFContHandlerRef containerRef,
1049 ItemCount * libraryCount, // May be null.
1050 ItemCount * symbolCount ) // May be null.
1051 {
1052 OSStatus err = cfragCFMInternalErr;
1053 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
1054
1055
1056 if ( pefPrivate == NULL ) goto ParameterError;
1057
1058 if ( libraryCount != NULL ) *libraryCount = pefPrivate->ldrHeader->numImportFiles;
1059 if ( symbolCount != NULL ) *symbolCount = pefPrivate->ldrHeader->numImportSyms;
1060
1061 err = noErr;
1062
1063 EXIT:
1064 return err;
1065
1066 ERROR:
1067 goto EXIT;
1068
1069 ParameterError:
1070 err = paramErr;
1071 goto ERROR;
1072
1073
1074 } // PEF_GetImportCounts ()
1075
1076
1077 // ¤
1078 // ===========================================================================================
1079 // PEF_GetImportedLibraryInfo ()
1080 // =============================
1081
1082
1083 OSStatus PEF_GetImportedLibraryInfo ( CFContHandlerRef containerRef,
1084 ItemCount libraryIndex,
1085 PBVersion infoVersion,
1086 CFContImportedLibraryInfo * libraryInfo )
1087 {
1088 OSStatus err = cfragCFMInternalErr;
1089 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
1090 LoaderImportFileID * importedLibrary = NULL;
1091 BytePtr nameText = NULL;
1092 ByteCount nameLength;
1093
1094
1095 if ( (pefPrivate == NULL) || (libraryInfo == NULL) ) goto ParameterError;
1096 if ( infoVersion != kCFContImportedLibraryInfoVersion ) goto ParameterError;
1097 if ( libraryIndex >= pefPrivate->ldrHeader->numImportFiles ) goto ParameterError;
1098
1099
1100 importedLibrary = &pefPrivate->ldrImportFiles[libraryIndex];
1101
1102 nameText = &pefPrivate->ldrStringTable[importedLibrary->fileNameOffset];
1103 nameLength = GetNameLength ( nameText );
1104
1105 libraryInfo->libraryName.nameHash = CFContHashName ( nameText, nameLength );
1106 libraryInfo->libraryName.nameText = nameText;
1107
1108 libraryInfo->linkedVersion = importedLibrary->linkedVersion;
1109 libraryInfo->oldImpVersion = importedLibrary->oldImpVersion;
1110 libraryInfo->options = kNilOptions;
1111
1112 if ( importedLibrary->options & kPEFInitBeforeMask ) libraryInfo->options |= kCFContInitBeforeMask;
1113 if ( importedLibrary->options & kPEFWeakLibraryMask ) libraryInfo->options |= kCFContWeakLibraryMask;
1114 if ( importedLibrary->options & kPEFDeferredBindMask ) libraryInfo->options |= kCFContDeferredBindMask;
1115
1116 err = noErr;
1117
1118 EXIT:
1119 return err;
1120
1121 ERROR:
1122 goto EXIT;
1123
1124 ParameterError:
1125 err = paramErr;
1126 goto ERROR;
1127
1128
1129 } // PEF_GetImportedLibraryInfo ()
1130
1131
1132 // ¤
1133 // ===========================================================================================
1134 // PEF_GetImportedSymbolInfo ()
1135 // ============================
1136
1137
1138 OSStatus PEF_GetImportedSymbolInfo ( CFContHandlerRef containerRef,
1139 ItemCount symbolIndex,
1140 PBVersion infoVersion,
1141 CFContImportedSymbolInfo * symbolInfo )
1142 {
1143 OSStatus err = cfragCFMInternalErr;
1144 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
1145 LoaderImport * importedSymbol = NULL;
1146 LoaderImportFileID * importedLibrary = NULL;
1147 BytePtr nameText = NULL;
1148 ByteCount nameLength;
1149 ItemCount libraryCount;
1150 ItemCount libraryIndex;
1151
1152
1153 if ( (pefPrivate == NULL) || (symbolInfo == NULL) ) goto ParameterError;
1154 if ( infoVersion != kCFContImportedSymbolInfoVersion ) goto ParameterError;
1155 if ( symbolIndex >= pefPrivate->ldrHeader->numImportSyms ) goto ParameterError;
1156
1157
1158 importedSymbol = &pefPrivate->ldrImportSymbols[symbolIndex];
1159 libraryCount = pefPrivate->ldrHeader->numImportFiles;
1160
1161 nameText = &pefPrivate->ldrStringTable[importedSymbol->nameOffset];
1162 nameLength = GetNameLength ( nameText );
1163
1164 symbolInfo->symbolName.nameHash = CFContHashName ( nameText, nameLength );
1165 symbolInfo->symbolName.nameText = nameText;
1166
1167 symbolInfo->symbolClass = importedSymbol->symClass & 0x0F;
1168 symbolInfo->reservedA = 0;
1169 symbolInfo->reservedB = 0;
1170 symbolInfo->options = 0;
1171
1172 if ( importedSymbol->symClass & kPEFWeakSymbolMask ) symbolInfo->options |= kCFContWeakSymbolMask;
1173
1174 for ( libraryIndex = 0; libraryIndex < libraryCount; libraryIndex += 1 ) {
1175 importedLibrary = &pefPrivate->ldrImportFiles[libraryIndex];
1176 if ( (importedLibrary->impFirst <= symbolIndex) &&
1177 (symbolIndex < (importedLibrary->impFirst + importedLibrary->numImports)) ) {
1178 break;
1179 }
1180 }
1181 if ( libraryIndex == libraryCount ) goto FragmentCorruptError;
1182
1183 symbolInfo->libraryIndex = libraryIndex;
1184
1185 err = noErr;
1186
1187 EXIT:
1188 return err;
1189
1190 ERROR:
1191 goto EXIT;
1192
1193 ParameterError:
1194 err = paramErr;
1195 goto ERROR;
1196
1197 FragmentCorruptError:
1198 err = cfragFragmentCorruptErr;
1199 goto ERROR;
1200
1201
1202 } // PEF_GetImportedSymbolInfo ()
1203
1204
1205 // ¤
1206 // ===========================================================================================
1207 // PEF_SetImportedSymbolAddress ()
1208 // ===============================
1209
1210
1211 OSStatus PEF_SetImportedSymbolAddress ( CFContHandlerRef containerRef,
1212 ItemCount symbolIndex,
1213 LogicalAddress symbolAddress )
1214 {
1215 OSStatus err = cfragCFMInternalErr;
1216 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
1217
1218
1219 if ( pefPrivate == NULL ) goto ParameterError;
1220 if ( symbolIndex >= pefPrivate->ldrHeader->numImportSyms ) goto ParameterError;
1221
1222
1223 pefPrivate->imports[symbolIndex] = symbolAddress;
1224
1225 err = noErr;
1226
1227 EXIT:
1228 return err;
1229
1230 ERROR:
1231 goto EXIT;
1232
1233 ParameterError:
1234 err = paramErr;
1235 goto ERROR;
1236
1237
1238 } // PEF_SetImportedSymbolAddress ()
1239
1240
1241 // ¤
1242 // ===========================================================================================
1243 // GetPackedDataCount ()
1244 // =====================
1245
1246
1247 static UInt32 GetPackedDataCount ( UInt8 * * byteHandle )
1248 {
1249 UInt32 count = 0;
1250 UInt8 * bytePtr = *byteHandle;
1251 UInt8 currByte;
1252
1253
1254 do {
1255 currByte = *bytePtr++;
1256 count = (count << kPEFPkDataVCountShift) | (currByte & kPEFPkDataVCountMask);
1257 } while ( (currByte & kPEFPkDataVCountEndMask) != 0 );
1258
1259 *byteHandle = bytePtr;
1260
1261 return count;
1262
1263
1264 } // GetPackedDataCount ()
1265
1266
1267 // ¤
1268 // ===========================================================================================
1269 // UnpackFullSection ()
1270 // ====================
1271
1272
1273 // ------------------------------------------------------------------------------------------
1274 // This is the "normal" case from CFM, unpacking all of the packed portion. Along the way we
1275 // make sure we're not writing beyond the end of the unpacked data. At the end we make sure
1276 // that all we didn't read past the end of the packed data, and that all of the output was
1277 // written.
1278
1279 // ! Note that the xyzEnd pointers are the actual end of the range, not one byte beyond. This
1280 // ! routine will work if the output end address is 0xFFFFFFFF, but not if the packed end is.
1281
1282 // ! Don't do range comparisons as "(lowAddr + length) > highAddr", because this might wrap
1283 // ! the end high end of the address space. Always do "(highAddr - lowAddr) > length".
1284
1285 // ??? We should gather some statistics on actual usage to see whether it is worthwhile to
1286 // ??? have local customized code for common cases. E.g. block fill of 1, 2, or 4 bytes, or
1287 // ??? of interleaved repeats with 1/2/4 byte common or custom portions.
1288
1289
1290 static OSStatus UnpackFullSection ( BytePtr packedBase,
1291 BytePtr packedEnd,
1292 BytePtr outputBase,
1293 BytePtr outputEnd )
1294 {
1295 OSStatus err = cfragCFMInternalErr;
1296 BytePtr packedPos = packedBase;
1297 BytePtr outputPos = outputBase;
1298 BytePtr outPosLimit = outputEnd + 1; // ! Might be zero if outputEnd is 0xFFFFFFFF.
1299
1300 UInt8 currByte;
1301 UInt8 opcode;
1302 UInt32 count1;
1303 UInt32 count2;
1304 UInt32 count3;
1305
1306
1307 if ( (packedEnd + 1) == 0 ) goto FragmentUsageError;
1308
1309
1310 while ( packedPos <= packedEnd ) {
1311
1312
1313 currByte = *packedPos++;
1314 opcode = currByte >> kPEFPkDataOpcodeShift;
1315 count1 = currByte & kPEFPkDataCount5Mask;
1316
1317 if ( count1 == 0 ) count1 = GetPackedDataCount ( &packedPos );
1318
1319
1320 switch ( opcode ) {
1321
1322
1323 case kPEFPkDataZero :
1324
1325 if ( (outPosLimit - outputPos) < count1 ) goto FragmentCorruptError;
1326
1327 PEF_BlockClear ( outputPos, count1 );
1328 outputPos += count1;
1329
1330 break;
1331
1332
1333 case kPEFPkDataBlock :
1334
1335 if ( (outPosLimit - outputPos) < count1 ) goto FragmentCorruptError;
1336
1337 PEF_BlockMove ( packedPos, outputPos, count1 );
1338 packedPos += count1;
1339 outputPos += count1;
1340
1341 break;
1342
1343
1344 case kPEFPkDataRepeat : // ??? Need a BlockFill routine?
1345
1346 count2 = GetPackedDataCount ( &packedPos ) + 1; // ! Stored count is 1 less.
1347
1348 if ( (outPosLimit - outputPos) < (count1 * count2) ) goto FragmentCorruptError;
1349
1350 if ( count1 == 1 ) { // ??? Is this worth the bother? Other sizes?
1351
1352 currByte = *packedPos++;
1353 for ( ; count2 != 0; count2 -= 1 ) *outputPos++ = currByte;
1354
1355 } else {
1356
1357 for ( ; count2 != 0; count2 -= 1 ) {
1358 PEF_BlockMove ( packedPos, outputPos, count1 );
1359 outputPos += count1;
1360 }
1361 packedPos += count1;
1362
1363 }
1364
1365 break;
1366
1367
1368 case kPEFPkDataRepeatBlock :
1369
1370 count2 = GetPackedDataCount ( &packedPos );
1371 count3 = GetPackedDataCount ( &packedPos );
1372
1373 if ( (outPosLimit - outputPos) < (((count1 + count2) * count3) + count1) ) goto FragmentCorruptError;
1374
1375 {
1376 BytePtr commonPos = packedPos;
1377
1378 packedPos += count1; // Skip the common part.
1379
1380 for ( ; count3 != 0; count3 -= 1 ) {
1381
1382 PEF_BlockMove ( commonPos, outputPos, count1 );
1383 outputPos += count1;
1384
1385 PEF_BlockMove ( packedPos, outputPos, count2 );
1386 packedPos += count2;
1387 outputPos += count2;
1388
1389 }
1390
1391 PEF_BlockMove ( commonPos, outputPos, count1 );
1392 outputPos += count1;
1393
1394 }
1395
1396 break;
1397
1398
1399 case kPEFPkDataRepeatZero :
1400
1401 count2 = GetPackedDataCount ( &packedPos );
1402 count3 = GetPackedDataCount ( &packedPos );
1403
1404 if ( (outPosLimit - outputPos) < (((count1 + count2) * count3) + count1) ) goto FragmentCorruptError;
1405
1406 PEF_BlockClear ( outputPos, count1 );
1407 outputPos += count1;
1408
1409 for ( ; count3 != 0; count3 -= 1 ) {
1410
1411 PEF_BlockMove ( packedPos, outputPos, count2 );
1412 packedPos += count2;
1413 outputPos += count2;
1414
1415 PEF_BlockClear ( outputPos, count1 );
1416 outputPos += count1;
1417
1418 }
1419
1420 break;
1421
1422
1423 default :
1424 goto FragmentCorruptError;
1425
1426 }
1427
1428 }
1429
1430
1431 if ( (packedPos != (packedEnd + 1)) || (outputPos != outPosLimit) ) goto FragmentCorruptError;
1432
1433 err = noErr;
1434
1435 EXIT:
1436 return err;
1437
1438 ERROR:
1439 goto EXIT;
1440
1441
1442 FragmentUsageError:
1443 err = cfragFragmentUsageErr;
1444 goto ERROR;
1445
1446 FragmentCorruptError:
1447 err = cfragFragmentCorruptErr;
1448 goto ERROR;
1449
1450
1451 } // UnpackFullSection ()
1452
1453
1454 // ¤
1455 // ===========================================================================================
1456 // UnpackPartialSection ()
1457 // =======================
1458
1459
1460 // -------------------------------------------------------------------------------------------
1461 // This is the case where we want to extract some arbitrary portion of a section as it would
1462 // be when instantiated but not relocated. We have to interpret the packed part up to the
1463 // desired output start, then continue begin unpacking for real. If we run out of packed data
1464 // before filling the output, we fill the rest of the output with zeroes.
1465
1466 // ! We have to be very careful in the skip logic because the current operation probably spans
1467 // ! the skip/output boundary. We have to be similarly careful at the output end because the
1468 // ! current operation probably spans the tail of the output. Don't forget that the partial
1469 // ! output at the start could also fill the output and overflow the tail!
1470
1471 // ! Note that the xyzEnd pointers are the actual end of the range, not one byte beyond. This
1472 // ! routine might not work if outputEnd is 0xFFFFFFFF. This is because outputPos points to
1473 // ! the next byte to be written. The loops that are controlled by "outputPos < outputBase"
1474 // ! or "outputPos <= outputEnd" would fail in this case if outputPos were "outputEnd + 1",
1475 // ! i.e. outputPos would be zero.
1476
1477 // ! Don't do range comparisons as "(lowAddr + length) > highAddr", because this might wrap
1478 // ! the end high end of the address space. Always do "(highAddr - lowAddr) > length".
1479
1480
1481 // -------------------------------------------------------------------------------------------
1482
1483
1484 static void PartialBlockClear ( BytePtr outputBase,
1485 ByteCount outputStartOffset,
1486 ByteCount outputEndOffset,
1487 ByteCount outputOffset,
1488 ByteCount count )
1489 {
1490
1491 if ( ((outputOffset + count) <= outputStartOffset) || (outputOffset > outputEndOffset) ) return; // Nothing to output.
1492
1493 if ( outputOffset < outputStartOffset ) {
1494 count -= (outputStartOffset - outputOffset);
1495 outputOffset = outputStartOffset;
1496 }
1497
1498 if ( count > (outputEndOffset - outputOffset + 1) ) count = outputEndOffset - outputOffset + 1;
1499
1500 PEF_BlockClear ( outputBase + (outputOffset - outputStartOffset), count );
1501
1502 } // PartialBlockClear ();
1503
1504
1505 // -------------------------------------------------------------------------------------------
1506
1507
1508 static void PartialBlockMove ( BytePtr source,
1509 BytePtr outputBase,
1510 ByteCount outputStartOffset,
1511 ByteCount outputEndOffset,
1512 ByteCount outputOffset,
1513 ByteCount count )
1514 {
1515
1516 if ( ((outputOffset + count) <= outputStartOffset) || (outputOffset > outputEndOffset) ) return; // Nothing to output.
1517
1518 if ( outputOffset < outputStartOffset ) {
1519 const ByteCount skipCount = outputStartOffset - outputOffset;
1520 source += skipCount;
1521 count -= skipCount;
1522 outputOffset = outputStartOffset;
1523 }
1524
1525 if ( count > (outputEndOffset - outputOffset + 1) ) count = outputEndOffset - outputOffset + 1;
1526
1527 PEF_BlockMove ( source, outputBase + (outputOffset - outputStartOffset), count );
1528
1529 } // PartialBlockClear ();
1530
1531
1532 // -------------------------------------------------------------------------------------------
1533
1534
1535 static OSStatus UnpackPartialSection ( BytePtr packedBase,
1536 BytePtr packedEnd,
1537 BytePtr outputBase,
1538 BytePtr outputEnd,
1539 ByteCount outputStartOffset )
1540 {
1541 OSStatus err = cfragCFMInternalErr;
1542 const ByteCount outputEndOffset = outputStartOffset + (outputEnd - outputBase);
1543 BytePtr packedPos = NULL;
1544 BytePtr packedBoundary = NULL;
1545 ByteCount outputOffset;
1546 ByteCount outputBoundary;
1547
1548 UInt8 currByte;
1549 UInt8 opcode;
1550 UInt32 count1;
1551 UInt32 count2;
1552 UInt32 count3;
1553
1554
1555 if ( ((packedEnd + 1) == 0) || ((outputEnd + 1) == 0) ) goto FragmentUsageError;
1556
1557
1558 // --------------------------------------------------------------------------------------
1559 // Skip the packed data until we get within the output range. We know there is something
1560 // to unpack, otherwise the zero fill of the output would be done by the caller. This
1561 // loop sets outputOffset to the end of what would be unpacked, until the outputOffset is
1562 // beyond the outputStartOffset. I.e. until we hit the first operation that would create
1563 // actual output.
1564
1565 outputOffset = 0;
1566 packedPos = packedBase;
1567
1568 do {
1569
1570 packedBoundary = packedPos; // The start of the current operation.
1571 outputBoundary = outputOffset;
1572
1573 currByte = *packedPos++;
1574 opcode = currByte >> kPEFPkDataOpcodeShift;
1575 count1 = currByte & kPEFPkDataCount5Mask;
1576
1577 if ( count1 == 0 ) count1 = GetPackedDataCount ( &packedPos );
1578
1579 switch ( opcode ) {
1580
1581 case kPEFPkDataZero :
1582 outputOffset += count1;
1583 break;
1584
1585 case kPEFPkDataBlock :
1586 packedPos += count1;
1587 outputOffset += count1;
1588 break;
1589
1590 case kPEFPkDataRepeat :
1591 count2 = GetPackedDataCount ( &packedPos ) + 1; // ! Stored count is 1 less.
1592 packedPos += count1;
1593 outputOffset += count1 * count2;
1594 break;
1595
1596
1597 case kPEFPkDataRepeatBlock :
1598 count2 = GetPackedDataCount ( &packedPos );
1599 count3 = GetPackedDataCount ( &packedPos );
1600 packedPos += count1 + (count2 * count3);
1601 outputOffset += count1 + ((count1 + count2) * count3);
1602 break;
1603
1604
1605 case kPEFPkDataRepeatZero :
1606 count2 = GetPackedDataCount ( &packedPos );
1607 count3 = GetPackedDataCount ( &packedPos );
1608 packedPos += count2 * count3;
1609 outputOffset += count1 + ((count1 + count2) * count3);
1610 break;
1611
1612
1613 default :
1614 goto FragmentCorruptError;
1615
1616 }
1617
1618 } while ( outputOffset <= outputStartOffset );
1619
1620
1621 //----------------------------------------------------------------------------------------
1622 // Now do the actual unpacking. This uses a copy of the full unpack logic with special
1623 // block copy/clear routines. These special routines do the bounds checking, only writing
1624 // output where actually allowed. This involves "unnecessary" checks for the "middle"
1625 // operations that are fully within the range, but vastly simplifies the boundary cases.
1626
1627 packedPos = packedBoundary; // Reset to the operation that spans the output start.
1628 outputOffset = outputBoundary;
1629
1630 do {
1631
1632 currByte = *packedPos++;
1633 opcode = currByte >> kPEFPkDataOpcodeShift;
1634 count1 = currByte & kPEFPkDataCount5Mask;
1635
1636 if ( count1 == 0 ) count1 = GetPackedDataCount ( &packedPos );
1637
1638 switch ( opcode ) {
1639
1640 case kPEFPkDataZero :
1641 PartialBlockClear ( outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 );
1642 outputOffset += count1;
1643 break;
1644
1645 case kPEFPkDataBlock :
1646 PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 );
1647 packedPos += count1;
1648 outputOffset += count1;
1649 break;
1650
1651 case kPEFPkDataRepeat : // ??? Need a BlockFill routine?
1652 count2 = GetPackedDataCount ( &packedPos ) + 1; // ! Stored count is 1 less.
1653 for ( ; count2 != 0; count2 -= 1 ) {
1654 PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 );
1655 outputOffset += count1;
1656 }
1657 packedPos += count1;
1658 break;
1659
1660 case kPEFPkDataRepeatBlock :
1661
1662 count2 = GetPackedDataCount ( &packedPos );
1663 count3 = GetPackedDataCount ( &packedPos );
1664
1665 {
1666 BytePtr commonPos = packedPos;
1667
1668 packedPos += count1; // Skip the common part.
1669
1670 for ( ; count3 != 0; count3 -= 1 ) {
1671
1672 PartialBlockMove ( commonPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 );
1673 outputOffset += count1;
1674
1675 PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count2 );
1676 packedPos += count2;
1677 outputOffset += count2;
1678
1679 }
1680
1681 PartialBlockMove ( commonPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 );
1682 outputOffset += count1;
1683
1684 }
1685
1686 break;
1687
1688 case kPEFPkDataRepeatZero :
1689
1690 count2 = GetPackedDataCount ( &packedPos );
1691 count3 = GetPackedDataCount ( &packedPos );
1692
1693 PartialBlockClear ( outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 );
1694 outputOffset += count1;
1695
1696 for ( ; count3 != 0; count3 -= 1 ) {
1697
1698 PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count2 );
1699 packedPos += count2;
1700 outputOffset += count2;
1701
1702 PartialBlockClear ( outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 );
1703 outputOffset += count1;
1704
1705 }
1706
1707 break;
1708
1709 default :
1710 goto FragmentCorruptError;
1711
1712 }
1713
1714 } while ( (outputOffset <= outputEndOffset) && (packedPos <= packedEnd) );
1715
1716
1717 // ------------------------------------------
1718 // Finally block clear anything that is left.
1719
1720 if ( outputOffset <= outputEndOffset ) {
1721 PEF_BlockClear ( outputBase + (outputOffset - outputStartOffset), outputEndOffset - outputOffset + 1 );
1722 }
1723
1724 err = noErr;
1725
1726 EXIT:
1727 return err;
1728
1729 ERROR:
1730 goto EXIT;
1731
1732
1733 FragmentUsageError:
1734 err = cfragFragmentUsageErr;
1735 goto ERROR;
1736
1737 FragmentCorruptError:
1738 err = cfragFragmentCorruptErr;
1739 goto ERROR;
1740
1741
1742 } // UnpackPartialSection ()
1743
1744
1745 // ¤
1746 // ===========================================================================================
1747 // PEF_UnpackSection ()
1748 // ====================
1749
1750
1751 OSStatus PEF_UnpackSection ( CFContHandlerRef containerRef,
1752 ItemCount sectionIndex,
1753 ByteCount sectionOffset,
1754 LogicalAddress bufferAddress,
1755 ByteCount bufferLength )
1756 {
1757 OSStatus err = cfragCFMInternalErr;
1758 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
1759 SectionHeader * section = NULL;
1760 BytePtr packedBase = NULL;
1761 BytePtr packedEnd = NULL;
1762 BytePtr outputBase = bufferAddress;
1763 BytePtr outputEnd = outputBase + bufferLength - 1;
1764
1765
1766 if ( pefPrivate == NULL ) goto ParameterError;
1767 if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError;
1768 if ( (bufferAddress == NULL) && (bufferLength != 0) ) goto ParameterError;
1769
1770 section = &pefPrivate->sections[sectionIndex];
1771 if ( (sectionOffset + bufferLength) > section->execSize ) goto ParameterError;
1772
1773 packedBase = pefPrivate->mappedContainer + section->containerOffset;
1774 packedEnd = packedBase + section->rawSize - 1;
1775
1776
1777 if ( (sectionOffset == 0) && (bufferLength == section->initSize) ) {
1778
1779 err = UnpackFullSection ( packedBase, packedEnd, outputBase, outputEnd );
1780 if ( err != noErr ) goto ERROR;
1781
1782 if ( false && EnableCFMDebugging && (section->execSize > 8) ) { // Force some tests of partial unpacking.
1783
1784 UInt32 word;
1785 BytePtr partContents = (*pefPrivate->Allocate) ( section->execSize - 2 );
1786
1787 PEF_Assert ( partContents != NULL );
1788
1789 err = PEF_UnpackSection ( containerRef, sectionIndex, 1, &word, 4 );
1790 PEF_Assert ( err == noErr );
1791
1792 err = PEF_UnpackSection ( containerRef, sectionIndex, section->execSize / 2, &word, 4 );
1793 PEF_Assert ( err == noErr );
1794
1795 err = PEF_UnpackSection ( containerRef, sectionIndex, section->execSize - 5, &word, 4 );
1796 PEF_Assert ( err == noErr );
1797
1798 err = PEF_UnpackSection ( containerRef, sectionIndex, 1, partContents, section->execSize - 2 );
1799 PEF_Assert ( err == noErr );
1800
1801 (*pefPrivate->Release) ( partContents );
1802 }
1803
1804 } else {
1805
1806 if ( section->initSize < sectionOffset ) {
1807 PEF_BlockClear ( bufferAddress, bufferLength );
1808 } else {
1809 err = UnpackPartialSection ( packedBase, packedEnd, outputBase, outputEnd, sectionOffset );
1810 if ( err != noErr ) goto ERROR;
1811 }
1812
1813 if ( EnableCFMDebugging ) { // See if the partial output agrees with full output.
1814
1815 BytePtr fullContents = (*pefPrivate->Allocate) ( section->execSize );
1816
1817 PEF_Assert ( fullContents != NULL );
1818 PEF_BlockClear ( fullContents, section->execSize );
1819
1820 err = UnpackFullSection ( packedBase, packedEnd, fullContents, fullContents + section->initSize - 1 );
1821 PEF_Assert ( err == noErr );
1822
1823 PEF_Assert ( PEF_CompareBytes ( fullContents + sectionOffset, bufferAddress, bufferLength ) );
1824
1825 (*pefPrivate->Release) ( fullContents );
1826
1827 }
1828
1829 }
1830
1831 err = noErr;
1832
1833 EXIT:
1834 return err;
1835
1836 ERROR:
1837 goto EXIT;
1838
1839
1840 ParameterError:
1841 err = paramErr;
1842 goto ERROR;
1843
1844
1845 } // PEF_UnpackSection ()
1846
1847
1848 // ¤
1849 // ===========================================================================================
1850 // PEF_RelocateSection ()
1851 // ======================
1852
1853
1854 // *** This needs cleaning up.
1855
1856
1857 OSStatus PEF_RelocateSection ( CFContHandlerRef containerRef,
1858 ItemCount sectionIndex )
1859 {
1860 OSStatus err = cfragCFMInternalErr;
1861 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
1862
1863 BytePtr * raddr;
1864 ByteCount dataA;
1865 int cnt; // ! Must be signed.
1866 ByteCount codeA;
1867 LoaderRelExpHeader * ldRelHdr;
1868 Relocation *reloc, *rlend;
1869 Relocation r;
1870 long rpt; // ! Must be signed.
1871 long secn;
1872 long rsymi;
1873 BytePtr *imports;
1874 ByteCount *regions;
1875 long i;
1876 long relNum;
1877 BytePtr regStart;
1878 SectionHeader * section;
1879
1880
1881 if ( pefPrivate == NULL ) goto ParameterError;
1882 if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError;
1883
1884 regStart = pefPrivate->mappedOrigins[sectionIndex];
1885 section = & pefPrivate->sections [sectionIndex];
1886
1887 pefPrivate->resolved = 1; // !!! Really means relocated, and should be set on exit.
1888
1889 for (i = 0; ; i++) {
1890 if ( i >= pefPrivate->sectionCount ) return noErr; // No relocations for this section.
1891 ldRelHdr = & pefPrivate->ldrSections [i];
1892 if ( ldRelHdr->sectionNumber == sectionIndex ) break;
1893 }
1894
1895 regions = pefPrivate->runningOffsets;
1896 imports = pefPrivate->imports;
1897
1898 reloc = (Relocation *) (pefPrivate->ldrRelocations + ldRelHdr->relocationsOffset);
1899 rlend = (Relocation *) ((RelocInstr *) reloc + ldRelHdr->numRelocations);
1900 raddr = (BytePtr *) regStart; // ! Change the stride from 1 to 4.
1901 rsymi = 0;
1902 codeA = regions [0];
1903 dataA = regions [1];
1904 rpt = 0;
1905
1906 #if 0
1907 sprintf ( gDebugMessage, "PLPrepareRegion: start @ %.8X\n", raddr );
1908 PutSerialMesssage ( gDebugMessage );
1909 #endif
1910
1911 relNum = 0;
1912 while (reloc < rlend) {
1913
1914 r = *reloc;
1915 reloc = (Relocation *) ((RelocInstr *) reloc + 1);
1916
1917 switch ( opcode [r.opcode.op] ) {
1918 case krDDAT :
1919 raddr = (BytePtr *) ((BytePtr)raddr + (r.deltadata.delta_d4 * 4)); // ! Reduce stride to 1.
1920 cnt = r.deltadata.cnt;
1921 while (--cnt >= 0) {
1922 *raddr++ += dataA;
1923 }
1924 break;
1925
1926 case krCODE :
1927 cnt = r.run.cnt_m1 + 1;
1928 while (--cnt >= 0) {
1929 *raddr++ += codeA;
1930 }
1931 break;
1932
1933 case krDATA :
1934 cnt = r.run.cnt_m1 + 1;
1935 while (--cnt >= 0) {
1936 *raddr++ += dataA;
1937 }
1938 break;
1939
1940 case krDESC :
1941 cnt = r.run.cnt_m1 + 1;
1942 while (--cnt >= 0) {
1943 *raddr++ += codeA;
1944 *raddr++ += dataA;
1945 raddr++;
1946 }
1947 break;
1948
1949 case krDSC2 :
1950 cnt = r.run.cnt_m1 + 1;
1951 while (--cnt >= 0) {
1952 *raddr++ += codeA;
1953 *raddr++ += dataA;
1954 }
1955 break;
1956
1957 case krVTBL :
1958 cnt = r.run.cnt_m1 + 1;
1959 while (--cnt >= 0) {
1960 *raddr++ += dataA;
1961 raddr++;
1962 }
1963 break;
1964
1965 case krSYMR :
1966 cnt = r.run.cnt_m1 + 1;
1967 while (--cnt >= 0) {
1968 *raddr++ += (ByteCount) imports [rsymi++];
1969 }
1970 break;
1971
1972 case krSYMB :
1973 rsymi = r.glp.idx;
1974 *raddr++ += (ByteCount) imports [rsymi++];
1975 break;
1976
1977 case krCDIS :
1978 codeA = regions [r.glp.idx];
1979 break;
1980
1981 case krDTIS :
1982 dataA = regions [r.glp.idx];
1983 break;
1984
1985 case krSECN :
1986 *raddr++ += regions [r.glp.idx];
1987 break;
1988
1989 case krDELT :
1990 raddr = (BytePtr *) ((BytePtr) raddr + r.delta.delta_m1 + 1); // ! Reduce stride to 1.
1991 #if 0
1992 sprintf ( gDebugMessage, "PLPrepareRegion: delta to %.8X\n", raddr );
1993 PutSerialMesssage ( gDebugMessage );
1994 #endif
1995 break;
1996
1997 case krRPT :
1998 if (--rpt == 0) break; // count was 1 --> rpt done
1999 if (rpt < 0) // first time rpt encountered?
2000 rpt = r.rpt.rcnt_m1 + 1; // yes- initialize rpt count
2001 cnt = r.rpt.icnt_m1 + 2; // yes or no - back up cnt instrs
2002 reloc = (Relocation *) ((RelocInstr *) reloc - cnt);
2003 break;
2004
2005 case krLABS :
2006 raddr = (BytePtr *) ((r.large1.idx_top << 16) + reloc->bot + regStart);
2007 reloc = (Relocation *) ((RelocInstr *) reloc + 1);
2008 #if 0
2009 sprintf ( gDebugMessage, "PLPrepareRegion: abs to %.8X\n", raddr );
2010 PutSerialMesssage ( gDebugMessage );
2011 #endif
2012 break;
2013
2014 case krLSYM :
2015 rsymi = (r.large1.idx_top << 16) + reloc->bot;
2016 reloc = (Relocation *) ((RelocInstr *) reloc + 1);
2017 *raddr++ += (ByteCount) imports [rsymi++];
2018 break;
2019
2020 case krLRPT :
2021 if (--rpt == 0) {
2022 reloc = (Relocation *) ((RelocInstr *) reloc + 1);
2023 break;
2024 }
2025 if (rpt < 0)
2026 rpt = (r.large2.idx_top << 16) + reloc->bot;
2027 cnt = r.large2.cnt_m1 + 2;
2028 reloc = (Relocation *) ((RelocInstr *) reloc - cnt);
2029 break;
2030
2031 case krLSEC :
2032 secn = (r.large2.idx_top << 16) + reloc->bot;
2033 switch (r.large2.cnt_m1) {
2034 case 0 : *raddr++ += regions [secn]; break;
2035 case 1 : codeA = regions [secn]; break;
2036 case 2 : dataA = regions [secn]; break;
2037 }
2038 reloc = (Relocation *) ((RelocInstr *) reloc + 1);
2039 break;
2040
2041 default :
2042 goto FragmentCorruptError;
2043 }
2044 }
2045
2046
2047 #if 0
2048 sprintf ( gDebugMessage, "PLPrepareRegion: end @ %.8X\n", raddr );
2049 PutSerialMesssage ( gDebugMessage );
2050 #endif
2051
2052 err = noErr;
2053
2054 EXIT:
2055 return err;
2056
2057 ERROR:
2058 goto EXIT;
2059
2060 ParameterError:
2061 err = paramErr;
2062 goto ERROR;
2063
2064 FragmentCorruptError:
2065 err = cfragFragmentCorruptErr;
2066 goto ERROR;
2067
2068
2069 } // PEF_RelocateSection ()
2070
2071
2072 // ¤
2073 // ===========================================================================================
2074 // PEF_RelocateImportsOnly ()
2075 // ==========================
2076
2077
2078 OSStatus PEF_RelocateImportsOnly ( CFContHandlerRef containerRef,
2079 ItemCount sectionIndex,
2080 ItemCount libraryIndex )
2081 {
2082 OSStatus err = cfragCFMInternalErr;
2083 PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef;
2084
2085
2086 if ( pefPrivate == NULL ) goto ParameterError;
2087 if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError;
2088 if ( libraryIndex >= pefPrivate->ldrHeader->numImportFiles ) goto ParameterError;
2089
2090
2091 if ( pefPrivate == NULL ) goto ParameterError;
2092
2093
2094 return unimpErr; // !!! Fix this!
2095
2096 EXIT:
2097 return err;
2098
2099 ERROR:
2100 goto EXIT;
2101
2102 ParameterError:
2103 err = paramErr;
2104 goto ERROR;
2105
2106
2107 } // PEF_RelocateImportsOnly ()
2108