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.
34 OFFSET_HEADER_MAGIC_NUMBERS
= [ to32Bit(0x9e43fd66), to32Bit(0x4379bfba) ]
35 OFFSET_MAGIC_NUMBERS
= [ to32Bit(0xec577ac7), to32Bit(0x0ff5e755) ]
38 # MissingMagicValuesException
40 # Thrown when magic values are missing from the binary.
43 class MissingMagicValuesException
< Exception
50 # Returns a list of offsets and sizes used by the AST.
54 ast
.filter(StructOffset
).uniq
.sort
58 ast
.filter(Sizeof
).uniq
.sort
62 # offsetsAndConfigurationIndex(ast, file) ->
63 # [[offsets, index], ...]
65 # Parses the offsets from a file and returns a list of offsets and the
66 # index of the configuration that is valid in this build target.
69 def offsetsAndConfigurationIndex(file
)
70 endiannessMarkerBytes
= nil
73 def readInt(endianness
, bytes
)
74 if endianness
== :little
89 def prepareMagic(endianness
, numbers
)
95 currentBytes
<< (number
& 0xff)
101 magicBytes +
= currentBytes
108 File
.open(file
, "rb") {
117 def sliceByteArrays(byteArray
, pattern
)
120 (byteArray
.length
- pattern
.length +
1).times
{
123 pattern
.length
.times
{
125 if byteArray
[index + subIndex
] !
= pattern
[subIndex
]
131 result
<< byteArray
[lastSlicePoint
...index
]
132 lastSlicePoint
= index + pattern
.length
136 result
<< byteArray
[lastSlicePoint
...(byteArray
.length
)]
141 [:little, :big].each
{
143 headerMagicBytes
= prepareMagic(endianness
, OFFSET_HEADER_MAGIC_NUMBERS
)
144 magicBytes
= prepareMagic(endianness
, OFFSET_MAGIC_NUMBERS
)
146 bigArray
= sliceByteArrays(fileBytes
, headerMagicBytes
)
147 unless bigArray
.size
<= 1
148 bigArray
[1..-1].each
{
150 array
= sliceByteArrays(configArray
, magicBytes
)
151 index
= readInt(endianness
, array
[1])
155 offsets
<< readInt(endianness
, data)
157 result
[index
] = offsets
162 raise MissingMagicValuesException
unless result
.length
>= 1
164 # result is {index1=>offsets1, index2=>offsets2} but we want to return
165 # [[offsets1, index1], [offsets2, index2]].
173 # buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
175 # Builds a mapping between StructOffset nodes and their values.
178 def buildOffsetsMap(ast
, offsetsList
)
181 astOffsetsList
= offsetsList(ast
)
182 astSizesList
= sizesList(ast
)
183 raise unless astOffsetsList
.size + astSizesList
.size
== offsetsList
.size
184 offsetsList(ast
).each_with_index
{
185 | structOffset
, index
|
186 offsetsMap
[structOffset
] = offsetsList
.shift
188 sizesList(ast
).each_with_index
{
190 sizesMap
[sizeof
] = offsetsList
.shift
192 [offsetsMap
, sizesMap
]