From f9b58c51984c76ec4e6f0305926075716fc8c079 Mon Sep 17 00:00:00 2001 From: Date: Mon, 17 Nov 2008 07:58:10 +0000 Subject: [PATCH] Re-organize the way to produce stacktrace. Since we introduced the API to set signal handler and print a stacktrace, we should avoid glibc's backtrace, which may call malloc. Basically, we choose the way to produce a stacktrace as same as perftools. Also, I removed GetStackFrames, which is not used and not implemented with glibc. git-svn-id: https://google-glog.googlecode.com/svn/trunk@16 eb4d4688-79bd-11dd-afb4-1d65580434c0 --- Makefile.am | 39 ++-- Makefile.in | 146 ++++++-------- configure | 280 +++++++++++++++++++++++--- configure.ac | 16 +- src/config.h.in | 6 + src/signalhandler.cc | 31 +-- src/signalhandler_unittest.cc | 2 +- src/signalhandler_unittest.sh | 7 + src/stacktrace.h | 34 ---- src/stacktrace_framesizes_unittest.cc | 119 ----------- src/stacktrace_generic-inl.h | 48 ----- src/stacktrace_libunwind-inl.h | 94 ++------- src/stacktrace_powerpc-inl.h | 78 ------- src/stacktrace_unittest.cc | 3 + src/stacktrace_x86-inl.h | 84 -------- src/stacktrace_x86_64-inl.h | 48 ----- src/symbolize_unittest.cc | 11 +- src/utilities.cc | 11 +- src/utilities.h | 75 ++++++- src/utilities_unittest.cc | 21 ++ 20 files changed, 497 insertions(+), 656 deletions(-) delete mode 100644 src/stacktrace_framesizes_unittest.cc create mode 100644 src/utilities_unittest.cc diff --git a/Makefile.am b/Makefile.am index 469c986..5b55e0f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,6 +40,9 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ ## The libraries (.so's) you want to install lib_LTLIBRARIES = +# The libraries libglog depends on. +COMMON_LIBS=$(PTHREAD_LIBS) $(GFLAGS_LIBS) $(UNWIND_LIBS) + ## unittests you want to run when people type 'make check'. ## TESTS is for binary unittests, check_SCRIPTS for script-based unittests. ## TESTS_ENVIRONMENT sets environment variables for when you run unittest, @@ -57,7 +60,7 @@ logging_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging_unittest.cc logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -logging_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_unittest_LDADD = libglog.la $(COMMON_LIBS) check_SCRIPTS += logging_striplog_test_sh noinst_SCRIPTS += src/logging_striplog_test.sh @@ -82,63 +85,63 @@ logging_striptest0_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging_striptest_main.cc logging_striptest0_CXXFLAGS = $(PTHREAD_CFLAGS) logging_striptest0_LDFLAGS = $(PTHREAD_CFLAGS) -logging_striptest0_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_striptest0_LDADD = libglog.la $(COMMON_LIBS) TEST_BINARIES += logging_striptest2 logging_striptest2_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging_striptest2.cc logging_striptest2_CXXFLAGS = $(PTHREAD_CFLAGS) logging_striptest2_LDFLAGS = $(PTHREAD_CFLAGS) -logging_striptest2_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_striptest2_LDADD = libglog.la $(COMMON_LIBS) TEST_BINARIES += logging_striptest10 logging_striptest10_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging_striptest10.cc logging_striptest10_CXXFLAGS = $(PTHREAD_CFLAGS) logging_striptest10_LDFLAGS = $(PTHREAD_CFLAGS) -logging_striptest10_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_striptest10_LDADD = libglog.la $(COMMON_LIBS) TESTS += demangle_unittest demangle_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/demangle_unittest.cc demangle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) demangle_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -demangle_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +demangle_unittest_LDADD = libglog.la $(COMMON_LIBS) TESTS += stacktrace_unittest stacktrace_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/stacktrace_unittest.cc stacktrace_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) stacktrace_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -stacktrace_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +stacktrace_unittest_LDADD = libglog.la $(COMMON_LIBS) TESTS += symbolize_unittest symbolize_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/symbolize_unittest.cc symbolize_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) symbolize_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -symbolize_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) - -TESTS += stacktrace_framesizes_unittest -stacktrace_framesizes_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ - src/stacktrace_framesizes_unittest.cc -stacktrace_framesizes_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) -stacktrace_framesizes_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -stacktrace_framesizes_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +symbolize_unittest_LDADD = libglog.la $(COMMON_LIBS) TESTS += stl_logging_unittest stl_logging_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/stl_logging_unittest.cc stl_logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) stl_logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -stl_logging_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +stl_logging_unittest_LDADD = libglog.la $(COMMON_LIBS) TEST_BINARIES += signalhandler_unittest signalhandler_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/signalhandler_unittest.cc signalhandler_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) signalhandler_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -signalhandler_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +signalhandler_unittest_LDADD = libglog.la $(COMMON_LIBS) + +TESTS += utilities_unittest +utilities_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ + src/utilities_unittest.cc +utilities_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) +utilities_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +utilities_unittest_LDADD = libglog.la $(COMMON_LIBS) ## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS @@ -147,7 +150,7 @@ libglog_la_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging.cc src/raw_logging.cc src/vlog_is_on.cc \ src/utilities.cc src/utilities.h \ src/demangle.cc src/demangle.h \ - src/stacktrace.cc src/stacktrace.h \ + src/stacktrace.h \ src/stacktrace_generic-inl.h \ src/stacktrace_libunwind-inl.h \ src/stacktrace_powerpc-inl.h \ @@ -160,7 +163,7 @@ libglog_la_SOURCES = $(gloginclude_HEADERS) src/config.h \ libglog_la_CXXFLAGS = $(PTRHEAD_CFLAGS) -DNDEBUG libglog_la_LDFLAGS = $(PTRHEAD_CFLAGS) -libglog_la_LIBADD = $(PTHREAD_LIBS) +libglog_la_LIBADD = $(COMMON_LIBS) ## ^^^^ END OF RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS diff --git a/Makefile.in b/Makefile.in index ffdfa82..c076f26 100644 --- a/Makefile.in +++ b/Makefile.in @@ -45,8 +45,7 @@ host_triplet = @host@ @ENABLE_FRAME_POINTERS_FALSE@@X86_64_TRUE@am__append_3 = -DNO_FRAME_POINTER TESTS = logging_unittest$(EXEEXT) demangle_unittest$(EXEEXT) \ stacktrace_unittest$(EXEEXT) symbolize_unittest$(EXEEXT) \ - stacktrace_framesizes_unittest$(EXEEXT) \ - stl_logging_unittest$(EXEEXT) + stl_logging_unittest$(EXEEXT) utilities_unittest$(EXEEXT) noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) subdir = . DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \ @@ -87,29 +86,28 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \ libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = -libglog_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +libglog_la_DEPENDENCIES = $(am__DEPENDENCIES_2) am__objects_1 = am_libglog_la_OBJECTS = $(am__objects_1) libglog_la-logging.lo \ libglog_la-raw_logging.lo libglog_la-vlog_is_on.lo \ libglog_la-utilities.lo libglog_la-demangle.lo \ - libglog_la-stacktrace.lo libglog_la-symbolize.lo \ - libglog_la-signalhandler.lo + libglog_la-symbolize.lo libglog_la-signalhandler.lo libglog_la_OBJECTS = $(am_libglog_la_OBJECTS) libglog_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libglog_la_CXXFLAGS) \ $(CXXFLAGS) $(libglog_la_LDFLAGS) $(LDFLAGS) -o $@ am__EXEEXT_1 = logging_unittest$(EXEEXT) demangle_unittest$(EXEEXT) \ stacktrace_unittest$(EXEEXT) symbolize_unittest$(EXEEXT) \ - stacktrace_framesizes_unittest$(EXEEXT) \ - stl_logging_unittest$(EXEEXT) + stl_logging_unittest$(EXEEXT) utilities_unittest$(EXEEXT) am__EXEEXT_2 = logging_striptest0$(EXEEXT) logging_striptest2$(EXEEXT) \ logging_striptest10$(EXEEXT) signalhandler_unittest$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_demangle_unittest_OBJECTS = $(am__objects_1) \ demangle_unittest-demangle_unittest.$(OBJEXT) demangle_unittest_OBJECTS = $(am_demangle_unittest_OBJECTS) -demangle_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +demangle_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) demangle_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(demangle_unittest_CXXFLAGS) $(CXXFLAGS) \ @@ -117,8 +115,7 @@ demangle_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ am_logging_striptest0_OBJECTS = $(am__objects_1) \ logging_striptest0-logging_striptest_main.$(OBJEXT) logging_striptest0_OBJECTS = $(am_logging_striptest0_OBJECTS) -logging_striptest0_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +logging_striptest0_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) logging_striptest0_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(logging_striptest0_CXXFLAGS) $(CXXFLAGS) \ @@ -126,8 +123,7 @@ logging_striptest0_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ am_logging_striptest10_OBJECTS = $(am__objects_1) \ logging_striptest10-logging_striptest10.$(OBJEXT) logging_striptest10_OBJECTS = $(am_logging_striptest10_OBJECTS) -logging_striptest10_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +logging_striptest10_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) logging_striptest10_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(logging_striptest10_CXXFLAGS) $(CXXFLAGS) \ @@ -135,8 +131,7 @@ logging_striptest10_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ am_logging_striptest2_OBJECTS = $(am__objects_1) \ logging_striptest2-logging_striptest2.$(OBJEXT) logging_striptest2_OBJECTS = $(am_logging_striptest2_OBJECTS) -logging_striptest2_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +logging_striptest2_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) logging_striptest2_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(logging_striptest2_CXXFLAGS) $(CXXFLAGS) \ @@ -144,8 +139,7 @@ logging_striptest2_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ am_logging_unittest_OBJECTS = $(am__objects_1) \ logging_unittest-logging_unittest.$(OBJEXT) logging_unittest_OBJECTS = $(am_logging_unittest_OBJECTS) -logging_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +logging_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) logging_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(logging_unittest_CXXFLAGS) $(CXXFLAGS) \ @@ -153,27 +147,15 @@ logging_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ am_signalhandler_unittest_OBJECTS = $(am__objects_1) \ signalhandler_unittest-signalhandler_unittest.$(OBJEXT) signalhandler_unittest_OBJECTS = $(am_signalhandler_unittest_OBJECTS) -signalhandler_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +signalhandler_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) signalhandler_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(signalhandler_unittest_CXXFLAGS) $(CXXFLAGS) \ $(signalhandler_unittest_LDFLAGS) $(LDFLAGS) -o $@ -am_stacktrace_framesizes_unittest_OBJECTS = $(am__objects_1) \ - stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.$(OBJEXT) -stacktrace_framesizes_unittest_OBJECTS = \ - $(am_stacktrace_framesizes_unittest_OBJECTS) -stacktrace_framesizes_unittest_DEPENDENCIES = libglog.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -stacktrace_framesizes_unittest_LINK = $(LIBTOOL) --tag=CXX \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ - $(stacktrace_framesizes_unittest_CXXFLAGS) $(CXXFLAGS) \ - $(stacktrace_framesizes_unittest_LDFLAGS) $(LDFLAGS) -o $@ am_stacktrace_unittest_OBJECTS = $(am__objects_1) \ stacktrace_unittest-stacktrace_unittest.$(OBJEXT) stacktrace_unittest_OBJECTS = $(am_stacktrace_unittest_OBJECTS) -stacktrace_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +stacktrace_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) stacktrace_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(stacktrace_unittest_CXXFLAGS) $(CXXFLAGS) \ @@ -181,8 +163,7 @@ stacktrace_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ am_stl_logging_unittest_OBJECTS = $(am__objects_1) \ stl_logging_unittest-stl_logging_unittest.$(OBJEXT) stl_logging_unittest_OBJECTS = $(am_stl_logging_unittest_OBJECTS) -stl_logging_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +stl_logging_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) stl_logging_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(stl_logging_unittest_CXXFLAGS) $(CXXFLAGS) \ @@ -190,12 +171,19 @@ stl_logging_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ am_symbolize_unittest_OBJECTS = $(am__objects_1) \ symbolize_unittest-symbolize_unittest.$(OBJEXT) symbolize_unittest_OBJECTS = $(am_symbolize_unittest_OBJECTS) -symbolize_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +symbolize_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) symbolize_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(symbolize_unittest_CXXFLAGS) $(CXXFLAGS) \ $(symbolize_unittest_LDFLAGS) $(LDFLAGS) -o $@ +am_utilities_unittest_OBJECTS = $(am__objects_1) \ + utilities_unittest-utilities_unittest.$(OBJEXT) +utilities_unittest_OBJECTS = $(am_utilities_unittest_OBJECTS) +utilities_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) +utilities_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) \ + $(utilities_unittest_LDFLAGS) $(LDFLAGS) -o $@ SCRIPTS = $(noinst_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -222,16 +210,14 @@ SOURCES = $(libglog_la_SOURCES) $(demangle_unittest_SOURCES) \ $(logging_striptest0_SOURCES) $(logging_striptest10_SOURCES) \ $(logging_striptest2_SOURCES) $(logging_unittest_SOURCES) \ $(signalhandler_unittest_SOURCES) \ - $(stacktrace_framesizes_unittest_SOURCES) \ $(stacktrace_unittest_SOURCES) $(stl_logging_unittest_SOURCES) \ - $(symbolize_unittest_SOURCES) + $(symbolize_unittest_SOURCES) $(utilities_unittest_SOURCES) DIST_SOURCES = $(libglog_la_SOURCES) $(demangle_unittest_SOURCES) \ $(logging_striptest0_SOURCES) $(logging_striptest10_SOURCES) \ $(logging_striptest2_SOURCES) $(logging_unittest_SOURCES) \ $(signalhandler_unittest_SOURCES) \ - $(stacktrace_framesizes_unittest_SOURCES) \ $(stacktrace_unittest_SOURCES) $(stl_logging_unittest_SOURCES) \ - $(symbolize_unittest_SOURCES) + $(symbolize_unittest_SOURCES) $(utilities_unittest_SOURCES) dist_docDATA_INSTALL = $(INSTALL_DATA) DATA = $(dist_doc_DATA) glogincludeHEADERS_INSTALL = $(INSTALL_HEADER) @@ -310,6 +296,7 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ +UNWIND_LIBS = @UNWIND_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -392,6 +379,9 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \ doc/designstyle.css doc/glog.html lib_LTLIBRARIES = libglog.la + +# The libraries libglog depends on. +COMMON_LIBS = $(PTHREAD_LIBS) $(GFLAGS_LIBS) $(UNWIND_LIBS) TESTS_ENVIRONMENT = check_SCRIPTS = logging_striplog_test_sh demangle_unittest_sh \ signalhandler_unittest_sh @@ -406,66 +396,66 @@ logging_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -logging_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_unittest_LDADD = libglog.la $(COMMON_LIBS) logging_striptest0_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging_striptest_main.cc logging_striptest0_CXXFLAGS = $(PTHREAD_CFLAGS) logging_striptest0_LDFLAGS = $(PTHREAD_CFLAGS) -logging_striptest0_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_striptest0_LDADD = libglog.la $(COMMON_LIBS) logging_striptest2_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging_striptest2.cc logging_striptest2_CXXFLAGS = $(PTHREAD_CFLAGS) logging_striptest2_LDFLAGS = $(PTHREAD_CFLAGS) -logging_striptest2_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_striptest2_LDADD = libglog.la $(COMMON_LIBS) logging_striptest10_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging_striptest10.cc logging_striptest10_CXXFLAGS = $(PTHREAD_CFLAGS) logging_striptest10_LDFLAGS = $(PTHREAD_CFLAGS) -logging_striptest10_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +logging_striptest10_LDADD = libglog.la $(COMMON_LIBS) demangle_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/demangle_unittest.cc demangle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) demangle_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -demangle_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +demangle_unittest_LDADD = libglog.la $(COMMON_LIBS) stacktrace_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/stacktrace_unittest.cc stacktrace_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) stacktrace_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -stacktrace_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +stacktrace_unittest_LDADD = libglog.la $(COMMON_LIBS) symbolize_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/symbolize_unittest.cc symbolize_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) symbolize_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -symbolize_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) -stacktrace_framesizes_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ - src/stacktrace_framesizes_unittest.cc - -stacktrace_framesizes_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) -stacktrace_framesizes_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -stacktrace_framesizes_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +symbolize_unittest_LDADD = libglog.la $(COMMON_LIBS) stl_logging_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/stl_logging_unittest.cc stl_logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) stl_logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -stl_logging_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +stl_logging_unittest_LDADD = libglog.la $(COMMON_LIBS) signalhandler_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/signalhandler_unittest.cc signalhandler_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) signalhandler_unittest_LDFLAGS = $(PTHREAD_CFLAGS) -signalhandler_unittest_LDADD = libglog.la $(PTHREAD_LIBS) $(GFLAGS_LIBS) +signalhandler_unittest_LDADD = libglog.la $(COMMON_LIBS) +utilities_unittest_SOURCES = $(gloginclude_HEADERS) src/config.h \ + src/utilities_unittest.cc + +utilities_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) +utilities_unittest_LDFLAGS = $(PTHREAD_CFLAGS) +utilities_unittest_LDADD = libglog.la $(COMMON_LIBS) libglog_la_SOURCES = $(gloginclude_HEADERS) src/config.h \ src/logging.cc src/raw_logging.cc src/vlog_is_on.cc \ src/utilities.cc src/utilities.h \ src/demangle.cc src/demangle.h \ - src/stacktrace.cc src/stacktrace.h \ + src/stacktrace.h \ src/stacktrace_generic-inl.h \ src/stacktrace_libunwind-inl.h \ src/stacktrace_powerpc-inl.h \ @@ -478,7 +468,7 @@ libglog_la_SOURCES = $(gloginclude_HEADERS) src/config.h \ libglog_la_CXXFLAGS = $(PTRHEAD_CFLAGS) -DNDEBUG libglog_la_LDFLAGS = $(PTRHEAD_CFLAGS) -libglog_la_LIBADD = $(PTHREAD_LIBS) +libglog_la_LIBADD = $(COMMON_LIBS) EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \ $(SCRIPTS) src/logging_unittest.err src/demangle_unittest.txt @@ -598,9 +588,6 @@ logging_unittest$(EXEEXT): $(logging_unittest_OBJECTS) $(logging_unittest_DEPEND signalhandler_unittest$(EXEEXT): $(signalhandler_unittest_OBJECTS) $(signalhandler_unittest_DEPENDENCIES) @rm -f signalhandler_unittest$(EXEEXT) $(signalhandler_unittest_LINK) $(signalhandler_unittest_OBJECTS) $(signalhandler_unittest_LDADD) $(LIBS) -stacktrace_framesizes_unittest$(EXEEXT): $(stacktrace_framesizes_unittest_OBJECTS) $(stacktrace_framesizes_unittest_DEPENDENCIES) - @rm -f stacktrace_framesizes_unittest$(EXEEXT) - $(stacktrace_framesizes_unittest_LINK) $(stacktrace_framesizes_unittest_OBJECTS) $(stacktrace_framesizes_unittest_LDADD) $(LIBS) stacktrace_unittest$(EXEEXT): $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_DEPENDENCIES) @rm -f stacktrace_unittest$(EXEEXT) $(stacktrace_unittest_LINK) $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_LDADD) $(LIBS) @@ -610,6 +597,9 @@ stl_logging_unittest$(EXEEXT): $(stl_logging_unittest_OBJECTS) $(stl_logging_uni symbolize_unittest$(EXEEXT): $(symbolize_unittest_OBJECTS) $(symbolize_unittest_DEPENDENCIES) @rm -f symbolize_unittest$(EXEEXT) $(symbolize_unittest_LINK) $(symbolize_unittest_OBJECTS) $(symbolize_unittest_LDADD) $(LIBS) +utilities_unittest$(EXEEXT): $(utilities_unittest_OBJECTS) $(utilities_unittest_DEPENDENCIES) + @rm -f utilities_unittest$(EXEEXT) + $(utilities_unittest_LINK) $(utilities_unittest_OBJECTS) $(utilities_unittest_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -622,7 +612,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-raw_logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-signalhandler.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-stacktrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-symbolize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-utilities.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-vlog_is_on.Plo@am__quote@ @@ -631,10 +620,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_striptest2-logging_striptest2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_unittest-logging_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbolize_unittest-symbolize_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utilities_unittest-utilities_unittest.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -692,13 +681,6 @@ libglog_la-demangle.lo: src/demangle.cc @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-demangle.lo `test -f 'src/demangle.cc' || echo '$(srcdir)/'`src/demangle.cc -libglog_la-stacktrace.lo: src/stacktrace.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-stacktrace.lo -MD -MP -MF $(DEPDIR)/libglog_la-stacktrace.Tpo -c -o libglog_la-stacktrace.lo `test -f 'src/stacktrace.cc' || echo '$(srcdir)/'`src/stacktrace.cc -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libglog_la-stacktrace.Tpo $(DEPDIR)/libglog_la-stacktrace.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stacktrace.cc' object='libglog_la-stacktrace.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-stacktrace.lo `test -f 'src/stacktrace.cc' || echo '$(srcdir)/'`src/stacktrace.cc - libglog_la-symbolize.lo: src/symbolize.cc @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-symbolize.lo -MD -MP -MF $(DEPDIR)/libglog_la-symbolize.Tpo -c -o libglog_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/libglog_la-symbolize.Tpo $(DEPDIR)/libglog_la-symbolize.Plo @@ -797,20 +779,6 @@ signalhandler_unittest-signalhandler_unittest.obj: src/signalhandler_unittest.cc @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(signalhandler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o signalhandler_unittest-signalhandler_unittest.obj `if test -f 'src/signalhandler_unittest.cc'; then $(CYGPATH_W) 'src/signalhandler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/signalhandler_unittest.cc'; fi` -stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.o: src/stacktrace_framesizes_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_framesizes_unittest_CXXFLAGS) $(CXXFLAGS) -MT stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.o -MD -MP -MF $(DEPDIR)/stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.Tpo -c -o stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.o `test -f 'src/stacktrace_framesizes_unittest.cc' || echo '$(srcdir)/'`src/stacktrace_framesizes_unittest.cc -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.Tpo $(DEPDIR)/stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stacktrace_framesizes_unittest.cc' object='stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_framesizes_unittest_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.o `test -f 'src/stacktrace_framesizes_unittest.cc' || echo '$(srcdir)/'`src/stacktrace_framesizes_unittest.cc - -stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.obj: src/stacktrace_framesizes_unittest.cc -@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_framesizes_unittest_CXXFLAGS) $(CXXFLAGS) -MT stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.obj -MD -MP -MF $(DEPDIR)/stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.Tpo -c -o stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.obj `if test -f 'src/stacktrace_framesizes_unittest.cc'; then $(CYGPATH_W) 'src/stacktrace_framesizes_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/stacktrace_framesizes_unittest.cc'; fi` -@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.Tpo $(DEPDIR)/stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stacktrace_framesizes_unittest.cc' object='stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_framesizes_unittest_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace_framesizes_unittest-stacktrace_framesizes_unittest.obj `if test -f 'src/stacktrace_framesizes_unittest.cc'; then $(CYGPATH_W) 'src/stacktrace_framesizes_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/stacktrace_framesizes_unittest.cc'; fi` - stacktrace_unittest-stacktrace_unittest.o: src/stacktrace_unittest.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_unittest_CXXFLAGS) $(CXXFLAGS) -MT stacktrace_unittest-stacktrace_unittest.o -MD -MP -MF $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Tpo -c -o stacktrace_unittest-stacktrace_unittest.o `test -f 'src/stacktrace_unittest.cc' || echo '$(srcdir)/'`src/stacktrace_unittest.cc @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Tpo $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Po @@ -853,6 +821,20 @@ symbolize_unittest-symbolize_unittest.obj: src/symbolize_unittest.cc @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(symbolize_unittest_CXXFLAGS) $(CXXFLAGS) -c -o symbolize_unittest-symbolize_unittest.obj `if test -f 'src/symbolize_unittest.cc'; then $(CYGPATH_W) 'src/symbolize_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/symbolize_unittest.cc'; fi` +utilities_unittest-utilities_unittest.o: src/utilities_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -MT utilities_unittest-utilities_unittest.o -MD -MP -MF $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo -c -o utilities_unittest-utilities_unittest.o `test -f 'src/utilities_unittest.cc' || echo '$(srcdir)/'`src/utilities_unittest.cc +@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo $(DEPDIR)/utilities_unittest-utilities_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/utilities_unittest.cc' object='utilities_unittest-utilities_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -c -o utilities_unittest-utilities_unittest.o `test -f 'src/utilities_unittest.cc' || echo '$(srcdir)/'`src/utilities_unittest.cc + +utilities_unittest-utilities_unittest.obj: src/utilities_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -MT utilities_unittest-utilities_unittest.obj -MD -MP -MF $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo -c -o utilities_unittest-utilities_unittest.obj `if test -f 'src/utilities_unittest.cc'; then $(CYGPATH_W) 'src/utilities_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/utilities_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo $(DEPDIR)/utilities_unittest-utilities_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/utilities_unittest.cc' object='utilities_unittest-utilities_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -c -o utilities_unittest-utilities_unittest.obj `if test -f 'src/utilities_unittest.cc'; then $(CYGPATH_W) 'src/utilities_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/utilities_unittest.cc'; fi` + mostlyclean-libtool: -rm -f *.lo diff --git a/configure b/configure index ae51b29..7a98f8e 100755 --- a/configure +++ b/configure @@ -884,6 +884,7 @@ acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS +UNWIND_LIBS ac_google_start_namespace ac_google_end_namespace ac_google_namespace @@ -5062,7 +5063,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 5065 "configure"' > conftest.$ac_ext + echo '#line 5066 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -7417,11 +7418,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7420: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7421: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7424: \$? = $ac_status" >&5 + echo "$as_me:7425: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7707,11 +7708,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7710: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7711: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7714: \$? = $ac_status" >&5 + echo "$as_me:7715: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7811,11 +7812,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7814: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7815: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7818: \$? = $ac_status" >&5 + echo "$as_me:7819: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -10188,7 +10189,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:12693: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:12696: \$? = $ac_status" >&5 + echo "$as_me:12697: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -12793,11 +12794,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12796: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12797: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12800: \$? = $ac_status" >&5 + echo "$as_me:12801: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14391,11 +14392,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14394: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14395: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14398: \$? = $ac_status" >&5 + echo "$as_me:14399: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -14495,11 +14496,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14498: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14499: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14502: \$? = $ac_status" >&5 + echo "$as_me:14503: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -16715,11 +16716,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16718: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16719: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16722: \$? = $ac_status" >&5 + echo "$as_me:16723: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -17005,11 +17006,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17008: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17009: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:17012: \$? = $ac_status" >&5 + echo "$as_me:17013: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -17109,11 +17110,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17112: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17113: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:17116: \$? = $ac_status" >&5 + echo "$as_me:17117: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -20680,7 +20681,6 @@ fi done # For backtrace with glibc. -# TODO(hamaji): Support other platforms using libgcc. for ac_header in execinfo.h do @@ -20826,6 +20826,154 @@ fi done +# For backtrace with libunwind. + +for ac_header in libunwind.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to opensource@google.com ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + ac_cv_have_libunwind_h=1 +else + ac_cv_have_libunwind_h=0 +fi + +done + for ac_header in ucontext.h do @@ -22744,6 +22892,87 @@ else GFLAGS_LIBS= fi +# We want to link in libunwind if it exists +UNWIND_LIBS= +# Unfortunately, we need to check the header file in addition to the +# lib file to check if libunwind is available since libunwind-0.98 +# doesn't install all necessary header files. +if test x"$ac_cv_have_libunwind_h" = x"1"; then + { echo "$as_me:$LINENO: checking for backtrace in -lunwind" >&5 +echo $ECHO_N "checking for backtrace in -lunwind... $ECHO_C" >&6; } +if test "${ac_cv_lib_unwind_backtrace+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lunwind $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char backtrace (); +int +main () +{ +return backtrace (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_unwind_backtrace=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_unwind_backtrace=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_unwind_backtrace" >&5 +echo "${ECHO_T}$ac_cv_lib_unwind_backtrace" >&6; } +if test $ac_cv_lib_unwind_backtrace = yes; then + UNWIND_LIBS=-lunwind +fi + +fi + +if test x"$UNWIND_LIBS" != x""; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIB_UNWIND 1 +_ACEOF + +fi + # We'd like to use read/write locks in several places in the code. # See if our pthreads support extends to that. Note: for linux, it # does as long as you define _XOPEN_SOURCE appropriately. @@ -24052,6 +24281,7 @@ acx_pthread_config!$acx_pthread_config$ac_delim PTHREAD_CC!$PTHREAD_CC$ac_delim PTHREAD_LIBS!$PTHREAD_LIBS$ac_delim PTHREAD_CFLAGS!$PTHREAD_CFLAGS$ac_delim +UNWIND_LIBS!$UNWIND_LIBS$ac_delim ac_google_start_namespace!$ac_google_start_namespace$ac_delim ac_google_end_namespace!$ac_google_end_namespace$ac_delim ac_google_namespace!$ac_google_namespace$ac_delim @@ -24071,7 +24301,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 35; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 36; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/configure.ac b/configure.ac index 9434fd1..008289b 100644 --- a/configure.ac +++ b/configure.ac @@ -31,8 +31,9 @@ AC_CHECK_HEADER(inttypes.h, ac_cv_have_inttypes_h=1, ac_cv_have_inttypes_h=0) AC_CHECK_HEADERS(syscall.h) AC_CHECK_HEADERS(sys/syscall.h) # For backtrace with glibc. -# TODO(hamaji): Support other platforms using libgcc. AC_CHECK_HEADERS(execinfo.h) +# For backtrace with libunwind. +AC_CHECK_HEADERS(libunwind.h, ac_cv_have_libunwind_h=1, ac_cv_have_libunwind_h=0) AC_CHECK_HEADERS(ucontext.h) AC_CHECK_SIZEOF(void *) @@ -92,6 +93,19 @@ else GFLAGS_LIBS= fi +# We want to link in libunwind if it exists +UNWIND_LIBS= +# Unfortunately, we need to check the header file in addition to the +# lib file to check if libunwind is available since libunwind-0.98 +# doesn't install all necessary header files. +if test x"$ac_cv_have_libunwind_h" = x"1"; then + AC_CHECK_LIB(unwind, backtrace, UNWIND_LIBS=-lunwind) +fi +AC_SUBST(UNWIND_LIBS) +if test x"$UNWIND_LIBS" != x""; then + AC_DEFINE(HAVE_LIB_UNWIND, 1, [define if you have libunwind]) +fi + # We'd like to use read/write locks in several places in the code. # See if our pthreads support extends to that. Note: for linux, it # does as long as you define _XOPEN_SOURCE appropriately. diff --git a/src/config.h.in b/src/config.h.in index 08c09c7..f73b9f7 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -15,9 +15,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBUNWIND_H + /* define if you have google gflags library */ #undef HAVE_LIB_GFLAGS +/* define if you have libunwind */ +#undef HAVE_LIB_UNWIND + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H diff --git a/src/signalhandler.cc b/src/signalhandler.cc index 8e30297..3c89715 100644 --- a/src/signalhandler.cc +++ b/src/signalhandler.cc @@ -22,30 +22,6 @@ _START_GOOGLE_NAMESPACE_ namespace { -// Wrapper of __sync_val_compare_and_swap. If the GCC extension isn't -// defined, we try the CPU specific logics (we only support x86 and -// x86_64 for now) first, then use a naive implementation, which has a -// race condition. -template -inline T* sync_val_compare_and_swap(T** ptr, T* oldval, T* newval) { -#if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP) - return __sync_val_compare_and_swap(ptr, oldval, newval); -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - T* ret; - __asm__ __volatile__("lock; cmpxchg %1, (%2);" - :"=a"(ret) - :"r"(newval), "r"(ptr), "a"(oldval) - :"memory", "cc"); - return ret; -#else - T* ret = *ptr; - if (ret == oldval) { - *ptr = newval; - } - return ret; -#endif -} - // We'll install the failure signal handler for these signals. We could // use strsignal() to get signal names, but we don't use it to avoid // introducing yet another #ifdef complication. @@ -262,9 +238,10 @@ void FailureSignalHandler(int signal_number, // old value (value returned from __sync_val_compare_and_swap) is // different from the original value (in this case NULL). pthread_t* old_thread_id_pointer = - sync_val_compare_and_swap(&g_entered_thread_id_pointer, - static_cast(NULL), - &my_thread_id); + glog_internal_namespace_::sync_val_compare_and_swap( + &g_entered_thread_id_pointer, + static_cast(NULL), + &my_thread_id); if (old_thread_id_pointer != NULL) { // We've already entered the signal handler. What should we do? if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) { diff --git a/src/signalhandler_unittest.cc b/src/signalhandler_unittest.cc index 5dc3b68..48fc713 100644 --- a/src/signalhandler_unittest.cc +++ b/src/signalhandler_unittest.cc @@ -27,7 +27,7 @@ void WriteToStdout(const char* data, int size) { } int main(int argc, char **argv) { -#ifdef HAVE_STACKTRACE +#if defined(HAVE_STACKTRACE) && defined(HAVE_SYMBOLIZE) InitGoogleLogging(argv[0]); InstallFailureSignalHandler(); const std::string command = argc > 1 ? argv[1] : "none"; diff --git a/src/signalhandler_unittest.sh b/src/signalhandler_unittest.sh index b139a5e..ef30450 100755 --- a/src/signalhandler_unittest.sh +++ b/src/signalhandler_unittest.sh @@ -35,6 +35,13 @@ if [ x`$BINARY` != 'xOK' ]; then exit 0 fi +# The PC cannot be obtained in signal handlers on PowerPC correctly. +# We just skip the test for PowerPC. +if [ x`uname -p` = x"powerpc" ]; then + echo "PASS (We don't test the signal handler on PowerPC.)" + exit 0 +fi + # Test for a case the program kills itself by SIGSEGV. $BINARY segv 2> signalhandler.out1 for pattern in SIGSEGV 0xdead main "Aborted at [0-9]"; do diff --git a/src/stacktrace.h b/src/stacktrace.h index d729880..39ec9f3 100644 --- a/src/stacktrace.h +++ b/src/stacktrace.h @@ -11,40 +11,6 @@ _START_GOOGLE_NAMESPACE_ -// Skips the most recent "skip_count" stack frames (also skips the -// frame generated for the "GetStackFrames" routine itself), and then -// records the pc values for up to the next "max_depth" frames in -// "pcs", and the corresponding stack frame sizes in "sizes". Returns -// the number of values recorded in "pcs"/"sizes". -// -// Example: -// main() { foo(); } -// foo() { bar(); } -// bar() { -// void* pcs[10]; -// int sizes[10]; -// int depth = GetStackFrames(pcs, sizes, 10, 1); -// } -// -// The GetStackFrames call will skip the frame for "bar". It will -// return 2 and will produce pc values that map to the following -// procedures: -// pcs[0] foo -// pcs[1] main -// (Actually, there may be a few more entries after "main" to account for -// startup procedures.) -// And corresponding stack frame sizes will also be recorded: -// sizes[0] 16 -// sizes[1] 16 -// (Stack frame sizes of 16 above are just for illustration purposes.) -// Stack frame sizes of 0 or less indicate that those frame sizes couldn't -// be identified. -// -// This routine may return fewer stack frame entries than are -// available. Also note that "pcs" and "sizes" must both be non-NULL. -extern int GetStackFrames(void** pcs, int* sizes, int max_depth, - int skip_count); - // This is similar to the GetStackFrames routine, except that it returns // the stack trace only, and not the stack frame sizes as well. // Example: diff --git a/src/stacktrace_framesizes_unittest.cc b/src/stacktrace_framesizes_unittest.cc deleted file mode 100644 index 58e893d..0000000 --- a/src/stacktrace_framesizes_unittest.cc +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2007 Google Inc. All Rights Reserved. -// Author: Raksit Ashok -// -// Unit test for the GetStackFrames function in stacktrace.cc. - -#include -#include "glog/logging.h" -#include "base/commandlineflags.h" -#include "stacktrace.h" -#include "config.h" -#include "utilities.h" - -using std::min; -using namespace GOOGLE_NAMESPACE; - -#ifdef HAVE_STACKTRACE - -// Obtain a backtrace of the stack frame sizes, verify that they look sane. - -//-----------------------------------------------------------------------// -int CheckFrameSizesLeaf(int32* i); // 8KB frame size. -int CheckFrameSizes2(int32* i); // 4KB -int CheckFrameSizes1(int32* i); // 2KB -int CheckFrameSizes(int32* i); // 1KB -//-----------------------------------------------------------------------// - -// The expected frame-sizes in the backtrace. -const int BACKTRACE_STEPS = 4; -int expected_frame_sizes[BACKTRACE_STEPS] = { - 1 << 13, - 1 << 12, - 1 << 11, - 1 << 10, -}; - -//-----------------------------------------------------------------------// - -void CheckFrameSizeIsOk(int actual_frame_size, int ref_frame_size) { - // Assume upto 512 bytes of miscellaneous stuff in CheckFrameSizes* frames. - const int misc_frame_size = 512; - CHECK_GE(actual_frame_size, ref_frame_size); - CHECK_LE(actual_frame_size, ref_frame_size + misc_frame_size); -} - -//-----------------------------------------------------------------------// - -int ATTRIBUTE_NOINLINE CheckFrameSizesLeaf(int32 *i) { - const int DEPTH = 10; - void* pcs[DEPTH]; - int frame_sizes[DEPTH]; - int size; - int32 j[2048]; // 8KB. - for (int k = 0; k < 2048; k++) j[k] = k + i[k % 1024]; - - for (int depth = 0; depth < DEPTH; depth++) { - size = GetStackFrames(pcs, frame_sizes, depth, 0); - printf("--- GetStackFrames(..., %d, 0) = %d\n", depth, size); - CHECK_LE(size, depth); - CHECK_GE(size, min(depth, BACKTRACE_STEPS)); - - for (int k = 0; k < size; k++) { - if (k < BACKTRACE_STEPS) - // GetStackFrames doesn't work correctly if we are using glibc's backtrace. -#ifndef HAVE_EXECINFO_H - CheckFrameSizeIsOk(frame_sizes[k], expected_frame_sizes[k]); -#endif - printf("frame_sizes[%d] = %d\n", k, frame_sizes[k]); - } - } - - int sum = 0; - for (int k = 0; k < 2048; k++) sum += j[k]; - return sum; -} - -//-----------------------------------------------------------------------// - -/* Dummy functions to make the frame-size backtrace more interesting. */ -int ATTRIBUTE_NOINLINE CheckFrameSizes2(int32* i) { - int32 j[1024]; // 4KB. - for (int k = 0; k < 1024; k++) j[k] = k + i[k % 512]; - return CheckFrameSizesLeaf(j) + j[512]; -} - -int ATTRIBUTE_NOINLINE CheckFrameSizes1(int32* i) { - int32 j[512]; // 2KB. - for (int k = 0; k < 512; k++) j[k] = k + i[k % 256]; - return CheckFrameSizes2(j) + j[256]; -} - -int ATTRIBUTE_NOINLINE CheckFrameSizes(int32* i) { - int32 j[256]; // 1KB. - for (int k = 0; k < 256; k++) j[k] = k + i[k]; - return CheckFrameSizes1(j) + j[128]; -} - -//-----------------------------------------------------------------------// - -int main(int argc, char ** argv) { - FLAGS_logtostderr = true; - InitGoogleLogging(argv[0]); - - int32 i[256]; // 1KB. - for (int j = 0; j < 256; j++) i[j] = j; - - int ret = CheckFrameSizes(i); - - printf("CheckFrameSizes returned: %d\n", ret); - - printf("PASS\n"); - return 0; -} - -#else -int main() { - printf("PASS (no stacktrace support)\n"); - return 0; -} -#endif // HAVE_STACKTRACE diff --git a/src/stacktrace_generic-inl.h b/src/stacktrace_generic-inl.h index 27db893..a4b240d 100644 --- a/src/stacktrace_generic-inl.h +++ b/src/stacktrace_generic-inl.h @@ -30,52 +30,4 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return result_count; } -// If you change this function, also change GetStackTrace above: -// -// This GetStackFrames routine shares a lot of code with GetStackTrace -// above. This code could have been refactored into a common routine, -// and then both GetStackTrace/GetStackFrames could call that routine. -// There are two problems with that: -// -// (1) The performance of the refactored-code suffers substantially - the -// refactored needs to be able to record the stack trace when called -// from GetStackTrace, and both the stack trace and stack frame sizes, -// when called from GetStackFrames - this introduces enough new -// conditionals that GetStackTrace performance can degrade by as much -// as 50%. -// -// (2) Whether the refactored routine gets inlined into GetStackTrace and -// GetStackFrames depends on the compiler, and we can't guarantee the -// behavior either-way, even with "__attribute__ ((always_inline))" -// or "__attribute__ ((noinline))". But we need this guarantee or the -// frame counts may be off by one. -// -// Both (1) and (2) can be addressed without this code duplication, by -// clever use of template functions, and by defining GetStackTrace and -// GetStackFrames as macros that expand to these template functions. -// However, this approach comes with its own set of problems - namely, -// macros and preprocessor trouble - for example, if GetStackTrace -// and/or GetStackFrames is ever defined as a member functions in some -// class, we are in trouble. -int GetStackFrames(void** pcs, int* sizes, int max_depth, int skip_count) { - static const int kStackLength = 64; - void * stack[kStackLength]; - int size; - - size = backtrace(stack, kStackLength); - skip_count++; // we want to skip the current frame as well - int result_count = size - skip_count; - if (result_count < 0) - result_count = 0; - if (result_count > max_depth) - result_count = max_depth; - for (int i = 0; i < result_count; i++) - pcs[i] = stack[i + skip_count]; - - // No implementation for finding out the stack frame sizes yet. - memset(sizes, 0, sizeof(*sizes) * result_count); - - return result_count; -} - _END_GOOGLE_NAMESPACE_ diff --git a/src/stacktrace_libunwind-inl.h b/src/stacktrace_libunwind-inl.h index f927a57..37fa13e 100644 --- a/src/stacktrace_libunwind-inl.h +++ b/src/stacktrace_libunwind-inl.h @@ -5,23 +5,25 @@ // // Produce stack trace using libunwind +#include "utilities.h" + extern "C" { +#define UNW_LOCAL_ONLY #include } -#include "base/stacktrace.h" -#include "base/raw_logging.h" -#include "base/spinlock.h" +#include "glog/raw_logging.h" +#include "stacktrace.h" _START_GOOGLE_NAMESPACE_ // Sometimes, we can try to get a stack trace from within a stack -// trace, because libunwind can call mmap/sbrk (maybe indirectly via -// malloc), and that mmap gets trapped and causes a stack-trace -// request. If were to try to honor that recursive request, we'd end -// up with infinite recursion or deadlock. Luckily, it's safe to -// ignore those subsequent traces. In such cases, we return 0 to -// indicate the situation. -static SpinLock libunwind_lock(SpinLock::LINKER_INITIALIZED); +// trace, because libunwind can call mmap (maybe indirectly via an +// internal mmap based memory allocator), and that mmap gets trapped +// and causes a stack-trace request. If were to try to honor that +// recursive request, we'd end up with infinite recursion or deadlock. +// Luckily, it's safe to gnore those subsequent traces. In such cases, +// we return 0 to indicate the situation. +static bool g_now_entering = false; // If you change this function, also change GetStackFrames below. int GetStackTrace(void** result, int max_depth, int skip_count) { @@ -30,7 +32,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { unw_cursor_t cursor; unw_context_t uc; - if (!libunwind_lock.TryLock()) { + if (sync_val_compare_and_swap(&g_now_entering, false, true)) { return 0; } @@ -52,75 +54,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { break; } - libunwind_lock.Unlock(); - return n; -} - -// If you change this function, also change GetStackTrace above: -// -// This GetStackFrames routine shares a lot of code with GetStackTrace -// above. This code could have been refactored into a common routine, -// and then both GetStackTrace/GetStackFrames could call that routine. -// There are two problems with that: -// -// (1) The performance of the refactored-code suffers substantially - the -// refactored needs to be able to record the stack trace when called -// from GetStackTrace, and both the stack trace and stack frame sizes, -// when called from GetStackFrames - this introduces enough new -// conditionals that GetStackTrace performance can degrade by as much -// as 50%. -// -// (2) Whether the refactored routine gets inlined into GetStackTrace and -// GetStackFrames depends on the compiler, and we can't guarantee the -// behavior either-way, even with "__attribute__ ((always_inline))" -// or "__attribute__ ((noinline))". But we need this guarantee or the -// frame counts may be off by one. -// -// Both (1) and (2) can be addressed without this code duplication, by -// clever use of template functions, and by defining GetStackTrace and -// GetStackFrames as macros that expand to these template functions. -// However, this approach comes with its own set of problems - namely, -// macros and preprocessor trouble - for example, if GetStackTrace -// and/or GetStackFrames is ever defined as a member functions in some -// class, we are in trouble. -int GetStackFrames(void** pcs, int* sizes, int max_depth, int skip_count) { - void *ip; - int n = 0; - unw_cursor_t cursor; - unw_context_t uc; - unw_word_t sp = 0, next_sp = 0; - - if (!libunwind_lock.TryLock()) { - return 0; - } - - unw_getcontext(&uc); - RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed"); - skip_count++; // Do not include the "GetStackFrames" frame - - while (skip_count--) { - if (unw_step(&cursor) <= 0 || - unw_get_reg(&cursor, UNW_REG_SP, &next_sp) < 0) { - goto out; - } - } - while (n < max_depth) { - sp = next_sp; - if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) - break; - if (unw_step(&cursor) <= 0 || - unw_get_reg(&cursor, UNW_REG_SP, &next_sp)) { - // We couldn't step any further (possibly because we reached _start). - // Provide the last good PC we've got, and get out. - sizes[n] = 0; - pcs[n++] = ip; - break; - } - sizes[n] = next_sp - sp; - pcs[n++] = ip; - } - out: - libunwind_lock.Unlock(); + g_now_entering = false; return n; } diff --git a/src/stacktrace_powerpc-inl.h b/src/stacktrace_powerpc-inl.h index 82ce1ab..2f57f9a 100644 --- a/src/stacktrace_powerpc-inl.h +++ b/src/stacktrace_powerpc-inl.h @@ -101,82 +101,4 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return n; } -// If you change this function, also change GetStackTrace above: -// -// This GetStackFrames routine shares a lot of code with GetStackTrace -// above. This code could have been refactored into a common routine, -// and then both GetStackTrace/GetStackFrames could call that routine. -// There are two problems with that: -// -// (1) The performance of the refactored-code suffers substantially - the -// refactored needs to be able to record the stack trace when called -// from GetStackTrace, and both the stack trace and stack frame sizes, -// when called from GetStackFrames - this introduces enough new -// conditionals that GetStackTrace performance can degrade by as much -// as 50%. -// -// (2) Whether the refactored routine gets inlined into GetStackTrace and -// GetStackFrames depends on the compiler, and we can't guarantee the -// behavior either-way, even with "__attribute__ ((always_inline))" -// or "__attribute__ ((noinline))". But we need this guarantee or the -// frame counts may be off by one. -// -// Both (1) and (2) can be addressed without this code duplication, by -// clever use of template functions, and by defining GetStackTrace and -// GetStackFrames as macros that expand to these template functions. -// However, this approach comes with its own set of problems - namely, -// macros and preprocessor trouble - for example, if GetStackTrace -// and/or GetStackFrames is ever defined as a member functions in some -// class, we are in trouble. -int GetStackFrames(void** pcs, int *sizes, int max_depth, int skip_count) { - void **sp; -#ifdef __APPLE__ - __asm__ volatile ("mr %0,r1" : "=r" (sp)); -#else - __asm__ volatile ("mr %0,1" : "=r" (sp)); -#endif - - StacktracePowerPCDummyFunction(); - // Note we do *not* increment skip_count here for the SYSV ABI. If - // we did, the list of stack frames wouldn't properly match up with - // the list of return addresses. Note this means the top pc entry - // is probably bogus for linux/ppc (and other SYSV-ABI systems). - - int n = 0; - while (sp && n < max_depth) { - // The GetStackFrames routine is called when we are in some - // informational context (the failure signal handler for example). - // Use the non-strict unwinding rules to produce a stack trace - // that is as complete as possible (even if it contains a few bogus - // entries in some rare cases). - void **next_sp = NextStackFrame(sp); - if (skip_count > 0) { - skip_count--; - } else { -#if defined(_CALL_AIX) || defined(_CALL_DARWIN) - pcs[n++] = *(sp+2); -#elif defined(_CALL_SYSV) - pcs[n++] = *(sp+1); -#elif defined(__APPLE__) || (defined(__linux) && defined(__PPC64__)) - // This check is in case the compiler doesn't define _CALL_AIX/etc. - pcs[n++] = *(sp+2); -#elif defined(__linux) - // This check is in case the compiler doesn't define _CALL_SYSV. - pcs[n++] = *(sp+1); -#else -#error Need to specify the PPC ABI for your archiecture. -#endif - if (next_sp > sp) { - sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; - } else { - // A frame-size of 0 is used to indicate unknown frame size. - sizes[n] = 0; - } - n++; - } - sp = next_sp; - } - return n; -} - _END_GOOGLE_NAMESPACE_ diff --git a/src/stacktrace_unittest.cc b/src/stacktrace_unittest.cc index 015579f..a3a026c 100644 --- a/src/stacktrace_unittest.cc +++ b/src/stacktrace_unittest.cc @@ -93,6 +93,9 @@ void CheckStackTraceLeaf(void) { CheckRetAddrIsInFunction(stack[i], expected_stack[i]); printf("OK\n"); } + + // Check if the second stacktrace returns the same size. + CHECK_EQ(size, GetStackTrace(stack, STACK_LEN, 0)); } //-----------------------------------------------------------------------// diff --git a/src/stacktrace_x86-inl.h b/src/stacktrace_x86-inl.h index 676ce35..7a06005 100644 --- a/src/stacktrace_x86-inl.h +++ b/src/stacktrace_x86-inl.h @@ -110,88 +110,4 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return n; } -// If you change this function, also change GetStackTrace above: -// -// This GetStackFrames routine shares a lot of code with GetStackTrace -// above. This code could have been refactored into a common routine, -// and then both GetStackTrace/GetStackFrames could call that routine. -// There are two problems with that: -// -// (1) The performance of the refactored-code suffers substantially - the -// refactored needs to be able to record the stack trace when called -// from GetStackTrace, and both the stack trace and stack frame sizes, -// when called from GetStackFrames - this introduces enough new -// conditionals that GetStackTrace performance can degrade by as much -// as 50%. -// -// (2) Whether the refactored routine gets inlined into GetStackTrace and -// GetStackFrames depends on the compiler, and we can't guarantee the -// behavior either-way, even with "__attribute__ ((always_inline))" -// or "__attribute__ ((noinline))". But we need this guarantee or the -// frame counts may be off by one. -// -// Both (1) and (2) can be addressed without this code duplication, by -// clever use of template functions, and by defining GetStackTrace and -// GetStackFrames as macros that expand to these template functions. -// However, this approach comes with its own set of problems - namely, -// macros and preprocessor trouble - for example, if GetStackTrace -// and/or GetStackFrames is ever defined as a member functions in some -// class, we are in trouble. -int GetStackFrames(void** pcs, int* sizes, int max_depth, int skip_count) { - void **sp; -#ifdef __i386__ - // Stack frame format: - // sp[0] pointer to previous frame - // sp[1] caller address - // sp[2] first argument - // ... - sp = (void **)&pcs - 2; -#endif - -#ifdef __x86_64__ - // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8 - unsigned long rbp; - // Move the value of the register %rbp into the local variable rbp. - // We need 'volatile' to prevent this instruction from getting moved - // around during optimization to before function prologue is done. - // An alternative way to achieve this - // would be (before this __asm__ instruction) to call Noop() defined as - // static void Noop() __attribute__ ((noinline)); // prevent inlining - // static void Noop() { asm(""); } // prevent optimizing-away - __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp)); - // Arguments are passed in registers on x86-64, so we can't just - // offset from &pcs - sp = (void **) rbp; -#endif - - int n = 0; - while (sp && n < max_depth) { - if (*(sp+1) == (void *)0) { - // In 64-bit code, we often see a frame that - // points to itself and has a return address of 0. - break; - } - // The GetStackFrames routine is called when we are in some - // informational context (the failure signal handler for example). - // Use the non-strict unwinding rules to produce a stack trace - // that is as complete as possible (even if it contains a few bogus - // entries in some rare cases). - void **next_sp = NextStackFrame(sp); - if (skip_count > 0) { - skip_count--; - } else { - pcs[n] = *(sp+1); - if (next_sp > sp) { - sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp; - } else { - // A frame-size of 0 is used to indicate unknown frame size. - sizes[n] = 0; - } - n++; - } - sp = next_sp; - } - return n; -} - _END_GOOGLE_NAMESPACE_ diff --git a/src/stacktrace_x86_64-inl.h b/src/stacktrace_x86_64-inl.h index 932b6c8..105da22 100644 --- a/src/stacktrace_x86_64-inl.h +++ b/src/stacktrace_x86_64-inl.h @@ -76,52 +76,4 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return targ.count; } -// If you change this function, also change GetStackTrace above: -// -// This GetStackFrames routine shares a lot of code with GetStackTrace -// above. This code could have been refactored into a common routine, -// and then both GetStackTrace/GetStackFrames could call that routine. -// There are two problems with that: -// -// (1) The performance of the refactored-code suffers substantially - the -// refactored needs to be able to record the stack trace when called -// from GetStackTrace, and both the stack trace and stack frame sizes, -// when called from GetStackFrames - this introduces enough new -// conditionals that GetStackTrace performance can degrade by as much -// as 50%. -// -// (2) Whether the refactored routine gets inlined into GetStackTrace and -// GetStackFrames depends on the compiler, and we can't guarantee the -// behavior either-way, even with "__attribute__ ((always_inline))" -// or "__attribute__ ((noinline))". But we need this guarantee or the -// frame counts may be off by one. -// -// Both (1) and (2) can be addressed without this code duplication, by -// clever use of template functions, and by defining GetStackTrace and -// GetStackFrames as macros that expand to these template functions. -// However, this approach comes with its own set of problems - namely, -// macros and preprocessor trouble - for example, if GetStackTrace -// and/or GetStackFrames is ever defined as a member functions in some -// class, we are in trouble. -int GetStackFrames(void** pcs, int* sizes, int max_depth, int skip_count) { - if (!ready_to_run) - return 0; - - trace_arg_t targ; - - skip_count += 1; // Do not include the "GetStackFrames" frame - - targ.result = pcs; - targ.max_depth = max_depth; - targ.skip_count = skip_count; - targ.count = 0; - - _Unwind_Backtrace(GetOneFrame, &targ); - - // No implementation for finding out the stack frame sizes yet. - memset(sizes, 0, sizeof(*sizes) * targ.count); - - return targ.count; -} - _END_GOOGLE_NAMESPACE_ diff --git a/src/symbolize_unittest.cc b/src/symbolize_unittest.cc index b11372d..f0040a2 100644 --- a/src/symbolize_unittest.cc +++ b/src/symbolize_unittest.cc @@ -3,6 +3,8 @@ // // Unit tests for functions in symbolize.cc. +#include "utilities.h" + #include #include @@ -10,7 +12,6 @@ #include "symbolize.h" #include "googletest.h" #include "config.h" -#include "utilities.h" using namespace std; using namespace GOOGLE_NAMESPACE; @@ -307,19 +308,17 @@ void ATTRIBUTE_NOINLINE TestWithReturnAddress() { int main(int argc, char **argv) { FLAGS_logtostderr = true; InitGoogleLogging(argv[0]); +#ifdef HAVE_SYMBOLIZE // 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); - // Symbolize() now only supports ELF binaries. - // The test makes sense only if __ELF__ is defined. -#ifndef __ELF__ - return 0; -#else TestWithPCInsideInlineFunction(); TestWithPCInsideNonInlineFunction(); TestWithReturnAddress(); return RUN_ALL_TESTS(); +#else + return 0; #endif } diff --git a/src/utilities.cc b/src/utilities.cc index 55bd595..1c4d52f 100644 --- a/src/utilities.cc +++ b/src/utilities.cc @@ -1,3 +1,6 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// Author: hamaji@google.com (Shinichiro Hamaji) + #include "utilities.h" #include @@ -105,7 +108,8 @@ static void DumpStackTraceAndExit() { abort(); } -#endif + +#endif // HAVE_STACKTRACE namespace glog_internal_namespace_ { @@ -179,3 +183,8 @@ void InitGoogleLogging(const char* argv0) { } _END_GOOGLE_NAMESPACE_ + +// Make an implementation of stacktrace compiled. +#ifdef STACKTRACE_H +# include STACKTRACE_H +#endif diff --git a/src/utilities.h b/src/utilities.h index c0fa5fb..1236fbe 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -1,3 +1,6 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// Author: hamaji@google.com (Shinichiro Hamaji) +// // Define utilties for glog internal usage. #ifndef UTILITIES_H__ @@ -40,13 +43,48 @@ #include "config.h" #include "glog/logging.h" -#if defined(HAVE_EXECINFO_H) -# define HAVE_STACKTRACE -#elif defined(STACKTRACE_WITH_FRAME_POINTER) +// There are three different ways we can try to get the stack trace: +// +// 1) The libunwind library. This is still in development, and as a +// separate library adds a new dependency, but doesn't need a frame +// pointer. It also doesn't call malloc. +// +// 2) Our hand-coded stack-unwinder. This depends on a certain stack +// layout, which is used by gcc (and those systems using a +// gcc-compatible ABI) on x86 systems, at least since gcc 2.95. +// It uses the frame pointer to do its work. +// +// 3) The gdb unwinder -- also the one used by the c++ exception code. +// It's obviously well-tested, but has a fatal flaw: it can call +// malloc() from the unwinder. This is a problem because we're +// trying to use the unwinder to instrument malloc(). +// +// Note: if you add a new implementation here, make sure it works +// correctly when GetStackTrace() is called with max_depth == 0. +// Some code may do that. + +#if defined(HAVE_LIB_UNWIND) +# define STACKTRACE_H "stacktrace_libunwind-inl.h" +#elif !defined(NO_FRAME_POINTER) +# if defined(__i386__) && __GNUC__ >= 2 +# define STACKTRACE_H "stacktrace_x86-inl.h" +# elif defined(__x86_64__) && __GNUC__ >= 2 +# define STACKTRACE_H "stacktrace_x86_64-inl.h" +# elif ((__ppc__) || defined(__PPC__)) && __GNUC__ >= 2 +# define STACKTRACE_H "stacktrace_powerpc-inl.h" +# endif +#endif + +#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_H) +# define STACKTRACE_H "stacktrace_generic-inl.h" +#endif + +#if defined(STACKTRACE_H) # define HAVE_STACKTRACE #endif -#if defined(__ELF__) // defined by gcc on Linux +// defined by gcc +#if defined(__ELF__) && defined(OS_LINUX) # define HAVE_SYMBOLIZE #elif defined(OS_MACOSX) && defined(HAVE_DLADDR) // Use dladdr to symbolize. @@ -78,7 +116,36 @@ int32 GetMainThreadPid(); const std::string& MyUserName(); +// Wrapper of __sync_val_compare_and_swap. If the GCC extension isn't +// defined, we try the CPU specific logics (we only support x86 and +// x86_64 for now) first, then use a naive implementation, which has a +// race condition. +template +inline T sync_val_compare_and_swap(T* ptr, T oldval, T newval) { +#if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP) + return __sync_val_compare_and_swap(ptr, oldval, newval); +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + T ret; + __asm__ __volatile__("lock; cmpxchg %1, (%2);" + :"=a"(ret) + // GCC may produces %sil or %dil for + // constraint "r", but some of apple's gas + // dosn't know the 8 bit registers. + // We use "q" to avoid these registers. + :"q"(newval), "q"(ptr), "a"(oldval) + :"memory", "cc"); + return ret; +#else + T ret = *ptr; + if (ret == oldval) { + *ptr = newval; + } + return ret; +#endif } + +} // namespace glog_internal_namespace_ + _END_GOOGLE_NAMESPACE_ using namespace GOOGLE_NAMESPACE::glog_internal_namespace_; diff --git a/src/utilities_unittest.cc b/src/utilities_unittest.cc new file mode 100644 index 0000000..cde2baa --- /dev/null +++ b/src/utilities_unittest.cc @@ -0,0 +1,21 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// Author: hamaji@google.com (Shinichiro Hamaji) + +#include "utilities.h" +#include "googletest.h" +#include "glog/logging.h" + +using namespace GOOGLE_NAMESPACE; + +TEST(sync_val_compare_and_swap, utilities) { + bool now_entering = false; + EXPECT_FALSE(sync_val_compare_and_swap(&now_entering, false, true)); + EXPECT_TRUE(sync_val_compare_and_swap(&now_entering, false, true)); + EXPECT_TRUE(sync_val_compare_and_swap(&now_entering, false, true)); +} + +int main(int argc, char **argv) { + InitGoogleLogging(argv[0]); + + CHECK_EQ(RUN_ALL_TESTS(), 0); +}