xref: /aosp_15_r20/external/cronet/build/android/gyp/extract_unwind_tables_tests.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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
8This test suite contains various tests for extracting CFI tables from breakpad
9symbol files.
10"""
11
12import io
13import optparse
14import os
15import struct
16import sys
17import tempfile
18import unittest
19
20import extract_unwind_tables
21
22sys.path.append(os.path.join(os.path.dirname(__file__), "gyp"))
23from util import build_utils
24
25
26class TestExtractUnwindTables(unittest.TestCase):
27  def testExtractCfi(self):
28    test_data_lines = """
29MODULE Linux arm CDE12FE1DF2B37A9C6560B4CBEE056420 lib_chrome.so
30INFO CODE_ID E12FE1CD2BDFA937C6560B4CBEE05642
31FILE 0 ../../base/allocator/allocator_check.cc
32FILE 1 ../../base/allocator/allocator_shim.cc
33FUNC 1adcb60 54 0 i2d_name_canon
341adcb60 1a 509 17054
353b94c70 2 69 40
36PUBLIC e17001 0 assist_ranker::(anonymous namespace)::FakePredict::Initialize()
37PUBLIC e17005 0 (anonymous namespace)::FileDeleter(base::File)
38STACK CFI INIT e17000 4 .cfa: sp 0 + .ra: lr
39STACK CFI INIT 0 4 .cfa: sp 0 + .ra: lr
40STACK CFI 2 .cfa: sp 4 +
41STACK CFI 4 .cfa: sp 12 + .ra: .cfa -8 + ^ r7: .cfa -12 + ^
42STACK CFI 6 .cfa: sp 16 +
43STACK CFI INIT e1a96e 20 .cfa: sp 0 + .ra: lr
44STACK CFI e1a970 .cfa: sp 4 +
45STACK CFI e1a972 .cfa: sp 12 + .ra: .cfa -8 + ^ r7: .cfa -12 + ^
46STACK CFI e1a974 .cfa: sp 16 +
47STACK CFI INIT e1a1e4 b0 .cfa: sp 0 + .ra: lr
48STACK CFI e1a1e6 .cfa: sp 16 + .ra: .cfa -4 + ^ r4: .cfa -16 + ^ r5: .cfa -12 +
49STACK CFI e1a1e8 .cfa: sp 80 +
50STACK CFI INIT 0 4 .cfa: sp 0 + .ra: lr
51STACK CFI INIT 3b92e24 3c .cfa: sp 0 + .ra: lr
52STACK CFI 3b92e4c .cfa: sp 16 + .ra: .cfa -12 + ^
53STACK CFI INIT e17004 0 .cfa: sp 0 + .ra: lr
54STACK CFI e17004 2 .cfa: sp 0 + .ra: lr
55STACK CFI INIT 3b92e70 38 .cfa: sp 0 + .ra: lr
56STACK CFI 3b92e74 .cfa: sp 8 + .ra: .cfa -4 + ^ r4: .cfa -8 + ^
57STACK CFI 3b92e90 .cfa: sp 0 + .ra: .ra r4: r4
58STACK CFI INIT 3b93114 6c .cfa: sp 0 + .ra: lr
59STACK CFI 3b93118 .cfa: r7 16 + .ra: .cfa -4 + ^
60STACK CFI INIT 3b92114 6c .cfa: sp 0 + .ra: lr
61STACK CFI 3b92118 .cfa: r7 16 + .ra: .cfa -20 + ^
62STACK CFI INIT 3b93214 fffff .cfa: sp 0 + .ra: lr
63STACK 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
119if __name__ == '__main__':
120  unittest.main()
121