-// Copyright 2006 Google Inc. All Rights Reserved.
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
// Author: Satoru Takabayashi
//
// Unit tests for functions in symbolize.cc.
#include "googletest.h"
#include "config.h"
+#ifdef HAVE_LIB_GFLAGS
+#include <gflags/gflags.h>
+using namespace GFLAGS_NAMESPACE;
+#endif
+
using namespace std;
using namespace GOOGLE_NAMESPACE;
-#if defined(HAVE_STACKTRACE) && defined(__ELF__)
+#if defined(HAVE_STACKTRACE)
#define always_inline
+// A wrapper function for Symbolize() to make the unit test simple.
+static const char *TrySymbolize(void *pc) {
+ static char symbol[4096];
+ if (Symbolize(pc, symbol, sizeof(symbol))) {
+ return symbol;
+ } else {
+ return NULL;
+ }
+}
+
+# if defined(__ELF__)
+
// This unit tests make sense only with GCC.
// Uses lots of GCC specific features.
#if defined(__GNUC__) && !defined(__OPENCC__)
# endif // defined(__i386__) || defined(__x86_64__)
#endif
-// A wrapper function for Symbolize() to make the unit test simple.
-static const char *TrySymbolize(void *pc) {
- static char symbol[4096];
- if (Symbolize(pc, symbol, sizeof(symbol))) {
- return symbol;
- } else {
- return NULL;
- }
-}
-
// Make them C linkage to avoid mangled names.
extern "C" {
void nonstatic_func() {
// Compilers should give us pointers to them.
EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func)));
- EXPECT_STREQ("static_func", TrySymbolize((void *)(&static_func)));
+
+ // The name of an internal linkage symbol is not specified; allow either a
+ // mangled or an unmangled name here.
+ const char *static_func_symbol = TrySymbolize((void *)(&static_func));
+ CHECK(NULL != static_func_symbol);
+ EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 ||
+ strcmp("static_func()", static_func_symbol) == 0);
EXPECT_TRUE(NULL == TrySymbolize(NULL));
}
memset(altstack, kAlternateStackFillValue, kAlternateStackSize);
// Set up the alt-signal-stack (and save the older one).
- stack_t sigstk = {}; // Zero-clear.
+ stack_t sigstk;
+ memset(&sigstk, 0, sizeof(stack_t));
stack_t old_sigstk;
sigstk.ss_sp = altstack;
sigstk.ss_size = kAlternateStackSize;
CHECK_ERR(sigaltstack(&sigstk, &old_sigstk));
// Set up SIGUSR1 and SIGUSR2 signal handlers (and save the older ones).
- struct sigaction sa = {}; // Zero-clear;
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(struct sigaction));
struct sigaction old_sa1, old_sa2;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_ONSTACK;
return g_symbolize_result;
}
+#ifdef __ppc64__
+// Symbolize stack consumption should be within 4kB.
+const int kStackConsumptionUpperLimit = 4096;
+#else
// Symbolize stack consumption should be within 2kB.
const int kStackConsumptionUpperLimit = 2048;
+#endif
TEST(Symbolize, SymbolizeStackConsumption) {
int stack_consumed;
EXPECT_GT(stack_consumed, 0);
EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
+ // The name of an internal linkage symbol is not specified; allow either a
+ // mangled or an unmangled name here.
symbol = SymbolizeStackConsumption((void *)(&static_func),
&stack_consumed);
- EXPECT_STREQ("static_func", symbol);
+ CHECK(NULL != symbol);
+ EXPECT_TRUE(strcmp("static_func", symbol) == 0 ||
+ strcmp("static_func()", symbol) == 0);
EXPECT_GT(stack_consumed, 0);
EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
}
#endif
}
+# elif defined(OS_WINDOWS)
+
+#include <intrin.h>
+#pragma intrinsic(_ReturnAddress)
+
+struct Foo {
+ static void func(int x);
+};
+
+__declspec(noinline) void Foo::func(int x) {
+ volatile int a = x;
+ ++a;
+}
+
+TEST(Symbolize, SymbolizeWithDemangling) {
+ Foo::func(100);
+ const char* ret = TrySymbolize((void *)(&Foo::func));
+ EXPECT_STREQ("public: static void __cdecl Foo::func(int)", ret);
+}
+
+__declspec(noinline) void TestWithReturnAddress() {
+ void *return_address = _ReturnAddress();
+ const char *symbol = TrySymbolize(return_address);
+ CHECK(symbol != NULL);
+ CHECK_STREQ(symbol, "main");
+ cout << "Test case TestWithReturnAddress passed." << endl;
+}
+# endif // __ELF__
+#endif // HAVE_STACKTRACE
+
int main(int argc, char **argv) {
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
InitGoogleTest(&argc, argv);
-#ifdef HAVE_SYMBOLIZE
+#if defined(HAVE_SYMBOLIZE)
+# if defined(__ELF__)
// We don't want to get affected by the callback interface, that may be
// used to install some callback function at InitGoogle() time.
InstallSymbolizeCallback(NULL);
TestWithPCInsideNonInlineFunction();
TestWithReturnAddress();
return RUN_ALL_TESTS();
-#else
- return 0;
-#endif
-}
-
-#else
-int main() {
-#ifdef HAVE_SYMBOLIZE
+# elif defined(OS_WINDOWS)
+ TestWithReturnAddress();
+ return RUN_ALL_TESTS();
+# else // OS_WINDOWS
printf("PASS (no symbolize_unittest support)\n");
+ return 0;
+# endif // __ELF__
#else
printf("PASS (no symbolize support)\n");
-#endif
return 0;
+#endif // HAVE_SYMBOLIZE
}
-#endif // HAVE_STACKTRACE