]> CyberLeo.Net >> Repos - FreeBSD/releng/9.1.git/blob - lib/libc/gen/aux.c
Update branch tag from RELENG_9 to RELENG_9_1.
[FreeBSD/releng/9.1.git] / lib / libc / gen / aux.c
1 /*-
2  * Copyright 2010, 2012 Konstantin Belousov <kib@FreeBSD.ORG>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "namespace.h"
31 #include <elf.h>
32 #include <errno.h>
33 #include <link.h>
34 #include <pthread.h>
35 #include <string.h>
36 #include "un-namespace.h"
37 #include "libc_private.h"
38
39 extern char **environ;
40 extern int _DYNAMIC;
41 #pragma weak _DYNAMIC
42
43 void *__elf_aux_vector;
44 static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
45
46 static void
47 init_aux_vector_once(void)
48 {
49         Elf_Addr *sp;
50
51         sp = (Elf_Addr *)environ;
52         while (*sp++ != 0)
53                 ;
54         __elf_aux_vector = (Elf_Auxinfo *)sp;
55 }
56
57 void
58 __init_elf_aux_vector(void)
59 {
60
61         if (&_DYNAMIC != NULL)
62                 return;
63         _once(&aux_vector_once, init_aux_vector_once);
64 }
65
66 static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
67 static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
68 static char *canary, *pagesizes;
69
70 static void
71 init_aux(void)
72 {
73         Elf_Auxinfo *aux;
74
75         for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
76                 switch (aux->a_type) {
77                 case AT_CANARY:
78                         canary = (char *)(aux->a_un.a_ptr);
79                         break;
80
81                 case AT_CANARYLEN:
82                         canary_len = aux->a_un.a_val;
83                         break;
84
85                 case AT_PAGESIZES:
86                         pagesizes = (char *)(aux->a_un.a_ptr);
87                         break;
88
89                 case AT_PAGESIZESLEN:
90                         pagesizes_len = aux->a_un.a_val;
91                         break;
92
93                 case AT_PAGESZ:
94                         pagesize = aux->a_un.a_val;
95                         break;
96
97                 case AT_OSRELDATE:
98                         osreldate = aux->a_un.a_val;
99                         break;
100
101                 case AT_NCPUS:
102                         ncpus = aux->a_un.a_val;
103                         break;
104                 }
105         }
106 }
107
108 int
109 _elf_aux_info(int aux, void *buf, int buflen)
110 {
111         int res;
112
113         __init_elf_aux_vector();
114         if (__elf_aux_vector == NULL)
115                 return (ENOSYS);
116         _once(&aux_once, init_aux);
117
118         switch (aux) {
119         case AT_CANARY:
120                 if (canary != NULL && canary_len >= buflen) {
121                         memcpy(buf, canary, buflen);
122                         memset(canary, 0, canary_len);
123                         canary = NULL;
124                         res = 0;
125                 } else
126                         res = ENOENT;
127                 break;
128         case AT_PAGESIZES:
129                 if (pagesizes != NULL && pagesizes_len >= buflen) {
130                         memcpy(buf, pagesizes, buflen);
131                         res = 0;
132                 } else
133                         res = ENOENT;
134                 break;
135
136         case AT_PAGESZ:
137                 if (buflen == sizeof(int)) {
138                         if (pagesize != 0) {
139                                 *(int *)buf = pagesize;
140                                 res = 0;
141                         } else
142                                 res = ENOENT;
143                 } else
144                         res = EINVAL;
145                 break;
146         case AT_OSRELDATE:
147                 if (buflen == sizeof(int)) {
148                         if (osreldate != 0) {
149                                 *(int *)buf = osreldate;
150                                 res = 0;
151                         } else
152                                 res = ENOENT;
153                 } else
154                         res = EINVAL;
155                 break;
156         case AT_NCPUS:
157                 if (buflen == sizeof(int)) {
158                         if (ncpus != 0) {
159                                 *(int *)buf = ncpus;
160                                 res = 0;
161                         } else
162                                 res = ENOENT;
163                 } else
164                         res = EINVAL;
165                 break;
166         default:
167                 res = ENOENT;
168                 break;
169         }
170         return (res);
171 }