Home | History | Annotate | Download | only in libdwfl
      1 /* Error handling in libdwfl.
      2    Copyright (C) 2005-2010 Red Hat, Inc.
      3    This file is part of elfutils.
      4 
      5    This file is free software; you can redistribute it and/or modify
      6    it under the terms of either
      7 
      8      * the GNU Lesser General Public License as published by the Free
      9        Software Foundation; either version 3 of the License, or (at
     10        your option) any later version
     11 
     12    or
     13 
     14      * the GNU General Public License as published by the Free
     15        Software Foundation; either version 2 of the License, or (at
     16        your option) any later version
     17 
     18    or both in parallel, as here.
     19 
     20    elfutils is distributed in the hope that it will be useful, but
     21    WITHOUT ANY WARRANTY; without even the implied warranty of
     22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     23    General Public License for more details.
     24 
     25    You should have received copies of the GNU General Public License and
     26    the GNU Lesser General Public License along with this program.  If
     27    not, see <http://www.gnu.org/licenses/>.  */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 # include <config.h>
     31 #endif
     32 
     33 #include <assert.h>
     34 #include <libintl.h>
     35 #include <stdbool.h>
     36 #include <stdint.h>
     37 #include <stdlib.h>
     38 #include <errno.h>
     39 
     40 #include "libdwflP.h"
     41 
     42 
     43 /* The error number.  */
     44 static __thread int global_error;
     45 
     46 
     47 int
     48 dwfl_errno (void)
     49 {
     50   int result = global_error;
     51   global_error = DWFL_E_NOERROR;
     52   return result;
     53 }
     54 INTDEF (dwfl_errno)
     55 
     56 
     57 static const struct msgtable
     58 {
     59 #define DWFL_ERROR(name, text) char msg_##name[sizeof text];
     60   DWFL_ERRORS
     61 #undef	DWFL_ERROR
     62 } msgtable =
     63   {
     64 #define DWFL_ERROR(name, text) text,
     65   DWFL_ERRORS
     66 #undef	DWFL_ERROR
     67   };
     68 #define msgstr (&msgtable.msg_NOERROR[0])
     69 
     70 static const uint_fast16_t msgidx[] =
     71 {
     72 #define DWFL_ERROR(name, text) \
     73   [DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
     74   DWFL_ERRORS
     75 #undef	DWFL_ERROR
     76 };
     77 #define nmsgidx (sizeof msgidx / sizeof msgidx[0])
     78 
     79 
     80 static inline int
     81 canonicalize (Dwfl_Error error)
     82 {
     83   unsigned int value;
     84 
     85   switch (error)
     86     {
     87     default:
     88       value = error;
     89       if ((value &~ 0xffff) != 0)
     90 	break;
     91       assert (value < nmsgidx);
     92       break;
     93     case DWFL_E_ERRNO:
     94       value = DWFL_E (ERRNO, errno);
     95       break;
     96     case DWFL_E_LIBELF:
     97       value = DWFL_E (LIBELF, elf_errno ());
     98       break;
     99     case DWFL_E_LIBDW:
    100       value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
    101       break;
    102 #if 0
    103     DWFL_E_LIBEBL:
    104       value = DWFL_E (LIBEBL, ebl_errno ());
    105       break;
    106 #endif
    107     }
    108 
    109   return value;
    110 }
    111 
    112 int
    113 internal_function
    114 __libdwfl_canon_error (Dwfl_Error error)
    115 {
    116   return canonicalize (error);
    117 }
    118 
    119 void
    120 internal_function
    121 __libdwfl_seterrno (Dwfl_Error error)
    122 {
    123   global_error = canonicalize (error);
    124 }
    125 
    126 
    127 const char *
    128 dwfl_errmsg (error)
    129      int error;
    130 {
    131   if (error == 0 || error == -1)
    132     {
    133       int last_error = global_error;
    134 
    135       if (error == 0 && last_error == 0)
    136 	return NULL;
    137 
    138       error = last_error;
    139       global_error = DWFL_E_NOERROR;
    140     }
    141 
    142   switch (error &~ 0xffff)
    143     {
    144     case OTHER_ERROR (ERRNO):
    145       return strerror_r (error & 0xffff, "bad", 0);
    146     case OTHER_ERROR (LIBELF):
    147       return elf_errmsg (error & 0xffff);
    148     case OTHER_ERROR (LIBDW):
    149       return INTUSE(dwarf_errmsg) (error & 0xffff);
    150 #if 0
    151     case OTHER_ERROR (LIBEBL):
    152       return ebl_errmsg (error & 0xffff);
    153 #endif
    154     }
    155 
    156   return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
    157 			  ? error : DWFL_E_UNKNOWN_ERROR]]);
    158 }
    159 INTDEF (dwfl_errmsg)
    160