auxv.c revision 211416
181634Sbrian/*-
281634Sbrian * Copyright 2010 Konstantin Belousov <kib@FreeBSD.ORG>.
381634Sbrian * All rights reserved.
481634Sbrian *
581634Sbrian * Redistribution and use in source and binary forms, with or without
681634Sbrian * modification, are permitted provided that the following conditions
781634Sbrian * are met:
881634Sbrian * 1. Redistributions of source code must retain the above copyright
981634Sbrian *    notice, this list of conditions and the following disclaimer.
1081634Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1181634Sbrian *    notice, this list of conditions and the following disclaimer in the
1281634Sbrian *    documentation and/or other materials provided with the distribution.
1381634Sbrian *
1481634Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1581634Sbrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1681634Sbrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1781634Sbrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1881634Sbrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1981634Sbrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2081634Sbrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2181634Sbrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2281634Sbrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2381634Sbrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2481634Sbrian *
2581634Sbrian */
2681634Sbrian
2781634Sbrian#include <sys/cdefs.h>
2881634Sbrian__FBSDID("$FreeBSD: head/lib/libc/gen/aux.c 211416 2010-08-17 09:13:26Z kib $");
2981634Sbrian
3081634Sbrian#include "namespace.h"
3181634Sbrian#include <elf.h>
3281634Sbrian#include <errno.h>
3381634Sbrian#include <link.h>
3481634Sbrian#include <pthread.h>
35102558Sbrian#include <string.h>
36102558Sbrian#include "un-namespace.h"
3781634Sbrian#include "libc_private.h"
3881634Sbrian
3981634SbrianElf_Auxinfo *__elf_aux_vector;
4081634Sbrian
4181634Sbrianstatic pthread_once_t aux_once = PTHREAD_ONCE_INIT;
4281634Sbrian
4381634Sbrianstatic int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
4481634Sbrianstatic char *canary, *pagesizes;
4581634Sbrian
46102558Sbrianstatic void
47102558Sbrianinit_aux(void)
4881634Sbrian{
4981634Sbrian	Elf_Auxinfo *aux;
5081634Sbrian
5181634Sbrian	for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
5281634Sbrian		switch (aux->a_type) {
5381634Sbrian		case AT_CANARY:
5481634Sbrian			canary = (char *)(aux->a_un.a_ptr);
5581634Sbrian			break;
5681634Sbrian
5781634Sbrian		case AT_CANARYLEN:
5881634Sbrian			canary_len = aux->a_un.a_val;
5981634Sbrian			break;
6081634Sbrian
6181634Sbrian		case AT_PAGESIZES:
6281634Sbrian			pagesizes = (char *)(aux->a_un.a_ptr);
6381634Sbrian			break;
6481634Sbrian
6581634Sbrian		case AT_PAGESIZESLEN:
6681634Sbrian			pagesizes_len = aux->a_un.a_val;
6781634Sbrian			break;
6881634Sbrian
6981634Sbrian		case AT_PAGESZ:
7081634Sbrian			pagesize = aux->a_un.a_val;
7181634Sbrian			break;
7281634Sbrian
7381634Sbrian		case AT_OSRELDATE:
7481634Sbrian			osreldate = aux->a_un.a_val;
7581634Sbrian			break;
7681634Sbrian
7781634Sbrian		case AT_NCPUS:
7881634Sbrian			ncpus = aux->a_un.a_val;
7981634Sbrian			break;
8081634Sbrian		}
8181634Sbrian	}
8281634Sbrian}
8381634Sbrian
84int
85_elf_aux_info(int aux, void *buf, int buflen)
86{
87	int res;
88
89	if (__elf_aux_vector == NULL)
90		return (ENOSYS);
91	_once(&aux_once, init_aux);
92
93	switch (aux) {
94	case AT_CANARY:
95		if (canary != NULL && canary_len >= buflen) {
96			memcpy(buf, canary, buflen);
97			memset(canary, 0, canary_len);
98			canary = NULL;
99			res = 0;
100		} else
101			res = ENOENT;
102		break;
103	case AT_PAGESIZES:
104		if (pagesizes != NULL && pagesizes_len >= buflen) {
105			memcpy(buf, pagesizes, buflen);
106			res = 0;
107		} else
108			res = ENOENT;
109		break;
110
111	case AT_PAGESZ:
112		if (buflen == sizeof(int)) {
113			if (pagesize != 0) {
114				*(int *)buf = pagesize;
115				res = 0;
116			} else
117				res = ENOENT;
118		} else
119			res = EINVAL;
120		break;
121	case AT_OSRELDATE:
122		if (buflen == sizeof(int)) {
123			if (osreldate != 0) {
124				*(int *)buf = osreldate;
125				res = 0;
126			} else
127				res = ENOENT;
128		} else
129			res = EINVAL;
130		break;
131	case AT_NCPUS:
132		if (buflen == sizeof(int)) {
133			if (ncpus != 0) {
134				*(int *)buf = ncpus;
135				res = 0;
136			} else
137				res = ENOENT;
138		} else
139			res = EINVAL;
140		break;
141	default:
142		res = ENOENT;
143		break;
144	}
145	return (res);
146}
147