| 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' |
| 221 | assert len(data0) == len(data1), 'memory contents differ in size' |
| 222 | |
| 223 | # scan both data chunks and keep the index and byte value of the unmatched ones. |
| 224 | # if memory contents are identical, this will result in an empty tuple |
| 225 | data_diff = tuple((i, b0) for i, (b0, b1) in enumerate(zip(data0, data1)) if b0 != b1) |
| 226 | |
| 227 | ram_diff[rng] = (MemDiff.MOD, (perms, label0, data_diff)) |
| 228 | |
| 229 | # <DEBUG> |
| 230 | # for rng, (opcode, diff) in sorted(ram_diff.items()): |
| 231 | # lbound, ubound = rng |
| 232 | # perms, label, data = diff |
| 233 | # |
| 234 | # print(f'{opcode.name} {lbound:010x} - {ubound:010x} {perms:03b} {label:24s} ~{len(data)}') |
| 235 | # </DEBUG> |
| 236 | |
| 237 | return ram_diff |
| 238 | |
| 239 | def diff(self, other: State) -> DiffedState: |
| 240 | """Diff between previous and current state. |