Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / debug_stub / debug_stub_test.py
1 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import re
6 import struct
7 import subprocess
8 import sys
9 import unittest
10 import xml.etree.ElementTree
11
12 import gdb_rsp
13
14
15 if sys.platform == 'win32':
16   RETURNCODE_KILL = -9
17 else:
18   RETURNCODE_KILL = -9 & 0xff
19
20
21 NACL_SIGTRAP = 5
22 NACL_SIGSEGV = 11
23
24
25 # These are set up by Main().
26 ARCH = None
27 NM_TOOL = None
28 SEL_LDR_COMMAND = None
29
30
31 def AssertEquals(x, y):
32   if x != y:
33     raise AssertionError('%r != %r' % (x, y))
34
35
36 def DecodeHex(data):
37   assert len(data) % 2 == 0, data
38   return ''.join([chr(int(data[index * 2 : (index + 1) * 2], 16))
39                   for index in xrange(len(data) / 2)])
40
41
42 def EncodeHex(data):
43   return ''.join('%02x' % ord(byte) for byte in data)
44
45
46 X86_32_REG_DEFS = [
47     ('eax', 'I'),
48     ('ecx', 'I'),
49     ('edx', 'I'),
50     ('ebx', 'I'),
51     ('esp', 'I'),
52     ('ebp', 'I'),
53     ('esi', 'I'),
54     ('edi', 'I'),
55     ('eip', 'I'),
56     ('eflags', 'I'),
57     ('cs', 'I'),
58     ('ss', 'I'),
59     ('ds', 'I'),
60     ('es', 'I'),
61     ('fs', 'I'),
62     ('gs', 'I'),
63 ]
64
65
66 X86_64_REG_DEFS = [
67     ('rax', 'Q'),
68     ('rbx', 'Q'),
69     ('rcx', 'Q'),
70     ('rdx', 'Q'),
71     ('rsi', 'Q'),
72     ('rdi', 'Q'),
73     ('rbp', 'Q'),
74     ('rsp', 'Q'),
75     ('r8', 'Q'),
76     ('r9', 'Q'),
77     ('r10', 'Q'),
78     ('r11', 'Q'),
79     ('r12', 'Q'),
80     ('r13', 'Q'),
81     ('r14', 'Q'),
82     ('r15', 'Q'),
83     ('rip', 'Q'),
84     ('eflags', 'I'),
85     ('cs', 'I'),
86     ('ss', 'I'),
87     ('ds', 'I'),
88     ('es', 'I'),
89     ('fs', 'I'),
90     ('gs', 'I'),
91 ]
92
93
94 ARM_REG_DEFS = ([('r%d' % regno, 'I') for regno in xrange(16)]
95                 + [('cpsr', 'I')])
96
97
98 MIPS_REG_DEFS = [
99      ('zero', 'I'),
100      ('at', 'I'),
101      ('v0', 'I'),
102      ('v1', 'I'),
103      ('a0', 'I'),
104      ('a1', 'I'),
105      ('a2', 'I'),
106      ('a3', 'I'),
107      ('t0', 'I'),
108      ('t1', 'I'),
109      ('t2', 'I'),
110      ('t3', 'I'),
111      ('t4', 'I'),
112      ('t5', 'I'),
113      ('t6', 'I'),
114      ('t7', 'I'),
115      ('s0', 'I'),
116      ('s1', 'I'),
117      ('s2', 'I'),
118      ('s3', 'I'),
119      ('s4', 'I'),
120      ('s5', 'I'),
121      ('s6', 'I'),
122      ('s7', 'I'),
123      ('t8', 'I'),
124      ('t9', 'I'),
125      ('k0', 'I'),
126      ('k1', 'I'),
127      ('global_ptr', 'I'),
128      ('stack_ptr', 'I'),
129      ('frame_ptr', 'I'),
130      ('return_addr', 'I'),
131      ('prog_ctr', 'I'),
132 ]
133
134
135 REG_DEFS = {
136     'x86-32': X86_32_REG_DEFS,
137     'x86-64': X86_64_REG_DEFS,
138     'arm': ARM_REG_DEFS,
139     'mips32': MIPS_REG_DEFS,
140     }
141
142
143 SP_REG = {
144     'x86-32': 'esp',
145     'x86-64': 'rsp',
146     'arm': 'r13',
147     'mips32': 'stack_ptr',
148     }
149
150
151 IP_REG = {
152     'x86-32': 'eip',
153     'x86-64': 'rip',
154     'arm': 'r15',
155     'mips32': 'prog_ctr',
156     }
157
158
159 X86_TRAP_FLAG = 1 << 8
160
161 # RESET_X86_FLAGS_VALUE is what ASM_WITH_REGS() resets the x86 flags
162 # to.  Copied from tests/common/register_set.h.
163 RESET_X86_FLAGS_VALUE = (1 << 2) | (1 << 6)
164 KNOWN_X86_FLAGS_MASK = (1<<0) | (1<<2) | (1<<6) | (1<<7) | (1<<11) | (1<<8)
165
166 # These are the only ARM CPSR bits that user code and untrusted code
167 # can read and modify, excluding the IT bits which are for Thumb-2
168 # (for If-Then-Else instructions).  Copied from
169 # tests/common/register_set.h.
170 ARM_USER_CPSR_FLAGS_MASK = (
171     (1<<31) | # N
172     (1<<30) | # Z
173     (1<<29) | # C
174     (1<<28) | # V
175     (1<<27) | # Q
176     (1<<19) | (1<<18) | (1<<17) | (1<<16)) # GE bits
177
178
179 def DecodeRegs(reply):
180   defs = REG_DEFS[ARCH]
181   names = [reg_name for reg_name, reg_fmt in defs]
182   fmt = ''.join([reg_fmt for reg_name, reg_fmt in defs])
183
184   values = struct.unpack_from(fmt, DecodeHex(reply))
185   return dict(zip(names, values))
186
187
188 def EncodeRegs(regs):
189   defs = REG_DEFS[ARCH]
190   names = [reg_name for reg_name, reg_fmt in defs]
191   fmt = ''.join([reg_fmt for reg_name, reg_fmt in defs])
192
193   values = [regs[r] for r in names]
194   return EncodeHex(struct.pack(fmt, *values))
195
196
197 def PopenDebugStub(test):
198   gdb_rsp.EnsurePortIsAvailable()
199   return subprocess.Popen(SEL_LDR_COMMAND + ['-g', test])
200
201
202 def KillProcess(process):
203   if process.returncode is not None:
204     # kill() won't work if we've already wait()'ed on the process.
205     return
206   try:
207     process.kill()
208   except OSError:
209     if sys.platform == 'win32':
210       # If process is already terminated, kill() throws
211       # "WindowsError: [Error 5] Access is denied" on Windows.
212       pass
213     else:
214       raise
215   process.wait()
216
217
218 class LaunchDebugStub(object):
219
220   def __init__(self, test):
221     self._proc = PopenDebugStub(test)
222
223   def __enter__(self):
224     try:
225       return gdb_rsp.GdbRspConnection()
226     except:
227       KillProcess(self._proc)
228       raise
229
230   def __exit__(self, exc_type, exc_value, traceback):
231     KillProcess(self._proc)
232
233
234 def GetSymbols():
235   assert '-f' in SEL_LDR_COMMAND
236   nexe_filename = SEL_LDR_COMMAND[SEL_LDR_COMMAND.index('-f') + 1]
237   symbols = {}
238   proc = subprocess.Popen([NM_TOOL, '--format=posix', nexe_filename],
239                           stdout=subprocess.PIPE)
240   for line in proc.stdout:
241     match = re.match('(\S+) [TtWwBD] ([0-9a-fA-F]+)', line)
242     if match is not None:
243       name = match.group(1)
244       addr = int(match.group(2), 16)
245       symbols[name] = addr
246   result = proc.wait()
247   assert result == 0, result
248   return symbols
249
250
251 def ParseThreadStopReply(reply):
252   match = re.match('T([0-9a-f]{2})thread:([0-9a-f]+);$', reply)
253   if match is None:
254     raise AssertionError('Bad thread stop reply: %r' % reply)
255   return {'signal': int(match.group(1), 16),
256           'thread_id': int(match.group(2), 16)}
257
258
259 def AssertReplySignal(reply, signal):
260   AssertEquals(ParseThreadStopReply(reply)['signal'], signal)
261
262
263 def ReadMemory(connection, address, size):
264   reply = connection.RspRequest('m%x,%x' % (address, size))
265   assert not reply.startswith('E'), reply
266   return DecodeHex(reply)
267
268
269 def ReadUint32(connection, address):
270   return struct.unpack('I', ReadMemory(connection, address, 4))[0]
271
272
273 def SingleSteppingWorks():
274   # Single-stepping is not yet supported on ARM and MIPS.
275   # TODO(eaeltsin):
276   #   http://code.google.com/p/nativeclient/issues/detail?id=2911
277   return ARCH in ('x86-32', 'x86-64')
278
279
280 class DebugStubTest(unittest.TestCase):
281
282   def test_initial_breakpoint(self):
283     # Any arguments to the nexe would work here because we are only
284     # testing that we get a breakpoint at the _start entry point.
285     with LaunchDebugStub('test_getting_registers') as connection:
286       reply = connection.RspRequest('?')
287       AssertReplySignal(reply, NACL_SIGTRAP)
288
289   def CheckTargetXml(self, connection):
290     reply = connection.RspRequest('qXfer:features:read:target.xml:0,fff')
291     self.assertEquals(reply[0], 'l')
292     # Just check that we are given parsable XML.
293     xml.etree.ElementTree.fromstring(reply[1:])
294
295   # Test that we can fetch register values.
296   # This check corresponds to the last instruction of debugger_test.c
297   def CheckReadRegisters(self, connection):
298     registers = DecodeRegs(connection.RspRequest('g'))
299     if ARCH == 'x86-32':
300       self.assertEquals(registers['eax'], 0x11000022)
301       self.assertEquals(registers['ebx'], 0x22000033)
302       self.assertEquals(registers['ecx'], 0x33000044)
303       self.assertEquals(registers['edx'], 0x44000055)
304       self.assertEquals(registers['esi'], 0x55000066)
305       self.assertEquals(registers['edi'], 0x66000077)
306       self.assertEquals(registers['ebp'], 0x77000088)
307       self.assertEquals(registers['esp'], 0x88000099)
308       self.assertEquals(registers['eflags'] & KNOWN_X86_FLAGS_MASK,
309                         RESET_X86_FLAGS_VALUE)
310     elif ARCH == 'x86-64':
311       self.assertEquals(registers['rax'], 0x1100000000000022)
312       self.assertEquals(registers['rbx'], 0x2200000000000033)
313       self.assertEquals(registers['rcx'], 0x3300000000000044)
314       self.assertEquals(registers['rdx'], 0x4400000000000055)
315       self.assertEquals(registers['rsi'], 0x5500000000000066)
316       self.assertEquals(registers['rdi'], 0x6600000000000077)
317       self.assertEquals(registers['r8'],  0x7700000000000088)
318       self.assertEquals(registers['r9'],  0x8800000000000099)
319       self.assertEquals(registers['r10'], 0x99000000000000aa)
320       self.assertEquals(registers['r11'], 0xaa000000000000bb)
321       self.assertEquals(registers['r12'], 0xbb000000000000cc)
322       self.assertEquals(registers['r13'], 0xcc000000000000dd)
323       self.assertEquals(registers['r14'], 0xdd000000000000ee)
324       self.assertEquals(registers['rsp'], registers['r15'] + 0x12300321)
325       self.assertEquals(registers['rbp'], registers['r15'] + 0x23400432)
326       self.assertEquals(registers['eflags'] & KNOWN_X86_FLAGS_MASK,
327                         RESET_X86_FLAGS_VALUE)
328     elif ARCH == 'arm':
329       self.assertEquals(registers['r0'], 0x00000001)
330       self.assertEquals(registers['r1'], 0x10000002)
331       self.assertEquals(registers['r2'], 0x20000003)
332       self.assertEquals(registers['r3'], 0x30000004)
333       self.assertEquals(registers['r4'], 0x40000005)
334       self.assertEquals(registers['r5'], 0x50000006)
335       self.assertEquals(registers['r6'], 0x60000007)
336       self.assertEquals(registers['r7'], 0x70000008)
337       self.assertEquals(registers['r8'], 0x80000009)
338       # Skip r9 because it is not supposed to be settable or readable
339       # by untrusted code.
340       self.assertEquals(registers['r10'], 0xa000000b)
341       self.assertEquals(registers['r11'], 0xb000000c)
342       self.assertEquals(registers['r12'], 0xc000000d)
343       self.assertEquals(registers['r13'], 0x12345678)
344       self.assertEquals(registers['r14'], 0xe000000f)
345       self.assertEquals(registers['cpsr'] & ARM_USER_CPSR_FLAGS_MASK,
346                         (1 << 29) | (1 << 27))
347     elif ARCH == 'mips32':
348       # We skip zero register because it cannot be set.
349       self.assertEquals(registers['at'], 0x11000220)
350       self.assertEquals(registers['v0'], 0x22000330)
351       self.assertEquals(registers['v1'], 0x33000440)
352       self.assertEquals(registers['a0'], 0x44000550)
353       self.assertEquals(registers['a1'], 0x55000660)
354       self.assertEquals(registers['a2'], 0x66000770)
355       self.assertEquals(registers['a3'], 0x77000880)
356       self.assertEquals(registers['t0'], 0x88000990)
357       self.assertEquals(registers['t1'], 0x99000aa0)
358       self.assertEquals(registers['t2'], 0xaa000bb0)
359       self.assertEquals(registers['t3'], 0xbb000cc0)
360       self.assertEquals(registers['t4'], 0xcc000dd0)
361       self.assertEquals(registers['t5'], 0xdd000ee0)
362       self.assertEquals(registers['t6'], 0x0ffffff0)
363       self.assertEquals(registers['t7'], 0x3fffffff)
364       # Skip t8 because it cannot be set by untrusted code.
365       self.assertEquals(registers['s0'], 0x11100222)
366       self.assertEquals(registers['s1'], 0x22200333)
367       self.assertEquals(registers['s2'], 0x33300444)
368       self.assertEquals(registers['s3'], 0x44400555)
369       self.assertEquals(registers['s4'], 0x55500666)
370       self.assertEquals(registers['s5'], 0x66600777)
371       self.assertEquals(registers['s6'], 0x77700888)
372       self.assertEquals(registers['s7'], 0x88800999)
373       self.assertEquals(registers['t9'], 0xaaa00bbb)
374       # Skip k0 and k1 registers, since they can be changed by kernel.
375       self.assertEquals(registers['global_ptr'],  0xddd00eee)
376       self.assertEquals(registers['stack_ptr'],   0x2ee00fff)
377       self.assertEquals(registers['frame_ptr'],   0xfff00000)
378       self.assertEquals(registers['return_addr'], 0x0a0a0a0a)
379     else:
380       raise AssertionError('Unknown architecture')
381
382     expected_fault_addr = GetSymbols()['fault_addr']
383     if ARCH == 'x86-64':
384       expected_fault_addr += registers['r15']
385     self.assertEquals(registers[IP_REG[ARCH]], expected_fault_addr)
386
387   # Test that we can write registers.
388   def CheckWriteRegisters(self, connection):
389     if ARCH == 'x86-32':
390       reg_name = 'edx'
391     elif ARCH == 'x86-64':
392       reg_name = 'rdx'
393     elif ARCH == 'arm':
394       reg_name = 'r0'
395     elif ARCH == 'mips32':
396       reg_name = 'a0'
397     else:
398       raise AssertionError('Unknown architecture')
399
400     # Read registers.
401     regs = DecodeRegs(connection.RspRequest('g'))
402
403     # Change a register.
404     regs[reg_name] += 1
405     new_value = regs[reg_name]
406
407     # Write registers.
408     self.assertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
409
410     # Read registers. Check for a new value.
411     regs = DecodeRegs(connection.RspRequest('g'))
412     self.assertEquals(regs[reg_name], new_value)
413
414     # TODO: Resume execution and check that changing the registers really
415     # influenced the program's execution. This would require changing
416     # debugger_test.c.
417
418   def CheckReadOnlyRegisters(self, connection):
419     if ARCH == 'x86-32':
420       sample_read_only_regs = ['cs', 'ds']
421     elif ARCH == 'x86-64':
422       sample_read_only_regs = ['r15', 'cs', 'ds']
423     elif ARCH == 'arm':
424       sample_read_only_regs = []
425     elif ARCH == 'mips32':
426       sample_read_only_regs = ['zero']
427     else:
428       raise AssertionError('Unknown architecture')
429
430     for reg_name in sample_read_only_regs:
431       # Read registers.
432       regs = DecodeRegs(connection.RspRequest('g'))
433
434       # Change a register.
435       old_value = regs[reg_name]
436       regs[reg_name] += 1
437
438       # Write registers.
439       self.assertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
440
441       # Read registers. Check for an old value.
442       regs = DecodeRegs(connection.RspRequest('g'))
443       self.assertEquals(regs[reg_name], old_value)
444
445   # Test that reading from an unreadable address gives a sensible error.
446   def CheckReadMemoryAtInvalidAddr(self, connection):
447     mem_addr = 0
448     result = connection.RspRequest('m%x,%x' % (mem_addr, 8))
449     self.assertEquals(result, 'E03')
450
451     # Check non-zero address in the first page.
452     mem_addr = 0xffff
453     resut = connection.RspRequest('m%x,%x' % (mem_addr, 1))
454     self.assertEquals(result, 'E03')
455
456   # Run tests on debugger_test.c binary.
457   def test_debugger_test(self):
458     with LaunchDebugStub('test_getting_registers') as connection:
459       # Tell the process to continue, because it starts at the
460       # breakpoint set at its start address.
461       reply = connection.RspRequest('c')
462       if ARCH == 'arm' or ARCH == 'mips32':
463         # The process should have stopped on a BKPT instruction.
464         AssertReplySignal(reply, NACL_SIGTRAP)
465       else:
466         # The process should have stopped on a HLT instruction.
467         AssertReplySignal(reply, NACL_SIGSEGV)
468
469       self.CheckTargetXml(connection)
470       self.CheckReadRegisters(connection)
471       self.CheckWriteRegisters(connection)
472       self.CheckReadOnlyRegisters(connection)
473
474   def test_jump_to_address_zero(self):
475     with LaunchDebugStub('test_jump_to_address_zero') as connection:
476       # Continue from initial breakpoint.
477       reply = connection.RspRequest('c')
478       AssertReplySignal(reply, NACL_SIGSEGV)
479       registers = DecodeRegs(connection.RspRequest('g'))
480       if ARCH == 'x86-64':
481         self.assertEquals(registers[IP_REG[ARCH]], registers['r15'])
482       else:
483         self.assertEquals(registers[IP_REG[ARCH]], 0)
484
485   def test_reading_and_writing_memory(self):
486     # Any arguments to the nexe would work here because we do not run
487     # the executable beyond the initial breakpoint.
488     with LaunchDebugStub('test_getting_registers') as connection:
489       mem_addr = GetSymbols()['g_example_var']
490       # Check reading memory.
491       expected_data = 'some_debug_stub_test_data\0'
492       reply = connection.RspRequest('m%x,%x' % (mem_addr, len(expected_data)))
493       self.assertEquals(DecodeHex(reply), expected_data)
494
495       # On x86-64, for reading/writing memory, the debug stub accepts
496       # untrusted addresses with or without the %r15 sandbox base
497       # address added, because GDB uses both.
498       # TODO(eaeltsin): Fix GDB to not use addresses with %r15 added,
499       # and change the expected result in the check below.
500       if ARCH == 'x86-64':
501         registers = DecodeRegs(connection.RspRequest('g'))
502         sandbox_base_addr = registers['r15']
503         reply = connection.RspRequest('m%x,%x' % (sandbox_base_addr + mem_addr,
504                                                   len(expected_data)))
505         self.assertEquals(DecodeHex(reply), expected_data)
506
507       # Check writing memory.
508       new_data = 'replacement_data\0'
509       assert len(new_data) < len(expected_data)
510       reply = connection.RspRequest('M%x,%x:%s' % (mem_addr, len(new_data),
511                                                    EncodeHex(new_data)))
512       self.assertEquals(reply, 'OK')
513       # Check that we can read back what we wrote.
514       reply = connection.RspRequest('m%x,%x' % (mem_addr, len(new_data)))
515       self.assertEquals(DecodeHex(reply), new_data)
516
517       self.CheckReadMemoryAtInvalidAddr(connection)
518
519   def test_exit_code(self):
520     with LaunchDebugStub('test_exit_code') as connection:
521       reply = connection.RspRequest('c')
522       self.assertEquals(reply, 'W02')
523
524   # Single-step and check IP corresponds to debugger_test:test_single_step
525   def CheckSingleStep(self, connection, step_command, thread_id):
526     if ARCH == 'x86-32':
527       instruction_sizes = [1, 2, 3, 6]
528     elif ARCH == 'x86-64':
529       instruction_sizes = [1, 3, 4, 6]
530     else:
531       raise AssertionError('Unknown architecture')
532
533     ip = DecodeRegs(connection.RspRequest('g'))[IP_REG[ARCH]]
534
535     for size in instruction_sizes:
536       reply = connection.RspRequest(step_command)
537       AssertReplySignal(reply, NACL_SIGTRAP)
538       self.assertEquals(ParseThreadStopReply(reply)['thread_id'], thread_id)
539       ip += size
540       regs = DecodeRegs(connection.RspRequest('g'))
541       self.assertEqual(regs[IP_REG[ARCH]], ip)
542       # The trap flag should be reported as unset.
543       self.assertEqual(regs['eflags'] & X86_TRAP_FLAG, 0)
544
545   def test_single_step(self):
546     if not SingleSteppingWorks():
547       return
548     with LaunchDebugStub('test_single_step') as connection:
549       # We expect test_single_step() to stop at a HLT instruction.
550       reply = connection.RspRequest('c')
551       AssertReplySignal(reply, NACL_SIGSEGV)
552       tid = ParseThreadStopReply(reply)['thread_id']
553       # Skip past the single-byte HLT instruction.
554       regs = DecodeRegs(connection.RspRequest('g'))
555       regs[IP_REG[ARCH]] += 1
556       AssertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
557
558       self.CheckSingleStep(connection, 's', tid)
559       # Check that we can continue after single-stepping.
560       reply = connection.RspRequest('c')
561       self.assertEquals(reply, 'W00')
562
563   def test_vCont(self):
564     # Basically repeat test_single_step, but using vCont commands.
565     if not SingleSteppingWorks():
566       return
567     with LaunchDebugStub('test_single_step') as connection:
568       # Test if vCont is supported.
569       reply = connection.RspRequest('vCont?')
570       self.assertEqual(reply, 'vCont;s;S;c;C')
571
572       # Continue using vCont.
573       # We expect test_single_step() to stop at a HLT instruction.
574       reply = connection.RspRequest('vCont;c')
575       AssertReplySignal(reply, NACL_SIGSEGV)
576       # Get signalled thread id.
577       tid = ParseThreadStopReply(reply)['thread_id']
578       # Skip past the single-byte HLT instruction.
579       regs = DecodeRegs(connection.RspRequest('g'))
580       regs[IP_REG[ARCH]] += 1
581       AssertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
582
583       self.CheckSingleStep(connection, 'vCont;s:%x' % tid, tid)
584
585       # Single step one thread and continue all others.
586       reply = connection.RspRequest('vCont;s:%x;c' % tid)
587       # WARNING! This check is valid in single-threaded case only!
588       # In multi-threaded case another thread might stop first.
589       self.assertEqual(reply, 'T05thread:%x;' % tid)
590
591       # Try to continue the thread and to single-step all others.
592       reply = connection.RspRequest('vCont;c:%x;s' % tid)
593       self.assertTrue(reply.startswith('E'))
594
595       # Try to single-step wrong thread.
596       reply = connection.RspRequest('vCont;s:%x' % (tid + 2))
597       self.assertTrue(reply.startswith('E'))
598
599       # Try to single-step all threads.
600       reply = connection.RspRequest('vCont;s')
601       self.assertTrue(reply.startswith('E'))
602
603   def test_interrupt(self):
604     if not SingleSteppingWorks():
605       return
606     func_addr = GetSymbols()['test_interrupt']
607     with LaunchDebugStub('test_interrupt') as connection:
608       # Single stepping inside syscalls doesn't work. So we need to reach
609       # a point where interrupt will not catch the program inside syscall.
610       reply = connection.RspRequest('Z0,%x,0' % func_addr)
611       self.assertEquals(reply, 'OK')
612       reply = connection.RspRequest('c')
613       AssertReplySignal(reply, NACL_SIGTRAP)
614       reply = connection.RspRequest('z0,%x,0' % func_addr)
615       self.assertEquals(reply, 'OK')
616
617       # Continue (program will spin forever), then interrupt.
618       connection.RspSendOnly('c')
619       reply = connection.RspInterrupt()
620       self.assertEqual(reply, 'T00')
621
622       # Single-step.
623       reply = connection.RspRequest('s')
624       AssertReplySignal(reply, NACL_SIGTRAP)
625
626   def test_modifying_code_is_disallowed(self):
627     with LaunchDebugStub('test_setting_breakpoint') as connection:
628       # Pick an arbitrary address in the code segment.
629       func_addr = GetSymbols()['breakpoint_target_func']
630       # Writing to the code area should be disallowed.
631       data = '\x00'
632       write_command = 'M%x,%x:%s' % (func_addr, len(data), EncodeHex(data))
633       reply = connection.RspRequest(write_command)
634       self.assertEquals(reply, 'E03')
635
636   def test_kill(self):
637     sel_ldr = PopenDebugStub('test_exit_code')
638     try:
639       connection = gdb_rsp.GdbRspConnection()
640       # Request killing the target.
641       reply = connection.RspRequest('k')
642       self.assertEquals(reply, 'OK')
643       self.assertEquals(sel_ldr.wait(), RETURNCODE_KILL)
644     finally:
645       KillProcess(sel_ldr)
646
647   def test_detach(self):
648     sel_ldr = PopenDebugStub('test_exit_code')
649     try:
650       connection = gdb_rsp.GdbRspConnection()
651       # Request detaching from the target.
652       # This resumes execution, so we get the nexe's normal exit() status.
653       reply = connection.RspRequest('D')
654       self.assertEquals(reply, 'OK')
655       self.assertEquals(sel_ldr.wait(), 2)
656     finally:
657       KillProcess(sel_ldr)
658
659   def test_disconnect(self):
660     sel_ldr = PopenDebugStub('test_exit_code')
661     try:
662       # Connect and record the instruction pointer.
663       connection = gdb_rsp.GdbRspConnection()
664       # Check something basic responds with sane results.
665       reply = connection.RspRequest('vCont?')
666       self.assertEqual(reply, 'vCont;s;S;c;C')
667       # Store the instruction pointer.
668       registers = DecodeRegs(connection.RspRequest('g'))
669       initial_ip = registers[IP_REG[ARCH]]
670       connection.Close()
671       # Reconnect 5 times.
672       for _ in range(5):
673         connection = gdb_rsp.GdbRspConnection()
674         # Confirm the instruction pointer stays where it was, indicating that
675         # the thread stayed suspended.
676         registers = DecodeRegs(connection.RspRequest('g'))
677         self.assertEquals(registers[IP_REG[ARCH]], initial_ip)
678         connection.Close()
679     finally:
680       KillProcess(sel_ldr)
681
682
683 class DebugStubBreakpointTest(unittest.TestCase):
684
685   def CheckInstructionPtr(self, connection, expected_ip):
686     ip_value = DecodeRegs(connection.RspRequest('g'))[IP_REG[ARCH]]
687     if ARCH == 'x86-64':
688       # TODO(mseaborn): The debug stub should probably omit the top
689       # bits of %rip automatically.
690       ip_value &= 0xffffffff
691     self.assertEquals(ip_value, expected_ip)
692
693   def test_setting_and_removing_breakpoint(self):
694     func_addr = GetSymbols()['breakpoint_target_func']
695     with LaunchDebugStub('test_setting_breakpoint') as connection:
696       # Set a breakpoint.
697       reply = connection.RspRequest('Z0,%x,0' % func_addr)
698       self.assertEquals(reply, 'OK')
699       # Requesting a breakpoint on an address that already has a
700       # breakpoint should return an error.
701       reply = connection.RspRequest('Z0,%x,0' % func_addr)
702       self.assertEquals(reply, 'E03')
703
704       # When we run the program, we should hit the breakpoint.  When
705       # we continue, we should hit the breakpoint again because it has
706       # not been removed: the debug stub does not step through
707       # breakpoints automatically.
708       for i in xrange(2):
709         reply = connection.RspRequest('c')
710         AssertReplySignal(reply, NACL_SIGTRAP)
711         self.CheckInstructionPtr(connection, func_addr)
712
713       # If we continue a single thread, the fault the thread receives
714       # should still be recognized as a breakpoint.
715       tid = ParseThreadStopReply(reply)['thread_id']
716       reply = connection.RspRequest('vCont;c:%x' % tid)
717       AssertReplySignal(reply, NACL_SIGTRAP)
718       self.CheckInstructionPtr(connection, func_addr)
719
720       # Check that we can remove the breakpoint.
721       reply = connection.RspRequest('z0,%x,0' % func_addr)
722       self.assertEquals(reply, 'OK')
723       # Requesting removing a breakpoint on an address that does not
724       # have one should return an error.
725       reply = connection.RspRequest('z0,%x,0' % func_addr)
726       self.assertEquals(reply, 'E03')
727       # After continuing, we should not hit the breakpoint again, and
728       # the program should run to completion.
729       reply = connection.RspRequest('c')
730       self.assertEquals(reply, 'W00')
731
732   def test_setting_breakpoint_on_invalid_address(self):
733     with LaunchDebugStub('test_exit_code') as connection:
734       # Requesting a breakpoint on an invalid address should give an error.
735       reply = connection.RspRequest('Z0,%x,1' % (1 << 32))
736       self.assertEquals(reply, 'E03')
737
738   def test_setting_breakpoint_on_data_address(self):
739     with LaunchDebugStub('test_exit_code') as connection:
740       # Pick an arbitrary address in the data segment.
741       data_addr = GetSymbols()['g_main_thread_var']
742       # Requesting a breakpoint on a non-code address should give an error.
743       reply = connection.RspRequest('Z0,%x,1' % data_addr)
744       self.assertEquals(reply, 'E03')
745
746   def test_breakpoint_memory_changes_are_hidden(self):
747     func_addr = GetSymbols()['breakpoint_target_func']
748     with LaunchDebugStub('test_setting_breakpoint') as connection:
749       chunk_size = 32
750       old_memory = ReadMemory(connection, func_addr, chunk_size)
751       reply = connection.RspRequest('Z0,%x,0' % func_addr)
752       self.assertEquals(reply, 'OK')
753
754       # The debug stub should hide the memory modification.
755       new_memory = ReadMemory(connection, func_addr, chunk_size)
756       self.assertEquals(new_memory, old_memory)
757       # Check reading a subset of the range.  (This will only be a
758       # proper subset on architectures where the breakpoint size is
759       # >1, such as ARM not but x86.)
760       new_memory = ReadMemory(connection, func_addr, 1)
761       self.assertEquals(new_memory, old_memory[:1])
762
763
764 class DebugStubThreadSuspensionTest(unittest.TestCase):
765
766   def SkipBreakpoint(self, connection, stop_reply):
767     # Skip past the faulting instruction in debugger_test.c's
768     # breakpoint() function.
769     regs = DecodeRegs(connection.RspRequest('g'))
770     if ARCH in ('x86-32', 'x86-64'):
771       AssertReplySignal(stop_reply, NACL_SIGSEGV)
772       # Skip past the single-byte HLT instruction.
773       regs[IP_REG[ARCH]] += 1
774     elif ARCH == 'arm':
775       AssertReplySignal(stop_reply, NACL_SIGTRAP)
776       bundle_size = 16
777       assert regs['r15'] % bundle_size == 0, regs['r15']
778       regs['r15'] += bundle_size
779     elif ARCH == 'mips32':
780       AssertReplySignal(stop_reply, NACL_SIGTRAP)
781       bundle_size = 16
782       assert regs['prog_ctr'] % bundle_size == 0, regs['prog_ctr']
783       regs['prog_ctr'] += bundle_size
784     else:
785       raise AssertionError('Unknown architecture')
786     AssertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
787
788   def WaitForTestThreadsToStart(self, connection, symbols):
789     # Wait until:
790     #  * The main thread starts to modify g_main_thread_var.
791     #  * The child thread executes a breakpoint.
792     old_value = ReadUint32(connection, symbols['g_main_thread_var'])
793     while True:
794       reply = connection.RspRequest('c')
795       self.SkipBreakpoint(connection, reply)
796       child_thread_id = ParseThreadStopReply(reply)['thread_id']
797       if ReadUint32(connection, symbols['g_main_thread_var']) != old_value:
798         break
799     return child_thread_id
800
801   def test_continuing_thread_with_others_suspended(self):
802     with LaunchDebugStub('test_suspending_threads') as connection:
803       symbols = GetSymbols()
804       child_thread_id = self.WaitForTestThreadsToStart(connection, symbols)
805
806       # Test continuing a single thread while other threads remain
807       # suspended.
808       for _ in range(3):
809         main_thread_val = ReadUint32(connection, symbols['g_main_thread_var'])
810         child_thread_val = ReadUint32(connection, symbols['g_child_thread_var'])
811         reply = connection.RspRequest('vCont;c:%x' % child_thread_id)
812         self.SkipBreakpoint(connection, reply)
813         self.assertEquals(ParseThreadStopReply(reply)['thread_id'],
814                           child_thread_id)
815         # The main thread should not be allowed to run, so should not
816         # modify g_main_thread_var.
817         self.assertEquals(
818             ReadUint32(connection, symbols['g_main_thread_var']),
819             main_thread_val)
820         # The child thread should always modify g_child_thread_var
821         # between each breakpoint.
822         self.assertNotEquals(
823             ReadUint32(connection, symbols['g_child_thread_var']),
824             child_thread_val)
825
826   def test_single_stepping_thread_with_others_suspended(self):
827     with LaunchDebugStub('test_suspending_threads') as connection:
828       symbols = GetSymbols()
829       child_thread_id = self.WaitForTestThreadsToStart(connection, symbols)
830
831       # Test single-stepping a single thread while other threads
832       # remain suspended.
833       for _ in range(3):
834         main_thread_val = ReadUint32(connection, symbols['g_main_thread_var'])
835         child_thread_val = ReadUint32(connection, symbols['g_child_thread_var'])
836         while True:
837           reply = connection.RspRequest('vCont;s:%x' % child_thread_id)
838           if (ARCH in ('x86-32', 'x86-64') and
839               ParseThreadStopReply(reply)['signal'] == NACL_SIGTRAP):
840             # We single-stepped through an instruction without
841             # otherwise faulting.  We did not hit the breakpoint, so
842             # there is nothing to do.
843             pass
844           else:
845             self.SkipBreakpoint(connection, reply)
846           self.assertEquals(ParseThreadStopReply(reply)['thread_id'],
847                             child_thread_id)
848           # The main thread should not be allowed to run, so should not
849           # modify g_main_thread_var.
850           self.assertEquals(
851               ReadUint32(connection, symbols['g_main_thread_var']),
852               main_thread_val)
853           # Eventually, the child thread should modify g_child_thread_var.
854           if (ReadUint32(connection, symbols['g_child_thread_var'])
855               != child_thread_val):
856             break
857
858
859 def Main():
860   # TODO(mseaborn): Clean up to remove the global variables.  They are
861   # currently here because unittest does not help with making
862   # parameterised tests.
863   index = sys.argv.index('--')
864   args = sys.argv[index + 1:]
865   # The remaining arguments go to unittest.main().
866   sys.argv = sys.argv[:index]
867   global ARCH
868   global NM_TOOL
869   global SEL_LDR_COMMAND
870   ARCH = args.pop(0)
871   NM_TOOL = args.pop(0)
872   SEL_LDR_COMMAND = args
873   unittest.main()
874
875
876 if __name__ == '__main__':
877   Main()