gdb: Don't skip prologue for explicit line breakpoints in assembler
[deliverable/binutils-gdb.git] / gdb / common / filestuff.c
index c829a8928321eda3ed28e809a1a619603104d3ff..c7b8c694055138cea1c66c89154f5251a70d2d50 100644 (file)
@@ -1,5 +1,5 @@
 /* Low-level file-handling.
-   Copyright (C) 2012-2015 Free Software Foundation, Inc.
+   Copyright (C) 2012-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -23,6 +23,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <algorithm>
 
 #ifdef USE_WIN32API
 #include <winsock2.h>
 #define HAVE_SOCKETS 1
 #endif
 
+#ifdef HAVE_KINFO_GETFILE
+#include <sys/user.h>
+#include <libutil.h>
+#endif
+
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif /* HAVE_SYS_RESOURCE_H */
 #define O_CLOEXEC 0
 #endif
 
+#ifndef O_NOINHERIT
+#define O_NOINHERIT 0
+#endif
+
 #ifndef SOCK_CLOEXEC
 #define SOCK_CLOEXEC 0
 #endif
@@ -79,7 +89,6 @@ fdwalk (int (*func) (void *, int), void *arg)
        {
          long fd;
          char *tail;
-         int result;
 
          errno = 0;
          fd = strtol (entry->d_name, &tail, 10);
@@ -104,6 +113,25 @@ fdwalk (int (*func) (void *, int), void *arg)
     }
   /* We may fall through to the next case.  */
 #endif
