about summary refs log tree commit diff stats
path: root/miasm2/analysis/gdbserver.py
diff options
context:
space:
mode:
authorFabrice Desclaux <fabrice.desclaux@cea.fr>2019-02-25 11:09:54 +0100
committerFabrice Desclaux <fabrice.desclaux@cea.fr>2019-03-05 16:52:49 +0100
commit02bbb30efea4980c9d133947cbbf69fb599071ad (patch)
tree3fea6826fcc5354840a27cb1dc99ff31eef81896 /miasm2/analysis/gdbserver.py
parenteab809932871f91d6f4aa770fc321af9e156e0f5 (diff)
downloadmiasm-02bbb30efea4980c9d133947cbbf69fb599071ad.tar.gz
miasm-02bbb30efea4980c9d133947cbbf69fb599071ad.zip
Support python2/python3
Diffstat (limited to 'miasm2/analysis/gdbserver.py')
-rw-r--r--miasm2/analysis/gdbserver.py336
1 files changed, 176 insertions, 160 deletions
diff --git a/miasm2/analysis/gdbserver.py b/miasm2/analysis/gdbserver.py
index 6c630f88..61ee8955 100644
--- a/miasm2/analysis/gdbserver.py
+++ b/miasm2/analysis/gdbserver.py
@@ -1,10 +1,15 @@
 #-*- coding:utf-8 -*-
 
+from __future__ import print_function
+from future.builtins import map, range
+
+from miasm2.core.utils import decode_hex, encode_hex, int_to_byte
+
 import socket
 import struct
 import time
 import logging
-from StringIO import StringIO
+from io import BytesIO
 import miasm2.analysis.debugging as debugging
 from miasm2.jitter.jitload import ExceptionHandle
 
@@ -15,7 +20,7 @@ class GdbServer(object):
 
     general_registers_order = []
     general_registers_size = {}  # RegName : Size in octet
-    status = "S05"
+    status = b"S05"
 
     def __init__(self, dbg, port=4455):
         server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -28,242 +33,243 @@ class GdbServer(object):
     # Communication methods
 
     def compute_checksum(self, data):
-        return chr(sum(map(ord, data)) % 256).encode("hex")
+        return encode_hex(int_to_byte(sum(map(ord, data)) % 256))
 
     def get_messages(self):
-        all_data = ""
-        data = self.sock.recv(4096)
-        all_data += data
-        while (len(data) == 4096 or data == ""):
-            if data == "":
-                # Avoid consuming CPU
-                time.sleep(0.001)
-                continue
+        all_data = b""
+        while True:
             data = self.sock.recv(4096)
+            if not data:
+                break
             all_data += data
 
         logging.debug("<- %r", all_data)
         self.recv_queue += self.parse_messages(all_data)
 
     def parse_messages(self, data):
-        buf = StringIO(data)
-
+        buf = BytesIO(data)
         msgs = []
 
         while (buf.tell() < buf.len):
             token = buf.read(1)
-            if token == "+":
+            if token == b"+":
                 continue
-            if token == "-":
+            if token == b"-":
                 raise NotImplementedError("Resend packet")
-            if token == "$":
-                packet_data = ""
+            if token == b"$":
+                packet_data = b""
                 c = buf.read(1)
-                while c != "#":
+                while c != b"#":
                     packet_data += c
                     c = buf.read(1)
                 checksum = buf.read(2)
                 if checksum != self.compute_checksum(packet_data):
                     raise ValueError("Incorrect checksum")
-
                 msgs.append(packet_data)
 
         return msgs
 
     def send_string(self, s):
-        self.send_queue.append("O" + s.encode("hex"))
+        self.send_queue.append(b"O" + encode_hex(s))
 
     def process_messages(self):
 
         while self.recv_queue:
             msg = self.recv_queue.pop(0)
-            buf = StringIO(msg)
+            buf = BytesIO(msg)
             msg_type = buf.read(1)
 
-            self.send_queue.append("+")
+            self.send_queue.append(b"+")
 
-            if msg_type == "q":
-                if msg.startswith("qSupported"):
-                    self.send_queue.append("PacketSize=3fff")
-                elif msg.startswith("qC"):
+            if msg_type == b"q":
+                if msg.startswith(b"qSupported"):
+                    self.send_queue.append(b"PacketSize=3fff")
+                elif msg.startswith(b"qC"):
                     # Current thread
-                    self.send_queue.append("")
-                elif msg.startswith("qAttached"):
+                    self.send_queue.append(b"")
+                elif msg.startswith(b"qAttached"):
                     # Not supported
