1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_
6 #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_
7 
8 #include <cstddef>
9 
10 #include "build/build_config.h"
11 #include "partition_alloc/partition_alloc_base/component_export.h"
12 #include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h"
13 #include "partition_alloc/partition_alloc_base/scoped_clear_last_error.h"
14 #include "partition_alloc/partition_alloc_base/strings/cstring_builder.h"
15 
16 namespace partition_alloc::internal::logging {
17 
18 // Sets the Log Message Handler that gets passed every log message before
19 // it's sent to other log destinations (if any).
20 // Returns true to signal that it handled the message and the message
21 // should not be sent to other log destinations.
22 typedef bool (*LogMessageHandlerFunction)(int severity,
23                                           const char* file,
24                                           int line,
25                                           size_t message_start,
26                                           const char* str);
27 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
28 void SetLogMessageHandler(LogMessageHandlerFunction handler);
29 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
30 LogMessageHandlerFunction GetLogMessageHandler();
31 
32 using LogSeverity = int;
33 constexpr LogSeverity LOGGING_VERBOSE = -1;  // This is level 1 verbosity
34 // Note: the log severities are used to index into the array of names,
35 // see log_severity_names.
36 constexpr LogSeverity LOGGING_INFO = 0;
37 constexpr LogSeverity LOGGING_WARNING = 1;
38 constexpr LogSeverity LOGGING_ERROR = 2;
39 constexpr LogSeverity LOGGING_FATAL = 3;
40 constexpr LogSeverity LOGGING_NUM_SEVERITIES = 4;
41 
42 // LOGGING_DFATAL is LOGGING_FATAL in DCHECK-enabled builds, ERROR in normal
43 // mode.
44 #if BUILDFLAG(PA_DCHECK_IS_ON)
45 constexpr LogSeverity LOGGING_DFATAL = LOGGING_FATAL;
46 #else
47 constexpr LogSeverity LOGGING_DFATAL = LOGGING_ERROR;
48 #endif
49 
50 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
51 extern base::strings::CStringBuilder* g_swallow_stream;
52 
53 // This class more or less represents a particular log message.  You
54 // create an instance of LogMessage and then stream stuff to it.
55 // When you finish streaming to it, ~LogMessage is called and the
56 // full message gets streamed to the appropriate destination.
57 //
58 // You shouldn't actually use LogMessage's constructor to log things,
59 // though.  You should use the PA_LOG() macro (and variants thereof)
60 // above.
PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)61 class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) LogMessage {
62  public:
63   // Used for PA_LOG(severity).
64   LogMessage(const char* file, int line, LogSeverity severity);
65 
66   // Used for CHECK().  Implied severity = LOGGING_FATAL.
67   LogMessage(const char* file, int line, const char* condition);
68   LogMessage(const LogMessage&) = delete;
69   LogMessage& operator=(const LogMessage&) = delete;
70   virtual ~LogMessage();
71 
72   base::strings::CStringBuilder& stream() { return stream_; }
73 
74   LogSeverity severity() { return severity_; }
75   const char* c_str() { return stream_.c_str(); }
76 
77  private:
78   void Init(const char* file, int line);
79 
80   const LogSeverity severity_;
81   base::strings::CStringBuilder stream_;
82   size_t message_start_;  // Offset of the start of the message (past prefix
83                           // info).
84   // The file and line information passed in to the constructor.
85   const char* const file_;
86   const int line_;
87 
88   // This is useful since the LogMessage class uses a lot of Win32 calls
89   // that will lose the value of GLE and the code that called the log function
90   // will have lost the thread error value when the log call returns.
91   base::ScopedClearLastError last_error_;
92 };
93 
94 // This class is used to explicitly ignore values in the conditional
95 // logging macros.  This avoids compiler warnings like "value computed
96 // is not used" and "statement has no effect".
97 class LogMessageVoidify {
98  public:
99   LogMessageVoidify() = default;
100   // This has to be an operator with a precedence lower than << but
101   // higher than ?:
102   void operator&(base::strings::CStringBuilder&) {}
103 };
104 
105 #if BUILDFLAG(IS_WIN)
106 typedef unsigned long SystemErrorCode;
107 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
108 typedef int SystemErrorCode;
109 #endif
110 
111 // Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to
112 // pull in windows.h just for GetLastError() and DWORD.
113 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
114 SystemErrorCode GetLastSystemErrorCode();
115 
116 #if BUILDFLAG(IS_WIN)
117 // Appends a formatted system message of the GetLastError() type.
PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)118 class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) Win32ErrorLogMessage
119     : public LogMessage {
120  public:
121   Win32ErrorLogMessage(const char* file,
122                        int line,
123                        LogSeverity severity,
124                        SystemErrorCode err);
125   Win32ErrorLogMessage(const Win32ErrorLogMessage&) = delete;
126   Win32ErrorLogMessage& operator=(const Win32ErrorLogMessage&) = delete;
127   // Appends the error message before destructing the encapsulated class.
128   ~Win32ErrorLogMessage() override;
129 
130  private:
131   SystemErrorCode err_;
132 };
133 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
134 // Appends a formatted system message of the errno type
PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)135 class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) ErrnoLogMessage
136     : public LogMessage {
137  public:
138   ErrnoLogMessage(const char* file,
139                   int line,
140                   LogSeverity severity,
141                   SystemErrorCode err);
142   ErrnoLogMessage(const ErrnoLogMessage&) = delete;
143   ErrnoLogMessage& operator=(const ErrnoLogMessage&) = delete;
144   // Appends the error message before destructing the encapsulated class.
145   ~ErrnoLogMessage() override;
146 
147  private:
148   SystemErrorCode err_;
149 };
150 #endif  // BUILDFLAG(IS_WIN)
151 
152 }  // namespace partition_alloc::internal::logging
153 
154 #endif  // PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_
155