beautiful section dumps
This commit is contained in:
parent
7f59ac9bca
commit
30bcded998
@ -1,7 +1,7 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, List, Tuple, Union, Optional
|
||||
from .Exceptions import *
|
||||
from .helpers import parse_numeric_argument, align_addr
|
||||
from .helpers import *
|
||||
|
||||
import typing
|
||||
|
||||
@ -127,7 +127,7 @@ class LoadedMemorySection:
|
||||
name: str
|
||||
base: int
|
||||
size: int
|
||||
content: Union[List[LoadedInstruction], bytearray]
|
||||
content: Union[List[LoadedInstruction], bytearray] = field(repr=False)
|
||||
flags: MemoryFlags
|
||||
|
||||
def read(self, offset: int, size: int):
|
||||
@ -162,6 +162,53 @@ class LoadedMemorySection:
|
||||
for i in range(size):
|
||||
self.content[offset + i] = data[i]
|
||||
|
||||
def dump(self, at_addr=None, fmt='hex', max_rows=10, group=4, bytes_per_row=16, all=False):
|
||||
highlight = -1
|
||||
if at_addr is None:
|
||||
at_addr = self.base
|
||||
else:
|
||||
highlight = at_addr - self.base
|
||||
|
||||
at_off = at_addr - self.base
|
||||
start = max(align_addr(at_off - ((max_rows * bytes_per_row) // 2), 8) - 8, 0)
|
||||
if all:
|
||||
end = self.size
|
||||
else:
|
||||
end = min(start + (max_rows * bytes_per_row), self.size)
|
||||
|
||||
|
||||
fmt_str = " 0x{:0" + str(ceil(log(self.base + end, 16))) + "X}: {}"
|
||||
|
||||
if self.flags.executable:
|
||||
# this section holds instructions!
|
||||
start = max(self.base - at_addr - (max_rows // 2), 0)
|
||||
end = min(self.size, start + max_rows)
|
||||
print(FMT_BOLD + FMT_MAGENTA + "MemorySection {} at base 0x{:08X}, viewing {} instructions:".format(
|
||||
self.name, self.base, end - start
|
||||
) + FMT_NONE)
|
||||
for i in range(start, end):
|
||||
if i == highlight:
|
||||
ins = FMT_UNDERLINE + FMT_ORANGE + repr(self.content[i]) + FMT_NONE
|
||||
else:
|
||||
ins = repr(self.content[i])
|
||||
print(fmt_str.format(self.base + i, ins))
|
||||
else:
|
||||
print(FMT_BOLD + FMT_MAGENTA + "MemorySection {} at base 0x{:08X}, viewing {} bytes:".format(
|
||||
self.name, self.base, end - start
|
||||
) + FMT_NONE)
|
||||
for i in range(start, end, bytes_per_row):
|
||||
data = self.content[start + i: min(start + i + bytes_per_row, end)]
|
||||
if start + i <= highlight <= start + i + bytes_per_row:
|
||||
# do hightlight here!
|
||||
hi_ind = (highlight - start - i) // group
|
||||
print(fmt_str.format(self.base + start + i, format_bytes(data, fmt, group, highlight=hi_ind)))
|
||||
else:
|
||||
print(fmt_str.format(self.base + start + i, format_bytes(data, fmt, group)))
|
||||
if end == self.size:
|
||||
print(FMT_BOLD + FMT_MAGENTA + "End of section!" + FMT_NONE)
|
||||
else:
|
||||
print(FMT_BOLD + FMT_MAGENTA + "..." + FMT_NONE)
|
||||
|
||||
|
||||
class LoadedExecutable:
|
||||
"""
|
||||
|
@ -1,5 +1,7 @@
|
||||
from math import log10, ceil, log
|
||||
from .Exceptions import NumberFormatException
|
||||
|
||||
|
||||
def align_addr(addr: int, to_bytes: int = 8):
|
||||
"""
|
||||
align an address to `to_bytes` (meaning addr & to_bytes = 0)
|
||||
@ -23,7 +25,7 @@ def int_to_bytes(val, bytes=4, unsigned=False):
|
||||
if unsigned and val < 0:
|
||||
raise NumberFormatException("unsigned negative number!")
|
||||
return bytearray([
|
||||
(val >> ((bytes-i-1) * 8)) & 0xFF for i in range(bytes)
|
||||
(val >> ((bytes - i - 1) * 8)) & 0xFF for i in range(bytes)
|
||||
])
|
||||
|
||||
|
||||
@ -44,7 +46,7 @@ def int_from_bytes(bytes, unsigned=False):
|
||||
|
||||
def to_unsigned(num: int, bytes=4):
|
||||
if num < 0:
|
||||
return 2**(bytes * 8) + num
|
||||
return 2 ** (bytes * 8) + num
|
||||
return num
|
||||
|
||||
|
||||
@ -53,6 +55,7 @@ def to_signed(num: int, bytes=4):
|
||||
return num - 2 ** (8 * bytes)
|
||||
return num
|
||||
|
||||
|
||||
# Colors
|
||||
|
||||
FMT_RED = '\033[31m'
|
||||
@ -66,3 +69,36 @@ FMT_NONE = '\033[0m'
|
||||
FMT_UNDERLINE = '\033[4m'
|
||||
|
||||
FMT_ERROR = FMT_RED + FMT_BOLD
|
||||
|
||||
|
||||
def create_chunks(my_list, chunk_size):
|
||||
return [my_list[i:i + chunk_size] for i in range(0, len(my_list), chunk_size)]
|
||||
|
||||
|
||||
def apply_highlight(item, ind, hi_ind):
|
||||
"""
|
||||
applies some hightlight such as underline to item if ind == hi_ind
|
||||
"""
|
||||
if ind == hi_ind:
|
||||
return FMT_UNDERLINE + FMT_ORANGE + item + FMT_NONE
|
||||
return item
|
||||
|
||||
|
||||
def highlight_in_list(items, hi_ind):
|
||||
return " ".join([apply_highlight(item, i, hi_ind) for i, item in enumerate(items)])
|
||||
|
||||
|
||||
def format_bytes(bytes, fmt, group=1, highlight=-1):
|
||||
chunks = create_chunks(bytes, group)
|
||||
if fmt == 'hex':
|
||||
return highlight_in_list(['0x{}'.format(ch.hex()) for ch in chunks], highlight)
|
||||
if fmt == 'int':
|
||||
spc = str(ceil(log10(2 ** (group * 8 - 1))) + 1)
|
||||
return highlight_in_list([('{:0' + spc + 'd}').format(int_from_bytes(ch)) for ch in chunks], highlight)
|
||||
if fmt == 'uint':
|
||||
spc = str(ceil(log10(2 ** (group * 8))))
|
||||
return highlight_in_list([('{:0' + spc + 'd}').format(int_from_bytes(ch, unsigned=True)) for ch in chunks],
|
||||
highlight)
|
||||
if fmt == 'ascii':
|
||||
spc = str(4 * group)
|
||||
return highlight_in_list([('{:>' + spc + '}').format(ch.decode('ascii')) for ch in chunks], highlight)
|
||||
|
Loading…
Reference in New Issue
Block a user