1 # Copyright (C) 2011 Apple Inc. All rights reserved. 
   3 # Redistribution and use in source and binary forms, with or without 
   4 # modification, are permitted provided that the following conditions 
   6 # 1. Redistributions of source code must retain the above copyright 
   7 #    notice, this list of conditions and the following disclaimer. 
   8 # 2. Redistributions in binary form must reproduce the above copyright 
   9 #    notice, this list of conditions and the following disclaimer in the 
  10 #    documentation and/or other materials provided with the distribution. 
  12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 
  13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
  14 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 
  16 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
  22 # THE POSSIBILITY OF SUCH DAMAGE. 
  26 OFFSET_HEADER_MAGIC_NUMBERS 
= [ 0x9e43fd66, 0x4379bfba ] 
  27 OFFSET_MAGIC_NUMBERS 
= [ 0xec577ac7, 0x0ff5e755 ] 
  30 # MissingMagicValuesException 
  32 # Thrown when magic values are missing from the binary. 
  33 # This is usually an indication that the classic interpreter is enabled. 
  36 class MissingMagicValuesException 
< Exception
 
  43 # Returns a list of offsets and sizes used by the AST. 
  47     ast
.filter(StructOffset
).uniq
.sort
 
  51     ast
.filter(Sizeof
).uniq
.sort
 
  55 # offsetsAndConfigurationIndex(ast, file) -> 
  56 #     [[offsets, index], ...] 
  58 # Parses the offsets from a file and returns a list of offsets and the 
  59 # index of the configuration that is valid in this build target. 
  62 def offsetsAndConfigurationIndex(file
) 
  63     endiannessMarkerBytes 
= nil 
  66     def readInt(endianness
, bytes
) 
  67         if endianness 
== :little 
  82     def prepareMagic(endianness
, numbers
) 
  88                 currentBytes 
<< (number 
& 0xff) 
  94             magicBytes +
= currentBytes
 
 101     File
.open(file
, "r") { 
 110     def sliceByteArrays(byteArray
, pattern
) 
 113         (byteArray
.length 
- pattern
.length + 
1).times 
{ 
 116             pattern
.length
.times 
{ 
 118                 if byteArray
[index + subIndex
] !
= pattern
[subIndex
] 
 124                 result 
<< byteArray
[lastSlicePoint
...index
] 
 125                 lastSlicePoint 
= index + pattern
.length
 
 129         result 
<< byteArray
[lastSlicePoint
...(byteArray
.length
)] 
 134     [:little, :big].each 
{ 
 136         headerMagicBytes 
= prepareMagic(endianness
, OFFSET_HEADER_MAGIC_NUMBERS
) 
 137         magicBytes 
= prepareMagic(endianness
, OFFSET_MAGIC_NUMBERS
) 
 139         bigArray 
= sliceByteArrays(fileBytes
, headerMagicBytes
) 
 140         unless bigArray
.size 
<= 1 
 141             bigArray
[1..-1].each 
{ 
 143                 array 
= sliceByteArrays(configArray
, magicBytes
) 
 144                 index 
= readInt(endianness
, array
[1]) 
 148                     offsets 
<< readInt(endianness
, data) 
 150                 result 
<< [offsets
, index
] 
 155     raise MissingMagicValuesException 
unless result
.length 
>= 1 
 156     raise if result
.map
{|v
| v
[1]}.uniq
.size 
< result
.map
{|v
| v
[1]}.size
 
 162 # buildOffsetsMap(ast, offsetsList) -> [offsets, sizes] 
 164 # Builds a mapping between StructOffset nodes and their values. 
 167 def buildOffsetsMap(ast
, offsetsList
) 
 170     astOffsetsList 
= offsetsList(ast
) 
 171     astSizesList 
= sizesList(ast
) 
 172     raise unless astOffsetsList
.size + astSizesList
.size 
== offsetsList
.size
 
 173     offsetsList(ast
).each_with_index 
{ 
 174         | structOffset
, index 
| 
 175         offsetsMap
[structOffset
] = offsetsList
.shift
 
 177     sizesList(ast
).each_with_index 
{ 
 179         sizesMap
[sizeof
] = offsetsList
.shift
 
 181     [offsetsMap
, sizesMap
]