(linenum→info "unix/slp.c:2238")

glibc/2.7/elf/dl-error.c

    1: /* Error handling for runtime dynamic linker.
    2:    Copyright (C) 1995-2002,2004,2005 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <libintl.h>
   21: #include <setjmp.h>
   22: #include <stdbool.h>
   23: #include <stdlib.h>
   24: #include <string.h>
   25: #include <unistd.h>
   26: #include <ldsodefs.h>
   27: 
   28: /* This structure communicates state between _dl_catch_error and
   29:    _dl_signal_error.  */
   30: struct catch
   31:   {
   32:     const char *objname;        /* Object/File name.  */
   33:     const char *errstring;      /* Error detail filled in here.  */
   34:     bool malloced;              /* Nonzero if the string is malloced
   35:                                    by the libc malloc.  */
   36:     jmp_buf env;                /* longjmp here on error.  */
   37:   };
   38: 
   39: /* Multiple threads at once can use the `_dl_catch_error' function.  The
   40:    calls can come from `_dl_map_object_deps', `_dlerror_run', or from
   41:    any of the libc functionality which loads dynamic objects (NSS, iconv).
   42:    Therefore we have to be prepared to save the state in thread-local
   43:    memory.  The _dl_error_catch_tsd function pointer is reset by the thread
   44:    library so that it returns the address of a thread-local variable.  */
   45: 
   46: 
   47: /* This message we return as a last resort.  We define the string in a
   48:    variable since we have to avoid freeing it and so have to enable
   49:    a pointer comparison.  See below and in dlfcn/dlerror.c.  */
   50: static const char _dl_out_of_memory[] = "out of memory";
   51: 
   52: 
   53: /* This points to a function which is called when an continuable error is
   54:    received.  Unlike the handling of `catch' this function may return.
   55:    The arguments will be the `errstring' and `objname'.
   56: 
   57:    Since this functionality is not used in normal programs (only in ld.so)
   58:    we do not care about multi-threaded programs here.  We keep this as a
   59:    global variable.  */
   60: static receiver_fct receiver;
   61: 
   62: #ifdef _LIBC_REENTRANT
   63: # define CATCH_HOOK     (*(struct catch **) (*GL(dl_error_catch_tsd)) ())
   64: #else
   65: static struct catch *catch_hook;
   66: # define CATCH_HOOK     catch_hook
   67: #endif
   68: 
   69: void
   70: internal_function
   71: _dl_signal_error (int errcode, const char *objname, const char *occation,
   72:                   const char *errstring)
   73: {
   74:   struct catch *lcatch;
   75: 
   76:   if (! errstring)
   77:     errstring = N_("DYNAMIC LINKER BUG!!!");
   78: 
   79:   lcatch = CATCH_HOOK;
   80:   if (objname == NULL)
   81:     objname = "";
   82:   if (lcatch != NULL)
   83:     {
   84:       /* We are inside _dl_catch_error.  Return to it.  We have to
   85:          duplicate the error string since it might be allocated on the
   86:          stack.  The object name is always a string constant.  */
   87:       size_t len_objname = strlen (objname) + 1;
   88:       size_t len_errstring = strlen (errstring) + 1;
   89: 
   90:       lcatch->errstring = (char *) malloc (len_objname + len_errstring);
   91:       if (lcatch->errstring != NULL)
   92:         {
   93:           /* Make a copy of the object file name and the error string.  */
   94:           lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring,
   95:                                                errstring, len_errstring),
   96:                                     objname, len_objname);
   97: 
   98:           /* If the main executable is relocated it means the libc's malloc
   99:              is used.  */
  100: #ifdef SHARED
  101:           lcatch->malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL
  102:                               && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated
  103:                                   != 0));
  104: #else
  105:           lcatch->malloced = true;
  106: #endif
  107:         }
  108:       else
  109:         {
  110:           /* This is better than nothing.  */
  111:           lcatch->objname = "";
  112:           lcatch->errstring = _dl_out_of_memory;
  113:           lcatch->malloced = false;
  114:         }
  115:       /* We do not restore the signal mask because none was saved.  */
  116:       __longjmp (lcatch->env[0].__jmpbuf, errcode ?: -1);
  117:     }
  118:   else
  119:     {
  120:       /* Lossage while resolving the program's own symbols is always fatal.  */
  121:       char buffer[1024];
  122:       _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
  123:                         rtld_progname ?: "<program name unknown>",
  124:                         occation ?: N_("error while loading shared libraries"),
  125:                         objname, *objname ? ": " : "",
  126:                         errstring, errcode ? ": " : "",
  127:                         (errcode
  128:                          ? __strerror_r (errcode, buffer, sizeof buffer)
  129:                          : ""));
  130:     }
  131: }
  132: 
  133: 
  134: void
  135: internal_function
  136: _dl_signal_cerror (int errcode, const char *objname, const char *occation,
  137:                    const char *errstring)
  138: {
  139:   if (__builtin_expect (GLRO(dl_debug_mask)
  140:                         & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
  141:     _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation,
  142:                       errstring, receiver ? "continued" : "fatal");
  143: 
  144:   if (receiver)
  145:     {
  146:       /* We are inside _dl_receive_error.  Call the user supplied
  147:          handler and resume the work.  The receiver will still be
  148:          installed.  */
  149:       (*receiver) (errcode, objname, errstring);
  150:     }
  151:   else
  152:     _dl_signal_error (errcode, objname, occation, errstring);
  153: }
  154: 
  155: 
  156: int
  157: internal_function
  158: _dl_catch_error (const char **objname, const char **errstring,
  159:                  bool *mallocedp, void (*operate) (void *), void *args)
  160: {
  161:   int errcode;
  162:   struct catch *volatile old;
  163:   struct catch c;
  164:   /* We need not handle `receiver' since setting a `catch' is handled
  165:      before it.  */
  166: 
  167:   /* Some systems (e.g., SPARC) handle constructors to local variables
  168:      inefficient.  So we initialize `c' by hand.  */
  169:   c.errstring = NULL;
  170: 
  171:   struct catch **const catchp = &CATCH_HOOK;
  172:   old = *catchp;
  173:   /* Do not save the signal mask.  */
  174:   errcode = __sigsetjmp (c.env, 0);
  175:   if (__builtin_expect (errcode, 0) == 0)
  176:     {
  177:       *catchp = &c;
  178:       (*operate) (args);
  179:       *catchp = old;
  180:       *objname = NULL;
  181:       *errstring = NULL;
  182:       *mallocedp = false;
  183:       return 0;
  184:     }
  185: 
  186:   /* We get here only if we longjmp'd out of OPERATE.  */
  187:   *catchp = old;
  188:   *objname = c.objname;
  189:   *errstring = c.errstring;
  190:   *mallocedp = c.malloced;
  191:   return errcode == -1 ? 0 : errcode;
  192: }
  193: 
  194: 
  195: void
  196: internal_function
  197: _dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
  198: {
  199:   struct catch **const catchp = &CATCH_HOOK;
  200:   struct catch *old_catch;
  201:   receiver_fct old_receiver;
  202: 
  203:   old_catch = *catchp;
  204:   old_receiver = receiver;
  205: 
  206:   /* Set the new values.  */
  207:   *catchp = NULL;
  208:   receiver = fct;
  209: 
  210:   (*operate) (args);
  211: 
  212:   *catchp = old_catch;
  213:   receiver = old_receiver;
  214: }
Syntax (Markdown)