Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions qiling/arch/evm/vm/evm.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@
from .utils import bytecode_to_bytes, runtime_code_detector
from ..abi import QlArchEVMABI

# Code name Release date Release block Opcode supported
# Code name Release date Release block Opcode supported

# Frontier 2015-07-30 0 Yes
# Ice Age 2015-09-08 200,000 -
# Homestead 2016-03-15 1,150,000 Yes
# DAO Fork (unplanned) 2016-07-20 1,920,000 -
# Tangerine Whistle (unplanned) 2016-10-18 2,463,000 Yes
# Spurious Dragon 2016-11-23 2,675,000 Yes
# Byzantium 2017-10-16 4,370,000 Yes
# Constantinople 2019-02-28 7,280,000 Yes
# Petersburg (unplanned) 2019-02-28 7,280,000 Yes
# Istanbul 2019-12-08 9,069,000 Yes
# Muir Glacier 2020-01-01 9,200,000 Yes
# Berlin TBD TBD Yes
# Frontier 2015-07-30 0 Yes
# Ice Age 2015-09-08 200,000 -
# Homestead 2016-03-15 1,150,000 Yes
# DAO Fork (unplanned) 2016-07-20 1,920,000 -
# Tangerine Whistle (unplanned) 2016-10-18 2,463,000 Yes
# Spurious Dragon 2016-11-23 2,675,000 Yes
# Byzantium 2017-10-16 4,370,000 Yes
# Constantinople 2019-02-28 7,280,000 Yes
# Petersburg (unplanned) 2019-02-28 7,280,000 Yes
# Istanbul 2019-12-08 9,069,000 Yes
# Muir Glacier 2020-01-01 9,200,000 Yes
# Berlin TBD TBD Yes


