github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/third_party/gofrontend/libbacktrace/fileline.c (about)

     1  /* fileline.c -- Get file and line number information in a backtrace.
     2     Copyright (C) 2012-2015 Free Software Foundation, Inc.
     3     Written by Ian Lance Taylor, Google.
     4  
     5  Redistribution and use in source and binary forms, with or without
     6  modification, are permitted provided that the following conditions are
     7  met:
     8  
     9      (1) Redistributions of source code must retain the above copyright
    10      notice, this list of conditions and the following disclaimer. 
    11  
    12      (2) Redistributions in binary form must reproduce the above copyright
    13      notice, this list of conditions and the following disclaimer in
    14      the documentation and/or other materials provided with the
    15      distribution.  
    16      
    17      (3) The name of the author may not be used to
    18      endorse or promote products derived from this software without
    19      specific prior written permission.
    20  
    21  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    22  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    23  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    24  DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
    25  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    26  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    27  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    28  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    29  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
    30  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    31  POSSIBILITY OF SUCH DAMAGE.  */
    32  
    33  #include "config.h"
    34  
    35  #include <sys/types.h>
    36  #include <sys/stat.h>
    37  #include <errno.h>
    38  #include <fcntl.h>
    39  #include <stdlib.h>
    40  
    41  #include "backtrace.h"
    42  #include "internal.h"
    43  
    44  #ifndef HAVE_GETEXECNAME
    45  #define getexecname() NULL
    46  #endif
    47  
    48  /* Initialize the fileline information from the executable.  Returns 1
    49     on success, 0 on failure.  */
    50  
    51  static int
    52  fileline_initialize (struct backtrace_state *state,
    53  		     backtrace_error_callback error_callback, void *data)
    54  {
    55    int failed;
    56    fileline fileline_fn;
    57    int pass;
    58    int called_error_callback;
    59    int descriptor;
    60  
    61    if (!state->threaded)
    62      failed = state->fileline_initialization_failed;
    63    else
    64      failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
    65  
    66    if (failed)
    67      {
    68        error_callback (data, "failed to read executable information", -1);
    69        return 0;
    70      }
    71  
    72    if (!state->threaded)
    73      fileline_fn = state->fileline_fn;
    74    else
    75      fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
    76    if (fileline_fn != NULL)
    77      return 1;
    78  
    79    /* We have not initialized the information.  Do it now.  */
    80  
    81    descriptor = -1;
    82    called_error_callback = 0;
    83    for (pass = 0; pass < 4; ++pass)
    84      {
    85        const char *filename;
    86        int does_not_exist;
    87  
    88        switch (pass)
    89  	{
    90  	case 0:
    91  	  filename = state->filename;
    92  	  break;
    93  	case 1:
    94  	  filename = getexecname ();
    95  	  break;
    96  	case 2:
    97  	  filename = "/proc/self/exe";
    98  	  break;
    99  	case 3:
   100  	  filename = "/proc/curproc/file";
   101  	  break;
   102  	default:
   103  	  abort ();
   104  	}
   105  
   106        if (filename == NULL)
   107  	continue;
   108  
   109        descriptor = backtrace_open (filename, error_callback, data,
   110  				   &does_not_exist);
   111        if (descriptor < 0 && !does_not_exist)
   112  	{
   113  	  called_error_callback = 1;
   114  	  break;
   115  	}
   116        if (descriptor >= 0)
   117  	break;
   118      }
   119  
   120    if (descriptor < 0)
   121      {
   122        if (!called_error_callback)
   123  	{
   124  	  if (state->filename != NULL)
   125  	    error_callback (data, state->filename, ENOENT);
   126  	  else
   127  	    error_callback (data,
   128  			    "libbacktrace could not find executable to open",
   129  			    0);
   130  	}
   131        failed = 1;
   132      }
   133  
   134    if (!failed)
   135      {
   136        if (!backtrace_initialize (state, descriptor, error_callback, data,
   137  				 &fileline_fn))
   138  	failed = 1;
   139      }
   140  
   141    if (failed)
   142      {
   143        if (!state->threaded)
   144  	state->fileline_initialization_failed = 1;
   145        else
   146  	backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
   147        return 0;
   148      }
   149  
   150    if (!state->threaded)
   151      state->fileline_fn = fileline_fn;
   152    else
   153      {
   154        backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
   155  
   156        /* Note that if two threads initialize at once, one of the data
   157  	 sets may be leaked.  */
   158      }
   159  
   160    return 1;
   161  }
   162  
   163  /* Given a PC, find the file name, line number, and function name.  */
   164  
   165  int
   166  backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
   167  		  backtrace_full_callback callback,
   168  		  backtrace_error_callback error_callback, void *data)
   169  {
   170    if (!fileline_initialize (state, error_callback, data))
   171      return 0;
   172  
   173    if (state->fileline_initialization_failed)
   174      return 0;
   175  
   176    return state->fileline_fn (state, pc, callback, error_callback, data);
   177  }
   178  
   179  /* Given a PC, find the symbol for it, and its value.  */
   180  
   181  int
   182  backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
   183  		   backtrace_syminfo_callback callback,
   184  		   backtrace_error_callback error_callback, void *data)
   185  {
   186    if (!fileline_initialize (state, error_callback, data))
   187      return 0;
   188  
   189    if (state->fileline_initialization_failed)
   190      return 0;
   191  
   192    state->syminfo_fn (state, pc, callback, error_callback, data);
   193    return 1;
   194  }