require "config"
require "ast"
def to32Bit(value)
if value > 0x7fffffff
value -= 1 << 32
end
value
end
OFFSET_HEADER_MAGIC_NUMBERS = [ to32Bit(0x9e43fd66), to32Bit(0x4379bfba) ]
OFFSET_MAGIC_NUMBERS = [ to32Bit(0xec577ac7), to32Bit(0x0ff5e755) ]
class MissingMagicValuesException < Exception
end
def offsetsList(ast)
ast.filter(StructOffset).uniq.sort
end
def sizesList(ast)
ast.filter(Sizeof).uniq.sort
end
def offsetsAndConfigurationIndex(file)
endiannessMarkerBytes = nil
result = {}
def readInt(endianness, bytes)
if endianness == :little
(bytes[0] << 0 |
bytes[1] << 8 |
bytes[2] << 16 |
bytes[3] << 24)
else
(bytes[0] << 24 |
bytes[1] << 16 |
bytes[2] << 8 |
bytes[3] << 0)
end
end
def prepareMagic(endianness, numbers)
magicBytes = []
numbers.each {
| number |
currentBytes = []
4.times {
currentBytes << (number & 0xff)
number >>= 8
}
if endianness == :big
currentBytes.reverse!
end
magicBytes += currentBytes
}
magicBytes
end
fileBytes = []
File.open(file, "rb") {
| inp |
loop {
byte = inp.getbyte
break unless byte
fileBytes << byte
}
}
def sliceByteArrays(byteArray, pattern)
result = []
lastSlicePoint = 0
(byteArray.length - pattern.length + 1).times {
| index |
foundOne = true
pattern.length.times {
| subIndex |
if byteArray[index + subIndex] != pattern[subIndex]
foundOne = false
break
end
}
if foundOne
result << byteArray[lastSlicePoint...index]
lastSlicePoint = index + pattern.length
end
}
result << byteArray[lastSlicePoint...(byteArray.length)]
result
end
[:little, :big].each {
| endianness |
headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)
magicBytes = prepareMagic(endianness, OFFSET_MAGIC_NUMBERS)
bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
unless bigArray.size <= 1
bigArray[1..-1].each {
| configArray |
array = sliceByteArrays(configArray, magicBytes)
index = readInt(endianness, array[1])
offsets = []
array[2..-1].each {
| data |
offsets << readInt(endianness, data)
}
result[index] = offsets
}
end
}
raise MissingMagicValuesException unless result.length >= 1
return result.map {
| pair |
pair.reverse
}
end
def buildOffsetsMap(ast, offsetsList)
offsetsMap = {}
sizesMap = {}
astOffsetsList = offsetsList(ast)
astSizesList = sizesList(ast)
raise unless astOffsetsList.size + astSizesList.size == offsetsList.size
offsetsList(ast).each_with_index {
| structOffset, index |
offsetsMap[structOffset] = offsetsList.shift
}
sizesList(ast).each_with_index {
| sizeof, index |
sizesMap[sizeof] = offsetsList.shift
}
[offsetsMap, sizesMap]
end