father_VMs = {
Expand Down
228 changes: 114 additions & 114 deletions qiling/cc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,171 +7,171 @@
from qiling.arch.arch import QlArch

class QlCC:
"""Calling convention base class.
"""
"""Calling convention base class.
"""

def __init__(self, arch: QlArch) -> None:
"""Initialize a calling convention instance.
def __init__(self, arch: QlArch) -> None:
"""Initialize a calling convention instance.

Args:
arch: underlying architecture instance
"""
Args:
arch: underlying architecture instance
"""

self.arch = arch
self.arch = arch

@staticmethod
def getNumSlots(argbits: int) -> int:
"""Get the number of slots allocated for an argument of width `argbits`.
"""
@staticmethod
def getNumSlots(argbits: int) -> int:
"""Get the number of slots allocated for an argument of width `argbits`.
"""

raise NotImplementedError
raise NotImplementedError

def getRawParam(self, slot: int, argbits: int = 0) -> int:
"""Read a value of native size from the specified argument slot.
def getRawParam(self, slot: int, argbits: int = 0) -> int:
"""Read a value of native size from the specified argument slot.

Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.

Args:
slot: argument slot to access
argbits: argument size in bits (default: arch native size)
Args:
slot: argument slot to access
argbits: argument size in bits (default: arch native size)

Returns: raw value
"""
Returns: raw value
"""

raise NotImplementedError
raise NotImplementedError

def setRawParam(self, slot: int, value: int, argbits: int = 0) -> None:
"""Replace the value in the specified argument slot.
def setRawParam(self, slot: int, value: int, argbits: int = 0) -> None:
"""Replace the value in the specified argument slot.

Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.
Note that argument slots and argument indexes are not the same. Though they often correlate
to each other, some implementations might use more than one slot to represent a sigle argument.

Args:
slot: argument slot to access
value: new raw value to write
argbits: argument size in bits (default: arch native size)
"""
Args:
slot: argument slot to access
value: new raw value to write
argbits: argument size in bits (default: arch native size)
"""

raise NotImplementedError
raise NotImplementedError

def getReturnValue(self) -> int:
"""Get function return value.
"""
def getReturnValue(self) -> int:
"""Get function return value.
"""

raise NotImplementedError
raise NotImplementedError

def setReturnValue(self, val: int) -> None:
"""Set function return value.
def setReturnValue(self, val: int) -> None:
"""Set function return value.

Args:
val: a value to set
"""
Args:
val: a value to set
"""

raise NotImplementedError
raise NotImplementedError

def setReturnAddress(self, addr: int) -> None:
"""Set function return address.
def setReturnAddress(self, addr: int) -> None:
"""Set function return address.

Args:
addr: return address to set
"""
Args:
addr: return address to set
"""

raise NotImplementedError
raise NotImplementedError

def reserve(self, nslots: int) -> None:
"""Reserve slots for function arguments.
def reserve(self, nslots: int) -> None:
"""Reserve slots for function arguments.

This may be used to stage a new frame before executing a native function.
This may be used to stage a new frame before executing a native function.

Args:
nslots: number of arg slots to reserve
"""
Args:
nslots: number of arg slots to reserve
"""

raise NotImplementedError
raise NotImplementedError

def unwind(self, nslots: int) -> int:
"""Unwind frame and return from function call.
def unwind(self, nslots: int) -> int:
"""Unwind frame and return from function call.

Args:
nslots: number of arg slots used
Args:
nslots: number of arg slots used

Returns: return address
"""
Returns: return address
"""

raise NotImplementedError
raise NotImplementedError

class QlCommonBaseCC(QlCC):
"""Calling convention base class that implements parameters access through both
registers and the stack. The extending class is resopnsible to implement the rest
of the QlCC interface.
"""
"""Calling convention base class that implements parameters access through both
registers and the stack. The extending class is resopnsible to implement the rest
of the QlCC interface.
"""

_retreg: int
_argregs: Sequence
_shadow = 0
_retaddr_on_stack = True
_retreg: int
_argregs: Sequence
_shadow = 0
_retaddr_on_stack = True

def __init__(self, arch: QlArch):
super().__init__(arch)
def __init__(self, arch: QlArch):
super().__init__(arch)

# native address size in bytes
self._asize = self.arch.pointersize
# native address size in bytes
self._asize = self.arch.pointersize

def __access_param(self, index: int, stack_access: Callable, reg_access: Callable) -> Tuple[Callable, int]:
"""[private] Generic accessor to function call parameters by their index.
def __access_param(self, index: int, stack_access: Callable, reg_access: Callable) -> Tuple[Callable, int]:
"""[private] Generic accessor to function call parameters by their index.

This method will determine whether the parameter should be accessed on the stack or in a
register, and return the appropriate accessor along with the location to access (either a
register id or stack address)
This method will determine whether the parameter should be accessed on the stack or in a
register, and return the appropriate accessor along with the location to access (either a
register id or stack address)

Args:
index: parameter index to access
stack_access: stack accessor method (either read or write)
reg_access: regs accessor method (either read or write)
Args:
index: parameter index to access
stack_access: stack accessor method (either read or write)
reg_access: regs accessor method (either read or write)

Returns: a tuple of the accessor method to use and the location to access
"""
Returns: a tuple of the accessor method to use and the location to access
"""

if index >= len(self._argregs):
raise IndexError(f'tried to access arg {index}, but only {len(self._argregs) - 1} args are supported')
if index >= len(self._argregs):
raise IndexError(f'tried to access arg {index}, but only {len(self._argregs) - 1} args are supported')

reg = self._argregs[index]
reg = self._argregs[index]

# should arg be read from a reg or the stack?
if reg is None:
# get matching stack item
si = index - self._argregs.index(None)
# should arg be read from a reg or the stack?
if reg is None:
# get matching stack item
si = index - self._argregs.index(None)

# skip return address and shadow space
return stack_access, (self._retaddr_on_stack + self._shadow + si) * self._asize
else:
return reg_access, reg
# skip return address and shadow space
return stack_access, (self._retaddr_on_stack + self._shadow + si) * self._asize
else:
return reg_access, reg

def getRawParam(self, index: int, argbits: int = 0) -> int:
read, loc = self.__access_param(index, self.arch.stack_read, self.arch.regs.read)
def getRawParam(self, index: int, argbits: int = 0) -> int:
read, loc = self.__access_param(index, self.arch.stack_read, self.arch.regs.read)

mask = (argbits and (1 << argbits)) - 1
mask = (argbits and (1 << argbits)) - 1

return read(loc) & mask
return read(loc) & mask

def setRawParam(self, index: int, value: int, argbits: int = 0) -> None:
write, loc = self.__access_param(index, self.arch.stack_write, self.arch.regs.write)
def setRawParam(self, index: int, value: int, argbits: int = 0) -> None:
write, loc = self.__access_param(index, self.arch.stack_write, self.arch.regs.write)

mask = (argbits and (1 << argbits)) - 1
mask = (argbits and (1 << argbits)) - 1

write(loc, value & mask)
write(loc, value & mask)

def getReturnValue(self) -> int:
return self.arch.regs.read(self._retreg)
def getReturnValue(self) -> int:
return self.arch.regs.read(self._retreg)

def setReturnValue(self, value: int) -> None:
self.arch.regs.write(self._retreg, value)
def setReturnValue(self, value: int) -> None:
self.arch.regs.write(self._retreg, value)

def reserve(self, nslots: int) -> None:
assert nslots < len(self._argregs), 'too many slots'
def reserve(self, nslots: int) -> None:
assert nslots < len(self._argregs), 'too many slots'

# count how many slots should be reserved on the stack
si = self._argregs[:nslots].count(None)
# count how many slots should be reserved on the stack
si = self._argregs[:nslots].count(None)

self.arch.regs.arch_sp -= (self._shadow + si) * self._asize
self.arch.regs.arch_sp -= (self._shadow + si) * self._asize
Loading