26 #include "gmock/gmock.h" 27 #include "gtest/gtest.h" 45 static void func(
int x);
77 #if ABSL_PER_THREAD_TLS 80 symbolize_test_thread_big[2 * 1024 * 1024];
101 "try_symbolize_buffer is too small");
108 "absl::Symbolize() did not properly terminate the string");
121 #ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE 130 EXPECT_TRUE(strcmp(
"static_func", static_func_symbol) == 0 ||
131 strcmp(
"static_func()", static_func_symbol) == 0);
137 constexpr
char kNonStaticFunc[] =
"nonstatic_func";
138 EXPECT_STREQ(
"nonstatic_func",
140 strlen(kNonStaticFunc) + 1));
141 EXPECT_STREQ(
"nonstatic_...",
143 strlen(kNonStaticFunc) + 0));
144 EXPECT_STREQ(
"nonstatic...",
146 strlen(kNonStaticFunc) - 1));
161 EXPECT_STREQ(
"unlikely_func()",
TrySymbolize((
void *)(&unlikely_func)));
162 EXPECT_STREQ(
"hot_func()",
TrySymbolize((
void *)(&hot_func)));
163 EXPECT_STREQ(
"startup_func()",
TrySymbolize((
void *)(&startup_func)));
164 EXPECT_STREQ(
"exit_func()",
TrySymbolize((
void *)(&exit_func)));
169 #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 171 static void *g_pc_to_symbolize;
172 static char g_symbolize_buffer[4096];
173 static char *g_symbolize_result;
175 static void SymbolizeSignalHandler(
int signo) {
177 sizeof(g_symbolize_buffer))) {
178 g_symbolize_result = g_symbolize_buffer;
180 g_symbolize_result =
nullptr;
185 static const char *SymbolizeStackConsumption(
void *pc,
int *stack_consumed) {
186 g_pc_to_symbolize = pc;
187 *stack_consumed = absl::debugging_internal::GetSignalHandlerStackConsumption(
188 SymbolizeSignalHandler);
189 return g_symbolize_result;
192 static int GetStackConsumptionUpperLimit() {
194 int stack_consumption_upper_limit = 2048;
195 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ 196 defined(THREAD_SANITIZER) 198 stack_consumption_upper_limit *= 5;
200 return stack_consumption_upper_limit;
204 int stack_consumed = 0;
207 SymbolizeStackConsumption((
void *)(&
nonstatic_func), &stack_consumed);
208 EXPECT_STREQ(
"nonstatic_func", symbol);
209 EXPECT_GT(stack_consumed, 0);
210 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
214 symbol = SymbolizeStackConsumption((
void *)(&
static_func), &stack_consumed);
215 EXPECT_TRUE(strcmp(
"static_func", symbol) == 0 ||
216 strcmp(
"static_func()", symbol) == 0);
217 EXPECT_GT(stack_consumed, 0);
218 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
223 int stack_consumed = 0;
226 SymbolizeStackConsumption((
void *)(&
Foo::func), &stack_consumed);
228 EXPECT_STREQ(
"Foo::func()", symbol);
229 EXPECT_GT(stack_consumed, 0);
230 EXPECT_LT(stack_consumed, GetStackConsumptionUpperLimit());
233 #endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 236 const size_t kPageSize = 64 << 10;
244 static int FilterElfHeader(
struct dl_phdr_info *info,
size_t size,
void *
data) {
245 for (
int i = 0;
i < info->dlpi_phnum;
i++) {
246 if (info->dlpi_phdr[
i].p_type == PT_LOAD &&
247 info->dlpi_phdr[
i].p_flags == (PF_R | PF_X)) {
248 const void *
const vaddr =
250 const auto segsize = info->dlpi_phdr[
i].p_memsz;
252 const char *self_exe;
253 if (info->dlpi_name !=
nullptr && info->dlpi_name[0] !=
'\0') {
254 self_exe = info->dlpi_name;
256 self_exe =
"/proc/self/exe";
260 vaddr, reinterpret_cast<const char *>(vaddr) + segsize,
261 info->dlpi_phdr[
i].p_offset, self_exe);
279 memset(buf, 0,
sizeof(buf));
281 EXPECT_STREQ(
"kPadding0", buf);
283 memset(buf, 0,
sizeof(buf));
285 EXPECT_STREQ(
"kPadding1", buf);
288 dl_iterate_phdr(FilterElfHeader,
nullptr);
291 const char *ptrs[] = {kPadding0, kPadding1};
293 for (
const char *
ptr : ptrs) {
294 const int kMapFlags = MAP_ANONYMOUS | MAP_PRIVATE;
295 void *addr = mmap(
nullptr, kPageSize, PROT_READ, kMapFlags, 0, 0);
296 ASSERT_NE(addr, MAP_FAILED);
300 void *remapped =
reinterpret_cast<void *
>(
301 reinterpret_cast<uintptr_t
>(
ptr + kPageSize) & ~(kPageSize - 1ULL));
303 const int kMremapFlags = (MREMAP_MAYMOVE | MREMAP_FIXED);
304 void *ret = mremap(addr, kPageSize, kPageSize, kMremapFlags, remapped);
305 ASSERT_NE(ret, MAP_FAILED);
312 const char *expected[] = {
"kPadding0",
"kPadding1"};
313 const size_t offsets[] = {0, kPageSize, 2 * kPageSize, 3 * kPageSize};
315 for (
int i = 0;
i < 2;
i++) {
316 for (
size_t offset : offsets) {
317 memset(buf, 0,
sizeof(buf));
319 EXPECT_STREQ(expected[
i], buf);
325 static void DummySymbolDecorator(
327 std::string *message =
static_cast<std::string *
>(args->
arg);
334 std::string a_message(
"a");
336 DummySymbolDecorator, &a_message),
340 std::string b_message(
"b");
342 DummySymbolDecorator, &b_message),
346 std::string c_message(
"c");
348 DummySymbolDecorator, &c_message),
351 char *address =
reinterpret_cast<char *
>(1);
368 static int in_data_section = 1;
371 int fd = TEMP_FAILURE_RETRY(open(
"/proc/self/exe", O_RDONLY));
374 std::vector<std::string> sections;
375 ASSERT_TRUE(absl::debugging_internal::ForEachSection(
376 fd, [§ions](
const std::string &
name,
const ElfW(Shdr) &) {
377 sections.push_back(name);
382 EXPECT_THAT(sections,
Contains(
".text"));
383 EXPECT_THAT(sections,
Contains(
".rodata"));
384 EXPECT_THAT(sections,
Contains(
".bss"));
386 EXPECT_THAT(sections,
Contains(
".data"));
395 #if defined(__i386__) 396 __asm__ __volatile__(
"call 1f;\n 1: pop %[PC]" : [ PC ]
"=r"(pc));
397 #elif defined(__x86_64__) 398 __asm__ __volatile__(
"leaq 0(%%rip),%[PC];\n" : [ PC ]
"=r"(pc));
405 #if defined(__i386__) 406 __asm__ __volatile__(
"call 1f;\n 1: pop %[PC]" : [ PC ]
"=r"(pc));
407 #elif defined(__x86_64__) 408 __asm__ __volatile__(
"leaq 0(%%rip),%[PC];\n" : [ PC ]
"=r"(pc));
414 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE) && \ 415 (defined(__i386__) || defined(__x86_64__)) 416 void *pc = non_inline_func();
418 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithPCInsideNonInlineFunction failed");
420 "TestWithPCInsideNonInlineFunction failed");
421 std::cout <<
"TestWithPCInsideNonInlineFunction passed" << std::endl;
426 #if defined(ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE) && \ 427 (defined(__i386__) || defined(__x86_64__)) 428 void *pc = inline_func();
430 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithPCInsideInlineFunction failed");
432 "TestWithPCInsideInlineFunction failed");
433 std::cout <<
"TestWithPCInsideInlineFunction passed" << std::endl;
440 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE) 441 void *return_address = __builtin_return_address(0);
443 ABSL_RAW_CHECK(symbol !=
nullptr,
"TestWithReturnAddress failed");
444 ABSL_RAW_CHECK(strcmp(symbol,
"main") == 0,
"TestWithReturnAddress failed");
445 std::cout <<
"TestWithReturnAddress passed" << std::endl;
449 #elif defined(_WIN32) && defined(_DEBUG) 457 ASSERT_TRUE(static_func_symbol !=
nullptr);
458 EXPECT_TRUE(strstr(static_func_symbol,
"static_func") !=
nullptr);
464 constexpr
char kNonStaticFunc[] =
"nonstatic_func";
465 EXPECT_STREQ(
"nonstatic_func",
467 strlen(kNonStaticFunc) + 1));
468 EXPECT_STREQ(
"nonstatic_...",
470 strlen(kNonStaticFunc) + 0));
471 EXPECT_STREQ(
"nonstatic...",
473 strlen(kNonStaticFunc) - 1));
484 ASSERT_TRUE(result !=
nullptr);
485 EXPECT_TRUE(strstr(result,
"Foo::func") !=
nullptr) << result;
488 #else // Symbolizer unimplemented 499 int main(
int argc,
char **argv) {
505 #if ABSL_PER_THREAD_TLS 507 symbolize_test_thread_small[0] = 0;
508 symbolize_test_thread_big[0] = 0;
512 testing::InitGoogleTest(&argc, argv);
514 #ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE 515 TestWithPCInsideInlineFunction();
516 TestWithPCInsideNonInlineFunction();
517 TestWithReturnAddress();
520 return RUN_ALL_TESTS();
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION()
int InstallSymbolDecorator(SymbolDecorator decorator, void *arg)
static const char * TrySymbolize(void *pc)
static constexpr size_t kHpageSize
static volatile bool volatile_bool
#define ABSL_RAW_LOG(severity,...)
void InitializeSymbolizer(const char *argv0)
#define ABSL_ATTRIBUTE_ALWAYS_INLINE
static const char * TrySymbolizeWithLimit(void *pc, int limit)
Dest bit_cast(const Source &source)
static char try_symbolize_buffer[4096]
#define ABSL_RAW_CHECK(condition, message)
int main(int argc, char **argv)
absl::disjunction< std::is_same< T, Ts >... > Contains
bool Symbolize(const void *pc, char *out, int out_size)
static char data[kDataSize]
bool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset, const char *filename)
#define ABSL_ATTRIBUTE_NOINLINE
static void static_func()
TEST(Symbolize, Unimplemented)
#define ABSL_PER_THREAD_TLS_KEYWORD
int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.unlikely) unlikely_func()
bool RemoveSymbolDecorator(int ticket)