9 def __init__(self
, entry
, guest
, host
, parameters
):
10 if not isinstance(entry
, str):
11 raise ValueError(entry
)
12 if not isinstance(guest
, int):
13 raise ValueError(guest
)
14 if not isinstance(parameters
, tuple):
15 raise ValueError(parameters
)
20 self
.__parameters
= parameters
22 return super().__init
__()
37 return len(self
.__parameters
)
40 return f
"{self.__class__.__name__}({self.entry} {self.guest}=>{self.host})"
42 def __call__(self
, *arguments
):
43 if len(arguments
) < len(self
):
44 raise ValueError("conflict between arguments and parameters")
46 for index
in range(len(arguments
)):
47 value
= arguments
[index
]
48 if not isinstance(value
, int):
49 raise ValueError("integer argument expected")
51 libc
= ctypes
.CDLL(None)
52 syscall
= libc
.syscall
53 restype
= syscall
.restype
54 argtypes
= syscall
.argtypes
55 syscall
.restype
= ctypes
.c_long
56 syscall
.argtypes
= ([ctypes
.c_long
] * len(arguments
))
57 res
= int(syscall(ctypes
.c_long(self
.host
), *map(ctypes
.c_long
, arguments
)))
58 syscall
.restype
= restype
59 syscall
.argtypes
= argtypes
63 class UnimplementedSyscall(Syscall
):
64 def __init__(self
, guest
):
65 return super().__init
__(entry
="sys_ni_syscall", guest
=guest
, host
=-1, parameters
=tuple())
67 def __call__(self
, *arguments
):
71 class UnknownSyscall(Syscall
):
72 def __init__(self
, entry
, guest
):
73 return super().__init
__(entry
=entry
, guest
=guest
, host
=-1, parameters
=tuple())
75 def __call__(self
, *arguments
):
80 def __init__(self
, guest
, host
, logger
=None, table
=None):
82 path
= (pathlib
.Path(__file__
).parent
/ "syscalls.json")
83 with
open(path
, "r", encoding
="UTF-8") as stream
:
84 table
= json
.load(stream
)
85 if not isinstance(table
, dict):
86 raise ValueError("dict instance expected")
87 if "sysnums" not in table
or "sysargs" not in table
:
88 raise ValueError("sysnums and sysargs keys expected")
91 logger
= lambda *args
, **kwargs
: None
94 yield from sysnums
["x86-32"]["i386"].items()
97 yield from sysnums
["x86-64"]["common"].items()
98 yield from sysnums
["x86-64"]["64"].items()
101 yield from sysnums
["ppc"]["nospu"].items()
102 yield from sysnums
["ppc"]["common"].items()
103 yield from sysnums
["ppc"]["32"].items()
106 yield from sysnums
["ppc"]["nospu"].items()
107 yield from sysnums
["ppc"]["common"].items()
108 yield from sysnums
["ppc"]["64"].items()
110 def riscv32(sysnums
):
111 yield from sysnums
["generic"]["arch32"].items()
113 def riscv64(sysnums
):
114 yield from sysnums
["generic"]["arch64"].items()
124 sysnums
= table
["sysnums"]
125 sysargs
= table
["sysargs"]
127 self
.__guest
= dict(arch
[guest
](sysnums
))
128 self
.__host
= dict(arch
[host
](sysnums
))
129 self
.__parameters
= sysargs
130 self
.__logger
= logger
131 self
.__libc
= ctypes
.CDLL(None)
133 return super().__init
__()
136 identifiers
= sorted(map(int, filter(str.isnumeric
, self
.__guest
)))
137 for identifier
in identifiers
:
138 entry
= self
.__guest
[str(identifier
)][1][0]
139 name
= self
.__guest
[str(identifier
)][0]
140 syscall
= getattr(self
, entry
, None)
142 if entry
== "sys_ni_syscall":
143 syscall
= UnimplementedSyscall(guest
=identifier
)
145 syscall
= UnknownSyscall(entry
=entry
, guest
=identifier
)
148 def __getitem__(self
, identifier
):
149 if not isinstance(identifier
, int):
150 raise ValueError(identifier
)
152 identifier
= str(identifier
)
153 entry
= self
.__guest
[identifier
][1][0]
155 return getattr(self
, entry
)
157 def __getattr__(self
, entry
):
158 if entry
.startswith("compat_sys_"):
159 identifier
= entry
[len("compat_sys_"):]
160 elif entry
.startswith("sys_"):
161 identifier
= entry
[len("sys_"):]
163 raise AttributeError(entry
)
165 if entry
not in self
.__parameters
:
166 raise AttributeError(entry
)
168 if identifier
not in self
.__guest
:
169 raise AttributeError(entry
)
171 if identifier
not in self
.__host
:
172 raise AttributeError(entry
)
174 guest
= int(self
.__guest
[identifier
])
175 host
= int(self
.__host
[identifier
])
176 parameters
= tuple(self
.__parameters
[entry
].items())
178 return Syscall(entry
=entry
, guest
=guest
, host
=host
, parameters
=parameters
)
180 def __call__(self
, identifier
, *arguments
):
181 syscall
= self
[identifier
]
183 return syscall(*arguments
)