internal_logging.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. // Copyright (c) 2005, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // ---
  31. // Sanjay Ghemawat <opensource@google.com>
  32. #include <config.h>
  33. #include "internal_logging.h"
  34. #include <stdarg.h> // for va_end, va_start
  35. #include <stdio.h> // for vsnprintf, va_list, etc
  36. #include <stdlib.h> // for abort
  37. #include <string.h> // for strlen, memcpy
  38. #ifdef HAVE_UNISTD_H
  39. #include <unistd.h> // for write()
  40. #endif
  41. #include <gperftools/malloc_extension.h>
  42. #include "base/logging.h" // for perftools_vsnprintf
  43. #include "base/spinlock.h" // for SpinLockHolder, SpinLock
  44. #ifndef TCMALLOC_SGX
  45. // Variables for storing crash output. Allocated statically since we
  46. // may not be able to heap-allocate while crashing.
  47. static SpinLock crash_lock(base::LINKER_INITIALIZED);
  48. static bool crashed = false;
  49. static const int kStatsBufferSize = 16 << 10;
  50. static char stats_buffer[kStatsBufferSize] = { 0 };
  51. #endif
  52. namespace tcmalloc {
  53. static void WriteMessage(const char* msg, int length) {
  54. write(STDERR_FILENO, msg, length);
  55. }
  56. void (*log_message_writer)(const char* msg, int length) = WriteMessage;
  57. #ifndef TCMALLOC_SGX
  58. class Logger {
  59. public:
  60. bool Add(const LogItem& item);
  61. bool AddStr(const char* str, int n);
  62. bool AddNum(uint64_t num, int base); // base must be 10 or 16.
  63. static const int kBufSize = 200;
  64. char* p_;
  65. char* end_;
  66. char buf_[kBufSize];
  67. };
  68. #endif
  69. void Log(LogMode mode, const char* filename, int line,
  70. LogItem a, LogItem b, LogItem c, LogItem d) {
  71. /*In SGX will not output any messages, only abort current program if reach here*/
  72. #ifndef TCMALLOC_SGX
  73. Logger state;
  74. state.p_ = state.buf_;
  75. state.end_ = state.buf_ + sizeof(state.buf_);
  76. state.AddStr(filename, strlen(filename))
  77. && state.AddStr(":", 1)
  78. && state.AddNum(line, 10)
  79. && state.AddStr("]", 1)
  80. && state.Add(a)
  81. && state.Add(b)
  82. && state.Add(c)
  83. && state.Add(d);
  84. // Teminate with newline
  85. if (state.p_ >= state.end_) {
  86. state.p_ = state.end_ - 1;
  87. }
  88. *state.p_ = '\n';
  89. state.p_++;
  90. int msglen = state.p_ - state.buf_;
  91. if (mode == kLog) {
  92. (*log_message_writer)(state.buf_, msglen);
  93. return;
  94. }
  95. bool first_crash = false;
  96. {
  97. SpinLockHolder l(&crash_lock);
  98. if (!crashed) {
  99. crashed = true;
  100. first_crash = true;
  101. }
  102. }
  103. (*log_message_writer)(state.buf_, msglen);
  104. if (first_crash && mode == kCrashWithStats) {
  105. MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize);
  106. (*log_message_writer)(stats_buffer, strlen(stats_buffer));
  107. }
  108. #else
  109. if(mode == kLog) {
  110. return;
  111. }
  112. #endif
  113. abort();
  114. }
  115. #ifndef TCMALLOC_SGX
  116. bool Logger::Add(const LogItem& item) {
  117. // Separate items with spaces
  118. if (p_ < end_) {
  119. *p_ = ' ';
  120. p_++;
  121. }
  122. switch (item.tag_) {
  123. case LogItem::kStr:
  124. return AddStr(item.u_.str, strlen(item.u_.str));
  125. case LogItem::kUnsigned:
  126. return AddNum(item.u_.unum, 10);
  127. case LogItem::kSigned:
  128. if (item.u_.snum < 0) {
  129. // The cast to uint64_t is intentionally before the negation
  130. // so that we do not attempt to negate -2^63.
  131. return AddStr("-", 1)
  132. && AddNum(- static_cast<uint64_t>(item.u_.snum), 10);
  133. } else {
  134. return AddNum(static_cast<uint64_t>(item.u_.snum), 10);
  135. }
  136. case LogItem::kPtr:
  137. return AddStr("0x", 2)
  138. && AddNum(reinterpret_cast<uintptr_t>(item.u_.ptr), 16);
  139. default:
  140. return false;
  141. }
  142. }
  143. bool Logger::AddStr(const char* str, int n) {
  144. if (end_ - p_ < n) {
  145. return false;
  146. } else {
  147. memcpy(p_, str, n);
  148. p_ += n;
  149. return true;
  150. }
  151. }
  152. bool Logger::AddNum(uint64_t num, int base) {
  153. static const char kDigits[] = "0123456789abcdef";
  154. char space[22]; // more than enough for 2^64 in smallest supported base (10)
  155. char* end = space + sizeof(space);
  156. char* pos = end;
  157. do {
  158. pos--;
  159. *pos = kDigits[num % base];
  160. num /= base;
  161. } while (num > 0 && pos > space);
  162. return AddStr(pos, end - pos);
  163. }
  164. #endif
  165. } // end tcmalloc namespace
  166. void TCMalloc_Printer::printf(const char* format, ...) {
  167. #ifndef TCMALLOC_SGX
  168. if (left_ > 0) {
  169. va_list ap;
  170. va_start(ap, format);
  171. const int r = perftools_vsnprintf(buf_, left_, format, ap);
  172. va_end(ap);
  173. if (r < 0) {
  174. // Perhaps an old glibc that returns -1 on truncation?
  175. left_ = 0;
  176. } else if (r > left_) {
  177. // Truncation
  178. left_ = 0;
  179. } else {
  180. left_ -= r;
  181. buf_ += r;
  182. }
  183. }
  184. #endif
  185. }