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 "gtest/gtest.h"
15 #include "interception/interception.h"
17 namespace __sanitizer
{
19 class TestFormattedStackTracePrinter final
: public FormattedStackTracePrinter
{
21 ~TestFormattedStackTracePrinter() {}
24 TEST(FormattedStackTracePrinter
, RenderSourceLocation
) {
25 InternalScopedString str
;
26 TestFormattedStackTracePrinter printer
;
28 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, false, "");
29 EXPECT_STREQ("/dir/file.cc:10:5", str
.data());
32 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 11, 0, false, "");
33 EXPECT_STREQ("/dir/file.cc:11", str
.data());
36 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 0, 0, false, "");
37 EXPECT_STREQ("/dir/file.cc", str
.data());
40 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, false, "/dir/");
41 EXPECT_STREQ("file.cc:10:5", str
.data());
44 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, true, "");
45 EXPECT_STREQ("/dir/file.cc(10,5)", str
.data());
48 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 11, 0, true, "");
49 EXPECT_STREQ("/dir/file.cc(11)", str
.data());
52 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 0, 0, true, "");
53 EXPECT_STREQ("/dir/file.cc", str
.data());
56 printer
.RenderSourceLocation(&str
, "/dir/file.cc", 10, 5, true, "/dir/");
57 EXPECT_STREQ("file.cc(10,5)", str
.data());
60 TEST(FormattedStackTracePrinter
, RenderModuleLocation
) {
61 InternalScopedString str
;
62 TestFormattedStackTracePrinter printer
;
63 printer
.RenderModuleLocation(&str
, "/dir/exe", 0x123, kModuleArchUnknown
, "");
64 EXPECT_STREQ("(/dir/exe+0x123)", str
.data());
66 // Check that we strip file prefix if necessary.
68 printer
.RenderModuleLocation(&str
, "/dir/exe", 0x123, kModuleArchUnknown
,
70 EXPECT_STREQ("(exe+0x123)", str
.data());
72 // Check that we render the arch.
74 printer
.RenderModuleLocation(&str
, "/dir/exe", 0x123, kModuleArchX86_64H
,
76 EXPECT_STREQ("(exe:x86_64h+0x123)", str
.data());
79 TEST(FormattedStackTracePrinter
, RenderFrame
) {
80 TestFormattedStackTracePrinter printer
;
83 info
.address
= 0x400000;
84 info
.module
= internal_strdup("/path/to/my/module");
85 info
.module_offset
= 0x200;
86 info
.function
= internal_strdup("foo");
87 info
.function_offset
= 0x100;
88 info
.file
= internal_strdup("/path/to/my/source");
91 InternalScopedString str
;
93 // Dump all the AddressInfo fields.
94 printer
.RenderFrame(&str
,
95 "%% Frame:%n PC:%p Module:%m ModuleOffset:%o "
96 "Function:%f FunctionOffset:%q Source:%s Line:%l "
98 frame_no
, info
.address
, &info
, false, "/path/to/");
99 EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 "
100 "Function:foo FunctionOffset:0x100 Source:my/source Line:10 "
105 // Check that RenderFrame() strips interceptor prefixes.
106 info
.function
= internal_strdup(SANITIZER_STRINGIFY(WRAP(bar
)));
107 printer
.RenderFrame(&str
,
108 "%% Frame:%n PC:%p Module:%m ModuleOffset:%o "
109 "Function:%f FunctionOffset:%q Source:%s Line:%l "
111 frame_no
, info
.address
, &info
, false, "/path/to/");
112 EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 "
113 "Function:bar FunctionOffset:0x100 Source:my/source Line:10 "
119 // Test special format specifiers.
120 info
.address
= 0x400000;
121 printer
.RenderFrame(&str
, "%M", frame_no
, info
.address
, &info
, false);
122 EXPECT_NE(nullptr, internal_strstr(str
.data(), "400000"));
125 printer
.RenderFrame(&str
, "%L", frame_no
, info
.address
, &info
, false);
126 EXPECT_STREQ("(<unknown module>)", str
.data());
129 info
.module
= internal_strdup("/path/to/module");
130 info
.module_offset
= 0x200;
131 printer
.RenderFrame(&str
, "%M", frame_no
, info
.address
, &info
, false);
132 EXPECT_NE(nullptr, internal_strstr(str
.data(), "(module+0x"));
133 EXPECT_NE(nullptr, internal_strstr(str
.data(), "200"));
136 printer
.RenderFrame(&str
, "%L", frame_no
, info
.address
, &info
, false);
137 EXPECT_STREQ("(/path/to/module+0x200)", str
.data());
140 printer
.RenderFrame(&str
, "%b", frame_no
, info
.address
, &info
, false);
141 EXPECT_STREQ("", str
.data());
148 printer
.RenderFrame(&str
, "%M", frame_no
, info
.address
, &info
, false);
149 EXPECT_NE(nullptr, internal_strstr(str
.data(), "(module+0x"));
150 EXPECT_NE(nullptr, internal_strstr(str
.data(), "200"));
152 EXPECT_EQ(nullptr, internal_strstr(str
.data(), "BuildId: 5566"));
154 EXPECT_NE(nullptr, internal_strstr(str
.data(), "BuildId: 5566"));
158 printer
.RenderFrame(&str
, "%L", frame_no
, info
.address
, &info
, false);
160 EXPECT_STREQ("(/path/to/module+0x200)", str
.data());
162 EXPECT_STREQ("(/path/to/module+0x200) (BuildId: 5566)", str
.data());
166 printer
.RenderFrame(&str
, "%b", frame_no
, info
.address
, &info
, false);
167 EXPECT_STREQ("(BuildId: 5566)", str
.data());
170 info
.function
= internal_strdup("my_function");
171 printer
.RenderFrame(&str
, "%F", frame_no
, info
.address
, &info
, false);
172 EXPECT_STREQ("in my_function", str
.data());
175 info
.function_offset
= 0x100;
176 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, false);
177 EXPECT_STREQ("in my_function+0x100 <null>", str
.data());
180 info
.file
= internal_strdup("my_file");
181 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, false);
182 EXPECT_STREQ("in my_function my_file", str
.data());
186 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, false);
187 EXPECT_STREQ("in my_function my_file:10", str
.data());
191 printer
.RenderFrame(&str
, "%S %L", frame_no
, info
.address
, &info
, false);
192 EXPECT_STREQ("my_file:10:5 my_file:10:5", str
.data());
195 printer
.RenderFrame(&str
, "%S %L", frame_no
, info
.address
, &info
, true);
196 EXPECT_STREQ("my_file(10,5) my_file(10,5)", str
.data());
200 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, true);
201 EXPECT_STREQ("in my_function my_file(10)", str
.data());
205 printer
.RenderFrame(&str
, "%F %S", frame_no
, info
.address
, &info
, true);
206 EXPECT_STREQ("in my_function my_file", str
.data());
212 } // namespace __sanitizer