1 /*
2 * Copyright (C) 2021 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 #include <sys/prctl.h>
19
20 #include <string>
21
22 #include <android-base/test_utils.h>
23
24 #include "libdebuggerd/tombstone.h"
25 #include "libdebuggerd/tombstone_proto_to_text.h"
26 #include "tombstone.pb.h"
27
28 using CallbackType = std::function<void(const std::string& line, bool should_log)>;
29
30 class TombstoneProtoToTextTest : public ::testing::Test {
31 public:
SetUp()32 void SetUp() {
33 tombstone_.reset(new Tombstone);
34
35 tombstone_->set_arch(Architecture::ARM64);
36 tombstone_->set_build_fingerprint("Test fingerprint");
37 tombstone_->set_timestamp("1970-01-01 00:00:00");
38 tombstone_->set_pid(100);
39 tombstone_->set_tid(100);
40 tombstone_->set_uid(0);
41 tombstone_->set_selinux_label("none");
42
43 Signal signal;
44 signal.set_number(SIGSEGV);
45 signal.set_name("SIGSEGV");
46 signal.set_code(0);
47 signal.set_code_name("none");
48
49 *tombstone_->mutable_signal_info() = signal;
50
51 Thread thread;
52 thread.set_id(100);
53 thread.set_name("main");
54 thread.set_tagged_addr_ctrl(0);
55 thread.set_pac_enabled_keys(0);
56
57 auto& threads = *tombstone_->mutable_threads();
58 threads[100] = thread;
59 main_thread_ = &threads[100];
60 }
61
ProtoToString()62 void ProtoToString() {
63 text_ = "";
64 EXPECT_TRUE(tombstone_proto_to_text(
65 *tombstone_,
66 [this](const std::string& line, bool should_log) {
67 if (should_log) {
68 text_ += "LOG ";
69 }
70 text_ += line + '\n';
71 },
72 [&](const BacktraceFrame& frame) {
73 text_ += "SYMBOLIZE " + frame.build_id() + " " + std::to_string(frame.pc()) + "\n";
74 }));
75 }
76
77 Thread* main_thread_;
78 std::string text_;
79 std::unique_ptr<Tombstone> tombstone_;
80 };
81
TEST_F(TombstoneProtoToTextTest,tagged_addr_ctrl)82 TEST_F(TombstoneProtoToTextTest, tagged_addr_ctrl) {
83 main_thread_->set_tagged_addr_ctrl(0);
84 ProtoToString();
85 EXPECT_MATCH(text_, "LOG tagged_addr_ctrl: 0000000000000000\\n");
86
87 main_thread_->set_tagged_addr_ctrl(PR_TAGGED_ADDR_ENABLE);
88 ProtoToString();
89 EXPECT_MATCH(text_, "LOG tagged_addr_ctrl: 0000000000000001 \\(PR_TAGGED_ADDR_ENABLE\\)\\n");
90
91 main_thread_->set_tagged_addr_ctrl(PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC |
92 (0xfffe << PR_MTE_TAG_SHIFT));
93 ProtoToString();
94 EXPECT_MATCH(text_,
95 "LOG tagged_addr_ctrl: 000000000007fff3 \\(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, "
96 "mask 0xfffe\\)\\n");
97
98 main_thread_->set_tagged_addr_ctrl(0xf0000000 | PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC |
99 PR_MTE_TCF_ASYNC | (0xfffe << PR_MTE_TAG_SHIFT));
100 ProtoToString();
101 EXPECT_MATCH(text_,
102 "LOG tagged_addr_ctrl: 00000000f007fff7 \\(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, "
103 "PR_MTE_TCF_ASYNC, mask 0xfffe, unknown 0xf0000000\\)\\n");
104 }
105
TEST_F(TombstoneProtoToTextTest,pac_enabled_keys)106 TEST_F(TombstoneProtoToTextTest, pac_enabled_keys) {
107 main_thread_->set_pac_enabled_keys(0);
108 ProtoToString();
109 EXPECT_MATCH(text_, "LOG pac_enabled_keys: 0000000000000000\\n");
110
111 main_thread_->set_pac_enabled_keys(PR_PAC_APIAKEY);
112 ProtoToString();
113 EXPECT_MATCH(text_, "LOG pac_enabled_keys: 0000000000000001 \\(PR_PAC_APIAKEY\\)\\n");
114
115 main_thread_->set_pac_enabled_keys(PR_PAC_APIAKEY | PR_PAC_APDBKEY);
116 ProtoToString();
117 EXPECT_MATCH(text_,
118 "LOG pac_enabled_keys: 0000000000000009 \\(PR_PAC_APIAKEY, PR_PAC_APDBKEY\\)\\n");
119
120 main_thread_->set_pac_enabled_keys(PR_PAC_APIAKEY | PR_PAC_APDBKEY | 0x1000);
121 ProtoToString();
122 EXPECT_MATCH(text_,
123 "LOG pac_enabled_keys: 0000000000001009 \\(PR_PAC_APIAKEY, PR_PAC_APDBKEY, unknown "
124 "0x1000\\)\\n");
125 }
126
TEST_F(TombstoneProtoToTextTest,crash_detail_string)127 TEST_F(TombstoneProtoToTextTest, crash_detail_string) {
128 auto* crash_detail = tombstone_->add_crash_details();
129 crash_detail->set_name("CRASH_DETAIL_NAME");
130 crash_detail->set_data("crash_detail_value");
131 ProtoToString();
132 EXPECT_MATCH(text_, "(CRASH_DETAIL_NAME: 'crash_detail_value')");
133 }
134
TEST_F(TombstoneProtoToTextTest,crash_detail_bytes)135 TEST_F(TombstoneProtoToTextTest, crash_detail_bytes) {
136 auto* crash_detail = tombstone_->add_crash_details();
137 crash_detail->set_name("CRASH_DETAIL_NAME");
138 crash_detail->set_data("helloworld\1\255\3");
139 ProtoToString();
140 EXPECT_MATCH(text_, R"(CRASH_DETAIL_NAME: 'helloworld\\1\\255\\3')");
141 }
142
TEST_F(TombstoneProtoToTextTest,stack_record)143 TEST_F(TombstoneProtoToTextTest, stack_record) {
144 auto* cause = tombstone_->add_causes();
145 cause->set_human_readable("stack tag-mismatch on thread 123");
146 auto* stack = tombstone_->mutable_stack_history_buffer();
147 stack->set_tid(123);
148 {
149 auto* shb_entry = stack->add_entries();
150 shb_entry->set_fp(0x1);
151 shb_entry->set_tag(0xb);
152 auto* addr = shb_entry->mutable_addr();
153 addr->set_rel_pc(0x567);
154 addr->set_file_name("foo.so");
155 addr->set_build_id("ABC123");
156 }
157 {
158 auto* shb_entry = stack->add_entries();
159 shb_entry->set_fp(0x2);
160 shb_entry->set_tag(0xc);
161 auto* addr = shb_entry->mutable_addr();
162 addr->set_rel_pc(0x678);
163 addr->set_file_name("bar.so");
164 }
165 ProtoToString();
166 EXPECT_MATCH(text_, "stack tag-mismatch on thread 123");
167 EXPECT_MATCH(text_, "stack_record fp:0x1 tag:0xb pc:foo\\.so\\+0x567 \\(BuildId: ABC123\\)");
168 EXPECT_MATCH(text_, "stack_record fp:0x2 tag:0xc pc:bar\\.so\\+0x678");
169 }
170
TEST_F(TombstoneProtoToTextTest,symbolize)171 TEST_F(TombstoneProtoToTextTest, symbolize) {
172 BacktraceFrame* frame = main_thread_->add_current_backtrace();
173 frame->set_pc(12345);
174 frame->set_build_id("0123456789abcdef");
175 ProtoToString();
176 EXPECT_MATCH(text_, "\\(BuildId: 0123456789abcdef\\)\\nSYMBOLIZE 0123456789abcdef 12345\\n");
177 }
178