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
]