]> git.saurik.com Git - apple/javascriptcore.git/blob - offlineasm/offsets.rb
JavaScriptCore-1218.0.1.tar.gz
[apple/javascriptcore.git] / offlineasm / offsets.rb
1 # Copyright (C) 2011 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
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.
11 #
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.
23
24 require "config"
25 require "ast"
26
27 def to32Bit(value)
28 if value > 0x7fffffff
29 value -= 1 << 32
30 end
31 value
32 end
33
34 OFFSET_HEADER_MAGIC_NUMBERS = [ to32Bit(0x9e43fd66), to32Bit(0x4379bfba) ]
35 OFFSET_MAGIC_NUMBERS = [ to32Bit(0xec577ac7), to32Bit(0x0ff5e755) ]
36
37 #
38 # MissingMagicValuesException
39 #
40 # Thrown when magic values are missing from the binary.
41 #
42
43 class MissingMagicValuesException < Exception
44 end
45
46 #
47 # offsetsList(ast)
48 # sizesList(ast)
49 #
50 # Returns a list of offsets and sizes used by the AST.
51 #
52
53 def offsetsList(ast)
54 ast.filter(StructOffset).uniq.sort
55 end
56
57 def sizesList(ast)
58 ast.filter(Sizeof).uniq.sort
59 end
60
61 #
62 # offsetsAndConfigurationIndex(ast, file) ->
63 # [[offsets, index], ...]
64 #
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.
67 #
68
69 def offsetsAndConfigurationIndex(file)
70 endiannessMarkerBytes = nil
71 result = {}
72
73 def readInt(endianness, bytes)
74 if endianness == :little
75 # Little endian
76 (bytes[0] << 0 |
77 bytes[1] << 8 |
78 bytes[2] << 16 |
79 bytes[3] << 24)
80 else
81 # Big endian
82 (bytes[0] << 24 |
83 bytes[1] << 16 |
84 bytes[2] << 8 |
85 bytes[3] << 0)
86 end
87 end
88
89 def prepareMagic(endianness, numbers)
90 magicBytes = []
91 numbers.each {
92 | number |
93 currentBytes = []
94 4.times {
95 currentBytes << (number & 0xff)
96 number >>= 8
97 }
98 if endianness == :big
99 currentBytes.reverse!
100 end
101 magicBytes += currentBytes
102 }
103 magicBytes
104 end
105
106 fileBytes = []
107
108 File.open(file, "rb") {
109 | inp |
110 loop {
111 byte = inp.getbyte
112 break unless byte
113 fileBytes << byte
114 }
115 }
116
117 def sliceByteArrays(byteArray, pattern)
118 result = []
119 lastSlicePoint = 0
120 (byteArray.length - pattern.length + 1).times {
121 | index |
122 foundOne = true
123 pattern.length.times {
124 | subIndex |
125 if byteArray[index + subIndex] != pattern[subIndex]
126 foundOne = false
127 break
128 end
129 }
130 if foundOne
131 result << byteArray[lastSlicePoint...index]
132 lastSlicePoint = index + pattern.length
133 end
134 }
135
136 result << byteArray[lastSlicePoint...(byteArray.length)]
137
138 result
139 end
140
141 [:little, :big].each {
142 | endianness |
143 headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)
144 magicBytes = prepareMagic(endianness, OFFSET_MAGIC_NUMBERS)
145
146 bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
147 unless bigArray.size <= 1
148 bigArray[1..-1].each {
149 | configArray |
150 array = sliceByteArrays(configArray, magicBytes)
151 index = readInt(endianness, array[1])
152 offsets = []
153 array[2..-1].each {
154 | data |
155 offsets << readInt(endianness, data)
156 }
157 result[index] = offsets
158 }
159 end
160 }
161
162 raise MissingMagicValuesException unless result.length >= 1
163
164 # result is {index1=>offsets1, index2=>offsets2} but we want to return
165 # [[offsets1, index1], [offsets2, index2]].
166 return result.map {
167 | pair |
168 pair.reverse
169 }
170 end
171
172 #
173 # buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
174 #
175 # Builds a mapping between StructOffset nodes and their values.
176 #
177
178 def buildOffsetsMap(ast, offsetsList)
179 offsetsMap = {}
180 sizesMap = {}
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
187 }
188 sizesList(ast).each_with_index {
189 | sizeof, index |
190 sizesMap[sizeof] = offsetsList.shift
191 }
192 [offsetsMap, sizesMap]
193 end
194