Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/dwarffi/dffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,7 @@ def _is_acceptable(sym: VtypeSymbol) -> bool:
if include_incomplete:
return True
addr = getattr(sym, "address", None)
has_addr = addr not in (None, 0)
has_type = getattr(sym, "type_info", None) is not None
return has_addr or has_type
return addr not in (None, 0)

if path is not None:
vj = self.vtypejsons.get(path)
Expand Down
4 changes: 2 additions & 2 deletions src/dwarffi/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,9 @@ def __init__(self, name: str, data: Dict[str, Any]):

def get_decoded_constant_data(self) -> Optional[bytes]:
"""Decodes base64-encoded constant data associated with the symbol."""
if self.constant_data:
if self.constant_data is not None:
try:
return base64.b64decode(self.constant_data)
return base64.b64decode(self.constant_data, validate=True)
except Exception:
return None
return None
Expand Down
56 changes: 56 additions & 0 deletions tests/test_backends.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from dwarffi import DFFI


class RecordingBackend:
def __init__(self, mem: bytearray):
self.mem = mem
self.reads = []
self.writes = []

def read(self, address: int, size: int) -> bytes:
self.reads.append((address, size))
return bytes(self.mem[address:address+size])

def write(self, address: int, data: bytes) -> None:
self.writes.append((address, bytes(data)))
self.mem[address:address+len(data)] = data

def _isf_ptr_struct():
return {
"metadata": {},
"base_types": {
"u32": {"kind": "int", "size": 4, "signed": False, "endian": "little"},
"pointer": {"kind": "pointer", "size": 8, "endian": "little"},
"void": {"kind": "void", "size": 0, "signed": False, "endian": "little"},
},
"user_types": {
"node": {
"kind": "struct",
"size": 16,
"fields": {
"val": {"offset": 0, "type": {"kind": "base", "name": "u32"}},
"next": {"offset": 8, "type": {"kind": "pointer", "subtype": {"kind": "struct", "name": "node"}}},
},
}
},
"enums": {},
"symbols": {},
}

def test_backend_read_write_sizes_and_addresses():
ffi = DFFI(_isf_ptr_struct())
mem = bytearray(b"\x00" * 0x100)
backend = RecordingBackend(mem)
ffi.backend = backend

# bind a node at address 0x20
n = ffi.from_address("struct node", 0x20)

# write should call backend.write with 4 bytes at 0x20
n.val = 0xDEADBEEF
assert backend.writes[-1][0] == 0x20
assert len(backend.writes[-1][1]) == 4

# read should call backend.read with 4 bytes at 0x20
_ = n.val
assert backend.reads[-1] == (0x20, 4)
42 changes: 42 additions & 0 deletions tests/test_bitfield_invariants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import struct

from dwarffi import DFFI


def test_bitfield_preserves_other_bits_across_patterns():
base_types = {
"u16": {"size": 2, "signed": False, "kind": "int", "endian": "little"},
"void": {"size": 0, "signed": False, "kind": "void", "endian": "little"},
"pointer": {"size": 8, "signed": False, "kind": "pointer", "endian": "little"},
}
ffi = DFFI({
"metadata": {},
"base_types": base_types,
"user_types": {
"bf": {
"kind": "struct", "size": 2,
"fields": {
# 5-bit field at bit 3
"f": {"offset": 0, "type": {"kind": "bitfield", "bit_length": 5, "bit_position": 3,
"type": {"kind": "base", "name": "u16"}}},
},
}
},
"enums": {}, "symbols": {},
})

mask = ((1 << 5) - 1) << 3 # 0b11111 << 3
patterns = [0x0000, 0xFFFF, 0xA55A, 0x1234, 0x8001, 0x0F0F]

for cur in patterns:
buf = bytearray(2)
struct.pack_into("<H", buf, 0, cur)
inst = ffi.from_buffer("struct bf", buf)

inst.f = 0 # clear field bits only
out = struct.unpack_from("<H", buf, 0)[0]
assert out == (cur & ~mask)

inst.f = 0x1F # set all field bits
out2 = struct.unpack_from("<H", buf, 0)[0]
assert out2 == ((cur & ~mask) | mask)
Loading
Loading