Re-organize the way to produce stacktrace.
author <shinichiro.hamaji@gmail.com> <>
Mon, 17 Nov 2008 07:58:10 +0000 (07:58 +0000)
committer <shinichiro.hamaji@gmail.com> <>
Mon, 17 Nov 2008 07:58:10 +0000 (07:58 +0000)
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

20 files changed:
Makefile.am
Makefile.in
configure
configure.ac
src/config.h.in
src/signalhandler.cc
src/signalhandler_unittest.cc
src/signalhandler_unittest.sh
src/stacktrace.h
src/stacktrace_framesizes_unittest.cc [deleted file]
src/stacktrace_generic-inl.h
src/stacktrace_libunwind-inl.h
src/stacktrace_powerpc-inl.h
src/stacktrace_unittest.cc
src/stacktrace_x86-inl.h
src/stacktrace_x86_64-inl.h
src/symbolize_unittest.cc
src/utilities.cc
src/utilities.h
src/utilities_unittest.cc [new file with mode: 0644]

index 469c986..5b55e0f 100644 (file)
@@ -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
 
index ffdfa82..c076f26 100644 (file)
@@ -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
 
index ae51b29..7a98f8e 100755 (executable)
--- 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 <<EOF
-#line 10191 "configure"
+#line 10192 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10288,7 +10289,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10291 "configure"
+#line 10292 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12689,11 +12690,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:12692: $lt_compile\"" >&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
 
 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
index 9434fd1..008289b 100644 (file)
@@ -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.
index 08c09c7..f73b9f7 100644 (file)
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the <libunwind.h> 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 <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
index 8e30297..3c89715 100644 (file)
@@ -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<typename T>
-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<pthread_t*>(NULL),
-                                &my_thread_id);
+      glog_internal_namespace_::sync_val_compare_and_swap(
+          &g_entered_thread_id_pointer,
+          static_cast<pthread_t*>(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)) {
index 5dc3b68..48fc713 100644 (file)
@@ -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";
index b139a5e..ef30450 100755 (executable)
@@ -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
index d729880..39ec9f3 100644 (file)
 
 _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 (file)
index 58e893d..0000000
+++ /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 <stdio.h>
-#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
index 27db893..a4b240d 100644 (file)
@@ -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_
index f927a57..37fa13e 100644 (file)
@@ -5,23 +5,25 @@
 //
 // Produce stack trace using libunwind
 
+#include "utilities.h"
+
 extern "C" {
+#define UNW_LOCAL_ONLY
 #include <libunwind.h>
 }
-#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;
 }
 
index 82ce1ab..2f57f9a 100644 (file)
@@ -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<false>(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_
index 015579f..a3a026c 100644 (file)
@@ -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));
 }
 
 //-----------------------------------------------------------------------//
index 676ce35..7a06005 100644 (file)
@@ -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<false>(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_
index 932b6c8..105da22 100644 (file)
@@ -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_
index b11372d..f0040a2 100644 (file)
@@ -3,6 +3,8 @@
 //
 // Unit tests for functions in symbolize.cc.
 
+#include "utilities.h"
+
 #include <signal.h>
 #include <iostream>
 
@@ -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
 }
 
index 55bd595..1c4d52f 100644 (file)
@@ -1,3 +1,6 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+// Author: hamaji@google.com (Shinichiro Hamaji)
+
 #include "utilities.h"
 
 #include <signal.h>
@@ -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
index c0fa5fb..1236fbe 100644 (file)
@@ -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__
 #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<typename T>
+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 (file)
index 0000000..cde2baa
--- /dev/null
@@ -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);
+}