Coverage Report

Created: 2026-08-13 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/elfutils/libdwfl/dwfl_error.c
Line
Count
Source
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 <stdbool.h>
35
#include <stdint.h>
36
#include <stdlib.h>
37
#include <errno.h>
38
39
#include "libdwflP.h"
40
41
42
/* The error number.  */
43
static __thread int global_error;
44
45
46
int
47
dwfl_errno (void)
48
0
{
49
0
  int result = global_error;
50
0
  global_error = DWFL_E_NOERROR;
51
0
  return result;
52
0
}
53
INTDEF (dwfl_errno)
54
55
56
struct msgtable
57
{
58
#define DWFL_ERROR(name, text) char msg_##name[sizeof text];
59
  DWFL_ERRORS
60
#undef  DWFL_ERROR
61
};
62
63
static const union
64
{
65
  struct msgtable table;
66
  char strings[
67
#define DWFL_ERROR(name, text)  + sizeof text
68
         DWFL_ERRORS
69
#undef  DWFL_ERROR
70
         ];
71
} msgtable =
72
  {
73
    .table =
74
    {
75
#define DWFL_ERROR(name, text) text,
76
      DWFL_ERRORS
77
#undef  DWFL_ERROR
78
    }
79
  };
80
#define msgstr (msgtable.strings)
81
82
static const uint_fast16_t msgidx[] =
83
{
84
#define DWFL_ERROR(name, text) \
85
  [DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
86
  DWFL_ERRORS
87
#undef  DWFL_ERROR
88
};
89
#define nmsgidx (sizeof msgidx / sizeof msgidx[0])
90
91
92
static inline int
93
canonicalize (Dwfl_Error error)
94
14.3k
{
95
14.3k
  unsigned int value;
96
97
14.3k
  switch (error)
98
14.3k
    {
99
13.3k
    default:
100
13.3k
      value = error;
101
13.3k
      if ((value &~ 0xffff) != 0)
102
3.84k
  break;
103
13.3k
      assert (value < nmsgidx);
104
9.47k
      break;
105
9.47k
    case DWFL_E_ERRNO:
106
0
      value = DWFL_E (ERRNO, errno);
107
0
      break;
108
1.03k
    case DWFL_E_LIBELF:
109
1.03k
      value = DWFL_E (LIBELF, elf_errno ());
110
1.03k
      break;
111
0
    case DWFL_E_LIBDW:
112
0
      value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
113
0
      break;
114
#if 0
115
    DWFL_E_LIBEBL:
116
      value = DWFL_E (LIBEBL, ebl_errno ());
117
      break;
118
#endif
119
14.3k
    }
120
121
14.3k
  return value;
122
14.3k
}
123
124
int
125
internal_function
126
__libdwfl_canon_error (Dwfl_Error error)
127
3.17k
{
128
3.17k
  return canonicalize (error);
129
3.17k
}
130
131
void
132
internal_function
133
__libdwfl_seterrno (Dwfl_Error error)
134
11.1k
{
135
11.1k
  global_error = canonicalize (error);
136
11.1k
}
137
138
139
static const char *
140
errnomsg(int error)
141
0
{
142
  /* Won't be changed by strerror_r, but not const so compiler doesn't throw warning */
143
0
  static char unknown[] = "unknown error";
144
145
0
#ifdef STRERROR_R_CHAR_P
146
0
  return strerror_r (error, unknown, 0);
147
#else
148
  /* To store the error message from strerror_r in a thread-safe manner */
149
  static __thread char msg[128];
150
  return strerror_r (error, msg, sizeof (msg)) ? unknown : msg;
151
#endif
152
0
}
153
154
const char *
155
dwfl_errmsg (int error)
156
0
{
157
0
  if (error == 0 || error == -1)
158
0
    {
159
0
      int last_error = global_error;
160
161
0
      if (error == 0 && last_error == 0)
162
0
  return NULL;
163
164
0
      error = last_error;
165
0
      global_error = DWFL_E_NOERROR;
166
0
    }
167
168
0
  switch (error &~ 0xffff)
169
0
    {
170
0
    case OTHER_ERROR (ERRNO):
171
0
      return errnomsg (error & 0xffff);
172
0
    case OTHER_ERROR (LIBELF):
173
0
      return elf_errmsg (error & 0xffff);
174
0
    case OTHER_ERROR (LIBDW):
175
0
      return INTUSE(dwarf_errmsg) (error & 0xffff);
176
#if 0
177
    case OTHER_ERROR (LIBEBL):
178
      return ebl_errmsg (error & 0xffff);
179
#endif
180
0
    }
181
182
0
  return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
183
0
        ? error : DWFL_E_UNKNOWN_ERROR]]);
184
0
}
185
INTDEF (dwfl_errmsg)