class GdbserverTarget(Target): def __init__(self, system, verbose=False): self._system = system self._verbose = verbose def init(self): conf = self._system.get_configuration() assert("avatar_configuration" in conf) assert("target_gdb_address" in conf["avatar_configuration"]) assert(conf["avatar_configuration"]["target_gdb_address"].startswith("tcp:")) sockaddr_str = conf["avatar_configuration"]["target_gdb_address"][4:] if "target_gdb_path" in conf["avatar_configuration"]: self.gdb_exec= conf["avatar_configuration"]["target_gdb_path"] else: self.gdb_exec = "/home/zaddach/projects/hdd-svn/gdb/gdb/gdb" log.warn("target_gdb_path not defined in avatar configuration, using hardcoded GDB path: %s", self.gdb_exec) if "target_gdb_additional_arguments" in conf["avatar_configuration"]: self.additional_args = conf["avatar_configuration"]["target_gdb_additional_arguments"] else: self.additional_args = [] self._sockaddress = (sockaddr_str[:sockaddr_str.rfind(":")], int(sockaddr_str[sockaddr_str.rfind(":") + 1:])) def start(self): #TODO: Handle timeout if self._verbose: log.info("Trying to connect to target gdb server at %s:%d", self._sockaddress[0], self._sockaddress[1]) self._gdb_interface = GdbDebugger(gdb_executable = self.gdb_exec, cwd = ".", additional_args = self.additional_args ) self._gdb_interface.set_async_message_handler(self.handle_gdb_async_message) self._gdb_interface.connect(("tcp", self._sockaddress[0], "%d" % self._sockaddress[1])) def write_typed_memory(self, address, size, data): self._gdb_interface.write_memory(address, size, data) def read_typed_memory(self, address, size): return self._gdb_interface.read_memory(address, size) def set_register(self, reg, val): self._gdb_interface.set_register(reg, val) def get_register(self, reg): return self._gdb_interface.get_register(reg) def get_register_from_nr(self, num): try: return self.get_register(["r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", "cpsr"][num]) except IndexError: log.warn("get_register_from_nr called with unexpected register index %d", num) return 0 def execute_gdb_command(self, cmd): return self._gdb_interface.execute_gdb_command(cmd) def get_checksum(self, addr, size): return self._gdb_interface.get_checksum(addr, size) def stop(self): pass def set_breakpoint(self, address, **properties): if "thumb" in properties: del properties["thumb"] bkpt = self._gdb_interface.insert_breakpoint(address, *properties) return GdbBreakpoint(self._system, int(bkpt["bkpt"]["number"])) def cont(self): self._gdb_interface.cont() def handle_gdb_async_message(self, msg): print("Received async message: '%s'" % str(msg)) if msg.type == Async.EXEC: if msg.klass == "running": self._post_event({"tags": [EVENT_RUNNING], "channel": "gdb"}) elif msg.klass == "stopped": if "reason" in msg.results and msg.results["reason"] == "breakpoint-hit": self._post_event({"tags": [EVENT_STOPPED, EVENT_BREAKPOINT], "properties": { "address": int(msg.results["frame"]["addr"], 16), "bkpt_number": int(msg.results["bkptno"])}, "channel": "gdb"}) elif "reason" in msg.results and msg.results["reason"] == "signal-received": # this is data abort try: addr = int(msg.results["frame"]["addr"], 16) except: addr = 0xDEADDEAD self._post_event({"tags": [EVENT_STOPPED, EVENT_SIGABRT], "properties": { "address": addr, }, "channel": "gdb"}) def _post_event(self, evt): evt["source"] = "target" self._system.post_event(evt) @classmethod def from_str(cls, sockaddr_str): assert(sockaddr_str.startswith("tcp:")) sockaddr = (sockaddr_str[:sockaddr_str.rfind(":")], int(sockaddr_str[sockaddr_str.rfind(":") + 1:])) return cls(sockaddr)
class S2EEmulator(Emulator): def __init__(self, system): super().__init__(system) self._configuration = S2EConfiguration( self._system.get_configuration()) def init(self): self._configuration.write_configuration_files( self._system.get_configuration()["output_directory"]) self._cmdline = self._configuration.get_command_line() def start(self): s2e_processes = find_processes(self._cmdline[0]) if s2e_processes: log.warn( "There are still S2E instances running, NOT killing them ...") log.warn( "Results might be corrupted if output files are not different") log.info("Executing S2E process: %s", " ".join(["'%s'" % x for x in self._cmdline])) self._s2e_thread = threading.Thread(target=self.run_s2e_process) self._is_s2e_running = threading.Event() self._s2e_thread.start() #TODO: Would be nicer to put this somewhere in a function called is_running #so that other stuff can start in parallel and in the end the system waits for everything #to be running self._is_s2e_running.wait() def stop(self): if hasattr(self, "_s2e_process"): self._s2e_process.kill() def exit(self): if hasattr(self, "_remote_memory_interface"): self._remote_memory_interface.stop() print("Exiting") def run_s2e_process(self): try: log.info("Starting S2E process: %s", " ".join(["'%s'" % x for x in self._cmdline])) self._s2e_process = subprocess.Popen( self._cmdline, cwd=self._configuration.get_output_directory(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) self._s2e_stdout_tee_process = subprocess.Popen( [ "tee", os.path.normpath( os.path.join( self._configuration.get_output_directory(), "s2e_stdout.log")) ], stdin=self._s2e_process.stdout, cwd=self._configuration.get_output_directory()) self._s2e_stderr_tee_process = subprocess.Popen( [ "tee", os.path.normpath( os.path.join( self._configuration.get_output_directory(), "s2e_stderr.log")) ], stdin=self._s2e_process.stderr, cwd=self._configuration.get_output_directory()) remote_target = False if "RemoteMemory" in self._configuration._s2e_configuration[ "plugins"]: remote_target = True if remote_target: self._remote_memory_interface = S2ERemoteMemoryInterface( self._configuration.get_remote_memory_listen_address()) self._remote_memory_interface.set_read_handler( self._notify_read_request_handler) self._remote_memory_interface.set_write_handler( self._notify_write_request_handler) self._remote_memory_interface.set_set_cpu_state_handler( self._notify_set_cpu_state_handler) self._remote_memory_interface.set_get_cpu_state_handler( self._notify_get_cpu_state_handler) self._remote_memory_interface.set_continue_handler( self._notify_continue_handler) self._remote_memory_interface.set_get_checksum_handler( self._system.get_target().get_checksum) time.sleep(2) #Wait a bit for the S2E process to start self._remote_memory_interface.start() try: gdb_path = self._configuration._s2e_configuration[ "emulator_gdb_path"] except KeyError: gdb_path = "arm-none-eabi-gdb" log.warn("Using default gdb executable path: %s" % gdb_path) try: gdb_additional_args = self._configuration._s2e_configuration[ "emulator_gdb_additional_arguments"] except KeyError: gdb_additional_args = [] self._gdb_interface = GdbDebugger( gdb_executable=gdb_path, cwd=".", additional_args=gdb_additional_args) self._gdb_interface.set_async_message_handler( self.handle_gdb_async_message) count = 10 while count != 0: try: log.debug("Trying to connect to emulator.") self._gdb_interface.connect( ("tcp", "127.0.0.1", "%d" % self._configuration.get_s2e_gdb_port())) break except: count -= 1 if count > 0: log.warning("Failed to connect to emulator, retrying.") time.sleep(3) if count == 0: raise Exception("Failed to connect to emulator. Giving up!") log.info("Successfully connected to emulator.") self._is_s2e_running.set() self._s2e_process.wait() except KeyboardInterrupt: pass self.exit() def write_typed_memory(self, address, size, data): self._gdb_interface.write_memory(address, size, data) def read_typed_memory(self, address, size): return self._gdb_interface.read_memory(address, size) def set_register(self, reg, val): self._gdb_interface.set_register(reg, val) def get_register_from_nr(self, reg_nr): return self._gdb_interface.get_register_from_nr(reg_nr) def get_register(self, reg): return self._gdb_interface.get_register(reg) def set_breakpoint(self, address, **properties): if "thumb" in properties: del properties["thumb"] bkpt = self._gdb_interface.insert_breakpoint(address, *properties) return S2EBreakpoint(self._system, int(bkpt["bkpt"]["number"])) def execute_gdb_command(self, cmd): return self._gdb_interface.execute_gdb_command(cmd) def cont(self): self._gdb_interface.cont() def stepi(self): self._gdb_interface.stepi() def send_signal(self, signalnr): self._gdb_interface.send_signal(signalnr) def handle_gdb_async_message(self, msg): print("Received async message: '%s'" % str(msg)) if msg.type == Async.EXEC: if msg.klass == "running": self.post_event({"tags": [EVENT_RUNNING], "channel": "gdb"}) elif msg.klass == "stopped": if "reason" in msg.results and msg.results[ "reason"] == "breakpoint-hit": self.post_event({ "tags": [EVENT_STOPPED, EVENT_BREAKPOINT], "properties": { "address": int(msg.results["frame"]["addr"], 16), "bkpt_number": int(msg.results["bkptno"]) }, "channel": "gdb" }) elif "reason" in msg.results and msg.results[ "reason"] == "end-stepping-range": self.post_event({ "tags": [EVENT_STOPPED, EVENT_END_STEPPING], "properties": { "address": int(msg.results["frame"]["addr"], 16) }, "channel": "gdb" }) # elif "signal-name" in msg.results and msg.results["signal-name"] == "SIGINT": # self.post_event({"tags": [EVENT_STOPPED, EVENT_END_STEPPING], # "properties": { # "address": int(msg.results["frame"]["addr"], 16) # }, # "channel": "gdb"}) def post_event(self, evt): evt["source"] = "emulator" self._system.post_event(evt)
class S2EEmulator(Emulator): def __init__(self, s2e_configuration, qemu_configuration, output_directory, configuration_directory): self._configuration = S2EConfiguration(s2e_configuration, qemu_configuration, output_directory, configuration_directory) self._name = "s2e" from avatar.system import System self._system = System.getInstance() self._output_directory = output_directory def __str__(self): return self._name def init(self): self._configuration.write_configuration_files(self._output_directory) self._cmdline = self._configuration.get_command_line() def start(self): s2e_processes = find_processes(self._cmdline[0]) if s2e_processes: log.warn("There are still S2E instances running, NOT killing them ...") log.warn("Results might be corrupted if output files are not different") self._s2e_thread = threading.Thread(target = self.run_s2e_process) self._is_s2e_running = threading.Event() self._s2e_thread.start() #TODO: Would be nicer to put this somewhere in a function called is_running #so that other stuff can start in parallel and in the end the system waits for everything #to be running self._is_s2e_running.wait() def stop(self): if hasattr(self, "_s2e_process"): self._s2e_process.kill() def exit(self): if hasattr(self, "_remote_memory_interface"): self._remote_memory_interface.stop() print("Exiting") def run_s2e_process(self): try: log.info("Starting S2E process \r\n : %s \r\n", " ".join(["'%s'" % x for x in self._cmdline])) self._s2e_process = subprocess.Popen( self._cmdline, cwd = self._configuration.get_output_directory(), stdout = subprocess.PIPE, stderr = subprocess.PIPE) self._s2e_stdout_tee_process = subprocess.Popen( ["tee", os.path.normpath(os.path.join(self._configuration.get_output_directory(), "s2e_stdout.log"))], stdin = self._s2e_process.stdout, cwd = self._configuration.get_output_directory()) self._s2e_stderr_tee_process = subprocess.Popen( ["tee", os.path.normpath(os.path.join(self._configuration.get_output_directory(), "s2e_stderr.log"))], stdin = self._s2e_process.stderr, cwd = self._configuration.get_output_directory()) remote_target = False if "RemoteMemory" in self._configuration._s2e_configuration["plugins"]: remote_target= True if remote_target: self._remote_memory_interface = S2ERemoteMemoryInterface(self._configuration.get_remote_memory_listen_address()) self._remote_memory_interface.set_read_handler(self._notify_read_request_handler) self._remote_memory_interface.set_write_handler(self._notify_write_request_handler) self._remote_memory_interface.set_set_cpu_state_handler(self._notify_set_cpu_state_handler) self._remote_memory_interface.set_get_cpu_state_handler(self._notify_get_cpu_state_handler) self._remote_memory_interface.set_continue_handler(self._notify_continue_handler) self._remote_memory_interface.set_get_checksum_handler(self._notify_get_checksum_handler) time.sleep(2) #Wait a bit for the S2E process to start self._remote_memory_interface.start() try: gdb_path = self._configuration._s2e_configuration["gdb_path"] except KeyError: gdb_path = "arm-none-eabi-gdb" log.warn("Using default gdb executable path: %s" % gdb_path) try: gdb_additional_args = self._configuration._s2e_configuration["gdb_options"] except KeyError: gdb_additional_args = [] self._gdb_interface = GdbDebugger(gdb_executable = gdb_path, cwd = ".", additional_args = gdb_additional_args) self._gdb_interface.set_async_message_handler(self.handle_gdb_async_message) count = 10 while count != 0: try: log.debug("Trying to connect to emulator.") self._gdb_interface.connect(("tcp", "127.0.0.1", "%d" % self._configuration.get_s2e_gdb_port())) break except: count -= 1 if count > 0: log.warning("Failed to connect to emulator, retrying.") time.sleep(3) if count == 0: raise Exception("Failed to connect to emulator. Giving up!") log.info("Successfully connected to emulator.") self._is_s2e_running.set() self._s2e_process.wait() except (FileNotFoundError, KeyboardInterrupt) as e: if type(e).__name__ == "FileNotFoundError" : log.error("Wrong path for s2e") else : pass self.exit() def write_typed_memory(self, address, size, data): self._gdb_interface.write_memory(address, size, data) def read_typed_memory(self, address, size): return self._gdb_interface.read_memory(address, size) def set_register(self, reg, val): self._gdb_interface.set_register(reg, val) def get_register_from_nr(self, reg_nr): return self._gdb_interface.get_register_from_nr(reg_nr) def get_register(self, reg): return self._gdb_interface.get_register(reg) def set_breakpoint(self, address, **properties): if "thumb" in properties: del properties["thumb"] bkpt = self._gdb_interface.insert_breakpoint(address, *properties) return S2EBreakpoint(int(bkpt["bkpt"]["number"])) def execute_gdb_command(self, cmd): return self._gdb_interface.execute_gdb_command(cmd) def cont(self): self._gdb_interface.cont() def stepi(self): self._gdb_interface.stepi() def send_signal(self, signalnr): self._gdb_interface.send_signal(signalnr) def handle_gdb_async_message(self, msg): print("Received async message: '%s'" % str(msg)) if msg.type == Async.EXEC: if msg.klass == "running": self.post_event({"tags": [Event.EVENT_RUNNING], "channel": "gdb"}) elif msg.klass == "stopped": if "reason" in msg.results and msg.results["reason"] == "breakpoint-hit": self.post_event({"tags": [Event.EVENT_STOPPED, Event.EVENT_BREAKPOINT], "properties": { "address": int(msg.results["frame"]["addr"], 16), "bkpt_number": int(msg.results["bkptno"])}, "channel": "gdb"}) elif "reason" in msg.results and msg.results["reason"] == "end-stepping-range": self.post_event({"tags": [Event.EVENT_STOPPED, Event.EVENT_END_STEPPING], "properties": { "address": int(msg.results["frame"]["addr"], 16) }, "channel": "gdb"}) # elif "signal-name" in msg.results and msg.results["signal-name"] == "SIGINT": # self.post_event({"tags": [Event.EVENT_STOPPED, Event.EVENT_END_STEPPING], # "properties": { # "address": int(msg.results["frame"]["addr"], 16) # }, # "channel": "gdb"}) def post_event(self, evt): evt["source"] = "emulator" System.getInstance().post_event(evt)
class GdbserverTarget(Target): def __init__(self, system, verbose=False): self._system = system self._verbose = verbose def init(self): conf = self._system.get_configuration() assert ("avatar_configuration" in conf) assert ("target_gdb_address" in conf["avatar_configuration"]) assert (conf["avatar_configuration"]["target_gdb_address"].startswith( "tcp:")) sockaddr_str = conf["avatar_configuration"]["target_gdb_address"][4:] if "target_gdb_path" in conf["avatar_configuration"]: self.gdb_exec = conf["avatar_configuration"]["target_gdb_path"] else: self.gdb_exec = "/home/zaddach/projects/hdd-svn/gdb/gdb/gdb" log.warn( "target_gdb_path not defined in avatar configuration, using hardcoded GDB path: %s", self.gdb_exec) self._sockaddress = (sockaddr_str[:sockaddr_str.rfind(":")], int(sockaddr_str[sockaddr_str.rfind(":") + 1:])) def start(self): #TODO: Handle timeout if self._verbose: log.info("Trying to connect to target gdb server at %s:%d", self._sockaddress[0], self._sockaddress[1]) self._gdb_interface = GdbDebugger(gdb_executable=self.gdb_exec) self._gdb_interface.set_async_message_handler( self.handle_gdb_async_message) self._gdb_interface.connect( ("tcp", self._sockaddress[0], "%d" % self._sockaddress[1])) def write_typed_memory(self, address, size, data): self._gdb_interface.write_memory(address, size, data) def read_typed_memory(self, address, size): return self._gdb_interface.read_memory(address, size) def set_register(self, reg, val): self._gdb_interface.set_register(reg, val) def get_register(self, reg): return self._gdb_interface.get_register(reg) def execute_gdb_command(self, cmd): return self._gdb_interface.execute_gdb_command(cmd) def get_checksum(self, addr, size): return self._gdb_interface.get_checksum(addr, size) def stop(self): pass def set_breakpoint(self, address, **properties): if "thumb" in properties: del properties["thumb"] bkpt = self._gdb_interface.insert_breakpoint(address, *properties) return GdbBreakpoint(self._system, int(bkpt["bkpt"]["number"])) def cont(self): self._gdb_interface.cont() def handle_gdb_async_message(self, msg): print("Received async message: '%s'" % str(msg)) if msg.type == Async.EXEC: if msg.klass == "running": self._post_event({"tags": [EVENT_RUNNING], "channel": "gdb"}) elif msg.klass == "stopped": if "reason" in msg.results and msg.results[ "reason"] == "breakpoint-hit": self._post_event({ "tags": [EVENT_STOPPED, EVENT_BREAKPOINT], "properties": { "address": int(msg.results["frame"]["addr"], 16), "bkpt_number": int(msg.results["bkptno"]) }, "channel": "gdb" }) def _post_event(self, evt): evt["source"] = "target" self._system.post_event(evt) @classmethod def from_str(cls, sockaddr_str): assert (sockaddr_str.startswith("tcp:")) sockaddr = (sockaddr_str[:sockaddr_str.rfind(":")], int(sockaddr_str[sockaddr_str.rfind(":") + 1:])) return cls(sockaddr)
class GdbserverTarget(Target): def __init__(self, host, port, exec_path="gdb", options=[], log_stdout=False, fname=None): self._port = port self._host = host self._config_file = config_file self._exec_path = exec_path self._options = options self._log_stdout = log_stdout self._fname = fname def start(self): #TODO: Handle timeout if self._exec_path != "gdb" : log.warn("target_gdb_path not defined in avatar configuration, using hardcoded GDB path: %s", self._exec_path) if System(None).is_debug : log.info("Trying to connect to target gdb server at %s:%d", self._host, self._port) self._gdb_interface = GdbDebugger(gdb_executable = self._exec_path, cwd = ".", additional_args = self._options ) self._gdb_interface.set_async_message_handler(self.handle_gdb_async_message) not_started = False while not_started : try: self._gdb_interface.connect(("tcp", self._host, "%d" % self._port)) not_started = True except TimeoutError : if System(None).is_debug : log.info("Timeout... Connecting to %s:%d again ", self._host, self._port) continue def write_typed_memory(self, address, size, data): self._gdb_interface.write_memory(address, size, data) def read_typed_memory(self, address, size): return self._gdb_interface.read_memory(address, size) def set_register(self, reg, val): self._gdb_interface.set_register(reg, val) def get_register(self, reg): return self._gdb_interface.get_register(reg) def get_register_from_nr(self, num): try: return self.get_register(["r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", "cpsr"][num]) except IndexError: log.warn("get_register_from_nr called with unexpected register index %d", num) return 0 def execute_gdb_command(self, cmd): return self._gdb_interface.execute_gdb_command(cmd) def get_checksum(self, addr, size): return self._gdb_interface.get_checksum(addr, size) def stop(self): pass def set_breakpoint(self, address, **properties): if "thumb" in properties: del properties["thumb"] bkpt = self._gdb_interface.insert_breakpoint(address, *properties) return GdbBreakpoint(self._system, int(bkpt["bkpt"]["number"])) def cont(self): self._gdb_interface.cont() def handle_gdb_async_message(self, msg): print("Received async message: '%s'" % str(msg)) if msg.type == Async.EXEC: if msg.klass == "running": self._post_event({"tags": [Event.EVENT_RUNNING], "channel": "gdb"}) elif msg.klass == "stopped": if "reason" in msg.results and msg.results["reason"] == "breakpoint-hit": self._post_event({"tags": [Event.EVENT_STOPPED, Event.EVENT_BREAKPOINT], "properties": { "address": int(msg.results["frame"]["addr"], 16), "bkpt_number": int(msg.results["bkptno"])}, "channel": "gdb"}) elif "reason" in msg.results and msg.results["reason"] == "signal-received": # this is data abort try: addr = int(msg.results["frame"]["addr"], 16) except: addr = 0xDEADDEAD self._post_event({"tags": [Event.EVENT_STOPPED, Event.EVENT_SIGABRT], "properties": { "address": addr, }, "channel": "gdb"}) def _post_event(self, evt): evt["source"] = "target" self._system.post_event(evt) @classmethod def from_str(cls, sockaddr_str): assert(sockaddr_str.startswith("tcp:")) sockaddr = (sockaddr_str[:sockaddr_str.rfind(":")], int(sockaddr_str[sockaddr_str.rfind(":") + 1:])) return cls(sockaddr)
class PandaEmulator(Emulator): def __init__(self, system): super().__init__(system) self._configuration = None #TODO def init(self): log.error("Panda init called") #TODO: Parse configuration file, generate command line # to debug command the emulator #self._cmdline = ["gdb", "-ex", "handle SIG38 nostop noprint pass", "-ex", "run", "--args", "/home/vagrant/panda/qemu/arm-softmmu/qemu-system-arm", "-sdl", "-M", "versatilepb", "-kernel", "/home/vagrant/avatar-samples/qemu_uboot/u-boot", "-qmp", "tcp::4000,server,nowait", #"-gdb", "tcp::5000,server,nowait", "-S", "-panda", "avatar_memory_hooker:range_uart0=0x101f1000_0x1000,range_uart1=0x101f2000_0x1000,range_uart2=0x101f3000_0x1000,range_uart3=0x10009000_0x1000"] ## -S damit der gdb vor der ersten Instruktion abwartet pausiert. # Normal (non debug mode) self._cmdline = [ "/home/vagrant/panda/qemu/arm-softmmu/qemu-system-arm", "-sdl", "-M", "versatilepb", "-kernel", "/home/vagrant/avatar-samples/qemu_uboot/u-boot", "-qmp", "tcp::4000,server,nowait", "-gdb", "tcp::5000,server,nowait", "-S", "-panda", "avatar_memory_hooker:range_uart0=0x101f1000_0x1000,range_uart1=0x101f2000_0x1000,range_uart2=0x101f3000_0x1000,range_uart3=0x10009000_0x1000" ] # -S damit der gdb vor der ersten Instruktion abwartet pausiert. def start(self): log.info("Executing Panda process: %s", " ".join(["'%s'" % x for x in self._cmdline])) self._panda_thread = threading.Thread(target=self.run_panda_process) self._is_panda_running = threading.Event() self._panda_thread.start() #TODO: Would be nicer to put this somewhere in a function called is_running #so that other stuff can start in parallel and in the end the system waits for everything #to be running self._is_panda_running.wait() def stop(self): if hasattr(self, "_panda_process"): self._panda_process.kill() def exit(self): if hasattr(self, "_remote_memory_interface"): self._remote_memory_interface.stop() print("Exiting") def run_panda_process(self): try: log.info("Starting Panda process: %s", " ".join(["'%s'" % x for x in self._cmdline])) self._panda_process = subprocess.Popen( self._cmdline, #cwd = self._configuration.get_output_directory(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) self._panda_stdout_tee_process = subprocess.Popen( [ "tee", os.path.normpath( os.path.join(OUTPUT_DIRECTORY, "panda_stdout.log")) ], stdin=self._panda_process.stdout, cwd=OUTPUT_DIRECTORY) self._panda_stderr_tee_process = subprocess.Popen( [ "tee", os.path.normpath( os.path.join(OUTPUT_DIRECTORY, "panda_stderr.log")) ], stdin=self._panda_process.stderr, cwd=OUTPUT_DIRECTORY) self._remote_memory_interface = PandaRemoteMemoryInterface( ("127.0.0.1", 5555)) # Uebergebe callbacks, ein callback ist z.B. self._notify_read_request_handler self._remote_memory_interface.set_read_handler( self._notify_read_request_handler) self._remote_memory_interface.set_write_handler( self._notify_write_request_handler) self._remote_memory_interface.set_set_cpu_state_handler( self._notify_set_cpu_state_handler) self._remote_memory_interface.set_get_cpu_state_handler( self._notify_get_cpu_state_handler) self._remote_memory_interface.set_continue_handler( self._notify_continue_handler) self._remote_memory_interface.set_get_checksum_handler( self._system.get_target().get_checksum) # We need some time until the sockets from the RemoteMemory plugin are open time.sleep( 2 ) #Wait a bit for the Panda process to start, der socket vom Panda Plugin wird # tatsaechlich vor dem GDB-emulaor-server socket aufgemacht self._remote_memory_interface.start() # We need some time until the (potential) sockets from the QMP are open AND # until the QEMU-gdb-server socket is open time.sleep(2) self._monitor_socket = socket.create_connection( ("127.0.0.1", 4000)) try: #TODO: Path fuer GDB fuer emulator hier finden raise KeyError() #gdb_path = self._configuration._panda_configuration["emulator_gdb_path"] except KeyError: gdb_path = "arm-none-eabi-gdb" log.warn("Using default gdb executable path: %s" % gdb_path) # try: # gdb_additional_args = self._configuration._panda_configuration["emulator_gdb_additional_arguments"] # except KeyError: gdb_additional_args = [] self._gdb_interface = GdbDebugger( gdb_executable=gdb_path, cwd=".", additional_args=gdb_additional_args) self._gdb_interface.set_async_message_handler( self.handle_gdb_async_message) count = 10 while count != 0: try: log.debug("Trying to connect to emulator.") self._gdb_interface.connect( ("tcp", "127.0.0.1", "%d" % 5000)) break except: count -= 1 if count > 0: log.warning("Failed to connect to emulator, retrying.") time.sleep(3) if count == 0: raise Exception("Failed to connect to emulator. Giving up!") log.info("Successfully connected to emulator.") self._is_panda_running.set() self._panda_process.wait() except KeyboardInterrupt: pass self.exit() def enable_remote_memory(): # TODO # talk over QMP to QEMU monitor and enable remote memory, i.e. activate memory callbacks in panda # same for disabling pass # uint_8, uint_16, uint_32, ... i.e. endianess etc. def write_typed_memory(self, address, size, data): self._gdb_interface.write_memory(address, size, data) def read_typed_memory(self, address, size): return self._gdb_interface.read_memory(address, size) def set_register(self, reg, val): self._gdb_interface.set_register(reg, val) def get_register_from_nr(self, reg_nr): return self._gdb_interface.get_register_from_nr(reg_nr) def get_register(self, reg): return self._gdb_interface.get_register(reg) def set_breakpoint(self, address, **properties): if "thumb" in properties: del properties["thumb"] bkpt = self._gdb_interface.insert_breakpoint(address, *properties) return GDBBreakpoint(self._system, int(bkpt["bkpt"]["number"])) def execute_gdb_command(self, cmd): return self._gdb_interface.execute_gdb_command(cmd) def cont(self): self._gdb_interface.cont() def stepi(self): self._gdb_interface.stepi() def send_signal(self, signalnr): self._gdb_interface.send_signal(signalnr) def handle_gdb_async_message(self, msg): print("Received async message: '%s'" % str(msg)) if msg.type == Async.EXEC: if msg.klass == "running": self.post_event({"tags": [EVENT_RUNNING], "channel": "gdb"}) elif msg.klass == "stopped": if "reason" in msg.results and msg.results[ "reason"] == "breakpoint-hit": self.post_event({ "tags": [EVENT_STOPPED, EVENT_BREAKPOINT], "properties": { "address": int(msg.results["frame"]["addr"], 16), "bkpt_number": int(msg.results["bkptno"]) }, "channel": "gdb" }) elif "reason" in msg.results and msg.results[ "reason"] == "end-stepping-range": self.post_event({ "tags": [EVENT_STOPPED, EVENT_END_STEPPING], "properties": { "address": int(msg.results["frame"]["addr"], 16) }, "channel": "gdb" }) # elif "signal-name" in msg.results and msg.results["signal-name"] == "SIGINT": # self.post_event({"tags": [EVENT_STOPPED, EVENT_END_STEPPING], # "properties": { # "address": int(msg.results["frame"]["addr"], 16) # }, # "channel": "gdb"}) def post_event(self, evt): evt["source"] = "emulator" self._system.post_event(evt)