elf_aux.c 1.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *  arch/um/kernel/elf_aux.c
 *
 *  Scan the Elf auxiliary vector provided by the host to extract
 *  information about vsyscall-page, etc.
 *
 *  Copyright (C) 2004 Fujitsu Siemens Computers GmbH
 *  Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com)
 */
#include <elf.h>
#include <stddef.h>
#include "init.h"
#include "elf_user.h"
J
Jeff Dike 已提交
14
#include "mem_user.h"
15
#include <kernel-offsets.h>
L
Linus Torvalds 已提交
16

17 18
/* Use the one from the kernel - the host may miss it, if having old headers. */
#if UM_ELF_CLASS == UM_ELFCLASS32
L
Linus Torvalds 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
typedef Elf32_auxv_t elf_auxv_t;
#else
typedef Elf64_auxv_t elf_auxv_t;
#endif

char * elf_aux_platform;
long elf_aux_hwcap;

unsigned long vsyscall_ehdr;
unsigned long vsyscall_end;

unsigned long __kernel_vsyscall;

__init void scan_elf_aux( char **envp)
{
	long page_size = 0;
	elf_auxv_t * auxv;

	while ( *envp++ != NULL) ;

	for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
		switch ( auxv->a_type ) {
			case AT_SYSINFO:
				__kernel_vsyscall = auxv->a_un.a_val;
				break;
			case AT_SYSINFO_EHDR:
				vsyscall_ehdr = auxv->a_un.a_val;
J
Jeff Dike 已提交
46 47 48
				/* See if the page is under TASK_SIZE */
				if (vsyscall_ehdr < (unsigned long) envp)
					vsyscall_ehdr = 0;
L
Linus Torvalds 已提交
49 50 51 52 53
				break;
			case AT_HWCAP:
				elf_aux_hwcap = auxv->a_un.a_val;
				break;
			case AT_PLATFORM:
J
Jeff Dike 已提交
54 55 56 57
                                /* elf.h removed the pointer elements from
                                 * a_un, so we have to use a_val, which is
                                 * all that's left.
                                 */
58 59
				elf_aux_platform =
					(char *) (long) auxv->a_un.a_val;
L
Linus Torvalds 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
				break;
			case AT_PAGESZ:
				page_size = auxv->a_un.a_val;
				break;
		}
	}
	if ( ! __kernel_vsyscall || ! vsyscall_ehdr ||
	     ! elf_aux_hwcap || ! elf_aux_platform ||
	     ! page_size || (vsyscall_ehdr % page_size) ) {
		__kernel_vsyscall = 0;
		vsyscall_ehdr = 0;
		elf_aux_hwcap = 0;
		elf_aux_platform = "i586";
	}
	else {
		vsyscall_end = vsyscall_ehdr + page_size;
	}
}