-                    self.send_queue.append("")
-                elif msg.startswith("qTStatus"):
+                    self.send_queue.append(b"")
+                elif msg.startswith(b"qTStatus"):
                     # Not supported
-                    self.send_queue.append("")
-                elif msg.startswith("qfThreadInfo"):
+                    self.send_queue.append(b"")
+                elif msg.startswith(b"qfThreadInfo"):
                     # Not supported
-                    self.send_queue.append("")
+                    self.send_queue.append(b"")
                 else:
                     raise NotImplementedError()
 
-            elif msg_type == "H":
+            elif msg_type == b"H":
                 # Set current thread
-                self.send_queue.append("OK")
+                self.send_queue.append(b"OK")
 
-            elif msg_type == "?":
+            elif msg_type == b"?":
                 # Report why the target halted
                 self.send_queue.append(self.status)  # TRAP signal
 
-            elif msg_type == "g":
+            elif msg_type == b"g":
                 # Report all general register values
                 self.send_queue.append(self.report_general_register_values())
 
-            elif msg_type == "p":
+            elif msg_type == b"p":
                 # Read a specific register
                 reg_num = int(buf.read(), 16)
                 self.send_queue.append(self.read_register(reg_num))
 
-            elif msg_type == "P":
+            elif msg_type == b"P":
                 # Set a specific register
-                reg_num, value = buf.read().split("=")
+                reg_num, value = buf.read().split(b"=")
                 reg_num = int(reg_num, 16)
-                value = int(value.decode("hex")[::-1].encode("hex"), 16)
+                value = int(encode_hex(decode_hex(value)[::-1]), 16)
                 self.set_register(reg_num, value)
-                self.send_queue.append("OK")
+                self.send_queue.append(b"OK")
 
-            elif msg_type == "m":
+            elif msg_type == b"m":
                 # Read memory
-                addr, size = map(lambda x: int(x, 16), buf.read().split(","))
+                addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
                 self.send_queue.append(self.read_memory(addr, size))
 
-            elif msg_type == "k":
+            elif msg_type == b"k":
                 # Kill
                 self.sock.close()
                 self.send_queue = []
                 self.sock = None
 
-            elif msg_type == "!":
+            elif msg_type == b"!":
                 # Extending debugging will be used
-                self.send_queue.append("OK")
+                self.send_queue.append(b"OK")
 
-            elif msg_type == "v":
-                if msg == "vCont?":
+            elif msg_type == b"v":
+                if msg == b"vCont?":
                     # Is vCont supported ?
-                    self.send_queue.append("")
+                    self.send_queue.append(b"")
 
-            elif msg_type == "s":
+            elif msg_type == b"s":
                 # Step
                 self.dbg.step()
-                self.send_queue.append("S05")  # TRAP signal
+                self.send_queue.append(b"S05")  # TRAP signal
 
-            elif msg_type == "Z":
+            elif msg_type == b"Z":
                 # Add breakpoint or watchpoint
                 bp_type = buf.read(1)
-                if bp_type == "0":
+                if bp_type == b"0":
                     # Exec breakpoint
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
 
                     if size != 1:
                         raise NotImplementedError("Bigger size")
                     self.dbg.add_breakpoint(addr)
-                    self.send_queue.append("OK")
+                    self.send_queue.append(b"OK")
 
-                elif bp_type == "1":
+                elif bp_type == b"1":
                     # Hardware BP
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
-
-                    self.dbg.add_memory_breakpoint(addr, size,
-                                                   read=True,
-                                                   write=True)
-                    self.send_queue.append("OK")
-
-                elif bp_type in ["2", "3", "4"]:
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
+
+                    self.dbg.add_memory_breakpoint(
+                        addr,
+                        size,
+                        read=True,
+                        write=True
+                    )
+                    self.send_queue.append(b"OK")
+
+                elif bp_type in [b"2", b"3", b"4"]:
                     # Memory breakpoint
-                    assert(buf.read(1) == ",")
-                    read = bp_type in ["3", "4"]
-                    write = bp_type in ["2", "4"]
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
-
-                    self.dbg.add_memory_breakpoint(addr, size,
-                                                   read=read,
-                                                   write=write)
-                    self.send_queue.append("OK")
+                    assert(buf.read(1) == b",")
+                    read = bp_type in [b"3", b"4"]
+                    write = bp_type in [b"2", b"4"]
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
+
+                    self.dbg.add_memory_breakpoint(
+                        addr,
+                        size,
+                        read=read,
+                        write=write
+                    )
+                    self.send_queue.append(b"OK")
 
                 else:
                     raise ValueError("Impossible value")
 
