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.
10 import xml.etree.ElementTree
15 if sys.platform == 'win32':
18 RETURNCODE_KILL = -9 & 0xff
25 # These are set up by Main().
28 SEL_LDR_COMMAND = None
31 def AssertEquals(x, y):
33 raise AssertionError('%r != %r' % (x, y))
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)])
43 return ''.join('%02x' % ord(byte) for byte in data)
94 ARM_REG_DEFS = ([('r%d' % regno, 'I') for regno in xrange(16)]
130 ('return_addr', 'I'),
136 'x86-32': X86_32_REG_DEFS,
137 'x86-64': X86_64_REG_DEFS,
139 'mips32': MIPS_REG_DEFS,
147 'mips32': 'stack_ptr',
155 'mips32': 'prog_ctr',
159 X86_TRAP_FLAG = 1 << 8
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)
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 = (
176 (1<<19) | (1<<18) | (1<<17) | (1<<16)) # GE bits
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])
184 values = struct.unpack_from(fmt, DecodeHex(reply))
185 return dict(zip(names, values))
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])
193 values = [regs[r] for r in names]
194 return EncodeHex(struct.pack(fmt, *values))
197 def PopenDebugStub(test):
198 gdb_rsp.EnsurePortIsAvailable()
199 return subprocess.Popen(SEL_LDR_COMMAND + ['-g', test])
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.
209 if sys.platform == 'win32':
210 # If process is already terminated, kill() throws
211 # "WindowsError: [Error 5] Access is denied" on Windows.
218 class LaunchDebugStub(object):
220 def __init__(self, test):
221 self._proc = PopenDebugStub(test)
225 return gdb_rsp.GdbRspConnection()
227 KillProcess(self._proc)
230 def __exit__(self, exc_type, exc_value, traceback):
231 KillProcess(self._proc)
235 assert '-f' in SEL_LDR_COMMAND
236 nexe_filename = SEL_LDR_COMMAND[SEL_LDR_COMMAND.index('-f') + 1]
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)
247 assert result == 0, result
251 def ParseThreadStopReply(reply):
252 match = re.match('T([0-9a-f]{2})thread:([0-9a-f]+);$', reply)
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)}
259 def AssertReplySignal(reply, signal):
260 AssertEquals(ParseThreadStopReply(reply)['signal'], signal)
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)
269 def ReadUint32(connection, address):
270 return struct.unpack('I', ReadMemory(connection, address, 4))[0]
273 def SingleSteppingWorks():
274 # Single-stepping is not yet supported on ARM and MIPS.
276 # http://code.google.com/p/nativeclient/issues/detail?id=2911
277 return ARCH in ('x86-32', 'x86-64')
280 class DebugStubTest(unittest.TestCase):
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)
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:])
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'))
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)
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
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)
380 raise AssertionError('Unknown architecture')
382 expected_fault_addr = GetSymbols()['fault_addr']
384 expected_fault_addr += registers['r15']
385 self.assertEquals(registers[IP_REG[ARCH]], expected_fault_addr)
387 # Test that we can write registers.
388 def CheckWriteRegisters(self, connection):
391 elif ARCH == 'x86-64':
395 elif ARCH == 'mips32':
398 raise AssertionError('Unknown architecture')
401 regs = DecodeRegs(connection.RspRequest('g'))
405 new_value = regs[reg_name]
408 self.assertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
410 # Read registers. Check for a new value.
411 regs = DecodeRegs(connection.RspRequest('g'))
412 self.assertEquals(regs[reg_name], new_value)
414 # TODO: Resume execution and check that changing the registers really
415 # influenced the program's execution. This would require changing
418 def CheckReadOnlyRegisters(self, connection):
420 sample_read_only_regs = ['cs', 'ds']
421 elif ARCH == 'x86-64':
422 sample_read_only_regs = ['r15', 'cs', 'ds']
424 sample_read_only_regs = []
425 elif ARCH == 'mips32':
426 sample_read_only_regs = ['zero']
428 raise AssertionError('Unknown architecture')
430 for reg_name in sample_read_only_regs:
432 regs = DecodeRegs(connection.RspRequest('g'))
435 old_value = regs[reg_name]
439 self.assertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
441 # Read registers. Check for an old value.
442 regs = DecodeRegs(connection.RspRequest('g'))
443 self.assertEquals(regs[reg_name], old_value)
445 # Test that reading from an unreadable address gives a sensible error.
446 def CheckReadMemoryAtInvalidAddr(self, connection):
448 result = connection.RspRequest('m%x,%x' % (mem_addr, 8))
449 self.assertEquals(result, 'E03')
451 # Check non-zero address in the first page.
453 resut = connection.RspRequest('m%x,%x' % (mem_addr, 1))
454 self.assertEquals(result, 'E03')
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)
466 # The process should have stopped on a HLT instruction.
467 AssertReplySignal(reply, NACL_SIGSEGV)
469 self.CheckTargetXml(connection)
470 self.CheckReadRegisters(connection)
471 self.CheckWriteRegisters(connection)
472 self.CheckReadOnlyRegisters(connection)
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'))
481 self.assertEquals(registers[IP_REG[ARCH]], registers['r15'])
483 self.assertEquals(registers[IP_REG[ARCH]], 0)
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)
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.
501 registers = DecodeRegs(connection.RspRequest('g'))
502 sandbox_base_addr = registers['r15']
503 reply = connection.RspRequest('m%x,%x' % (sandbox_base_addr + mem_addr,
505 self.assertEquals(DecodeHex(reply), expected_data)
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)
517 self.CheckReadMemoryAtInvalidAddr(connection)
519 def test_exit_code(self):
520 with LaunchDebugStub('test_exit_code') as connection:
521 reply = connection.RspRequest('c')
522 self.assertEquals(reply, 'W02')
524 # Single-step and check IP corresponds to debugger_test:test_single_step
525 def CheckSingleStep(self, connection, step_command, thread_id):
527 instruction_sizes = [1, 2, 3, 6]
528 elif ARCH == 'x86-64':
529 instruction_sizes = [1, 3, 4, 6]
531 raise AssertionError('Unknown architecture')
533 ip = DecodeRegs(connection.RspRequest('g'))[IP_REG[ARCH]]
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)
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)
545 def test_single_step(self):
546 if not SingleSteppingWorks():
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')
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')
563 def test_vCont(self):
564 # Basically repeat test_single_step, but using vCont commands.
565 if not SingleSteppingWorks():
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')
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')
583 self.CheckSingleStep(connection, 'vCont;s:%x' % tid, tid)
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)
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'))
595 # Try to single-step wrong thread.
596 reply = connection.RspRequest('vCont;s:%x' % (tid + 2))
597 self.assertTrue(reply.startswith('E'))
599 # Try to single-step all threads.
600 reply = connection.RspRequest('vCont;s')
601 self.assertTrue(reply.startswith('E'))
603 def test_interrupt(self):
604 if not SingleSteppingWorks():
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')
617 # Continue (program will spin forever), then interrupt.
618 connection.RspSendOnly('c')
619 reply = connection.RspInterrupt()
620 self.assertEqual(reply, 'T00')
623 reply = connection.RspRequest('s')
624 AssertReplySignal(reply, NACL_SIGTRAP)
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.
632 write_command = 'M%x,%x:%s' % (func_addr, len(data), EncodeHex(data))
633 reply = connection.RspRequest(write_command)
634 self.assertEquals(reply, 'E03')
637 sel_ldr = PopenDebugStub('test_exit_code')
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)
647 def test_detach(self):
648 sel_ldr = PopenDebugStub('test_exit_code')
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)
659 def test_disconnect(self):
660 sel_ldr = PopenDebugStub('test_exit_code')
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]]
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)
683 class DebugStubBreakpointTest(unittest.TestCase):
685 def CheckInstructionPtr(self, connection, expected_ip):
686 ip_value = DecodeRegs(connection.RspRequest('g'))[IP_REG[ARCH]]
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)
693 def test_setting_and_removing_breakpoint(self):
694 func_addr = GetSymbols()['breakpoint_target_func']
695 with LaunchDebugStub('test_setting_breakpoint') as connection:
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')
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.
709 reply = connection.RspRequest('c')
710 AssertReplySignal(reply, NACL_SIGTRAP)
711 self.CheckInstructionPtr(connection, func_addr)
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)
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')
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')
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')
746 def test_breakpoint_memory_changes_are_hidden(self):
747 func_addr = GetSymbols()['breakpoint_target_func']
748 with LaunchDebugStub('test_setting_breakpoint') as connection:
750 old_memory = ReadMemory(connection, func_addr, chunk_size)
751 reply = connection.RspRequest('Z0,%x,0' % func_addr)
752 self.assertEquals(reply, 'OK')
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])
764 class DebugStubThreadSuspensionTest(unittest.TestCase):
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
775 AssertReplySignal(stop_reply, NACL_SIGTRAP)
777 assert regs['r15'] % bundle_size == 0, regs['r15']
778 regs['r15'] += bundle_size
779 elif ARCH == 'mips32':
780 AssertReplySignal(stop_reply, NACL_SIGTRAP)
782 assert regs['prog_ctr'] % bundle_size == 0, regs['prog_ctr']
783 regs['prog_ctr'] += bundle_size
785 raise AssertionError('Unknown architecture')
786 AssertEquals(connection.RspRequest('G' + EncodeRegs(regs)), 'OK')
788 def WaitForTestThreadsToStart(self, connection, symbols):
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'])
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:
799 return child_thread_id
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)
806 # Test continuing a single thread while other threads remain
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'],
815 # The main thread should not be allowed to run, so should not
816 # modify g_main_thread_var.
818 ReadUint32(connection, symbols['g_main_thread_var']),
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']),
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)
831 # Test single-stepping a single thread while other threads
834 main_thread_val = ReadUint32(connection, symbols['g_main_thread_var'])
835 child_thread_val = ReadUint32(connection, symbols['g_child_thread_var'])
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.
845 self.SkipBreakpoint(connection, reply)
846 self.assertEquals(ParseThreadStopReply(reply)['thread_id'],
848 # The main thread should not be allowed to run, so should not
849 # modify g_main_thread_var.
851 ReadUint32(connection, symbols['g_main_thread_var']),
853 # Eventually, the child thread should modify g_child_thread_var.
854 if (ReadUint32(connection, symbols['g_child_thread_var'])
855 != child_thread_val):
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]
869 global SEL_LDR_COMMAND
871 NM_TOOL = args.pop(0)
872 SEL_LDR_COMMAND = args
876 if __name__ == '__main__':