]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/offsets.rb
JavaScriptCore-1097.13.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
24require "ast"
25
26OFFSET_HEADER_MAGIC_NUMBERS = [ 0x9e43fd66, 0x4379bfba ]
27OFFSET_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
36class MissingMagicValuesException < Exception
37end
38
39#
40# offsetsList(ast)
41# sizesList(ast)
42#
43# Returns a list of offsets and sizes used by the AST.
44#
45
46def offsetsList(ast)
47 ast.filter(StructOffset).uniq.sort
48end
49
50def sizesList(ast)
51 ast.filter(Sizeof).uniq.sort
52end
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
62def 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
159end
160
161#
162# buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
163#
164# Builds a mapping between StructOffset nodes and their values.
165#
166
167def 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]
182end
183