1 //===-- sanitizer_common_printer_test.cpp ---------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of sanitizer_common test suite.
11 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common/sanitizer_stacktrace_printer.h"
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16 #include "interception/interception.h"
18 using testing::MatchesRegex
;
20 namespace __sanitizer
{
22 class TestFormattedStackTracePrinter final
: public FormattedStackTracePrinter
{
24 ~TestFormattedStackTracePrinter() {}
27 TEST(FormattedStackTracePrinter
, RenderSourceLocation
) {
28 InternalScopedString str
;
29 TestFormattedStackTracePrinter printer
;
31 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, false, "");
32 EXPECT_STREQ("/dir/file.cc:10:5", str
.data());
35 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 11, 0, false, "");
36 EXPECT_STREQ("/dir/file.cc:11", str
.data());
39 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 0, 0, false, "");
40 EXPECT_STREQ("/dir/file.cc", str
.data());
43 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, false, "/dir/");
44 EXPECT_STREQ("file.cc:10:5", str
.data());
47 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, true, "");
48 EXPECT_STREQ("/dir/file.cc(10,5)", str
.data());
51 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 11, 0, true, "");
52 EXPECT_STREQ("/dir/file.cc(11)", str
.data());
55 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 0, 0, true, "");
56 EXPECT_STREQ("/dir/file.cc", str
.data());
59 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, true, "/dir/");
60 EXPECT_STREQ("file.cc(10,5)", str
.data());
63 TEST(FormattedStackTracePrinter
, RenderModuleLocation
) {
64 InternalScopedString str
;
65 TestFormattedStackTracePrinter printer
;
66 printer
.RenderModuleLocation(&str
, "/dir/exe", 0x123, kModuleArchUnknown
, "");
67 EXPECT_STREQ("(/dir/exe+0x123)", str
.data());
69 // Check that we strip file prefix if necessary.
71 printer
.RenderModuleLocation(&str
, "/dir/exe", 0x123, kModuleArchUnknown
,
73 EXPECT_STREQ("(exe+0x123)", str
.data());
75 // Check that we render the arch.
77 printer
.RenderModuleLocation(&str
, "/dir/exe", 0x123, kModuleArchX86_64H
,
79 EXPECT_STREQ("(exe:x86_64h+0x123)", str
.data());
82 TEST(FormattedStackTracePrinter
, RenderFrame
) {
83 TestFormattedStackTracePrinter printer
;
86 info
.address
= 0x400000;
87 info
.module
= internal_strdup("/path/to/my/module");
88 info
.module_offset
= 0x200;
89 info
.function
= internal_strdup("foo");
90 info
.function_offset
= 0x100;
91 info
.file
= internal_strdup("/path/to/my/source");
94 InternalScopedString str
;
96 // Dump all the AddressInfo fields.
97 printer
.RenderFrame(&str
,
98 "%% Frame:%n PC:%p Module:%m ModuleOffset:%o "
99 "Function:%f FunctionOffset:%q Source:%s Line:%l "
101 frame_no
, info
.address
, &info
, false, "/path/to/");
105 "% Frame:42 PC:0x0*400000 Module:my/module ModuleOffset:0x200 "
106 "Function:foo FunctionOffset:0x100 Source:my/source Line:10 "
110 // Check that RenderFrame() strips interceptor prefixes.
111 info
.function
= internal_strdup(SANITIZER_STRINGIFY(WRAP(bar
)));
112 printer
.RenderFrame(&str
,
113 "%% Frame:%n PC:%p Module:%m ModuleOffset:%o "
114 "Function:%f FunctionOffset:%q Source:%s Line:%l "
116 frame_no
, info
.address
, &info
, false, "/path/to/");
120 "% Frame:42 PC:0x0*400000 Module:my/module ModuleOffset:0x200 "
121 "Function:bar FunctionOffset:0x100 Source:my/source Line:10 "
126 // Test special format specifiers.
127 info
.address
= 0x400000;
128 printer
.RenderFrame(&str
, "%M", frame_no
, info
.address
, &info
, false);
129 EXPECT_NE(nullptr, internal_strstr(str
.data(), "400000"));
132 printer
.RenderFrame(&str
, "%L", frame_no
, info
.address
, &info
, false);
133 EXPECT_STREQ("(<unknown module>)", str
.data());
136 info
.module
= internal_strdup("/path/to/module");
137 info
.module_offset
= 0x200;
138 printer
.RenderFrame(&str
, "%M", frame_no
, info
.address
, &info
, false);
139 EXPECT_NE(nullptr, internal_strstr(str
.data(), "(module+0x"));
140 EXPECT_NE(nullptr, internal_strstr(str
.data(), "200"));
143 printer
.RenderFrame(&str
, "%L", frame_no
, info
.address
, &info
, false);
144 EXPECT_STREQ("(/path/to/module+0x200)", str
.data());
147 printer
.RenderFrame(&str
, "%b", frame_no
, info
.address
, &info
, false);
148 EXPECT_STREQ("", str
.data());
155 printer
.RenderFrame(&str
, "%M", frame_no
, info
.address
, &info
, false);
156 EXPECT_NE(nullptr, internal_strstr(str
.data(), "(module+0x"));
157 EXPECT_NE(nullptr, internal_strstr(str
.data(), "200"));
159 EXPECT_EQ(nullptr, internal_strstr(str
.data(), "BuildId: 5566"));
161 EXPECT_NE(nullptr, internal_strstr(str
.data(), "BuildId: 5566"));
165 printer
.RenderFrame(&str
, "%L", frame_no
, info
.address
, &info
, false);
167 EXPECT_STREQ("(/path/to/module+0x200)", str
.data());
169 EXPECT_STREQ("(/path/to/module+0x200) (BuildId: 5566)", str
.data());
173 printer
.RenderFrame(&str
, "%b", frame_no
, info
.address
, &info
, false);
174 EXPECT_STREQ("(BuildId: 5566)", str
.data());
177 info
.function
= internal_strdup("my_function");
178 printer
.RenderFrame(&str
, "%F", frame_no
, info
.address
, &info
, false);
179 EXPECT_STREQ("in my_function", str
.data());
182 info
.function_offset
= 0x100;
183 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, false);
184 EXPECT_STREQ("in my_function+0x100 <null>", str
.data());
187 info
.file
= internal_strdup("my_file");
188 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, false);
189 EXPECT_STREQ("in my_function my_file", str
.data());
193 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, false);
194 EXPECT_STREQ("in my_function my_file:10", str
.data());
198 printer
.RenderFrame(&str
, "%S %L", frame_no
, info
.address
, &info
, false);
199 EXPECT_STREQ("my_file:10:5 my_file:10:5", str
.data());
202 printer
.RenderFrame(&str
, "%S %L", frame_no
, info
.address
, &info
, true);
203 EXPECT_STREQ("my_file(10,5) my_file(10,5)", str
.data());
207 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, true);
208 EXPECT_STREQ("in my_function my_file(10)", str
.data());
212 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, true);
213 EXPECT_STREQ("in my_function my_file", str
.data());
219 } // namespace __sanitizer