1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and use spans.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "base/profiler/chrome_unwind_info_android_32.h"
11
12 #include <tuple>
13
14 #include "base/test/gtest_util.h"
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19
operator ==(const FunctionTableEntry & e1,const FunctionTableEntry & e2)20 bool operator==(const FunctionTableEntry& e1, const FunctionTableEntry& e2) {
21 return std::tie(e1.function_start_address_page_instruction_offset,
22 e1.function_offset_table_byte_index) ==
23 std::tie(e2.function_start_address_page_instruction_offset,
24 e2.function_offset_table_byte_index);
25 }
26
27 template <class T,
28 size_t E1,
29 size_t E2,
30 typename InternalPtrType1,
31 typename InternalPtrType2>
ExpectSpanSizeAndContentsEqual(span<T,E1,InternalPtrType1> actual,span<T,E2,InternalPtrType2> expected)32 void ExpectSpanSizeAndContentsEqual(span<T, E1, InternalPtrType1> actual,
33 span<T, E2, InternalPtrType2> expected) {
34 EXPECT_EQ(actual.size(), expected.size());
35 if (actual.size() != expected.size()) {
36 return;
37 }
38
39 for (size_t i = 0; i < actual.size(); i++) {
40 EXPECT_EQ(actual[i], expected[i]);
41 }
42 }
43
TEST(ChromeUnwindInfoAndroid32Test,CreateUnwindInfo)44 TEST(ChromeUnwindInfoAndroid32Test, CreateUnwindInfo) {
45 ChromeUnwindInfoAndroid32Header header = {
46 /* page_table_byte_offset */ 64,
47 /* page_table_entries */ 1,
48
49 /* function_table_byte_offset */ 128,
50 /* function_table_entries */ 2,
51
52 /* function_offset_table_byte_offset */ 192,
53 /* function_offset_table_size_in_bytes */ 3,
54
55 /* unwind_instruction_table_byte_offset */ 256,
56 /* unwind_instruction_table_size_in_bytes */ 4,
57 };
58
59 uint8_t data[512] = {};
60 // Note: `CreateChromeUnwindInfoAndroid32` is not expected to verify the
61 // content of each unwind table.
62 const uint32_t page_table[] = {1};
63 const FunctionTableEntry function_table[] = {{0, 2}, {0, 3}};
64 const uint8_t function_offset_table[] = {3, 3, 3};
65 const uint8_t unwind_instruction_table[] = {4, 4, 4, 4};
66
67 ASSERT_LT(sizeof(ChromeUnwindInfoAndroid32Header), 64ul);
68 memcpy(&data[0], &header, sizeof(ChromeUnwindInfoAndroid32Header));
69
70 memcpy(&data[header.page_table_byte_offset], page_table, sizeof(page_table));
71 memcpy(&data[header.function_table_byte_offset], function_table,
72 sizeof(function_table));
73 memcpy(&data[header.function_offset_table_byte_offset], function_offset_table,
74 sizeof(function_offset_table));
75 memcpy(&data[header.unwind_instruction_table_byte_offset],
76 unwind_instruction_table, sizeof(unwind_instruction_table));
77
78 ChromeUnwindInfoAndroid32 unwind_info = CreateChromeUnwindInfoAndroid32(data);
79
80 ASSERT_EQ(&data[64],
81 reinterpret_cast<const uint8_t*>(&unwind_info.page_table[0]));
82 ASSERT_EQ(&data[128],
83 reinterpret_cast<const uint8_t*>(&unwind_info.function_table[0]));
84 ASSERT_EQ(&data[192], reinterpret_cast<const uint8_t*>(
85 &unwind_info.function_offset_table[0]));
86 ASSERT_EQ(&data[256], reinterpret_cast<const uint8_t*>(
87 &unwind_info.unwind_instruction_table[0]));
88
89 ExpectSpanSizeAndContentsEqual(unwind_info.page_table, span(page_table));
90 ExpectSpanSizeAndContentsEqual(unwind_info.function_table,
91 span(function_table));
92 ExpectSpanSizeAndContentsEqual(unwind_info.function_offset_table,
93 span(function_offset_table));
94 ExpectSpanSizeAndContentsEqual(unwind_info.unwind_instruction_table,
95 span(unwind_instruction_table));
96 }
97
98 } // namespace base
99