fix: better encapsulate internals (#1055)

This commit is contained in:
Sergiu Deitsch 2024-01-09 23:51:43 +01:00 committed by GitHub
parent 2b5a53c880
commit ec455f2cc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 392 additions and 265 deletions

View File

@ -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

View File

@ -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,

View File

@ -31,6 +31,9 @@
/* Define if you have the 'pread' function */
#cmakedefine HAVE_PREAD
/* Define if you have the 'posix_fadvise' function in <fcntl.h> */
#cmakedefine HAVE_POSIX_FADVISE
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H

View File

@ -37,7 +37,6 @@
#include "demangle.h"
#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <limits>
@ -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

View File

@ -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 <cstddef>
#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

View File

@ -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

View File

@ -56,7 +56,7 @@
# include "glog/export.h"
#endif
#if !defined(GLOG_EXPORT)
#if !defined(GLOG_EXPORT) || !defined(GLOG_NO_EXPORT)
# error <glog/logging.h> 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 <typename T>
@ -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 <typename T1, typename T2>
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 <typename T>
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>(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 <typename T>
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>(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:

View File

@ -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.

View File

@ -51,12 +51,16 @@
#include <utility>
#include <vector>
#include "utilities.h"
#include "config.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#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<CapturedStream> s_captured_streams[STDERR_FILENO + 1];
static std::map<int, std::unique_ptr<CapturedStream>> 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<CapturedStream>(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<CapturedStream> cap = std::move(s_captured_streams[fd]);
CHECK((fd == fileno(stdout)) || (fd == fileno(stderr)));
std::unique_ptr<CapturedStream> 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.

View File

@ -48,13 +48,11 @@
#include <utility>
#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<SinkMutex> 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<off_t>(dropped_mem_length_),
static_cast<off_t>(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;
}

View File

@ -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

View File

@ -33,29 +33,18 @@
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <mutex>
#include <ostream>
#include <streambuf>
#include <thread>
#include "utilities.h"
#include "config.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h> // for close() and write()
#endif
#include <fcntl.h> // for open()
#include <ctime>
#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"
#endif
#if defined(HAVE_SYSCALL_H)
# include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H)
@ -64,6 +53,12 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <fcntl.h> // 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<char*>(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;

View File

@ -33,12 +33,15 @@
#include <algorithm>
#include <csignal>
#include <cstring>
#include <ctime>
#include <mutex>
#include <sstream>
#include <thread>
#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));

View File

@ -39,13 +39,21 @@
#include <string>
#include <thread>
#include "config.h"
#include "glog/logging.h"
#include "utilities.h"
#include "stacktrace.h"
#include "symbolize.h"
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif
#ifdef GLOG_USE_GFLAGS
# include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE;
#endif
#if defined(_MSC_VER)
# include <io.h> // 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.
}
}

38
src/stacktrace.cc Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -41,8 +41,6 @@
# include <execinfo.h>
#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);

View File

@ -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

View File

@ -31,15 +31,13 @@
//
// Windows implementation - just use CaptureStackBackTrace
// clang-format off
#include <windows.h> // Must come before <dbghelp.h>
#include <dbghelp.h>
#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<DWORD>(max_depth), result, nullptr);
}
} // namespace glog_internal_namespace_
} // namespace google

View File

@ -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

View File

@ -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 <cstring>
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 <windows.h>
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 <cassert>
# 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

View File

@ -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 <cstddef>
#include <cstdint>
#include <type_traits>
#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 <elf.h>
# endif
# if !defined(ANDROID)
# if !defined(GLOG_OS_ANDROID)
# include <link.h> // 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

View File

@ -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 <android/log.h>
#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

View File

@ -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 <cstddef>
#include <cstdio>
@ -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 <unistd.h>
#endif
#if !defined(HAVE_SSIZE_T)
# if defined(GLOG_OS_WINDOWS)
# include <basetsd.h>
@ -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<std::FILE> {
void operator()(FILE* p) const noexcept { fclose(p); }
};
#endif // UTILITIES_H__
#endif // GLOG_INTERNAL_UTILITIES_H

View File

@ -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 <mutex>
#include <string>
#include "glog/logging.h"
#include "glog/raw_logging.h"
#include "utilities.h"
// glog doesn't have annotation
#define ANNOTATE_BENIGN_RACE(address, description)

View File

@ -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*/

View File

@ -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

View File

@ -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 */