import ctypes import enum from enum import auto import os from typing import BinaryIO, NamedTuple, Optional, Sequence, Union import drgn from drgn.internal.mock import MockType from tests import _drgn_pydll, _drgn_cdll from tests.libelf import _Elf, Elf from tests.libdw import _Dwarf_Die, Die class _drgn_error(ctypes.Structure): _fields_ = [ ('code', ctypes.c_uint), ('errnum', ctypes.c_int), ('path', ctypes.c_char_p), ('msg', ctypes.c_char_p), ] _drgn_pydll.set_drgn_error.restype = ctypes.py_object _drgn_pydll.set_drgn_error.argtypes = [ctypes.POINTER(_drgn_error)] def _check_err(err): if err: return _drgn_pydll.set_drgn_error(err) class _path_iterator_component(ctypes.Structure): _fields_ = [ ('path', ctypes.c_char_p), ('len', ctypes.c_size_t), ] class _path_iterator(ctypes.Structure): _fields_ = [ ('components', ctypes.POINTER(_path_iterator_component)), ('num_components', ctypes.c_size_t), ('dot_dot', ctypes.c_size_t), ] _drgn_cdll.drgn_test_path_iterator_next.restype = ctypes.c_bool _drgn_cdll.drgn_test_path_iterator_next.argtypes = [ ctypes.POINTER(_path_iterator), ctypes.POINTER(ctypes.POINTER(ctypes.c_char)), ctypes.POINTER(ctypes.c_size_t), ] class PathIterator: def __init__(self, *paths): components = (_path_iterator_component * len(paths))() for i, path in enumerate(paths): path = os.fsencode(path) components[i].path = path components[i].len = len(path) self._it = _path_iterator(components, len(paths)) def __iter__(self): return self def __next__(self): component = ctypes.POINTER(ctypes.c_char)() component_len = ctypes.c_size_t() if _drgn_cdll.drgn_test_path_iterator_next(ctypes.pointer(self._it), ctypes.pointer(component), ctypes.pointer(component_len)): return os.fsdecode(ctypes.string_at(component, component_len.value)) else: raise StopIteration() _drgn_cdll.drgn_test_path_ends_with.restype = ctypes.c_bool _drgn_cdll.drgn_test_path_ends_with.argtypes = [ ctypes.POINTER(_path_iterator), ctypes.POINTER(_path_iterator), ] def path_ends_with(path1: PathIterator, path2: PathIterator): return _drgn_cdll.drgn_test_path_ends_with(ctypes.pointer(path1._it), ctypes.pointer(path2._it)) class _drgn_type(ctypes.Structure): pass class _drgn_qualified_type(ctypes.Structure): _fields_ = [ ('type', ctypes.POINTER(_drgn_type)), ('qualifiers', ctypes.c_uint), ] _drgn_pydll.DrgnType_wrap.restype = ctypes.py_object _drgn_pydll.DrgnType_wrap.argtypes = [_drgn_qualified_type, ctypes.py_object] class _drgn_token(ctypes.Structure): _fields_ = [ ('kind', ctypes.c_int), ('value', ctypes.c_void_p), ('len', ctypes.c_size_t), ] class _drgn_lexer(ctypes.Structure): _fields_ = [ ('func', ctypes.c_void_p), ('p', ctypes.c_void_p), ('stack', ctypes.POINTER(_drgn_token)), ('stack_len', ctypes.c_size_t), ('stack_capacity', ctypes.c_size_t), ] drgn_lexer_func = ctypes.CFUNCTYPE(ctypes.POINTER(_drgn_error), ctypes.POINTER(_drgn_lexer), ctypes.POINTER(_drgn_token)) _drgn_cdll.drgn_test_lexer_init.restype = None _drgn_cdll.drgn_test_lexer_init.argtypes = [ ctypes.POINTER(_drgn_lexer), ctypes.POINTER(drgn_lexer_func), ctypes.c_char_p, ] _drgn_cdll.drgn_test_lexer_deinit.restype = None _drgn_cdll.drgn_test_lexer_deinit.argtypes = [ctypes.POINTER(_drgn_lexer)] _drgn_cdll.drgn_test_lexer_pop.restype = ctypes.POINTER(_drgn_error) _drgn_cdll.drgn_test_lexer_pop.argtypes = [ ctypes.POINTER(_drgn_lexer), ctypes.POINTER(_drgn_token), ] _drgn_cdll.drgn_test_lexer_push.restype = ctypes.POINTER(_drgn_error) _drgn_cdll.drgn_test_lexer_push.argtypes = [ ctypes.POINTER(_drgn_lexer), ctypes.POINTER(_drgn_token), ] _drgn_cdll.drgn_test_lexer_peek.restype = ctypes.POINTER(_drgn_error) _drgn_cdll.drgn_test_lexer_peek.argtypes = [ ctypes.POINTER(_drgn_lexer), ctypes.POINTER(_drgn_token), ] drgn_lexer_c = drgn_lexer_func.in_dll(_drgn_cdll, 'drgn_test_lexer_c') drgn_test_lexer_func = drgn_lexer_func.in_dll(_drgn_cdll, 'drgn_test_lexer_func') class C_TOKEN(enum.IntEnum): EOF = -1 VOID = auto() CHAR = auto() SHORT = auto() INT = auto() LONG = auto() SIGNED = auto() UNSIGNED = auto() BOOL = auto() FLOAT = auto() DOUBLE = auto() COMPLEX = auto() CONST = auto() RESTRICT = auto() VOLATILE = auto() ATOMIC = auto() STRUCT = auto() UNION = auto() ENUM = auto() LPAREN = auto() RPAREN = auto() LBRACKET = auto() RBRACKET = auto() ASTERISK = auto() DOT = auto() NUMBER = auto() IDENTIFIER = auto() class Token: def __init__(self, token): self._token = token @property def kind(self): return self._token.kind @property def value(self): return ctypes.string_at(self._token.value, self._token.len).decode() def __repr__(self): return f'Token({self.kind}, {self.value!r})' class Lexer: def __init__(self, func, str): self._lexer = _drgn_lexer() self._func = func self._str = str.encode() _drgn_cdll.drgn_test_lexer_init(ctypes.pointer(self._lexer), self._func, self._str) def __del__(self): _drgn_cdll.drgn_test_lexer_deinit(ctypes.pointer(self._lexer)) def pop(self): token = _drgn_token() _check_err(_drgn_cdll.drgn_test_lexer_pop(ctypes.pointer(self._lexer), ctypes.pointer(token))) return Token(token) def push(self, token): _check_err(_drgn_cdll.drgn_test_lexer_push(ctypes.pointer(self._lexer), ctypes.pointer(token._token))) def peek(self): token = _drgn_token() _check_err(_drgn_cdll.drgn_test_lexer_peek(ctypes.pointer(self._lexer), ctypes.pointer(token))) return Token(token) _drgn_cdll.drgn_test_serialize_bits.restype = None _drgn_cdll.drgn_test_serialize_bits.argtypes = [ ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint8, ctypes.c_bool, ] _drgn_cdll.drgn_test_deserialize_bits.restype = ctypes.c_uint64 _drgn_cdll.drgn_test_deserialize_bits.argtypes = [ ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint8, ctypes.c_bool, ] def serialize_bits(buf, bit_offset, uvalue, bit_size, little_endian): assert (bit_offset + bit_size + 7) // 8 <= len(buf) c_buf = (ctypes.c_char * len(buf)).from_buffer(buf) return _drgn_cdll.drgn_test_serialize_bits(c_buf, bit_offset, uvalue, bit_size, little_endian) def deserialize_bits(buf, bit_offset, bit_size, little_endian): assert (bit_offset + bit_size + 7) // 8 <= len(buf) c_buf = (ctypes.c_char * len(buf)).from_buffer_copy(buf) return _drgn_cdll.drgn_test_deserialize_bits(c_buf, bit_offset, bit_size, little_endian)