xref: /aosp_15_r20/external/abseil-cpp/absl/debugging/symbolize_test.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker 
15*9356374aSAndroid Build Coastguard Worker #include "absl/debugging/symbolize.h"
16*9356374aSAndroid Build Coastguard Worker 
17*9356374aSAndroid Build Coastguard Worker #ifdef __EMSCRIPTEN__
18*9356374aSAndroid Build Coastguard Worker #include <emscripten.h>
19*9356374aSAndroid Build Coastguard Worker #endif
20*9356374aSAndroid Build Coastguard Worker 
21*9356374aSAndroid Build Coastguard Worker #ifndef _WIN32
22*9356374aSAndroid Build Coastguard Worker #include <fcntl.h>
23*9356374aSAndroid Build Coastguard Worker #include <sys/mman.h>
24*9356374aSAndroid Build Coastguard Worker #endif
25*9356374aSAndroid Build Coastguard Worker 
26*9356374aSAndroid Build Coastguard Worker #include <cstring>
27*9356374aSAndroid Build Coastguard Worker #include <iostream>
28*9356374aSAndroid Build Coastguard Worker #include <memory>
29*9356374aSAndroid Build Coastguard Worker 
30*9356374aSAndroid Build Coastguard Worker #include "gmock/gmock.h"
31*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
32*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
33*9356374aSAndroid Build Coastguard Worker #include "absl/base/casts.h"
34*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
35*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/per_thread_tls.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/base/optimization.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/debugging/internal/stack_consumption.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/log/check.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/log/log.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/memory/memory.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
42*9356374aSAndroid Build Coastguard Worker 
43*9356374aSAndroid Build Coastguard Worker #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
44*9356374aSAndroid Build Coastguard Worker #define MAP_ANONYMOUS MAP_ANON
45*9356374aSAndroid Build Coastguard Worker #endif
46*9356374aSAndroid Build Coastguard Worker 
47*9356374aSAndroid Build Coastguard Worker using testing::Contains;
48*9356374aSAndroid Build Coastguard Worker 
49*9356374aSAndroid Build Coastguard Worker #ifdef _WIN32
50*9356374aSAndroid Build Coastguard Worker #define ABSL_SYMBOLIZE_TEST_NOINLINE __declspec(noinline)
51*9356374aSAndroid Build Coastguard Worker #else
52*9356374aSAndroid Build Coastguard Worker #define ABSL_SYMBOLIZE_TEST_NOINLINE ABSL_ATTRIBUTE_NOINLINE
53*9356374aSAndroid Build Coastguard Worker #endif
54*9356374aSAndroid Build Coastguard Worker 
55*9356374aSAndroid Build Coastguard Worker // Functions to symbolize. Use C linkage to avoid mangled names.
56*9356374aSAndroid Build Coastguard Worker extern "C" {
nonstatic_func()57*9356374aSAndroid Build Coastguard Worker ABSL_SYMBOLIZE_TEST_NOINLINE void nonstatic_func() {
58*9356374aSAndroid Build Coastguard Worker   // The next line makes this a unique function to prevent the compiler from
59*9356374aSAndroid Build Coastguard Worker   // folding identical functions together.
60*9356374aSAndroid Build Coastguard Worker   volatile int x = __LINE__;
61*9356374aSAndroid Build Coastguard Worker   static_cast<void>(x);
62*9356374aSAndroid Build Coastguard Worker   ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
63*9356374aSAndroid Build Coastguard Worker }
64*9356374aSAndroid Build Coastguard Worker 
static_func()65*9356374aSAndroid Build Coastguard Worker ABSL_SYMBOLIZE_TEST_NOINLINE static void static_func() {
66*9356374aSAndroid Build Coastguard Worker   // The next line makes this a unique function to prevent the compiler from
67*9356374aSAndroid Build Coastguard Worker   // folding identical functions together.
68*9356374aSAndroid Build Coastguard Worker   volatile int x = __LINE__;
69*9356374aSAndroid Build Coastguard Worker   static_cast<void>(x);
70*9356374aSAndroid Build Coastguard Worker   ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
71*9356374aSAndroid Build Coastguard Worker }
72*9356374aSAndroid Build Coastguard Worker }  // extern "C"
73*9356374aSAndroid Build Coastguard Worker 
74*9356374aSAndroid Build Coastguard Worker struct Foo {
75*9356374aSAndroid Build Coastguard Worker   static void func(int x);
76*9356374aSAndroid Build Coastguard Worker };
77*9356374aSAndroid Build Coastguard Worker 
78*9356374aSAndroid Build Coastguard Worker // A C++ method that should have a mangled name.
func(int)79*9356374aSAndroid Build Coastguard Worker ABSL_SYMBOLIZE_TEST_NOINLINE void Foo::func(int) {
80*9356374aSAndroid Build Coastguard Worker   // The next line makes this a unique function to prevent the compiler from
81*9356374aSAndroid Build Coastguard Worker   // folding identical functions together.
82*9356374aSAndroid Build Coastguard Worker   volatile int x = __LINE__;
83*9356374aSAndroid Build Coastguard Worker   static_cast<void>(x);
84*9356374aSAndroid Build Coastguard Worker   ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
85*9356374aSAndroid Build Coastguard Worker }
86*9356374aSAndroid Build Coastguard Worker 
87*9356374aSAndroid Build Coastguard Worker // Create functions that will remain in different text sections in the
88*9356374aSAndroid Build Coastguard Worker // final binary when linker option "-z,keep-text-section-prefix" is used.
unlikely_func()89*9356374aSAndroid Build Coastguard Worker int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.unlikely) unlikely_func() {
90*9356374aSAndroid Build Coastguard Worker   return 0;
91*9356374aSAndroid Build Coastguard Worker }
92*9356374aSAndroid Build Coastguard Worker 
hot_func()93*9356374aSAndroid Build Coastguard Worker int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.hot) hot_func() { return 0; }
94*9356374aSAndroid Build Coastguard Worker 
startup_func()95*9356374aSAndroid Build Coastguard Worker int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.startup) startup_func() { return 0; }
96*9356374aSAndroid Build Coastguard Worker 
exit_func()97*9356374aSAndroid Build Coastguard Worker int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.exit) exit_func() { return 0; }
98*9356374aSAndroid Build Coastguard Worker 
regular_func()99*9356374aSAndroid Build Coastguard Worker int /*ABSL_ATTRIBUTE_SECTION_VARIABLE(.text)*/ regular_func() { return 0; }
100*9356374aSAndroid Build Coastguard Worker 
101*9356374aSAndroid Build Coastguard Worker // Thread-local data may confuse the symbolizer, ensure that it does not.
102*9356374aSAndroid Build Coastguard Worker // Variable sizes and order are important.
103*9356374aSAndroid Build Coastguard Worker #if ABSL_PER_THREAD_TLS
104*9356374aSAndroid Build Coastguard Worker static ABSL_PER_THREAD_TLS_KEYWORD char symbolize_test_thread_small[1];
105*9356374aSAndroid Build Coastguard Worker static ABSL_PER_THREAD_TLS_KEYWORD char
106*9356374aSAndroid Build Coastguard Worker     symbolize_test_thread_big[2 * 1024 * 1024];
107*9356374aSAndroid Build Coastguard Worker #endif
108*9356374aSAndroid Build Coastguard Worker 
109*9356374aSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
GetPCFromFnPtr(void * ptr)110*9356374aSAndroid Build Coastguard Worker static void *GetPCFromFnPtr(void *ptr) { return ptr; }
111*9356374aSAndroid Build Coastguard Worker 
112*9356374aSAndroid Build Coastguard Worker // Used below to hopefully inhibit some compiler/linker optimizations
113*9356374aSAndroid Build Coastguard Worker // that may remove kHpageTextPadding, kPadding0, and kPadding1 from
114*9356374aSAndroid Build Coastguard Worker // the binary.
115*9356374aSAndroid Build Coastguard Worker static volatile bool volatile_bool = false;
116*9356374aSAndroid Build Coastguard Worker 
117*9356374aSAndroid Build Coastguard Worker // Force the binary to be large enough that a THP .text remap will succeed.
118*9356374aSAndroid Build Coastguard Worker static constexpr size_t kHpageSize = 1 << 21;
119*9356374aSAndroid Build Coastguard Worker const char kHpageTextPadding[kHpageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(
120*9356374aSAndroid Build Coastguard Worker         .text) = "";
121*9356374aSAndroid Build Coastguard Worker 
122*9356374aSAndroid Build Coastguard Worker #else
GetPCFromFnPtr(void * ptr)123*9356374aSAndroid Build Coastguard Worker static void *GetPCFromFnPtr(void *ptr) {
124*9356374aSAndroid Build Coastguard Worker   return EM_ASM_PTR(
125*9356374aSAndroid Build Coastguard Worker       { return wasmOffsetConverter.convert(wasmTable.get($0).name, 0); }, ptr);
126*9356374aSAndroid Build Coastguard Worker }
127*9356374aSAndroid Build Coastguard Worker 
128*9356374aSAndroid Build Coastguard Worker #endif  // !defined(__EMSCRIPTEN__)
129*9356374aSAndroid Build Coastguard Worker 
130*9356374aSAndroid Build Coastguard Worker static char try_symbolize_buffer[4096];
131*9356374aSAndroid Build Coastguard Worker 
132*9356374aSAndroid Build Coastguard Worker // A wrapper function for absl::Symbolize() to make the unit test simple.  The
133*9356374aSAndroid Build Coastguard Worker // limit must be < sizeof(try_symbolize_buffer).  Returns null if
134*9356374aSAndroid Build Coastguard Worker // absl::Symbolize() returns false, otherwise returns try_symbolize_buffer with
135*9356374aSAndroid Build Coastguard Worker // the result of absl::Symbolize().
TrySymbolizeWithLimit(void * pc,int limit)136*9356374aSAndroid Build Coastguard Worker static const char *TrySymbolizeWithLimit(void *pc, int limit) {
137*9356374aSAndroid Build Coastguard Worker   CHECK_LE(limit, sizeof(try_symbolize_buffer))
138*9356374aSAndroid Build Coastguard Worker       << "try_symbolize_buffer is too small";
139*9356374aSAndroid Build Coastguard Worker 
140*9356374aSAndroid Build Coastguard Worker   // Use the heap to facilitate heap and buffer sanitizer tools.
141*9356374aSAndroid Build Coastguard Worker   auto heap_buffer = absl::make_unique<char[]>(sizeof(try_symbolize_buffer));
142*9356374aSAndroid Build Coastguard Worker   bool found = absl::Symbolize(pc, heap_buffer.get(), limit);
143*9356374aSAndroid Build Coastguard Worker   if (found) {
144*9356374aSAndroid Build Coastguard Worker     CHECK_LT(static_cast<int>(
145*9356374aSAndroid Build Coastguard Worker                  strnlen(heap_buffer.get(), static_cast<size_t>(limit))),
146*9356374aSAndroid Build Coastguard Worker              limit)
147*9356374aSAndroid Build Coastguard Worker         << "absl::Symbolize() did not properly terminate the string";
148*9356374aSAndroid Build Coastguard Worker     strncpy(try_symbolize_buffer, heap_buffer.get(),
149*9356374aSAndroid Build Coastguard Worker             sizeof(try_symbolize_buffer) - 1);
150*9356374aSAndroid Build Coastguard Worker     try_symbolize_buffer[sizeof(try_symbolize_buffer) - 1] = '\0';
151*9356374aSAndroid Build Coastguard Worker   }
152*9356374aSAndroid Build Coastguard Worker 
153*9356374aSAndroid Build Coastguard Worker   return found ? try_symbolize_buffer : nullptr;
154*9356374aSAndroid Build Coastguard Worker }
155*9356374aSAndroid Build Coastguard Worker 
156*9356374aSAndroid Build Coastguard Worker // A wrapper for TrySymbolizeWithLimit(), with a large limit.
TrySymbolize(void * pc)157*9356374aSAndroid Build Coastguard Worker static const char *TrySymbolize(void *pc) {
158*9356374aSAndroid Build Coastguard Worker   return TrySymbolizeWithLimit(pc, sizeof(try_symbolize_buffer));
159*9356374aSAndroid Build Coastguard Worker }
160*9356374aSAndroid Build Coastguard Worker 
161*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) ||    \
162*9356374aSAndroid Build Coastguard Worker     defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE) || \
163*9356374aSAndroid Build Coastguard Worker     defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE)
164*9356374aSAndroid Build Coastguard Worker 
165*9356374aSAndroid Build Coastguard Worker // Test with a return address.
TestWithReturnAddress()166*9356374aSAndroid Build Coastguard Worker void ABSL_ATTRIBUTE_NOINLINE TestWithReturnAddress() {
167*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
168*9356374aSAndroid Build Coastguard Worker   void *return_address = __builtin_return_address(0);
169*9356374aSAndroid Build Coastguard Worker   const char *symbol = TrySymbolize(return_address);
170*9356374aSAndroid Build Coastguard Worker   CHECK_NE(symbol, nullptr) << "TestWithReturnAddress failed";
171*9356374aSAndroid Build Coastguard Worker   CHECK_STREQ(symbol, "main") << "TestWithReturnAddress failed";
172*9356374aSAndroid Build Coastguard Worker   std::cout << "TestWithReturnAddress passed" << std::endl;
173*9356374aSAndroid Build Coastguard Worker #endif
174*9356374aSAndroid Build Coastguard Worker }
175*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,Cached)176*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, Cached) {
177*9356374aSAndroid Build Coastguard Worker   // Compilers should give us pointers to them.
178*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic_func",
179*9356374aSAndroid Build Coastguard Worker                TrySymbolize(GetPCFromFnPtr((void *)(&nonstatic_func))));
180*9356374aSAndroid Build Coastguard Worker   // The name of an internal linkage symbol is not specified; allow either a
181*9356374aSAndroid Build Coastguard Worker   // mangled or an unmangled name here.
182*9356374aSAndroid Build Coastguard Worker   const char *static_func_symbol =
183*9356374aSAndroid Build Coastguard Worker       TrySymbolize(GetPCFromFnPtr((void *)(&static_func)));
184*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 ||
185*9356374aSAndroid Build Coastguard Worker               strcmp("static_func()", static_func_symbol) == 0);
186*9356374aSAndroid Build Coastguard Worker 
187*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(nullptr == TrySymbolize(nullptr));
188*9356374aSAndroid Build Coastguard Worker }
189*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,Truncation)190*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, Truncation) {
191*9356374aSAndroid Build Coastguard Worker   constexpr char kNonStaticFunc[] = "nonstatic_func";
192*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic_func",
193*9356374aSAndroid Build Coastguard Worker                TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)),
194*9356374aSAndroid Build Coastguard Worker                                      strlen(kNonStaticFunc) + 1));
195*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic_...",
196*9356374aSAndroid Build Coastguard Worker                TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)),
197*9356374aSAndroid Build Coastguard Worker                                      strlen(kNonStaticFunc) + 0));
198*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic...",
199*9356374aSAndroid Build Coastguard Worker                TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)),
200*9356374aSAndroid Build Coastguard Worker                                      strlen(kNonStaticFunc) - 1));
201*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("n...", TrySymbolizeWithLimit(
202*9356374aSAndroid Build Coastguard Worker                            GetPCFromFnPtr((void *)(&nonstatic_func)), 5));
203*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("...", TrySymbolizeWithLimit(
204*9356374aSAndroid Build Coastguard Worker                           GetPCFromFnPtr((void *)(&nonstatic_func)), 4));
205*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("..", TrySymbolizeWithLimit(
206*9356374aSAndroid Build Coastguard Worker                          GetPCFromFnPtr((void *)(&nonstatic_func)), 3));
207*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ(
208*9356374aSAndroid Build Coastguard Worker       ".", TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)), 2));
209*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ(
210*9356374aSAndroid Build Coastguard Worker       "", TrySymbolizeWithLimit(GetPCFromFnPtr((void *)(&nonstatic_func)), 1));
211*9356374aSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, TrySymbolizeWithLimit(
212*9356374aSAndroid Build Coastguard Worker                          GetPCFromFnPtr((void *)(&nonstatic_func)), 0));
213*9356374aSAndroid Build Coastguard Worker }
214*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,SymbolizeWithDemangling)215*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, SymbolizeWithDemangling) {
216*9356374aSAndroid Build Coastguard Worker   Foo::func(100);
217*9356374aSAndroid Build Coastguard Worker #ifdef __EMSCRIPTEN__
218*9356374aSAndroid Build Coastguard Worker   // Emscripten's online symbolizer is more precise with arguments.
219*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("Foo::func(int)",
220*9356374aSAndroid Build Coastguard Worker                TrySymbolize(GetPCFromFnPtr((void *)(&Foo::func))));
221*9356374aSAndroid Build Coastguard Worker #else
222*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("Foo::func()",
223*9356374aSAndroid Build Coastguard Worker                TrySymbolize(GetPCFromFnPtr((void *)(&Foo::func))));
224*9356374aSAndroid Build Coastguard Worker #endif
225*9356374aSAndroid Build Coastguard Worker }
226*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,SymbolizeSplitTextSections)227*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, SymbolizeSplitTextSections) {
228*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("unlikely_func()",
229*9356374aSAndroid Build Coastguard Worker                TrySymbolize(GetPCFromFnPtr((void *)(&unlikely_func))));
230*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("hot_func()", TrySymbolize(GetPCFromFnPtr((void *)(&hot_func))));
231*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("startup_func()",
232*9356374aSAndroid Build Coastguard Worker                TrySymbolize(GetPCFromFnPtr((void *)(&startup_func))));
233*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("exit_func()",
234*9356374aSAndroid Build Coastguard Worker                TrySymbolize(GetPCFromFnPtr((void *)(&exit_func))));
235*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("regular_func()",
236*9356374aSAndroid Build Coastguard Worker                TrySymbolize(GetPCFromFnPtr((void *)(&regular_func))));
237*9356374aSAndroid Build Coastguard Worker }
238*9356374aSAndroid Build Coastguard Worker 
239*9356374aSAndroid Build Coastguard Worker // Tests that verify that Symbolize stack footprint is within some limit.
240*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
241*9356374aSAndroid Build Coastguard Worker 
242*9356374aSAndroid Build Coastguard Worker static void *g_pc_to_symbolize;
243*9356374aSAndroid Build Coastguard Worker static char g_symbolize_buffer[4096];
244*9356374aSAndroid Build Coastguard Worker static char *g_symbolize_result;
245*9356374aSAndroid Build Coastguard Worker 
SymbolizeSignalHandler(int signo)246*9356374aSAndroid Build Coastguard Worker static void SymbolizeSignalHandler(int signo) {
247*9356374aSAndroid Build Coastguard Worker   if (absl::Symbolize(g_pc_to_symbolize, g_symbolize_buffer,
248*9356374aSAndroid Build Coastguard Worker                       sizeof(g_symbolize_buffer))) {
249*9356374aSAndroid Build Coastguard Worker     g_symbolize_result = g_symbolize_buffer;
250*9356374aSAndroid Build Coastguard Worker   } else {
251*9356374aSAndroid Build Coastguard Worker     g_symbolize_result = nullptr;
252*9356374aSAndroid Build Coastguard Worker   }
253*9356374aSAndroid Build Coastguard Worker }
254*9356374aSAndroid Build Coastguard Worker 
255*9356374aSAndroid Build Coastguard Worker // Call Symbolize and figure out the stack footprint of this call.
SymbolizeStackConsumption(void * pc,int * stack_consumed)256*9356374aSAndroid Build Coastguard Worker static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) {
257*9356374aSAndroid Build Coastguard Worker   g_pc_to_symbolize = pc;
258*9356374aSAndroid Build Coastguard Worker   *stack_consumed = absl::debugging_internal::GetSignalHandlerStackConsumption(
259*9356374aSAndroid Build Coastguard Worker       SymbolizeSignalHandler);
260*9356374aSAndroid Build Coastguard Worker   return g_symbolize_result;
261*9356374aSAndroid Build Coastguard Worker }
262*9356374aSAndroid Build Coastguard Worker 
GetStackConsumptionUpperLimit()263*9356374aSAndroid Build Coastguard Worker static int GetStackConsumptionUpperLimit() {
264*9356374aSAndroid Build Coastguard Worker   // Symbolize stack consumption should be within 2kB.
265*9356374aSAndroid Build Coastguard Worker   int stack_consumption_upper_limit = 2048;
266*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
267*9356374aSAndroid Build Coastguard Worker     defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
268*9356374aSAndroid Build Coastguard Worker   // Account for sanitizer instrumentation requiring additional stack space.
269*9356374aSAndroid Build Coastguard Worker   stack_consumption_upper_limit *= 5;
270*9356374aSAndroid Build Coastguard Worker #endif
271*9356374aSAndroid Build Coastguard Worker   return stack_consumption_upper_limit;
272*9356374aSAndroid Build Coastguard Worker }
273*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,SymbolizeStackConsumption)274*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, SymbolizeStackConsumption) {
275*9356374aSAndroid Build Coastguard Worker   int stack_consumed = 0;
276*9356374aSAndroid Build Coastguard Worker 
277*9356374aSAndroid Build Coastguard Worker   const char *symbol =
278*9356374aSAndroid Build Coastguard Worker       SymbolizeStackConsumption((void *)(&nonstatic_func), &stack_consumed);
279*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic_func", symbol);
280*9356374aSAndroid Build Coastguard Worker   EXPECT_GT(stack_consumed, 0);
281*9356374aSAndroid Build Coastguard Worker   EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
282*9356374aSAndroid Build Coastguard Worker 
283*9356374aSAndroid Build Coastguard Worker   // The name of an internal linkage symbol is not specified; allow either a
284*9356374aSAndroid Build Coastguard Worker   // mangled or an unmangled name here.
285*9356374aSAndroid Build Coastguard Worker   symbol = SymbolizeStackConsumption((void *)(&static_func), &stack_consumed);
286*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(strcmp("static_func", symbol) == 0 ||
287*9356374aSAndroid Build Coastguard Worker               strcmp("static_func()", symbol) == 0);
288*9356374aSAndroid Build Coastguard Worker   EXPECT_GT(stack_consumed, 0);
289*9356374aSAndroid Build Coastguard Worker   EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
290*9356374aSAndroid Build Coastguard Worker }
291*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,SymbolizeWithDemanglingStackConsumption)292*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {
293*9356374aSAndroid Build Coastguard Worker   Foo::func(100);
294*9356374aSAndroid Build Coastguard Worker   int stack_consumed = 0;
295*9356374aSAndroid Build Coastguard Worker 
296*9356374aSAndroid Build Coastguard Worker   const char *symbol =
297*9356374aSAndroid Build Coastguard Worker       SymbolizeStackConsumption((void *)(&Foo::func), &stack_consumed);
298*9356374aSAndroid Build Coastguard Worker 
299*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("Foo::func()", symbol);
300*9356374aSAndroid Build Coastguard Worker   EXPECT_GT(stack_consumed, 0);
301*9356374aSAndroid Build Coastguard Worker   EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
302*9356374aSAndroid Build Coastguard Worker }
303*9356374aSAndroid Build Coastguard Worker 
304*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
305*9356374aSAndroid Build Coastguard Worker 
306*9356374aSAndroid Build Coastguard Worker #if !defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE) && \
307*9356374aSAndroid Build Coastguard Worker     !defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE)
308*9356374aSAndroid Build Coastguard Worker // Use a 64K page size for PPC.
309*9356374aSAndroid Build Coastguard Worker const size_t kPageSize = 64 << 10;
310*9356374aSAndroid Build Coastguard Worker // We place a read-only symbols into the .text section and verify that we can
311*9356374aSAndroid Build Coastguard Worker // symbolize them and other symbols after remapping them.
312*9356374aSAndroid Build Coastguard Worker const char kPadding0[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = "";
313*9356374aSAndroid Build Coastguard Worker const char kPadding1[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = "";
314*9356374aSAndroid Build Coastguard Worker 
FilterElfHeader(struct dl_phdr_info * info,size_t size,void * data)315*9356374aSAndroid Build Coastguard Worker static int FilterElfHeader(struct dl_phdr_info *info, size_t size, void *data) {
316*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i < info->dlpi_phnum; i++) {
317*9356374aSAndroid Build Coastguard Worker     if (info->dlpi_phdr[i].p_type == PT_LOAD &&
318*9356374aSAndroid Build Coastguard Worker         info->dlpi_phdr[i].p_flags == (PF_R | PF_X)) {
319*9356374aSAndroid Build Coastguard Worker       const void *const vaddr =
320*9356374aSAndroid Build Coastguard Worker           absl::bit_cast<void *>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
321*9356374aSAndroid Build Coastguard Worker       const auto segsize = info->dlpi_phdr[i].p_memsz;
322*9356374aSAndroid Build Coastguard Worker 
323*9356374aSAndroid Build Coastguard Worker       const char *self_exe;
324*9356374aSAndroid Build Coastguard Worker       if (info->dlpi_name != nullptr && info->dlpi_name[0] != '\0') {
325*9356374aSAndroid Build Coastguard Worker         self_exe = info->dlpi_name;
326*9356374aSAndroid Build Coastguard Worker       } else {
327*9356374aSAndroid Build Coastguard Worker         self_exe = "/proc/self/exe";
328*9356374aSAndroid Build Coastguard Worker       }
329*9356374aSAndroid Build Coastguard Worker 
330*9356374aSAndroid Build Coastguard Worker       absl::debugging_internal::RegisterFileMappingHint(
331*9356374aSAndroid Build Coastguard Worker           vaddr, reinterpret_cast<const char *>(vaddr) + segsize,
332*9356374aSAndroid Build Coastguard Worker           info->dlpi_phdr[i].p_offset, self_exe);
333*9356374aSAndroid Build Coastguard Worker 
334*9356374aSAndroid Build Coastguard Worker       return 1;
335*9356374aSAndroid Build Coastguard Worker     }
336*9356374aSAndroid Build Coastguard Worker   }
337*9356374aSAndroid Build Coastguard Worker 
338*9356374aSAndroid Build Coastguard Worker   return 1;
339*9356374aSAndroid Build Coastguard Worker }
340*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,SymbolizeWithMultipleMaps)341*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, SymbolizeWithMultipleMaps) {
342*9356374aSAndroid Build Coastguard Worker   // Force kPadding0 and kPadding1 to be linked in.
343*9356374aSAndroid Build Coastguard Worker   if (volatile_bool) {
344*9356374aSAndroid Build Coastguard Worker     LOG(INFO) << kPadding0;
345*9356374aSAndroid Build Coastguard Worker     LOG(INFO) << kPadding1;
346*9356374aSAndroid Build Coastguard Worker   }
347*9356374aSAndroid Build Coastguard Worker 
348*9356374aSAndroid Build Coastguard Worker   // Verify we can symbolize everything.
349*9356374aSAndroid Build Coastguard Worker   char buf[512];
350*9356374aSAndroid Build Coastguard Worker   memset(buf, 0, sizeof(buf));
351*9356374aSAndroid Build Coastguard Worker   absl::Symbolize(kPadding0, buf, sizeof(buf));
352*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("kPadding0", buf);
353*9356374aSAndroid Build Coastguard Worker 
354*9356374aSAndroid Build Coastguard Worker   memset(buf, 0, sizeof(buf));
355*9356374aSAndroid Build Coastguard Worker   absl::Symbolize(kPadding1, buf, sizeof(buf));
356*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("kPadding1", buf);
357*9356374aSAndroid Build Coastguard Worker 
358*9356374aSAndroid Build Coastguard Worker   // Specify a hint for the executable segment.
359*9356374aSAndroid Build Coastguard Worker   dl_iterate_phdr(FilterElfHeader, nullptr);
360*9356374aSAndroid Build Coastguard Worker 
361*9356374aSAndroid Build Coastguard Worker   // Reload at least one page out of kPadding0, kPadding1
362*9356374aSAndroid Build Coastguard Worker   const char *ptrs[] = {kPadding0, kPadding1};
363*9356374aSAndroid Build Coastguard Worker 
364*9356374aSAndroid Build Coastguard Worker   for (const char *ptr : ptrs) {
365*9356374aSAndroid Build Coastguard Worker     const int kMapFlags = MAP_ANONYMOUS | MAP_PRIVATE;
366*9356374aSAndroid Build Coastguard Worker     void *addr = mmap(nullptr, kPageSize, PROT_READ, kMapFlags, 0, 0);
367*9356374aSAndroid Build Coastguard Worker     ASSERT_NE(addr, MAP_FAILED);
368*9356374aSAndroid Build Coastguard Worker 
369*9356374aSAndroid Build Coastguard Worker     // kPadding[0-1] is full of zeroes, so we can remap anywhere within it, but
370*9356374aSAndroid Build Coastguard Worker     // we ensure there is at least a full page of padding.
371*9356374aSAndroid Build Coastguard Worker     void *remapped = reinterpret_cast<void *>(
372*9356374aSAndroid Build Coastguard Worker         reinterpret_cast<uintptr_t>(ptr + kPageSize) & ~(kPageSize - 1ULL));
373*9356374aSAndroid Build Coastguard Worker 
374*9356374aSAndroid Build Coastguard Worker     const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED);
375*9356374aSAndroid Build Coastguard Worker     void *ret = mremap(addr, kPageSize, kPageSize, kMremapFlags, remapped);
376*9356374aSAndroid Build Coastguard Worker     ASSERT_NE(ret, MAP_FAILED);
377*9356374aSAndroid Build Coastguard Worker   }
378*9356374aSAndroid Build Coastguard Worker 
379*9356374aSAndroid Build Coastguard Worker   // Invalidate the symbolization cache so we are forced to rely on the hint.
380*9356374aSAndroid Build Coastguard Worker   absl::Symbolize(nullptr, buf, sizeof(buf));
381*9356374aSAndroid Build Coastguard Worker 
382*9356374aSAndroid Build Coastguard Worker   // Verify we can still symbolize.
383*9356374aSAndroid Build Coastguard Worker   const char *expected[] = {"kPadding0", "kPadding1"};
384*9356374aSAndroid Build Coastguard Worker   const size_t offsets[] = {0, kPageSize, 2 * kPageSize, 3 * kPageSize};
385*9356374aSAndroid Build Coastguard Worker 
386*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i < 2; i++) {
387*9356374aSAndroid Build Coastguard Worker     for (size_t offset : offsets) {
388*9356374aSAndroid Build Coastguard Worker       memset(buf, 0, sizeof(buf));
389*9356374aSAndroid Build Coastguard Worker       absl::Symbolize(ptrs[i] + offset, buf, sizeof(buf));
390*9356374aSAndroid Build Coastguard Worker       EXPECT_STREQ(expected[i], buf);
391*9356374aSAndroid Build Coastguard Worker     }
392*9356374aSAndroid Build Coastguard Worker   }
393*9356374aSAndroid Build Coastguard Worker }
394*9356374aSAndroid Build Coastguard Worker 
395*9356374aSAndroid Build Coastguard Worker // Appends string(*args->arg) to args->symbol_buf.
DummySymbolDecorator(const absl::debugging_internal::SymbolDecoratorArgs * args)396*9356374aSAndroid Build Coastguard Worker static void DummySymbolDecorator(
397*9356374aSAndroid Build Coastguard Worker     const absl::debugging_internal::SymbolDecoratorArgs *args) {
398*9356374aSAndroid Build Coastguard Worker   std::string *message = static_cast<std::string *>(args->arg);
399*9356374aSAndroid Build Coastguard Worker   strncat(args->symbol_buf, message->c_str(),
400*9356374aSAndroid Build Coastguard Worker           args->symbol_buf_size - strlen(args->symbol_buf) - 1);
401*9356374aSAndroid Build Coastguard Worker }
402*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,InstallAndRemoveSymbolDecorators)403*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, InstallAndRemoveSymbolDecorators) {
404*9356374aSAndroid Build Coastguard Worker   int ticket_a;
405*9356374aSAndroid Build Coastguard Worker   std::string a_message("a");
406*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(ticket_a = absl::debugging_internal::InstallSymbolDecorator(
407*9356374aSAndroid Build Coastguard Worker                 DummySymbolDecorator, &a_message),
408*9356374aSAndroid Build Coastguard Worker             0);
409*9356374aSAndroid Build Coastguard Worker 
410*9356374aSAndroid Build Coastguard Worker   int ticket_b;
411*9356374aSAndroid Build Coastguard Worker   std::string b_message("b");
412*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(ticket_b = absl::debugging_internal::InstallSymbolDecorator(
413*9356374aSAndroid Build Coastguard Worker                 DummySymbolDecorator, &b_message),
414*9356374aSAndroid Build Coastguard Worker             0);
415*9356374aSAndroid Build Coastguard Worker 
416*9356374aSAndroid Build Coastguard Worker   int ticket_c;
417*9356374aSAndroid Build Coastguard Worker   std::string c_message("c");
418*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(ticket_c = absl::debugging_internal::InstallSymbolDecorator(
419*9356374aSAndroid Build Coastguard Worker                 DummySymbolDecorator, &c_message),
420*9356374aSAndroid Build Coastguard Worker             0);
421*9356374aSAndroid Build Coastguard Worker 
422*9356374aSAndroid Build Coastguard Worker   // Use addresses 4 and 8 here to ensure that we always use valid addresses
423*9356374aSAndroid Build Coastguard Worker   // even on systems that require instructions to be 32-bit aligned.
424*9356374aSAndroid Build Coastguard Worker   char *address = reinterpret_cast<char *>(4);
425*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("abc", TrySymbolize(address));
426*9356374aSAndroid Build Coastguard Worker 
427*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_b));
428*9356374aSAndroid Build Coastguard Worker 
429*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("ac", TrySymbolize(address + 4));
430*9356374aSAndroid Build Coastguard Worker 
431*9356374aSAndroid Build Coastguard Worker   // Cleanup: remove all remaining decorators so other stack traces don't
432*9356374aSAndroid Build Coastguard Worker   // get mystery "ac" decoration.
433*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_a));
434*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_c));
435*9356374aSAndroid Build Coastguard Worker }
436*9356374aSAndroid Build Coastguard Worker 
437*9356374aSAndroid Build Coastguard Worker // Some versions of Clang with optimizations enabled seem to be able
438*9356374aSAndroid Build Coastguard Worker // to optimize away the .data section if no variables live in the
439*9356374aSAndroid Build Coastguard Worker // section. This variable should get placed in the .data section, and
440*9356374aSAndroid Build Coastguard Worker // the test below checks for the existence of a .data section.
441*9356374aSAndroid Build Coastguard Worker static int in_data_section = 1;
442*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,ForEachSection)443*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, ForEachSection) {
444*9356374aSAndroid Build Coastguard Worker   int fd = TEMP_FAILURE_RETRY(open("/proc/self/exe", O_RDONLY));
445*9356374aSAndroid Build Coastguard Worker   ASSERT_NE(fd, -1);
446*9356374aSAndroid Build Coastguard Worker 
447*9356374aSAndroid Build Coastguard Worker   std::vector<std::string> sections;
448*9356374aSAndroid Build Coastguard Worker   ASSERT_TRUE(absl::debugging_internal::ForEachSection(
449*9356374aSAndroid Build Coastguard Worker       fd, [&sections](const absl::string_view name, const ElfW(Shdr) &) {
450*9356374aSAndroid Build Coastguard Worker         sections.emplace_back(name);
451*9356374aSAndroid Build Coastguard Worker         return true;
452*9356374aSAndroid Build Coastguard Worker       }));
453*9356374aSAndroid Build Coastguard Worker 
454*9356374aSAndroid Build Coastguard Worker   // Check for the presence of common section names.
455*9356374aSAndroid Build Coastguard Worker   EXPECT_THAT(sections, Contains(".text"));
456*9356374aSAndroid Build Coastguard Worker   EXPECT_THAT(sections, Contains(".rodata"));
457*9356374aSAndroid Build Coastguard Worker   EXPECT_THAT(sections, Contains(".bss"));
458*9356374aSAndroid Build Coastguard Worker   ++in_data_section;
459*9356374aSAndroid Build Coastguard Worker   EXPECT_THAT(sections, Contains(".data"));
460*9356374aSAndroid Build Coastguard Worker 
461*9356374aSAndroid Build Coastguard Worker   close(fd);
462*9356374aSAndroid Build Coastguard Worker }
463*9356374aSAndroid Build Coastguard Worker #endif  // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE &&
464*9356374aSAndroid Build Coastguard Worker         // !ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE
465*9356374aSAndroid Build Coastguard Worker 
466*9356374aSAndroid Build Coastguard Worker // x86 specific tests.  Uses some inline assembler.
467*9356374aSAndroid Build Coastguard Worker extern "C" {
inline_func()468*9356374aSAndroid Build Coastguard Worker inline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() {
469*9356374aSAndroid Build Coastguard Worker   void *pc = nullptr;
470*9356374aSAndroid Build Coastguard Worker #if defined(__i386__)
471*9356374aSAndroid Build Coastguard Worker   __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [PC] "=r"(pc));
472*9356374aSAndroid Build Coastguard Worker #elif defined(__x86_64__)
473*9356374aSAndroid Build Coastguard Worker   __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [PC] "=r"(pc));
474*9356374aSAndroid Build Coastguard Worker #endif
475*9356374aSAndroid Build Coastguard Worker   return pc;
476*9356374aSAndroid Build Coastguard Worker }
477*9356374aSAndroid Build Coastguard Worker 
non_inline_func()478*9356374aSAndroid Build Coastguard Worker void *ABSL_ATTRIBUTE_NOINLINE non_inline_func() {
479*9356374aSAndroid Build Coastguard Worker   void *pc = nullptr;
480*9356374aSAndroid Build Coastguard Worker #if defined(__i386__)
481*9356374aSAndroid Build Coastguard Worker   __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [PC] "=r"(pc));
482*9356374aSAndroid Build Coastguard Worker #elif defined(__x86_64__)
483*9356374aSAndroid Build Coastguard Worker   __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [PC] "=r"(pc));
484*9356374aSAndroid Build Coastguard Worker #endif
485*9356374aSAndroid Build Coastguard Worker   return pc;
486*9356374aSAndroid Build Coastguard Worker }
487*9356374aSAndroid Build Coastguard Worker 
TestWithPCInsideNonInlineFunction()488*9356374aSAndroid Build Coastguard Worker void ABSL_ATTRIBUTE_NOINLINE TestWithPCInsideNonInlineFunction() {
489*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE) && \
490*9356374aSAndroid Build Coastguard Worker     (defined(__i386__) || defined(__x86_64__))
491*9356374aSAndroid Build Coastguard Worker   void *pc = non_inline_func();
492*9356374aSAndroid Build Coastguard Worker   const char *symbol = TrySymbolize(pc);
493*9356374aSAndroid Build Coastguard Worker   CHECK_NE(symbol, nullptr) << "TestWithPCInsideNonInlineFunction failed";
494*9356374aSAndroid Build Coastguard Worker   CHECK_STREQ(symbol, "non_inline_func")
495*9356374aSAndroid Build Coastguard Worker       << "TestWithPCInsideNonInlineFunction failed";
496*9356374aSAndroid Build Coastguard Worker   std::cout << "TestWithPCInsideNonInlineFunction passed" << std::endl;
497*9356374aSAndroid Build Coastguard Worker #endif
498*9356374aSAndroid Build Coastguard Worker }
499*9356374aSAndroid Build Coastguard Worker 
TestWithPCInsideInlineFunction()500*9356374aSAndroid Build Coastguard Worker void ABSL_ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() {
501*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE) && \
502*9356374aSAndroid Build Coastguard Worker     (defined(__i386__) || defined(__x86_64__))
503*9356374aSAndroid Build Coastguard Worker   void *pc = inline_func();  // Must be inlined.
504*9356374aSAndroid Build Coastguard Worker   const char *symbol = TrySymbolize(pc);
505*9356374aSAndroid Build Coastguard Worker   CHECK_NE(symbol, nullptr) << "TestWithPCInsideInlineFunction failed";
506*9356374aSAndroid Build Coastguard Worker   CHECK_STREQ(symbol, __FUNCTION__) << "TestWithPCInsideInlineFunction failed";
507*9356374aSAndroid Build Coastguard Worker   std::cout << "TestWithPCInsideInlineFunction passed" << std::endl;
508*9356374aSAndroid Build Coastguard Worker #endif
509*9356374aSAndroid Build Coastguard Worker }
510*9356374aSAndroid Build Coastguard Worker }
511*9356374aSAndroid Build Coastguard Worker 
512*9356374aSAndroid Build Coastguard Worker #if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && \
513*9356374aSAndroid Build Coastguard Worker     ((__ARM_ARCH >= 7) || !defined(__ARM_PCS_VFP))
514*9356374aSAndroid Build Coastguard Worker // Test that we correctly identify bounds of Thumb functions on ARM.
515*9356374aSAndroid Build Coastguard Worker //
516*9356374aSAndroid Build Coastguard Worker // Thumb functions have the lowest-order bit set in their addresses in the ELF
517*9356374aSAndroid Build Coastguard Worker // symbol table. This requires some extra logic to properly compute function
518*9356374aSAndroid Build Coastguard Worker // bounds. To test this logic, nudge a Thumb function right up against an ARM
519*9356374aSAndroid Build Coastguard Worker // function and try to symbolize the ARM function.
520*9356374aSAndroid Build Coastguard Worker //
521*9356374aSAndroid Build Coastguard Worker // A naive implementation will simply use the Thumb function's entry point as
522*9356374aSAndroid Build Coastguard Worker // written in the symbol table and will therefore treat the Thumb function as
523*9356374aSAndroid Build Coastguard Worker // extending one byte further in the instruction stream than it actually does.
524*9356374aSAndroid Build Coastguard Worker // When asked to symbolize the start of the ARM function, it will identify an
525*9356374aSAndroid Build Coastguard Worker // overlap between the Thumb and ARM functions, and it will return the name of
526*9356374aSAndroid Build Coastguard Worker // the Thumb function.
527*9356374aSAndroid Build Coastguard Worker //
528*9356374aSAndroid Build Coastguard Worker // A correct implementation, on the other hand, will null out the lowest-order
529*9356374aSAndroid Build Coastguard Worker // bit in the Thumb function's entry point. It will correctly compute the end of
530*9356374aSAndroid Build Coastguard Worker // the Thumb function, it will find no overlap between the Thumb and ARM
531*9356374aSAndroid Build Coastguard Worker // functions, and it will return the name of the ARM function.
532*9356374aSAndroid Build Coastguard Worker //
533*9356374aSAndroid Build Coastguard Worker // Unfortunately we cannot perform this test on armv6 or lower systems that use
534*9356374aSAndroid Build Coastguard Worker // the hard float ABI because gcc refuses to compile thumb functions on such
535*9356374aSAndroid Build Coastguard Worker // systems with a "sorry, unimplemented: Thumb-1 hard-float VFP ABI" error.
536*9356374aSAndroid Build Coastguard Worker 
ArmThumbOverlapThumb(int x)537*9356374aSAndroid Build Coastguard Worker __attribute__((target("thumb"))) int ArmThumbOverlapThumb(int x) {
538*9356374aSAndroid Build Coastguard Worker   return x * x * x;
539*9356374aSAndroid Build Coastguard Worker }
540*9356374aSAndroid Build Coastguard Worker 
ArmThumbOverlapArm(int x)541*9356374aSAndroid Build Coastguard Worker __attribute__((target("arm"))) int ArmThumbOverlapArm(int x) {
542*9356374aSAndroid Build Coastguard Worker   return x * x * x;
543*9356374aSAndroid Build Coastguard Worker }
544*9356374aSAndroid Build Coastguard Worker 
TestArmThumbOverlap()545*9356374aSAndroid Build Coastguard Worker void ABSL_ATTRIBUTE_NOINLINE TestArmThumbOverlap() {
546*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
547*9356374aSAndroid Build Coastguard Worker   const char *symbol = TrySymbolize((void *)&ArmThumbOverlapArm);
548*9356374aSAndroid Build Coastguard Worker   CHECK_NE(symbol, nullptr) << "TestArmThumbOverlap failed";
549*9356374aSAndroid Build Coastguard Worker   CHECK_STREQ("ArmThumbOverlapArm()", symbol) << "TestArmThumbOverlap failed";
550*9356374aSAndroid Build Coastguard Worker   std::cout << "TestArmThumbOverlap passed" << std::endl;
551*9356374aSAndroid Build Coastguard Worker #endif
552*9356374aSAndroid Build Coastguard Worker }
553*9356374aSAndroid Build Coastguard Worker 
554*9356374aSAndroid Build Coastguard Worker #endif  // defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && ((__ARM_ARCH >= 7)
555*9356374aSAndroid Build Coastguard Worker         // || !defined(__ARM_PCS_VFP))
556*9356374aSAndroid Build Coastguard Worker 
557*9356374aSAndroid Build Coastguard Worker #elif defined(_WIN32)
558*9356374aSAndroid Build Coastguard Worker #if !defined(ABSL_CONSUME_DLL)
559*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,Basics)560*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, Basics) {
561*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func)));
562*9356374aSAndroid Build Coastguard Worker 
563*9356374aSAndroid Build Coastguard Worker   // The name of an internal linkage symbol is not specified; allow either a
564*9356374aSAndroid Build Coastguard Worker   // mangled or an unmangled name here.
565*9356374aSAndroid Build Coastguard Worker   const char *static_func_symbol = TrySymbolize((void *)(&static_func));
566*9356374aSAndroid Build Coastguard Worker   ASSERT_TRUE(static_func_symbol != nullptr);
567*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(strstr(static_func_symbol, "static_func") != nullptr);
568*9356374aSAndroid Build Coastguard Worker 
569*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(nullptr == TrySymbolize(nullptr));
570*9356374aSAndroid Build Coastguard Worker }
571*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,Truncation)572*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, Truncation) {
573*9356374aSAndroid Build Coastguard Worker   constexpr char kNonStaticFunc[] = "nonstatic_func";
574*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic_func",
575*9356374aSAndroid Build Coastguard Worker                TrySymbolizeWithLimit((void *)(&nonstatic_func),
576*9356374aSAndroid Build Coastguard Worker                                      strlen(kNonStaticFunc) + 1));
577*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic_...",
578*9356374aSAndroid Build Coastguard Worker                TrySymbolizeWithLimit((void *)(&nonstatic_func),
579*9356374aSAndroid Build Coastguard Worker                                      strlen(kNonStaticFunc) + 0));
580*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("nonstatic...",
581*9356374aSAndroid Build Coastguard Worker                TrySymbolizeWithLimit((void *)(&nonstatic_func),
582*9356374aSAndroid Build Coastguard Worker                                      strlen(kNonStaticFunc) - 1));
583*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("n...", TrySymbolizeWithLimit((void *)(&nonstatic_func), 5));
584*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("...", TrySymbolizeWithLimit((void *)(&nonstatic_func), 4));
585*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("..", TrySymbolizeWithLimit((void *)(&nonstatic_func), 3));
586*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ(".", TrySymbolizeWithLimit((void *)(&nonstatic_func), 2));
587*9356374aSAndroid Build Coastguard Worker   EXPECT_STREQ("", TrySymbolizeWithLimit((void *)(&nonstatic_func), 1));
588*9356374aSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, TrySymbolizeWithLimit((void *)(&nonstatic_func), 0));
589*9356374aSAndroid Build Coastguard Worker }
590*9356374aSAndroid Build Coastguard Worker 
TEST(Symbolize,SymbolizeWithDemangling)591*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, SymbolizeWithDemangling) {
592*9356374aSAndroid Build Coastguard Worker   const char *result = TrySymbolize((void *)(&Foo::func));
593*9356374aSAndroid Build Coastguard Worker   ASSERT_TRUE(result != nullptr);
594*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(strstr(result, "Foo::func") != nullptr) << result;
595*9356374aSAndroid Build Coastguard Worker }
596*9356374aSAndroid Build Coastguard Worker 
597*9356374aSAndroid Build Coastguard Worker #endif  // !defined(ABSL_CONSUME_DLL)
598*9356374aSAndroid Build Coastguard Worker #else   // Symbolizer unimplemented
TEST(Symbolize,Unimplemented)599*9356374aSAndroid Build Coastguard Worker TEST(Symbolize, Unimplemented) {
600*9356374aSAndroid Build Coastguard Worker   char buf[64];
601*9356374aSAndroid Build Coastguard Worker   EXPECT_FALSE(absl::Symbolize((void *)(&nonstatic_func), buf, sizeof(buf)));
602*9356374aSAndroid Build Coastguard Worker   EXPECT_FALSE(absl::Symbolize((void *)(&static_func), buf, sizeof(buf)));
603*9356374aSAndroid Build Coastguard Worker   EXPECT_FALSE(absl::Symbolize((void *)(&Foo::func), buf, sizeof(buf)));
604*9356374aSAndroid Build Coastguard Worker }
605*9356374aSAndroid Build Coastguard Worker 
606*9356374aSAndroid Build Coastguard Worker #endif
607*9356374aSAndroid Build Coastguard Worker 
main(int argc,char ** argv)608*9356374aSAndroid Build Coastguard Worker int main(int argc, char **argv) {
609*9356374aSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
610*9356374aSAndroid Build Coastguard Worker   // Make sure kHpageTextPadding is linked into the binary.
611*9356374aSAndroid Build Coastguard Worker   if (volatile_bool) {
612*9356374aSAndroid Build Coastguard Worker     LOG(INFO) << kHpageTextPadding;
613*9356374aSAndroid Build Coastguard Worker   }
614*9356374aSAndroid Build Coastguard Worker #endif  // !defined(__EMSCRIPTEN__)
615*9356374aSAndroid Build Coastguard Worker 
616*9356374aSAndroid Build Coastguard Worker #if ABSL_PER_THREAD_TLS
617*9356374aSAndroid Build Coastguard Worker   // Touch the per-thread variables.
618*9356374aSAndroid Build Coastguard Worker   symbolize_test_thread_small[0] = 0;
619*9356374aSAndroid Build Coastguard Worker   symbolize_test_thread_big[0] = 0;
620*9356374aSAndroid Build Coastguard Worker #endif
621*9356374aSAndroid Build Coastguard Worker 
622*9356374aSAndroid Build Coastguard Worker   absl::InitializeSymbolizer(argv[0]);
623*9356374aSAndroid Build Coastguard Worker   testing::InitGoogleTest(&argc, argv);
624*9356374aSAndroid Build Coastguard Worker 
625*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) ||        \
626*9356374aSAndroid Build Coastguard Worker     defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE) || \
627*9356374aSAndroid Build Coastguard Worker     defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
628*9356374aSAndroid Build Coastguard Worker   TestWithPCInsideInlineFunction();
629*9356374aSAndroid Build Coastguard Worker   TestWithPCInsideNonInlineFunction();
630*9356374aSAndroid Build Coastguard Worker   TestWithReturnAddress();
631*9356374aSAndroid Build Coastguard Worker #if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && \
632*9356374aSAndroid Build Coastguard Worker     ((__ARM_ARCH >= 7) || !defined(__ARM_PCS_VFP))
633*9356374aSAndroid Build Coastguard Worker   TestArmThumbOverlap();
634*9356374aSAndroid Build Coastguard Worker #endif
635*9356374aSAndroid Build Coastguard Worker #endif
636*9356374aSAndroid Build Coastguard Worker 
637*9356374aSAndroid Build Coastguard Worker   return RUN_ALL_TESTS();
638*9356374aSAndroid Build Coastguard Worker }
639