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 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) ] 36 37# 38# MissingMagicValuesException 39# 40# Thrown when magic values are missing from the binary. 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 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 } 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 195