mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-17 22:00:41 +00:00

*** to conform to clang-format’s LLVM style. This kind of mass change has *** two obvious implications: Firstly, merging this particular commit into a downstream fork may be a huge effort. Alternatively, it may be worth merging all changes up to this commit, performing the same reformatting operation locally, and then discarding the merge for this particular commit. The commands used to accomplish this reformatting were as follows (with current working directory as the root of the repository): find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} + find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ; The version of clang-format used was 3.9.0, and autopep8 was 1.2.4. Secondly, “blame” style tools will generally point to this commit instead of a meaningful prior commit. There are alternatives available that will attempt to look through this change and find the appropriate prior commit. YMMV. llvm-svn: 280751
227 lines
7.9 KiB
Python
Executable File
227 lines
7.9 KiB
Python
Executable File
#! /usr/bin/env python
|
|
|
|
import string
|
|
import struct
|
|
import sys
|
|
|
|
|
|
class FileExtract:
|
|
'''Decode binary data from a file'''
|
|
|
|
def __init__(self, f, b='='):
|
|
'''Initialize with an open binary file and optional byte order'''
|
|
|
|
self.file = f
|
|
self.byte_order = b
|
|
self.offsets = list()
|
|
|
|
def set_byte_order(self, b):
|
|
'''Set the byte order, valid values are "big", "little", "swap", "native", "<", ">", "@", "="'''
|
|
if b == 'big':
|
|
self.byte_order = '>'
|
|
elif b == 'little':
|
|
self.byte_order = '<'
|
|
elif b == 'swap':
|
|
# swap what ever the current byte order is
|
|
self.byte_order = swap_unpack_char()
|
|
elif b == 'native':
|
|
self.byte_order = '='
|
|
elif b == '<' or b == '>' or b == '@' or b == '=':
|
|
self.byte_order = b
|
|
else:
|
|
print "error: invalid byte order specified: '%s'" % b
|
|
|
|
def is_in_memory(self):
|
|
return False
|
|
|
|
def seek(self, offset, whence=0):
|
|
if self.file:
|
|
return self.file.seek(offset, whence)
|
|
raise ValueError
|
|
|
|
def tell(self):
|
|
if self.file:
|
|
return self.file.tell()
|
|
raise ValueError
|
|
|
|
def read_size(self, byte_size):
|
|
s = self.file.read(byte_size)
|
|
if len(s) != byte_size:
|
|
return None
|
|
return s
|
|
|
|
def push_offset_and_seek(self, offset):
|
|
'''Push the current file offset and seek to "offset"'''
|
|
self.offsets.append(self.file.tell())
|
|
self.file.seek(offset, 0)
|
|
|
|
def pop_offset_and_seek(self):
|
|
'''Pop a previously pushed file offset, or do nothing if there were no previously pushed offsets'''
|
|
if len(self.offsets) > 0:
|
|
self.file.seek(self.offsets.pop())
|
|
|
|
def get_sint8(self, fail_value=0):
|
|
'''Extract a single int8_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(1)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'b', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_uint8(self, fail_value=0):
|
|
'''Extract a single uint8_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(1)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'B', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_sint16(self, fail_value=0):
|
|
'''Extract a single int16_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(2)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'h', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_uint16(self, fail_value=0):
|
|
'''Extract a single uint16_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(2)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'H', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_sint32(self, fail_value=0):
|
|
'''Extract a single int32_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(4)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'i', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_uint32(self, fail_value=0):
|
|
'''Extract a single uint32_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(4)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'I', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_sint64(self, fail_value=0):
|
|
'''Extract a single int64_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(8)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'q', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_uint64(self, fail_value=0):
|
|
'''Extract a single uint64_t from the binary file at the current file position, returns a single integer'''
|
|
s = self.read_size(8)
|
|
if s:
|
|
v, = struct.unpack(self.byte_order + 'Q', s)
|
|
return v
|
|
else:
|
|
return fail_value
|
|
|
|
def get_fixed_length_c_string(
|
|
self,
|
|
n,
|
|
fail_value='',
|
|
isprint_only_with_space_padding=False):
|
|
'''Extract a single fixed length C string from the binary file at the current file position, returns a single C string'''
|
|
s = self.read_size(n)
|
|
if s:
|
|
cstr, = struct.unpack(self.byte_order + ("%i" % n) + 's', s)
|
|
# Strip trialing NULLs
|
|
cstr = string.strip(cstr, "\0")
|
|
if isprint_only_with_space_padding:
|
|
for c in cstr:
|
|
if c in string.printable or ord(c) == 0:
|
|
continue
|
|
return fail_value
|
|
return cstr
|
|
else:
|
|
return fail_value
|
|
|
|
def get_c_string(self):
|
|
'''Extract a single NULL terminated C string from the binary file at the current file position, returns a single C string'''
|
|
cstr = ''
|
|
byte = self.get_uint8()
|
|
while byte != 0:
|
|
cstr += "%c" % byte
|
|
byte = self.get_uint8()
|
|
return cstr
|
|
|
|
def get_n_sint8(self, n, fail_value=0):
|
|
'''Extract "n" int8_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'b', s)
|
|
else:
|
|
return (fail_value,) * n
|
|
|
|
def get_n_uint8(self, n, fail_value=0):
|
|
'''Extract "n" uint8_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'B', s)
|
|
else:
|
|
return (fail_value,) * n
|
|
|
|
def get_n_sint16(self, n, fail_value=0):
|
|
'''Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(2 * n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'h', s)
|
|
else:
|
|
return (fail_value,) * n
|
|
|
|
def get_n_uint16(self, n, fail_value=0):
|
|
'''Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(2 * n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'H', s)
|
|
else:
|
|
return (fail_value,) * n
|
|
|
|
def get_n_sint32(self, n, fail_value=0):
|
|
'''Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(4 * n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'i', s)
|
|
else:
|
|
return (fail_value,) * n
|
|
|
|
def get_n_uint32(self, n, fail_value=0):
|
|
'''Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(4 * n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'I', s)
|
|
else:
|
|
return (fail_value,) * n
|
|
|
|
def get_n_sint64(self, n, fail_value=0):
|
|
'''Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(8 * n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'q', s)
|
|
else:
|
|
return (fail_value,) * n
|
|
|
|
def get_n_uint64(self, n, fail_value=0):
|
|
'''Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers'''
|
|
s = self.read_size(8 * n)
|
|
if s:
|
|
return struct.unpack(self.byte_order + ("%u" % n) + 'Q', s)
|
|
else:
|
|
return (fail_value,) * n
|