]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/offsets.rb
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / offlineasm / offsets.rb
CommitLineData
6fe7ccc8
A
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
93a37866 24require "config"
6fe7ccc8
A
25require "ast"
26
93a37866
A
27def to32Bit(value)
28 if value > 0x7fffffff
29 value -= 1 << 32
30 end
31 value
32end
33
34OFFSET_HEADER_MAGIC_NUMBERS = [ to32Bit(0x9e43fd66), to32Bit(0x4379bfba) ]
35OFFSET_MAGIC_NUMBERS = [ to32Bit(0xec577ac7), to32Bit(0x0ff5e755) ]
6fe7ccc8
A
36
37#
38# MissingMagicValuesException
39#
40# Thrown when magic values are missing from the binary.
6fe7ccc8
A
41#
42
43class MissingMagicValuesException < Exception
44end
45
46#
47# offsetsList(ast)
48# sizesList(ast)
49#
50# Returns a list of offsets and sizes used by the AST.
51#
52
53def offsetsList(ast)
54 ast.filter(StructOffset).uniq.sort
55end
56
57def sizesList(ast)
58 ast.filter(Sizeof).uniq.sort
59end
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
69def offsetsAndConfigurationIndex(file)
70 endiannessMarkerBytes = nil
93a37866 71 result = {}
6fe7ccc8
A
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
93a37866 108 File.open(file, "rb") {
6fe7ccc8
A
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 }
93a37866 157 result[index] = offsets
6fe7ccc8
A
158 }
159 end
160 }
161
162 raise MissingMagicValuesException unless result.length >= 1
6fe7ccc8 163
93a37866
A
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 }
6fe7ccc8
A
170end
171
172#
173# buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
174#
175# Builds a mapping between StructOffset nodes and their values.
176#
177
178def 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]
193end
194