summaryrefslogtreecommitdiffstats
path: root/mozglue/misc/Debug.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mozglue/misc/Debug.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/mozglue/misc/Debug.cpp b/mozglue/misc/Debug.cpp
new file mode 100644
index 0000000000..c3a2ca89e0
--- /dev/null
+++ b/mozglue/misc/Debug.cpp
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/glue/Debug.h"
+#include "mozilla/Fuzzing.h"
+#include "mozilla/Sprintf.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifdef XP_WIN
+# include <io.h>
+# include <windows.h>
+#endif
+
+#ifdef ANDROID
+# include <android/log.h>
+#endif
+
+#ifndef ANDROID
+static void vprintf_stderr_buffered(const char* aFmt, va_list aArgs) {
+ // Avoid interleaving by writing to an on-stack buffer and then writing in one
+ // go with fputs, as long as the output fits into the buffer.
+ char buffer[1024];
+ va_list argsCpy;
+ va_copy(argsCpy, aArgs);
+ int n = VsprintfLiteral(buffer, aFmt, aArgs);
+ if (n < int(sizeof(buffer))) {
+ fputs(buffer, stderr);
+ } else {
+ // Message too long for buffer. Just print it, not worrying about
+ // interleaving. (We could malloc, but the underlying write() syscall could
+ // get interleaved if the output is too big anyway.)
+ vfprintf(stderr, aFmt, argsCpy);
+ }
+ va_end(argsCpy);
+ fflush(stderr);
+}
+#endif
+
+#if defined(XP_WIN)
+MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
+ if (IsDebuggerPresent()) {
+ int lengthNeeded = _vscprintf(aFmt, aArgs);
+ if (lengthNeeded) {
+ lengthNeeded++;
+ auto buf = mozilla::MakeUnique<char[]>(lengthNeeded);
+ if (buf) {
+ va_list argsCpy;
+ va_copy(argsCpy, aArgs);
+ vsnprintf(buf.get(), lengthNeeded, aFmt, argsCpy);
+ buf[lengthNeeded - 1] = '\0';
+ va_end(argsCpy);
+ OutputDebugStringA(buf.get());
+ }
+ }
+ }
+
+ vprintf_stderr_buffered(aFmt, aArgs);
+}
+
+#elif defined(ANDROID)
+MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
+ __android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, aArgs);
+}
+#elif defined(FUZZING_SNAPSHOT)
+MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
+ if (nyx_puts) {
+ auto msgbuf = mozilla::Vsmprintf(aFmt, aArgs);
+ nyx_puts(msgbuf.get());
+ } else {
+ vprintf_stderr_buffered(aFmt, aArgs);
+ }
+}
+#else
+MFBT_API void vprintf_stderr(const char* aFmt, va_list aArgs) {
+ vprintf_stderr_buffered(aFmt, aArgs);
+}
+#endif
+
+MFBT_API void printf_stderr(const char* aFmt, ...) {
+ va_list args;
+ va_start(args, aFmt);
+ vprintf_stderr(aFmt, args);
+ va_end(args);
+}
+
+MFBT_API void fprintf_stderr(FILE* aFile, const char* aFmt, ...) {
+ va_list args;
+ va_start(args, aFmt);
+ if (aFile == stderr) {
+ vprintf_stderr(aFmt, args);
+ } else {
+ vfprintf(aFile, aFmt, args);
+ }
+ va_end(args);
+}
+
+MFBT_API void print_stderr(std::stringstream& aStr) {
+#if defined(ANDROID)
+ // On Android logcat output is truncated to 1024 chars per line, and
+ // we usually use std::stringstream to build up giant multi-line gobs
+ // of output. So to avoid the truncation we find the newlines and
+ // print the lines individually.
+ std::string line;
+ while (std::getline(aStr, line)) {
+ printf_stderr("%s\n", line.c_str());
+ }
+#else
+ printf_stderr("%s", aStr.str().c_str());
+#endif
+}
+
+MFBT_API void fprint_stderr(FILE* aFile, std::stringstream& aStr) {
+ if (aFile == stderr) {
+ print_stderr(aStr);
+ } else {
+ fprintf_stderr(aFile, "%s", aStr.str().c_str());
+ }
+}