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