vtv_utils.cc 5.5 KB

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