2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1997 Apple Computer, Inc.
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 21 July 98 - start IOKit
37 Contains: PEF loader implementation.
41 Copyright: © 1994-1996 by Apple Computer, Inc., all rights reserved.
47 Other Contact: <<unknown>>
49 Technology: Core Runtime
56 Change History (most recent first):
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
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.
93 ------------------------------------------------------------------------------------
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
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
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
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.
122 #include "IOPEFInternals.h"
124 // ===========================================================================================
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
,
132 #define PEF_CompareBytes(a,b,c) PCFM_CompareBytes(a,b,c)
134 #define EnableCFMDebugging 0
136 // ===========================================================================================
140 kPEFHandlerProcCount
= 18
143 static CFContHandlerProcs PEFHandlerProcs
= {
144 kPEFHandlerProcCount
,
145 kCFContHandlerABIVersion
,
147 PEF_OpenContainer
, // 1
148 PEF_CloseContainer
, // 2
149 PEF_GetContainerInfo
, // 3
151 PEF_GetSectionCount
, // 4
152 PEF_GetSectionInfo
, // 5
153 PEF_FindSectionInfo
, // 6
154 PEF_SetSectionAddress
, // 7
156 PEF_GetAnonymousSymbolLocations
, // 8
158 PEF_GetExportedSymbolCount
, // 9
159 PEF_GetExportedSymbolInfo
, // 10
160 PEF_FindExportedSymbolInfo
, // 11
162 PEF_GetImportCounts
, // 12
163 PEF_GetImportedLibraryInfo
, // 13
164 PEF_GetImportedSymbolInfo
, // 14
165 PEF_SetImportedSymbolAddress
, // 15
167 PEF_UnpackSection
, // 16
168 PEF_RelocateSection
, // 17
169 PEF_RelocateImportsOnly
, // 18
173 #if EnableCFMDebugging
174 static char gDebugMessage
[256];
177 // ===========================================================================================
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
,
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
,
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
,
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
,
202 // ===========================================================================================
207 static ByteCount
GetNameLength ( BytePtr nameStart
)
209 BytePtr nameEnd
= nameStart
;
212 if ( nameStart
!= NULL
) {
213 while ( *nameEnd
!= 0 ) nameEnd
+= 1;
216 return (nameEnd
- nameStart
);
219 } // GetNameLength ()
223 // ===========================================================================================
224 // FindRelocationInfo ()
225 // =====================
228 static LoaderRelExpHeader
* FindRelocationInfo ( PEFPrivateInfo
* pefPrivate
,
229 ItemCount sectionIndex
)
231 LoaderRelExpHeader
* relocInfo
= NULL
;
232 const ItemCount loopLimit
= pefPrivate
->ldrHeader
->numSections
;
233 ItemCount relocIndex
;
236 for ( relocIndex
= 0; relocIndex
< loopLimit
; relocIndex
+= 1 ) {
237 relocInfo
= &pefPrivate
->ldrSections
[relocIndex
];
238 if ( sectionIndex
== relocInfo
->sectionNumber
) return relocInfo
;
243 } // FindRelocationInfo ()
247 // ===========================================================================================
252 static void GetSectionName ( PEFPrivateInfo
* pefPrivate
,
253 SectionHeader
* sectionHeader
,
254 CFContHashedName
* sectionName
)
256 CFContStringHash nameHash
= 0;
257 BytePtr nameText
= NULL
;
258 ByteCount nameLength
;
261 if ( sectionHeader
->sectionName
!= -1 ) {
262 nameText
= pefPrivate
->stringTable
+ sectionHeader
->sectionName
;
263 nameLength
= GetNameLength ( nameText
);
264 nameHash
= CFContHashName ( nameText
, nameLength
);
267 sectionName
->nameHash
= nameHash
;
268 sectionName
->nameText
= nameText
;
271 } // GetSectionName ()
275 // ===========================================================================================
276 // PEF_OpenContainer ()
277 // ====================
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
)
291 #pragma unused ( containerLength )
292 #pragma unused ( runningProcessID )
293 #pragma unused ( cfragName )
295 OSStatus err
= -1;//cfragCFMInternalErr;
296 FileHeader
* fileHeader
= (FileHeader
*) mappedAddress
;
297 PEFPrivateInfo
* pefPrivate
= NULL
;
298 SectionHeader
* loaderSection
= NULL
;
302 if ( (sizeof ( PEF_SBits32
) != 4) | (sizeof ( PEF_UBits32
) != 4) ) goto InternalError
; // ! Is "int" 32 bits?
304 if ( (Allocate
== NULL
) ||
306 (containerRef
== NULL
) ||
307 (handlerProcs
== NULL
) ) goto ParameterError
;
309 *containerRef
= NULL
; // Clear for errors, only set on OK path.
310 *handlerProcs
= NULL
;
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.
317 if ( mappedAddress
== NULL
) goto OK
;
319 if ( (fileHeader
->magic1
!= kPEFMagic1
) ||
320 (fileHeader
->magic2
!= kPEFMagic2
) ||
321 (fileHeader
->fileTypeID
!= kPEFTypeID
) ||
322 (fileHeader
->versionNumber
!= kPEFVersion
) ) goto FragmentFormatError
;
325 // -----------------------------------------------
326 // Allocate and initialize the private info block.
328 pefPrivate
= (PEFPrivateInfo
*) ((*Allocate
) ( sizeof ( PEFPrivateInfo
) ));
329 if ( pefPrivate
== NULL
) goto PrivateMemoryError
;
331 PEF_BlockClear ( pefPrivate
, sizeof ( *pefPrivate
) );
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);
342 // -----------------------------------------------------
343 // Find the loader section and extract important fields.
345 for ( sectionIndex
= 0; sectionIndex
< fileHeader
->numberSections
; sectionIndex
+= 1 ) {
346 loaderSection
= & pefPrivate
->sections
[sectionIndex
];
347 if ( loaderSection
->regionKind
== kPEFLoaderSection
) break;
349 if ( sectionIndex
== fileHeader
->numberSections
) goto FragmentCorruptError
;
351 pefPrivate
->ldrSectionNo
= sectionIndex
;
352 pefPrivate
->ldrHeader
= (LoaderHeader
*) ((BytePtr
)mappedAddress
+ loaderSection
->containerOffset
);
353 pefPrivate
->ldrStringTable
= (BytePtr
)pefPrivate
->ldrHeader
+ pefPrivate
->ldrHeader
->stringsOffset
;
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
;
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
);
364 // ----------------------------------------------------
365 // Set up the array to store resolved import addresses.
367 if ( pefPrivate
->ldrHeader
->numImportSyms
> 0 ) {
368 pefPrivate
->imports
= (BytePtr
*) ((*Allocate
) ( pefPrivate
->ldrHeader
->numImportSyms
* sizeof ( BytePtr
) ));
369 if ( pefPrivate
->imports
== NULL
) goto PrivateMemoryError
;
372 // -----------------------------------------------------------------
373 // Set up the pointers to the arrays of section origins and offsets.
375 if (pefPrivate
->sectionCount
<= kBuiltinSectionArraySize
) {
376 pefPrivate
->mappedOrigins
= & pefPrivate
->originArray
[0];
377 pefPrivate
->runningOffsets
= & pefPrivate
->offsetArray
[0];
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
;
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.
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.
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.
400 for ( sectionIndex
= 0; sectionIndex
< pefPrivate
->sectionCount
; sectionIndex
+= 1 ) {
402 SectionHeader
* section
= & pefPrivate
->sections
[sectionIndex
];
404 pefPrivate
->mappedOrigins
[sectionIndex
] = (BytePtr
) -1; // ! Just a diagnostic tag.
405 pefPrivate
->runningOffsets
[sectionIndex
] = - ((ByteCount
) section
->sectionAddress
); // Subtract the presumed address.
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.
416 if ( options
& kCFContPrepareInPlaceMask
) fileHeader
->memoryAddress
= runningAddress
;
421 *handlerProcs
= &PEFHandlerProcs
;
422 *containerRef
= (CFContHandlerRef
) pefPrivate
;
428 (void) PEF_CloseContainer ( (CFContHandlerRef
) pefPrivate
, kNilOptions
);
432 err
= cfragCFMInternalErr
;
440 err
= cfragFragmentFormatErr
;
444 err
= cfragNoPrivateMemErr
;
447 FragmentCorruptError
:
448 err
= cfragFragmentCorruptErr
;
452 err
= cfragFragmentUsageErr
;
456 } // PEF_OpenContainer ()
460 // ===========================================================================================
461 // PEF_CloseContainer ()
462 // =====================
465 OSStatus
PEF_CloseContainer ( CFContHandlerRef containerRef
,
466 CFContCloseOptions options
)
468 OSStatus err
= cfragCFMInternalErr
;
469 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
470 CFContReleaseMem Release
= NULL
;
473 if ( pefPrivate
== NULL
) goto OK
; // Simplifies error cleanup from PEF_OpenContainer.
476 Release
= pefPrivate
->Release
;
478 if ( pefPrivate
->sectionCount
> kBuiltinSectionArraySize
) {
479 if ( pefPrivate
->mappedOrigins
!= NULL
) {
480 (*Release
) ( pefPrivate
->mappedOrigins
);
481 pefPrivate
->mappedOrigins
= NULL
;
483 if ( pefPrivate
->runningOffsets
!= NULL
) {
484 (*Release
) ( pefPrivate
->runningOffsets
);
485 pefPrivate
->runningOffsets
= NULL
;
489 if ( pefPrivate
->imports
!= NULL
) {
490 (*Release
) ( pefPrivate
->imports
);
491 pefPrivate
->imports
= NULL
;
494 pefPrivate
->resolved
= 0; // ! Disables reexported import optimization.
496 if ( ! (options
& kCFContPartialCloseMask
) ) (*Release
) ( pefPrivate
);
503 } // PEF_CloseContainer ()
507 // ===========================================================================================
508 // PEF_GetContainerInfo ()
509 // =======================
512 OSStatus
PEF_GetContainerInfo ( CFContHandlerRef containerRef
,
513 PBVersion infoVersion
,
514 CFContContainerInfo
* containerInfo
)
516 OSStatus err
= cfragCFMInternalErr
;
517 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
518 FileHeader
* fileHeader
= NULL
;
521 if ( (pefPrivate
== NULL
) || (containerInfo
== NULL
) ) goto ParameterError
;
522 if ( infoVersion
!= kCFContContainerInfoVersion
) goto ParameterError
;
525 fileHeader
= (FileHeader
*) pefPrivate
->mappedContainer
;
527 containerInfo
->cfragName
.nameHash
= 0; // PEF does not have an embedded name.
528 containerInfo
->cfragName
.nameText
= NULL
;
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
;
549 } // PEF_GetContainerInfo ()
553 // ===========================================================================================
554 // PEF_GetSectionCount ()
555 // ======================
558 OSStatus
PEF_GetSectionCount ( CFContHandlerRef containerRef
,
559 ItemCount
* sectionCount
)
561 OSStatus err
= cfragCFMInternalErr
;
562 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
565 if ( (pefPrivate
== NULL
) || (sectionCount
== NULL
) ) goto ParameterError
;
567 *sectionCount
= pefPrivate
->sectionCount
;
582 } // PEF_GetSectionCount ()
586 // ===========================================================================================
587 // PEF_GetSectionInfo ()
588 // =====================
591 OSStatus
PEF_GetSectionInfo ( CFContHandlerRef containerRef
,
592 ItemCount sectionIndex
,
593 PBVersion infoVersion
,
594 CFContSectionInfo
* sectionInfo
)
596 OSStatus err
= cfragCFMInternalErr
;
597 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
598 SectionHeader
* sectionHeader
= NULL
;
601 if ( (pefPrivate
== NULL
) || (sectionInfo
== NULL
) ) goto ParameterError
;
602 if ( infoVersion
!= kCFContSectionInfoVersion
) goto ParameterError
;
603 if ( sectionIndex
>= pefPrivate
->sectionCount
) goto ParameterError
;
606 sectionHeader
= &pefPrivate
->sections
[sectionIndex
];
608 GetSectionName ( pefPrivate
, sectionHeader
, §ionInfo
->sectionName
);
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
;
619 sectionInfo
->options
= kNilOptions
;
620 if ( FindRelocationInfo ( pefPrivate
, sectionIndex
) != NULL
) sectionInfo
->options
|= kRelocatedCFContSectionMask
;
622 switch ( pefPrivate
->sections
[sectionIndex
].regionKind
) {
623 case kPEFCodeSection
:
624 sectionInfo
->access
= kCFContNormalCode
;
626 case kPEFDataSection
:
627 sectionInfo
->access
= kCFContWriteableData
;
629 case kPEFPIDataSection
:
630 sectionInfo
->access
= kCFContWriteableData
;
631 sectionInfo
->options
|= kPackedCFContSectionMask
;
633 case kPEFConstantSection
:
634 sectionInfo
->access
= kCFContReadOnlyData
;
636 case kPEFExecDataSection
:
637 sectionInfo
->access
= kCFContWriteableData
| kCFContMemExecuteMask
;
640 sectionInfo
->access
= kCFContReadOnlyData
; // ! Not necessarily right, but safe.
657 } // PEF_GetSectionInfo ()
661 // ===========================================================================================
662 // PEF_FindSectionInfo ()
663 // ======================
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.
672 OSStatus err
= cfragCFMInternalErr
;
673 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
674 SectionHeader
* sectionHeader
= NULL
;
675 CFContHashedName hashedName
;
678 CFContSectionInfo tempInfo
;
681 if ( pefPrivate
== NULL
) goto ParameterError
;
682 if ( (sectionInfo
!= NULL
) && (infoVersion
!= kCFContSectionInfoVersion
) ) goto ParameterError
;
684 if ( sectionIndex
== NULL
) sectionIndex
= &tempIndex
;
685 if ( sectionInfo
== NULL
) sectionInfo
= &tempInfo
;
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;
694 if ( tempIndex
== pefPrivate
->sectionCount
) goto NoSectionError
;
695 *sectionIndex
= tempIndex
;
697 err
= PEF_GetSectionInfo ( containerRef
, tempIndex
, infoVersion
, sectionInfo
);
698 if ( err
!= noErr
) goto ERROR
;
713 err
= cfragNoSectionErr
;
717 } // PEF_FindSectionInfo ()
721 // ===========================================================================================
722 // PEF_SetSectionAddress ()
723 // ========================
726 OSStatus
PEF_SetSectionAddress ( CFContHandlerRef containerRef
,
727 ItemCount sectionIndex
,
728 LogicalAddress mappedAddress
,
729 LogicalAddress runningAddress
)
731 OSErr err
= cfragCFMInternalErr
;
732 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
733 SectionHeader
* section
= NULL
;
736 if ( (pefPrivate
== NULL
) || (sectionIndex
>= pefPrivate
->sectionCount
) ) goto ParameterError
;
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.
743 section
= & pefPrivate
->sections
[sectionIndex
];
745 if ( ! pefPrivate
->loadInPlace
) {
747 pefPrivate
->mappedOrigins
[sectionIndex
] = (BytePtr
) mappedAddress
;
748 pefPrivate
->runningOffsets
[sectionIndex
] += (ByteCount
) runningAddress
;
752 if ( (runningAddress
!= section
->sectionAddress
) ||
753 (mappedAddress
!= pefPrivate
->mappedOrigins
[sectionIndex
]) ) goto UsageError
;
770 err
= cfragFragmentUsageErr
;
774 } // PEF_SetSectionAddress ()
778 // ===========================================================================================
779 // PEF_GetAnonymousSymbolLocations ()
780 // ==================================
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.
788 OSStatus err
= cfragCFMInternalErr
;
789 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
790 LoaderHeader
* ldrHeader
= NULL
;
792 CFContLogicalLocation tempLocation
;
795 if ( (pefPrivate
== NULL
) ) goto ParameterError
;
797 if ( mainLocation
== NULL
) mainLocation
= &tempLocation
;
798 if ( initLocation
== NULL
) initLocation
= &tempLocation
;
799 if ( termLocation
== NULL
) termLocation
= &tempLocation
;
802 ldrHeader
= pefPrivate
->ldrHeader
;
804 mainLocation
->section
= ldrHeader
->entryPointSection
;
805 mainLocation
->offset
= ldrHeader
->entryPointOffset
;
807 initLocation
->section
= ldrHeader
->initPointSection
;
808 initLocation
->offset
= ldrHeader
->initPointOffset
;
810 termLocation
->section
= ldrHeader
->termPointSection
;
811 termLocation
->offset
= ldrHeader
->termPointOffset
;
826 } // PEF_GetAnonymousSymbolLocations ()
830 // ===========================================================================================
831 // PEF_GetExportedSymbolCount ()
832 // =============================
835 extern OSStatus
PEF_GetExportedSymbolCount ( CFContHandlerRef containerRef
,
836 ItemCount
* exportCount
)
838 OSStatus err
= cfragCFMInternalErr
;
839 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
842 if ( (pefPrivate
== NULL
) || (exportCount
== NULL
) ) goto ParameterError
;
844 *exportCount
= pefPrivate
->ldrHeader
->numExportSyms
;
859 } // PEF_GetExportedSymbolCount ()
863 // ===========================================================================================
864 // PEF_GetExportedSymbolInfo ()
865 // ============================
868 OSStatus
PEF_GetExportedSymbolInfo ( CFContHandlerRef containerRef
,
869 CFContSignedIndex exportIndex
,
870 PBVersion infoVersion
,
871 CFContExportedSymbolInfo
* exportInfo
)
873 OSStatus err
= cfragCFMInternalErr
;
874 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
875 LoaderExport
* exportedSymbol
= NULL
;
878 if ( (pefPrivate
== NULL
) || (exportInfo
== NULL
) ) goto ParameterError
;
879 if ( exportIndex
>= pefPrivate
->ldrHeader
->numExportSyms
) goto ParameterError
;
880 if ( infoVersion
!= kCFContExportedSymbolInfoVersion
) goto ParameterError
;
883 if ( exportIndex
>= 0 ) {
885 exportedSymbol
= &pefPrivate
->ldrExportSymbols
[exportIndex
];
887 exportInfo
->symbolName
.nameHash
= pefPrivate
->ldrHashChain
[exportIndex
].hashword
;
888 exportInfo
->symbolName
.nameText
= &pefPrivate
->ldrStringTable
[exportedSymbol
->nameOffset
];
890 exportInfo
->symbolClass
= exportedSymbol
->symClass
;
891 exportInfo
->reservedA
= 0;
892 exportInfo
->reservedB
= 0;
893 exportInfo
->options
= kNilOptions
;
895 exportInfo
->location
.section
= exportedSymbol
->sectionNumber
;
897 #if 1 // *** Disable the reexported import optimization.
898 exportInfo
->location
.offset
= exportedSymbol
->offset
;
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
;
906 exportInfo
->location
.section
= kPhysicalExport
;
907 exportInfo
->location
.offset
= pefPrivate
->imports
[exportedSymbol
->address
];
913 CFContLogicalLocation mainLocation
;
914 CFContLogicalLocation initLocation
;
915 CFContLogicalLocation termLocation
;
917 err
= PEF_GetAnonymousSymbolLocations ( containerRef
, &mainLocation
, &initLocation
, &termLocation
);
918 if ( err
!= noErr
) goto ERROR
;
920 switch ( exportIndex
) {
921 case kMainCFragSymbolIndex
:
922 exportInfo
->location
= mainLocation
;
923 exportInfo
->symbolClass
= 0xFF; // !!! Ought to have a kUnknownCFragSymbol constant.
925 case kInitCFragSymbolIndex
:
926 exportInfo
->location
= initLocation
;
927 exportInfo
->symbolClass
= kTVectorCFragSymbol
; // ! Very well better be!
929 case kTermCFragSymbolIndex
:
930 exportInfo
->location
= termLocation
;
931 exportInfo
->symbolClass
= kTVectorCFragSymbol
; // ! Very well better be!
937 exportInfo
->symbolName
.nameHash
= 0;
938 exportInfo
->symbolName
.nameText
= NULL
;
940 exportInfo
->reservedA
= 0;
941 exportInfo
->reservedB
= 0;
942 exportInfo
->options
= kNilOptions
;
959 } // PEF_GetExportedSymbolInfo ()
963 // ===========================================================================================
964 // PEF_FindExportedSymbolInfo ()
965 // =============================
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.
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
;
983 ItemCount chainLimit
;
987 if ( pefPrivate
== NULL
) goto ParameterError
;
988 if ( infoVersion
!= kCFContExportedSymbolInfoVersion
) goto ParameterError
;
991 hashwordList
= &pefPrivate
->ldrHashChain
[0].hashword
;
993 slotIndex
= GetPEFHashSlot ( exportName
->nameHash
, pefPrivate
->ldrHeader
->hashSlotTabSize
);
994 hashSlot
= &pefPrivate
->ldrHashSlot
[slotIndex
];
996 exportIndex
= hashSlot
->chainIndex
;
997 chainLimit
= exportIndex
+ hashSlot
->chainCount
;
998 nextHashword
= &hashwordList
[exportIndex
];
1000 while ( exportIndex
< chainLimit
) {
1002 if ( *nextHashword
== exportName
->nameHash
) {
1003 exportedSymbol
= &pefPrivate
->ldrExportSymbols
[exportIndex
];
1004 nameMatch
= PEF_CompareBytes ( exportName
->nameText
,
1005 &pefPrivate
->ldrStringTable
[exportedSymbol
->nameOffset
],
1007 if ( nameMatch
) goto Found
;
1011 nextHashword
+= 1; // ! Pointer arithmetic.
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
;
1035 err
= cfragNoSymbolErr
;
1039 } // PEF_FindExportedSymbolInfo ()
1043 // ===========================================================================================
1044 // PEF_GetImportCounts ()
1045 // ======================
1048 OSStatus
PEF_GetImportCounts ( CFContHandlerRef containerRef
,
1049 ItemCount
* libraryCount
, // May be null.
1050 ItemCount
* symbolCount
) // May be null.
1052 OSStatus err
= cfragCFMInternalErr
;
1053 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
1056 if ( pefPrivate
== NULL
) goto ParameterError
;
1058 if ( libraryCount
!= NULL
) *libraryCount
= pefPrivate
->ldrHeader
->numImportFiles
;
1059 if ( symbolCount
!= NULL
) *symbolCount
= pefPrivate
->ldrHeader
->numImportSyms
;
1074 } // PEF_GetImportCounts ()
1078 // ===========================================================================================
1079 // PEF_GetImportedLibraryInfo ()
1080 // =============================
1083 OSStatus
PEF_GetImportedLibraryInfo ( CFContHandlerRef containerRef
,
1084 ItemCount libraryIndex
,
1085 PBVersion infoVersion
,
1086 CFContImportedLibraryInfo
* libraryInfo
)
1088 OSStatus err
= cfragCFMInternalErr
;
1089 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
1090 LoaderImportFileID
* importedLibrary
= NULL
;
1091 BytePtr nameText
= NULL
;
1092 ByteCount nameLength
;
1095 if ( (pefPrivate
== NULL
) || (libraryInfo
== NULL
) ) goto ParameterError
;
1096 if ( infoVersion
!= kCFContImportedLibraryInfoVersion
) goto ParameterError
;
1097 if ( libraryIndex
>= pefPrivate
->ldrHeader
->numImportFiles
) goto ParameterError
;
1100 importedLibrary
= &pefPrivate
->ldrImportFiles
[libraryIndex
];
1102 nameText
= &pefPrivate
->ldrStringTable
[importedLibrary
->fileNameOffset
];
1103 nameLength
= GetNameLength ( nameText
);
1105 libraryInfo
->libraryName
.nameHash
= CFContHashName ( nameText
, nameLength
);
1106 libraryInfo
->libraryName
.nameText
= nameText
;
1108 libraryInfo
->linkedVersion
= importedLibrary
->linkedVersion
;
1109 libraryInfo
->oldImpVersion
= importedLibrary
->oldImpVersion
;
1110 libraryInfo
->options
= kNilOptions
;
1112 if ( importedLibrary
->options
& kPEFInitBeforeMask
) libraryInfo
->options
|= kCFContInitBeforeMask
;
1113 if ( importedLibrary
->options
& kPEFWeakLibraryMask
) libraryInfo
->options
|= kCFContWeakLibraryMask
;
1114 if ( importedLibrary
->options
& kPEFDeferredBindMask
) libraryInfo
->options
|= kCFContDeferredBindMask
;
1129 } // PEF_GetImportedLibraryInfo ()
1133 // ===========================================================================================
1134 // PEF_GetImportedSymbolInfo ()
1135 // ============================
1138 OSStatus
PEF_GetImportedSymbolInfo ( CFContHandlerRef containerRef
,
1139 ItemCount symbolIndex
,
1140 PBVersion infoVersion
,
1141 CFContImportedSymbolInfo
* symbolInfo
)
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
;
1153 if ( (pefPrivate
== NULL
) || (symbolInfo
== NULL
) ) goto ParameterError
;
1154 if ( infoVersion
!= kCFContImportedSymbolInfoVersion
) goto ParameterError
;
1155 if ( symbolIndex
>= pefPrivate
->ldrHeader
->numImportSyms
) goto ParameterError
;
1158 importedSymbol
= &pefPrivate
->ldrImportSymbols
[symbolIndex
];
1159 libraryCount
= pefPrivate
->ldrHeader
->numImportFiles
;
1161 nameText
= &pefPrivate
->ldrStringTable
[importedSymbol
->nameOffset
];
1162 nameLength
= GetNameLength ( nameText
);
1164 symbolInfo
->symbolName
.nameHash
= CFContHashName ( nameText
, nameLength
);
1165 symbolInfo
->symbolName
.nameText
= nameText
;
1167 symbolInfo
->symbolClass
= importedSymbol
->symClass
& 0x0F;
1168 symbolInfo
->reservedA
= 0;
1169 symbolInfo
->reservedB
= 0;
1170 symbolInfo
->options
= 0;
1172 if ( importedSymbol
->symClass
& kPEFWeakSymbolMask
) symbolInfo
->options
|= kCFContWeakSymbolMask
;
1174 for ( libraryIndex
= 0; libraryIndex
< libraryCount
; libraryIndex
+= 1 ) {
1175 importedLibrary
= &pefPrivate
->ldrImportFiles
[libraryIndex
];
1176 if ( (importedLibrary
->impFirst
<= symbolIndex
) &&
1177 (symbolIndex
< (importedLibrary
->impFirst
+ importedLibrary
->numImports
)) ) {
1181 if ( libraryIndex
== libraryCount
) goto FragmentCorruptError
;
1183 symbolInfo
->libraryIndex
= libraryIndex
;
1197 FragmentCorruptError
:
1198 err
= cfragFragmentCorruptErr
;
1202 } // PEF_GetImportedSymbolInfo ()
1206 // ===========================================================================================
1207 // PEF_SetImportedSymbolAddress ()
1208 // ===============================
1211 OSStatus
PEF_SetImportedSymbolAddress ( CFContHandlerRef containerRef
,
1212 ItemCount symbolIndex
,
1213 LogicalAddress symbolAddress
)
1215 OSStatus err
= cfragCFMInternalErr
;
1216 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
1219 if ( pefPrivate
== NULL
) goto ParameterError
;
1220 if ( symbolIndex
>= pefPrivate
->ldrHeader
->numImportSyms
) goto ParameterError
;
1223 pefPrivate
->imports
[symbolIndex
] = symbolAddress
;
1238 } // PEF_SetImportedSymbolAddress ()
1242 // ===========================================================================================
1243 // GetPackedDataCount ()
1244 // =====================
1247 static UInt32
GetPackedDataCount ( UInt8
* * byteHandle
)
1250 UInt8
* bytePtr
= *byteHandle
;
1255 currByte
= *bytePtr
++;
1256 count
= (count
<< kPEFPkDataVCountShift
) | (currByte
& kPEFPkDataVCountMask
);
1257 } while ( (currByte
& kPEFPkDataVCountEndMask
) != 0 );
1259 *byteHandle
= bytePtr
;
1264 } // GetPackedDataCount ()
1268 // ===========================================================================================
1269 // UnpackFullSection ()
1270 // ====================
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
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.
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".
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.
1290 static OSStatus
UnpackFullSection ( BytePtr packedBase
,
1295 OSStatus err
= cfragCFMInternalErr
;
1296 BytePtr packedPos
= packedBase
;
1297 BytePtr outputPos
= outputBase
;
1298 BytePtr outPosLimit
= outputEnd
+ 1; // ! Might be zero if outputEnd is 0xFFFFFFFF.
1307 if ( (packedEnd
+ 1) == 0 ) goto FragmentUsageError
;
1310 while ( packedPos
<= packedEnd
) {
1313 currByte
= *packedPos
++;
1314 opcode
= currByte
>> kPEFPkDataOpcodeShift
;
1315 count1
= currByte
& kPEFPkDataCount5Mask
;
1317 if ( count1
== 0 ) count1
= GetPackedDataCount ( &packedPos
);
1323 case kPEFPkDataZero
:
1325 if ( (outPosLimit
- outputPos
) < count1
) goto FragmentCorruptError
;
1327 PEF_BlockClear ( outputPos
, count1
);
1328 outputPos
+= count1
;
1333 case kPEFPkDataBlock
:
1335 if ( (outPosLimit
- outputPos
) < count1
) goto FragmentCorruptError
;
1337 PEF_BlockMove ( packedPos
, outputPos
, count1
);
1338 packedPos
+= count1
;
1339 outputPos
+= count1
;
1344 case kPEFPkDataRepeat
: // ??? Need a BlockFill routine?
1346 count2
= GetPackedDataCount ( &packedPos
) + 1; // ! Stored count is 1 less.
1348 if ( (outPosLimit
- outputPos
) < (count1
* count2
) ) goto FragmentCorruptError
;
1350 if ( count1
== 1 ) { // ??? Is this worth the bother? Other sizes?
1352 currByte
= *packedPos
++;
1353 for ( ; count2
!= 0; count2
-= 1 ) *outputPos
++ = currByte
;
1357 for ( ; count2
!= 0; count2
-= 1 ) {
1358 PEF_BlockMove ( packedPos
, outputPos
, count1
);
1359 outputPos
+= count1
;
1361 packedPos
+= count1
;
1368 case kPEFPkDataRepeatBlock
:
1370 count2
= GetPackedDataCount ( &packedPos
);
1371 count3
= GetPackedDataCount ( &packedPos
);
1373 if ( (outPosLimit
- outputPos
) < (((count1
+ count2
) * count3
) + count1
) ) goto FragmentCorruptError
;
1376 BytePtr commonPos
= packedPos
;
1378 packedPos
+= count1
; // Skip the common part.
1380 for ( ; count3
!= 0; count3
-= 1 ) {
1382 PEF_BlockMove ( commonPos
, outputPos
, count1
);
1383 outputPos
+= count1
;
1385 PEF_BlockMove ( packedPos
, outputPos
, count2
);
1386 packedPos
+= count2
;
1387 outputPos
+= count2
;
1391 PEF_BlockMove ( commonPos
, outputPos
, count1
);
1392 outputPos
+= count1
;
1399 case kPEFPkDataRepeatZero
:
1401 count2
= GetPackedDataCount ( &packedPos
);
1402 count3
= GetPackedDataCount ( &packedPos
);
1404 if ( (outPosLimit
- outputPos
) < (((count1
+ count2
) * count3
) + count1
) ) goto FragmentCorruptError
;
1406 PEF_BlockClear ( outputPos
, count1
);
1407 outputPos
+= count1
;
1409 for ( ; count3
!= 0; count3
-= 1 ) {
1411 PEF_BlockMove ( packedPos
, outputPos
, count2
);
1412 packedPos
+= count2
;
1413 outputPos
+= count2
;
1415 PEF_BlockClear ( outputPos
, count1
);
1416 outputPos
+= count1
;
1424 goto FragmentCorruptError
;
1431 if ( (packedPos
!= (packedEnd
+ 1)) || (outputPos
!= outPosLimit
) ) goto FragmentCorruptError
;
1443 err
= cfragFragmentUsageErr
;
1446 FragmentCorruptError
:
1447 err
= cfragFragmentCorruptErr
;
1451 } // UnpackFullSection ()
1455 // ===========================================================================================
1456 // UnpackPartialSection ()
1457 // =======================
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.
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!
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.
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".
1481 // -------------------------------------------------------------------------------------------
1484 static void PartialBlockClear ( BytePtr outputBase
,
1485 ByteCount outputStartOffset
,
1486 ByteCount outputEndOffset
,
1487 ByteCount outputOffset
,
1491 if ( ((outputOffset
+ count
) <= outputStartOffset
) || (outputOffset
> outputEndOffset
) ) return; // Nothing to output.
1493 if ( outputOffset
< outputStartOffset
) {
1494 count
-= (outputStartOffset
- outputOffset
);
1495 outputOffset
= outputStartOffset
;
1498 if ( count
> (outputEndOffset
- outputOffset
+ 1) ) count
= outputEndOffset
- outputOffset
+ 1;
1500 PEF_BlockClear ( outputBase
+ (outputOffset
- outputStartOffset
), count
);
1502 } // PartialBlockClear ();
1505 // -------------------------------------------------------------------------------------------
1508 static void PartialBlockMove ( BytePtr source
,
1510 ByteCount outputStartOffset
,
1511 ByteCount outputEndOffset
,
1512 ByteCount outputOffset
,
1516 if ( ((outputOffset
+ count
) <= outputStartOffset
) || (outputOffset
> outputEndOffset
) ) return; // Nothing to output.
1518 if ( outputOffset
< outputStartOffset
) {
1519 const ByteCount skipCount
= outputStartOffset
- outputOffset
;
1520 source
+= skipCount
;
1522 outputOffset
= outputStartOffset
;
1525 if ( count
> (outputEndOffset
- outputOffset
+ 1) ) count
= outputEndOffset
- outputOffset
+ 1;
1527 PEF_BlockMove ( source
, outputBase
+ (outputOffset
- outputStartOffset
), count
);
1529 } // PartialBlockClear ();
1532 // -------------------------------------------------------------------------------------------
1535 static OSStatus
UnpackPartialSection ( BytePtr packedBase
,
1539 ByteCount outputStartOffset
)
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
;
1555 if ( ((packedEnd
+ 1) == 0) || ((outputEnd
+ 1) == 0) ) goto FragmentUsageError
;
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
1566 packedPos
= packedBase
;
1570 packedBoundary
= packedPos
; // The start of the current operation.
1571 outputBoundary
= outputOffset
;
1573 currByte
= *packedPos
++;
1574 opcode
= currByte
>> kPEFPkDataOpcodeShift
;
1575 count1
= currByte
& kPEFPkDataCount5Mask
;
1577 if ( count1
== 0 ) count1
= GetPackedDataCount ( &packedPos
);
1581 case kPEFPkDataZero
:
1582 outputOffset
+= count1
;
1585 case kPEFPkDataBlock
:
1586 packedPos
+= count1
;
1587 outputOffset
+= count1
;
1590 case kPEFPkDataRepeat
:
1591 count2
= GetPackedDataCount ( &packedPos
) + 1; // ! Stored count is 1 less.
1592 packedPos
+= count1
;
1593 outputOffset
+= count1
* count2
;
1597 case kPEFPkDataRepeatBlock
:
1598 count2
= GetPackedDataCount ( &packedPos
);
1599 count3
= GetPackedDataCount ( &packedPos
);
1600 packedPos
+= count1
+ (count2
* count3
);
1601 outputOffset
+= count1
+ ((count1
+ count2
) * count3
);
1605 case kPEFPkDataRepeatZero
:
1606 count2
= GetPackedDataCount ( &packedPos
);
1607 count3
= GetPackedDataCount ( &packedPos
);
1608 packedPos
+= count2
* count3
;
1609 outputOffset
+= count1
+ ((count1
+ count2
) * count3
);
1614 goto FragmentCorruptError
;
1618 } while ( outputOffset
<= outputStartOffset
);
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.
1627 packedPos
= packedBoundary
; // Reset to the operation that spans the output start.
1628 outputOffset
= outputBoundary
;
1632 currByte
= *packedPos
++;
1633 opcode
= currByte
>> kPEFPkDataOpcodeShift
;
1634 count1
= currByte
& kPEFPkDataCount5Mask
;
1636 if ( count1
== 0 ) count1
= GetPackedDataCount ( &packedPos
);
1640 case kPEFPkDataZero
:
1641 PartialBlockClear ( outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count1
);
1642 outputOffset
+= count1
;
1645 case kPEFPkDataBlock
:
1646 PartialBlockMove ( packedPos
, outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count1
);
1647 packedPos
+= count1
;
1648 outputOffset
+= count1
;
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
;
1657 packedPos
+= count1
;
1660 case kPEFPkDataRepeatBlock
:
1662 count2
= GetPackedDataCount ( &packedPos
);
1663 count3
= GetPackedDataCount ( &packedPos
);
1666 BytePtr commonPos
= packedPos
;
1668 packedPos
+= count1
; // Skip the common part.
1670 for ( ; count3
!= 0; count3
-= 1 ) {
1672 PartialBlockMove ( commonPos
, outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count1
);
1673 outputOffset
+= count1
;
1675 PartialBlockMove ( packedPos
, outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count2
);
1676 packedPos
+= count2
;
1677 outputOffset
+= count2
;
1681 PartialBlockMove ( commonPos
, outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count1
);
1682 outputOffset
+= count1
;
1688 case kPEFPkDataRepeatZero
:
1690 count2
= GetPackedDataCount ( &packedPos
);
1691 count3
= GetPackedDataCount ( &packedPos
);
1693 PartialBlockClear ( outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count1
);
1694 outputOffset
+= count1
;
1696 for ( ; count3
!= 0; count3
-= 1 ) {
1698 PartialBlockMove ( packedPos
, outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count2
);
1699 packedPos
+= count2
;
1700 outputOffset
+= count2
;
1702 PartialBlockClear ( outputBase
, outputStartOffset
, outputEndOffset
, outputOffset
, count1
);
1703 outputOffset
+= count1
;
1710 goto FragmentCorruptError
;
1714 } while ( (outputOffset
<= outputEndOffset
) && (packedPos
<= packedEnd
) );
1717 // ------------------------------------------
1718 // Finally block clear anything that is left.
1720 if ( outputOffset
<= outputEndOffset
) {
1721 PEF_BlockClear ( outputBase
+ (outputOffset
- outputStartOffset
), outputEndOffset
- outputOffset
+ 1 );
1734 err
= cfragFragmentUsageErr
;
1737 FragmentCorruptError
:
1738 err
= cfragFragmentCorruptErr
;
1742 } // UnpackPartialSection ()
1746 // ===========================================================================================
1747 // PEF_UnpackSection ()
1748 // ====================
1751 OSStatus
PEF_UnpackSection ( CFContHandlerRef containerRef
,
1752 ItemCount sectionIndex
,
1753 ByteCount sectionOffset
,
1754 LogicalAddress bufferAddress
,
1755 ByteCount bufferLength
)
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;
1766 if ( pefPrivate
== NULL
) goto ParameterError
;
1767 if ( sectionIndex
>= pefPrivate
->sectionCount
) goto ParameterError
;
1768 if ( (bufferAddress
== NULL
) && (bufferLength
!= 0) ) goto ParameterError
;
1770 section
= &pefPrivate
->sections
[sectionIndex
];
1771 if ( (sectionOffset
+ bufferLength
) > section
->execSize
) goto ParameterError
;
1773 packedBase
= pefPrivate
->mappedContainer
+ section
->containerOffset
;
1774 packedEnd
= packedBase
+ section
->rawSize
- 1;
1777 if ( (sectionOffset
== 0) && (bufferLength
== section
->initSize
) ) {
1779 err
= UnpackFullSection ( packedBase
, packedEnd
, outputBase
, outputEnd
);
1780 if ( err
!= noErr
) goto ERROR
;
1782 if ( false && EnableCFMDebugging
&& (section
->execSize
> 8) ) { // Force some tests of partial unpacking.
1785 BytePtr partContents
= (*pefPrivate
->Allocate
) ( section
->execSize
- 2 );
1787 PEF_Assert ( partContents
!= NULL
);
1789 err
= PEF_UnpackSection ( containerRef
, sectionIndex
, 1, &word
, 4 );
1790 PEF_Assert ( err
== noErr
);
1792 err
= PEF_UnpackSection ( containerRef
, sectionIndex
, section
->execSize
/ 2, &word
, 4 );
1793 PEF_Assert ( err
== noErr
);
1795 err
= PEF_UnpackSection ( containerRef
, sectionIndex
, section
->execSize
- 5, &word
, 4 );
1796 PEF_Assert ( err
== noErr
);
1798 err
= PEF_UnpackSection ( containerRef
, sectionIndex
, 1, partContents
, section
->execSize
- 2 );
1799 PEF_Assert ( err
== noErr
);
1801 (*pefPrivate
->Release
) ( partContents
);
1806 if ( section
->initSize
< sectionOffset
) {
1807 PEF_BlockClear ( bufferAddress
, bufferLength
);
1809 err
= UnpackPartialSection ( packedBase
, packedEnd
, outputBase
, outputEnd
, sectionOffset
);
1810 if ( err
!= noErr
) goto ERROR
;
1813 if ( EnableCFMDebugging
) { // See if the partial output agrees with full output.
1815 BytePtr fullContents
= (*pefPrivate
->Allocate
) ( section
->execSize
);
1817 PEF_Assert ( fullContents
!= NULL
);
1818 PEF_BlockClear ( fullContents
, section
->execSize
);
1820 err
= UnpackFullSection ( packedBase
, packedEnd
, fullContents
, fullContents
+ section
->initSize
- 1 );
1821 PEF_Assert ( err
== noErr
);
1823 PEF_Assert ( PEF_CompareBytes ( fullContents
+ sectionOffset
, bufferAddress
, bufferLength
) );
1825 (*pefPrivate
->Release
) ( fullContents
);
1845 } // PEF_UnpackSection ()
1849 // ===========================================================================================
1850 // PEF_RelocateSection ()
1851 // ======================
1854 // *** This needs cleaning up.
1857 OSStatus
PEF_RelocateSection ( CFContHandlerRef containerRef
,
1858 ItemCount sectionIndex
)
1860 OSStatus err
= cfragCFMInternalErr
;
1861 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
1865 int cnt
; // ! Must be signed.
1867 LoaderRelExpHeader
* ldRelHdr
;
1868 Relocation
*reloc
, *rlend
;
1870 long rpt
; // ! Must be signed.
1878 SectionHeader
* section
;
1881 if ( pefPrivate
== NULL
) goto ParameterError
;
1882 if ( sectionIndex
>= pefPrivate
->sectionCount
) goto ParameterError
;
1884 regStart
= pefPrivate
->mappedOrigins
[sectionIndex
];
1885 section
= & pefPrivate
->sections
[sectionIndex
];
1887 pefPrivate
->resolved
= 1; // !!! Really means relocated, and should be set on exit.
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;
1895 regions
= pefPrivate
->runningOffsets
;
1896 imports
= pefPrivate
->imports
;
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.
1902 codeA
= regions
[0];
1903 dataA
= regions
[1];
1907 sprintf ( gDebugMessage
, "PLPrepareRegion: start @ %.8X\n", raddr
);
1908 PutSerialMesssage ( gDebugMessage
);
1912 while (reloc
< rlend
) {
1915 reloc
= (Relocation
*) ((RelocInstr
*) reloc
+ 1);
1917 switch ( opcode
[r
.opcode
.op
] ) {
1919 raddr
= (BytePtr
*) ((BytePtr
)raddr
+ (r
.deltadata
.delta_d4
* 4)); // ! Reduce stride to 1.
1920 cnt
= r
.deltadata
.cnt
;
1921 while (--cnt
>= 0) {
1927 cnt
= r
.run
.cnt_m1
+ 1;
1928 while (--cnt
>= 0) {
1934 cnt
= r
.run
.cnt_m1
+ 1;
1935 while (--cnt
>= 0) {
1941 cnt
= r
.run
.cnt_m1
+ 1;
1942 while (--cnt
>= 0) {
1950 cnt
= r
.run
.cnt_m1
+ 1;
1951 while (--cnt
>= 0) {
1958 cnt
= r
.run
.cnt_m1
+ 1;
1959 while (--cnt
>= 0) {
1966 cnt
= r
.run
.cnt_m1
+ 1;
1967 while (--cnt
>= 0) {
1968 *raddr
++ += (ByteCount
) imports
[rsymi
++];
1974 *raddr
++ += (ByteCount
) imports
[rsymi
++];
1978 codeA
= regions
[r
.glp
.idx
];
1982 dataA
= regions
[r
.glp
.idx
];
1986 *raddr
++ += regions
[r
.glp
.idx
];
1990 raddr
= (BytePtr
*) ((BytePtr
) raddr
+ r
.delta
.delta_m1
+ 1); // ! Reduce stride to 1.
1992 sprintf ( gDebugMessage
, "PLPrepareRegion: delta to %.8X\n", raddr
);
1993 PutSerialMesssage ( gDebugMessage
);
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
);
2006 raddr
= (BytePtr
*) ((r
.large1
.idx_top
<< 16) + reloc
->bot
+ regStart
);
2007 reloc
= (Relocation
*) ((RelocInstr
*) reloc
+ 1);
2009 sprintf ( gDebugMessage
, "PLPrepareRegion: abs to %.8X\n", raddr
);
2010 PutSerialMesssage ( gDebugMessage
);
2015 rsymi
= (r
.large1
.idx_top
<< 16) + reloc
->bot
;
2016 reloc
= (Relocation
*) ((RelocInstr
*) reloc
+ 1);
2017 *raddr
++ += (ByteCount
) imports
[rsymi
++];
2022 reloc
= (Relocation
*) ((RelocInstr
*) reloc
+ 1);
2026 rpt
= (r
.large2
.idx_top
<< 16) + reloc
->bot
;
2027 cnt
= r
.large2
.cnt_m1
+ 2;
2028 reloc
= (Relocation
*) ((RelocInstr
*) reloc
- cnt
);
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;
2038 reloc
= (Relocation
*) ((RelocInstr
*) reloc
+ 1);
2042 goto FragmentCorruptError
;
2048 sprintf ( gDebugMessage
, "PLPrepareRegion: end @ %.8X\n", raddr
);
2049 PutSerialMesssage ( gDebugMessage
);
2064 FragmentCorruptError
:
2065 err
= cfragFragmentCorruptErr
;
2069 } // PEF_RelocateSection ()
2073 // ===========================================================================================
2074 // PEF_RelocateImportsOnly ()
2075 // ==========================
2078 OSStatus
PEF_RelocateImportsOnly ( CFContHandlerRef containerRef
,
2079 ItemCount sectionIndex
,
2080 ItemCount libraryIndex
)
2082 OSStatus err
= cfragCFMInternalErr
;
2083 PEFPrivateInfo
* pefPrivate
= (PEFPrivateInfo
*) containerRef
;
2086 if ( pefPrivate
== NULL
) goto ParameterError
;
2087 if ( sectionIndex
>= pefPrivate
->sectionCount
) goto ParameterError
;
2088 if ( libraryIndex
>= pefPrivate
->ldrHeader
->numImportFiles
) goto ParameterError
;
2091 if ( pefPrivate
== NULL
) goto ParameterError
;
2094 return unimpErr
; // !!! Fix this!
2107 } // PEF_RelocateImportsOnly ()