+#ifdef HAVE_KINFO_GETFILE
+  int nfd;
+  gdb::unique_xmalloc_ptr<struct kinfo_file[]> fdtbl
+    (kinfo_getfile (getpid (), &nfd));
+  if (fdtbl != NULL)
+    {
+      for (int i = 0; i < nfd; i++)
+       {
+         if (fdtbl[i].kf_fd >= 0)
+           {
+             int result = func (arg, fdtbl[i].kf_fd);
+             if (result != 0)
+               return result;
+           }
+       }
+      return 0;
+    }
+  /* We may fall through to the next case.  */
+#endif
 
   {
     int max, fd;
@@ -146,11 +174,10 @@ fdwalk (int (*func) (void *, int), void *arg)
 
 \f
 
-/* A VEC holding all the fds open when notice_open_fds was called.  We
-   don't use a hashtab because libiberty isn't linked into gdbserver;
-   and anyway we don't expect there to be many open fds.  */
+/* A vector holding all the fds open when notice_open_fds was called.  We
+   don't use a hashtab because we don't expect there to be many open fds.  */
 
-static VEC (int) *open_fds;
+static std::vector<int> open_fds;
 
 /* An fdwalk callback function used by notice_open_fds.  It puts the
    given file descriptor into the vec.  */
@@ -158,7 +185,7 @@ static VEC (int) *open_fds;
 static int
 do_mark_open_fd (void *ignore, int fd)
 {
-  VEC_safe_push (int, open_fds, fd);
+  open_fds.push_back (fd);
   return 0;
 }
 
@@ -183,18 +210,12 @@ mark_fd_no_cloexec (int fd)
 void
 unmark_fd_no_cloexec (int fd)
 {
-  int i, val;
-
-  for (i = 0; VEC_iterate (int, open_fds, i, val); ++i)
-    {
-      if (fd == val)
-       {
-         VEC_unordered_remove (int, open_fds, i);
-         return;
-       }
-    }
+  auto it = std::remove (open_fds.begin (), open_fds.end (), fd);
 
-  gdb_assert_not_reached (_("fd not found in open_fds"));
+  if (it != open_fds.end ())
+    open_fds.erase (it);
+  else
+    gdb_assert_not_reached (_("fd not found in open_fds"));
 }
 
 /* Helper function for close_most_fds that closes the file descriptor
@@ -203,9 +224,7 @@ unmark_fd_no_cloexec (int fd)
 static int
 do_close (void *ignore, int fd)
 {
-  int i, val;
-
-  for (i = 0; VEC_iterate (int, open_fds, i, val); ++i)
+  for (int val : open_fds)
     {
       if (fd == val)
        {
@@ -300,7 +319,7 @@ gdb_open_cloexec (const char *filename, int flags, unsigned long mode)
 
 /* See filestuff.h.  */
 
-FILE *
+gdb_file_up
 gdb_fopen_cloexec (const char *filename, const char *opentype)
 {
   FILE *result;
@@ -309,14 +328,16 @@ gdb_fopen_cloexec (const char *filename, const char *opentype)
      skip it.  E.g., the Windows runtime issues an "Invalid parameter
      passed to C runtime function" OutputDebugString warning for
      unknown modes.  Assume that if O_CLOEXEC is zero, then "e" isn't
-     supported.  */
-  static int fopen_e_ever_failed_einval = O_CLOEXEC == 0;
+     supported.  On MinGW, O_CLOEXEC is an alias of O_NOINHERIT, and
+     "e" isn't supported.  */
+  static int fopen_e_ever_failed_einval =
+    O_CLOEXEC == 0 || O_CLOEXEC == O_NOINHERIT;
 
   if (!fopen_e_ever_failed_einval)
     {
       char *copy;
 
-      copy = alloca (strlen (opentype) + 2);
+      copy = (char *) alloca (strlen (opentype) + 2);
       strcpy (copy, opentype);
       /* This is a glibc extension but we try it unconditionally on
         this path.  */
@@ -336,7 +357,7 @@ gdb_fopen_cloexec (const char *filename, const char *opentype)
   if (result != NULL)
     maybe_mark_cloexec (fileno (result));
 
-  return result;
+  return gdb_file_up (result);
 }
 
 #ifdef HAVE_SOCKETS
@@ -405,23 +426,78 @@ gdb_pipe_cloexec (int filedes[2])
   return result;
 }
 
-/* Helper function which does the work for make_cleanup_close.  */
+/* See common/filestuff.h.  */
 
-static void
-do_close_cleanup (void *arg)
+bool
+is_regular_file (const char *name, int *errno_ptr)
 {
-  int *fd = arg;
+  struct stat st;
+  const int status = stat (name, &st);
+
+  /* Stat should never fail except when the file does not exist.
+     If stat fails, analyze the source of error and return true
+     unless the file does not exist, to avoid returning false results
+     on obscure systems where stat does not work as expected.  */
 
-  close (*fd);
+  if (status != 0)
+    {
+      if (errno != ENOENT)
+       return true;
+      *errno_ptr = ENOENT;
+      return false;
+    }
+
+  if (S_ISREG (st.st_mode))
+    return true;
+
+  if (S_ISDIR (st.st_mode))
+    *errno_ptr = EISDIR;
+  else
+    *errno_ptr = EINVAL;
+  return false;
 }
 
-/* See cleanup-utils.h.  */
+/* See common/filestuff.h.  */
 
-struct cleanup *
-make_cleanup_close (int fd)
+bool
+mkdir_recursive (const char *dir)
 {
-  int *saved_fd = XNEW (int);
+  auto holder = make_unique_xstrdup (dir);
+  char * const start = holder.get ();
+  char *component_start = start;
+  char *component_end = start;
 
-  *saved_fd = fd;
-  return make_cleanup_dtor (do_close_cleanup, saved_fd, xfree);
+  while (1)
+    {
+      /* Find the beginning of the next component.  */
+      while (*component_start == '/')
+       component_start++;
+
+      /* Are we done?  */
+      if (*component_start == '\0')
+       return true;
+
+      /* Find the slash or null-terminator after this component.  */
+      component_end = component_start;
+      while (*component_end != '/' && *component_end != '\0')
+       component_end++;
+
+      /* Temporarily replace the slash with a null terminator, so we can create
+         the directory up to this component.  */
+      char saved_char = *component_end;
+      *component_end = '\0';
+
+      /* If we get EEXIST and the existing path is a directory, then we're
+         happy.  If it exists, but it's a regular file and this is not the last
+         component, we'll fail at the next component.  If this is the last
+         component, the caller will fail with ENOTDIR when trying to
+         open/create a file under that path.  */
+      if (mkdir (start, 0700) != 0)
+       if (errno != EEXIST)
+         return false;
+
+      /* Restore the overwritten char.  */
+      *component_end = saved_char;
+      component_start = component_end;
+    }
 }
This page took 0.027605 seconds and 4 git commands to generate.