diff --git a/mode/hex.py b/mode/hex.py index a01fba9..d0260e9 100644 --- a/mode/hex.py +++ b/mode/hex.py @@ -1,4 +1,5 @@ -import string, struct +import re, string, struct +from subprocess import Popen, PIPE, STDOUT import color, mode from lex import Grammar, PatternRule, RegionRule from method import Method, Argument @@ -6,6 +7,9 @@ from point import Point class Hex(mode.Fundamental): modename = 'Hex' + config = { + 'hex.disinst': 'disinst', + } lmargin = 12 rmargin = 18 _ctrans = ['.'] * 256 @@ -88,6 +92,7 @@ class Hex(mode.Fundamental): self.add_action_and_bindings(HexReadAligned('double', 'd'), ('C-c d',)) self.add_action_and_bindings(ShowAddress(), ('C-c a',)) + self.add_action_and_bindings(ShowX86Instruction(), ('C-c x',)) self.add_action_and_bindings(GotoAddress(), ('C-c M-g',)) # create all the insert actions for the basic text input @@ -129,15 +134,16 @@ class Hex(mode.Fundamental): else: return ((0, s, self.cgreen),) - def read_data(self, cy, ix, fmt, size): + def read_data(self, cy, ix, size): b = self.window.buffer s = b.rawdata[cy][ix:] if len(s) < size: if cy < len(b.rawdata) - 1: s += b.rawdata[cy + 1] - else: - return None s = s[:size] + return s + def read_struct(self, cy, ix, fmt, size): + s = self.read_data(cy, ix, size) return struct.unpack(fmt, s)[0] class HexForward(Method): @@ -194,7 +200,7 @@ class HexRead(Method): ix = self._get_ix(b, cy, cx) addr = b.get_address(cy, 0) + ix try: - v = w.mode.read_data(cy, ix, self.fmt, self.size) + v = w.mode.read_struct(cy, ix, self.fmt, self.size) if v is None: w.set_error("not enough data to read %s" % self.type_) else: @@ -228,6 +234,27 @@ class HexOverwriteChar(Method): while w.cursor_char().isspace() and w.cursor < end: w.forward() +class ShowX86Instruction(Method): + '''''' + size_re = re.compile(r'X86 insn \((\d+) bytes\):') + def _execute(self, w, **vargs): + disinst = w.application.config.get('hex.disinst') + (cx, cy) = w.cursor.xy() + ix = w.buffer.cursorx_to_datax(cy, cx) + data = w.mode.read_data(cy, ix, 13) + data = ''.join(['%02x' % ord(c) for c in data]) + try: + p = Popen((disinst, data), stdout=PIPE, stderr=STDOUT) + lines = [l.strip() for l in p.stdout.readlines()] + result = p.wait() + m = self.size_re.match(lines[0]) + assert m + size = int(m.group(1)) + data = data[:size] + w.set_error("%s %s" % (data, lines[1])) + except Exception, e: + w.set_error("there was an error") + class GotoAddress(Method): '''Jump to the specified line number''' args = [Argument("address", type=type(0), prompt="Goto address: ")] @@ -241,6 +268,7 @@ class GotoAddress(Method): cy = addr // (b.groupsize * b.numgroups) w.goto(Point(cx, cy)) w.set_error("Goto 0x%08x (%r, %r)" % (addr, cx, cy)) + class ShowAddress(Method): '''Show the cursor's address in the current buffer''' def _execute(self, w, **vargs):