1211416Skib/*- 2232388Skib * Copyright 2010, 2012 Konstantin Belousov <kib@FreeBSD.ORG>. 3211416Skib * All rights reserved. 4211416Skib * 5211416Skib * Redistribution and use in source and binary forms, with or without 6211416Skib * modification, are permitted provided that the following conditions 7211416Skib * are met: 8211416Skib * 1. Redistributions of source code must retain the above copyright 9211416Skib * notice, this list of conditions and the following disclaimer. 10211416Skib * 2. Redistributions in binary form must reproduce the above copyright 11211416Skib * notice, this list of conditions and the following disclaimer in the 12211416Skib * documentation and/or other materials provided with the distribution. 13211416Skib * 14211416Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15211416Skib * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16211416Skib * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17211416Skib * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18211416Skib * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19211416Skib * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20211416Skib * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21211416Skib * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22211416Skib * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23211416Skib * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24211416Skib * 25211416Skib */ 26211416Skib 27211416Skib#include <sys/cdefs.h> 28211416Skib__FBSDID("$FreeBSD$"); 29211416Skib 30211416Skib#include "namespace.h" 31211416Skib#include <elf.h> 32211416Skib#include <errno.h> 33211416Skib#include <link.h> 34211416Skib#include <pthread.h> 35211416Skib#include <string.h> 36211416Skib#include "un-namespace.h" 37211416Skib#include "libc_private.h" 38211416Skib 39232388Skibextern char **environ; 40232388Skibextern int _DYNAMIC; 41232388Skib#pragma weak _DYNAMIC 42211416Skib 43232388Skibvoid *__elf_aux_vector; 44232388Skibstatic pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT; 45232388Skib 46232388Skibstatic void 47232388Skibinit_aux_vector_once(void) 48232388Skib{ 49232388Skib Elf_Addr *sp; 50232388Skib 51232388Skib sp = (Elf_Addr *)environ; 52232388Skib while (*sp++ != 0) 53232388Skib ; 54232388Skib __elf_aux_vector = (Elf_Auxinfo *)sp; 55232388Skib} 56232388Skib 57232388Skibvoid 58232388Skib__init_elf_aux_vector(void) 59232388Skib{ 60232388Skib 61232388Skib if (&_DYNAMIC != NULL) 62232388Skib return; 63232388Skib _once(&aux_vector_once, init_aux_vector_once); 64232388Skib} 65232388Skib 66211416Skibstatic pthread_once_t aux_once = PTHREAD_ONCE_INIT; 67211416Skibstatic int pagesize, osreldate, canary_len, ncpus, pagesizes_len; 68211416Skibstatic char *canary, *pagesizes; 69240819Skibstatic void *timekeep; 70211416Skib 71211416Skibstatic void 72211416Skibinit_aux(void) 73211416Skib{ 74211416Skib Elf_Auxinfo *aux; 75211416Skib 76211416Skib for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) { 77211416Skib switch (aux->a_type) { 78211416Skib case AT_CANARY: 79211416Skib canary = (char *)(aux->a_un.a_ptr); 80211416Skib break; 81211416Skib 82211416Skib case AT_CANARYLEN: 83211416Skib canary_len = aux->a_un.a_val; 84211416Skib break; 85211416Skib 86211416Skib case AT_PAGESIZES: 87211416Skib pagesizes = (char *)(aux->a_un.a_ptr); 88211416Skib break; 89211416Skib 90211416Skib case AT_PAGESIZESLEN: 91211416Skib pagesizes_len = aux->a_un.a_val; 92211416Skib break; 93211416Skib 94211416Skib case AT_PAGESZ: 95211416Skib pagesize = aux->a_un.a_val; 96211416Skib break; 97211416Skib 98211416Skib case AT_OSRELDATE: 99211416Skib osreldate = aux->a_un.a_val; 100211416Skib break; 101211416Skib 102211416Skib case AT_NCPUS: 103211416Skib ncpus = aux->a_un.a_val; 104211416Skib break; 105240819Skib 106240819Skib case AT_TIMEKEEP: 107240819Skib timekeep = aux->a_un.a_ptr; 108240819Skib break; 109211416Skib } 110211416Skib } 111211416Skib} 112211416Skib 113211416Skibint 114211416Skib_elf_aux_info(int aux, void *buf, int buflen) 115211416Skib{ 116211416Skib int res; 117211416Skib 118232388Skib __init_elf_aux_vector(); 119211416Skib if (__elf_aux_vector == NULL) 120211416Skib return (ENOSYS); 121211416Skib _once(&aux_once, init_aux); 122211416Skib 123211416Skib switch (aux) { 124211416Skib case AT_CANARY: 125211416Skib if (canary != NULL && canary_len >= buflen) { 126211416Skib memcpy(buf, canary, buflen); 127211416Skib memset(canary, 0, canary_len); 128211416Skib canary = NULL; 129211416Skib res = 0; 130211416Skib } else 131211416Skib res = ENOENT; 132211416Skib break; 133211416Skib case AT_PAGESIZES: 134211416Skib if (pagesizes != NULL && pagesizes_len >= buflen) { 135211416Skib memcpy(buf, pagesizes, buflen); 136211416Skib res = 0; 137211416Skib } else 138211416Skib res = ENOENT; 139211416Skib break; 140211416Skib 141211416Skib case AT_PAGESZ: 142211416Skib if (buflen == sizeof(int)) { 143211416Skib if (pagesize != 0) { 144211416Skib *(int *)buf = pagesize; 145211416Skib res = 0; 146211416Skib } else 147211416Skib res = ENOENT; 148211416Skib } else 149211416Skib res = EINVAL; 150211416Skib break; 151211416Skib case AT_OSRELDATE: 152211416Skib if (buflen == sizeof(int)) { 153211416Skib if (osreldate != 0) { 154211416Skib *(int *)buf = osreldate; 155211416Skib res = 0; 156211416Skib } else 157211416Skib res = ENOENT; 158211416Skib } else 159211416Skib res = EINVAL; 160211416Skib break; 161211416Skib case AT_NCPUS: 162211416Skib if (buflen == sizeof(int)) { 163211416Skib if (ncpus != 0) { 164211416Skib *(int *)buf = ncpus; 165211416Skib res = 0; 166211416Skib } else 167211416Skib res = ENOENT; 168211416Skib } else 169211416Skib res = EINVAL; 170211416Skib break; 171240819Skib case AT_TIMEKEEP: 172240819Skib if (buflen == sizeof(void *)) { 173240819Skib if (timekeep != NULL) { 174240819Skib *(void **)buf = timekeep; 175240819Skib res = 0; 176240819Skib } else 177240819Skib res = ENOENT; 178240819Skib } else 179240819Skib res = EINVAL; 180240819Skib break; 181211416Skib default: 182211416Skib res = ENOENT; 183211416Skib break; 184211416Skib } 185211416Skib return (res); 186211416Skib} 187