diff --git a/CMakeLists.txt b/CMakeLists.txt index be281cdce..5a0b1c056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,7 @@ check_type_size (ssize_t HAVE_SSIZE_T LANGUAGE CXX) check_cxx_symbol_exists (dladdr dlfcn.h HAVE_DLADDR) check_cxx_symbol_exists (fcntl fcntl.h HAVE_FCNTL) +check_cxx_symbol_exists (posix_fadvise fcntl.h HAVE_POSIX_FADVISE) check_cxx_symbol_exists (pread unistd.h HAVE_PREAD) check_cxx_symbol_exists (pwrite unistd.h HAVE_PWRITE) check_cxx_symbol_exists (sigaction csignal HAVE_SIGACTION) @@ -364,6 +365,8 @@ set (GLOG_SRCS src/logging.cc src/raw_logging.cc src/signalhandler.cc + src/stacktrace.cc + src/stacktrace.h src/symbolize.cc src/symbolize.h src/utilities.cc diff --git a/bazel/glog.bzl b/bazel/glog.bzl index 30dafa472..10cf3d2b0 100644 --- a/bazel/glog.bzl +++ b/bazel/glog.bzl @@ -48,8 +48,6 @@ def glog_library(with_gflags = 1, **kwargs): common_copts = [ "-std=c++14", - "-DGLOG_BAZEL_BUILD", - "-DHAVE_STRING_H", "-I%s/glog_internal" % gendir, ] + (["-DGLOG_USE_GFLAGS"] if with_gflags else []) @@ -74,6 +72,7 @@ def glog_library(with_gflags = 1, **kwargs): "-DGLOG_EXPORT=__attribute__((visibility(\\\"default\\\")))", "-DGLOG_NO_EXPORT=__attribute__((visibility(\\\"default\\\")))", "-DHAVE_MODE_T", + "-DHAVE_POSIX_FADVISE", "-DHAVE_SSIZE_T", "-DHAVE_SYS_TYPES_H", # For src/utilities.cc. @@ -102,10 +101,11 @@ def glog_library(with_gflags = 1, **kwargs): windows_only_copts = [ # Override -DGLOG_EXPORT= from the cc_library's defines. "-DGLOG_EXPORT=__declspec(dllexport)", - "-DGLOG_NO_EXPORT=", "-DGLOG_NO_ABBREVIATED_SEVERITIES", + "-DGLOG_NO_EXPORT=", "-DGLOG_USE_WINDOWS_PORT", "-DHAVE__CHSIZE_S", + "-DHAVE_DBGHELP", "-I" + src_windows, ] @@ -115,7 +115,6 @@ def glog_library(with_gflags = 1, **kwargs): ] windows_only_srcs = [ - "src/glog/log_severity.h", "src/windows/dirent.h", "src/windows/port.cc", "src/windows/port.h", @@ -127,13 +126,15 @@ def glog_library(with_gflags = 1, **kwargs): # GLOG_EXPORT is normally set by export.h, but that's not # generated for Bazel. "@bazel_tools//src/conditions:windows": [ - "GLOG_EXPORT=", "GLOG_DEPRECATED=__declspec(deprecated)", + "GLOG_EXPORT=", "GLOG_NO_ABBREVIATED_SEVERITIES", + "GLOG_NO_EXPORT=", ], "//conditions:default": [ "GLOG_DEPRECATED=__attribute__((deprecated))", "GLOG_EXPORT=__attribute__((visibility(\\\"default\\\")))", + "GLOG_NO_EXPORT=__attribute__((visibility(\\\"default\\\")))", ], }) @@ -171,6 +172,8 @@ def glog_library(with_gflags = 1, **kwargs): "src/logging.cc", "src/raw_logging.cc", "src/signalhandler.cc", + "src/stacktrace.cc", + "src/stacktrace.h", "src/stacktrace_generic-inl.h", "src/stacktrace_libunwind-inl.h", "src/stacktrace_powerpc-inl.h", @@ -180,6 +183,7 @@ def glog_library(with_gflags = 1, **kwargs): "src/symbolize.cc", "src/symbolize.h", "src/utilities.cc", + "src/utilities.h", "src/vlog_is_on.cc", ] + select({ "@bazel_tools//src/conditions:windows": windows_only_srcs, diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in index dac54d7c9..f60570a44 100644 --- a/src/config.h.cmake.in +++ b/src/config.h.cmake.in @@ -31,6 +31,9 @@ /* Define if you have the 'pread' function */ #cmakedefine HAVE_PREAD +/* Define if you have the 'posix_fadvise' function in */ +#cmakedefine HAVE_POSIX_FADVISE + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PWD_H diff --git a/src/demangle.cc b/src/demangle.cc index b9ca47b30..9902c1e10 100644 --- a/src/demangle.cc +++ b/src/demangle.cc @@ -37,7 +37,6 @@ #include "demangle.h" #include -#include #include #include @@ -52,6 +51,7 @@ #endif namespace google { +inline namespace glog_internal_namespace_ { #if !defined(GLOG_OS_WINDOWS) && !defined(HAVE___CXA_DEMANGLE) namespace { @@ -1359,4 +1359,5 @@ bool Demangle(const char* mangled, char* out, size_t out_size) { #endif } +} // namespace glog_internal_namespace_ } // namespace google diff --git a/src/demangle.h b/src/demangle.h index 75c6fc813..d63c7b08a 100644 --- a/src/demangle.h +++ b/src/demangle.h @@ -67,19 +67,28 @@ // C++ ABI in the future. // -#ifndef BASE_DEMANGLE_H_ -#define BASE_DEMANGLE_H_ +#ifndef GLOG_INTERNAL_DEMANGLE_H +#define GLOG_INTERNAL_DEMANGLE_H -#include "config.h" -#include "glog/logging.h" +#include + +#if defined(GLOG_USE_GLOG_EXPORT) +# include "glog/export.h" +#endif + +#if !defined(GLOG_NO_EXPORT) +# error "demangle.h" was not included correctly. +#endif namespace google { +inline namespace glog_internal_namespace_ { // Demangle "mangled". On success, return true and write the // demangled symbol name to "out". Otherwise, return false. // "out" is modified even if demangling is unsuccessful. -bool GLOG_EXPORT Demangle(const char* mangled, char* out, size_t out_size); +bool GLOG_NO_EXPORT Demangle(const char* mangled, char* out, size_t out_size); +} // namespace glog_internal_namespace_ } // namespace google -#endif // BASE_DEMANGLE_H_ +#endif // GLOG_INTERNAL_DEMANGLE_H diff --git a/src/glog/log_severity.h b/src/glog/log_severity.h index ad588161b..1fb6a4c01 100644 --- a/src/glog/log_severity.h +++ b/src/glog/log_severity.h @@ -95,8 +95,6 @@ constexpr int NUM_SEVERITIES = 4; # define DFATAL_LEVEL FATAL #endif -extern GLOG_EXPORT const char* const LogSeverityNames[NUM_SEVERITIES]; - // NDEBUG usage helpers related to (RAW_)DCHECK: // // DEBUG_MODE is for small !NDEBUG uses like diff --git a/src/glog/logging.h b/src/glog/logging.h index 769183d94..f4d6b4dfe 100644 --- a/src/glog/logging.h +++ b/src/glog/logging.h @@ -56,7 +56,7 @@ # include "glog/export.h" #endif -#if !defined(GLOG_EXPORT) +#if !defined(GLOG_EXPORT) || !defined(GLOG_NO_EXPORT) # error was not included correctly. See the documention for how to consume the library. #endif @@ -580,13 +580,16 @@ class LogSink; // defined below LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \ << "Check failed: " #condition " " +namespace logging { +namespace internal { + // A container for a string pointer which can be evaluated to a bool - // true iff the pointer is nullptr. struct CheckOpString { CheckOpString(std::string* str) : str_(str) {} // No destructor: if str_ is non-nullptr, we're about to LOG(FATAL), // so there's no point in cleaning up str_. - operator bool() const { + explicit operator bool() const noexcept { return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != nullptr); } std::string* str_; @@ -616,18 +619,14 @@ inline unsigned long long GetReferenceableValue(unsigned long long t) { // This is a dummy class to define the following operator. struct DummyClassToDefineOperator {}; -} // namespace google - // Define global operator<< to declare using ::operator<<. // This declaration will allow use to use CHECK macros for user // defined classes which have operator<< (e.g., stl_logging.h). inline std::ostream& operator<<(std::ostream& out, - const google::DummyClassToDefineOperator&) { + const DummyClassToDefineOperator&) { return out; } -namespace google { - // This formats a value for a failing CHECK_XX statement. Ordinarily, // it uses the definition for operator<<, with a few special cases below. template @@ -660,8 +659,6 @@ std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) #endif ; -namespace base { - // A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX // statement. See MakeCheckOpString for sample usage. Other // approaches were considered: use of a template method (e.g., @@ -685,12 +682,10 @@ class GLOG_EXPORT CheckOpMessageBuilder { std::ostringstream* stream_; }; -} // namespace base - template std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) { - base::CheckOpMessageBuilder comb(exprtext); + CheckOpMessageBuilder comb(exprtext); MakeCheckOpValueString(comb.ForVar1(), v1); MakeCheckOpValueString(comb.ForVar2(), v2); return comb.NewString(); @@ -717,13 +712,13 @@ std::string* MakeCheckOpString(const T1& v1, const T2& v2, // base/logging.h provides its own #defines for the simpler names EQ, NE, etc. // This happens if, for example, those are used as token names in a // yacc grammar. -DEFINE_CHECK_OP_IMPL(Check_EQ, - ==) // Compilation error with CHECK_EQ(nullptr, x)? -DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == nullptr) instead. +DEFINE_CHECK_OP_IMPL(Check_EQ, ==) +DEFINE_CHECK_OP_IMPL(Check_NE, !=) DEFINE_CHECK_OP_IMPL(Check_LE, <=) DEFINE_CHECK_OP_IMPL(Check_LT, <) DEFINE_CHECK_OP_IMPL(Check_GE, >=) DEFINE_CHECK_OP_IMPL(Check_GT, >) + #undef DEFINE_CHECK_OP_IMPL // Helper macro for binary operators. @@ -743,18 +738,23 @@ DEFINE_CHECK_OP_IMPL(Check_GT, >) // file is included). Save the current meaning now and use it // in the macro. typedef std::string _Check_string; -# define CHECK_OP_LOG(name, op, val1, val2, log) \ - while (google::_Check_string* _result = google::Check##name##Impl( \ - google::GetReferenceableValue(val1), \ - google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \ - log(__FILE__, __LINE__, google::CheckOpString(_result)).stream() +# define CHECK_OP_LOG(name, op, val1, val2, log) \ + while (google::logging::internal::_Check_string* _result = \ + google::logging::internal::Check##name##Impl( \ + google::logging::internal::GetReferenceableValue(val1), \ + google::logging::internal::GetReferenceableValue(val2), \ + #val1 " " #op " " #val2)) \ + log(__FILE__, __LINE__, google::logging::internal::CheckOpString(_result)) \ + .stream() #else // In optimized mode, use CheckOpString to hint to compiler that // the while condition is unlikely. -# define CHECK_OP_LOG(name, op, val1, val2, log) \ - while (google::CheckOpString _result = google::Check##name##Impl( \ - google::GetReferenceableValue(val1), \ - google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \ +# define CHECK_OP_LOG(name, op, val1, val2, log) \ + while (google::logging::internal::CheckOpString _result = \ + google::logging::internal::Check##name##Impl( \ + google::logging::internal::GetReferenceableValue(val1), \ + google::logging::internal::GetReferenceableValue(val2), \ + #val1 " " #op " " #val2)) \ log(__FILE__, __LINE__, _result).stream() #endif // STATIC_ANALYSIS, DCHECK_IS_ON() @@ -794,26 +794,32 @@ typedef std::string _Check_string; // Check that the input is non nullptr. This very useful in constructor // initializer lists. -#define CHECK_NOTNULL(val) \ - google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non nullptr", \ - (val)) +#define CHECK_NOTNULL(val) \ + google::logging::internal::CheckNotNull( \ + __FILE__, __LINE__, "'" #val "' Must be non nullptr", (val)) // Helper functions for string comparisons. // To avoid bloat, the definitions are in logging.cc. #define DECLARE_CHECK_STROP_IMPL(func, expected) \ GLOG_EXPORT std::string* Check##func##expected##Impl( \ const char* s1, const char* s2, const char* names); + DECLARE_CHECK_STROP_IMPL(strcmp, true) DECLARE_CHECK_STROP_IMPL(strcmp, false) DECLARE_CHECK_STROP_IMPL(strcasecmp, true) DECLARE_CHECK_STROP_IMPL(strcasecmp, false) + +} // namespace internal +} // namespace logging + #undef DECLARE_CHECK_STROP_IMPL // Helper macro for string comparisons. // Don't use this macro directly in your code, use CHECK_STREQ et al below. -#define CHECK_STROP(func, op, expected, s1, s2) \ - while (google::CheckOpString _result = google::Check##func##expected##Impl( \ - (s1), (s2), #s1 " " #op " " #s2)) \ +#define CHECK_STROP(func, op, expected, s1, s2) \ + while (google::logging::internal::CheckOpString _result = \ + google::logging::internal::Check##func##expected##Impl( \ + (s1), (s2), #s1 " " #op " " #s2)) \ LOG(FATAL) << *_result.str_ // String (char*) equality/inequality checks. @@ -1181,6 +1187,12 @@ class GLOG_EXPORT LogStreamBuf : public std::streambuf { } // namespace base_logging +namespace logging { +namespace internal { +struct GLOG_NO_EXPORT LogMessageData; +} // namespace internal +} // namespace logging + // // This class more or less represents a particular log message. You // create an instance of LogMessage and then stream stuff to it. @@ -1297,7 +1309,8 @@ class GLOG_EXPORT LogMessage { std::string* message); // A special constructor used for check failures - LogMessage(const char* file, int line, const CheckOpString& result); + LogMessage(const char* file, int line, + const logging::internal::CheckOpString& result); ~LogMessage(); @@ -1355,8 +1368,8 @@ class GLOG_EXPORT LogMessage { // We keep the data in a separate struct so that each instance of // LogMessage uses less stack space. - LogMessageData* allocated_; - LogMessageData* data_; + logging::internal::LogMessageData* allocated_; + logging::internal::LogMessageData* data_; LogMessageTime time_; friend class LogDestination; @@ -1371,7 +1384,8 @@ class GLOG_EXPORT LogMessage { class GLOG_EXPORT LogMessageFatal : public LogMessage { public: LogMessageFatal(const char* file, int line); - LogMessageFatal(const char* file, int line, const CheckOpString& result); + LogMessageFatal(const char* file, int line, + const logging::internal::CheckOpString& result); [[noreturn]] ~LogMessageFatal(); }; @@ -1388,22 +1402,6 @@ inline void LogAtLevel(LogSeverity severity, std::string const& msg) { #define LOG_AT_LEVEL(severity) \ google::LogMessage(__FILE__, __LINE__, severity).stream() -// Helper for CHECK_NOTNULL(). -// -// In C++11, all cases can be handled by a single function. Since the value -// category of the argument is preserved (also for rvalue references), -// member initializer lists like the one below will compile correctly: -// -// Foo() -// : x_(CHECK_NOTNULL(MethodReturningUniquePtr())) {} -template -T CheckNotNull(const char* file, int line, const char* names, T&& t) { - if (t == nullptr) { - LogMessageFatal(file, line, new std::string(names)); - } - return std::forward(t); -} - // Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This // only works if ostream is a LogStream. If the ostream is not a // LogStream you'll get an assert saying as much at runtime. @@ -1429,13 +1427,29 @@ class GLOG_EXPORT ErrnoLogMessage : public LogMessage { namespace logging { namespace internal { -class LogMessageVoidify { - public: - LogMessageVoidify() {} + +// Helper for CHECK_NOTNULL(). +// +// In C++11, all cases can be handled by a single function. Since the value +// category of the argument is preserved (also for rvalue references), +// member initializer lists like the one below will compile correctly: +// +// Foo() +// : x_(CHECK_NOTNULL(MethodReturningUniquePtr())) {} +template +T CheckNotNull(const char* file, int line, const char* names, T&& t) { + if (t == nullptr) { + LogMessageFatal(file, line, new std::string(names)); + } + return std::forward(t); +} + +struct LogMessageVoidify { // This has to be an operator with a precedence lower than << but // higher than ?: - void operator&(std::ostream&) {} + void operator&(std::ostream&) noexcept {} }; + } // namespace internal } // namespace logging @@ -1637,7 +1651,7 @@ class GLOG_EXPORT NullStream : public LogMessage::LogStream { // the overloaded NullStream::operator<< will not be invoked. NullStream(); NullStream(const char* /*file*/, int /*line*/, - const CheckOpString& /*result*/); + const logging::internal::CheckOpString& /*result*/); NullStream& stream(); private: diff --git a/src/glog/platform.h b/src/glog/platform.h index 3951f27c6..4aaf5b08f 100644 --- a/src/glog/platform.h +++ b/src/glog/platform.h @@ -52,6 +52,8 @@ # define GLOG_OS_OPENBSD #elif defined(__EMSCRIPTEN__) # define GLOG_OS_EMSCRIPTEN +#elif defined(__ANDROID__) +# define GLOG_OS_ANDROID #else // TODO(hamaji): Add other platforms. #error Platform not supported by glog. Please consider to contribute platform information by submitting a pull request on Github. diff --git a/src/googletest.h b/src/googletest.h index 0e81de012..971c5b401 100644 --- a/src/googletest.h +++ b/src/googletest.h @@ -51,12 +51,16 @@ #include #include -#include "utilities.h" +#include "config.h" #ifdef HAVE_UNISTD_H # include #endif +#if defined(GLOG_USE_WINDOWS_PORT) +# include "port.h" +#endif // defined(GLOG_USE_WINDOWS_PORT) #include "base/commandlineflags.h" +#include "utilities.h" #if __cplusplus < 201103L && !defined(_MSC_VER) # define GOOGLE_GLOG_THROW_BAD_ALLOC throw(std::bad_alloc) @@ -339,20 +343,20 @@ class CapturedStream { uncaptured_fd_; // where the stream was originally being sent to string filename_; // file where stream is being saved }; -static std::unique_ptr s_captured_streams[STDERR_FILENO + 1]; +static std::map> s_captured_streams; // Redirect a file descriptor to a file. -// fd - Should be STDOUT_FILENO or STDERR_FILENO +// fd - Should be stdout or stderr // filename - File where output should be stored static inline void CaptureTestOutput(int fd, const string& filename) { - CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO)); - CHECK(s_captured_streams[fd] == nullptr); + CHECK((fd == fileno(stdout)) || (fd == fileno(stderr))); + CHECK(s_captured_streams.find(fd) == s_captured_streams.end()); s_captured_streams[fd] = std::make_unique(fd, filename); } static inline void CaptureTestStdout() { - CaptureTestOutput(STDOUT_FILENO, FLAGS_test_tmpdir + "/captured.out"); + CaptureTestOutput(fileno(stdout), FLAGS_test_tmpdir + "/captured.out"); } static inline void CaptureTestStderr() { - CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err"); + CaptureTestOutput(fileno(stderr), FLAGS_test_tmpdir + "/captured.err"); } // Return the size (in bytes) of a file static inline size_t GetFileSize(FILE* file) { @@ -379,11 +383,11 @@ static inline string ReadEntireFile(FILE* file) { return std::string(content.data(), bytes_read); } -// Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when -// fd is STDERR_FILENO) as a string +// Get the captured stdout or stderr as a string static inline string GetCapturedTestOutput(int fd) { - CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO); - std::unique_ptr cap = std::move(s_captured_streams[fd]); + CHECK((fd == fileno(stdout)) || (fd == fileno(stderr))); + std::unique_ptr cap = std::move(s_captured_streams.at(fd)); + s_captured_streams.erase(fd); CHECK(cap) << ": did you forget CaptureTestStdout() or CaptureTestStderr()?"; // Make sure everything is flushed. @@ -398,7 +402,7 @@ static inline string GetCapturedTestOutput(int fd) { } // Get the captured stderr of a test as a string. static inline string GetCapturedTestStderr() { - return GetCapturedTestOutput(STDERR_FILENO); + return GetCapturedTestOutput(fileno(stderr)); } static const std::size_t kLoggingPrefixLength = 9; @@ -499,7 +503,9 @@ static inline void WriteToFile(const string& body, const string& file) { static inline bool MungeAndDiffTest(const string& golden_filename, CapturedStream* cap) { - if (cap == s_captured_streams[STDOUT_FILENO].get()) { + auto pos = s_captured_streams.find(fileno(stdout)); + + if (pos != s_captured_streams.end() && cap == pos->second.get()) { CHECK(cap) << ": did you forget CaptureTestStdout()?"; } else { CHECK(cap) << ": did you forget CaptureTestStderr()?"; @@ -535,12 +541,12 @@ static inline bool MungeAndDiffTest(const string& golden_filename, static inline bool MungeAndDiffTestStderr(const string& golden_filename) { return MungeAndDiffTest(golden_filename, - s_captured_streams[STDERR_FILENO].get()); + s_captured_streams.at(fileno(stderr)).get()); } static inline bool MungeAndDiffTestStdout(const string& golden_filename) { return MungeAndDiffTest(golden_filename, - s_captured_streams[STDOUT_FILENO].get()); + s_captured_streams.at(fileno(stdout)).get()); } // Save flags used from logging_unittest.cc. diff --git a/src/logging.cc b/src/logging.cc index a83ac697f..f9ffa703c 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -48,13 +48,11 @@ #include #include "config.h" +#include "glog/platform.h" #include "glog/raw_logging.h" +#include "stacktrace.h" #include "utilities.h" -#ifdef HAVE_STACKTRACE -# include "stacktrace.h" -#endif - #ifdef GLOG_OS_WINDOWS # include "windows/dirent.h" #else @@ -217,6 +215,7 @@ static bool TerminalSupportsColor() { namespace google { +GLOG_NO_EXPORT std::string StrError(int err); enum GLogColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; @@ -283,13 +282,15 @@ static uint32 MaxLogSize() { // is so that streaming can be done more efficiently. const size_t LogMessage::kMaxLogMessageLen = 30000; -struct LogMessage::LogMessageData { +namespace logging { +namespace internal { +struct LogMessageData { LogMessageData(); int preserved_errno_; // preserved errno // Buffer space; contains complete message text. char message_text_[LogMessage::kMaxLogMessageLen + 1]; - LogStream stream_; + LogMessage::LogStream stream_; LogSeverity severity_; // What level is this LogMessage logged at? int line_; // line number where logging call is. void (LogMessage::*send_method_)(); // Call this in destructor to send @@ -311,6 +312,8 @@ struct LogMessage::LogMessageData { LogMessageData(const LogMessageData&) = delete; void operator=(const LogMessageData&) = delete; }; +} // namespace internal +} // namespace logging // A mutex that allows only one thread to log at a time, to keep things from // getting jumbled. Some other very uncommon logging operations (like @@ -325,8 +328,7 @@ int64 LogMessage::num_messages_[NUM_SEVERITIES] = {0, 0, 0, 0}; // Globally disable log writing (if disk is full) static bool stop_writing = false; -const char* const LogSeverityNames[NUM_SEVERITIES] = {"INFO", "WARNING", - "ERROR", "FATAL"}; +const char* const LogSeverityNames[] = {"INFO", "WARNING", "ERROR", "FATAL"}; // Has the user called SetExitOnDFatal(true)? static bool exit_on_dfatal = true; @@ -547,7 +549,7 @@ class LogDestination { // Wait for all registered sinks via WaitTillSent // including the optional one in "data". - static void WaitForSinks(LogMessage::LogMessageData* data); + static void WaitForSinks(logging::internal::LogMessageData* data); static LogDestination* log_destination(LogSeverity severity); @@ -854,7 +856,8 @@ inline void LogDestination::LogToSinks(LogSeverity severity, } } -inline void LogDestination::WaitForSinks(LogMessage::LogMessageData* data) { +inline void LogDestination::WaitForSinks( + logging::internal::LogMessageData* data) { std::shared_lock l{sink_mutex_}; if (sinks_) { for (size_t i = sinks_->size(); i-- > 0;) { @@ -1266,10 +1269,7 @@ void LogFileObject::Write( uint32 this_drop_length = total_drop_length - dropped_mem_length_; if (this_drop_length >= (2U << 20U)) { // Only advise when >= 2MiB to drop -# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) - // 'posix_fadvise' introduced in API 21: - // * https://android.googlesource.com/platform/bionic/+/6880f936173081297be0dc12f687d341b86a4cfa/libc/libc.map.txt#732 -# else +# if defined(HAVE_POSIX_FADVISE) posix_fadvise( fileno(file_.get()), static_cast(dropped_mem_length_), static_cast(this_drop_length), POSIX_FADV_DONTNEED); @@ -1488,8 +1488,8 @@ bool LogCleaner::IsLogLastModifiedOver( static std::mutex fatal_msg_lock; static logging::internal::CrashReason crash_reason; static bool fatal_msg_exclusive = true; -static LogMessage::LogMessageData fatal_msg_data_exclusive; -static LogMessage::LogMessageData fatal_msg_data_shared; +static logging::internal::LogMessageData fatal_msg_data_exclusive; +static logging::internal::LogMessageData fatal_msg_data_shared; #ifdef GLOG_THREAD_LOCAL_STORAGE // Static thread-local log data space to use, because typically at most one @@ -1499,16 +1499,16 @@ static thread_local bool thread_data_available = true; # if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L // std::aligned_storage is deprecated in C++23 -alignas(LogMessage::LogMessageData) static thread_local std::byte - thread_msg_data[sizeof(LogMessage::LogMessageData)]; +alignas(logging::internal::LogMessageData) static thread_local std::byte + thread_msg_data[sizeof(logging::internal::LogMessageData)]; # else // !(defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L) static thread_local std::aligned_storage< - sizeof(LogMessage::LogMessageData), - alignof(LogMessage::LogMessageData)>::type thread_msg_data; + sizeof(logging::internal::LogMessageData), + alignof(logging::internal::LogMessageData)>::type thread_msg_data; # endif // defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L #endif // defined(GLOG_THREAD_LOCAL_STORAGE) -LogMessage::LogMessageData::LogMessageData() +logging::internal::LogMessageData::LogMessageData() : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {} LogMessage::LogMessage(const char* file, int line, LogSeverity severity, @@ -1518,7 +1518,8 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity, data_->stream_.set_ctr(ctr); } -LogMessage::LogMessage(const char* file, int line, const CheckOpString& result) +LogMessage::LogMessage(const char* file, int line, + const logging::internal::CheckOpString& result) : allocated_(nullptr) { Init(file, line, GLOG_FATAL, &LogMessage::SendToLog); stream() << "Check failed: " << (*result.str_) << " "; @@ -1564,13 +1565,13 @@ void LogMessage::Init(const char* file, int line, LogSeverity severity, // No need for locking, because this is thread local. if (thread_data_available) { thread_data_available = false; - data_ = new (&thread_msg_data) LogMessageData; + data_ = new (&thread_msg_data) logging::internal::LogMessageData; } else { - allocated_ = new LogMessageData(); + allocated_ = new logging::internal::LogMessageData(); data_ = allocated_; } #else // !defined(GLOG_THREAD_LOCAL_STORAGE) - allocated_ = new LogMessageData(); + allocated_ = new logging::internal::LogMessageData(); data_ = allocated_; #endif // defined(GLOG_THREAD_LOCAL_STORAGE) data_->first_fatal_ = false; @@ -1828,7 +1829,7 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) { LogDestination::WaitForSinks(data_); const char* message = "*** Check failure stack trace: ***\n"; - if (write(STDERR_FILENO, message, strlen(message)) < 0) { + if (write(fileno(stderr), message, strlen(message)) < 0) { // Ignore errors. } AlsoErrorWrite(GLOG_FATAL, @@ -1856,7 +1857,7 @@ GLOG_NO_EXPORT logging_fail_func_t g_logging_fail_func = NullStream::NullStream() : LogMessage::LogStream(message_buffer_, 2, 0) {} NullStream::NullStream(const char* /*file*/, int /*line*/, - const CheckOpString& /*result*/) + const logging::internal::CheckOpString& /*result*/) : LogMessage::LogStream(message_buffer_, 2, 0) {} NullStream& NullStream::stream() { return *this; } @@ -2455,6 +2456,8 @@ void TruncateStdoutStderr() { #endif } +namespace logging { +namespace internal { // Helper functions for string comparisons. #define DEFINE_CHECK_STROP_IMPL(name, func, expected) \ string* Check##func##expected##Impl(const char* s1, const char* s2, \ @@ -2475,6 +2478,8 @@ DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false) DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true) DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false) #undef DEFINE_CHECK_STROP_IMPL +} // namespace internal +} // namespace logging // glibc has traditionally implemented two incompatible versions of // strerror_r(). There is a poorly defined convention for picking the @@ -2541,7 +2546,6 @@ int posix_strerror_r(int err, char* buf, size_t len) { // A thread-safe replacement for strerror(). Returns a string describing the // given POSIX error code. -GLOG_NO_EXPORT string StrError(int err) { char buf[100]; int rc = posix_strerror_r(err, buf, sizeof(buf)); @@ -2555,7 +2559,7 @@ LogMessageFatal::LogMessageFatal(const char* file, int line) : LogMessage(file, line, GLOG_FATAL) {} LogMessageFatal::LogMessageFatal(const char* file, int line, - const CheckOpString& result) + const logging::internal::CheckOpString& result) : LogMessage(file, line, result) {} LogMessageFatal::~LogMessageFatal() { @@ -2563,7 +2567,8 @@ LogMessageFatal::~LogMessageFatal() { LogMessage::Fail(); } -namespace base { +namespace logging { +namespace internal { CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext) : stream_(new ostringstream) { @@ -2582,8 +2587,6 @@ string* CheckOpMessageBuilder::NewString() { return new string(stream_->str()); } -} // namespace base - template <> void MakeCheckOpValueString(std::ostream* os, const char& v) { if (v >= 32 && v <= 126) { @@ -2616,9 +2619,10 @@ void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& /*v*/) { (*os) << "nullptr"; } -void InitGoogleLogging(const char* argv0) { - glog_internal_namespace_::InitGoogleLoggingUtilities(argv0); -} +} // namespace internal +} // namespace logging + +void InitGoogleLogging(const char* argv0) { InitGoogleLoggingUtilities(argv0); } void InitGoogleLogging(const char* argv0, CustomPrefixCallback prefix_callback, void* prefix_callback_data) { @@ -2628,7 +2632,7 @@ void InitGoogleLogging(const char* argv0, CustomPrefixCallback prefix_callback, } void ShutdownGoogleLogging() { - glog_internal_namespace_::ShutdownGoogleLoggingUtilities(); + ShutdownGoogleLoggingUtilities(); LogDestination::DeleteLogDestinations(); logging_directories_list = nullptr; } diff --git a/src/logging_unittest.cc b/src/logging_unittest.cc index 09cabbf42..dde1fbf89 100644 --- a/src/logging_unittest.cc +++ b/src/logging_unittest.cc @@ -61,6 +61,7 @@ #include "glog/logging.h" #include "glog/raw_logging.h" #include "googletest.h" +#include "stacktrace.h" #include "utilities.h" #ifdef GLOG_USE_GFLAGS diff --git a/src/raw_logging.cc b/src/raw_logging.cc index 388cca00f..e1510cd82 100644 --- a/src/raw_logging.cc +++ b/src/raw_logging.cc @@ -33,29 +33,18 @@ #include #include +#include #include #include #include #include #include -#include "utilities.h" -#ifdef HAVE_UNISTD_H -# include // for close() and write() -#endif -#include // for open() - -#include - -#include "base/commandlineflags.h" #include "config.h" -#include "glog/logging.h" // To pick up flag settings etc. -#include "glog/raw_logging.h" -#ifdef HAVE_STACKTRACE -# include "stacktrace.h" +#ifdef HAVE_UNISTD_H +# include // for close() and write() #endif - #if defined(HAVE_SYSCALL_H) # include // for syscall() #elif defined(HAVE_SYS_SYSCALL_H) @@ -64,6 +53,12 @@ #ifdef HAVE_UNISTD_H # include #endif +#include // for open() + +#include "glog/logging.h" +#include "glog/raw_logging.h" +#include "stacktrace.h" +#include "utilities.h" #if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \ (!(defined(GLOG_OS_MACOSX)) && !(defined(GLOG_OS_OPENBSD))) && \ @@ -173,7 +168,7 @@ void RawLog__(LogSeverity severity, const char* file, int line, // NOTE: this format should match the specification in base/logging.h DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %s %s:%d] RAW: ", - LogSeverityNames[severity][0], sbuf.data(), + GetLogSeverityName(severity)[0], sbuf.data(), const_basename(const_cast(file)), line); // Record the position and size of the buffer after the prefix @@ -193,7 +188,7 @@ void RawLog__(LogSeverity severity, const char* file, int line, // avoiding FILE buffering (to avoid invoking malloc()), and bypassing // libc (to side-step any libc interception). // We write just once to avoid races with other invocations of RawLog__. - safe_write(STDERR_FILENO, buffer, strlen(buffer)); + safe_write(fileno(stderr), buffer, strlen(buffer)); if (severity == GLOG_FATAL) { std::call_once(crashed, [file, line, msg_start, msg_size] { crash_reason.filename = file; diff --git a/src/signalhandler.cc b/src/signalhandler.cc index 992fffb1f..c5bae598d 100644 --- a/src/signalhandler.cc +++ b/src/signalhandler.cc @@ -33,12 +33,15 @@ #include #include +#include #include #include #include #include +#include "config.h" #include "glog/logging.h" +#include "glog/platform.h" #include "stacktrace.h" #include "symbolize.h" #include "utilities.h" @@ -155,7 +158,7 @@ class MinimalFormatter { // Writes the given data with the size to the standard error. void WriteToStderr(const char* data, size_t size) { - if (write(STDERR_FILENO, data, size) < 0) { + if (write(fileno(stderr), data, size) < 0) { // Ignore errors. } } @@ -231,6 +234,7 @@ void DumpSignalInfo(int signal_number, siginfo_t* siginfo) { void DumpStackFrameInfo(const char* prefix, void* pc) { // Get the symbol name. const char* symbol = "(unknown)"; +#if defined(HAVE_SYMBOLIZE) char symbolized[1024]; // Big enough for a sane symbol. // Symbolizes the previous address of pc because pc may be in the // next function. @@ -238,6 +242,10 @@ void DumpStackFrameInfo(const char* prefix, void* pc) { sizeof(symbolized))) { symbol = symbolized; } +#else +# pragma message( \ + "Symbolize functionality is not available for target platform: stack dump will contain empty frames.") +#endif // defined(HAVE_SYMBOLIZE) char buf[1024]; // Big enough for stack frame info. MinimalFormatter formatter(buf, sizeof(buf)); diff --git a/src/signalhandler_unittest.cc b/src/signalhandler_unittest.cc index 7db32aed7..d15aace76 100644 --- a/src/signalhandler_unittest.cc +++ b/src/signalhandler_unittest.cc @@ -39,13 +39,21 @@ #include #include +#include "config.h" #include "glog/logging.h" -#include "utilities.h" +#include "stacktrace.h" +#include "symbolize.h" +#if defined(HAVE_UNISTD_H) +# include +#endif #ifdef GLOG_USE_GFLAGS # include using namespace GFLAGS_NAMESPACE; #endif +#if defined(_MSC_VER) +# include // write +#endif using namespace google; @@ -59,7 +67,7 @@ static void DieInThread(int* a) { } static void WriteToStdout(const char* data, size_t size) { - if (write(STDOUT_FILENO, data, size) < 0) { + if (write(fileno(stdout), data, size) < 0) { // Ignore errors. } } diff --git a/src/stacktrace.cc b/src/stacktrace.cc new file mode 100644 index 000000000..6ba178e7e --- /dev/null +++ b/src/stacktrace.cc @@ -0,0 +1,38 @@ +// Copyright (c) 2024, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Routines to extract the current stack trace. These functions are +// thread-safe. + +#include "stacktrace.h" + +// Make an implementation of stacktrace compiled. +#if defined(STACKTRACE_H) +# include STACKTRACE_H +#endif diff --git a/src/stacktrace.h b/src/stacktrace.h index fb851e492..fbbe92d67 100644 --- a/src/stacktrace.h +++ b/src/stacktrace.h @@ -1,4 +1,4 @@ -// Copyright (c) 2000 - 2007, Google Inc. +// Copyright (c) 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -30,13 +30,46 @@ // Routines to extract the current stack trace. These functions are // thread-safe. -#ifndef BASE_STACKTRACE_H_ -#define BASE_STACKTRACE_H_ +#ifndef GLOG_INTERNAL_STACKTRACE_H +#define GLOG_INTERNAL_STACKTRACE_H + +#include "glog/platform.h" + +#if defined(GLOG_USE_GLOG_EXPORT) +# include "glog/export.h" +#endif + +#if !defined(GLOG_NO_EXPORT) +# error "stacktrace.h" was not included correctly. +#endif #include "config.h" -#include "glog/logging.h" +#if defined(HAVE_LIBUNWIND) +# define STACKTRACE_H "stacktrace_libunwind-inl.h" +#elif defined(HAVE_UNWIND) +# define STACKTRACE_H "stacktrace_unwind-inl.h" +#elif !defined(NO_FRAME_POINTER) +# if defined(__i386__) && __GNUC__ >= 2 +# define STACKTRACE_H "stacktrace_x86-inl.h" +# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2 +# define STACKTRACE_H "stacktrace_powerpc-inl.h" +# elif defined(GLOG_OS_WINDOWS) +# define STACKTRACE_H "stacktrace_windows-inl.h" +# endif +#endif + +#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_BACKTRACE) +# define STACKTRACE_H "stacktrace_generic-inl.h" +#endif + +#if defined(STACKTRACE_H) +# define HAVE_STACKTRACE +#endif namespace google { +inline namespace glog_internal_namespace_ { + +#if defined(HAVE_STACKTRACE) // This is similar to the GetStackFrames routine, except that it returns // the stack trace only, and not the stack frame sizes as well. @@ -54,8 +87,11 @@ namespace google { // .... ... // // "result" must not be nullptr. -GLOG_EXPORT int GetStackTrace(void** result, int max_depth, int skip_count); +GLOG_NO_EXPORT int GetStackTrace(void** result, int max_depth, int skip_count); + +#endif // defined(HAVE_STACKTRACE) +} // namespace glog_internal_namespace_ } // namespace google -#endif // BASE_STACKTRACE_H_ +#endif // GLOG_INTERNAL_STACKTRACE_H diff --git a/src/stacktrace_generic-inl.h b/src/stacktrace_generic-inl.h index bdfadfa0c..e3a392665 100644 --- a/src/stacktrace_generic-inl.h +++ b/src/stacktrace_generic-inl.h @@ -38,6 +38,7 @@ #include "stacktrace.h" namespace google { +inline namespace glog_internal_namespace_ { // If you change this function, also change GetStackFrames below. int GetStackTrace(void** result, int max_depth, int skip_count) { @@ -61,4 +62,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return result_count; } +} // namespace glog_internal_namespace_ } // namespace google diff --git a/src/stacktrace_libunwind-inl.h b/src/stacktrace_libunwind-inl.h index 288742fe7..71c69ad08 100644 --- a/src/stacktrace_libunwind-inl.h +++ b/src/stacktrace_libunwind-inl.h @@ -41,6 +41,7 @@ extern "C" { #include "stacktrace.h" namespace google { +inline namespace glog_internal_namespace_ { // Sometimes, we can try to get a stack trace from within a stack // trace, because libunwind can call mmap (maybe indirectly via an @@ -90,4 +91,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return n; } +} // namespace glog_internal_namespace_ } // namespace google diff --git a/src/stacktrace_powerpc-inl.h b/src/stacktrace_powerpc-inl.h index 168f47234..52bfd0230 100644 --- a/src/stacktrace_powerpc-inl.h +++ b/src/stacktrace_powerpc-inl.h @@ -41,6 +41,7 @@ #include "stacktrace.h" namespace google { +inline namespace glog_internal_namespace_ { // Given a pointer to a stack frame, locate and return the calling // stackframe, or return nullptr if no stackframe can be found. Perform sanity @@ -131,4 +132,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return n; } +} // namespace glog_internal_namespace_ } // namespace google diff --git a/src/stacktrace_unittest.cc b/src/stacktrace_unittest.cc index 9060a2a60..6a3253fe6 100644 --- a/src/stacktrace_unittest.cc +++ b/src/stacktrace_unittest.cc @@ -41,8 +41,6 @@ # include #endif -using namespace google; - #ifdef HAVE_STACKTRACE // Obtain a backtrace, verify that the expected callers are present in the @@ -132,7 +130,7 @@ static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() { ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]); INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]); DECLARE_ADDRESS_LABEL(start); - size = GetStackTrace(stack, STACK_LEN, 0); + size = google::GetStackTrace(stack, STACK_LEN, 0); printf("Obtained %d stack frames.\n", size); CHECK_GE(size, 1); CHECK_LE(size, STACK_LEN); @@ -231,7 +229,7 @@ static int main(int, char** argv) { FLAGS_logtostderr = true; - InitGoogleLogging(argv[0]); + google::InitGoogleLogging(argv[0]); CheckStackTrace(0); diff --git a/src/stacktrace_unwind-inl.h b/src/stacktrace_unwind-inl.h index 78b1e2eb8..894f1af93 100644 --- a/src/stacktrace_unwind-inl.h +++ b/src/stacktrace_unwind-inl.h @@ -36,6 +36,7 @@ #include "stacktrace.h" namespace google { +inline namespace glog_internal_namespace_ { struct trace_arg_t { void** result; @@ -101,4 +102,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return targ.count; } +} // namespace glog_internal_namespace_ } // namespace google diff --git a/src/stacktrace_windows-inl.h b/src/stacktrace_windows-inl.h index 851c9bb11..26d66c501 100644 --- a/src/stacktrace_windows-inl.h +++ b/src/stacktrace_windows-inl.h @@ -31,15 +31,13 @@ // // Windows implementation - just use CaptureStackBackTrace +// clang-format off +#include // Must come before #include - -#include "config.h" -#if defined(GLOG_USE_WINDOWS_PORT) -# include "port.h" -#endif -#include "stacktrace.h" +// clang-format on namespace google { +inline namespace glog_internal_namespace_ { int GetStackTrace(void** result, int max_depth, int skip_count) { if (max_depth > 64) { @@ -51,4 +49,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { static_cast(max_depth), result, nullptr); } +} // namespace glog_internal_namespace_ } // namespace google diff --git a/src/stacktrace_x86-inl.h b/src/stacktrace_x86-inl.h index 3ca9f68f5..ac0e55c87 100644 --- a/src/stacktrace_x86-inl.h +++ b/src/stacktrace_x86-inl.h @@ -43,6 +43,7 @@ #include "stacktrace.h" namespace google { +inline namespace glog_internal_namespace_ { // Given a pointer to a stack frame, locate and return the calling // stackframe, or return nullptr if no stackframe can be found. Perform sanity @@ -155,5 +156,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { } return n; } - +} // namespace glog_internal_namespace_ } // namespace google diff --git a/src/symbolize.cc b/src/symbolize.cc index e226aa7a1..5c78be565 100644 --- a/src/symbolize.cc +++ b/src/symbolize.cc @@ -71,6 +71,7 @@ # define GLOG_SAFE_ASSERT(expr) ((expr) ? 0 : (std::abort(), 0)) namespace google { +inline namespace glog_internal_namespace_ { namespace { @@ -105,6 +106,7 @@ void InstallSymbolizeOpenObjectFileCallback( g_symbolize_open_object_file_callback = callback; } +} // namespace glog_internal_namespace_ } // namespace google # if defined(__ELF__) @@ -135,6 +137,7 @@ void InstallSymbolizeOpenObjectFileCallback( # include "symbolize.h" namespace google { +inline namespace glog_internal_namespace_ { namespace { @@ -822,6 +825,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle( return true; } +} // namespace glog_internal_namespace_ } // namespace google # elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR) @@ -831,6 +835,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle( # include namespace google { +inline namespace glog_internal_namespace_ { static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle( void* pc, char* out, size_t out_size, SymbolizeOptions /*options*/) { @@ -848,6 +853,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle( return false; } +} // namespace glog_internal_namespace_ } // namespace google # elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN) @@ -856,6 +862,9 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle( # include namespace google { +inline namespace glog_internal_namespace_ { + +namespace { class SymInitializer final { public: @@ -883,6 +892,8 @@ class SymInitializer final { SymInitializer& operator=(SymInitializer&&) = delete; }; +} // namespace + static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out, size_t out_size, SymbolizeOptions options) { @@ -942,6 +953,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out, return false; } +} // namespace glog_internal_namespace_ } // namespace google # else @@ -949,28 +961,13 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out, # endif namespace google { +inline namespace glog_internal_namespace_ { bool Symbolize(void* pc, char* out, size_t out_size, SymbolizeOptions options) { return SymbolizeAndDemangle(pc, out, out_size, options); } -} // namespace google - -#else /* HAVE_SYMBOLIZE */ - -# include - -# include "config.h" - -namespace google { - -// TODO: Support other environments. -bool Symbolize(void* /*pc*/, char* /*out*/, size_t /*out_size*/, - SymbolizeOptions /*options*/) { - assert(0); - return false; -} - +} // namespace glog_internal_namespace_ } // namespace google #endif diff --git a/src/symbolize.h b/src/symbolize.h index a93584f3b..dfd5fec90 100644 --- a/src/symbolize.h +++ b/src/symbolize.h @@ -51,14 +51,38 @@ // malloc() and other unsafe operations. It should be both // thread-safe and async-signal-safe. -#ifndef BASE_SYMBOLIZE_H_ -#define BASE_SYMBOLIZE_H_ +#ifndef GLOG_INTERNAL_SYMBOLIZE_H +#define GLOG_INTERNAL_SYMBOLIZE_H +#include +#include #include #include "config.h" -#include "glog/logging.h" -#include "utilities.h" +#include "glog/platform.h" + +#if defined(GLOG_USE_GLOG_EXPORT) +# include "glog/export.h" +#endif + +#if !defined(GLOG_NO_EXPORT) +# error "symbolize.h" was not included correctly. +#endif + +#ifndef GLOG_NO_SYMBOLIZE_DETECTION +# ifndef HAVE_SYMBOLIZE +// defined by gcc +# if defined(__ELF__) && defined(GLOG_OS_LINUX) +# define HAVE_SYMBOLIZE +# elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR) +// Use dladdr to symbolize. +# define HAVE_SYMBOLIZE +# elif defined(GLOG_OS_WINDOWS) +// Use DbgHelp to symbolize +# define HAVE_SYMBOLIZE +# endif +# endif // !defined(HAVE_SYMBOLIZE) +#endif // !defined(GLOG_NO_SYMBOLIZE_DETECTION) #ifdef HAVE_SYMBOLIZE @@ -69,7 +93,7 @@ # include # endif -# if !defined(ANDROID) +# if !defined(GLOG_OS_ANDROID) # include // For ElfW() macro. # endif @@ -95,17 +119,21 @@ # endif namespace google { +inline namespace glog_internal_namespace_ { // Gets the section header for the given name, if it exists. Returns true on // success. Otherwise, returns false. +GLOG_NO_EXPORT bool GetSectionHeaderByName(int fd, const char* name, size_t name_len, ElfW(Shdr) * out); +} // namespace glog_internal_namespace_ } // namespace google # endif /* __ELF__ */ namespace google { +inline namespace glog_internal_namespace_ { // Restrictions on the callbacks that follow: // - The callbacks must not use heaps but only use stacks. @@ -119,7 +147,7 @@ namespace google { // and return the size of the output written. On error, the callback // function should return -1. using SymbolizeCallback = int (*)(int, void*, char*, size_t, uint64_t); -GLOG_EXPORT +GLOG_NO_EXPORT void InstallSymbolizeCallback(SymbolizeCallback callback); // Installs a callback function, which will be called instead of @@ -134,15 +162,19 @@ void InstallSymbolizeCallback(SymbolizeCallback callback); // (including the null-terminator). using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t&, uint64_t&, char*, size_t); -GLOG_EXPORT +GLOG_NO_EXPORT void InstallSymbolizeOpenObjectFileCallback( SymbolizeOpenObjectFileCallback callback); +} // namespace glog_internal_namespace_ } // namespace google #endif namespace google { +inline namespace glog_internal_namespace_ { + +#if defined(HAVE_SYMBOLIZE) enum class SymbolizeOptions { // No additional options. @@ -169,9 +201,13 @@ constexpr SymbolizeOptions operator|(SymbolizeOptions lhs, // symbol name to "out". The symbol name is demangled if possible // (supports symbols generated by GCC 3.x or newer). Otherwise, // returns false. -GLOG_EXPORT bool Symbolize(void* pc, char* out, size_t out_size, - SymbolizeOptions options = SymbolizeOptions::kNone); +GLOG_NO_EXPORT bool Symbolize( + void* pc, char* out, size_t out_size, + SymbolizeOptions options = SymbolizeOptions::kNone); + +#endif // defined(HAVE_SYMBOLIZE) +} // namespace glog_internal_namespace_ } // namespace google -#endif // BASE_SYMBOLIZE_H_ +#endif // GLOG_INTERNAL_SYMBOLIZE_H diff --git a/src/utilities.cc b/src/utilities.cc index aa71e9bc7..bd949ef0b 100644 --- a/src/utilities.cc +++ b/src/utilities.cc @@ -41,8 +41,12 @@ #include "base/googleinit.h" #include "config.h" +#include "glog/flags.h" +#include "glog/logging.h" +#include "stacktrace.h" +#include "symbolize.h" -#ifdef __ANDROID__ +#ifdef GLOG_OS_ANDROID # include #endif #ifdef HAVE_SYS_TIME_H @@ -88,7 +92,7 @@ void AlsoErrorWrite(LogSeverity severity, const char* tag, (void)tag; // On Windows, also output to the debugger ::OutputDebugStringA(message); -#elif defined(__ANDROID__) +#elif defined(GLOG_OS_ANDROID) constexpr int android_log_levels[] = { ANDROID_LOG_INFO, ANDROID_LOG_WARN, @@ -125,7 +129,7 @@ static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*); static void DebugWriteToStderr(const char* data, void*) { // This one is signal-safe. - if (write(STDERR_FILENO, data, strlen(data)) < 0) { + if (write(fileno(stderr), data, strlen(data)) < 0) { // Ignore errors. } AlsoErrorWrite(GLOG_FATAL, @@ -319,18 +323,4 @@ void ShutdownGoogleLoggingUtilities() { } } // namespace glog_internal_namespace_ - } // namespace google - -// Make an implementation of stacktrace compiled. -#ifdef STACKTRACE_H -# include STACKTRACE_H -# if 0 -// For include scanners which can't handle macro expansions. -# include "stacktrace_generic-inl.h" -# include "stacktrace_libunwind-inl.h" -# include "stacktrace_powerpc-inl.h" -# include "stacktrace_x86-inl.h" -# include "stacktrace_x86_64-inl.h" -# endif -#endif diff --git a/src/utilities.h b/src/utilities.h index ea6344c00..581bff7f5 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -32,8 +32,8 @@ // // Define utilities for glog internal usage. -#ifndef UTILITIES_H__ -#define UTILITIES_H__ +#ifndef GLOG_INTERNAL_UTILITIES_H +#define GLOG_INTERNAL_UTILITIES_H #include #include @@ -60,18 +60,14 @@ #define PRIXS __PRIS_PREFIX "X" #define PRIoS __PRIS_PREFIX "o" -#include "glog/logging.h" - +#include "config.h" +#include "glog/platform.h" #if defined(GLOG_USE_WINDOWS_PORT) # include "port.h" #endif - -#include "config.h" - #if defined(HAVE_UNISTD_H) # include #endif - #if !defined(HAVE_SSIZE_T) # if defined(GLOG_OS_WINDOWS) # include @@ -81,6 +77,9 @@ using ssize_t = std::ptrdiff_t; # endif #endif +#include "glog/log_severity.h" +#include "glog/types.h" + // 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 @@ -103,43 +102,6 @@ using ssize_t = std::ptrdiff_t; // correctly when GetStackTrace() is called with max_depth == 0. // Some code may do that. -#if defined(HAVE_LIBUNWIND) -# define STACKTRACE_H "stacktrace_libunwind-inl.h" -#elif defined(HAVE_UNWIND) -# define STACKTRACE_H "stacktrace_unwind-inl.h" -#elif !defined(NO_FRAME_POINTER) -# if defined(__i386__) && __GNUC__ >= 2 -# define STACKTRACE_H "stacktrace_x86-inl.h" -# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2 -# define STACKTRACE_H "stacktrace_powerpc-inl.h" -# elif defined(GLOG_OS_WINDOWS) -# define STACKTRACE_H "stacktrace_windows-inl.h" -# endif -#endif - -#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_BACKTRACE) -# define STACKTRACE_H "stacktrace_generic-inl.h" -#endif - -#if defined(STACKTRACE_H) -# define HAVE_STACKTRACE -#endif - -#ifndef GLOG_NO_SYMBOLIZE_DETECTION -# ifndef HAVE_SYMBOLIZE -// defined by gcc -# if defined(__ELF__) && defined(GLOG_OS_LINUX) -# define HAVE_SYMBOLIZE -# elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR) -// Use dladdr to symbolize. -# define HAVE_SYMBOLIZE -# elif defined(GLOG_OS_WINDOWS) -// Use DbgHelp to symbolize -# define HAVE_SYMBOLIZE -# endif -# endif // !defined(HAVE_SYMBOLIZE) -#endif // !defined(GLOG_NO_SYMBOLIZE_DETECTION) - #ifndef ARRAYSIZE // There is a better way, but this is good enough for our purpose. # define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a))) @@ -320,4 +282,4 @@ struct std::default_delete { void operator()(FILE* p) const noexcept { fclose(p); } }; -#endif // UTILITIES_H__ +#endif // GLOG_INTERNAL_UTILITIES_H diff --git a/src/vlog_is_on.cc b/src/vlog_is_on.cc index d6d308899..60dfae660 100644 --- a/src/vlog_is_on.cc +++ b/src/vlog_is_on.cc @@ -1,4 +1,4 @@ -// Copyright (c) 1999, 2007, Google Inc. +// Copyright (c) 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -39,9 +39,7 @@ #include #include -#include "glog/logging.h" #include "glog/raw_logging.h" -#include "utilities.h" // glog doesn't have annotation #define ANNOTATE_BENIGN_RACE(address, description) diff --git a/src/windows/dirent.h b/src/windows/dirent.h index 9ed3845fb..316726440 100644 --- a/src/windows/dirent.h +++ b/src/windows/dirent.h @@ -6,8 +6,8 @@ * under the MIT license. For all details and documentation, see * https://github.com/tronkko/dirent */ -#ifndef DIRENT_H -#define DIRENT_H +#ifndef GLOG_INTERNAL_WINDOWS_DIRENT_H +#define GLOG_INTERNAL_WINDOWS_DIRENT_H /* Hide warnings about unreferenced local functions */ #if defined(__clang__) @@ -1037,4 +1037,4 @@ static void dirent_set_errno(int error) { #ifdef __cplusplus } #endif -#endif /*DIRENT_H*/ +#endif /*GLOG_INTERNAL_WINDOWS_DIRENT_H*/ diff --git a/src/windows/port.cc b/src/windows/port.cc index 6bc473052..35e556a32 100644 --- a/src/windows/port.cc +++ b/src/windows/port.cc @@ -42,6 +42,9 @@ #include "config.h" +namespace google { +inline namespace glog_internal_namespace_ { + #ifndef HAVE_LOCALTIME_R struct tm* localtime_r(const std::time_t* timep, std::tm* result) { localtime_s(result, timep); @@ -54,3 +57,6 @@ struct tm* gmtime_r(const std::time_t* timep, std::tm* result) { return result; } #endif // not HAVE_GMTIME_R + +} // namespace glog_internal_namespace_ +} // namespace google diff --git a/src/windows/port.h b/src/windows/port.h index 82de81cca..8344e5ae8 100644 --- a/src/windows/port.h +++ b/src/windows/port.h @@ -43,6 +43,14 @@ #include "config.h" +#if defined(GLOG_USE_GLOG_EXPORT) +# include "glog/export.h" +#endif + +#if !defined(GLOG_EXPORT) +# error "port.h" was not included correctly. +#endif + #ifdef _WIN32 # ifndef WIN32_LEAN_AND_MEAN @@ -62,8 +70,6 @@ * used by both C and C++ code, so we put all the C++ together. */ -# include "glog/logging.h" - # ifdef _MSC_VER /* 4244: otherwise we get problems when substracting two size_t's to an int @@ -89,9 +95,6 @@ # define O_CREAT _O_CREAT # define O_EXCL _O_EXCL -# ifndef __MINGW32__ -enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 }; -# endif # define S_IRUSR S_IREAD # define S_IWUSR S_IWRITE @@ -116,24 +119,23 @@ enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 }; # endif // _MSC_VER +namespace google { +inline namespace glog_internal_namespace_ { # ifndef HAVE_LOCALTIME_R -extern GLOG_EXPORT std::tm* localtime_r(const std::time_t* timep, - std::tm* result); +GLOG_NO_EXPORT std::tm* localtime_r(const std::time_t* timep, std::tm* result); # endif // not HAVE_LOCALTIME_R # ifndef HAVE_GMTIME_R -extern GLOG_EXPORT std::tm* gmtime_r(const std::time_t* timep, std::tm* result); +GLOG_NO_EXPORT std::tm* gmtime_r(const std::time_t* timep, std::tm* result); # endif // not HAVE_GMTIME_R +GLOG_NO_EXPORT inline char* strerror_r(int errnum, char* buf, std::size_t buflen) { strerror_s(buf, buflen, errnum); return buf; } - -# ifndef __cplusplus -/* I don't see how to get inlining for C code in MSVC. Ah well. */ -# define inline -# endif +} // namespace glog_internal_namespace_ +} // namespace google #endif /* _WIN32 */