]>
git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/usertaskdebugging/gdbserver.py
2 from interface
import Interface
7 class GDBServer(object):
8 """instance of gdbserver"""
9 def __init__(self
, backing_instance
):
10 super(GDBServer
, self
).__init
__()
11 self
.process
= backing_instance
12 self
.portnum
= random
.randint(2000, 8000)
13 logging
.info("Starting gdb server for localhost:%d" % self
.portnum
)
14 self
.conn
= Interface('localhost', self
.portnum
)
15 self
.version_string
= 'name:kdbserver;version:0.1'
18 if not self
.conn
.connect():
19 logging
.critical("No client connected. Bailing.")
22 logging
.debug('Starting gdb server.')
25 #loop for running the server.
31 p_bytes
= self
.conn
.read()
33 logging
.warn("found exception in read %s" % (str(e
)))
34 logging
.debug("currentbytes: %s" % readBytes
)
38 p_begin
= readBytes
.find('$')
39 p_end
= readBytes
.find('#')
40 if p_begin
>= 0 and p_end
>= 0 and p_end
> p_begin
:
42 # ignore if empty or ack messages
43 if readBytes
in ('', '+'):
44 logging
.debug('ignoring message: %s' % readBytes
)
46 req_msg
= rsprotocol
.Message
.fromRSPByteData(readBytes
)
47 resp
= self
.handleMessage(req_msg
)
48 #in case resp is to detach
52 logging
.debug("response: %s" % r_msg
.getRSPByteData())
53 self
.conn
.write(r_msg
.getRSPByteData())
56 def handleMessage(self
, msg
):
57 """ return array of messages that needs to responded. """
61 logging
.debug('RCV:' + query
)
64 h_msg
= rsprotocol
.Message(self
.process
.getSignalInfo())
65 replymsgs
.append(h_msg
)
68 replymsgs
.append(self
.getMemory(query
))
70 elif query
in ('qVAttachOrWaitSupported'):
71 logging
.debug('Ignoring query %s' % query
)
72 replymsgs
.append(rsprotocol
.UnSupportedMessage
)
75 replymsgs
.append(self
.getCurrentThreadID(query
))
77 elif query
[0] in ('z', 'Z'):
78 logging
.debug('Ignoring breakpoint query %s' % query
)
79 replymsgs
.append(rsprotocol
.UnSupportedMessage
)
81 elif query
[0] in ('g', 'p'):
82 replymsgs
.append(self
.getRegisterData(query
))
84 elif query
[0] in ('P', 'G'):
85 # we do not support writing into registers
86 replymsgs
.append(rsprotocol
.Message('E05'))
88 elif query
in ('QStartNoAckMode'):
89 replymsgs
.append(rsprotocol
.OKMessage
)
92 elif query
in ('QListThreadsInStopReply', 'QThreadSuffixSupported'):
93 replymsgs
.append(rsprotocol
.OKMessage
)
95 elif query
== 'qGDBServerVersion':
96 replymsgs
.append(rsprotocol
.Message(self
.version_string
))
98 elif query
== 'qShlibInfoAddr':
99 #return shared library info address if any
100 replymsgs
.append(self
.getSharedLibInfoAddress(query
))
102 elif query
== 'qProcessInfo':
103 replymsgs
.append(self
.getProcessInfo(query
))
105 elif query
== 'qHostInfo':
106 h_msg
= rsprotocol
.Message(self
.process
.getHostInfo())
107 replymsgs
.append(h_msg
)
109 elif query
== 'vCont?':
110 replymsgs
.append(rsprotocol
.Message('vCont;'))
113 logging
.info('Client requested to detach.')
116 elif query
.find('qRegisterInfo') >= 0:
117 replymsgs
.append(self
.getRegisterInfo(query
))
119 elif query
.find('qMemoryRegionInfo') >= 0:
120 replymsgs
.append(self
.getMemoryRegionInfo(query
))
122 elif query
.find('qThreadStopInfo') >= 0 or query
in ('qfThreadInfo', 'qsThreadInfo'):
123 replymsgs
.append(self
.getThreadRegistersInfo(query
))
126 replymsgs
.append(rsprotocol
.UnSupportedMessage
)
128 if sendAck
is not None:
130 replymsgs
.insert(0, rsprotocol
.AckMessage
)
132 replymsgs
.insert(0, rsprotocol
.NAckMessage
)
136 def getThreadRegistersInfo(self
, query
):
138 if query
== 'qfThreadInfo':
139 bytes = self
.process
.getFirstThreadInfo()
140 elif query
== 'qsThreadInfo':
141 bytes = self
.process
.getSubsequestThreadInfo()
144 query
= query
.replace('qThreadStopInfo', '')
146 bytes = self
.process
.getThreadStopInfo(tid
)
148 logging
.error("Failed to get register information query: %s error: %s" % (query
, e
.message
))
149 return rsprotocol
.Message(bytes)
151 def getRegisterData(self
, query
):
153 #TODO should implement thissometime. Considering getThreadRegistersInfo is there
154 #we wont need this one.
155 return rsprotocol
.UnSupportedMessage
157 #the query is of type p<regnum>;thread:<id>;
160 args
= query
[1:].split(';')
162 regnum
= int(args
[0], 16)
163 if args
[1].find('thread') >= 0:
164 threadid
= int(args
[1].split(':')[-1], 16)
165 bytes = self
.process
.getRegisterDataForThread(threadid
, regnum
)
166 logging
.debug('REGISTER INFO bytes = ' + bytes)
168 logging
.error("Failed to get register information query: %s error: %s" % (query
, e
.message
))
169 return rsprotocol
.Message(bytes)
171 def getRegisterInfo(self
, query
):
174 query
= query
.replace('qRegisterInfo', '')
175 regnum
= int(query
, 16)
176 bytes = self
.process
.getRegisterInfo(regnum
)
178 logging
.error("Failed to get register information error: %s" % e
.message
)
179 return rsprotocol
.Message(bytes)
181 def getMemory(self
, query
):
183 addr
, size
= query
.split(',')
184 mem_address
= int(addr
, 16)
185 mem_size
= int(size
, 16)
188 bytes = self
.process
.readMemory(mem_address
, mem_size
)
190 logging
.warn('Failed to read data %s' % str(e
))
191 return rsprotocol
.Message('E03')
192 return rsprotocol
.Message(bytes)
194 def getMemoryRegionInfo(self
, query
):
195 return rsprotocol
.UnSupportedMessage
197 def setMemory(self
, query
):
198 logging
.info('Not supporting writing to memory. %s' % query
)
199 return rsprotocol
.Message('E09')
201 def getProcessInfo(self
, query
):
204 data
= self
.process
.getProcessInfo()
206 logging
.error("Failed to get process information")
207 return rsprotocol
.Message(data
)
209 def getSharedLibInfoAddress(self
, query
):
212 data
= self
.process
.getSharedLibInfoAddress()
213 data
= self
.process
.encodeThreadID(data
)
215 logging
.error("Failed to get Shared Library information")
216 return rsprotocol
.Message(data
)
218 def getCurrentThreadID(self
, query
):
221 tid
= '%x' % (self
.process
.getCurrentThreadID())
223 logging
.error("Failed to get QC info")
225 return rsprotocol
.Message('QC'+tid
)