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