OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc1/] [newlib/] [libc/] [sys/] [linux/] [dl/] [dl-error.c] - Diff between revs 207 and 345

Only display areas with differences | Details | Blame | View Log

Rev 207 Rev 345
/* Error handling for runtime dynamic linker.
/* Error handling for runtime dynamic linker.
   Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
   Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   This file is part of the GNU C Library.
 
 
   The GNU C Library is free software; you can redistribute it and/or
   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
   version 2.1 of the License, or (at your option) any later version.
 
 
   The GNU C Library is distributed in the hope that it will be useful,
   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   Lesser General Public License for more details.
 
 
   You should have received a copy of the GNU Lesser General Public
   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */
   02111-1307 USA.  */
 
 
#include <libintl.h>
#include <libintl.h>
#include <setjmp.h>
#include <setjmp.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <unistd.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <ldsodefs.h>
#include <sys/libc-tsd.h>
#include <sys/libc-tsd.h>
 
 
/* This structure communicates state between _dl_catch_error and
/* This structure communicates state between _dl_catch_error and
   _dl_signal_error.  */
   _dl_signal_error.  */
struct catch
struct catch
  {
  {
    const char *objname;        /* Object/File name.  */
    const char *objname;        /* Object/File name.  */
    const char *errstring;      /* Error detail filled in here.  */
    const char *errstring;      /* Error detail filled in here.  */
    jmp_buf env;                /* longjmp here on error.  */
    jmp_buf env;                /* longjmp here on error.  */
  };
  };
 
 
/* Multiple threads at once can use the `_dl_catch_error' function.  The
/* Multiple threads at once can use the `_dl_catch_error' function.  The
   calls can come from `_dl_map_object_deps', `_dlerror_run', or from
   calls can come from `_dl_map_object_deps', `_dlerror_run', or from
   any of the libc functionality which loads dynamic objects (NSS, iconv).
   any of the libc functionality which loads dynamic objects (NSS, iconv).
   Therefore we have to be prepared to save the state in thread-local
   Therefore we have to be prepared to save the state in thread-local
   memory.  */
   memory.  */
 
 
__libc_tsd_define (static, DL_ERROR)
__libc_tsd_define (static, DL_ERROR)
#define tsd_getspecific()       __libc_tsd_get (DL_ERROR)
#define tsd_getspecific()       __libc_tsd_get (DL_ERROR)
#define tsd_setspecific(data)   __libc_tsd_set (DL_ERROR, (data))
#define tsd_setspecific(data)   __libc_tsd_set (DL_ERROR, (data))
 
 
 
 
/* This message we return as a last resort.  We define the string in a
/* This message we return as a last resort.  We define the string in a
   variable since we have to avoid freeing it and so have to enable
   variable since we have to avoid freeing it and so have to enable
   a pointer comparison.  See below and in dlfcn/dlerror.c.  */
   a pointer comparison.  See below and in dlfcn/dlerror.c.  */
const char _dl_out_of_memory[] = "out of memory";
const char _dl_out_of_memory[] = "out of memory";
 
 
 
 
/* This points to a function which is called when an continuable error is
/* This points to a function which is called when an continuable error is
   received.  Unlike the handling of `catch' this function may return.
   received.  Unlike the handling of `catch' this function may return.
   The arguments will be the `errstring' and `objname'.
   The arguments will be the `errstring' and `objname'.
 
 
   Since this functionality is not used in normal programs (only in ld.so)
   Since this functionality is not used in normal programs (only in ld.so)
   we do not care about multi-threaded programs here.  We keep this as a
   we do not care about multi-threaded programs here.  We keep this as a
   global variable.  */
   global variable.  */