-            elif msg_type == "z":
+            elif msg_type == b"z":
                 # Remove breakpoint or watchpoint
                 bp_type = buf.read(1)
-                if bp_type == "0":
+                if bp_type == b"0":
                     # Exec breakpoint
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
 
                     if size != 1:
                         raise NotImplementedError("Bigger size")
                     dbgsoft = self.dbg.get_breakpoint_by_addr(addr)
                     assert(len(dbgsoft) == 1)
                     self.dbg.remove_breakpoint(dbgsoft[0])
-                    self.send_queue.append("OK")
+                    self.send_queue.append(b"OK")
 
-                elif bp_type == "1":
+                elif bp_type == b"1":
                     # Hardware BP
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
                     self.dbg.remove_memory_breakpoint_by_addr_access(
-                        addr, read=True, write=True)
-                    self.send_queue.append("OK")
+                        addr,
+                        read=True,
+                        write=True
+                    )
+                    self.send_queue.append(b"OK")
 
-                elif bp_type in ["2", "3", "4"]:
+                elif bp_type in [b"2", b"3", b"4"]:
                     # Memory breakpoint
-                    assert(buf.read(1) == ",")
-                    read = bp_type in ["3", "4"]
-                    write = bp_type in ["2", "4"]
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    read = bp_type in [b"3", b"4"]
+                    write = bp_type in [b"2", b"4"]
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
 
                     self.dbg.remove_memory_breakpoint_by_addr_access(
-                        addr, read=read, write=write)
-                    self.send_queue.append("OK")
+                        addr,
+                        read=read,
+                        write=write
+                    )
+                    self.send_queue.append(b"OK")
 
                 else:
                     raise ValueError("Impossible value")
 
-            elif msg_type == "c":
+            elif msg_type == b"c":
                 # Continue
-                self.status = ""
+                self.status = b""
                 self.send_messages()
                 ret = self.dbg.run()
                 if isinstance(ret, debugging.DebugBreakpointSoft):
-                    self.status = "S05"
-                    self.send_queue.append("S05")  # TRAP signal
+                    self.status = b"S05"
+                    self.send_queue.append(b"S05")  # TRAP signal
                 elif isinstance(ret, ExceptionHandle):
                     if ret == ExceptionHandle.memoryBreakpoint():
-                        self.status = "S05"
-                        self.send_queue.append("S05")
+                        self.status = b"S05"
+                        self.send_queue.append(b"S05")
                     else:
                         raise NotImplementedError("Unknown Except")
                 elif isinstance(ret, debugging.DebugBreakpointTerminate):
                     # Connexion should close, but keep it running as a TRAP
                     # The connexion will be close on instance destruction
-                    print ret
-                    self.status = "S05"
-                    self.send_queue.append("S05")
+                    print(ret)
+                    self.status = b"S05"
+                    self.send_queue.append(b"S05")
                 else:
                     raise NotImplementedError()
 
             else:
                 raise NotImplementedError(
-                    "Not implemented: message type '%s'" % msg_type)
+                    "Not implemented: message type %r" % msg_type
+                )
 
     def send_messages(self):
         for msg in self.send_queue:
-            if msg == "+":
-                data = "+"
+            if msg == b"+":
+                data = b"+"
             else:
-                data = "$%s#%s" % (msg, self.compute_checksum(msg))
+                data = b"$%s#%s" % (msg, self.compute_checksum(msg))
             logging.debug("-> %r", data)
             self.sock.send(data)
         self.send_queue = []
@@ -272,7 +278,7 @@ class GdbServer(object):
         self.recv_queue = []
         self.send_queue = []
 
-        self.send_string("Test\n")
+        self.send_string(b"Test\n")
 
         while (self.sock):
             self.get_messages()
@@ -285,8 +291,8 @@ class GdbServer(object):
 
     # Debugguer processing methods
     def report_general_register_values(self):
-        s = ""
-        for i in xrange(len(self.general_registers_order)):
+        s = b""
+        for i in range(len(self.general_registers_order)):
             s += self.read_register(i)
         return s
 
@@ -307,7 +313,7 @@ class GdbServer(object):
         else:
             raise NotImplementedError("Unknown size")
 
