1//===-- sanitizer_common_printer_test.cpp ---------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of sanitizer_common test suite.
10//
11//===----------------------------------------------------------------------===//
12#include "sanitizer_common/sanitizer_stacktrace_printer.h"
13
14#include "gtest/gtest.h"
15#include "interception/interception.h"
16
17namespace __sanitizer {
18
19class TestFormattedStackTracePrinter final : public FormattedStackTracePrinter {
20 public:
21 ~TestFormattedStackTracePrinter() {}
22};
23
24TEST(FormattedStackTracePrinter, RenderSourceLocation) {
25 InternalScopedString str;
26 TestFormattedStackTracePrinter printer;
27
28 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 10, column: 5, vs_style: false, strip_path_prefix: "");
29 EXPECT_STREQ("/dir/file.cc:10:5", str.data());
30
31 str.clear();
32 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 11, column: 0, vs_style: false, strip_path_prefix: "");
33 EXPECT_STREQ("/dir/file.cc:11", str.data());
34
35 str.clear();
36 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 0, column: 0, vs_style: false, strip_path_prefix: "");
37 EXPECT_STREQ("/dir/file.cc", str.data());
38
39 str.clear();
40 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 10, column: 5, vs_style: false, strip_path_prefix: "/dir/");
41 EXPECT_STREQ("file.cc:10:5", str.data());
42
43 str.clear();
44 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 10, column: 5, vs_style: true, strip_path_prefix: "");
45 EXPECT_STREQ("/dir/file.cc(10,5)", str.data());
46
47 str.clear();
48 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 11, column: 0, vs_style: true, strip_path_prefix: "");
49 EXPECT_STREQ("/dir/file.cc(11)", str.data());
50
51 str.clear();
52 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 0, column: 0, vs_style: true, strip_path_prefix: "");
53 EXPECT_STREQ("/dir/file.cc", str.data());
54
55 str.clear();
56 printer.RenderSourceLocation(buffer: &str, file: "/dir/file.cc", line: 10, column: 5, vs_style: true, strip_path_prefix: "/dir/");
57 EXPECT_STREQ("file.cc(10,5)", str.data());
58}
59
60TEST(FormattedStackTracePrinter, RenderModuleLocation) {
61 InternalScopedString str;
62 TestFormattedStackTracePrinter printer;
63 printer.RenderModuleLocation(buffer: &str, module: "/dir/exe", offset: 0x123, arch: kModuleArchUnknown, strip_path_prefix: "");
64 EXPECT_STREQ("(/dir/exe+0x123)", str.data());
65
66 // Check that we strip file prefix if necessary.
67 str.clear();
68 printer.RenderModuleLocation(buffer: &str, module: "/dir/exe", offset: 0x123, arch: kModuleArchUnknown,
69 strip_path_prefix: "/dir/");
70 EXPECT_STREQ("(exe+0x123)", str.data());
71
72 // Check that we render the arch.
73 str.clear();
74 printer.RenderModuleLocation(buffer: &str, module: "/dir/exe", offset: 0x123, arch: kModuleArchX86_64H,
75 strip_path_prefix: "/dir/");
76 EXPECT_STREQ("(exe:x86_64h+0x123)", str.data());
77}
78
79TEST(FormattedStackTracePrinter, RenderFrame) {
80 TestFormattedStackTracePrinter printer;
81 int frame_no = 42;
82 AddressInfo info;
83 info.address = 0x400000;
84 info.module = internal_strdup(s: "/path/to/my/module");
85 info.module_offset = 0x200;
86 info.function = internal_strdup(s: "foo");
87 info.function_offset = 0x100;
88 info.file = internal_strdup(s: "/path/to/my/source");
89 info.line = 10;
90 info.column = 5;
91 InternalScopedString str;
92
93 // Dump all the AddressInfo fields.
94 printer.RenderFrame(buffer: &str,
95 format: "%% Frame:%n PC:%p Module:%m ModuleOffset:%o "
96 "Function:%f FunctionOffset:%q Source:%s Line:%l "
97 "Column:%c",
98 frame_no, address: info.address, info: &info, vs_style: false, strip_path_prefix: "/path/to/");
99 EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 "
100 "Function:foo FunctionOffset:0x100 Source:my/source Line:10 "
101 "Column:5",
102 str.data());
103
104 str.clear();
105 // Check that RenderFrame() strips interceptor prefixes.
106 info.function = internal_strdup(SANITIZER_STRINGIFY(WRAP(bar)));
107 printer.RenderFrame(buffer: &str,
108 format: "%% Frame:%n PC:%p Module:%m ModuleOffset:%o "
109 "Function:%f FunctionOffset:%q Source:%s Line:%l "
110 "Column:%c",
111 frame_no, address: info.address, info: &info, vs_style: false, strip_path_prefix: "/path/to/");
112 EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 "
113 "Function:bar FunctionOffset:0x100 Source:my/source Line:10 "
114 "Column:5",
115 str.data());
116 info.Clear();
117 str.clear();
118
119 // Test special format specifiers.
120 info.address = 0x400000;
121 printer.RenderFrame(buffer: &str, format: "%M", frame_no, address: info.address, info: &info, vs_style: false);
122 EXPECT_NE(nullptr, internal_strstr(haystack: str.data(), needle: "400000"));
123 str.clear();
124
125 printer.RenderFrame(buffer: &str, format: "%L", frame_no, address: info.address, info: &info, vs_style: false);
126 EXPECT_STREQ("(<unknown module>)", str.data());
127 str.clear();
128
129 info.module = internal_strdup(s: "/path/to/module");
130 info.module_offset = 0x200;
131 printer.RenderFrame(buffer: &str, format: "%M", frame_no, address: info.address, info: &info, vs_style: false);
132 EXPECT_NE(nullptr, internal_strstr(haystack: str.data(), needle: "(module+0x"));
133 EXPECT_NE(nullptr, internal_strstr(haystack: str.data(), needle: "200"));
134 str.clear();
135
136 printer.RenderFrame(buffer: &str, format: "%L", frame_no, address: info.address, info: &info, vs_style: false);
137 EXPECT_STREQ("(/path/to/module+0x200)", str.data());
138 str.clear();
139
140 printer.RenderFrame(buffer: &str, format: "%b", frame_no, address: info.address, info: &info, vs_style: false);
141 EXPECT_STREQ("", str.data());
142 str.clear();
143
144 info.uuid_size = 2;
145 info.uuid[0] = 0x55;
146 info.uuid[1] = 0x66;
147
148 printer.RenderFrame(buffer: &str, format: "%M", frame_no, address: info.address, info: &info, vs_style: false);
149 EXPECT_NE(nullptr, internal_strstr(haystack: str.data(), needle: "(module+0x"));
150 EXPECT_NE(nullptr, internal_strstr(haystack: str.data(), needle: "200"));
151#if SANITIZER_APPLE
152 EXPECT_EQ(nullptr, internal_strstr(str.data(), "BuildId: 5566"));
153#else
154 EXPECT_NE(nullptr, internal_strstr(haystack: str.data(), needle: "BuildId: 5566"));
155#endif
156 str.clear();
157
158 printer.RenderFrame(buffer: &str, format: "%L", frame_no, address: info.address, info: &info, vs_style: false);
159#if SANITIZER_APPLE
160 EXPECT_STREQ("(/path/to/module+0x200)", str.data());
161#else
162 EXPECT_STREQ("(/path/to/module+0x200) (BuildId: 5566)", str.data());
163#endif
164 str.clear();
165
166 printer.RenderFrame(buffer: &str, format: "%b", frame_no, address: info.address, info: &info, vs_style: false);
167 EXPECT_STREQ("(BuildId: 5566)", str.data());
168 str.clear();
169
170 info.function = internal_strdup(s: "my_function");
171 printer.RenderFrame(buffer: &str, format: "%F", frame_no, address: info.address, info: &info, vs_style: false);
172 EXPECT_STREQ("in my_function", str.data());
173 str.clear();
174
175 info.function_offset = 0x100;
176 printer.RenderFrame(buffer: &str, format: "%F %S", frame_no, address: info.address, info: &info, vs_style: false);
177 EXPECT_STREQ("in my_function+0x100 <null>", str.data());
178 str.clear();
179
180 info.file = internal_strdup(s: "my_file");
181 printer.RenderFrame(buffer: &str, format: "%F %S", frame_no, address: info.address, info: &info, vs_style: false);
182 EXPECT_STREQ("in my_function my_file", str.data());
183 str.clear();
184
185 info.line = 10;
186 printer.RenderFrame(buffer: &str, format: "%F %S", frame_no, address: info.address, info: &info, vs_style: false);
187 EXPECT_STREQ("in my_function my_file:10", str.data());
188 str.clear();
189
190 info.column = 5;
191 printer.RenderFrame(buffer: &str, format: "%S %L", frame_no, address: info.address, info: &info, vs_style: false);
192 EXPECT_STREQ("my_file:10:5 my_file:10:5", str.data());
193 str.clear();
194
195 printer.RenderFrame(buffer: &str, format: "%S %L", frame_no, address: info.address, info: &info, vs_style: true);
196 EXPECT_STREQ("my_file(10,5) my_file(10,5)", str.data());
197 str.clear();
198
199 info.column = 0;
200 printer.RenderFrame(buffer: &str, format: "%F %S", frame_no, address: info.address, info: &info, vs_style: true);
201 EXPECT_STREQ("in my_function my_file(10)", str.data());
202 str.clear();
203
204 info.line = 0;
205 printer.RenderFrame(buffer: &str, format: "%F %S", frame_no, address: info.address, info: &info, vs_style: true);
206 EXPECT_STREQ("in my_function my_file", str.data());
207 str.clear();
208
209 info.Clear();
210}
211
212} // namespace __sanitizer
213

source code of compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp