miasm.core.utils module
from __future__ import print_function import sys from builtins import range import struct import inspect try: from collections.abc import MutableMapping as DictMixin except ImportError: from collections import MutableMapping as DictMixin from operator import itemgetter import codecs from future.utils import viewitems import collections upck8 = lambda x: struct.unpack('B', x)[0] upck16 = lambda x: struct.unpack('H', x)[0] upck32 = lambda x: struct.unpack('I', x)[0] upck64 = lambda x: struct.unpack('Q', x)[0] pck8 = lambda x: struct.pack('B', x) pck16 = lambda x: struct.pack('H', x) pck32 = lambda x: struct.pack('I', x) pck64 = lambda x: struct.pack('Q', x) # Little endian upck8le = lambda x: struct.unpack('<B', x)[0] upck16le = lambda x: struct.unpack('<H', x)[0] upck32le = lambda x: struct.unpack('<I', x)[0] upck64le = lambda x: struct.unpack('<Q', x)[0] pck8le = lambda x: struct.pack('<B', x) pck16le = lambda x: struct.pack('<H', x) pck32le = lambda x: struct.pack('<I', x) pck64le = lambda x: struct.pack('<Q', x) # Big endian upck8be = lambda x: struct.unpack('>B', x)[0] upck16be = lambda x: struct.unpack('>H', x)[0] upck32be = lambda x: struct.unpack('>I', x)[0] upck64be = lambda x: struct.unpack('>Q', x)[0] pck8be = lambda x: struct.pack('>B', x) pck16be = lambda x: struct.pack('>H', x) pck32be = lambda x: struct.pack('>I', x) pck64be = lambda x: struct.pack('>Q', x) LITTLE_ENDIAN = 1 BIG_ENDIAN = 2 pck = {8: pck8, 16: pck16, 32: pck32, 64: pck64} def get_caller_name(caller_num=0): """Get the nth caller's name @caller_num: 0 = the caller of get_caller_name, 1 = next parent, ...""" pystk = inspect.stack() if len(pystk) > 1 + caller_num: return pystk[1 + caller_num][3] else: return "Bad caller num" def whoami(): """Returns the caller's name""" return get_caller_name(1) class Disasm_Exception(Exception): pass def printable(string): if isinstance(string, bytes): return "".join( c.decode() if b" " <= c < b"~" else "." for c in (string[i:i+1] for i in range(len(string))) ) return string def force_bytes(value): if isinstance(value, bytes): return value if not isinstance(value, str): return value out = [] for c in value: c = ord(c) assert c < 0x100 out.append(c) return bytes(out) def force_str(value): if isinstance(value, str): return value elif isinstance(value, bytes): out = "" for i in range(len(value)): # For Python2/Python3 compatibility c = ord(value[i:i+1]) out += chr(c) value = out else: raise ValueError("Unsupported type") return value def iterbytes(string): for i in range(len(string)): yield string[i:i+1] def int_to_byte(value): return struct.pack('B', value) def cmp_elts(elt1, elt2): return (elt1 > elt2) - (elt1 < elt2) _DECODE_HEX = codecs.getdecoder("hex_codec") _ENCODE_HEX = codecs.getencoder("hex_codec") def decode_hex(value): return _DECODE_HEX(value)[0] def encode_hex(value): return _ENCODE_HEX(value)[0] def size2mask(size): """Return the bit mask of size @size""" return (1 << size) - 1 def hexdump(src, length=16): lines = [] for c in range(0, len(src), length): chars = src[c:c + length] hexa = ' '.join("%02x" % ord(x) for x in iterbytes(chars)) printable = ''.join( x.decode() if 32 <= ord(x) <= 126 else '.' for x in iterbytes(chars) ) lines.append("%04x %-*s %s\n" % (c, length * 3, hexa, printable)) print(''.join(lines)) # stackoverflow.com/questions/2912231 class keydefaultdict(collections.defaultdict): def __missing__(self, key): if self.default_factory is None: raise KeyError(key) value = self[key] = self.default_factory(key) return value class BoundedDict(DictMixin): """Limited in size dictionary. To reduce combinatory cost, once an upper limit @max_size is reached, @max_size - @min_size elements are suppressed. The targeted elements are the less accessed. One can define a callback called when an element is removed """ def __init__(self, max_size, min_size=None, initialdata=None, delete_cb=None): """Create a BoundedDict @max_size: maximum size of the dictionary @min_size: (optional) number of most used element to keep when resizing @initialdata: (optional) dict instance with initial data @delete_cb: (optional) callback called when an element is removed """ self._data = initialdata.copy() if initialdata else {} self._min_size = min_size if min_size else max_size // 3 self._max_size = max_size self._size = len(self._data) # Do not use collections.Counter as it is quite slow self._counter = {k: 1 for k in self._data} self._delete_cb = delete_cb def __setitem__(self, asked_key, value): if asked_key not in self._data: # Update internal size and use's counter self._size += 1 # Bound can only be reached on a new element if (self._size >= self._max_size): most_common = sorted( viewitems(self._counter), key=itemgetter(1), reverse=True ) # Handle callback if self._delete_cb is not None: for key, _ in most_common[self._min_size - 1:]: self._delete_cb(key) # Keep only the most @_min_size used self._data = {key: self._data[key] for key, _ in most_common[:self._min_size - 1]} self._size = self._min_size # Reset use's counter self._counter = {k: 1 for k in self._data} # Avoid rechecking in dict: set to 1 here, add 1 otherwise self._counter[asked_key] = 1 else: self._counter[asked_key] += 1 self._data[asked_key] = value def __contains__(self, key): # Do not call has_key to avoid adding function call overhead return key in self._data def has_key(self, key): return key in self._data def keys(self): "Return the list of dict's keys" return list(self._data) @property def data(self): "Return the current instance as a dictionary" return self._data def __getitem__(self, key): # Retrieve data first to raise the proper exception on error data = self._data[key] # Should never raise, since the key is in self._data self._counter[key] += 1 return data def __delitem__(self, key): if self._delete_cb is not None: self._delete_cb(key) del self._data[key] self._size -= 1 del self._counter[key] def __del__(self): """Ensure the callback is called when last reference is lost""" if self._delete_cb: for key in self._data: self._delete_cb(key) def __len__(self): return len(self._data) def __iter__(self): return iter(self._data) def find_free_name(loc_db, name): """ If @name is not known in DB, return it Else append an index to it corresponding to the next unknown name @name: string """ if loc_db.get_name_location(name) is None: return name i = 0 while True: new_name = "%s_%d" % (name, i) if loc_db.get_name_location(new_name) is None: return new_name i += 1
Module variables
var BIG_ENDIAN
var LITTLE_ENDIAN
var pck
Functions
def cmp_elts(
elt1, elt2)
def cmp_elts(elt1, elt2): return (elt1 > elt2) - (elt1 < elt2)
def decode_hex(
value)
def decode_hex(value): return _DECODE_HEX(value)[0]
def encode_hex(
value)
def encode_hex(value): return _ENCODE_HEX(value)[0]
def find_free_name(
loc_db, name)
If @name is not known in DB, return it Else append an index to it corresponding to the next unknown name
@name: string
def find_free_name(loc_db, name): """ If @name is not known in DB, return it Else append an index to it corresponding to the next unknown name @name: string """ if loc_db.get_name_location(name) is None: return name i = 0 while True: new_name = "%s_%d" % (name, i) if loc_db.get_name_location(new_name) is None: return new_name i += 1
def force_bytes(
value)
def force_bytes(value): if isinstance(value, bytes): return value if not isinstance(value, str): return value out = [] for c in value: c = ord(c) assert c < 0x100 out.append(c) return bytes(out)
def force_str(
value)
def force_str(value): if isinstance(value, str): return value elif isinstance(value, bytes): out = "" for i in range(len(value)): # For Python2/Python3 compatibility c = ord(value[i:i+1]) out += chr(c) value = out else: raise ValueError("Unsupported type") return value
def get_caller_name(
caller_num=0)
Get the nth caller's name @caller_num: 0 = the caller of get_caller_name, 1 = next parent, ...
def get_caller_name(caller_num=0): """Get the nth caller's name @caller_num: 0 = the caller of get_caller_name, 1 = next parent, ...""" pystk = inspect.stack() if len(pystk) > 1 + caller_num: return pystk[1 + caller_num][3] else: return "Bad caller num"
def hexdump(
src, length=16)
def hexdump(src, length=16): lines = [] for c in range(0, len(src), length): chars = src[c:c + length] hexa = ' '.join("%02x" % ord(x) for x in iterbytes(chars)) printable = ''.join( x.decode() if 32 <= ord(x) <= 126 else '.' for x in iterbytes(chars) ) lines.append("%04x %-*s %s\n" % (c, length * 3, hexa, printable)) print(''.join(lines))
def int_to_byte(
value)
def int_to_byte(value): return struct.pack('B', value)
def iterbytes(
string)
def iterbytes(string): for i in range(len(string)): yield string[i:i+1]
def pck16(
x)
pck16 = lambda x: struct.pack('H', x)
def pck16be(
x)
pck16be = lambda x: struct.pack('>H', x)
def pck16le(
x)
pck16le = lambda x: struct.pack('<H', x)
def pck32(
x)
pck32 = lambda x: struct.pack('I', x)
def pck32be(
x)
pck32be = lambda x: struct.pack('>I', x)
def pck32le(
x)
pck32le = lambda x: struct.pack('<I', x)
def pck64(
x)
pck64 = lambda x: struct.pack('Q', x)
def pck64be(
x)
pck64be = lambda x: struct.pack('>Q', x)
def pck64le(
x)
pck64le = lambda x: struct.pack('<Q', x)
def pck8(
x)
pck8 = lambda x: struct.pack('B', x)
def pck8be(
x)
pck8be = lambda x: struct.pack('>B', x)
def pck8le(
x)
pck8le = lambda x: struct.pack('<B', x)
def printable(
string)
def printable(string): if isinstance(string, bytes): return "".join( c.decode() if b" " <= c < b"~" else "." for c in (string[i:i+1] for i in range(len(string))) ) return string
def size2mask(
size)
Return the bit mask of size @size
def size2mask(size): """Return the bit mask of size @size""" return (1 << size) - 1
def upck16(
x)
upck16 = lambda x: struct.unpack('H', x)[0]
def upck16be(
x)
upck16be = lambda x: struct.unpack('>H', x)[0]
def upck16le(
x)
upck16le = lambda x: struct.unpack('<H', x)[0]
def upck32(
x)
upck32 = lambda x: struct.unpack('I', x)[0]
def upck32be(
x)
upck32be = lambda x: struct.unpack('>I', x)[0]
def upck32le(
x)
upck32le = lambda x: struct.unpack('<I', x)[0]
def upck64(
x)
upck64 = lambda x: struct.unpack('Q', x)[0]
def upck64be(
x)
upck64be = lambda x: struct.unpack('>Q', x)[0]
def upck64le(
x)
upck64le = lambda x: struct.unpack('<Q', x)[0]
def upck8(
x)
upck8 = lambda x: struct.unpack('B', x)[0]
def upck8be(
x)
upck8be = lambda x: struct.unpack('>B', x)[0]
def upck8le(
x)
upck8le = lambda x: struct.unpack('<B', x)[0]
def whoami(
)
Returns the caller's name
def whoami(): """Returns the caller's name""" return get_caller_name(1)
Classes
class BoundedDict
Limited in size dictionary.
To reduce combinatory cost, once an upper limit @max_size is reached, @max_size - @min_size elements are suppressed. The targeted elements are the less accessed.
One can define a callback called when an element is removed
class BoundedDict(DictMixin): """Limited in size dictionary. To reduce combinatory cost, once an upper limit @max_size is reached, @max_size - @min_size elements are suppressed. The targeted elements are the less accessed. One can define a callback called when an element is removed """ def __init__(self, max_size, min_size=None, initialdata=None, delete_cb=None): """Create a BoundedDict @max_size: maximum size of the dictionary @min_size: (optional) number of most used element to keep when resizing @initialdata: (optional) dict instance with initial data @delete_cb: (optional) callback called when an element is removed """ self._data = initialdata.copy() if initialdata else {} self._min_size = min_size if min_size else max_size // 3 self._max_size = max_size self._size = len(self._data) # Do not use collections.Counter as it is quite slow self._counter = {k: 1 for k in self._data} self._delete_cb = delete_cb def __setitem__(self, asked_key, value): if asked_key not in self._data: # Update internal size and use's counter self._size += 1 # Bound can only be reached on a new element if (self._size >= self._max_size): most_common = sorted( viewitems(self._counter), key=itemgetter(1), reverse=True ) # Handle callback if self._delete_cb is not None: for key, _ in most_common[self._min_size - 1:]: self._delete_cb(key) # Keep only the most @_min_size used self._data = {key: self._data[key] for key, _ in most_common[:self._min_size - 1]} self._size = self._min_size # Reset use's counter self._counter = {k: 1 for k in self._data} # Avoid rechecking in dict: set to 1 here, add 1 otherwise self._counter[asked_key] = 1 else: self._counter[asked_key] += 1 self._data[asked_key] = value def __contains__(self, key): # Do not call has_key to avoid adding function call overhead return key in self._data def has_key(self, key): return key in self._data def keys(self): "Return the list of dict's keys" return list(self._data) @property def data(self): "Return the current instance as a dictionary" return self._data def __getitem__(self, key): # Retrieve data first to raise the proper exception on error data = self._data[key] # Should never raise, since the key is in self._data self._counter[key] += 1 return data def __delitem__(self, key): if self._delete_cb is not None: self._delete_cb(key) del self._data[key] self._size -= 1 del self._counter[key] def __del__(self): """Ensure the callback is called when last reference is lost""" if self._delete_cb: for key in self._data: self._delete_cb(key) def __len__(self): return len(self._data) def __iter__(self): return iter(self._data)
Ancestors (in MRO)
- BoundedDict
- collections.abc.MutableMapping
- collections.abc.Mapping
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- builtins.object
Static methods
def __init__(
self, max_size, min_size=None, initialdata=None, delete_cb=None)
Create a BoundedDict @max_size: maximum size of the dictionary @min_size: (optional) number of most used element to keep when resizing @initialdata: (optional) dict instance with initial data @delete_cb: (optional) callback called when an element is removed
def __init__(self, max_size, min_size=None, initialdata=None, delete_cb=None): """Create a BoundedDict @max_size: maximum size of the dictionary @min_size: (optional) number of most used element to keep when resizing @initialdata: (optional) dict instance with initial data @delete_cb: (optional) callback called when an element is removed """ self._data = initialdata.copy() if initialdata else {} self._min_size = min_size if min_size else max_size // 3 self._max_size = max_size self._size = len(self._data) # Do not use collections.Counter as it is quite slow self._counter = {k: 1 for k in self._data} self._delete_cb = delete_cb
def clear(
self)
D.clear() -> None. Remove all items from D.
def clear(self): 'D.clear() -> None. Remove all items from D.' try: while True: self.popitem() except KeyError: pass
def get(
self, key, default=None)
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
def get(self, key, default=None): 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' try: return self[key] except KeyError: return default
def has_key(
self, key)
def has_key(self, key): return key in self._data
def items(
self)
D.items() -> a set-like object providing a view on D's items
def items(self): "D.items() -> a set-like object providing a view on D's items" return ItemsView(self)
def keys(
self)
Return the list of dict's keys
def keys(self): "Return the list of dict's keys" return list(self._data)
def pop(
self, key, default=<object object at 0x7f33ffb2b140>)
D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised.
def pop(self, key, default=__marker): '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised. ''' try: value = self[key] except KeyError: if default is self.__marker: raise return default else: del self[key] return value
def popitem(
self)
D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty.
def popitem(self): '''D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty. ''' try: key = next(iter(self)) except StopIteration: raise KeyError from None value = self[key] del self[key] return key, value
def setdefault(
self, key, default=None)
D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
def setdefault(self, key, default=None): 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' try: return self[key] except KeyError: self[key] = default return default
def update(
self, other=(), **kwds)
D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v
def update(self, other=(), /, **kwds): ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v ''' if isinstance(other, Mapping): for key in other: self[key] = other[key] elif hasattr(other, "keys"): for key in other.keys(): self[key] = other[key] else: for key, value in other: self[key] = value for key, value in kwds.items(): self[key] = value
def values(
self)
D.values() -> an object providing a view on D's values
def values(self): "D.values() -> an object providing a view on D's values" return ValuesView(self)
Instance variables
var data
Return the current instance as a dictionary
class Disasm_Exception
Common base class for all non-exit exceptions.
class Disasm_Exception(Exception): pass
Ancestors (in MRO)
- Disasm_Exception
- builtins.Exception
- builtins.BaseException
- builtins.object
Class variables
var args
class keydefaultdict
defaultdict(default_factory[, ...]) --> dict with default factory
The default factory is called without arguments to produce a new value when a key is not present, in getitem only. A defaultdict compares equal to a dict with the same items. All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments.
class keydefaultdict(collections.defaultdict): def __missing__(self, key): if self.default_factory is None: raise KeyError(key) value = self[key] = self.default_factory(key) return value
Ancestors (in MRO)
- keydefaultdict
- collections.defaultdict
- builtins.dict
- builtins.object
Class variables
var default_factory