├── .gitignore ├── LICENSE ├── README.md ├── aarch64-core.xml ├── aarch64-fpu.xml ├── arm-core.xml ├── arm-neon.xml ├── arm-vfp.xml ├── arm-vfp3.xml ├── checksum.py ├── dummy_remote.py ├── machine.py ├── sample.txt ├── stub_server.py ├── target.xml └── unicorn_machine.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyGDB_remote 2 | a python GDB remote protocol implementation 3 | -------------------------------------------------------------------------------- /aarch64-core.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /aarch64-fpu.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /arm-core.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /arm-neon.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /arm-vfp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /arm-vfp3.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /checksum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | def checksum(target): 4 | sum = 0; 5 | if target is None or len(target) == 0: 6 | return "00" 7 | for c in target: 8 | sum += ord(c); 9 | result= "%02x" %( sum % 256); 10 | return result 11 | 12 | 13 | if __name__ == '__main__': 14 | #result should be '2a' 15 | print checksum("qSupported:multiprocess+;qRelocInsn+") 16 | 17 | #result should be '09' 18 | print checksum("Hc-1") 19 | -------------------------------------------------------------------------------- /dummy_remote.py: -------------------------------------------------------------------------------- 1 | 2 | import socket 3 | import re 4 | from threading import Thread,currentThread,activeCount 5 | 6 | from checksum import checksum 7 | 8 | __DEBUG__ = True 9 | 10 | class Sender: 11 | def __init__(self,conn): 12 | self.conn = conn 13 | self.last_sent = ("",True) 14 | def send(self,data,need_checksum=True): 15 | if __DEBUG__ is True:print "<- %s" % data 16 | if need_checksum: 17 | self.conn.sendall("$%s#%s" % (data,checksum(data))) 18 | else: 19 | self.conn.sendall(data) 20 | self.last_sent = (data,need_checksum) 21 | def resend(self): 22 | self.send(self.last_sent[0],self.last_sent[1]) 23 | 24 | class Packet: 25 | packetRE = re.compile(r'([\+\-]*)\$([^#]+)#([0-9a-f]{2})'); 26 | def __init__(self,raw_data): 27 | self.raw_data = raw_data 28 | self.ack = None 29 | self.command = None 30 | self.checksum = None 31 | 32 | if raw_data == "-": 33 | self.ack = "-" 34 | return 35 | 36 | if raw_data == "+": 37 | self.ack = "+" 38 | return 39 | 40 | matchObj = self.packetRE.match(raw_data) 41 | if matchObj is None: 42 | self = None 43 | print "WARN: %s can not be parsed!" % raw_data 44 | return 45 | self.ack =matchObj.group(1) 46 | self.command =matchObj.group(2) 47 | self.checksum =matchObj.group(3) 48 | 49 | def is_valid(self): 50 | if self.command is None or self.checksum is None: 51 | if self.ack is not None: 52 | return True 53 | else: 54 | return False 55 | 56 | if checksum(self.command) == self.checksum: 57 | return True 58 | else: 59 | return False 60 | 61 | class GDB_server(object): 62 | def __init__(self, host="127.0.0.1" , port=1234): 63 | self.host = host 64 | self.port = port 65 | self.ack_mode =True 66 | 67 | def start(self): 68 | self.s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 69 | self.s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 70 | self.s.bind((self.host, self.port)) 71 | self.s.listen(1) 72 | if __DEBUG__ is True:print "Server listenning %s:%d" % (self.host,self.port) 73 | self.conn,self.gdb_addr = self.s.accept() 74 | if __DEBUG__ is True:print "connet from:",self.gdb_addr 75 | self.sender = Sender(self.conn) 76 | 77 | #enter main loop 78 | while True: 79 | data = self.conn.recv(4096+8) 80 | if len(data) == 0: 81 | conn.close() 82 | print "connect lost." 83 | break 84 | 85 | #pump up packet 86 | if __DEBUG__ is True:print "raw data: %s" % data 87 | pack = Packet(data) 88 | self.packet_handle(pack) 89 | 90 | def packet_handle(self,packet): 91 | '''Abstract Method''' 92 | pass 93 | 94 | def send(self,data,need_checksum=True): 95 | self.sender.send(data,need_checksum) 96 | 97 | class Dummy_device(GDB_server): 98 | def packet_handle(self,packet): 99 | 100 | pass 101 | 102 | class Proxy_server(GDB_server): 103 | def __init__(self,host,port): 104 | super(Proxy_server,self).__init__(host,port) 105 | self.socks = None 106 | 107 | def revc_from_qemu(self): 108 | while True: 109 | try: 110 | res_data = self.socks.recv(4096) 111 | print("GOT: %s" % res_data) 112 | except socket.timeout: 113 | print("qemu gdb time out!") 114 | res_data = "-" 115 | self.send(res_data, False) 116 | def connect_real(self,host="127.0.0.1",port=1234): 117 | if self.socks is not None: 118 | return 119 | socks = socket.socket() 120 | #socks.settimeout(1) 121 | socks.connect((host,port)) 122 | self.socks = socks 123 | Thread(target = self.revc_from_qemu, args =()).start() 124 | 125 | def packet_handle(self,packet): 126 | self.connect_real() 127 | self.socks.sendall(packet.raw_data) 128 | 129 | if __name__ == "__main__": 130 | server = Proxy_server("127.0.0.1", 51234) 131 | server.start() 132 | 133 | if __name__ == "__main__old": 134 | s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 135 | s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 136 | s.bind(('127.0.0.1',1234)) 137 | s.listen(1) 138 | 139 | ack_mode = True 140 | while True: 141 | conn,addr = s.accept() 142 | print "connet from:",addr 143 | sender = Sender(conn) 144 | while True: 145 | data = conn.recv(4096+8) 146 | if len(data) == 0: 147 | conn.close() 148 | print "connect lost." 149 | break 150 | print "-> %s" % data 151 | 152 | pack = Packet(data) 153 | if not pack.is_valid(): 154 | #sender.send("-",False) 155 | print "Packet checksum fail! ack= %s , command = %s, checksum = %s" % (pack.ack,pack.command,pack.checksum) 156 | continue 157 | if pack.ack == "-": 158 | sender.resend() 159 | continue 160 | 161 | if pack.ack[0] == "+" or pack.ack[0] == "-" or pack.ack == "-+" and pack.checksum is None: 162 | continue 163 | 164 | if ack_mode: 165 | sender.send("+",True) 166 | if pack.command.split(":")[0] == "qSupported": 167 | sender.send("PacketSize=1000;QStartNoAckMode+;multiprocess-;") 168 | #sender.send("PacketSize=1000;qXfer:features:read+") 169 | #sender.send("") 170 | if pack.command == "QStartNoAckMode": 171 | sender.send("OK") 172 | ack_mode = False 173 | if pack.command == "Hg0" or pack.command == "Hc-1": #select any thread or set target thread 174 | sender.send("OK") 175 | 176 | if pack.command == "?": 177 | sender.send("T05thread:01;") 178 | 179 | if pack.command == "qC": #current thread id. 180 | sender.send("QC0") 181 | 182 | if pack.command == "qAttached": #attached ? 183 | sender.send("1") 184 | 185 | if pack.command == "qOffsets": #section reloc info 186 | sender.send("Text=0;Data=0;Bss=0") 187 | if pack.command == "g": 188 | sender.send("0100015c"*15) 189 | if pack.command == "pf": 190 | sender.send("342d0001") 191 | if pack.command == "qSymbol::": 192 | sender.send("OK") 193 | if pack.command == "qTStatus": 194 | #sender.send("tnotrun:0") 195 | sender.send("") 196 | #if data == "+": 197 | #continue 198 | #if data == "-": 199 | #sender.resend() 200 | #continue 201 | #conn.send("+") 202 | #m = re.match(r'^\+?\$qSupported:.*',data) 203 | #if m is not None: 204 | #sender.send("PacketSize=512") 205 | #m = re.match(r'\+?\$Hg0.*',data) 206 | #if m is not None: 207 | #sender.send("OK") 208 | -------------------------------------------------------------------------------- /machine.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import struct 3 | 4 | __DEBUG__ = True 5 | 6 | class Machine(object): 7 | 8 | 9 | def __init__(self,bit=64): 10 | self.maxbit = bit 11 | self.reg_pack_char = None 12 | if bit == 64 :self.reg_pack_char = "Q" 13 | if bit == 32 :self.reg_pack_char = "I" 14 | def _bin2hex(self,data): 15 | return binascii.b2a_hex(struct.pack(self.reg_pack_char,data)) 16 | 17 | def get_machine_maxbits(self): 18 | return self.maxbit 19 | 20 | def read_reg(self,regnum): 21 | pass 22 | 23 | def get_regs(self): 24 | pass 25 | 26 | def write_reg(self,regnum,value): 27 | pass 28 | 29 | def read_mem(self,start,size): 30 | pass 31 | 32 | def write_mem(self,start,size,buf): 33 | pass 34 | 35 | def get_cpus(self): 36 | pass 37 | 38 | def get_cpu_info(self,cpunum): 39 | pass 40 | 41 | def run_break(self): 42 | pass 43 | 44 | def run_continue(self,addr): 45 | pass 46 | 47 | def run_single_step(self,addr): 48 | pass 49 | 50 | def set_single_inst(self): 51 | pass 52 | 53 | def read_mem_as_hexstr(self,addr,size): 54 | mem = self.read_mem(addr,size) 55 | if mem is None: 56 | return mem 57 | else: 58 | return binascii.b2a_hex(mem) 59 | 60 | def write_mem_as_hexstr(self,addr,size, buf): 61 | res = self.write_mem(addr,size,binascii.a2b_hex(buf)) 62 | if res is None: 63 | return res 64 | else: 65 | return "OK" 66 | def read_reg_as_hexstr(self,regnum): 67 | reg = self.read_reg(regnum); 68 | return self._bin2hex(reg) 69 | 70 | def get_regs_as_hexstr(self): 71 | regs = self.get_regs(); 72 | if __DEBUG__: print "@get_regs_with_hexstr: reg= ",regs 73 | hexstr = "" 74 | for reg in regs: 75 | hexstr = hexstr + self._bin2hex(reg) 76 | return hexstr 77 | 78 | def set_regs_with_hexstr(self,hexstr): 79 | binarr = binascii.a2b_hex(hexstr) 80 | binarr_split = [binarr[i:i+self.get_machine_maxbits()/8] for i in xrange(0,len(binarr),self.get_machine_maxbits()/8)] 81 | if __DEBUG__: print "@set_regs_with_hexstr: %d regs found. " % len(binarr_split) 82 | 83 | self.set_regs([struct.unpack(self.reg_pack_char,reg)[0] for reg in binarr_split]) 84 | def get_target_xml(self): 85 | pass 86 | class Dummy_machine(Machine): 87 | def __init__(self): 88 | super(Dummy_machine,self).__init__(); 89 | 90 | 91 | -------------------------------------------------------------------------------- /sample.txt: -------------------------------------------------------------------------------- 1 | python dumy_remote.py 2 | Server listenning 127.0.0.1:51234 3 | connet from: ('127.0.0.1', 35480) 4 | raw data: +$qSupported:multiprocess+;qRelocInsn+#2a 5 | GOT: +$PacketSize=1000;qXfer:features:read+#cc 6 | <- +$PacketSize=1000;qXfer:features:read+#cc 7 | raw data: +$Hg0#df 8 | GOT: +$OK#9a 9 | <- +$OK#9a 10 | raw data: +$qXfer:features:read:target.xml:0,ffb#79 11 | GOT: + 12 | <- + 13 | GOT: $laarch64#b6 14 | <- $laarch64#b6 15 | raw data: + 16 | raw data: $qXfer:features:read:aarch64-core.xml:0,ffb#31 17 | GOT: + 18 | <- + 19 | GOT: $l 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | #2d 66 | <- $l 67 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | #2d 113 | raw data: + 114 | raw data: $qXfer:features:read:aarch64-fpu.xml:0,ffb#d3 115 | GOT: + 116 | <- + 117 | GOT: $m 118 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 176 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | #2e 267 | <- $l /> 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | #2e 297 | raw data: + 298 | raw data: $?#3f 299 | GOT: + 300 | <- + 301 | GOT: $T05thread:01;#07 302 | <- $T05thread:01;#07 303 | raw data: +$Hc-1#09 304 | GOT: + 305 | <- + 306 | GOT: $OK#9a 307 | <- $OK#9a 308 | raw data: +$qAttached#8f 309 | GOT: + 310 | <- + 311 | GOT: $1#31 312 | <- $1#31 313 | raw data: + 314 | raw data: $qOffsets#4b 315 | GOT: +$#00 316 | <- +$#00 317 | raw data: + 318 | raw data: $g#67 319 | GOT: +$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000cd030040#f7 320 | <- +$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000cd030040#f7 321 | raw data: + 322 | raw data: $m81000000,4#56 323 | GOT: +$44070010#90 324 | <- +$44070010#90 325 | raw data: + 326 | raw data: $m80fffffc,4#96 327 | GOT: +$00000000#80 328 | <- +$00000000#80 329 | raw data: + 330 | raw data: $m81000000,4#56 331 | GOT: +$44070010#90 332 | <- +$44070010#90 333 | raw data: + 334 | raw data: $qSymbol::#5b 335 | GOT: +$#00 336 | <- +$#00 337 | raw data: + 338 | raw data: $qTStatus#49 339 | GOT: + 340 | <- + 341 | GOT: $#00 342 | <- $#00 343 | raw data: + 344 | raw data: $qTStatus#49 345 | GOT: +$#00 346 | <- +$#00 347 | raw data: + 348 | raw data: $Z0,ffff00004008bd64,4#6a 349 | GOT: + 350 | <- + 351 | GOT: $OK#9a 352 | <- $OK#9a 353 | raw data: + 354 | raw data: $vCont?#49 355 | GOT: + 356 | <- + 357 | GOT: $vCont;c;C;s;S#62 358 | <- $vCont;c;C;s;S#62 359 | raw data: + 360 | raw data: $vCont;s:1;c#c1 361 | GOT: + 362 | <- + 363 | GOT: $T05thread:01;#07 364 | <- $T05thread:01;#07 365 | raw data: + 366 | raw data: $g#67 367 | GOT: +$0000000000000000000000000000000000000000000000000000000000000000e8000081000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400008100000000cd030040#41 368 | <- +$0000000000000000000000000000000000000000000000000000000000000000e8000081000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400008100000000cd030040#41 369 | raw data: + 370 | raw data: $m81000004,4#5a 371 | GOT: +$65060058#9e 372 | <- +$65060058#9e 373 | raw data: +$m81000000,4#56 374 | GOT: +$44070010#90 375 | <- +$44070010#90 376 | raw data: + 377 | raw data: $m81000004,4#5a 378 | GOT: +$65060058#9e 379 | <- +$65060058#9e 380 | raw data: + 381 | raw data: $z0,ffff00004008bd64,4#8a 382 | GOT: +$OK#9a 383 | <- +$OK#9a 384 | raw data: + 385 | raw data: $p42#d6 386 | GOT: +$00000000#80 387 | <- +$00000000#80 388 | raw data: + 389 | raw data: $p43#d7 390 | GOT: + 391 | <- + 392 | GOT: $00000000#80 393 | <- $00000000#80 394 | raw data: + 395 | 396 | 397 | 398 | 399 | raw data: $qTStatus#49 400 | GOT: +$#00 401 | <- +$#00 402 | raw data: + 403 | raw data: $Z0,ffff00004008bd64,4#6a 404 | GOT: +$OK#9a 405 | <- +$OK#9a 406 | raw data: + 407 | raw data: $vCont;s:1;c#c1 408 | GOT: + 409 | <- + 410 | GOT: $T05thread:01;#07 411 | <- $T05thread:01;#07 412 | raw data: + 413 | raw data: $g#67 414 | GOT: + 415 | <- + 416 | GOT: $0000000000000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#8b 417 | <- $0000000000000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#8b 418 | raw data: + 419 | raw data: $m81000008,4#5e 420 | GOT: +$9f0005eb#2b 421 | <- +$9f0005eb#2b 422 | raw data: + 423 | raw data: $m81000004,4#5a 424 | GOT: +$65060058#9e 425 | <- +$65060058#9e 426 | raw data: + 427 | raw data: $m81000008,4#5e 428 | GOT: +$9f0005eb#2b 429 | <- +$9f0005eb#2b 430 | raw data: + 431 | raw data: $z0,ffff00004008bd64,4#8a 432 | GOT: + 433 | <- + 434 | GOT: $OK#9a 435 | <- $OK#9a 436 | raw data: + 437 | 438 | 439 | i r 440 | raw data: $p42#d6 441 | GOT: +$00000000#80 442 | <- +$00000000#80 443 | raw data: + 444 | raw data: $p43#d7 445 | GOT: +$00000000#80 446 | <- +$00000000#80 447 | raw data: + 448 | raw data: $mffff000000000000,4#a5 449 | GOT: + 450 | <- + 451 | GOT: $00000000#80 452 | <- $00000000#80 453 | raw data: + 454 | raw data: $mffff000000000000,4#a5 455 | GOT: + 456 | <- + 457 | GOT: $00000000#80 458 | <- $00000000#80 459 | raw data: + 460 | raw data: $mffff000000000004,4#a9 461 | GOT: +$00000000#80 462 | <- +$00000000#80 463 | raw data: + 464 | raw data: $mffff000000000008,4#ad 465 | GOT: +$00000000#80 466 | <- +$00000000#80 467 | raw data: + 468 | raw data: $mffff00000000000c,4#d8 469 | GOT: +$00000000#80 470 | <- +$00000000#80 471 | raw data: + 472 | raw data: $mffff000000000010,4#a6 473 | GOT: +$00000000#80 474 | <- +$00000000#80 475 | raw data: + 476 | raw data: $mffff000000000014,4#aa 477 | GOT: +$00000000#80 478 | <- +$00000000#80 479 | raw data: + 480 | raw data: $mffff000000000018,4#ae 481 | GOT: +$00000000#80 482 | <- +$00000000#80 483 | raw data: + 484 | raw data: $mffff00000000001c,4#d9 485 | GOT: +$00000000#80 486 | <- +$00000000#80 487 | raw data: + 488 | raw data: $P0=0100000000000000#be 489 | GOT: + 490 | <- + 491 | GOT: $OK#9a 492 | <- $OK#9a 493 | raw data: + 494 | raw data: $g#67 495 | GOT: + 496 | <- + 497 | GOT: $0100000000000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#8c 498 | <- $0100000000000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#8c 499 | raw data: + 500 | raw data: $m81000008,4#5e 501 | GOT: +$9f0005eb#2b 502 | <- +$9f0005eb#2b 503 | raw data: + 504 | raw data: $m81000004,4#5a 505 | GOT: +$65060058#9e 506 | <- +$65060058#9e 507 | raw data: + 508 | raw data: $m81000008,4#5e 509 | GOT: +$9f0005eb#2b 510 | <- +$9f0005eb#2b 511 | raw data: + 512 | raw data: $P0=0200000000000000#bf 513 | GOT: +$OK#9a 514 | <- +$OK#9a 515 | raw data: + 516 | raw data: $g#67 517 | GOT: +$0200000000000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#8d 518 | <- +$0200000000000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#8d 519 | raw data: + 520 | raw data: $m81000008,4#5e 521 | GOT: + 522 | <- + 523 | GOT: $9f0005eb#2b 524 | <- $9f0005eb#2b 525 | raw data: + 526 | raw data: $m81000004,4#5aOT: + 527 | <- + 528 | GOT: $65060058#9e 529 | <- $65060058#9e 530 | raw data: + 531 | raw data: $m81000008,4#5e 532 | GOT: + 533 | <- + 534 | GOT: $9f0005eb#2b 535 | <- $9f0005eb#2b 536 | raw data: + 537 | raw data: $P0=7856341200000000#e1 538 | GOT: + 539 | <- + 540 | GOT: $OK#9a 541 | <- $OK#9a 542 | raw data: + 543 | raw data: $g#67 544 | GOT: +$7856341200000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#af 545 | <- +$7856341200000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#af 546 | raw data: + 547 | raw data: $m81000008,4#5e 548 | GOT: +$9f0005eb#2b 549 | <- +$9f0005eb#2b 550 | raw data: + 551 | raw data: $m81000004,4#5a 552 | GOT: +$65060058#9e 553 | <- +$65060058#9e 554 | raw data: + 555 | raw data: $m81000008,4#5e 556 | GOT: +$9f0005eb#2b 557 | <- +$9f0005eb#2b 558 | raw data: + 559 | raw data: $P0=0156341200000000#d3 560 | GOT: +$OK#9a 561 | <- +$OK#9a 562 | raw data: + 563 | raw data: $g#67 564 | GOT: +$0156341200000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#a1 565 | <- +$0156341200000000000000000000000000000000000000000000000000000000e800008100000000e800008100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008100000000cd030040#a1 566 | raw data: + 567 | raw data: $m81000008,4#5e 568 | GOT: + 569 | <- + 570 | GOT: $9f0005eb#2b 571 | <- $9f0005eb#2b 572 | raw data: +$m81000004,4#5a 573 | GOT: + 574 | <- + 575 | GOT: $65060058#9e 576 | <- $65060058#9e 577 | raw data: + 578 | raw data: $m81000008,4#5e 579 | GOT: +$9f0005eb#2b 580 | <- +$9f0005eb#2b 581 | raw data: + -------------------------------------------------------------------------------- /stub_server.py: -------------------------------------------------------------------------------- 1 | 2 | import re 3 | import socket 4 | 5 | from checksum import checksum 6 | from threading import Thread,currentThread,activeCount 7 | 8 | __DEBUG__ = True 9 | 10 | class Stub_server(object): 11 | def __init__(self, machine): 12 | self.socks = None 13 | self.last_send = None 14 | self.conn = None 15 | self.gdb_addr = None 16 | self.need_checksum = True 17 | self.RECV_SIZE = 16388 18 | self.machine = machine 19 | 20 | 21 | def start(self,host="127.0.0.1",port=1234): 22 | self.host = host 23 | self.port = port 24 | s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 25 | s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 26 | s.bind((self.host, self.port)) 27 | s.listen(1) 28 | self.socks = s 29 | if __DEBUG__ is True:print "Server listenning %s:%d" % (self.host,self.port) 30 | self.conn,self.gdb_addr = s.accept() 31 | if __DEBUG__ is True:print "connet from:",self.gdb_addr 32 | while True: 33 | data = self.conn.recv(self.RECV_SIZE) 34 | if __DEBUG__:print "--> %s" % data 35 | if len(data) == 0: 36 | self.conn.close() 37 | print "connect lost." 38 | break 39 | ##handle with multi-thread 40 | #Thread(target = self.sequence_handle, args =(data,)).start() 41 | self.sequence_handle(data) 42 | 43 | 44 | def send(self, data): 45 | self.last_send = data 46 | if __DEBUG__:print "<-- %s" % data 47 | self.conn.sendall(data) 48 | pass 49 | 50 | def resend(self): 51 | self.send(self.last_send) 52 | 53 | def send_cmd(self, cmd_string): 54 | self.send("$%s#%s" % (cmd_string,checksum(cmd_string))) 55 | 56 | def sequence_handle(self,buf): 57 | if buf is None or len(buf)==0: 58 | print "Waring: buf is None or empty." 59 | return 60 | while len(buf) > 0: 61 | if buf[0]=="+": 62 | buf = buf[1:] 63 | continue 64 | if buf[0]=="\x03": 65 | if __DEBUG__:print "recv \\x03, break." 66 | buf = buf[1:] 67 | self.machine.run_break() 68 | #self.send_cmd("T02thread:01;") 69 | continue 70 | if buf[0]=='-': 71 | if __DEBUG__:print "Got -, resend." 72 | self.resend() 73 | buf = buf[1:] 74 | continue 75 | if buf[0]=="$": 76 | if __DEBUG__:print "Got cmd, %s" % buf 77 | mobj = re.match(r'^\$([^#]+)#([0-9a-f]{2}$)', buf) 78 | if mobj is None: 79 | print "Waring: Bad format cmd found! cmd= %s" % buf 80 | continue 81 | 82 | cmd = mobj.groups()[0] 83 | chk_sum_value = mobj.groups()[1] 84 | 85 | if __DEBUG__:print "cmd = %s, checksum = %s" % (cmd, chk_sum_value) 86 | 87 | if len("$") + len(cmd) + len("#") + len(chk_sum_value) != len(buf): 88 | print "Waring: multi-cmd received! buf= %s" % (buf) 89 | 90 | if checksum(cmd) != chk_sum_value: 91 | print "Waring: checksum mismatch! checksum(cmd) = %s, chk_sum_value = %s" % (checksum(cmd), chk_sum_value) 92 | self.send("-") #request gdb to send commmand again. 93 | break #ignore this pack. 94 | 95 | 96 | self.cmd_handle(cmd) 97 | break 98 | 99 | def cmd_handle(self, cmd): 100 | if cmd is None or len(cmd) < 1: 101 | print "Waring: cmd is None or empty! cmd = %s" % cmd 102 | self.send("-") 103 | return 104 | 105 | #ack, cmd received. 106 | self.send("+") 107 | m = None 108 | m = re.match(r'qSupported:(.*)',cmd) #qSupported:multiprocess+;qRelocInsn+": 109 | if m is not None: 110 | self.send_cmd("PacketSize=%x;qXfer:features:read+" % (self.RECV_SIZE - 4)) 111 | return 112 | 113 | if cmd == "Hg0": 114 | self.send_cmd("OK") 115 | return 116 | m = None 117 | m = re.match(r'qXfer:features:read:(.*\.xml).*', cmd) 118 | if m is not None and len(m.groups()) > 0: 119 | read_xml = "l" 120 | target_file = m.groups()[0] 121 | if target_file == "target.xml": 122 | read_xml = read_xml + self.machine.get_target_xml() 123 | else: 124 | with open(target_file,"r") as f: 125 | read_xml = read_xml + f.read(); 126 | self.send_cmd(read_xml) 127 | return 128 | if cmd == "qAttached": 129 | self.send_cmd("1") 130 | return 131 | if cmd == "qOffsets": 132 | self.send_cmd("") 133 | return 134 | if cmd == "?": 135 | self.send_cmd("T05thread:01;") 136 | return 137 | if cmd == "Hc-1": 138 | self.send_cmd("OK") 139 | return 140 | if cmd == "qfThreadInfo": 141 | self.send_cmd("m1") 142 | return 143 | if cmd == "qsThreadInfo": 144 | self.send_cmd("l") 145 | return 146 | if cmd == "g": 147 | #self.send_cmd("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000cd030040") 148 | #print len("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000cd030040") 149 | self.send_cmd(self.machine.get_regs_as_hexstr()) 150 | return 151 | m = re.match(r'G([0-9a-fA-F]+)',cmd) 152 | if m is not None: 153 | hexstr = m.groups()[0] 154 | self.machine.set_regs_with_hexstr(hexstr) 155 | 156 | m = re.match(r'm([a-fA-F0-9]+),([0-9a-fA-F]+)',cmd) 157 | if m is not None: 158 | if __DEBUG__:print "reading mem: %x size: %d" % (int(m.groups()[0],16), int (m.groups()[1],16)) 159 | #self.send_cmd("00000000") 160 | read_str = self.machine.read_mem_as_hexstr(int(m.groups()[0],16), int (m.groups()[1],16)) 161 | if read_str is None: 162 | 163 | #some old urgly gdb can not afford the E00 164 | #self.send_cmd("E00") 165 | self.send_cmd("00") 166 | else: 167 | self.send_cmd(read_str) 168 | return 169 | m = re.match(r'M([a-fA-F0-9]+),([0-9a-fA-F]+):([0-9a-fA-F]+)',cmd) 170 | if m is not None: 171 | if __DEBUG__:print "write mem: %x size: %d" % (int(m.groups()[0],16), int (m.groups()[1],16)) 172 | #self.send_cmd("00000000") 173 | write_res = self.machine.write_mem_as_hexstr(int(m.groups()[0],16), int (m.groups()[1],16),m.groups()[2] ) 174 | if write_res is None: 175 | self.send_cmd("E00") 176 | else: 177 | self.send_cmd("OK") 178 | return 179 | 180 | m = re.match(r'c([0-9a-fA-F]*)',cmd) 181 | if m is not None: 182 | if __DEBUG__:print "continue!" 183 | addr = m.groups()[0] 184 | if addr is None or len(addr) == 0: 185 | addr = None 186 | else: 187 | addr = int(addr,16) 188 | def run_continue_thread_func(): 189 | res = self.machine.run_continue(addr) 190 | if res is None: 191 | self.send_cmd("E00") 192 | else: 193 | self.send_cmd("T05thread:01;") 194 | Thread(target = run_continue_thread_func, args=()).start() 195 | return 196 | 197 | if cmd == "s": 198 | self.machine.set_single_inst() 199 | def run_continue_thread_func(): 200 | res = self.machine.run_continue(None) 201 | if res is None: 202 | self.send_cmd("E00") 203 | else: 204 | self.send_cmd("T05thread:01;") 205 | Thread(target = run_continue_thread_func, args=()).start() 206 | return 207 | if cmd == "qSymbol::": 208 | self.send_cmd("OK") 209 | return 210 | 211 | if cmd == "qTStatus": 212 | self.send_cmd("T0") 213 | return 214 | 215 | print "Waring: cmd not handled! cmd = %s" % cmd 216 | self.send_cmd("") 217 | 218 | if __name__ == "__main__": 219 | import unicorn_machine 220 | #um = unicorn_machine.Unicorn_machine_aarch64() 221 | um = unicorn_machine.Unicorn_machine_arm() 222 | server = Stub_server(um) 223 | 224 | import sys 225 | #print sys.argv[0] 226 | if sys.argv[0] == '/usr/bin/ipython': 227 | print "Run under ipython." 228 | server_thread = Thread(target=server.start, args=()) 229 | server_thread.start() 230 | else: 231 | server.start() 232 | -------------------------------------------------------------------------------- /target.xml: -------------------------------------------------------------------------------- 1 | aarch64 2 | -------------------------------------------------------------------------------- /unicorn_machine.py: -------------------------------------------------------------------------------- 1 | import unicorn 2 | #from unicorn import * 3 | #from unicorn.arm64_const import * 4 | #from unicorn.arm_const import * 5 | import machine 6 | 7 | __DEBUG__ = True 8 | 9 | class Unicorn_machine(machine.Machine): 10 | 11 | 12 | 13 | def __init__(self,arch=unicorn.UC_ARCH_ARM64,mode=unicorn.UC_MODE_ARM,write_auto_map = True): 14 | bit = None 15 | if arch == unicorn.UC_ARCH_ARM64: 16 | bit = 64 17 | else: 18 | bit = 32 19 | super(Unicorn_machine, self).__init__(bit) 20 | self.mu = unicorn.Uc(arch,mode) 21 | self.mu.hook_add(unicorn.UC_HOOK_MEM_UNMAPPED,self._uc_hook_mem_unmapped) 22 | 23 | #force UC run every instruction instead of block 24 | self.mu.hook_add(unicorn.UC_HOOK_CODE,self._uc_hook_code) 25 | 26 | self.write_auto_map = write_auto_map 27 | 28 | self.last_pc = None 29 | 30 | self.single_inst_state = 0 31 | 32 | def _uc_hook_code(self,handle,pc,size,user_data): 33 | #print("running: %x") % (pc) 34 | self.last_pc = pc 35 | if self.single_inst_state == 1: 36 | self.single_inst_state = 2 37 | elif self.single_inst_state == 2: 38 | self.single_inst_state = 3 39 | if __DEBUG__:print "Single instruction run end. break." 40 | self.run_break() 41 | 42 | def _uc_hook_mem_unmapped(self,handle, access, address, size, value, user_data): 43 | print("Waring:>>> uc hook type=0x%x addr at 0x%x, size = 0x%x, value=0x%x, user_data=0x%x" %(access,address, size,value,0)) 44 | #self.mu.emu_stop() 45 | if __DEBUG__: 46 | print "Machine state:" 47 | print "PC: 0x%x" % self.mu.reg_read(self.uc_pc_reg) 48 | for i in self.mu.mem_regions(): 49 | print "[ 0x%x , 0x%x ] flag=0x%x" % i 50 | 51 | def read_reg(regnum): 52 | pass 53 | 54 | def write_reg(regnum,value): 55 | pass 56 | 57 | def get_regs(self): 58 | regs = list() 59 | for reg_name in self.uc_gen_regs: 60 | regs.append(self.mu.reg_read(reg_name)) 61 | nzcv = self.mu.reg_read(self.uc_nzcv_reg) 62 | cpsr = nzcv 63 | regs.append(cpsr) 64 | return regs 65 | 66 | def set_regs(self,regs): 67 | cur_index = 0 68 | for reg_name in self.uc_gen_regs: 69 | self.mu.reg_write(reg_name, regs[cur_index]) 70 | cur_index = cur_index + 1 71 | 72 | self.mu.reg_write(self.uc_nzcv_reg, regs[cur_index]) 73 | 74 | def read_mem(self,start,size): 75 | try: 76 | mem = self.mu.mem_read(start,size) 77 | except unicorn.UcError,e: 78 | print "Waring:[%s] read bad address=0x%x size=0x%x" % (e,start,size) 79 | return None 80 | return mem 81 | 82 | def write_mem(self,start,size,buf): 83 | try: 84 | self.mu.mem_write(start,buf) 85 | except unicorn.UcError,e: 86 | print "Waring:[%s] write bad address=0x%x size=0x%x len(buf)=0x%x" % (e,start,size,len(buf)) 87 | if self.write_auto_map: 88 | tunc_addr = start & 0xfffffffffffff000 89 | round_size = ((size+start-tunc_addr-1) & 0xfffffffffffff000)+0x1000; 90 | if __DEBUG__:print "But write_auto_map is on. let's map it automaticly. addr = 0x%x size = 0x%x" % (tunc_addr,round_size) 91 | try: 92 | for i in self.mu.mem_regions(): 93 | if tunc_addr <= i[1] and tunc_addr >= i[0]: 94 | #some area already mapped... 95 | round_size = round_size - (i[1]-tunc_addr) - 1 96 | tunc_addr = i[1] + 1 97 | break 98 | 99 | if __DEBUG__:print "addjusted . addr = 0x%x size = 0x%x" % (tunc_addr,round_size) 100 | if round_size < 4090: 101 | print "Waring: no need to map!!!!" 102 | #round_size = 4096 103 | self.mu.mem_map(tunc_addr,round_size) 104 | except unicorn.UcError,e: 105 | print "Waring:[%s] auto map failed can not write!!! " % e 106 | for i in self.mu.mem_regions(): 107 | print "start 0x%x end 0x%x flag 0x%x" % i 108 | try: 109 | self.mu.mem_write(start,buf) 110 | return "OK" 111 | except unicorn.UcError,e: 112 | print "Waring:[%s] still can not write!!! " % e 113 | return None 114 | return None 115 | return "OK" 116 | 117 | def run_break(self): 118 | if __DEBUG__:print "run_break called." 119 | self.mu.emu_stop() 120 | if self.last_pc is not None: 121 | pc = self.mu.reg_read(self.uc_pc_reg) 122 | if __DEBUG__:print "last pc from hook: %x ,pc from UC: %x" % (self.last_pc, pc) 123 | if pc != self.last_pc: 124 | print "Waring: reg_read pc: %x last_pc: %x. FIX IT." % (pc ,self.last_pc) 125 | self.mu.reg_write(self.uc_pc_reg,self.last_pc) 126 | else: 127 | print "Waring: _uc_hook_code not called." 128 | 129 | def run_continue(self,start_addr,end_addr = 0xfffffffffffffffc): 130 | if start_addr is None: 131 | start_addr = self.mu.reg_read(self.uc_pc_reg) 132 | if __DEBUG__:print "unicorn i ki ma su. addr=0x%x" % start_addr 133 | try: 134 | self.mu.emu_start(start_addr, end_addr) 135 | if __DEBUG__:print "unicorn stopped! pc=%x" % self.mu.reg_read(self.uc_pc_reg) 136 | if self.single_inst_state == 3: 137 | #UC will set pc back to the last one. Seems to be a bug. 138 | pc = self.mu.reg_read(self.uc_pc_reg) 139 | if __DEBUG__:print "need adjust PC from %x to %x after single inst mode" % (pc,self.last_pc) 140 | self.mu.reg_write(self.uc_pc_reg, self.last_pc) 141 | self.single_inst_state = 0 142 | except unicorn.UcError,e: 143 | print "Waring:[%s] continue failed." % e 144 | self.run_break() 145 | return None 146 | return "OK" 147 | 148 | def set_single_inst(self): 149 | self.single_inst_state = 1 150 | 151 | def get_cpus(): 152 | pass 153 | 154 | def get_cpu_info(): 155 | pass 156 | 157 | def get_current_el(): 158 | pass 159 | def get_target_xml(self): 160 | return """aarch64""" 161 | 162 | class Unicorn_machine_aarch64(Unicorn_machine): 163 | def __init__(self): 164 | super(Unicorn_machine_aarch64,self).__init__() 165 | self.mu.mem_map(0x80000000, 128*1024*1024) #ram for qemu virt machine, 128M 166 | if __DEBUG__: 167 | #map a test area 168 | self.mu.mem_map(0xfffffffffffff000, 4*1024) 169 | 170 | self.uc_gen_regs = [ 171 | unicorn.arm64_const.UC_ARM64_REG_X0, 172 | unicorn.arm64_const.UC_ARM64_REG_X1, 173 | unicorn.arm64_const.UC_ARM64_REG_X2, 174 | unicorn.arm64_const.UC_ARM64_REG_X3, 175 | unicorn.arm64_const.UC_ARM64_REG_X4, 176 | unicorn.arm64_const.UC_ARM64_REG_X5, 177 | unicorn.arm64_const.UC_ARM64_REG_X6, 178 | unicorn.arm64_const.UC_ARM64_REG_X7, 179 | unicorn.arm64_const.UC_ARM64_REG_X8, 180 | unicorn.arm64_const.UC_ARM64_REG_X9, 181 | unicorn.arm64_const.UC_ARM64_REG_X10, 182 | unicorn.arm64_const.UC_ARM64_REG_X11, 183 | unicorn.arm64_const.UC_ARM64_REG_X12, 184 | unicorn.arm64_const.UC_ARM64_REG_X13, 185 | unicorn.arm64_const.UC_ARM64_REG_X14, 186 | unicorn.arm64_const.UC_ARM64_REG_X15, 187 | unicorn.arm64_const.UC_ARM64_REG_X16, 188 | unicorn.arm64_const.UC_ARM64_REG_X17, 189 | unicorn.arm64_const.UC_ARM64_REG_X18, 190 | unicorn.arm64_const.UC_ARM64_REG_X19, 191 | unicorn.arm64_const.UC_ARM64_REG_X20, 192 | unicorn.arm64_const.UC_ARM64_REG_X21, 193 | unicorn.arm64_const.UC_ARM64_REG_X22, 194 | unicorn.arm64_const.UC_ARM64_REG_X23, 195 | unicorn.arm64_const.UC_ARM64_REG_X24, 196 | unicorn.arm64_const.UC_ARM64_REG_X25, 197 | unicorn.arm64_const.UC_ARM64_REG_X26, 198 | unicorn.arm64_const.UC_ARM64_REG_X27, 199 | unicorn.arm64_const.UC_ARM64_REG_X28, 200 | unicorn.arm64_const.UC_ARM64_REG_X29, 201 | unicorn.arm64_const.UC_ARM64_REG_X30, 202 | unicorn.arm64_const.UC_ARM64_REG_SP, 203 | unicorn.arm64_const.UC_ARM64_REG_PC 204 | ] 205 | self.uc_nzcv_reg = unicorn.arm64_const.UC_ARM64_REG_NZCV 206 | self.uc_pc_reg = unicorn.arm64_const.UC_ARM64_REG_PC 207 | 208 | class Unicorn_machine_arm(Unicorn_machine): 209 | 210 | 211 | def __init__(self): 212 | super(Unicorn_machine_arm,self).__init__(unicorn.UC_ARCH_ARM,unicorn.UC_MODE_ARM,True) 213 | self.mu.mem_map(0x60000000, 128*1024*1024) #ram for qemu vexpress machine, 128M 214 | if __DEBUG__: 215 | #map a test area 216 | self.mu.mem_map(0xfffff000, 4*1024) 217 | self.uc_gen_regs = [ 218 | unicorn.arm_const.UC_ARM_REG_R0, 219 | unicorn.arm_const.UC_ARM_REG_R1, 220 | unicorn.arm_const.UC_ARM_REG_R2, 221 | unicorn.arm_const.UC_ARM_REG_R3, 222 | unicorn.arm_const.UC_ARM_REG_R4, 223 | unicorn.arm_const.UC_ARM_REG_R5, 224 | unicorn.arm_const.UC_ARM_REG_R6, 225 | unicorn.arm_const.UC_ARM_REG_R7, 226 | unicorn.arm_const.UC_ARM_REG_R8, 227 | unicorn.arm_const.UC_ARM_REG_R9, 228 | unicorn.arm_const.UC_ARM_REG_R10, 229 | unicorn.arm_const.UC_ARM_REG_R11, 230 | unicorn.arm_const.UC_ARM_REG_R12, 231 | unicorn.arm_const.UC_ARM_REG_R13, 232 | unicorn.arm_const.UC_ARM_REG_R14, 233 | unicorn.arm_const.UC_ARM_REG_R15 234 | ] 235 | 236 | self.uc_nzcv_reg = unicorn.arm_const.UC_ARM_REG_CPSR 237 | self.uc_pc_reg = unicorn.arm_const.UC_ARM_REG_R15 238 | 239 | def get_target_xml(self): 240 | return """arm""" 241 | def get_machine_maxbits(self): 242 | return 32 243 | 244 | if __name__ == "__main__": 245 | print "begin test." 246 | ma = Unicorn_machine() 247 | print "::::::::::::::::::::::" 248 | print "get_regs test start." 249 | ma.mu.reg_write(ma.uc_gen_regs[0],0x1122334455667788) 250 | print ma.get_regs() 251 | print ma.get_regs_as_hexstr() 252 | print len(ma.get_regs_as_hexstr()) 253 | print "set_regs test start." 254 | hexstr = "00f0debc8a674523000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000" 255 | ma.set_regs_with_hexstr(hexstr) 256 | print ma.get_regs() 257 | --------------------------------------------------------------------------------