vtv_utils.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* Copyright (C) 2012-2013
  2. Free Software Foundation
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3, or (at your option)
  7. any later version.
  8. GCC is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. /* This file is part of the vtable verication runtime library (see
  20. comments in vtv_rts.cc for more information about vtable
  21. verification). This file contains log file utilities. */
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <fcntl.h>
  25. #include <stdarg.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #if defined (__CYGWIN__) || defined (__MINGW32__)
  30. #include <windows.h>
  31. #else
  32. #include <execinfo.h>
  33. #endif
  34. #include <unistd.h>
  35. #include <errno.h>
  36. #include "vtv_utils.h"
  37. #ifndef HAVE_SECURE_GETENV
  38. # ifdef HAVE___SECURE_GETENV
  39. # define secure_getenv __secure_getenv
  40. # else
  41. # define secure_getenv getenv
  42. # endif
  43. #endif
  44. static int vtv_failures_log_fd = -1;
  45. /* This function takes the NAME of a log file to open, attempts to
  46. open it in the logs_dir directory, and returns the resulting file
  47. descriptor.
  48. This function first checks to see if the user has specifed (via
  49. the environment variable VTV_LOGS_DIR) a directory to use for the
  50. vtable verification logs. If that fails, the function will open
  51. the logs in the current directory.
  52. */
  53. int
  54. __vtv_open_log (const char *name)
  55. {
  56. char log_name[1024];
  57. char log_dir[512];
  58. #if defined (__CYGWIN__) || defined (__MINGW32__)
  59. pid_t process_id = GetCurrentProcessId ();
  60. #else
  61. uid_t user_id = getuid ();
  62. pid_t process_id = getpid ();
  63. #endif
  64. char *logs_prefix;
  65. bool logs_dir_specified = false;
  66. int fd = -1;
  67. logs_prefix = secure_getenv ("VTV_LOGS_DIR");
  68. if (logs_prefix && strlen (logs_prefix) > 0)
  69. {
  70. logs_dir_specified = true;
  71. #ifdef __MINGW32__
  72. mkdir (logs_prefix);
  73. #else
  74. mkdir (logs_prefix, S_IRWXU);
  75. #endif
  76. snprintf (log_dir, sizeof (log_dir), "%s/vtv_logs", logs_prefix);
  77. #ifdef __MINGW32__
  78. mkdir (log_dir);
  79. #else
  80. mkdir (log_dir, S_IRWXU);
  81. #endif
  82. #if defined (__CYGWIN__) || defined (__MINGW32__)
  83. snprintf (log_name, sizeof (log_name), "%s_%d_%s", log_dir,
  84. (unsigned) process_id, name);
  85. fd = open (log_name, O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
  86. #else
  87. snprintf (log_name, sizeof (log_name), "%s/%d_%d_%s", log_dir,
  88. (unsigned) user_id, (unsigned) process_id, name);
  89. fd = open (log_name, O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW,
  90. S_IRWXU);
  91. #endif
  92. }
  93. else
  94. fd = dup (2);
  95. if (fd == -1)
  96. __vtv_add_to_log (2, "Cannot open log file %s %s\n", name,
  97. strerror (errno));
  98. return fd;
  99. }
  100. /* This function takes a file descriptor (FD) and a string (STR) and
  101. tries to write the string to the file. */
  102. static int
  103. vtv_log_write (int fd, const char *str)
  104. {
  105. if (write (fd, str, strlen (str)) != -1)
  106. return 0;
  107. if (fd != 2) /* Make sure we dont get in a loop. */
  108. __vtv_add_to_log (2, "Error writing to log: %s\n", strerror (errno));
  109. return -1;
  110. }
  111. /* This function takes a file decriptor (LOG_FILE) and an output
  112. format string (FORMAT), followed by zero or more print format
  113. arguments (the same as fprintf, for example). It gets the current
  114. process ID and PPID, pre-pends them to the formatted message, and
  115. writes write it out to the log file referenced by LOG_FILE via calles
  116. to vtv_log_write. */
  117. int
  118. __vtv_add_to_log (int log_file, const char * format, ...)
  119. {
  120. /* We dont want to dynamically allocate this buffer. This should be
  121. more than enough in most cases. It if isn't we are careful not to
  122. do a buffer overflow. */
  123. char output[1024];
  124. va_list ap;
  125. va_start (ap, format);
  126. #if defined (__CYGWIN__) || defined (__MINGW32__)
  127. snprintf (output, sizeof (output), "VTV: PID=%ld ", GetCurrentProcessId ());
  128. #else
  129. snprintf (output, sizeof (output), "VTV: PID=%d PPID=%d ", getpid (),
  130. getppid ());
  131. #endif
  132. vtv_log_write (log_file, output);
  133. vsnprintf (output, sizeof (output), format, ap);
  134. vtv_log_write (log_file, output);
  135. va_end (ap);
  136. return 0;
  137. }
  138. /* Open error logging file, if not already open, and write vtable
  139. verification failure messages (LOG_MSG) to the log file. Also
  140. generate a backtrace in the log file, if GENERATE_BACKTRACE is
  141. set. */
  142. void
  143. __vtv_log_verification_failure (const char *log_msg, bool generate_backtrace)
  144. {
  145. if (vtv_failures_log_fd == -1)
  146. vtv_failures_log_fd = __vtv_open_log ("vtable_verification_failures.log");
  147. if (vtv_failures_log_fd == -1)
  148. return;
  149. __vtv_add_to_log (vtv_failures_log_fd, "%s", log_msg);
  150. #if !defined (__CYGWIN__) && !defined (__MINGW32__)
  151. if (generate_backtrace)
  152. {
  153. #define STACK_DEPTH 20
  154. void *callers[STACK_DEPTH];
  155. int actual_depth = backtrace (callers, STACK_DEPTH);
  156. backtrace_symbols_fd (callers, actual_depth, vtv_failures_log_fd);
  157. }
  158. #endif
  159. }