[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / compiler-rt / test / sanitizer_common / TestCases / Linux / internal_symbolizer.cpp
blobe43f7a28e275dd3de70dcbd04c7e3934ea36bed3
1 // RUN: %clangxx %s -o %t -g && %run %t 2>&1 | FileCheck %s
3 // REQUIRES: internal_symbolizer
5 #include <assert.h>
6 #include <dlfcn.h>
7 #include <link.h>
8 #include <sanitizer/hwasan_interface.h>
9 #include <sanitizer/msan_interface.h>
10 #include <string.h>
12 #include <string>
13 #include <vector>
15 extern "C" {
16 bool __sanitizer_symbolize_code(const char *ModuleName, uint64_t ModuleOffset,
17 char *Buffer, int MaxLength,
18 bool SymbolizeInlineFrames);
19 bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,
20 char *Buffer, int MaxLength);
21 bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset,
22 char *Buffer, int MaxLength);
23 void __sanitizer_print_stack_trace();
24 bool __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
25 int MaxLength);
28 struct ScopedInSymbolizer {
29 #if defined(__has_feature)
30 # if __has_feature(memory_sanitizer)
31 ScopedInSymbolizer() { __msan_scoped_disable_interceptor_checks(); }
32 ~ScopedInSymbolizer() { __msan_scoped_enable_interceptor_checks(); }
33 # endif
34 #endif
37 struct FrameInfo {
38 int line;
39 std::string file;
40 std::string function;
41 void *address;
44 __attribute__((noinline)) void *GetPC() { return __builtin_return_address(0); }
46 __attribute__((always_inline)) FrameInfo InlineFunction() {
47 void *address = GetPC();
48 return {0, "", "",
49 reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(address) - 1)};
52 __attribute__((noinline)) FrameInfo NoInlineFunction() {
53 void *address = GetPC();
54 return {0, "", "",
55 reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(address) - 1)};
58 template <int N> struct A {
59 template <class T> FrameInfo RecursiveTemplateFunction(const T &t);
62 template <int N>
63 template <class T>
64 __attribute__((noinline)) FrameInfo A<N>::RecursiveTemplateFunction(const T &) {
65 std::vector<T> t;
66 return A<N - 1>().RecursiveTemplateFunction(t);
69 template <>
70 template <class T>
71 __attribute__((noinline)) FrameInfo A<0>::RecursiveTemplateFunction(const T &) {
72 return NoInlineFunction();
75 __attribute__((no_sanitize_memory)) std::pair<const char *, uint64_t>
76 GetModuleAndOffset(const void *address) {
77 Dl_info di;
78 link_map *lm = nullptr;
79 #if __has_feature(hwaddress_sanitizer)
80 address = __hwasan_tag_pointer(address, 0);
81 #endif
82 assert(
83 dladdr1(address, &di, reinterpret_cast<void **>(&lm), RTLD_DL_LINKMAP));
84 return {di.dli_fname, reinterpret_cast<uint64_t>(address) - lm->l_addr};
87 std::string Symbolize(FrameInfo frame) {
88 auto modul_offset = GetModuleAndOffset(frame.address);
89 char buffer[1024] = {};
90 ScopedInSymbolizer in_symbolizer;
91 assert(__sanitizer_symbolize_code(modul_offset.first, modul_offset.second,
92 buffer, std::size(buffer), true));
93 return buffer;
96 std::string GetRegex(const FrameInfo &frame) {
97 return frame.function + "[^\\n]*\\n[^\\n]*" + frame.file + ":" +
98 std::to_string(frame.line);
101 void TestInline() {
102 auto frame = InlineFunction();
103 fprintf(stderr, "%s: %s\n", __FUNCTION__, Symbolize(frame).c_str());
104 // CHECK-LABEL: TestInline: InlineFunction()
105 // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 58]]
106 // CHECK-NEXT: TestInline()
107 // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 5]]
110 void TestNoInline() {
111 auto frame = NoInlineFunction();
112 fprintf(stderr, "%s: %s\n", __FUNCTION__, Symbolize(frame).c_str());
113 // CHECK-LABEL: TestNoInline: NoInlineFunction()
114 // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 61]]
117 void TestLongFunctionNames() {
118 auto frame = A<10>().RecursiveTemplateFunction(0);
119 fprintf(stderr, "%s: %s\n", __FUNCTION__, Symbolize(frame).c_str());
120 // CHECK-LABEL: TestLongFunctionNames: NoInlineFunction()
121 // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 68]]
124 std::string SymbolizeStaticVar() {
125 static int var = 1;
126 auto modul_offset = GetModuleAndOffset(&var);
127 char buffer[1024] = {};
128 ScopedInSymbolizer in_symbolizer;
129 assert(__sanitizer_symbolize_data(modul_offset.first, modul_offset.second,
130 buffer, std::size(buffer)));
131 return buffer;
134 void TestData() {
135 fprintf(stderr, "%s: %s\n", __FUNCTION__, SymbolizeStaticVar().c_str());
136 // CHECK-LABEL: TestData: SymbolizeStaticVar[abi:cxx11]()::var
137 // CHECK-NEXT: {{[0-9]+ +[0-9]+}}
138 // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 13]]
141 __attribute__((noinline)) std::string SymbolizeLocalVars(const void *pc) {
142 auto modul_offset = GetModuleAndOffset(pc);
143 char buffer[1024] = {};
144 ScopedInSymbolizer in_symbolizer;
145 __sanitizer_symbolize_frame(modul_offset.first, modul_offset.second, buffer,
146 std::size(buffer));
147 return buffer;
150 __attribute__((
151 noinline,
152 no_sanitize_address /* Asan merges allocas destroying variable DI */)) void
153 TestFrame() {
154 volatile int var = 1;
155 void *address = GetPC();
156 fprintf(stderr, "%s: %s\n", __FUNCTION__,
157 SymbolizeLocalVars(address).c_str());
158 // CHECK-LABEL: TestFrame: TestFrame
159 // CHECK-NEXT: var
160 // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 6]]
161 // CHECK-NEXT: {{-?[0-9]+ +[0-9]+}}
162 // CHECK-NEXT: TestFrame
163 // CHECK-NEXT: address
164 // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 9]]
165 // CHECK-NEXT: {{-?[0-9]+ +[0-9]+}}
168 void TestDemangle() {
169 char out[128];
170 assert(!__sanitizer_symbolize_demangle("1A", out, sizeof(out)));
172 const char name[] = "_Z3fooi";
173 for (int i = 1; i < sizeof(out); ++i) {
174 memset(out, 1, sizeof(out));
175 assert(__sanitizer_symbolize_demangle(name, out, i) == (i > 8));
176 assert(i < 9 || 0 == strncmp(out, "foo(int)", i - 1));
180 int main() {
181 TestInline();
182 TestNoInline();
183 TestLongFunctionNames();
184 TestData();
185 TestFrame();
186 TestDemangle();