forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			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
 |