1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Retrieve ELF descriptor used for DWARF access.
2441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
3441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
5441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   This program is Open Source software; you can redistribute it and/or
6441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   modify it under the terms of the Open Software License version 1.0 as
7441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   published by the Open Source Initiative.
8441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
9441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   You should have received a copy of the Open Software License along
10441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   with this program; if not, you may obtain a copy of the Open Software
11441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   License version 1.0 from http://www.opensource.org/licenses/osl.php or
12441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   3001 King Ranch Road, Ukiah, CA 95482.   */
14441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
15441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef HAVE_CONFIG_H
16441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# include <config.h>
17441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif
18441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
19441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <assert.h>
20441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stddef.h>
21441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
22441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include "libdwP.h"
23441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
24441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
25441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef USE_TLS
26441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* The error number.  */
27441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int global_error;
28441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#else
29441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* This is the key for the thread specific memory.  */
30441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic tls_key_t key;
31441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
32441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* The error number.  Used in non-threaded programs.  */
33441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int global_error;
34441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool threaded;
35441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* We need to initialize the thread-specific data.  */
36441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectonce_define (static, once);
37441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
38441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* The initialization and destruction functions.  */
39441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void init (void);
40441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void free_key_mem (void *mem);
41441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif	/* TLS */
42441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
43441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
44441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectint
45441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectdwarf_errno (void)
46441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
47441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int result;
48441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
49441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifndef USE_TLS
50441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If we have not yet initialized the buffer do it now.  */
51441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  once_execute (once, init);
52441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
53441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (threaded)
54441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    {
55441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* We do not allocate memory for the data.  It is only a word.
56441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       We can store it in place of the pointer.  */
57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      result = (intptr_t) getspecific (key);
58441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      setspecific (key, (void *) (intptr_t) DWARF_E_NOERROR);
60441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project      return result;
61441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    }
62441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif	/* TLS */
63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  result = global_error;
65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  global_error = DWARF_E_NOERROR;
66441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return result;
67441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
68441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* XXX For now we use string pointers.  Once the table stablelizes
71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project   make it more DSO-friendly.  */
72441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *errmsgs[] =
73441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  {
74441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NOERROR] = N_("no error"),
75441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_UNKNOWN_ERROR] = N_("unknown error"),
76441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_ACCESS] = N_("invalid access"),
77441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_REGFILE] = N_("no regular file"),
78441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_IO_ERROR] = N_("I/O error"),
79441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_ELF] = N_("invalid ELF file"),
80441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_DWARF] = N_("no DWARF information"),
81441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NOELF] = N_("no ELF file"),
82441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_GETEHDR_ERROR] = N_("cannot get ELF header"),
83441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NOMEM] = N_("out of memory"),
84441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_UNIMPL] = N_("not implemented"),
85441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_CMD] = N_("invalid command"),
86441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_VERSION] = N_("invalid version"),
87441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_FILE] = N_("invalid file"),
88441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_ENTRY] = N_("no entries found"),
89441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_DWARF] = N_("invalid DWARF"),
90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_STRING] = N_("no string data"),
91441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_ADDR] = N_("no address value"),
92441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_CONSTANT] = N_("no constant value"),
93441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_REFERENCE] = N_("no reference value"),
94441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_REFERENCE] = N_("invalid reference value"),
95441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_DEBUG_LINE] = N_(".debug_line section missing"),
96441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_DEBUG_LINE] = N_("invalid .debug_line section"),
97441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_TOO_BIG] = N_("debug information too big"),
98441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_VERSION] = N_("invalid DWARF version"),
99441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_DIR_IDX] = N_("invalid directory index"),
100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_ADDR_OUTOFRANGE] = N_("address out of range"),
101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_LOCLIST] = N_("no location list value"),
102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_BLOCK] = N_("no block data"),
103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_LINE_IDX] = N_("invalid line index"),
104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_INVALID_ARANGE_IDX] = N_("invalid address range index"),
105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_MATCH] = N_("no matching address range"),
106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    [DWARF_E_NO_FLAG] = N_("no flag value"),
107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  };
108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0]))
109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectvoid
112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project__libdw_seterrno (value)
113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     int value;
114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifndef USE_TLS
116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If we have not yet initialized the buffer do it now.  */
117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  once_execute (once, init);
118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (threaded)
120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* We do not allocate memory for the data.  It is only a word.
121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       We can store it in place of the pointer.  */
122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    setspecific (key, (void *) (intptr_t) value);
123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif	/* TLS */
124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  global_error = (value >= 0 && value < (int) nerrmsgs
126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project		  ? value : DWARF_E_UNKNOWN_ERROR);
127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectconst char *
131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectdwarf_errmsg (error)
132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project     int error;
133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  int last_error;
135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifndef USE_TLS
137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  /* If we have not yet initialized the buffer do it now.  */
138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  once_execute (once, init);
139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if ((error == 0 || error == -1) && threaded)
141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* We do not allocate memory for the data.  It is only a word.
142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project       We can store it in place of the pointer.  */
143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    last_error = (intptr_t) getspecific (key);
144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else
145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif	/* TLS */
146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    last_error = global_error;
147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (error == 0)
149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return last_error != 0 ? _(errmsgs[last_error]) : NULL;
150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  else if (error < -1 || error >= (int) nerrmsgs)
151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    return _(errmsgs[DWARF_E_UNKNOWN_ERROR]);
152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  return _(errmsgs[error == -1 ? last_error : error]);
154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifndef USE_TLS
158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Free the thread specific data, this is done if a thread terminates.  */
159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectfree_key_mem (void *mem)
161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  setspecific (key, NULL);
163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Initialize the key for the global variable.  */
167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void
168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectinit (void)
169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{
170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  // XXX Screw you, gcc4, the unused function attribute does not work.
171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  __asm ("" :: "r" (free_key_mem));
172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project
173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project  if (key_create (&key, free_key_mem) == 0)
174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    /* Creating the key succeeded.  */
175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project    threaded = true;
176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}
177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif	/* TLS */
178