├── .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 |
--------------------------------------------------------------------------------