Fix typos.
[gcc.git] / libbacktrace / fileline.c
index de2a58993eb065e4921ee6cf79b3aa9b9315b1b5..e5c39be8e0e406ac34b6ab970c1ea6d3ea01b9a9 100644 (file)
@@ -1,5 +1,5 @@
 /* fileline.c -- Get file and line number information in a backtrace.
-   Copyright (C) 2012 Free Software Foundation, Inc.
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 Redistribution and use in source and binary forms, with or without
@@ -34,11 +34,17 @@ POSSIBILITY OF SUCH DAMAGE.  */
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <stdlib.h>
 
 #include "backtrace.h"
 #include "internal.h"
 
+#ifndef HAVE_GETEXECNAME
+#define getexecname() NULL
+#endif
+
 /* Initialize the fileline information from the executable.  Returns 1
    on success, 0 on failure.  */
 
@@ -48,6 +54,8 @@ fileline_initialize (struct backtrace_state *state,
 {
   int failed;
   fileline fileline_fn;
+  int pass;
+  int called_error_callback;
   int descriptor;
 
   failed = state->fileline_initialization_failed;
@@ -62,7 +70,7 @@ fileline_initialize (struct backtrace_state *state,
 
   if (failed)
     {
-      error_callback (data, "failed to read executable information", 0);
+      error_callback (data, "failed to read executable information", -1);
       return 0;
     }
 
@@ -78,12 +86,58 @@ fileline_initialize (struct backtrace_state *state,
 
   /* We have not initialized the information.  Do it now.  */
 
-  if (state->filename != NULL)
-    descriptor = backtrace_open (state->filename, error_callback, data);
-  else
-    descriptor = backtrace_open ("/proc/self/exe", error_callback, data);
+  descriptor = -1;
+  called_error_callback = 0;
+  for (pass = 0; pass < 4; ++pass)
+    {
+      const char *filename;
+      int does_not_exist;
+
+      switch (pass)
+       {
+       case 0:
+         filename = state->filename;
+         break;
+       case 1:
+         filename = getexecname ();
+         break;
+       case 2:
+         filename = "/proc/self/exe";
+         break;
+       case 3:
+         filename = "/proc/curproc/file";
+         break;
+       default:
+         abort ();
+       }
+
+      if (filename == NULL)
+       continue;
+
+      descriptor = backtrace_open (filename, error_callback, data,
+                                  &does_not_exist);
+      if (descriptor < 0 && !does_not_exist)
+       {
+         called_error_callback = 1;
+         break;
+       }
+      if (descriptor >= 0)
+       break;
+    }
+
   if (descriptor < 0)
-    failed = 1;
+    {
+      if (!called_error_callback)
+       {
+         if (state->filename != NULL)
+           error_callback (data, state->filename, ENOENT);
+         else
+           error_callback (data,
+                           "libbacktrace could not find executable to open",
+                           0);
+       }
+      failed = 1;
+    }
 
   if (!failed)
     {