1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Error handling in libasm. 2441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Copyright (C) 2002, 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 <libintl.h> 20441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdbool.h> 21441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdlib.h> 22441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 23441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include "libasmP.h" 24441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 25441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 26441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* This is the key for the thread specific memory. */ 27441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic tls_key_t key; 28441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 29441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* The error number. Used in non-threaded programs. */ 30441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int global_error; 31441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool threaded; 32441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* We need to initialize the thread-specific data. */ 33441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectonce_define (static, once); 34441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 35441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* The initialization and destruction functions. */ 36441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void init (void); 37441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void free_key_mem (void *mem); 38441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 39441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 40441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectint 41441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectasm_errno (void) 42441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 43441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int result; 44441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 45441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* If we have not yet initialized the buffer do it now. */ 46441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project once_execute (once, init); 47441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 48441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (threaded) 49441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 50441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* We have a key. Use it to get the thread-specific buffer. */ 51441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int *buffer = getspecific (key); 52441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (buffer == NULL) 53441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 54441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No buffer allocated so far. */ 55441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buffer = (int *) malloc (sizeof (int)); 56441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (buffer == NULL) 57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No more memory available. We use the static buffer. */ 58441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buffer = &global_error; 59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 60441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project setspecific (key, buffer); 61441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 62441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project *buffer = 0; 63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project result = *buffer; 66441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project *buffer = ASM_E_NOERROR; 67441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return result; 68441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project result = global_error; 71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project global_error = ASM_E_NOERROR; 72441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return result; 73441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 74441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 75441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 76441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectvoid 77441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project__libasm_seterrno (value) 78441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int value; 79441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 80441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* If we have not yet initialized the buffer do it now. */ 81441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project once_execute (once, init); 82441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 83441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (threaded) 84441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 85441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* We have a key. Use it to get the thread-specific buffer. */ 86441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int *buffer = getspecific (key); 87441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (buffer == NULL) 88441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 89441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No buffer allocated so far. */ 90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buffer = malloc (sizeof (int)); 91441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (buffer == NULL) 92441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No more memory available. We use the static buffer. */ 93441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buffer = &global_error; 94441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 95441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project setspecific (key, buffer); 96441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 97441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 98441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project *buffer = value; 99441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project global_error = value; 102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 104441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 105441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Return the appropriate message for the error. */ 106441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char *msgs[ASM_E_NUM] = 107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_NOERROR] = N_("no error"), 109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_NOMEM] = N_("out of memory"), 110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_CANNOT_CREATE] = N_("cannot create output file"), 111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_INVALID] = N_("invalid parameter"), 112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_CANNOT_CHMOD] = N_("cannot change mode of output file"), 113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_CANNOT_RENAME] = N_("cannot rename output file"), 114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_DUPLSYM] = N_("duplicate symbol"), 115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [ASM_E_TYPE] = N_("invalid section type for operation") 116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}; 117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectconst char * 119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectasm_errmsg (error) 120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int error; 121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int last_error; 123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* If we have not yet initialized the buffer do it now. */ 125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project once_execute (once, init); 126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((error == 0 || error == -1) && threaded) 128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* We have a key. Use it to get the thread-specific buffer. */ 130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int *buffer = (int *) getspecific (key); 131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (buffer == NULL) 132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No buffer allocated so far. */ 134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buffer = (int *) malloc (sizeof (int)); 135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (buffer == NULL) 136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No more memory available. We use the static buffer. */ 137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buffer = &global_error; 138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project setspecific (key, buffer); 140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project *buffer = 0; 141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project last_error = *buffer; 144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 145441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project last_error = global_error; 147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (error < -1) 149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return _("Unknown error"); 150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (error == 0 && last_error == 0) 151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No error. */ 152441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return NULL; 153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (error != -1) 155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project last_error = error; 156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (last_error == ASM_E_LIBELF) 158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return elf_errmsg (-1); 159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return _(msgs[last_error]); 161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Free the thread specific data, this is done if a thread terminates. */ 165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectfree_key_mem (void *mem) 167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project free (mem); 169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project setspecific (key, NULL); 170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Initialize the key for the global variable. */ 174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectinit (void) 176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project // XXX Screw you, gcc4, the unused function attribute does not work. 178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project __asm ("" :: "r" (free_key_mem)); 179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (key_create (&key, free_key_mem) == 0) 181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Creating the key succeeded. */ 182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project threaded = true; 183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 184