123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- /* Copyright (C) 2012-2013
- Free Software Foundation
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- /* This file is part of the vtable verication runtime library (see
- comments in vtv_rts.cc for more information about vtable
- verification). This file contains log file utilities. */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #if defined (__CYGWIN__) || defined (__MINGW32__)
- #include <windows.h>
- #else
- #include <execinfo.h>
- #endif
- #include <unistd.h>
- #include <errno.h>
- #include "vtv_utils.h"
- #ifndef HAVE_SECURE_GETENV
- # ifdef HAVE___SECURE_GETENV
- # define secure_getenv __secure_getenv
- # else
- # define secure_getenv getenv
- # endif
- #endif
- static int vtv_failures_log_fd = -1;
- /* This function takes the NAME of a log file to open, attempts to
- open it in the logs_dir directory, and returns the resulting file
- descriptor.
- This function first checks to see if the user has specifed (via
- the environment variable VTV_LOGS_DIR) a directory to use for the
- vtable verification logs. If that fails, the function will open
- the logs in the current directory.
- */
- int
- __vtv_open_log (const char *name)
- {
- char log_name[1024];
- char log_dir[512];
- #if defined (__CYGWIN__) || defined (__MINGW32__)
- pid_t process_id = GetCurrentProcessId ();
- #else
- uid_t user_id = getuid ();
- pid_t process_id = getpid ();
- #endif
- char *logs_prefix;
- bool logs_dir_specified = false;
- int fd = -1;
- logs_prefix = secure_getenv ("VTV_LOGS_DIR");
- if (logs_prefix && strlen (logs_prefix) > 0)
- {
- logs_dir_specified = true;
- #ifdef __MINGW32__
- mkdir (logs_prefix);
- #else
- mkdir (logs_prefix, S_IRWXU);
- #endif
- snprintf (log_dir, sizeof (log_dir), "%s/vtv_logs", logs_prefix);
- #ifdef __MINGW32__
- mkdir (log_dir);
- #else
- mkdir (log_dir, S_IRWXU);
- #endif
- #if defined (__CYGWIN__) || defined (__MINGW32__)
- snprintf (log_name, sizeof (log_name), "%s_%d_%s", log_dir,
- (unsigned) process_id, name);
- fd = open (log_name, O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
- #else
- snprintf (log_name, sizeof (log_name), "%s/%d_%d_%s", log_dir,
- (unsigned) user_id, (unsigned) process_id, name);
- fd = open (log_name, O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW,
- S_IRWXU);
- #endif
- }
- else
- fd = dup (2);
- if (fd == -1)
- __vtv_add_to_log (2, "Cannot open log file %s %s\n", name,
- strerror (errno));
- return fd;
- }
- /* This function takes a file descriptor (FD) and a string (STR) and
- tries to write the string to the file. */
- static int
- vtv_log_write (int fd, const char *str)
- {
- if (write (fd, str, strlen (str)) != -1)
- return 0;
- if (fd != 2) /* Make sure we dont get in a loop. */
- __vtv_add_to_log (2, "Error writing to log: %s\n", strerror (errno));
- return -1;
- }
- /* This function takes a file decriptor (LOG_FILE) and an output
- format string (FORMAT), followed by zero or more print format
- arguments (the same as fprintf, for example). It gets the current
- process ID and PPID, pre-pends them to the formatted message, and
- writes write it out to the log file referenced by LOG_FILE via calles
- to vtv_log_write. */
- int
- __vtv_add_to_log (int log_file, const char * format, ...)
- {
- /* We dont want to dynamically allocate this buffer. This should be
- more than enough in most cases. It if isn't we are careful not to
- do a buffer overflow. */
- char output[1024];
- va_list ap;
- va_start (ap, format);
- #if defined (__CYGWIN__) || defined (__MINGW32__)
- snprintf (output, sizeof (output), "VTV: PID=%ld ", GetCurrentProcessId ());
- #else
- snprintf (output, sizeof (output), "VTV: PID=%d PPID=%d ", getpid (),
- getppid ());
- #endif
- vtv_log_write (log_file, output);
- vsnprintf (output, sizeof (output), format, ap);
- vtv_log_write (log_file, output);
- va_end (ap);
- return 0;
- }
- /* Open error logging file, if not already open, and write vtable
- verification failure messages (LOG_MSG) to the log file. Also
- generate a backtrace in the log file, if GENERATE_BACKTRACE is
- set. */
- void
- __vtv_log_verification_failure (const char *log_msg, bool generate_backtrace)
- {
- if (vtv_failures_log_fd == -1)
- vtv_failures_log_fd = __vtv_open_log ("vtable_verification_failures.log");
- if (vtv_failures_log_fd == -1)
- return;
- __vtv_add_to_log (vtv_failures_log_fd, "%s", log_msg);
- #if !defined (__CYGWIN__) && !defined (__MINGW32__)
- if (generate_backtrace)
- {
- #define STACK_DEPTH 20
- void *callers[STACK_DEPTH];
- int actual_depth = backtrace (callers, STACK_DEPTH);
- backtrace_symbols_fd (callers, actual_depth, vtv_failures_log_fd);
- }
- #endif
- }
|