#!/usr/bin/env python
# Generates ELF, COFF and MachO object files for different architectures
# containing all relocations:
#
# ELF: i386, x86_64, ppc64, aarch64, arm, mips, mips64el
# COFF: i386, x86_64
# MachO: i386, x86_64, arm
# (see end of file for triples)
#
# To simplify generation, object files are generated with just the proper
# number of relocations through repeated instructions. Afterwards, the
# relocations in the object file are patched to their proper value.
import operator
import shutil
import StringIO
import struct
import subprocess
import sys
class EnumType(type):
def __init__(self, name, bases = (), attributes = {}):
super(EnumType, self).__init__(name, bases, attributes)
type.__setattr__(self, '_map', {})
type.__setattr__(self, '_nameMap', {})
for symbol in attributes:
if symbol.startswith('__') or symbol.endswith('__'):
continue
value = attributes[symbol]
# MyEnum.symbol == value
type.__setattr__(self, symbol, value)
self._nameMap[symbol] = value
# The first symbol with the given value is authoritative.
if not (value in self._map):
# MyEnum[value] == symbol
self._map[value] = symbol
# Not supported (Enums are immutable).
def __setattr__(self, name, value):
raise NotSupportedException, self.__setattr__
# Not supported (Enums are immutable).
def __delattr__(self, name):
raise NotSupportedException, self.__delattr__
# Gets the enum symbol for the specified value.
def __getitem__(self, value):
symbol = self._map.get(value)
if symbol is None:
raise KeyError, value
return symbol
# Gets the enum symbol for the specified value or none.
def lookup(self, value):
symbol = self._map.get(value)
return symbol
# Not supported (Enums are immutable).
def __setitem__(self, value, symbol):
raise NotSupportedException, self.__setitem__
# Not supported (Enums are immutable).
def __delitem__(self, value):
raise NotSupportedException, self.__delitem__
def entries(self):
# sort by (value, name)
def makeKey(item):
return (item[1], item[0])
e = []
for pair in sorted(self._nameMap.iteritems(), key=makeKey):
e.append(pair)
return e
def __iter__(self):
for e in self.entries():
yield e
Enum = EnumType('Enum', (), {})
class BinaryReader:
def __init__(self, path):
self.file = open(path, "r+b", 0)
self.isLSB = None
self.is64Bit = None
self.isN64 = False
def tell(self):
return self.file.tell()
def seek(self, pos):
self.file.seek(pos)
def read(self, N):
data = self.file.read(N)
if len(data) != N:
raise ValueError, "Out of data!"
return data
def int8(self):
return ord(self.read(1))
def uint8(self):
return ord(self.read(1))
def int16(self):
return struct.unpack('><'[self.isLSB] + 'h', self.read(2))[0]
def uint16(self):
return struct.unpack('><'[self.isLSB] + 'H', self.read(2))[0]
def int32(self):
return struct.unpack('><'[self.isLSB] + 'i', self.read(4))[0]
def uint32(self):
return struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0]
def int64(self):
return struct.unpack('><'[self.isLSB] + 'q', self.read(8))[0]
def uint64(self):
return struct.unpack('><'[self.isLSB] + 'Q', self.read(8))[0]
def writeUInt8(self, value):
self.file.write(struct.pack('><'[self.isLSB] + 'B', value))
def writeUInt16(self, value):
self.file.write(struct.pack('><'[self.isLSB]