static receiver_fct receiver;
static receiver_fct receiver;
 
 
 
 
void
void
internal_function
internal_function
_dl_signal_error (int errcode, const char *objname, const char *occation,
_dl_signal_error (int errcode, const char *objname, const char *occation,
                  const char *errstring)
                  const char *errstring)
{
{
  struct catch *lcatch;
  struct catch *lcatch;
 
 
  if (! errstring)
  if (! errstring)
    errstring = N_("DYNAMIC LINKER BUG!!!");
    errstring = N_("DYNAMIC LINKER BUG!!!");
 
 
  lcatch = tsd_getspecific ();
  lcatch = tsd_getspecific ();
  if (objname == NULL)
  if (objname == NULL)
    objname = "";
    objname = "";
  if (lcatch != NULL)
  if (lcatch != NULL)
    {
    {
      /* We are inside _dl_catch_error.  Return to it.  We have to
      /* We are inside _dl_catch_error.  Return to it.  We have to
         duplicate the error string since it might be allocated on the
         duplicate the error string since it might be allocated on the
         stack.  The object name is always a string constant.  */
         stack.  The object name is always a string constant.  */
      size_t len_objname = strlen (objname) + 1;
      size_t len_objname = strlen (objname) + 1;
      size_t len_errstring = strlen (errstring) + 1;
      size_t len_errstring = strlen (errstring) + 1;
 
 
      lcatch->errstring = (char *) malloc (len_objname + len_errstring);
      lcatch->errstring = (char *) malloc (len_objname + len_errstring);
      if (lcatch->errstring != NULL)
      if (lcatch->errstring != NULL)
        {
        {
          char *tmp;
          char *tmp;
          /* Make a copy of the object file name and the error string.  */
          /* Make a copy of the object file name and the error string.  */
          tmp = memcpy ((char *) lcatch->errstring,
          tmp = memcpy ((char *) lcatch->errstring,
                           errstring, len_errstring);
                           errstring, len_errstring);
          tmp += len_errstring;
          tmp += len_errstring;
          lcatch->objname = memcpy (tmp,
          lcatch->objname = memcpy (tmp,
                                  objname, len_objname);
                                  objname, len_objname);
        }
        }
      else
      else
        {
        {
          /* This is better than nothing.  */
          /* This is better than nothing.  */
          lcatch->objname = "";
          lcatch->objname = "";
          lcatch->errstring = _dl_out_of_memory;
          lcatch->errstring = _dl_out_of_memory;
        }
        }
      longjmp (lcatch->env, errcode ?: -1);
      longjmp (lcatch->env, errcode ?: -1);
    }
    }
  else
  else
    {
    {
      /* Lossage while resolving the program's own symbols is always fatal.  */
      /* Lossage while resolving the program's own symbols is always fatal.  */
      char buffer[1024];
      char buffer[1024];
      _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
      _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
                        _dl_argv[0] ?: "<program name unknown>",
                        _dl_argv[0] ?: "<program name unknown>",
                        occation ?: N_("error while loading shared libraries"),
                        occation ?: N_("error while loading shared libraries"),
                        objname, *objname ? ": " : "",
                        objname, *objname ? ": " : "",
                        errstring, errcode ? ": " : "",
                        errstring, errcode ? ": " : "",
                        (errcode
                        (errcode
                         ? __strerror_r (errcode, buffer, sizeof buffer)
                         ? __strerror_r (errcode, buffer, sizeof buffer)
                         : ""));
                         : ""));
    }
    }
}
}
 
 
 
 
void
void
internal_function
internal_function
_dl_signal_cerror (int errcode, const char *objname, const char *occation,
_dl_signal_cerror (int errcode, const char *objname, const char *occation,
                   const char *errstring)
                   const char *errstring)
{
{
  if (receiver)
  if (receiver)
    {
    {
      /* We are inside _dl_receive_error.  Call the user supplied
      /* We are inside _dl_receive_error.  Call the user supplied
         handler and resume the work.  The receiver will still be
         handler and resume the work.  The receiver will still be
         installed.  */
         installed.  */
      (*receiver) (errcode, objname, errstring);
      (*receiver) (errcode, objname, errstring);
    }
    }
  else
  else
    _dl_signal_error (errcode, objname, occation, errstring);
    _dl_signal_error (errcode, objname, occation, errstring);
}
}
 
 
 
 
int
int
internal_function
internal_function
_dl_catch_error (const char **objname, const char **errstring,
_dl_catch_error (const char **objname, const char **errstring,
                 void (*operate) (void *), void *args)
                 void (*operate) (void *), void *args)
{
{
  int errcode;
  int errcode;
  struct catch *volatile old;
  struct catch *volatile old;
  struct catch c;
  struct catch c;
  /* We need not handle `receiver' since setting a `catch' is handled
  /* We need not handle `receiver' since setting a `catch' is handled
     before it.  */
     before it.  */
 
 
  /* Some systems (e.g., SPARC) handle constructors to local variables
  /* Some systems (e.g., SPARC) handle constructors to local variables
     inefficient.  So we initialize `c' by hand.  */
     inefficient.  So we initialize `c' by hand.  */
  c.errstring = NULL;
  c.errstring = NULL;
 
 
  old = tsd_getspecific ();
  old = tsd_getspecific ();
  errcode = setjmp (c.env);
  errcode = setjmp (c.env);
  if (__builtin_expect (errcode, 0) == 0)
  if (__builtin_expect (errcode, 0) == 0)
    {
    {
      tsd_setspecific (&c);
      tsd_setspecific (&c);
      (*operate) (args);
      (*operate) (args);
      tsd_setspecific (old);
      tsd_setspecific (old);
      *objname = NULL;
      *objname = NULL;
      *errstring = NULL;
      *errstring = NULL;
      return 0;
      return 0;
    }
    }
 
 
  /* We get here only if we longjmp'd out of OPERATE.  */
  /* We get here only if we longjmp'd out of OPERATE.  */
  tsd_setspecific (old);
  tsd_setspecific (old);
  *objname = c.objname;
  *objname = c.objname;
  *errstring = c.errstring;
  *errstring = c.errstring;
  return errcode == -1 ? 0 : errcode;
  return errcode == -1 ? 0 : errcode;
}
}
 
 
void
void
internal_function
internal_function
_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
{
{
  struct catch *old_catch;
  struct catch *old_catch;
  receiver_fct old_receiver;
  receiver_fct old_receiver;
 
 
  old_catch = tsd_getspecific ();
  old_catch = tsd_getspecific ();
  old_receiver = receiver;
  old_receiver = receiver;
 
 
  /* Set the new values.  */
  /* Set the new values.  */
  tsd_setspecific (NULL);
  tsd_setspecific (NULL);
  receiver = fct;
  receiver = fct;
 
 
  (*operate) (args);
  (*operate) (args);
 
 
  tsd_setspecific (old_catch);
  tsd_setspecific (old_catch);
  receiver = old_receiver;
  receiver = old_receiver;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.