source: webkit/trunk/Source/JavaScriptCore/offlineasm/offsets.rb

Last change on this file was 269171, checked in by [email protected], 5 years ago

JavaScriptCore should support multiple build variants
<https://webkit.org/b/218347>
<rdar://problem/70786057>

Patch by Jérôme Decoodt <[email protected]> on 2020-10-29
Reviewed by Keith Miller.

Update JavaScriptCore to handle BUILD_VARIANTS properly by
passing the value to build phase scripts and handling all
variants set during the build. For engineering builds,
BUILD_VARIANTS=normal.

  • CMakeLists.txt:
  • Update to pass equivalent ${BUILD_VARIANTS} for non-Apple platforms to asm.rb and generate_offset_extractor.rb.

(LLInt Offsets | Generate Derived Sources):
(Offline Assembler | Offline Assemble):

  • Update build phase script to pass "${BUILD_VARIANTS}" as an argument to scripts.
  • offlineasm/asm.rb:
  • Parse BUILD_VARIANTS argument to pass to offsetsAndConfigurationIndexForVariants().
  • offlineasm/generate_offset_extractor.rb:
  • Parse BUILD_VARIANTS argument to pass to configurationIndicesForVariants().
  • offlineasm/offsets.rb:

(offsetsAndConfigurationIndex):

  • Update argument list in comment block.

(offsetsAndConfigurationIndexForVariants): Add.

  • Invoke offsetsAndConfigurationIndex() for each build variant.

(configurationIndices):

  • Update argument list in comment block.

(configurationIndicesForVariants): Add.

  • Invoke configurationIndices() for each build variant.
