1
0

proj/test-return-values: Try to handle fork() correctly

This commit is contained in:
2025-05-07 11:38:32 +02:00
parent f0b18f7e81
commit 478b826c57
3 changed files with 44 additions and 19 deletions

View File

@@ -93,7 +93,7 @@ class Parser:
pid: Optional[int]
tid: Optional[int]
path: Optional[str]
stack: list[tuple[int, int, str, Optional[str], Optional[str], Optional[int], str, tuple]]
stack: dict[tuple[int, int], list[tuple[int, int, str, Optional[str], Optional[str], Optional[int], str, tuple]]]
ret_addr: int
rel_ret_addr: int
dli_file_name: str
@@ -104,7 +104,7 @@ class Parser:
def __init__(self, rfile: BinaryIO, wfile: BinaryIO = None):
self.rfile = rfile
self.wfile = wfile
self.stack = []
self.stack = {}
self.pid = None
self.path = None
@@ -255,14 +255,22 @@ class Parser:
idx += 1
return PointerTo(val, l), idx
else:
m = re.match(r'0x[0-9a-fA-F]+|[0-9]+|\(nil\)', argument[idx:])
if m is not None:
value = m.group(0)
idx += len(value)
if idx < len(argument) and argument[idx] == ',':
idx += 1
value = int(value, 0) if value != '(nil)' else 0
return PointerTo(val, value), idx
m = re.match(r'[A-Z0-9_]+', argument[idx:])
if not m:
raise ValueError()
value = m.group(0)
idx += len(value)
if idx < len(argument) and argument[idx] == ',':
idx += 1
return Constant(val, value), idx
if m is not None:
value = m.group(0)
idx += len(value)
if idx < len(argument) and argument[idx] == ',':
idx += 1
return Constant(val, value), idx
raise ValueError()
@staticmethod
def parse_args(arguments: str, named: bool = False, ret: bool = False) -> tuple[tuple or dict, int]:
@@ -292,6 +300,8 @@ class Parser:
def handle_msg(self, msg: bytes):
timestamp, pid, tid, data = msg.rstrip(b'\n').split(b' ', 3)
self.pid, self.tid = int(pid), int(tid)
if len(self.stack) == 0:
self.stack[(self.pid, self.tid)] = []
if not data.startswith(b'return ') and not data == b'return':
call = data.decode('utf-8')
#print(f'[{self.pid}][{self.tid}] {call}')
@@ -306,11 +316,13 @@ class Parser:
self.src_file_name = src_fname
self.src_line_num = int(src_line, 0) if src_line else None
args, _ = Parser.parse_args(call[call.find('(') + 1:call.rfind(': ') - 1])
self.stack.append(
self.stack[(self.pid, self.tid)].append(
(self.ret_addr, self.rel_ret_addr,
self.dli_file_name, self.dli_sym_name,
self.src_file_name, self.src_line_num,
func_name, args))
if func_name == 'fork':
self.stack[(0, 0)] = self.stack[(self.pid, self.tid)][:]
try:
func = getattr(self, f'before_{func_name}')
if not callable(func):
@@ -338,10 +350,13 @@ class Parser:
other_vals = ret[1].strip() if len(ret) > 1 else ''
if len(other_vals) > 0:
kwargs, _ = Parser.parse_args(other_vals, named=True, ret=True)
if (self.pid, self.tid) not in self.stack:
self.stack[(self.pid, self.tid)] = self.stack[(0, 0)]
del self.stack[(0, 0)]
(self.ret_addr, self.rel_ret_addr,
self.dli_file_name, self.dli_sym_name,
self.src_file_name, self.src_line_num,
func_name, args) = self.stack.pop()
func_name, args) = self.stack[(self.pid, self.tid)].pop()
try:
func = getattr(self, f'after_{func_name}')
if not callable(func):
@@ -354,12 +369,12 @@ class Parser:
if ret_value is None:
func(*args, **kwargs)
else:
func(*args, ret_value, **kwargs)
func(*args, ret_value=ret_value, **kwargs)
except NotImplementedError:
if ret_value is None:
self.after_fallback(func_name, *args, **kwargs)
else:
self.after_fallback(func_name, *args, ret_value, **kwargs)
self.after_fallback(func_name, *args, ret_value=ret_value, **kwargs)
#print(f'[{self.pid}][{self.tid}] -> {ret}')
def before_malloc(self, size: int) -> str:
@@ -658,7 +673,7 @@ class Handler(StreamRequestHandler, Parser):
self.pid = int(meta['PID']) if 'PID' in meta else None
self.path = meta['PATH'] if 'PATH' in meta else None
print(f'Process with PID {self.pid} connected ({self.path})')
self.stack = []
self.stack = {}
self.parse()