15 #include "absl/debugging/symbolize.h"
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include "absl/base/attributes.h"
29 #include "absl/base/casts.h"
30 #include "absl/base/config.h"
31 #include "absl/base/internal/per_thread_tls.h"
32 #include "absl/base/internal/raw_logging.h"
33 #include "absl/base/optimization.h"
34 #include "absl/debugging/internal/stack_consumption.h"
35 #include "absl/memory/memory.h"
36 #include "absl/strings/string_view.h"
41 #define ABSL_SYMBOLIZE_TEST_NOINLINE __declspec(noinline)
43 #define ABSL_SYMBOLIZE_TEST_NOINLINE ABSL_ATTRIBUTE_NOINLINE
51 volatile int x = __LINE__;
59 volatile int x = __LINE__;
66 static void func(
int x);
73 volatile int x = __LINE__;
102 #if ABSL_PER_THREAD_TLS
105 symbolize_test_thread_big[2 * 1024 * 1024];
108 #if !defined(__EMSCRIPTEN__)
118 #endif // !defined(__EMSCRIPTEN__)
128 "try_symbolize_buffer is too small");
135 "absl::Symbolize() did not properly terminate the string");
149 #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
150 defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
159 EXPECT_TRUE(strcmp(
"static_func", static_func_symbol) == 0 ||
160 strcmp(
"static_func()", static_func_symbol) == 0);
166 constexpr
char kNonStaticFunc[] =
"nonstatic_func";
169 strlen(kNonStaticFunc) + 1));
172 strlen(kNonStaticFunc) + 0));
175 strlen(kNonStaticFunc) - 1));
198 #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
200 static void *g_pc_to_symbolize;
201 static char g_symbolize_buffer[4096];
202 static char *g_symbolize_result;
204 static void SymbolizeSignalHandler(
int signo) {
206 sizeof(g_symbolize_buffer))) {
207 g_symbolize_result = g_symbolize_buffer;
209 g_symbolize_result =
nullptr;
214 static const char *SymbolizeStackConsumption(
void *pc,
int *stack_consumed) {
215 g_pc_to_symbolize = pc;
216 *stack_consumed = absl::debugging_internal::GetSignalHandlerStackConsumption(
217 SymbolizeSignalHandler);
218 return g_symbolize_result;
221 static int GetStackConsumptionUpperLimit() {
223 int stack_consumption_upper_limit = 2048;
224 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
225 defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
227 stack_consumption_upper_limit *= 5;
229 return stack_consumption_upper_limit;
233 int stack_consumed = 0;
236 SymbolizeStackConsumption((
void *)(&
nonstatic_func), &stack_consumed);
239 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
243 symbol = SymbolizeStackConsumption((
void *)(&
static_func), &stack_consumed);
245 strcmp(
"static_func()", symbol) == 0);
247 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
252 int stack_consumed = 0;
255 SymbolizeStackConsumption((
void *)(&
Foo::func), &stack_consumed);
259 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
262 #endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
264 #ifndef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
266 const size_t kPageSize = 64 << 10;
274 static int FilterElfHeader(
struct dl_phdr_info *info,
size_t size,
void *
data) {
275 for (
int i = 0;
i < info->dlpi_phnum;
i++) {
276 if (info->dlpi_phdr[
i].p_type ==
PT_LOAD &&
277 info->dlpi_phdr[
i].p_flags == (
PF_R |
PF_X)) {
278 const void *
const vaddr =
279 absl::bit_cast<void *>(info->dlpi_addr + info->dlpi_phdr[
i].p_vaddr);
280 const auto segsize = info->dlpi_phdr[
i].p_memsz;
282 const char *self_exe;
283 if (info->dlpi_name !=
nullptr && info->dlpi_name[0] !=
'\0') {
284 self_exe = info->dlpi_name;
286 self_exe =
"/proc/self/exe";
289 absl::debugging_internal::RegisterFileMappingHint(
290 vaddr,
reinterpret_cast<const char *
>(vaddr) + segsize,
291 info->dlpi_phdr[
i].p_offset, self_exe);
318 dl_iterate_phdr(FilterElfHeader,
nullptr);
321 const char *ptrs[] = {kPadding0, kPadding1};
323 for (
const char *
ptr : ptrs) {
324 const int kMapFlags = MAP_ANONYMOUS | MAP_PRIVATE;
325 void *
addr = mmap(
nullptr, kPageSize, PROT_READ, kMapFlags, 0, 0);
330 void *remapped =
reinterpret_cast<void *
>(
333 const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED);
334 void *
ret = mremap(
addr, kPageSize, kPageSize, kMremapFlags, remapped);
342 const char *expected[] = {
"kPadding0",
"kPadding1"};
343 const size_t offsets[] = {0, kPageSize, 2 * kPageSize, 3 * kPageSize};
345 for (
int i = 0;
i < 2;
i++) {
346 for (
size_t offset : offsets) {
355 static void DummySymbolDecorator(
356 const absl::debugging_internal::SymbolDecoratorArgs *
args) {
359 args->symbol_buf_size - strlen(
args->symbol_buf) - 1);
365 EXPECT_GE(ticket_a = absl::debugging_internal::InstallSymbolDecorator(
366 DummySymbolDecorator, &a_message),
371 EXPECT_GE(ticket_b = absl::debugging_internal::InstallSymbolDecorator(
372 DummySymbolDecorator, &b_message),
377 EXPECT_GE(ticket_c = absl::debugging_internal::InstallSymbolDecorator(
378 DummySymbolDecorator, &c_message),
381 char *address =
reinterpret_cast<char *
>(1);
384 EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_b));
390 EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_a));
391 EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_c));
398 static int in_data_section = 1;
401 int fd = TEMP_FAILURE_RETRY(
open(
"/proc/self/exe", O_RDONLY));
420 #endif // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
426 #if defined(__i386__)
427 __asm__ __volatile__(
"call 1f;\n 1: pop %[PC]" : [ PC ]
"=r"(pc));
428 #elif defined(__x86_64__)
429 __asm__ __volatile__(
"leaq 0(%%rip),%[PC];\n" : [ PC ]
"=r"(pc));
436 #if defined(__i386__)
437 __asm__ __volatile__(
"call 1f;\n 1: pop %[PC]" : [ PC ]
"=r"(pc));
438 #elif defined(__x86_64__)
439 __asm__ __volatile__(
"leaq 0(%%rip),%[PC];\n" : [ PC ]
"=r"(pc));
445 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE) && \
446 (defined(__i386__) || defined(__x86_64__))
447 void *pc = non_inline_func();
449 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithPCInsideNonInlineFunction failed");
451 "TestWithPCInsideNonInlineFunction failed");
452 std::cout <<
"TestWithPCInsideNonInlineFunction passed" << std::endl;
457 #if defined(ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE) && \
458 (defined(__i386__) || defined(__x86_64__))
459 void *pc = inline_func();
461 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithPCInsideInlineFunction failed");
463 "TestWithPCInsideInlineFunction failed");
464 std::cout <<
"TestWithPCInsideInlineFunction passed" << std::endl;
471 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
472 void *return_address = __builtin_return_address(0);
474 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithReturnAddress failed");
475 ABSL_RAW_CHECK(strcmp(symbol,
"main") == 0,
"TestWithReturnAddress failed");
476 std::cout <<
"TestWithReturnAddress passed" << std::endl;
480 #if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target)
509 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
510 const char *symbol =
TrySymbolize((
void *)&ArmThumbOverlapArm);
513 "TestArmThumbOverlap failed");
514 std::cout <<
"TestArmThumbOverlap passed" << std::endl;
518 #endif // defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target)
520 #elif defined(_WIN32)
521 #if !defined(ABSL_CONSUME_DLL)
530 EXPECT_TRUE(strstr(static_func_symbol,
"static_func") !=
nullptr);
536 constexpr
char kNonStaticFunc[] =
"nonstatic_func";
539 strlen(kNonStaticFunc) + 1));
542 strlen(kNonStaticFunc) + 0));
545 strlen(kNonStaticFunc) - 1));
560 #endif // !defined(ABSL_CONSUME_DLL)
561 #else // Symbolizer unimplemented
572 int main(
int argc,
char **argv) {
573 #if !defined(__EMSCRIPTEN__)
578 #endif // !defined(__EMSCRIPTEN__)
580 #if ABSL_PER_THREAD_TLS
582 symbolize_test_thread_small[0] = 0;
583 symbolize_test_thread_big[0] = 0;
589 #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
590 defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
591 TestWithPCInsideInlineFunction();
592 TestWithPCInsideNonInlineFunction();
593 TestWithReturnAddress();
594 #if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target)
595 TestArmThumbOverlap();