Home | History | Annotate | Download | only in libdwfl
      1 /* Error handling in libdwfl.
      2    Copyright (C) 2005-2015 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 struct msgtable
     58 {
     59 #define DWFL_ERROR(name, text) char msg_##name[sizeof text];
     60   DWFL_ERRORS
     61 #undef	DWFL_ERROR
     62 };
     63 
     64 static const union
     65 {
     66   struct msgtable table;
     67   char strings[
     68 #define DWFL_ERROR(name, text)	+ sizeof text
     69 	       DWFL_ERRORS
     70 #undef	DWFL_ERROR
     71 	       ];
     72 } msgtable =
     73   {
     74     .table =
     75     {
     76 #define DWFL_ERROR(name, text) text,
     77       DWFL_ERRORS
     78 #undef	DWFL_ERROR
     79     }
     80   };
     81 #define msgstr (msgtable.strings)
     82 
     83 static const uint_fast16_t msgidx[] =
     84 {
     85 #define DWFL_ERROR(name, text) \
     86   [DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
     87   DWFL_ERRORS
     88 #undef	DWFL_ERROR
     89 };
     90 #define nmsgidx (sizeof msgidx / sizeof msgidx[0])
     91 
     92 
     93 static inline int
     94 canonicalize (Dwfl_Error error)
     95 {
     96   unsigned int value;
     97 
     98   switch (error)
     99     {
    100     default:
    101       value = error;
    102       if ((value &~ 0xffff) != 0)
    103 	break;
    104       assert (value < nmsgidx);
    105       break;
    106     case DWFL_E_ERRNO:
    107       value = DWFL_E (ERRNO, errno);
    108       break;
    109     case DWFL_E_LIBELF:
    110       value = DWFL_E (LIBELF, elf_errno ());
    111       break;
    112     case DWFL_E_LIBDW:
    113       value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
    114       break;
    115 #if 0
    116     DWFL_E_LIBEBL:
    117       value = DWFL_E (LIBEBL, ebl_errno ());
    118       break;
    119 #endif
    120     }
    121 
    122   return value;
    123 }
    124 
    125 int
    126 internal_function
    127 __libdwfl_canon_error (Dwfl_Error error)
    128 {
    129   return canonicalize (error);
    130 }
    131 
    132 void
    133 internal_function
    134 __libdwfl_seterrno (Dwfl_Error error)
    135 {
    136   global_error = canonicalize (error);
    137 }
    138 
    139 
    140 const char *
    141 dwfl_errmsg (int error)
    142 {
    143   if (error == 0 || error == -1)
    144     {
    145       int last_error = global_error;
    146 
    147       if (error == 0 && last_error == 0)
    148 	return NULL;
    149 
    150       error = last_error;
    151       global_error = DWFL_E_NOERROR;
    152     }
    153 
    154   switch (error &~ 0xffff)
    155     {
    156     case OTHER_ERROR (ERRNO):
    157       return strerror_r (error & 0xffff, "bad", 0);
    158     case OTHER_ERROR (LIBELF):
    159       return elf_errmsg (error & 0xffff);
    160     case OTHER_ERROR (LIBDW):
    161       return INTUSE(dwarf_errmsg) (error & 0xffff);
    162 #if 0
    163     case OTHER_ERROR (LIBEBL):
    164       return ebl_errmsg (error & 0xffff);
    165 #endif
    166     }
    167 
    168   return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
    169 			  ? error : DWFL_E_UNKNOWN_ERROR]]);
    170 }
    171 INTDEF (dwfl_errmsg)
    172