aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libvtv/vtv_utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libvtv/vtv_utils.cc')
-rw-r--r--gcc-4.9/libvtv/vtv_utils.cc161
1 files changed, 161 insertions, 0 deletions
diff --git a/gcc-4.9/libvtv/vtv_utils.cc b/gcc-4.9/libvtv/vtv_utils.cc
new file mode 100644
index 000000000..9cf4b08dc
--- /dev/null
+++ b/gcc-4.9/libvtv/vtv_utils.cc
@@ -0,0 +1,161 @@
+/* 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>
+#include <execinfo.h>
+#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];
+ uid_t user_id = getuid ();
+ pid_t process_id = getpid ();
+ 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;
+ mkdir (logs_prefix, S_IRWXU);
+ snprintf (log_dir, sizeof (log_dir), "%s/vtv_logs", logs_prefix);
+ mkdir (log_dir, S_IRWXU);
+
+ 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);
+ }
+ 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);
+
+ snprintf (output, sizeof (output), "VTV: PID=%d PPID=%d ", getpid (),
+ getppid ());
+ 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 (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);
+ }
+}