2 * Copyright (c) 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@
24 Written by: Jeffrey Robbin
25 Copyright: © 1994, 1996 by Apple Computer, Inc., all rights reserved.
27 Change History (most recent first):
28 <3> 9/20/96 MRN Changed "" to <> on including Types.h, Errors.h and Memory.h
30 <2> 9/20/94 TS Dump the globals!
31 <1> 9/6/94 TS first checked in
34 File: GetSymbolFromPEF.c
35 Written by: Jeffrey Robbin
36 Copyright: © 1994, 1996 by Apple Computer, Inc., all rights reserved.
38 Change History (most recent first):
40 <6> 9/20/96 MRN Changed <> to "" on including GetSymbolFromPEF.h that was
42 <5> 3/7/96 MRN Minor adjustments to build with the latest version of
43 SuperMarioLatestBuild name revision of MasterInterfaces.
44 <4> 10/13/94 JF Changed CFM error enums-- from 'cfragXXXErr' to 'fragXXX'
45 <3> 10/11/94 TS Move to new CFM error codes
46 <2> 9/16/94 TS Switch to pascal strings in SymbolCompare function
47 <1> 9/6/94 TS first checked in
51 typedef unsigned char Boolean
;
52 typedef unsigned char *Ptr
;
53 typedef char *StringPtr
;
57 typedef unsigned long OSStatus
;
58 typedef unsigned long ByteCount
;
59 typedef unsigned long LogicalAddress
;
66 #include "GetSymbolFromPEF.h"
72 unsigned char PEFGetNextByte (unsigned char** rawBuffer
, long* rawBufferRemaining
)
74 *rawBufferRemaining
= *rawBufferRemaining
- 1;
75 return *(*rawBuffer
)++;
79 unsigned long PEFGetCount(unsigned char** rawBuffer
, long* rawBufferRemaining
)
81 register unsigned char b
;
82 register unsigned long value
= 0UL;
84 /* Scan the count value. All required bytes MUST be present... */
86 b
= PEFGetNextByte(rawBuffer
, rawBufferRemaining
);
87 if (!IS_LAST_PICNT_BYTE(b
)) { /* if 1st byte is not that last... */
88 value
= CONCAT_PICNT(value
, b
); /* ...init value using 1st byte */
90 b
= PEFGetNextByte(rawBuffer
, rawBufferRemaining
);
91 if (!IS_LAST_PICNT_BYTE(b
)) { /* if 2nd byte is not the last... */
92 value
= CONCAT_PICNT(value
, b
); /* ...add in 2nd byte */
94 b
= PEFGetNextByte(rawBuffer
, rawBufferRemaining
);
95 if (!IS_LAST_PICNT_BYTE(b
)) { /* if 3rd byte is not the last... */
96 value
= CONCAT_PICNT(value
, b
); /* ...add in 3rd byte */
98 b
= PEFGetNextByte(rawBuffer
, rawBufferRemaining
);
99 if (!IS_LAST_PICNT_BYTE(b
)) { /* if 4th byte is not the last... */
100 value
= CONCAT_PICNT(value
, b
); /* ...add in 4th byte */
102 /* 5th byte is definitly last! */
103 b
= PEFGetNextByte(rawBuffer
, rawBufferRemaining
);
109 value
= CONCAT_PICNT(value
, b
); /* add in "last" byte (whichever one) */
115 void MemSet (unsigned char* theBuffer
, long theValue
, long theCount
)
117 while (theCount
-- > 0)
118 *theBuffer
++ = theValue
;
122 // UnpackPiData expands a compressed section into memory.
124 OSErr
UnpackPiData (LogicalAddress thePEFPtr
,
125 SectionHeaderPtr sectionHeaderPtr
,
126 LogicalAddress
* theData
)
128 long cntX
, cnt
, rpt
, dcnt
, delta
;
130 unsigned char* unpackBuffer
;
131 unsigned char* originalUnpackBuffer
;
132 unsigned char* endUnpackBuffer
;
133 unsigned char* oldRawBuffer
;
134 long oldRawBufferRemaining
;
135 unsigned char* rawBuffer
;
136 long rawBufferRemaining
;
138 // Verify incoming section is packed.
139 if (sectionHeaderPtr
->regionKind
!= kPIDataSection
)
143 // Allocate memory to unpack into
144 originalUnpackBuffer
= (unsigned char*)NewPtrSys(sectionHeaderPtr
->initSize
);
145 if (originalUnpackBuffer
== nil
)
148 unpackBuffer
= originalUnpackBuffer
;
149 endUnpackBuffer
= unpackBuffer
+ sectionHeaderPtr
->initSize
;
150 rawBuffer
= (unsigned char*)((unsigned long)thePEFPtr
+ sectionHeaderPtr
->containerOffset
);
151 rawBufferRemaining
= sectionHeaderPtr
->rawSize
;
154 /* Expand the pidata instructions. EOF will terminate processing through the setjmp */
155 /* on pidData_jmpbuf above... */
157 while (rawBufferRemaining
> 0) {
159 /* The first byte of each instruction contains the opcode and a count. If the count */
160 /* is 0, the count starts in the next byte... */
162 /* Pick up the opcode and first count operand... */
164 b
= PEFGetNextByte(&rawBuffer
, &rawBufferRemaining
);
170 cnt
= PEFGetCount(&rawBuffer
, &rawBufferRemaining
);
172 /* Unpack the data as a function of the opcode... */
175 case kZero
: /* zero out cnt bytes...*/
176 if (unpackBuffer
+ cnt
> endUnpackBuffer
)
178 MemSet(unpackBuffer
, 0, cnt
);
182 case kBlock
: /* copy cnt bytes...*/
183 if (unpackBuffer
+ cnt
> endUnpackBuffer
)
186 *unpackBuffer
++ = PEFGetNextByte(&rawBuffer
, &rawBufferRemaining
);
189 case kRepeat
: /* copy cnt bytes rpt times...*/
190 rpt
= PEFGetCount(&rawBuffer
, &rawBufferRemaining
) + 1;
194 if (unpackBuffer
+ rpt
> endUnpackBuffer
)
196 b
= PEFGetNextByte(&rawBuffer
, &rawBufferRemaining
);
197 MemSet(unpackBuffer
, b
, rpt
);
202 oldRawBufferRemaining
= rawBufferRemaining
;
203 oldRawBuffer
= rawBuffer
;
205 if (unpackBuffer
+ cnt
> endUnpackBuffer
)
207 rawBufferRemaining
= oldRawBufferRemaining
;
208 rawBuffer
= oldRawBuffer
;
211 *unpackBuffer
++ = PEFGetNextByte(&rawBuffer
, &rawBufferRemaining
);
216 case kRepeatZero
: /* copy cnt 0's and dcnt bytes rpt times*/
217 dcnt
= PEFGetCount(&rawBuffer
, &rawBufferRemaining
); /* ...then copy cnt more 0's */
218 rpt
= PEFGetCount(&rawBuffer
, &rawBufferRemaining
);
220 goto rptPart1
; /* jump into loop to copy 0's first... */
223 if (unpackBuffer
+ dcnt
> endUnpackBuffer
)
225 cntX
= dcnt
; /* cnt repeating parts follow each other*/
227 *unpackBuffer
++ = PEFGetNextByte(&rawBuffer
, &rawBufferRemaining
);
228 rptPart1
: /* non-repeating part is always 0's... */
229 if (unpackBuffer
+ cnt
> endUnpackBuffer
)
231 MemSet(unpackBuffer
, 0, cnt
);
237 case kRepeatBlock
: /* copy cnt repeating bytes and dcnt */
238 dcnt
= PEFGetCount(&rawBuffer
, &rawBufferRemaining
); /* non-repating bytes rcnt times... */
239 rpt
= PEFGetCount(&rawBuffer
, &rawBufferRemaining
); /* ...then copy cnt repeating bytes */
241 oldRawBufferRemaining
= rawBufferRemaining
;
242 oldRawBuffer
= rawBuffer
;
243 delta
= 0; /* the repeating part and each non-rep */
245 goto rptPart2
; /* jump into loop to copy rptng part 1st*/
248 if (unpackBuffer
+ dcnt
> endUnpackBuffer
)
251 rawBuffer
= oldRawBuffer
+ cnt
+ delta
;
252 rawBufferRemaining
= oldRawBufferRemaining
- (cnt
+ delta
);
255 *unpackBuffer
++ = PEFGetNextByte(&rawBuffer
, &rawBufferRemaining
);
258 if (unpackBuffer
+ cnt
> endUnpackBuffer
)
260 rawBuffer
= oldRawBuffer
;
261 rawBufferRemaining
= oldRawBufferRemaining
;
264 *unpackBuffer
++ = PEFGetNextByte(&rawBuffer
, &rawBufferRemaining
);
267 rawBuffer
= oldRawBuffer
+ cnt
+ delta
;
268 rawBufferRemaining
= oldRawBufferRemaining
- (cnt
+ delta
);
276 *theData
= originalUnpackBuffer
;
282 DisposePtr((Ptr
)originalUnpackBuffer
);
292 // GetSymbolFromPEF will extract from a PEF container the data associated
293 // with a given symbol name. It requires that the PEF file have been previously
294 // loaded into memory.
296 OSStatus
GetSymbolFromPEF ( StringPtr theSymbolName
,
297 LogicalAddress thePEFPtr
,
298 LogicalAddress theSymbolPtr
,
299 ByteCount theSymbolSize
)
301 ContainerHeaderPtr containerHeaderPtr
; // Pointer to the Container Header
302 SectionHeaderPtr loaderSectionPtr
; // Pointer to the Loader Section Header
303 SectionHeaderPtr exportSectionPtr
; // Pointer to the Section Header with the symbol
304 short currentSection
;
305 Boolean foundSection
;
307 long numExportSymbols
;
308 LoaderHeaderPtr loaderHeaderPtr
;
309 ExportSymbolEntryPtr exportSymbolEntryPtr
;
310 LoaderExportChainEntryPtr exportChainEntryPtr
;
311 StringPtr exportSymbolName
;
312 LogicalAddress expandedDataPtr
;
313 unsigned char* sourceDataPtr
;
314 unsigned char* destDataPtr
;
317 containerHeaderPtr
= (ContainerHeaderPtr
)thePEFPtr
;
319 // Does the magic cookie match?
320 if (containerHeaderPtr
->magicCookie
!= 'Joy!')
321 return cfragFragmentFormatErr
;
323 // Is this a known PEF container format?
324 if (containerHeaderPtr
->containerID
!= 'peff')
325 return cfragFragmentFormatErr
;
327 // Validate parameters
328 if (theSymbolPtr
== nil
)
332 // Find the loader section.
333 foundSection
= false;
334 for (currentSection
= 0; currentSection
< containerHeaderPtr
->nbrOfSections
; currentSection
++)
336 loaderSectionPtr
= (SectionHeaderPtr
)( (unsigned long)containerHeaderPtr
+
337 sizeof(ContainerHeader
) +
338 (sizeof(SectionHeader
) * currentSection
));
339 if (loaderSectionPtr
->regionKind
== kLoaderSection
)
346 if (foundSection
== false)
347 return cfragNoSectionErr
;
349 // Get the number of export symbols.
350 loaderHeaderPtr
= (LoaderHeaderPtr
)((unsigned long)thePEFPtr
+ loaderSectionPtr
->containerOffset
);
351 numExportSymbols
= loaderHeaderPtr
->nbrExportSyms
;
353 // Start at the first exported symbol.
354 exportSymbolEntryPtr
= (ExportSymbolEntryPtr
)( (unsigned long)loaderHeaderPtr
+
355 loaderHeaderPtr
->slotTblOffset
+
356 (sizeof(LoaderHashSlotEntry
) * (1<<loaderHeaderPtr
->hashSlotTblSz
)) +
357 (sizeof(LoaderExportChainEntry
) * numExportSymbols
));
359 exportChainEntryPtr
= (LoaderExportChainEntryPtr
)( (unsigned long)loaderHeaderPtr
+
360 loaderHeaderPtr
->slotTblOffset
+
361 (sizeof(LoaderHashSlotEntry
) * (1<<loaderHeaderPtr
->hashSlotTblSz
)));
364 while (numExportSymbols
-- > 0)
366 exportSymbolName
= (StringPtr
)( (unsigned long)loaderHeaderPtr
+
367 loaderHeaderPtr
->strTblOffset
+
368 (exportSymbolEntryPtr
->class_and_name
& 0x00FFFFFF));
369 if (SymbolCompare(theSymbolName
, exportSymbolName
, exportChainEntryPtr
->_h
._h_h
._nameLength
))
374 exportSymbolEntryPtr
= (ExportSymbolEntryPtr
)(((int)exportSymbolEntryPtr
) + 10);
375 exportChainEntryPtr
++;
378 if (foundSymbol
== false)
379 return cfragNoSymbolErr
;
382 // Found the symbol, so... let's go get the data!
384 exportSectionPtr
= (SectionHeaderPtr
)( (unsigned long)containerHeaderPtr
+
385 sizeof(ContainerHeader
) +
386 (sizeof(SectionHeader
) * exportSymbolEntryPtr
->sectionNumber
));
388 expandedDataPtr
= nil
;
390 switch (exportSectionPtr
-> regionKind
)
394 // Expand the data! (Not yet... :)
396 if (UnpackPiData (thePEFPtr
, exportSectionPtr
, &expandedDataPtr
) != noErr
)
397 return cfragFragmentCorruptErr
;
399 sourceDataPtr
= (unsigned char*)((unsigned long)expandedDataPtr
+
400 exportSymbolEntryPtr
->address
);
404 sourceDataPtr
= (unsigned char*)((unsigned long)thePEFPtr
+
405 exportSectionPtr
->containerOffset
+
406 exportSymbolEntryPtr
->address
);
413 destDataPtr
= (unsigned char*)theSymbolPtr
;
416 while (theSymbolSize
-- > 0)
417 *destDataPtr
++ = *sourceDataPtr
++;
420 // Cleanup any expanded data
422 if (expandedDataPtr
!= nil
)
423 DisposePtr((Ptr
)expandedDataPtr
);
432 // theExportSymbol is NOT null-terminated, so use theExportSymbolLength.
434 Boolean
SymbolCompare ( StringPtr theLookedForSymbol
,
435 StringPtr theExportSymbol
,
436 unsigned long theExportSymbolLength
)
438 unsigned char* p1
= (unsigned char*)theLookedForSymbol
;
439 unsigned char* p2
= (unsigned char*)theExportSymbol
;
442 // (skip over p string len byte)
443 if ( theExportSymbolLength
!= *p1
++ )
446 while ( theExportSymbolLength
-- != 0 )
448 if ( *p1
++ != *p2
++ )