internal container for storing raw state from qiling
| 161 | |
| 162 | |
| 163 | class State: |
| 164 | """ |
| 165 | internal container for storing raw state from qiling |
| 166 | """ |
| 167 | |
| 168 | def __init__(self, saved: Mapping[str, Mapping]): |
| 169 | self.reg: Dict[str, int] = saved.get("reg") or {} |
| 170 | self.xreg: Dict[str, int] = saved.get("cpr") or saved.get("msr") or {} |
| 171 | |
| 172 | mem = saved.get("mem") or {} |
| 173 | ram = mem.get("ram") or [] |
| 174 | |
| 175 | # saved ram lists might not match in order, we turn them into dicts to work around |
| 176 | # that. in these dicts every memory content is mapped to its memory entry's properties |
| 177 | self.ram: Dict[RamKey, RamVal] = {(lbound, ubound): (perms, label, data) for lbound, ubound, perms, label, data in ram} |
| 178 | |
| 179 | self.loader: Dict[str, Any] = saved.get('loader') or {} |
| 180 | |
| 181 | @staticmethod |
| 182 | def __dict_diff(d0: Mapping[_K, _V], d1: Mapping[_K, _V]) -> Dict[_K, _V]: |
| 183 | return {k: v for k, v in d0.items() if v != d1.get(k)} |
| 184 | |
| 185 | def _diff_reg(self, other: State) -> Dict[str, int]: |
| 186 | return State.__dict_diff(self.reg, other.reg) |
| 187 | |
| 188 | def _diff_xreg(self, other: State) -> Dict[str, int]: |
| 189 | return State.__dict_diff(self.xreg, other.xreg) |
| 190 | |
| 191 | def _diff_ram(self, other: State) -> Dict[RamDiffKey, RamDiffVal]: |
| 192 | ram0 = self.ram |
| 193 | ram1 = other.ram |
| 194 | |
| 195 | ram_diff: Dict[RamDiffKey, RamDiffVal] = {} |
| 196 | |
| 197 | removed = [rng for rng in ram0 if rng not in ram1] |
| 198 | added = [rng for rng in ram1 if rng not in ram0] |
| 199 | modified = [rng for rng in ram0 if rng in ram1 and ram0[rng] != ram1[rng]] |
| 200 | |
| 201 | # memory regions that got removed should be re-added |
| 202 | for rng in removed: |
| 203 | ram_diff[rng] = (MemDiff.ADD, ram0[rng]) |
| 204 | |
| 205 | # memory regions that got added should be removed |
| 206 | for rng in added: |
| 207 | _, label, _ = ram1[rng] |
| 208 | |
| 209 | # though we discard data as it is not required anymore, label is still required |
| 210 | # to determine the method of removing the region: brk, mmap, or ordinary map |
| 211 | ram_diff[rng] = (MemDiff.REM, (-1, label, b'')) |
| 212 | |
| 213 | # memory regions that fot modified should be reverted back |
| 214 | for rng in modified: |
| 215 | perms0, label0, data0 = ram0[rng] |
| 216 | perms1, label1, data1 = ram1[rng] |
| 217 | |
| 218 | perms = -1 if perms0 == perms1 else perms0 |
| 219 | |
| 220 | assert label0 == label1, 'memory region label changed unexpectedly' |