• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2012 The Chromium 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
5import re
6import sys
7import xml.etree.ElementTree
8
9import gdb_rsp
10
11
12def GetTargetArch(connection):
13  """Get the CPU architecture of the NaCl application."""
14  reply = connection.RspRequest('qXfer:features:read:target.xml:0,fff')
15  assert reply[0] == 'l', reply
16  tree = xml.etree.ElementTree.fromstring(reply[1:])
17  arch_tag = tree.find('architecture')
18  assert arch_tag is not None, reply
19  return arch_tag.text.strip()
20
21
22def ReverseBytes(byte_string):
23  """Reverse bytes in the hex string: '09ab' -> 'ab09'. This converts
24  little-endian number in the hex string to its normal string representation.
25  """
26  assert len(byte_string) % 2 == 0, byte_string
27  return ''.join([byte_string[i - 2 : i]
28                  for i in xrange(len(byte_string), 0, -2)])
29
30
31def GetProgCtrString(connection, arch):
32  """Get current execution point."""
33  registers = connection.RspRequest('g')
34  # PC register indices can be found in
35  # native_client/src/trusted/debug_stub/abi.cc in AbiInit function.
36  if arch == 'i386':
37    # eip index is 8
38    return ReverseBytes(registers[8 * 8 : 8 * 8 + 8])
39  if arch == 'i386:x86-64':
40    # rip index is 16
41    return ReverseBytes(registers[16 * 16 : 16 * 16 + 8])
42  if arch == 'iwmmxt':
43    # pc index is 15
44    return ReverseBytes(registers[15 * 8 : 15 * 8 + 8])
45  raise AssertionError('Unknown architecture: %s' % arch)
46
47
48def TestContinue(connection):
49  result = connection.RspRequest('vCont;c')
50  # Once the NaCl test module reports that the test passed, the NaCl <embed>
51  # element is removed from the page and so the NaCl module is killed by
52  # the browser what is reported as exit due to SIGKILL (X09).
53  assert result == 'X09', result
54
55
56def TestBreakpoint(connection):
57  # Breakpoints and single-stepping might interfere with Chrome sandbox. So we
58  # check that they work properly in this test.
59  arch = GetTargetArch(connection)
60  registers = connection.RspRequest('g')
61  pc = GetProgCtrString(connection, arch)
62  # Set breakpoint
63  result = connection.RspRequest('Z0,%s,1' % pc)
64  assert result == 'OK', result
65  # Check that we stopped at breakpoint
66  result = connection.RspRequest('vCont;c')
67  stop_reply = re.compile(r'T05thread:(\d+);')
68  assert stop_reply.match(result), result
69  thread = stop_reply.match(result).group(1)
70  # Check that registers haven't changed
71  result = connection.RspRequest('g')
72  assert result == registers, (result, registers)
73  # Remove breakpoint
74  result = connection.RspRequest('z0,%s,1' % pc)
75  assert result == 'OK', result
76  # Check single stepping
77  result = connection.RspRequest('vCont;s:%s' % thread)
78  assert result == 'T05thread:%s;' % thread, result
79  assert pc != GetProgCtrString(connection, arch)
80  # Check that we terminate normally
81  result = connection.RspRequest('vCont;c')
82  assert result == 'X09', result
83
84
85def Main(args):
86  port = int(args[0])
87  name = args[1]
88  connection = gdb_rsp.GdbRspConnection(('localhost', port))
89  if name == 'continue':
90    TestContinue(connection)
91  elif name == 'breakpoint':
92    TestBreakpoint(connection)
93  else:
94    raise AssertionError('Unknown test name: %r' % name)
95
96
97if __name__ == '__main__':
98  Main(sys.argv[1:])
99