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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_LOGGING_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_LOGGING_H_
7
8 #include <stddef.h>
9
10 #include <cassert>
11 #include <cstdint>
12 #include <sstream>
13 #include <string>
14
15 #include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
16 #include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
17 #include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
18 #include "base/allocator/partition_allocator/partition_alloc_base/scoped_clear_last_error.h"
19 #include "build/build_config.h"
20
21 // TODO(1151236): Need to update the description, because logging for PA
22 // standalone library was minimized.
23 //
24 // Optional message capabilities
25 // -----------------------------
26 // Assertion failed messages and fatal errors are displayed in a dialog box
27 // before the application exits. However, running this UI creates a message
28 // loop, which causes application messages to be processed and potentially
29 // dispatched to existing application windows. Since the application is in a
30 // bad state when this assertion dialog is displayed, these messages may not
31 // get processed and hang the dialog, or the application might go crazy.
32 //
33 // Therefore, it can be beneficial to display the error dialog in a separate
34 // process from the main application. When the logging system needs to display
35 // a fatal error dialog box, it will look for a program called
36 // "DebugMessage.exe" in the same directory as the application executable. It
37 // will run this application with the message as the command line, and will
38 // not include the name of the application as is traditional for easier
39 // parsing.
40 //
41 // The code for DebugMessage.exe is only one line. In WinMain, do:
42 // MessageBox(NULL, GetCommandLineW(), L"Fatal Error", 0);
43 //
44 // If DebugMessage.exe is not found, the logging code will use a normal
45 // MessageBox, potentially causing the problems discussed above.
46
47 // Instructions
48 // ------------
49 //
50 // Make a bunch of macros for logging. The way to log things is to stream
51 // things to PA_LOG(<a particular severity level>). E.g.,
52 //
53 // PA_LOG(INFO) << "Found " << num_cookies << " cookies";
54 //
55 // You can also do conditional logging:
56 //
57 // PA_LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
58 //
59 // The CHECK(condition) macro is active in both debug and release builds and
60 // effectively performs a PA_LOG(FATAL) which terminates the process and
61 // generates a crashdump unless a debugger is attached.
62 //
63 // There are also "debug mode" logging macros like the ones above:
64 //
65 // PA_DLOG(INFO) << "Found cookies";
66 //
67 // PA_DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
68 //
69 // All "debug mode" logging is compiled away to nothing for non-debug mode
70 // compiles. PA_LOG_IF and development flags also work well together
71 // because the code can be compiled away sometimes.
72 //
73 // We also have
74 //
75 // PA_LOG_ASSERT(assertion);
76 // PA_DLOG_ASSERT(assertion);
77 //
78 // which is syntactic sugar for PA_{,D}LOG_IF(FATAL, assert fails) << assertion;
79 //
80 // There are "verbose level" logging macros. They look like
81 //
82 // PA_VLOG(1) << "I'm printed when you run the program with --v=1 or more";
83 // PA_VLOG(2) << "I'm printed when you run the program with --v=2 or more";
84 //
85 // These always log at the INFO log level (when they log at all).
86 //
87 // There's also PA_VLOG_IS_ON(n) "verbose level" condition macro. To be used as
88 //
89 // if (PA_VLOG_IS_ON(2)) {
90 // // do some logging preparation and logging
91 // // that can't be accomplished with just PA_VLOG(2) << ...;
92 // }
93 //
94 // There is also a PA_VLOG_IF "verbose level" condition macro for sample
95 // cases, when some extra computation and preparation for logs is not
96 // needed.
97 //
98 // PA_VLOG_IF(1, (size > 1024))
99 // << "I'm printed when size is more than 1024 and when you run the "
100 // "program with --v=1 or more";
101 //
102 // We also override the standard 'assert' to use 'PA_DLOG_ASSERT'.
103 //
104 // Lastly, there is:
105 //
106 // PA_PLOG(ERROR) << "Couldn't do foo";
107 // PA_DPLOG(ERROR) << "Couldn't do foo";
108 // PA_PLOG_IF(ERROR, cond) << "Couldn't do foo";
109 // PA_DPLOG_IF(ERROR, cond) << "Couldn't do foo";
110 // PA_PCHECK(condition) << "Couldn't do foo";
111 // PA_DPCHECK(condition) << "Couldn't do foo";
112 //
113 // which append the last system error to the message in string form (taken from
114 // GetLastError() on Windows and errno on POSIX).
115 //
116 // The supported severity levels for macros that allow you to specify one
117 // are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
118 //
119 // Very important: logging a message at the FATAL severity level causes
120 // the program to terminate (after the message is logged).
121 //
122 // There is the special severity of DFATAL, which logs FATAL in DCHECK-enabled
123 // builds, ERROR in normal mode.
124 //
125 // Output is formatted as per the following example:
126 // [VERBOSE1:drm_device_handle.cc(90)] Succeeded
127 // authenticating /dev/dri/card0 in 0 ms with 1 attempt(s)
128 //
129 // The colon separated fields inside the brackets are as follows:
130 // 1. The log level
131 // 2. The filename and line number where the log was instantiated
132 //
133 // Additional logging-related information can be found here:
134 // https://chromium.googlesource.com/chromium/src/+/main/docs/linux/debugging.md#Logging
135
136 namespace partition_alloc::internal::logging {
137
138 // Sets the log level. Anything at or above this level will be written to the
139 // log file/displayed to the user (if applicable). Anything below this level
140 // will be silently ignored. The log level defaults to 0 (everything is logged
141 // up to level INFO) if this function is not called.
142 // Note that log messages for VLOG(x) are logged at level -x, so setting
143 // the min log level to negative values enables verbose logging.
144 PA_COMPONENT_EXPORT(PARTITION_ALLOC) void SetMinLogLevel(int level);
145
146 // Gets the current log level.
147 PA_COMPONENT_EXPORT(PARTITION_ALLOC) int GetMinLogLevel();
148
149 // Used by PA_LOG_IS_ON to lazy-evaluate stream arguments.
150 PA_COMPONENT_EXPORT(PARTITION_ALLOC) bool ShouldCreateLogMessage(int severity);
151
152 // Gets the PA_VLOG default verbosity level.
153 PA_COMPONENT_EXPORT(PARTITION_ALLOC) int GetVlogVerbosity();
154
155 // Sets the Log Message Handler that gets passed every log message before
156 // it's sent to other log destinations (if any).
157 // Returns true to signal that it handled the message and the message
158 // should not be sent to other log destinations.
159 typedef bool (*LogMessageHandlerFunction)(int severity,
160 const char* file,
161 int line,
162 size_t message_start,
163 const std::string& str);
164 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
165 void SetLogMessageHandler(LogMessageHandlerFunction handler);
166 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
167 LogMessageHandlerFunction GetLogMessageHandler();
168
169 using LogSeverity = int;
170 constexpr LogSeverity LOGGING_VERBOSE = -1; // This is level 1 verbosity
171 // Note: the log severities are used to index into the array of names,
172 // see log_severity_names.
173 constexpr LogSeverity LOGGING_INFO = 0;
174 constexpr LogSeverity LOGGING_WARNING = 1;
175 constexpr LogSeverity LOGGING_ERROR = 2;
176 constexpr LogSeverity LOGGING_FATAL = 3;
177 constexpr LogSeverity LOGGING_NUM_SEVERITIES = 4;
178
179 // LOGGING_DFATAL is LOGGING_FATAL in DCHECK-enabled builds, ERROR in normal
180 // mode.
181 #if BUILDFLAG(PA_DCHECK_IS_ON)
182 constexpr LogSeverity LOGGING_DFATAL = LOGGING_FATAL;
183 #else
184 constexpr LogSeverity LOGGING_DFATAL = LOGGING_ERROR;
185 #endif
186
187 // This block duplicates the above entries to facilitate incremental conversion
188 // from LOG_FOO to LOGGING_FOO.
189 // TODO(thestig): Convert existing users to LOGGING_FOO and remove this block.
190 constexpr LogSeverity LOG_VERBOSE = LOGGING_VERBOSE;
191 constexpr LogSeverity LOG_INFO = LOGGING_INFO;
192 constexpr LogSeverity LOG_WARNING = LOGGING_WARNING;
193 constexpr LogSeverity LOG_ERROR = LOGGING_ERROR;
194 constexpr LogSeverity LOG_FATAL = LOGGING_FATAL;
195 constexpr LogSeverity LOG_DFATAL = LOGGING_DFATAL;
196
197 // A few definitions of macros that don't generate much code. These are used
198 // by PA_LOG() and LOG_IF, etc. Since these are used all over our code, it's
199 // better to have compact code for these operations.
200 #define PA_COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
201 ::partition_alloc::internal::logging::ClassName( \
202 __FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_INFO, \
203 ##__VA_ARGS__)
204 #define PA_COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
205 ::partition_alloc::internal::logging::ClassName( \
206 __FILE__, __LINE__, \
207 ::partition_alloc::internal::logging::LOGGING_WARNING, ##__VA_ARGS__)
208 #define PA_COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
209 ::partition_alloc::internal::logging::ClassName( \
210 __FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_ERROR, \
211 ##__VA_ARGS__)
212 #define PA_COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
213 ::partition_alloc::internal::logging::ClassName( \
214 __FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_FATAL, \
215 ##__VA_ARGS__)
216 #define PA_COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
217 ::partition_alloc::internal::logging::ClassName( \
218 __FILE__, __LINE__, \
219 ::partition_alloc::internal::logging::LOGGING_DFATAL, ##__VA_ARGS__)
220 #define PA_COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
221 ::partition_alloc::internal::logging::ClassName( \
222 __FILE__, __LINE__, \
223 ::partition_alloc::internal::logging::LOGGING_DCHECK, ##__VA_ARGS__)
224
225 #define PA_COMPACT_GOOGLE_LOG_INFO PA_COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
226 #define PA_COMPACT_GOOGLE_LOG_WARNING \
227 PA_COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage)
228 #define PA_COMPACT_GOOGLE_LOG_ERROR PA_COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage)
229 #define PA_COMPACT_GOOGLE_LOG_FATAL PA_COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage)
230 #define PA_COMPACT_GOOGLE_LOG_DFATAL PA_COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage)
231 #define PA_COMPACT_GOOGLE_LOG_DCHECK PA_COMPACT_GOOGLE_LOG_EX_DCHECK(LogMessage)
232
233 #if BUILDFLAG(IS_WIN)
234 // wingdi.h defines ERROR to be 0. When we call PA_LOG(ERROR), it gets
235 // substituted with 0, and it expands to PA_COMPACT_GOOGLE_LOG_0. To allow us
236 // to keep using this syntax, we define this macro to do the same thing
237 // as PA_COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that
238 // the Windows SDK does for consistency.
239 #define PA_ERROR 0
240 #define PA_COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \
241 PA_COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ##__VA_ARGS__)
242 #define PA_COMPACT_GOOGLE_LOG_0 PA_COMPACT_GOOGLE_LOG_ERROR
243 // Needed for LOG_IS_ON(ERROR).
244 constexpr LogSeverity LOGGING_0 = LOGGING_ERROR;
245 #endif
246
247 // As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also,
248 // LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will
249 // always fire if they fail.
250 #define PA_LOG_IS_ON(severity) \
251 (::partition_alloc::internal::logging::ShouldCreateLogMessage( \
252 ::partition_alloc::internal::logging::LOGGING_##severity))
253
254 // We don't do any caching tricks with VLOG_IS_ON() like the
255 // google-glog version since it increases binary size. This means
256 // that using the v-logging functions in conjunction with --vmodule
257 // may be slow.
258 #define PA_VLOG_IS_ON(verboselevel) \
259 ((verboselevel) <= ::partition_alloc::internal::logging::GetVlogVerbosity())
260
261 // Helper macro which avoids evaluating the arguments to a stream if
262 // the condition doesn't hold. Condition is evaluated once and only once.
263 #define PA_LAZY_STREAM(stream, condition) \
264 !(condition) \
265 ? (void)0 \
266 : ::partition_alloc::internal::logging::LogMessageVoidify() & (stream)
267
268 // We use the preprocessor's merging operator, "##", so that, e.g.,
269 // PA_LOG(INFO) becomes the token PA_COMPACT_GOOGLE_LOG_INFO. There's some
270 // funny subtle difference between ostream member streaming functions (e.g.,
271 // ostream::operator<<(int) and ostream non-member streaming functions
272 // (e.g., ::operator<<(ostream&, string&): it turns out that it's
273 // impossible to stream something like a string directly to an unnamed
274 // ostream. We employ a neat hack by calling the stream() member
275 // function of LogMessage which seems to avoid the problem.
276 #define PA_LOG_STREAM(severity) PA_COMPACT_GOOGLE_LOG_##severity.stream()
277
278 #define PA_LOG(severity) \
279 PA_LAZY_STREAM(PA_LOG_STREAM(severity), PA_LOG_IS_ON(severity))
280 #define PA_LOG_IF(severity, condition) \
281 PA_LAZY_STREAM(PA_LOG_STREAM(severity), PA_LOG_IS_ON(severity) && (condition))
282
283 // The VLOG macros log with negative verbosities.
284 #define PA_VLOG_STREAM(verbose_level) \
285 ::partition_alloc::internal::logging::LogMessage(__FILE__, __LINE__, \
286 -(verbose_level)) \
287 .stream()
288
289 #define PA_VLOG(verbose_level) \
290 PA_LAZY_STREAM(PA_VLOG_STREAM(verbose_level), PA_VLOG_IS_ON(verbose_level))
291
292 #define PA_VLOG_IF(verbose_level, condition) \
293 PA_LAZY_STREAM(PA_VLOG_STREAM(verbose_level), \
294 PA_VLOG_IS_ON(verbose_level) && (condition))
295
296 #if BUILDFLAG(IS_WIN)
297 #define PA_VPLOG_STREAM(verbose_level) \
298 ::partition_alloc::internal::logging::Win32ErrorLogMessage( \
299 __FILE__, __LINE__, -(verbose_level), \
300 ::partition_alloc::internal::logging::GetLastSystemErrorCode()) \
301 .stream()
302 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
303 #define PA_VPLOG_STREAM(verbose_level) \
304 ::partition_alloc::internal::logging::ErrnoLogMessage( \
305 __FILE__, __LINE__, -(verbose_level), \
306 ::partition_alloc::internal::logging::GetLastSystemErrorCode()) \
307 .stream()
308 #endif
309
310 #define PA_VPLOG(verbose_level) \
311 PA_LAZY_STREAM(PA_VPLOG_STREAM(verbose_level), PA_VLOG_IS_ON(verbose_level))
312
313 #define PA_VPLOG_IF(verbose_level, condition) \
314 PA_LAZY_STREAM(PA_VPLOG_STREAM(verbose_level), \
315 PA_VLOG_IS_ON(verbose_level) && (condition))
316
317 // TODO(akalin): Add more VLOG variants, e.g. VPLOG.
318
319 #define PA_LOG_ASSERT(condition) \
320 PA_LOG_IF(FATAL, !(PA_ANALYZER_ASSUME_TRUE(condition))) \
321 << "Assert failed: " #condition ". "
322
323 #if BUILDFLAG(IS_WIN)
324 #define PA_PLOG_STREAM(severity) \
325 PA_COMPACT_GOOGLE_LOG_EX_##severity( \
326 Win32ErrorLogMessage, \
327 ::partition_alloc::internal::logging::GetLastSystemErrorCode()) \
328 .stream()
329 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
330 #define PA_PLOG_STREAM(severity) \
331 PA_COMPACT_GOOGLE_LOG_EX_##severity( \
332 ErrnoLogMessage, \
333 ::partition_alloc::internal::logging::GetLastSystemErrorCode()) \
334 .stream()
335 #endif
336
337 #define PA_PLOG(severity) \
338 PA_LAZY_STREAM(PA_PLOG_STREAM(severity), PA_LOG_IS_ON(severity))
339
340 #define PA_PLOG_IF(severity, condition) \
341 PA_LAZY_STREAM(PA_PLOG_STREAM(severity), \
342 PA_LOG_IS_ON(severity) && (condition))
343
344 PA_COMPONENT_EXPORT(PARTITION_ALLOC) extern std::ostream* g_swallow_stream;
345
346 // Note that g_swallow_stream is used instead of an arbitrary PA_LOG() stream to
347 // avoid the creation of an object with a non-trivial destructor (LogMessage).
348 // On MSVC x86 (checked on 2015 Update 3), this causes a few additional
349 // pointless instructions to be emitted even at full optimization level, even
350 // though the : arm of the ternary operator is clearly never executed. Using a
351 // simpler object to be &'d with Voidify() avoids these extra instructions.
352 // Using a simpler POD object with a templated operator<< also works to avoid
353 // these instructions. However, this causes warnings on statically defined
354 // implementations of operator<<(std::ostream, ...) in some .cc files, because
355 // they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an
356 // ostream* also is not suitable, because some compilers warn of undefined
357 // behavior.
358 #define PA_EAT_STREAM_PARAMETERS \
359 true ? (void)0 \
360 : ::partition_alloc::internal::logging::LogMessageVoidify() & \
361 (*::partition_alloc::internal::logging::g_swallow_stream)
362
363 // Definitions for DLOG et al.
364
365 #if BUILDFLAG(PA_DCHECK_IS_ON)
366
367 #define PA_DLOG_IS_ON(severity) PA_LOG_IS_ON(severity)
368 #define PA_DLOG_IF(severity, condition) PA_LOG_IF(severity, condition)
369 #define PA_DLOG_ASSERT(condition) PA_LOG_ASSERT(condition)
370 #define PA_DPLOG_IF(severity, condition) PA_PLOG_IF(severity, condition)
371 #define PA_DVLOG_IF(verboselevel, condition) PA_VLOG_IF(verboselevel, condition)
372 #define PA_DVPLOG_IF(verboselevel, condition) \
373 PA_VPLOG_IF(verboselevel, condition)
374
375 #else // BUILDFLAG(PA_DCHECK_IS_ON)
376
377 // If !BUILDFLAG(PA_DCHECK_IS_ON), we want to avoid emitting any references to
378 // |condition| (which may reference a variable defined only if
379 // BUILDFLAG(PA_DCHECK_IS_ON)). Contrast this with DCHECK et al., which has
380 // different behavior.
381
382 #define PA_DLOG_IS_ON(severity) false
383 #define PA_DLOG_IF(severity, condition) PA_EAT_STREAM_PARAMETERS
384 #define PA_DLOG_ASSERT(condition) PA_EAT_STREAM_PARAMETERS
385 #define PA_DPLOG_IF(severity, condition) PA_EAT_STREAM_PARAMETERS
386 #define PA_DVLOG_IF(verboselevel, condition) PA_EAT_STREAM_PARAMETERS
387 #define PA_DVPLOG_IF(verboselevel, condition) PA_EAT_STREAM_PARAMETERS
388
389 #endif // BUILDFLAG(PA_DCHECK_IS_ON)
390
391 #define PA_DLOG(severity) \
392 PA_LAZY_STREAM(PA_LOG_STREAM(severity), PA_DLOG_IS_ON(severity))
393
394 #define PA_DPLOG(severity) \
395 PA_LAZY_STREAM(PA_PLOG_STREAM(severity), PA_DLOG_IS_ON(severity))
396
397 #define PA_DVLOG(verboselevel) PA_DVLOG_IF(verboselevel, true)
398
399 #define PA_DVPLOG(verboselevel) PA_DVPLOG_IF(verboselevel, true)
400
401 // Definitions for DCHECK et al.
402
403 #if BUILDFLAG(PA_DCHECK_IS_CONFIGURABLE)
404 PA_COMPONENT_EXPORT(PARTITION_ALLOC) extern LogSeverity LOGGING_DCHECK;
405 #else
406 constexpr LogSeverity LOGGING_DCHECK = LOGGING_FATAL;
407 #endif // BUILDFLAG(PA_DCHECK_IS_CONFIGURABLE)
408
409 // Redefine the standard assert to use our nice log files
410 #undef assert
411 #define assert(x) PA_DLOG_ASSERT(x)
412
413 // This class more or less represents a particular log message. You
414 // create an instance of LogMessage and then stream stuff to it.
415 // When you finish streaming to it, ~LogMessage is called and the
416 // full message gets streamed to the appropriate destination.
417 //
418 // You shouldn't actually use LogMessage's constructor to log things,
419 // though. You should use the PA_LOG() macro (and variants thereof)
420 // above.
PA_COMPONENT_EXPORT(PARTITION_ALLOC)421 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LogMessage {
422 public:
423 // Used for PA_LOG(severity).
424 LogMessage(const char* file, int line, LogSeverity severity);
425
426 // Used for CHECK(). Implied severity = LOGGING_FATAL.
427 LogMessage(const char* file, int line, const char* condition);
428 LogMessage(const LogMessage&) = delete;
429 LogMessage& operator=(const LogMessage&) = delete;
430 virtual ~LogMessage();
431
432 std::ostream& stream() { return stream_; }
433
434 LogSeverity severity() { return severity_; }
435 std::string str() { return stream_.str(); }
436
437 private:
438 void Init(const char* file, int line);
439
440 const LogSeverity severity_;
441 std::ostringstream stream_;
442 size_t message_start_; // Offset of the start of the message (past prefix
443 // info).
444 // The file and line information passed in to the constructor.
445 const char* const file_;
446 const int line_;
447
448 // This is useful since the LogMessage class uses a lot of Win32 calls
449 // that will lose the value of GLE and the code that called the log function
450 // will have lost the thread error value when the log call returns.
451 base::ScopedClearLastError last_error_;
452 };
453
454 // This class is used to explicitly ignore values in the conditional
455 // logging macros. This avoids compiler warnings like "value computed
456 // is not used" and "statement has no effect".
457 class LogMessageVoidify {
458 public:
459 LogMessageVoidify() = default;
460 // This has to be an operator with a precedence lower than << but
461 // higher than ?:
462 void operator&(std::ostream&) {}
463 };
464
465 #if BUILDFLAG(IS_WIN)
466 typedef unsigned long SystemErrorCode;
467 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
468 typedef int SystemErrorCode;
469 #endif
470
471 // Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to
472 // pull in windows.h just for GetLastError() and DWORD.
473 PA_COMPONENT_EXPORT(PARTITION_ALLOC) SystemErrorCode GetLastSystemErrorCode();
474 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
475 std::string SystemErrorCodeToString(SystemErrorCode error_code);
476
477 #if BUILDFLAG(IS_WIN)
478 // Appends a formatted system message of the GetLastError() type.
PA_COMPONENT_EXPORT(PARTITION_ALLOC)479 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) Win32ErrorLogMessage
480 : public LogMessage {
481 public:
482 Win32ErrorLogMessage(const char* file,
483 int line,
484 LogSeverity severity,
485 SystemErrorCode err);
486 Win32ErrorLogMessage(const Win32ErrorLogMessage&) = delete;
487 Win32ErrorLogMessage& operator=(const Win32ErrorLogMessage&) = delete;
488 // Appends the error message before destructing the encapsulated class.
489 ~Win32ErrorLogMessage() override;
490
491 private:
492 SystemErrorCode err_;
493 };
494 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
495 // Appends a formatted system message of the errno type
PA_COMPONENT_EXPORT(PARTITION_ALLOC)496 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ErrnoLogMessage : public LogMessage {
497 public:
498 ErrnoLogMessage(const char* file,
499 int line,
500 LogSeverity severity,
501 SystemErrorCode err);
502 ErrnoLogMessage(const ErrnoLogMessage&) = delete;
503 ErrnoLogMessage& operator=(const ErrnoLogMessage&) = delete;
504 // Appends the error message before destructing the encapsulated class.
505 ~ErrnoLogMessage() override;
506
507 private:
508 SystemErrorCode err_;
509 };
510 #endif // BUILDFLAG(IS_WIN)
511
512 // Async signal safe logging mechanism.
513 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
514 void RawLog(int level, const char* message);
515
516 #define PA_RAW_LOG(level, message) \
517 ::partition_alloc::internal::logging::RawLog( \
518 ::partition_alloc::internal::logging::LOGGING_##level, message)
519
520 } // namespace partition_alloc::internal::logging
521
522 #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_LOGGING_H_
523