-        return struct.pack(pack_token, reg_value).encode("hex")
+        return encode_hex(struct.pack(pack_token, reg_value))
 
     def set_register(self, reg_num, value):
         reg_name = self.general_registers_order[reg_num]
@@ -319,39 +325,44 @@ class GdbServer(object):
     def read_memory(self, addr, size):
         except_flag_vm = self.dbg.myjit.vm.get_exception()
         try:
-            return self.dbg.get_mem_raw(addr, size).encode("hex")
+            return encode_hex(self.dbg.get_mem_raw(addr, size))
         except RuntimeError:
             self.dbg.myjit.vm.set_exception(except_flag_vm)
-            return "00" * size
+            return b"00" * size
 
 
 class GdbServer_x86_32(GdbServer):
 
     "Extend GdbServer for x86 32bits purposes"
 
-    general_registers_order = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI",
-                               "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES",
-                               "FS", "GS"]
-
-    general_registers_size = {"EAX": 4,
-                              "ECX": 4,
-                              "EDX": 4,
-                              "EBX": 4,
-                              "ESP": 4,
-                              "EBP": 4,
-                              "ESI": 4,
-                              "EDI": 4,
-                              "EIP": 4,
-                              "EFLAGS": 2,
-                              "CS": 2,
-                              "SS": 2,
-                              "DS": 2,
-                              "ES": 2,
-                              "FS": 2,
-                              "GS": 2}
+    general_registers_order = [
+        "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI",
+        "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES",
+        "FS", "GS"
+    ]
+
+    general_registers_size = {
+        "EAX": 4,
+        "ECX": 4,
+        "EDX": 4,
+        "EBX": 4,
+        "ESP": 4,
+        "EBP": 4,
+        "ESI": 4,
+        "EDI": 4,
+        "EIP": 4,
+        "EFLAGS": 2,
+        "CS": 2,
+        "SS": 2,
+        "DS": 2,
+        "ES": 2,
+        "FS": 2,
+        "GS": 2
+    }
 
     register_ignore = [
-        "tf", "i_f", "nt", "rf", "vm", "ac", "vif", "vip", "i_d"]
+        "tf", "i_f", "nt", "rf", "vm", "ac", "vif", "vip", "i_d"
+    ]
 
     def read_register_by_name(self, reg_name):
         sup_func = super(GdbServer_x86_32, self).read_register_by_name
@@ -364,7 +375,8 @@ class GdbServer_x86_32(GdbServer):
         if reg_name == "EFLAGS":
             val = 0
             eflags_args = [
-                "cf", 1, "pf", 0, "af", 0, "zf", "nf", "tf", "i_f", "df", "of"]
+                "cf", 1, "pf", 0, "af", 0, "zf", "nf", "tf", "i_f", "df", "of"
+            ]
             eflags_args += ["nt", 0, "rf", "vm", "ac", "vif", "vip", "i_d"]
             eflags_args += [0] * 10
 
@@ -387,26 +399,30 @@ class GdbServer_msp430(GdbServer):
 
     "Extend GdbServer for msp430 purposes"
 
-    general_registers_order = ["PC", "SP", "SR", "R3", "R4", "R5", "R6", "R7",
-                               "R8", "R9", "R10", "R11", "R12", "R13", "R14",
-                               "R15"]
-
-    general_registers_size = {"PC": 2,
-                              "SP": 2,
-                              "SR": 2,
-                              "R3": 2,
-                              "R4": 2,
-                              "R5": 2,
-                              "R6": 2,
-                              "R7": 2,
-                              "R8": 2,
-                              "R9": 2,
-                              "R10": 2,
-                              "R11": 2,
-                              "R12": 2,
-                              "R13": 2,
-                              "R14": 2,
-                              "R15": 2}
+    general_registers_order = [
+        "PC", "SP", "SR", "R3", "R4", "R5", "R6", "R7",
+        "R8", "R9", "R10", "R11", "R12", "R13", "R14",
+        "R15"
+    ]
+
+    general_registers_size = {
+        "PC": 2,
+        "SP": 2,
+        "SR": 2,
+        "R3": 2,
+        "R4": 2,
+        "R5": 2,
+        "R6": 2,
+        "R7": 2,
+        "R8": 2,
+        "R9": 2,
+        "R10": 2,
+        "R11": 2,
+        "R12": 2,
+        "R13": 2,
+        "R14": 2,
+        "R15": 2
+    }
 
     def read_register_by_name(self, reg_name):
         sup_func = super(GdbServer_msp430, self).read_register_by_name