tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

extract_unwind_tables_tests.py (4307B)


      1 #!/usr/bin/env python3
      2 # Copyright 2018 The Chromium Authors
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 """Tests for extract_unwind_tables.py
      7 
      8 This test suite contains various tests for extracting CFI tables from breakpad
      9 symbol files.
     10 """
     11 
     12 import io
     13 import optparse
     14 import os
     15 import struct
     16 import sys
     17 import tempfile
     18 import unittest
     19 
     20 import extract_unwind_tables
     21 
     22 sys.path.append(os.path.join(os.path.dirname(__file__), "gyp"))
     23 from util import build_utils
     24 
     25 
     26 class TestExtractUnwindTables(unittest.TestCase):
     27  def testExtractCfi(self):
     28    test_data_lines = """
     29 MODULE Linux arm CDE12FE1DF2B37A9C6560B4CBEE056420 lib_chrome.so
     30 INFO CODE_ID E12FE1CD2BDFA937C6560B4CBEE05642
     31 FILE 0 ../../base/allocator/allocator_check.cc
     32 FILE 1 ../../base/allocator/allocator_shim.cc
     33 FUNC 1adcb60 54 0 i2d_name_canon
     34 1adcb60 1a 509 17054
     35 3b94c70 2 69 40
     36 PUBLIC e17001 0 assist_ranker::(anonymous namespace)::FakePredict::Initialize()
     37 PUBLIC e17005 0 (anonymous namespace)::FileDeleter(base::File)
     38 STACK CFI INIT e17000 4 .cfa: sp 0 + .ra: lr
     39 STACK CFI INIT 0 4 .cfa: sp 0 + .ra: lr
     40 STACK CFI 2 .cfa: sp 4 +
     41 STACK CFI 4 .cfa: sp 12 + .ra: .cfa -8 + ^ r7: .cfa -12 + ^
     42 STACK CFI 6 .cfa: sp 16 +
     43 STACK CFI INIT e1a96e 20 .cfa: sp 0 + .ra: lr
     44 STACK CFI e1a970 .cfa: sp 4 +
     45 STACK CFI e1a972 .cfa: sp 12 + .ra: .cfa -8 + ^ r7: .cfa -12 + ^
     46 STACK CFI e1a974 .cfa: sp 16 +
     47 STACK CFI INIT e1a1e4 b0 .cfa: sp 0 + .ra: lr
     48 STACK CFI e1a1e6 .cfa: sp 16 + .ra: .cfa -4 + ^ r4: .cfa -16 + ^ r5: .cfa -12 +
     49 STACK CFI e1a1e8 .cfa: sp 80 +
     50 STACK CFI INIT 0 4 .cfa: sp 0 + .ra: lr
     51 STACK CFI INIT 3b92e24 3c .cfa: sp 0 + .ra: lr
     52 STACK CFI 3b92e4c .cfa: sp 16 + .ra: .cfa -12 + ^
     53 STACK CFI INIT e17004 0 .cfa: sp 0 + .ra: lr
     54 STACK CFI e17004 2 .cfa: sp 0 + .ra: lr
     55 STACK CFI INIT 3b92e70 38 .cfa: sp 0 + .ra: lr
     56 STACK CFI 3b92e74 .cfa: sp 8 + .ra: .cfa -4 + ^ r4: .cfa -8 + ^
     57 STACK CFI 3b92e90 .cfa: sp 0 + .ra: .ra r4: r4
     58 STACK CFI INIT 3b93114 6c .cfa: sp 0 + .ra: lr
     59 STACK CFI 3b93118 .cfa: r7 16 + .ra: .cfa -4 + ^
     60 STACK CFI INIT 3b92114 6c .cfa: sp 0 + .ra: lr
     61 STACK CFI 3b92118 .cfa: r7 16 + .ra: .cfa -20 + ^
     62 STACK CFI INIT 3b93214 fffff .cfa: sp 0 + .ra: lr
     63 STACK CFI 3b93218 .cfa: r7 16 + .ra: .cfa -4 + ^
     64 """.splitlines()
     65    cfi_data = extract_unwind_tables._GetAllCfiRows(
     66        [l.encode('utf8') for l in test_data_lines])
     67    out_file = io.BytesIO()
     68    extract_unwind_tables._WriteCfiData(cfi_data, out_file)
     69 
     70    expected_cfi_data = {
     71        0xe1a1e4: [0x2, 0x11, 0x4, 0x50],
     72        0xe1a296: [],
     73        0xe1a96e: [0x2, 0x4, 0x4, 0xe, 0x6, 0x10],
     74        0xe1a990: [],
     75        0x3b92e24: [0x28, 0x13],
     76        0x3b92e62: [],
     77    }
     78    expected_function_count = len(expected_cfi_data)
     79 
     80    actual_output = []
     81    out_file.seek(0)
     82    while True:
     83      read = out_file.read(2)
     84      if not read:
     85        break
     86      actual_output.append(struct.unpack('H', read)[0])
     87 
     88    # First value is size of unw_index table.
     89    unw_index_size = actual_output[1] << 16 | actual_output[0]
     90    # |unw_index_size| should match entry count.
     91    self.assertEqual(expected_function_count, unw_index_size)
     92    # |actual_output| is in blocks of 2 bytes. Skip first 4 bytes representing
     93    # size.
     94    unw_index_start = 2
     95    unw_index_addr_end = unw_index_start + expected_function_count * 2
     96    unw_index_end = unw_index_addr_end + expected_function_count
     97    unw_index_addr_col = actual_output[unw_index_start:unw_index_addr_end]
     98    unw_index_index_col = actual_output[unw_index_addr_end:unw_index_end]
     99 
    100    unw_data_start = unw_index_end
    101    unw_data = actual_output[unw_data_start:]
    102 
    103    for func_iter in range(0, expected_function_count):
    104      func_addr = (unw_index_addr_col[func_iter * 2 + 1] << 16
    105                   | unw_index_addr_col[func_iter * 2])
    106      index = unw_index_index_col[func_iter]
    107      # If index is CANT_UNWIND then invalid function.
    108      if index == 0xFFFF:
    109        self.assertEqual(expected_cfi_data[func_addr], [])
    110        continue
    111 
    112      func_start = index + 1
    113      func_end = func_start + unw_data[index] * 2
    114      self.assertEqual(len(expected_cfi_data[func_addr]), func_end - func_start)
    115      func_cfi = unw_data[func_start:func_end]
    116      self.assertEqual(expected_cfi_data[func_addr], func_cfi)
    117 
    118 
    119 if __name__ == '__main__':
    120  unittest.main()