]> git.saurik.com Git - apple/javascriptcore.git/blob - offlineasm/offsets.rb
JavaScriptCore-1097.13.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 "ast"
25
26 OFFSET_HEADER_MAGIC_NUMBERS = [ 0x9e43fd66, 0x4379bfba ]
27 OFFSET_MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ]
28
29 #
30 # MissingMagicValuesException
31 #
32 # Thrown when magic values are missing from the binary.
33 # This is usually an indication that the classic interpreter is enabled.
34 #
35
36 class MissingMagicValuesException < Exception
37 end
38
39 #
40 # offsetsList(ast)
41 # sizesList(ast)
42 #
43 # Returns a list of offsets and sizes used by the AST.
44 #
45
46 def offsetsList(ast)
47 ast.filter(StructOffset).uniq.sort
48 end
49
50 def sizesList(ast)
51 ast.filter(Sizeof).uniq.sort
52 end
53
54 #
55 # offsetsAndConfigurationIndex(ast, file) ->
56 # [[offsets, index], ...]
57 #
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.
60 #
61
62 def offsetsAndConfigurationIndex(file)
63 endiannessMarkerBytes = nil
64 result = []
65
66 def readInt(endianness, bytes)
67 if endianness == :little
68 # Little endian
69 (bytes[0] << 0 |
70 bytes[1] << 8 |
71 bytes[2] << 16 |
72 bytes[3] << 24)
73 else
74 # Big endian
75 (bytes[0] << 24 |
76 bytes[1] << 16 |
77 bytes[2] << 8 |
78 bytes[3] << 0)
79 end
80 end
81
82 def prepareMagic(endianness, numbers)
83 magicBytes = []
84 numbers.each {
85 | number |
86 currentBytes = []
87 4.times {
88 currentBytes << (number & 0xff)
89 number >>= 8
90 }
91 if endianness == :big
92 currentBytes.reverse!
93 end
94 magicBytes += currentBytes
95 }
96 magicBytes
97 end
98
99 fileBytes = []
100
101 File.open(file, "r") {
102 | inp |
103 loop {
104 byte = inp.getbyte
105 break unless byte
106 fileBytes << byte
107 }
108 }
109
110 def sliceByteArrays(byteArray, pattern)
111 result = []
112 lastSlicePoint = 0
113 (byteArray.length - pattern.length + 1).times {
114 | index |
115 foundOne = true
116 pattern.length.times {
117 | subIndex |
118 if byteArray[index + subIndex] != pattern[subIndex]
119 foundOne = false
120 break
121 end
122 }
123 if foundOne
124 result << byteArray[lastSlicePoint...index]
125 lastSlicePoint = index + pattern.length
126 end
127 }
128
129 result << byteArray[lastSlicePoint...(byteArray.length)]
130
131 result
132 end
133
134 [:little, :big].each {
135 | endianness |
136 headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)
137 magicBytes = prepareMagic(endianness, OFFSET_MAGIC_NUMBERS)
138
139 bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
140 unless bigArray.size <= 1
141 bigArray[1..-1].each {
142 | configArray |
143 array = sliceByteArrays(configArray, magicBytes)
144 index = readInt(endianness, array[1])
145 offsets = []
146 array[2..-1].each {
147 | data |
148 offsets << readInt(endianness, data)
149 }
150 result << [offsets, index]
151 }
152 end
153 }
154
155 raise MissingMagicValuesException unless result.length >= 1
156 raise if result.map{|v| v[1]}.uniq.size < result.map{|v| v[1]}.size
157
158 result
159 end
160
161 #
162 # buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
163 #
164 # Builds a mapping between StructOffset nodes and their values.
165 #
166
167 def buildOffsetsMap(ast, offsetsList)
168 offsetsMap = {}
169 sizesMap = {}
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
176 }
177 sizesList(ast).each_with_index {
178 | sizeof, index |
179 sizesMap[sizeof] = offsetsList.shift
180 }
181 [offsetsMap, sizesMap]
182 end
183