Source code for angr.storage.memory_mixins.hex_dumper_mixin
import string
from ...errors import SimValueError
from . import MemoryMixin
[docs]class HexDumperMixin(MemoryMixin):
[docs] def hex_dump(
self,
start,
size,
word_size=4,
words_per_row=4,
endianness="Iend_BE",
symbolic_char="?",
unprintable_char=".",
solve=False,
extra_constraints=None,
inspect=False,
disable_actions=True,
):
"""
Returns a hex dump as a string. The solver, if enabled, is called once for every byte
potentially making this function very slow. It is meant to be used mainly as a
"visualization" for debugging.
Warning: May read and display more bytes than `size` due to rounding. Particularly,
if size is less than, or not a multiple of word_size*words_per_line.
:param start: starting address from which to print
:param size: number of bytes to display
:param word_size: number of bytes to group together as one space-delimited unit
:param words_per_row: number of words to display per row of output
:param endianness: endianness to use when displaying each word (ASCII representation is unchanged)
:param symbolic_char: the character to display when a byte is symbolic and has multiple solutions
:param unprintable_char: the character to display when a byte is not printable
:param solve: whether or not to attempt to solve (warning: can be very slow)
:param extra_constraints: extra constraints to pass to the solver is solve is True
:param inspect: whether or not to trigger SimInspect breakpoints for the memory load
:param disable_actions: whether or not to disable SimActions for the memory load
:return: hex dump as a string
"""
if endianness == "Iend_BE":
end = 1
else:
end = -1
if extra_constraints is None:
extra_constraints = []
# round up size so that chop() works
line_size = word_size * words_per_row
size = size if size % line_size == 0 else size + line_size - size % line_size
raw_mem = super().load(start, size=size, inspect=inspect, disable_actions=disable_actions)
i = start
dump_str = ""
for line in raw_mem.chop(line_size * self.state.arch.byte_width):
dump = "%x:" % i
group_str = ""
for word in line.chop(word_size * self.state.arch.byte_width):
word_bytes = ""
word_str = ""
for byte_ in word.chop(self.state.arch.byte_width)[::end]:
byte_value = None
if not self.state.solver.symbolic(byte_) or solve:
try:
byte_value = self.state.solver.eval_one(byte_, extra_constraints=extra_constraints)
except SimValueError:
pass
if byte_value is not None:
word_bytes += "%02x" % byte_value
if chr(byte_value) in string.printable[:-5]:
word_str += chr(byte_value)
else:
word_str += unprintable_char
else:
word_bytes += symbolic_char * 2
word_str += symbolic_char
dump += " " + word_bytes
group_str += word_str[::end] # always print ASCII representation in little-endian
dump += " " + group_str
i += line_size
dump_str += dump + "\n"
return dump_str