Skip to content

Commit

Permalink
Read consts from elffile
Browse files Browse the repository at this point in the history
  • Loading branch information
hackenbergstefan committed Jul 15, 2022
1 parent f3c9259 commit c813da7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
40 changes: 27 additions & 13 deletions pygti2/device_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,41 @@ def uint2int(value, size):
class VarProxy:
"""VarProxy behaves like a pointer to its type."""

__slots__ = ("backend", "com", "type", "address", "length")
__slots__ = ("backend", "com", "type", "address", "length", "data")
cffi_compatibility_mode = True

@staticmethod
def new(backend: ElfBackend, com: Communicator, type: CType, address: int, length: int = -1):
def new(backend: ElfBackend, com: Communicator, type: CType, address: int, length: int = -1, data=None):
if type.kind not in ("pointer", "array"):
raise TypeError("Only pointer or arrays can be created.")

if type.kind == "array":
length = type.length
return VarProxy.new2(backend, com, type.base, address, length)
return VarProxy.new2(backend, com, type.base, address, length, data)

@staticmethod
def new2(backend: ElfBackend, com: Communicator, type: CType, address: int, length: int = -1):
def new2(backend: ElfBackend, com: Communicator, type: CType, address: int, length: int = -1, data=None):
if type.kind in ("struct", "typedef struct"):
cls = VarProxyStruct
else:
cls = VarProxy
return cls(backend, com, type, address, length)

def __init__(self, backend: ElfBackend, com: Communicator, type: CType, address: int, length: int = -1):
return cls(backend, com, type, address, length, data)

def __init__(
self,
backend: ElfBackend,
com: Communicator,
type: CType,
address: int,
length: int = -1,
data=None,
):
self.backend = backend
self.com = com
self.type = type
self.address = address
self.length = length
self.data = data

def __repr__(self) -> str:
return f"<{self.__class__.__name__} {self.type}[{self.length}] @ 0x{self.address or 0:08x}>"
Expand All @@ -56,6 +65,7 @@ def _getitem_single(self, index, content=None):
self.com,
self.type,
self.address + index * self.type.size,
data=self.data[index * self.type.size :] if self.data is not None else None,
)
if content is None:
content = newvarproxy.get_value()
Expand Down Expand Up @@ -83,6 +93,7 @@ def __getitem__(self, index):
self.type,
self.address + index.start * self.type.size,
length=index.stop - index.start,
data=self.data[index.start * self.type.size :] if self.data is not None else None,
).get_value()
return [self._getitem_single(i) for i in range(index.start, index.stop)]
else:
Expand Down Expand Up @@ -121,7 +132,7 @@ def get_value(self):
for part in junks(content, self.type.size):
value = int.from_bytes(part, self.backend.endian)
if getattr(self.type, "signed", False) and value >> (8 * self.type.size - 1) != 0:
value = int.from_bytes(self.type.size * b"\xff", self.backend.endian) - value - 1
value = value - int.from_bytes(self.type.size * b"\xff", self.backend.endian) - 1
values.append(value)
if len(values) == 1:
return values[0]
Expand All @@ -143,10 +154,8 @@ def set_value(self, data: Union[list, int, "VarProxy"]):
)

def to_bytes(self, *args):
if isinstance(self.type, CTypeVariable) and self.type.data is not None:
if self.address != self.type.address:
raise TypeError("Address mismatch.")
return self.type.data
if self.data is not None:
return self.data
return self.com.memory_read(self.address, self.type.size * (self.length if self.length > 0 else 1))

@property
Expand All @@ -159,6 +168,9 @@ def __len__(self):
def __iter__(self):
if self.length < 1:
return None
if self.length == 1:
yield self[0]
return
yield from self.__getitem__(slice(0, self.length))


Expand Down Expand Up @@ -286,6 +298,7 @@ def __getattr__(self, name):
raise TypeError(f"Unknown type: {name}")

if type.kind == "variable":
data = type.data
address = type.address
if type.type.kind == "array":
length = type.type.length
Expand All @@ -299,6 +312,7 @@ def __getattr__(self, name):
type,
address,
length,
data=data,
)
if var.cffi_compatibility_mode and var.length == -1 and var.type.kind == "int":
return var[0]
Expand Down Expand Up @@ -366,7 +380,7 @@ def memmove(self, destination: Union[VarProxy, int], source: Union[VarProxy, int
destination = destination.address
if isinstance(source, VarProxy):
source = source.address
content = self.com.memory_read(source, length)
content = source if isinstance(source, bytes) else self.com.memory_read(source, length)
self.com.memory_write(destination, content)

def sizeof(self, var: VarProxy):
Expand Down
7 changes: 3 additions & 4 deletions pygti2/elfbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,12 @@ def fromdie(cls, backend: "ElfBackend", die: DIE) -> "CTypeVariable":
elif "DW_AT_location" in die.attributes:
location = loc2addr(die)
typedie = die.get_DIE_from_attribute("DW_AT_type")
isconst = False
if typedie.tag == "DW_TAG_const_type":
isconst = True
typedie = typedie.get_DIE_from_attribute("DW_AT_type")
type = backend.type_from_die(typedie)
if location is not None:
if location is not None and isconst:
data = backend.read_memory(location, type.size)
return CType.fromdie(CTypeVariable, backend, die, type=type, location=location, data=data)

Expand Down Expand Up @@ -559,9 +561,6 @@ def read_memory(self, location: int, size: int):
for segment in self.elffile.iter_segments(type="PT_LOAD"):
if segment["p_vaddr"] is None:
continue
if segment["p_flags"] & P_FLAGS.PF_W != 0:
# Skip segments with writable data
continue
offset = location - segment["p_vaddr"]
if offset >= 0 and location + size <= segment["p_vaddr"] + segment["p_filesz"]:
return segment.data()[offset : offset + size]

0 comments on commit c813da7

Please sign in to comment.