dwarf_error.c revision 441f72d43a9b550baa779fc82f70816da5f74f0e
1/* Retrieve ELF descriptor used for DWARF access.
2   Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
3   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5   This program is Open Source software; you can redistribute it and/or
6   modify it under the terms of the Open Software License version 1.0 as
7   published by the Open Source Initiative.
8
9   You should have received a copy of the Open Software License along
10   with this program; if not, you may obtain a copy of the Open Software
11   License version 1.0 from http://www.opensource.org/licenses/osl.php or
12   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13   3001 King Ranch Road, Ukiah, CA 95482.   */
14
15#ifdef HAVE_CONFIG_H
16# include <config.h>
17#endif
18
19#include <assert.h>
20#include <stddef.h>
21
22#include "libdwP.h"
23
24
25#ifdef USE_TLS
26/* The error number.  */
27static int global_error;
28#else
29/* This is the key for the thread specific memory.  */
30static tls_key_t key;
31
32/* The error number.  Used in non-threaded programs.  */
33static int global_error;
34static bool threaded;
35/* We need to initialize the thread-specific data.  */
36once_define (static, once);
37
38/* The initialization and destruction functions.  */
39static void init (void);
40static void free_key_mem (void *mem);
41#endif	/* TLS */
42
43
44int
45dwarf_errno (void)
46{
47  int result;
48
49#ifndef USE_TLS
50  /* If we have not yet initialized the buffer do it now.  */
51  once_execute (once, init);
52
53  if (threaded)
54    {
55    /* We do not allocate memory for the data.  It is only a word.
56       We can store it in place of the pointer.  */
57      result = (intptr_t) getspecific (key);
58
59      setspecific (key, (void *) (intptr_t) DWARF_E_NOERROR);
60      return result;
61    }
62#endif	/* TLS */
63
64  result = global_error;
65  global_error = DWARF_E_NOERROR;
66  return result;
67}
68
69
70/* XXX For now we use string pointers.  Once the table stablelizes
71   make it more DSO-friendly.  */
72static const char *errmsgs[] =
73  {
74    [DWARF_E_NOERROR] = N_("no error"),
75    [DWARF_E_UNKNOWN_ERROR] = N_("unknown error"),
76    [DWARF_E_INVALID_ACCESS] = N_("invalid access"),
77    [DWARF_E_NO_REGFILE] = N_("no regular file"),
78    [DWARF_E_IO_ERROR] = N_("I/O error"),
79    [DWARF_E_INVALID_ELF] = N_("invalid ELF file"),
80    [DWARF_E_NO_DWARF] = N_("no DWARF information"),
81    [DWARF_E_NOELF] = N_("no ELF file"),
82    [DWARF_E_GETEHDR_ERROR] = N_("cannot get ELF header"),
83    [DWARF_E_NOMEM] = N_("out of memory"),
84    [DWARF_E_UNIMPL] = N_("not implemented"),
85    [DWARF_E_INVALID_CMD] = N_("invalid command"),
86    [DWARF_E_INVALID_VERSION] = N_("invalid version"),
87    [DWARF_E_INVALID_FILE] = N_("invalid file"),
88    [DWARF_E_NO_ENTRY] = N_("no entries found"),
89    [DWARF_E_INVALID_DWARF] = N_("invalid DWARF"),
90    [DWARF_E_NO_STRING] = N_("no string data"),
91    [DWARF_E_NO_ADDR] = N_("no address value"),
92    [DWARF_E_NO_CONSTANT] = N_("no constant value"),
93    [DWARF_E_NO_REFERENCE] = N_("no reference value"),
94    [DWARF_E_INVALID_REFERENCE] = N_("invalid reference value"),
95    [DWARF_E_NO_DEBUG_LINE] = N_(".debug_line section missing"),
96    [DWARF_E_INVALID_DEBUG_LINE] = N_("invalid .debug_line section"),
97    [DWARF_E_TOO_BIG] = N_("debug information too big"),
98    [DWARF_E_VERSION] = N_("invalid DWARF version"),
99    [DWARF_E_INVALID_DIR_IDX] = N_("invalid directory index"),
100    [DWARF_E_ADDR_OUTOFRANGE] = N_("address out of range"),
101    [DWARF_E_NO_LOCLIST] = N_("no location list value"),
102    [DWARF_E_NO_BLOCK] = N_("no block data"),
103    [DWARF_E_INVALID_LINE_IDX] = N_("invalid line index"),
104    [DWARF_E_INVALID_ARANGE_IDX] = N_("invalid address range index"),
105    [DWARF_E_NO_MATCH] = N_("no matching address range"),
106    [DWARF_E_NO_FLAG] = N_("no flag value"),
107  };
108#define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0]))
109
110
111void
112__libdw_seterrno (value)
113     int value;
114{
115#ifndef USE_TLS
116  /* If we have not yet initialized the buffer do it now.  */
117  once_execute (once, init);
118
119  if (threaded)
120    /* We do not allocate memory for the data.  It is only a word.
121       We can store it in place of the pointer.  */
122    setspecific (key, (void *) (intptr_t) value);
123#endif	/* TLS */
124
125  global_error = (value >= 0 && value < (int) nerrmsgs
126		  ? value : DWARF_E_UNKNOWN_ERROR);
127}
128
129
130const char *
131dwarf_errmsg (error)
132     int error;
133{
134  int last_error;
135
136#ifndef USE_TLS
137  /* If we have not yet initialized the buffer do it now.  */
138  once_execute (once, init);
139
140  if ((error == 0 || error == -1) && threaded)
141    /* We do not allocate memory for the data.  It is only a word.
142       We can store it in place of the pointer.  */
143    last_error = (intptr_t) getspecific (key);
144  else
145#endif	/* TLS */
146    last_error = global_error;
147
148  if (error == 0)
149    return last_error != 0 ? _(errmsgs[last_error]) : NULL;
150  else if (error < -1 || error >= (int) nerrmsgs)
151    return _(errmsgs[DWARF_E_UNKNOWN_ERROR]);
152
153  return _(errmsgs[error == -1 ? last_error : error]);
154}
155
156
157#ifndef USE_TLS
158/* Free the thread specific data, this is done if a thread terminates.  */
159static void
160free_key_mem (void *mem)
161{
162  setspecific (key, NULL);
163}
164
165
166/* Initialize the key for the global variable.  */
167static void
168init (void)
169{
170  // XXX Screw you, gcc4, the unused function attribute does not work.
171  __asm ("" :: "r" (free_key_mem));
172
173  if (key_create (&key, free_key_mem) == 0)
174    /* Creating the key succeeded.  */
175    threaded = true;
176}
177#endif	/* TLS */
178