def test_struct_typedefs(): structs = dump_struct_layout( "struct s { int y; }; typedef struct s s_t; struct x { s_t s1; };", None) assert len(structs.keys()) == 2 x = structs["x"].fields assert x["s1"] == (0, StructField(32, "s")) # not by typedef assert "s" in structs assert "s_t" not in structs structs = dump_struct_layout( "typedef struct { int y; } s_t; struct x { s_t s1; };", None) assert len(structs.keys()) == 2 x = structs["x"].fields assert x["s1"] == (0, StructField(32, "s_t")) assert "s" not in structs assert "s_t" in structs # also for enums, they have special treatment x = dump_struct_layout( "typedef enum { y = 1, } e_t; struct x { e_t e1; };", "x")["x"].fields assert x["e1"] == (0, Scalar(32, "e_t", False)) x = dump_struct_layout( "typedef enum e { y = 1, } e_t; struct x { e_t e1; };", "x")["x"].fields assert x["e1"] == (0, Scalar(32, "e", False))
def test_struct_array_flexible_and_zero(): s = dump_struct_layout("struct x { int arr[0]; };", "x")["x"].fields assert len(s.keys()) == 1 assert s["arr"] == (0, Array(0, 0, Scalar(32, "int", True))) # flexible array can't be the first field. s = dump_struct_layout("struct x { int y; int arr[]; };", "x")["x"].fields assert len(s.keys()) == 2 assert s["y"] == (0, Scalar(32, "int", True)) assert s["arr"] == (32, Array(0, 0, Scalar(32, "int", True)))
def test_struct_dump_all(): decls = dump_struct_layout("struct a { int x; }; struct b { int y; };", None) b = decls["b"].fields assert len(b.keys()) == 1 assert b["y"] == (0, Scalar(32, "int", True)) b = decls["a"].fields assert len(b.keys()) == 1 assert b["x"] == (0, Scalar(32, "int", True))
def test_struct_union(): structs = dump_struct_layout( "union u { int x; char c; long l; }; struct c { union u u; };", "c") c = structs["c"].fields assert len(c.keys()) == 1 assert c["u"] == (0, StructField(64, "u")) u = structs["u"] assert u.total_size == 64 u = u.fields assert len(u.keys()) == 3 assert u["x"] == (0, Scalar(32, "int", True)) assert u["c"] == (0, Scalar(8, "char", True)) assert u["l"] == (0, Scalar(64, "long int", True))
def test_struct_struct(): s = (dump_struct_layout( "struct a { int x; }; struct b { struct a aa; int xx; };", "b")["b"].fields) assert len(s.keys()) == 2 assert s["aa"] == (0, StructField(32, "a")) assert s["xx"] == (32, Scalar(32, "int", True))
def test_struct_dump_only_necessary(): structs = dump_struct_layout("struct a { int x; }; struct b { int y; };", "b") b = structs["b"].fields assert len(b.keys()) == 1 assert b["y"] == (0, Scalar(32, "int", True)) assert "a" not in structs
class ArrayPtr(object): CHAR_TYPE = Scalar(8, "char", True) def __init__(self, base, num_elem, elem_type): self.____ptr = base self._num_elem = num_elem or None self._elem_type = elem_type def __check_index(self, key): if self._num_elem and not (0 <= key < self._num_elem): raise IndexError("Index {!r} not in range: 0 - {!r}".format( key, self._num_elem - 1)) def __getitem__(self, key): self.__check_index(key) return _read_accessor(self._elem_type, self.____ptr, key * self._elem_type.total_size) def __setitem__(self, key, value): self.__check_index(key) return _write_accessor(self._elem_type, self.____ptr, key * self._elem_type.total_size, value) def __eq__(self, other): if not isinstance(other, ArrayPtr): return NotImplemented return (self.____ptr == other.____ptr and self._num_elem == other._num_elem and self._elem_type == other._elem_type) def __len__(self): return self._num_elem def __repr__(self): return "ArrayPtr(0x{:x}, {!r}, {!r})".format(self.____ptr, self._num_elem, self._elem_type) def __int__(self): return self.____ptr def read(self, n=None): n = n if n is not None else self._num_elem items = [] for i in range(n): items.append(self[i]) if self._elem_type == ArrayPtr.CHAR_TYPE: # special case: if type is "char", convert to string s = "".join(map(chr, items)) if s.find('\x00') != -1: s = s[:s.find('\x00')] return s else: return items
def test_accessor_pointer(): set_memory_struct(">QL", MEM_BASE + 8, 5) s = partial_struct( dump_struct_layout("struct x { int *ptr; int x; };", "x")["x"])(MEM_BASE) assert s.x == 5 assert s.ptr == Ptr(Scalar(32, "int", True), MEM_BASE + 8) assert s.ptr.p() == 5
def test_struct_pointer(): s = dump_struct_layout("struct x { void *p; void **h; const int ***z; };", "x")["x"].fields assert len(s.keys()) == 3 assert s["p"] == (0, Pointer(64, Void())) assert s["h"] == (64, Pointer(64, Pointer(64, Void()))) assert s["z"] == (128, Pointer( 64, Pointer(64, Pointer(64, Scalar(32, "int", True)))))
def test_struct_bitfields(): x = (dump_struct_layout( "struct x { int bf1: 3; int:5; int bf2: 1; int n; int bf3: 29; unsigned int bf4: 1; };", "x")["x"].fields) assert len(x.keys()) == 5 assert x["bf1"] == (0, Bitfield(3, True)) assert x["bf2"] == (8, Bitfield(1, True)) assert x["n"] == (32, Scalar(32, "int", True)) assert x["bf3"] == (64, Bitfield(29, True)) assert x["bf4"] == (93, Bitfield(1, False))
def test_accessor_pointer_to_array(): set_memory_struct(">Q3L", MEM_BASE + 8, 0, 1, 2) s = partial_struct( dump_struct_layout("struct x { int (*aptr)[3]; };", "x")["x"])(MEM_BASE) assert s.aptr == ArrayPtr(MEM_BASE + 8, 3, Scalar(32, "int", True)) assert s.aptr[0] == 0 assert s.aptr[1] == 1 assert s.aptr[2] == 2
def test_struct_recursive_dump(): structs = dump_struct_layout( "struct a { int x; }; struct b { struct a a; }; ", "b") b = structs["b"].fields assert len(b.keys()) == 1 assert b["a"] == (0, StructField(32, "a")) a = structs[b["a"][1].type].fields assert len(a.keys()) == 1 assert a["x"] == (0, Scalar(32, "int", True))
def test_accessor_set_pointer(): set_memory_struct(">QL", 0, 5) s = partial_struct( dump_struct_layout("struct x { int *ptr; int x; };", "x")["x"])(MEM_BASE) assert s.ptr == Ptr(Scalar(32, "int", True), 0) s.ptr = MEM_BASE + 8 assert s.ptr[0] == s.x
def test_struct_array_two_dimensions(): s = dump_struct_layout("struct x { int arr[5][2]; };", "x")["x"].fields assert len(s.keys()) == 1 assert s["arr"] == (0, Array(5 * 2 * 32, 5, Array(2 * 32, 2, Scalar(32, "int", True))))
def test_struct_array(): s = dump_struct_layout("struct x { int arr[5]; void *p[2]; };", "x")["x"].fields assert len(s.keys()) == 2 assert s["arr"] == (0, Array(5 * 32, 5, Scalar(32, "int", True))) assert s["p"] == (5 * 32 + 32, Array(2 * 64, 2, Pointer(64, Void())))
def test_struct_basic(): s = dump_struct_layout("struct x { int y; unsigned char z; };", "x")["x"].fields assert len(s.keys()) == 2 assert s["y"] == (0, Scalar(32, "int", True)) assert s["z"] == (32, Scalar(8, "unsigned char", False))
def test_struct_anonymous_enum(): x = dump_struct_layout("struct x { enum { x = 5, } e; };", "x")["x"].fields assert len(x.keys()) == 1 assert x["e"] == (0, Scalar(32, "anonymous enum", False))
def test_struct_anonymous_union(): s = dump_struct_layout("struct c { union { int x; float f; }; };", "c")["c"].fields assert len(s.keys()) == 2 assert s["x"] == (0, Scalar(32, "int", True)) assert s["f"] == (0, Scalar(32, "float", True))