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) || \
151 defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE)
155 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
156 void *return_address = __builtin_return_address(0);
158 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithReturnAddress failed");
159 ABSL_RAW_CHECK(strcmp(symbol,
"main") == 0,
"TestWithReturnAddress failed");
160 std::cout <<
"TestWithReturnAddress passed" << std::endl;
164 #ifndef ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE
173 EXPECT_TRUE(strcmp(
"static_func", static_func_symbol) == 0 ||
174 strcmp(
"static_func()", static_func_symbol) == 0);
180 constexpr
char kNonStaticFunc[] =
"nonstatic_func";
183 strlen(kNonStaticFunc) + 1));
186 strlen(kNonStaticFunc) + 0));
189 strlen(kNonStaticFunc) - 1));
212 #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
214 static void *g_pc_to_symbolize;
215 static char g_symbolize_buffer[4096];
216 static char *g_symbolize_result;
218 static void SymbolizeSignalHandler(
int signo) {
220 sizeof(g_symbolize_buffer))) {
221 g_symbolize_result = g_symbolize_buffer;
223 g_symbolize_result =
nullptr;
228 static const char *SymbolizeStackConsumption(
void *pc,
int *stack_consumed) {
229 g_pc_to_symbolize = pc;
230 *stack_consumed = absl::debugging_internal::GetSignalHandlerStackConsumption(
231 SymbolizeSignalHandler);
232 return g_symbolize_result;
235 static int GetStackConsumptionUpperLimit() {
237 int stack_consumption_upper_limit = 2048;
238 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
239 defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
241 stack_consumption_upper_limit *= 5;
243 return stack_consumption_upper_limit;
247 int stack_consumed = 0;
250 SymbolizeStackConsumption((
void *)(&
nonstatic_func), &stack_consumed);
253 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
257 symbol = SymbolizeStackConsumption((
void *)(&
static_func), &stack_consumed);
259 strcmp(
"static_func()", symbol) == 0);
261 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
266 int stack_consumed = 0;
269 SymbolizeStackConsumption((
void *)(&
Foo::func), &stack_consumed);
273 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
276 #endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
278 #ifndef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
280 const size_t kPageSize = 64 << 10;
288 static int FilterElfHeader(
struct dl_phdr_info *info,
size_t size,
void *
data) {
289 for (
int i = 0;
i < info->dlpi_phnum;
i++) {
290 if (info->dlpi_phdr[
i].p_type ==
PT_LOAD &&
291 info->dlpi_phdr[
i].p_flags == (
PF_R |
PF_X)) {
292 const void *
const vaddr =
293 absl::bit_cast<void *>(info->dlpi_addr + info->dlpi_phdr[
i].p_vaddr);
294 const auto segsize = info->dlpi_phdr[
i].p_memsz;
296 const char *self_exe;
297 if (info->dlpi_name !=
nullptr && info->dlpi_name[0] !=
'\0') {
298 self_exe = info->dlpi_name;
300 self_exe =
"/proc/self/exe";
303 absl::debugging_internal::RegisterFileMappingHint(
304 vaddr,
reinterpret_cast<const char *
>(vaddr) + segsize,
305 info->dlpi_phdr[
i].p_offset, self_exe);
332 dl_iterate_phdr(FilterElfHeader,
nullptr);
335 const char *ptrs[] = {kPadding0, kPadding1};
337 for (
const char *
ptr : ptrs) {
338 const int kMapFlags = MAP_ANONYMOUS | MAP_PRIVATE;
339 void *
addr = mmap(
nullptr, kPageSize, PROT_READ, kMapFlags, 0, 0);
344 void *remapped =
reinterpret_cast<void *
>(
347 const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED);
348 void *
ret = mremap(
addr, kPageSize, kPageSize, kMremapFlags, remapped);
356 const char *expected[] = {
"kPadding0",
"kPadding1"};
357 const size_t offsets[] = {0, kPageSize, 2 * kPageSize, 3 * kPageSize};
359 for (
int i = 0;
i < 2;
i++) {
360 for (
size_t offset : offsets) {
369 static void DummySymbolDecorator(
370 const absl::debugging_internal::SymbolDecoratorArgs *
args) {
373 args->symbol_buf_size - strlen(
args->symbol_buf) - 1);
379 EXPECT_GE(ticket_a = absl::debugging_internal::InstallSymbolDecorator(
380 DummySymbolDecorator, &a_message),
385 EXPECT_GE(ticket_b = absl::debugging_internal::InstallSymbolDecorator(
386 DummySymbolDecorator, &b_message),
391 EXPECT_GE(ticket_c = absl::debugging_internal::InstallSymbolDecorator(
392 DummySymbolDecorator, &c_message),
397 char *address =
reinterpret_cast<char *
>(4);
400 EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_b));
406 EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_a));
407 EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_c));
414 static int in_data_section = 1;
417 int fd = TEMP_FAILURE_RETRY(
open(
"/proc/self/exe", O_RDONLY));
436 #endif // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
437 #endif // !ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE
443 #if defined(__i386__)
444 __asm__ __volatile__(
"call 1f;\n 1: pop %[PC]" : [ PC ]
"=r"(pc));
445 #elif defined(__x86_64__)
446 __asm__ __volatile__(
"leaq 0(%%rip),%[PC];\n" : [ PC ]
"=r"(pc));
453 #if defined(__i386__)
454 __asm__ __volatile__(
"call 1f;\n 1: pop %[PC]" : [ PC ]
"=r"(pc));
455 #elif defined(__x86_64__)
456 __asm__ __volatile__(
"leaq 0(%%rip),%[PC];\n" : [ PC ]
"=r"(pc));
462 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE) && \
463 (defined(__i386__) || defined(__x86_64__))
464 void *pc = non_inline_func();
466 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithPCInsideNonInlineFunction failed");
468 "TestWithPCInsideNonInlineFunction failed");
469 std::cout <<
"TestWithPCInsideNonInlineFunction passed" << std::endl;
474 #if defined(ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE) && \
475 (defined(__i386__) || defined(__x86_64__))
476 void *pc = inline_func();
478 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithPCInsideInlineFunction failed");
480 "TestWithPCInsideInlineFunction failed");
481 std::cout <<
"TestWithPCInsideInlineFunction passed" << std::endl;
486 #if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && \
487 ((__ARM_ARCH >= 7) || !defined(__ARM_PCS_VFP))
520 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
521 const char *symbol =
TrySymbolize((
void *)&ArmThumbOverlapArm);
524 "TestArmThumbOverlap failed");
525 std::cout <<
"TestArmThumbOverlap passed" << std::endl;
529 #endif // defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && ((__ARM_ARCH >= 7)
532 #elif defined(_WIN32)
533 #if !defined(ABSL_CONSUME_DLL)
542 EXPECT_TRUE(strstr(static_func_symbol,
"static_func") !=
nullptr);
548 constexpr
char kNonStaticFunc[] =
"nonstatic_func";
551 strlen(kNonStaticFunc) + 1));
554 strlen(kNonStaticFunc) + 0));
557 strlen(kNonStaticFunc) - 1));
572 #endif // !defined(ABSL_CONSUME_DLL)
573 #else // Symbolizer unimplemented
583 int main(
int argc,
char **argv) {
584 #if !defined(__EMSCRIPTEN__)
589 #endif // !defined(__EMSCRIPTEN__)
591 #if ABSL_PER_THREAD_TLS
593 symbolize_test_thread_small[0] = 0;
594 symbolize_test_thread_big[0] = 0;
600 #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
601 defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
602 TestWithPCInsideInlineFunction();
603 TestWithPCInsideNonInlineFunction();
604 TestWithReturnAddress();
605 #if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target) && \
606 ((__ARM_ARCH >= 7) || !defined(__ARM_PCS_VFP))
607 TestArmThumbOverlap();