1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18
19 #include <android-base/test_utils.h>
20
21 #include "get_test_data.h"
22 #include "kallsyms.h"
23 #include "test_util.h"
24
25 using namespace simpleperf;
26
ModulesMatch(const char * p,const char * q)27 static bool ModulesMatch(const char* p, const char* q) {
28 if (p == nullptr && q == nullptr) {
29 return true;
30 }
31 if (p != nullptr && q != nullptr) {
32 return strcmp(p, q) == 0;
33 }
34 return false;
35 }
36
KernelSymbolsMatch(const KernelSymbol & sym1,const KernelSymbol & sym2)37 static bool KernelSymbolsMatch(const KernelSymbol& sym1, const KernelSymbol& sym2) {
38 return sym1.addr == sym2.addr && sym1.type == sym2.type && strcmp(sym1.name, sym2.name) == 0 &&
39 ModulesMatch(sym1.module, sym2.module);
40 }
41
TEST(kallsyms,ProcessKernelSymbols)42 TEST(kallsyms, ProcessKernelSymbols) {
43 std::string data =
44 "ffffffffa005c4e4 d __warned.41698 [libsas]\n"
45 "aaaaaaaaaaaaaaaa T _text\n"
46 "cccccccccccccccc c ccccc\n";
47 KernelSymbol expected_symbol;
48 expected_symbol.addr = 0xffffffffa005c4e4ULL;
49 expected_symbol.type = 'd';
50 expected_symbol.name = "__warned.41698";
51 expected_symbol.module = "libsas";
52 ASSERT_TRUE(ProcessKernelSymbols(
53 data, std::bind(&KernelSymbolsMatch, std::placeholders::_1, expected_symbol)));
54
55 expected_symbol.addr = 0xaaaaaaaaaaaaaaaaULL;
56 expected_symbol.type = 'T';
57 expected_symbol.name = "_text";
58 expected_symbol.module = nullptr;
59 ASSERT_TRUE(ProcessKernelSymbols(
60 data, std::bind(&KernelSymbolsMatch, std::placeholders::_1, expected_symbol)));
61
62 expected_symbol.name = "non_existent_symbol";
63 ASSERT_FALSE(ProcessKernelSymbols(
64 data, std::bind(&KernelSymbolsMatch, std::placeholders::_1, expected_symbol)));
65 }
66
TEST(kallsyms,ProcessKernelSymbols_ignore_arm_mapping_symbols)67 TEST(kallsyms, ProcessKernelSymbols_ignore_arm_mapping_symbols) {
68 std::string data =
69 "aaaaaaaaaaaaaaaa t $x.9 [coresight_etm4x]\n"
70 "bbbbbbbbbbbbbbbb t etm4_pm_clear [coresight_etm4x]\n";
71 bool has_normal_symbol = false;
72 bool has_arm_mapping_symbol = false;
73 auto callback = [&](const KernelSymbol& sym) {
74 if (strcmp(sym.name, "etm4_pm_clear") == 0) {
75 has_normal_symbol = true;
76 } else {
77 has_arm_mapping_symbol = true;
78 }
79 return false;
80 };
81 ProcessKernelSymbols(data, callback);
82 ASSERT_TRUE(has_normal_symbol);
83 ASSERT_FALSE(has_arm_mapping_symbol);
84 }
85
86 #if defined(__ANDROID__)
TEST(kallsyms,GetKernelStartAddress)87 TEST(kallsyms, GetKernelStartAddress) {
88 TEST_REQUIRE_ROOT();
89 ASSERT_NE(GetKernelStartAddress(), 0u);
90 }
91
TEST(kallsyms,LoadKernelSymbols)92 TEST(kallsyms, LoadKernelSymbols) {
93 TEST_REQUIRE_ROOT();
94 std::string kallsyms;
95 ASSERT_TRUE(LoadKernelSymbols(&kallsyms));
96 }
97
TEST(kallsyms,print_warning)98 TEST(kallsyms, print_warning) {
99 TEST_REQUIRE_NON_ROOT();
100 const std::string warning_msg = "Access to kernel symbol addresses is restricted.";
101 CapturedStderr capture;
102
103 // Call each function requiring kernel addresses once. Check if the warning is printed.
104 ResetKernelAddressWarning();
105 ASSERT_EQ(0, GetKernelStartAddress());
106 capture.Stop();
107 ASSERT_NE(capture.str().find(warning_msg), std::string::npos);
108
109 capture.Reset();
110 capture.Start();
111 ResetKernelAddressWarning();
112 std::string kallsyms;
113 ASSERT_FALSE(LoadKernelSymbols(&kallsyms));
114 capture.Stop();
115 ASSERT_NE(capture.str().find(warning_msg), std::string::npos);
116
117 capture.Reset();
118 capture.Start();
119 ResetKernelAddressWarning();
120 ASSERT_TRUE(GetLoadedModules().empty());
121 capture.Stop();
122 ASSERT_NE(capture.str().find(warning_msg), std::string::npos);
123
124 // Call functions requiring kernel addresses more than once.
125 // Check if the kernel address warning is only printed once.
126 capture.Reset();
127 capture.Start();
128 ResetKernelAddressWarning();
129 for (int i = 0; i < 2; i++) {
130 ASSERT_EQ(0, GetKernelStartAddress());
131 ASSERT_FALSE(LoadKernelSymbols(&kallsyms));
132 ASSERT_TRUE(GetLoadedModules().empty());
133 }
134 capture.Stop();
135 std::string output = capture.str();
136 auto pos = output.find(warning_msg);
137 ASSERT_NE(pos, std::string::npos);
138 ASSERT_EQ(output.find(warning_msg, pos + warning_msg.size()), std::string::npos);
139 }
140 #endif // defined(__ANDROID__)
141