PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/translator/c/gcc/test/test_trackgcroot.py

https://bitbucket.org/kcr/pypy
Python | 177 lines | 171 code | 6 blank | 0 comment | 0 complexity | 43c0d25d2a8bd55b225500d901e860ab MD5 | raw file
Possible License(s): Apache-2.0
  1. import py
  2. import sys, re
  3. from rpython.translator.c.gcc.trackgcroot import LOC_NOWHERE, LOC_REG
  4. from rpython.translator.c.gcc.trackgcroot import LOC_EBP_PLUS, LOC_EBP_MINUS
  5. from rpython.translator.c.gcc.trackgcroot import LOC_ESP_PLUS
  6. from rpython.translator.c.gcc.trackgcroot import ElfAssemblerParser
  7. from rpython.translator.c.gcc.trackgcroot import DarwinAssemblerParser
  8. from rpython.translator.c.gcc.trackgcroot import PARSERS
  9. from rpython.translator.c.gcc.trackgcroot import ElfFunctionGcRootTracker32
  10. from StringIO import StringIO
  11. import py.test
  12. this_dir = py.path.local(__file__).dirpath()
  13. def test_format_location():
  14. cls = ElfFunctionGcRootTracker32
  15. assert cls.format_location(LOC_NOWHERE) == '?'
  16. assert cls.format_location(LOC_REG | (1<<2)) == '%ebx'
  17. assert cls.format_location(LOC_REG | (2<<2)) == '%esi'
  18. assert cls.format_location(LOC_REG | (3<<2)) == '%edi'
  19. assert cls.format_location(LOC_REG | (4<<2)) == '%ebp'
  20. assert cls.format_location(LOC_EBP_PLUS + 0) == '(%ebp)'
  21. assert cls.format_location(LOC_EBP_PLUS + 4) == '4(%ebp)'
  22. assert cls.format_location(LOC_EBP_MINUS + 4) == '-4(%ebp)'
  23. assert cls.format_location(LOC_ESP_PLUS + 0) == '(%esp)'
  24. assert cls.format_location(LOC_ESP_PLUS + 4) == '4(%esp)'
  25. def test_format_callshape():
  26. cls = ElfFunctionGcRootTracker32
  27. expected = ('{4(%ebp) ' # position of the return address
  28. '| 8(%ebp), 12(%ebp), 16(%ebp), 20(%ebp) ' # 4 saved regs
  29. '| 24(%ebp), 28(%ebp)}') # GC roots
  30. assert cls.format_callshape((LOC_EBP_PLUS+4,
  31. LOC_EBP_PLUS+8,
  32. LOC_EBP_PLUS+12,
  33. LOC_EBP_PLUS+16,
  34. LOC_EBP_PLUS+20,
  35. LOC_EBP_PLUS+24,
  36. LOC_EBP_PLUS+28)) == expected
  37. def test_compress_callshape():
  38. cls = ElfFunctionGcRootTracker32
  39. shape = (1, 127, 0x1234, 0x5678, 0x234567,
  40. 0x765432, 0x61626364, 0x41424344)
  41. bytes = list(cls.compress_callshape(shape))
  42. print bytes
  43. assert len(bytes) == 1+1+2+3+4+4+5+5+1
  44. assert cls.decompress_callshape(bytes) == list(shape)
  45. def test_find_functions_elf():
  46. source = """\
  47. \t.p2align 4,,15
  48. .globl pypy_g_make_tree
  49. \t.type\tpypy_g_make_tree, @function
  50. \tFOO
  51. \t.size\tpypy_g_make_tree, .-pypy_g_make_tree
  52. \t.p2align 4,,15
  53. .globl pypy_fn2
  54. \t.type\tpypy_fn2, @function
  55. \tBAR
  56. \t.size\tpypy_fn2, .-pypy_fn2
  57. \tMORE STUFF
  58. """
  59. lines = source.splitlines(True)
  60. parts = list(ElfAssemblerParser().find_functions(iter(lines)))
  61. assert len(parts) == 5
  62. assert parts[0] == (False, lines[:2])
  63. assert parts[1] == (True, lines[2:5])
  64. assert parts[2] == (False, lines[5:8])
  65. assert parts[3] == (True, lines[8:11])
  66. assert parts[4] == (False, lines[11:])
  67. def test_find_functions_darwin():
  68. source = """\
  69. \t.text
  70. \t.align 4,0x90
  71. .globl _pypy_g_ll_str__StringR_Ptr_GcStruct_rpy_strin_rpy_strin
  72. _pypy_g_ll_str__StringR_Ptr_GcStruct_rpy_strin_rpy_strin:
  73. L0:
  74. \tFOO
  75. \t.align 4,0x90
  76. _static:
  77. \tSTATIC
  78. \t.align 4,0x90
  79. .globl _pypy_g_ll_issubclass__object_vtablePtr_object_vtablePtr
  80. _pypy_g_ll_issubclass__object_vtablePtr_object_vtablePtr:
  81. \tBAR
  82. \t.cstring
  83. \t.ascii "foo"
  84. \t.text
  85. \t.align 4,0x90
  86. .globl _pypy_g_RPyRaiseException
  87. _pypy_g_RPyRaiseException:
  88. \tBAZ
  89. \t.section stuff
  90. """
  91. lines = source.splitlines(True)
  92. parts = list(DarwinAssemblerParser().find_functions(iter(lines)))
  93. assert len(parts) == 6
  94. assert parts[0] == (False, lines[:3])
  95. assert parts[1] == (True, lines[3:7])
  96. assert parts[2] == (True, lines[7:11])
  97. assert parts[3] == (True, lines[11:18])
  98. assert parts[4] == (True, lines[18:20])
  99. assert parts[5] == (False, lines[20:])
  100. def test_computegcmaptable():
  101. tests = []
  102. for format in ('elf', 'elf64', 'darwin', 'darwin64', 'msvc'):
  103. for path in this_dir.join(format).listdir("track*.s"):
  104. n = path.purebasename[5:]
  105. try:
  106. n = int(n)
  107. except ValueError:
  108. pass
  109. tests.append((format, n, path))
  110. tests.sort()
  111. for format, _, path in tests:
  112. yield check_computegcmaptable, format, path
  113. r_expected = re.compile(r"\s*;;\s*expected\s+([{].+[}])")
  114. r_gcroot_constant = re.compile(r";\tmov\t.+, .+_constant_always_one_")
  115. def check_computegcmaptable(format, path):
  116. if format == 'msvc':
  117. r_globallabel = re.compile(r"([\w]+)::")
  118. else:
  119. r_globallabel = re.compile(r"([\w]+)=[.]+")
  120. print
  121. print path.dirpath().basename + '/' + path.basename
  122. lines = path.readlines()
  123. expectedlines = lines[:]
  124. tracker = PARSERS[format].FunctionGcRootTracker(lines)
  125. table = tracker.computegcmaptable(verbose=sys.maxint)
  126. tabledict = {}
  127. seen = {}
  128. for entry in table:
  129. print '%s: %s' % (entry[0], tracker.format_callshape(entry[1]))
  130. tabledict[entry[0]] = entry[1]
  131. # find the ";; expected" lines
  132. prevline = ""
  133. for i, line in enumerate(lines):
  134. match = r_expected.match(line)
  135. if match:
  136. expected = match.group(1)
  137. prevmatch = r_globallabel.match(prevline)
  138. assert prevmatch, "the computed table is not complete"
  139. label = prevmatch.group(1)
  140. assert label in tabledict
  141. got = tabledict[label]
  142. assert tracker.format_callshape(got) == expected
  143. seen[label] = True
  144. if format == 'msvc':
  145. expectedlines.insert(i-2, 'PUBLIC\t%s\n' % (label,))
  146. expectedlines.insert(i-1, '%s::\n' % (label,))
  147. else:
  148. expectedlines.insert(i-2, '\t.globl\t%s\n' % (label,))
  149. expectedlines.insert(i-1, '%s=.+%d\n' % (label,
  150. tracker.OFFSET_LABELS))
  151. if format == 'msvc' and r_gcroot_constant.match(line):
  152. expectedlines[i] = ';' + expectedlines[i]
  153. expectedlines[i+1] = (expectedlines[i+1]
  154. .replace('\timul\t', '\tmov\t')
  155. + '\t; GCROOT\n')
  156. prevline = line
  157. assert len(seen) == len(tabledict), (
  158. "computed table contains unexpected entries:\n%r" %
  159. [key for key in tabledict if key not in seen])
  160. print '--------------- got ---------------'
  161. print ''.join(lines)
  162. print '------------- expected ------------'
  163. print ''.join(expectedlines)
  164. print '-----------------------------------'
  165. assert lines == expectedlines