Skip to content

Commit

Permalink
homebrew arches
Browse files Browse the repository at this point in the history
  • Loading branch information
rhelmot committed Mar 23, 2023
1 parent de57b57 commit 889fc6e
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 9 deletions.
30 changes: 30 additions & 0 deletions pyvex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@
__version__ = "9.2.44.dev0"

from . import const, expr, stmt
from .arches import (
ARCH_AMD64,
ARCH_ARM64_BE,
ARCH_ARM64_LE,
ARCH_ARM_BE,
ARCH_ARM_LE,
ARCH_MIPS32_BE,
ARCH_MIPS32_LE,
ARCH_MIPS64_BE,
ARCH_MIPS64_LE,
ARCH_PPC32,
ARCH_PPC64_BE,
ARCH_PPC64_LE,
ARCH_S390X,
ARCH_X86,
)
from .block import IRSB, IRTypeEnv
from .const import get_type_size, get_type_spec_size, tag_to_const_class
from .enums import (
Expand Down Expand Up @@ -54,4 +70,18 @@
"IRStmt",
"IRExpr",
"IRConst",
"ARCH_X86",
"ARCH_AMD64",
"ARCH_ARM_LE",
"ARCH_ARM_BE",
"ARCH_ARM64_LE",
"ARCH_ARM64_BE",
"ARCH_PPC32",
"ARCH_PPC64_BE",
"ARCH_PPC64_LE",
"ARCH_S390X",
"ARCH_MIPS32_BE",
"ARCH_MIPS32_LE",
"ARCH_MIPS64_BE",
"ARCH_MIPS64_LE",
]
78 changes: 78 additions & 0 deletions pyvex/arches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from typing import Dict, List, Tuple

from .enums import default_vex_archinfo, vex_endness_from_string
from .types import Register
from .vex_ffi import guest_offsets


class PyvexArch:
def __init__(self, name: str, bits: int, memory_endness: str):
self.name = name
self.bits = bits
self.memory_endness = memory_endness
self.instruction_endness = "Iend_BE"
self.byte_width = 8
self.register_list: List[Register] = []
self.registers: Dict[str, Tuple[int, int]] = {}
self.vex_arch = {
"X86": "VexArchX86",
"AMD64": "VexArchAMD64",
"ARM": "VexArchARM",
"AArch64": "VexArchARM64",
"PPC32": "VexArchPPC32",
"PPC64": "VexArchPPC64",
"S390X": "VexArchS390X",
"MIPS32": "VexArchMIPS32",
"MIPS64": "VexArchMIPS64",
}[name]
self.ip_offset = guest_offsets[
(
self.vex_name_small,
{
"X86": "eip",
"AMD64": "rip",
"ARM": "r15t",
"AArch64": "pc",
"PPC32": "cia",
"PPC64": "cia",
"S390X": "ia",
"MIPS32": "pc",
"MIPS64": "pc",
}[name],
)
]
self.vex_archinfo = default_vex_archinfo()
if memory_endness == "Iend_BE":
self.vex_archinfo["endness"] = vex_endness_from_string("VexEndnessBE")

def __repr__(self):
return f"<PyvexArch {self.name}"

@property
def vex_name_small(self):
return self.vex_arch[7:].lower()

def translate_register_name(self, offset, size=None):
for (arch, reg), offset2 in guest_offsets.items():
if arch == self.vex_name_small and offset2 == offset:
return reg
return None

def get_register_offset(self, name: str) -> int:
return guest_offsets[(self.vex_name_small, name)]


ARCH_X86 = PyvexArch("X86", 32, "Iend_LE")
ARCH_AMD64 = PyvexArch("AMD64", 64, "Iend_LE")
ARCH_ARM_LE = PyvexArch("ARM", 32, "Iend_LE")
ARCH_ARM_BE = PyvexArch("ARM", 32, "Iend_LE")
ARCH_ARM64_LE = PyvexArch("AArch64", 64, "Iend_LE")
ARCH_ARM64_BE = PyvexArch("AArch64", 64, "Iend_BE")
ARCH_PPC32 = PyvexArch("PPC32", 32, "Iend_BE")
ARCH_PPC64_BE = PyvexArch("PPC64", 64, "Iend_BE")
ARCH_PPC64_LE = PyvexArch("PPC64", 64, "Iend_LE")
ARCH_S390X = PyvexArch("S390X", 64, "Iend_BE")
ARCH_MIPS32_BE = PyvexArch("MIPS32", 32, "Iend_BE")
ARCH_MIPS32_LE = PyvexArch("MIPS32", 32, "Iend_LE")
ARCH_MIPS64_BE = PyvexArch("MIPS64", 64, "Iend_BE")
ARCH_MIPS64_LE = PyvexArch("MIPS64", 64, "Iend_LE")
4 changes: 2 additions & 2 deletions pyvex/const.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import re
from typing import List
from typing import List, Optional

from .enums import VEXObject, get_enum_from_int
from .errors import PyVEXError
Expand All @@ -11,7 +11,7 @@ class IRConst(VEXObject):
__slots__ = ["_value"]

type: str
size: int
size: Optional[int] = None
tag: str
c_constructor = None
_value: int
Expand Down
15 changes: 8 additions & 7 deletions pyvex/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ def __eq__(self, other):

def __hash__(self):
values = [getattr(self, slot) for slot in self.__slots__]
for i in range(len(values)):
if isinstance(values[i], list):
values[i] = tuple(values[i])
for i, lst_val in enumerate(values):
if isinstance(lst_val, list):
values[i] = tuple(lst_val)
return stable_hash(tuple([type(self)] + values))


Expand Down Expand Up @@ -55,7 +55,7 @@ def _from_c(c_callee):

@staticmethod
def _to_c(callee): # pylint: disable=unused-argument
raise Exception(
raise TypeError(
"This doesn't work! Please invent a way to get the correct address for the named function from pyvex_c."
)
# c_callee = pvc.mkIRCallee(callee.regparms,
Expand Down Expand Up @@ -109,8 +109,11 @@ def get_int_from_enum(e):
return enums_to_ints[e]


_add_enum_counter = 0


def _add_enum(s, i=None): # TODO get rid of this
global _add_enum_counter
global _add_enum_counter # pylint: disable=global-statement
if i is None:
while _add_enum_counter in ints_to_enums:
_add_enum_counter += 1
Expand All @@ -125,8 +128,6 @@ def _add_enum(s, i=None): # TODO get rid of this
irop_enums_to_ints[s] = i


_add_enum_counter = 0

for attr in dir(pvc):
if attr[0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" and hasattr(pvc, attr) and isinstance(getattr(pvc, attr), int):
_add_enum(attr, getattr(pvc, attr))
Expand Down
12 changes: 12 additions & 0 deletions pyvex/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,18 @@


class Register(Protocol):
"""
A register. Pyvex should probably not have this dependency.
"""

name: str


class Arch(Protocol):
"""
An architecture description.
"""

name: str
ip_offset: int
bits: int
Expand All @@ -26,6 +34,10 @@ def get_register_offset(self, name: str) -> int:

@runtime_checkable
class LibvexArch(Protocol):
"""
The description for an architecture that is usable with libvex
"""

vex_arch: str
vex_archinfo: Dict[str, Any]

Expand Down

0 comments on commit 889fc6e

Please sign in to comment.