File size: 7.7 KB
Line 
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
24require "config"
25require "ast"
26
27OFFSET_HEADER_MAGIC_NUMBERS = [ 0x2e43fd66, 0x4379bfba ]
28OFFSET_MAGIC_NUMBERS = [ 0x5c577ac7, 0x0ff5e755 ]
29
30#
31# MissingMagicValuesException
32#
33# Thrown when magic values are missing from the binary.
34#
35
36class MissingMagicValuesException < Exception
37end
38
39#
40# offsetsList(ast)
41# sizesList(ast)
42# constsLists(ast)
43#
44# Returns a list of offsets, sizeofs, and consts used by the AST.
45#
46
47def offsetsList(ast)
48 ast.filter(StructOffset).uniq.sort
49end
50
51def sizesList(ast)
52 ast.filter(Sizeof).uniq.sort
53end
54
55def constsList(ast)
56 ast.filter(ConstExpr).uniq.sort
57end
58
59def readInt(endianness, bytes)
60 if endianness == :little
61 # Little endian
62 number = (bytes[0] << 0 |
63 bytes[1] << 8 |
64 bytes[2] << 16 |
65 bytes[3] << 24 |
66 bytes[4] << 32 |
67 bytes[5] << 40 |
68 bytes[6] << 48 |
69 bytes[7] << 56)
70 else
71 # Big endian
72 number = (bytes[0] << 56 |
73 bytes[1] << 48 |
74 bytes[2] << 40 |
75 bytes[3] << 32 |
76 bytes[4] << 24 |
77 bytes[5] << 16 |
78 bytes[6] << 8 |
79 bytes[7] << 0)
80 end
81 if number > 0x7fffffff_ffffffff
82 number -= 1 << 64
83 end
84 number
85end
86
87def prepareMagic(endianness, numbers)
88 magicBytes = []
89 numbers.each {
90 | number |
91 currentBytes = []
92 8.times {
93 currentBytes << (number & 0xff)
94 number >>= 8
95 }
96 if endianness == :big
97 currentBytes.reverse!
98 end
99 magicBytes += currentBytes
100 }
101 magicBytes
102end
103
104def fileBytes(file)
105 fileBytes = []
106 File.open(file, "rb") {
107 | inp |
108 loop {
109 byte = inp.getbyte
110 break unless byte
111 fileBytes << byte
112 }
113 }
114 fileBytes
115end
116
117def 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
139end
140
141#
142# offsetsAndConfigurationIndex(file) ->
143# [[offsets, index], ...]
144#
145# Parses the offsets from a file and returns a list of offsets and the
146# index of the configuration that is valid in this build target.
147#
148
149def offsetsAndConfigurationIndex(file)
150 fileBytes = fileBytes(file)
151 result = {}
152
153 [:little, :big].each {
154 | endianness |
155 headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)
156 magicBytes = prepareMagic(endianness, OFFSET_MAGIC_NUMBERS)
157
158 bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
159 unless bigArray.size <= 1
160 bigArray[1..-1].each {
161 | configArray |
162 array = sliceByteArrays(configArray, magicBytes)
163 index = readInt(endianness, array[1])
164 offsets = []
165 array[2..-1].each {
166 | data |
167 offsets << readInt(endianness, data)
168 }
169 result[index] = offsets
170 }
171 end
172 }
173
174 raise MissingMagicValuesException unless result.length >= 1
175
176 # result is {index1=>offsets1, index2=>offsets2} but we want to return
177 # [[offsets1, index1], [offsets2, index2]].
178 return result.map {
179 | pair |
180 pair.reverse
181 }
182end
183
184#
185# offsetsAndConfigurationIndex(file) ->
186# [[offsets, index], ...]
187#
188# Parses the offsets from a file and all its variants and returns a list of
189# offsets and the index of the configuration that is valid in this build target.
190#
191
192def offsetsAndConfigurationIndexForVariants(file, variants)
193 results = []
194 variants.each {
195 | current_variant |
196 suffix = ""
197 unless current_variant == "normal"
198 suffix = "_" + current_variant
199 end
200 results << offsetsAndConfigurationIndex(file + suffix)
201 }
202 return results.flatten(1)
203end
204
205#
206# configurationIndices(file) ->
207# [[offsets, index], ...]
208#
209# Parses the configurations from a file and returns a list of the indices of
210# the configurations that are valid in this build target.
211#
212
213def configurationIndices(file)
214 fileBytes = fileBytes(file)
215 result = []
216
217 [:little, :big].each {
218 | endianness |
219 headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)
220
221 bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
222 unless bigArray.size <= 1
223 bigArray[1..-1].each {
224 | configArray |
225 result << readInt(endianness, configArray)
226 }
227 end
228 }
229
230 raise MissingMagicValuesException unless result.length >= 1
231
232 return result
233end
234
235#
236# configurationIndicesForVariants(file, variants) ->
237# [[offsets, index], ...]
238#
239# Parses the configurations from a file and all its variants and returns a list
240# of the indices of the configurations that are valid in this build target.
241#
242
243def configurationIndicesForVariants(file, variants)
244 results = []
245 variants.each {
246 | current_variant |
247 suffix = ""
248 unless current_variant == "normal"
249 suffix = "_" + current_variant
250 end
251 results << configurationIndices(file + suffix)
252 }
253 return results.flatten(1)
254end
255
256#
257# buildOffsetsMap(ast, extractedConstants) -> map
258#
259# Builds a mapping between StructOffset, Sizeof, and ConstExpr nodes and their values.
260#
261
262def buildOffsetsMap(ast, extractedConstants)
263 map = {}
264 astOffsetsList = offsetsList(ast)
265 astSizesList = sizesList(ast)
266 astConstsList = constsList(ast)
267
268 raise unless astOffsetsList.size + astSizesList.size + astConstsList.size == extractedConstants.size
269 astOffsetsList.each_with_index {
270 | structOffset, index |
271 map[structOffset] = extractedConstants.shift
272 }
273 astSizesList.each_with_index {
274 | sizeof, index |
275 map[sizeof] = extractedConstants.shift
276 }
277 astConstsList.each_with_index {
278 | const, index |
279 map[const] = extractedConstants.shift
280 }
281 map
282end
283
Note: See TracBrowser for help on using the repository browser.