xref: /aosp_15_r20/external/ltp/libs/libltpvdso/parse_vdso.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  * parse_vdso.c: Linux reference vDSO parser
3*49cdfc7eSAndroid Build Coastguard Worker  * Written by Andrew Lutomirski, 2011-2014.
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  * This code is meant to be linked in to various programs that run on Linux.
6*49cdfc7eSAndroid Build Coastguard Worker  * As such, it is available with as few restrictions as possible.  This file
7*49cdfc7eSAndroid Build Coastguard Worker  * is licensed under the Creative Commons Zero License, version 1.0,
8*49cdfc7eSAndroid Build Coastguard Worker  * available at http://creativecommons.org/publicdomain/zero/1.0/legalcode
9*49cdfc7eSAndroid Build Coastguard Worker  *
10*49cdfc7eSAndroid Build Coastguard Worker  * The vDSO is a regular ELF DSO that the kernel maps into user space when
11*49cdfc7eSAndroid Build Coastguard Worker  * it starts a program.  It works equally well in statically and dynamically
12*49cdfc7eSAndroid Build Coastguard Worker  * linked binaries.
13*49cdfc7eSAndroid Build Coastguard Worker  *
14*49cdfc7eSAndroid Build Coastguard Worker  * This code is tested on x86.  In principle it should work on any
15*49cdfc7eSAndroid Build Coastguard Worker  * architecture that has a vDSO.
16*49cdfc7eSAndroid Build Coastguard Worker  */
17*49cdfc7eSAndroid Build Coastguard Worker 
18*49cdfc7eSAndroid Build Coastguard Worker #include <stdbool.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <stdint.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include <elf.h>
23*49cdfc7eSAndroid Build Coastguard Worker 
24*49cdfc7eSAndroid Build Coastguard Worker /* And here's the code. */
25*49cdfc7eSAndroid Build Coastguard Worker #ifndef ELF_BITS
26*49cdfc7eSAndroid Build Coastguard Worker # if ULONG_MAX > 0xffffffffUL
27*49cdfc7eSAndroid Build Coastguard Worker #  define ELF_BITS 64
28*49cdfc7eSAndroid Build Coastguard Worker # else
29*49cdfc7eSAndroid Build Coastguard Worker #  define ELF_BITS 32
30*49cdfc7eSAndroid Build Coastguard Worker # endif
31*49cdfc7eSAndroid Build Coastguard Worker #endif
32*49cdfc7eSAndroid Build Coastguard Worker 
33*49cdfc7eSAndroid Build Coastguard Worker #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
34*49cdfc7eSAndroid Build Coastguard Worker #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
35*49cdfc7eSAndroid Build Coastguard Worker #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)
36*49cdfc7eSAndroid Build Coastguard Worker 
37*49cdfc7eSAndroid Build Coastguard Worker static struct vdso_info
38*49cdfc7eSAndroid Build Coastguard Worker {
39*49cdfc7eSAndroid Build Coastguard Worker 	bool valid;
40*49cdfc7eSAndroid Build Coastguard Worker 
41*49cdfc7eSAndroid Build Coastguard Worker 	/* Load information */
42*49cdfc7eSAndroid Build Coastguard Worker 	uintptr_t load_addr;
43*49cdfc7eSAndroid Build Coastguard Worker 	uintptr_t load_offset;  /* load_addr - recorded vaddr */
44*49cdfc7eSAndroid Build Coastguard Worker 
45*49cdfc7eSAndroid Build Coastguard Worker 	/* Symbol table */
46*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Sym) *symtab;
47*49cdfc7eSAndroid Build Coastguard Worker 	const char *symstrings;
48*49cdfc7eSAndroid Build Coastguard Worker 	void *bucket, *chain;
49*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Word) nbucket, nchain;
50*49cdfc7eSAndroid Build Coastguard Worker 	bool hash_ent_is_dword;
51*49cdfc7eSAndroid Build Coastguard Worker 
52*49cdfc7eSAndroid Build Coastguard Worker 	/* Version table */
53*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Versym) *versym;
54*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Verdef) *verdef;
55*49cdfc7eSAndroid Build Coastguard Worker } vdso_info;
56*49cdfc7eSAndroid Build Coastguard Worker 
57*49cdfc7eSAndroid Build Coastguard Worker /* Straight from the ELF specification. */
elf_hash(const unsigned char * name)58*49cdfc7eSAndroid Build Coastguard Worker static unsigned long elf_hash(const unsigned char *name)
59*49cdfc7eSAndroid Build Coastguard Worker {
60*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long h = 0, g;
61*49cdfc7eSAndroid Build Coastguard Worker 	while (*name)
62*49cdfc7eSAndroid Build Coastguard Worker 	{
63*49cdfc7eSAndroid Build Coastguard Worker 		h = (h << 4) + *name++;
64*49cdfc7eSAndroid Build Coastguard Worker 		if ((g = h & 0xf0000000))
65*49cdfc7eSAndroid Build Coastguard Worker 			h ^= g >> 24;
66*49cdfc7eSAndroid Build Coastguard Worker 		h &= ~g;
67*49cdfc7eSAndroid Build Coastguard Worker 	}
68*49cdfc7eSAndroid Build Coastguard Worker 	return h;
69*49cdfc7eSAndroid Build Coastguard Worker }
70*49cdfc7eSAndroid Build Coastguard Worker 
71*49cdfc7eSAndroid Build Coastguard Worker /* return value of hash table entry */
get_hash_val(void * ptr,ELF (Word)idx)72*49cdfc7eSAndroid Build Coastguard Worker ELF(Word) get_hash_val(void *ptr, ELF(Word) idx)
73*49cdfc7eSAndroid Build Coastguard Worker {
74*49cdfc7eSAndroid Build Coastguard Worker 	if (vdso_info.hash_ent_is_dword) {
75*49cdfc7eSAndroid Build Coastguard Worker 		ELF(Xword) *table = ptr;
76*49cdfc7eSAndroid Build Coastguard Worker 		/* for vdso assume all values fit in Elf Word */
77*49cdfc7eSAndroid Build Coastguard Worker 		return (ELF(Word)) table[idx];
78*49cdfc7eSAndroid Build Coastguard Worker 	}
79*49cdfc7eSAndroid Build Coastguard Worker 
80*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Word) *table = ptr;
81*49cdfc7eSAndroid Build Coastguard Worker 	return table[idx];
82*49cdfc7eSAndroid Build Coastguard Worker }
83*49cdfc7eSAndroid Build Coastguard Worker 
84*49cdfc7eSAndroid Build Coastguard Worker /* return pointer to hash table entry */
get_hash_ptr(void * ptr,ELF (Word)idx)85*49cdfc7eSAndroid Build Coastguard Worker void *get_hash_ptr(void *ptr, ELF(Word) idx)
86*49cdfc7eSAndroid Build Coastguard Worker {
87*49cdfc7eSAndroid Build Coastguard Worker 	if (vdso_info.hash_ent_is_dword)
88*49cdfc7eSAndroid Build Coastguard Worker 		return &((ELF(Xword) *) ptr)[idx];
89*49cdfc7eSAndroid Build Coastguard Worker 
90*49cdfc7eSAndroid Build Coastguard Worker 	return &((ELF(Word) *) ptr)[idx];
91*49cdfc7eSAndroid Build Coastguard Worker }
92*49cdfc7eSAndroid Build Coastguard Worker 
vdso_init_from_sysinfo_ehdr(uintptr_t base)93*49cdfc7eSAndroid Build Coastguard Worker void vdso_init_from_sysinfo_ehdr(uintptr_t base)
94*49cdfc7eSAndroid Build Coastguard Worker {
95*49cdfc7eSAndroid Build Coastguard Worker 	size_t i;
96*49cdfc7eSAndroid Build Coastguard Worker 	bool found_vaddr = false;
97*49cdfc7eSAndroid Build Coastguard Worker 
98*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.valid = false;
99*49cdfc7eSAndroid Build Coastguard Worker 
100*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.load_addr = base;
101*49cdfc7eSAndroid Build Coastguard Worker 
102*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Ehdr) *hdr = (ELF(Ehdr)*)base;
103*49cdfc7eSAndroid Build Coastguard Worker 	if (hdr->e_ident[EI_CLASS] !=
104*49cdfc7eSAndroid Build Coastguard Worker 	    (ELF_BITS == 32 ? ELFCLASS32 : ELFCLASS64)) {
105*49cdfc7eSAndroid Build Coastguard Worker 		return;  /* Wrong ELF class -- check ELF_BITS */
106*49cdfc7eSAndroid Build Coastguard Worker 	}
107*49cdfc7eSAndroid Build Coastguard Worker 
108*49cdfc7eSAndroid Build Coastguard Worker 	/* 64bit s390 and alpha have hash entry size of 8 bytes */
109*49cdfc7eSAndroid Build Coastguard Worker 	if ((hdr->e_machine == EM_ALPHA
110*49cdfc7eSAndroid Build Coastguard Worker 		|| hdr->e_machine == EM_S390)
111*49cdfc7eSAndroid Build Coastguard Worker 		&& hdr->e_ident[EI_CLASS] == ELFCLASS64)
112*49cdfc7eSAndroid Build Coastguard Worker 		vdso_info.hash_ent_is_dword = true;
113*49cdfc7eSAndroid Build Coastguard Worker 	else
114*49cdfc7eSAndroid Build Coastguard Worker 		vdso_info.hash_ent_is_dword = false;
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Phdr) *pt = (ELF(Phdr)*)(vdso_info.load_addr + hdr->e_phoff);
117*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Dyn) *dyn = 0;
118*49cdfc7eSAndroid Build Coastguard Worker 
119*49cdfc7eSAndroid Build Coastguard Worker 	/*
120*49cdfc7eSAndroid Build Coastguard Worker 	 * We need two things from the segment table: the load offset
121*49cdfc7eSAndroid Build Coastguard Worker 	 * and the dynamic table.
122*49cdfc7eSAndroid Build Coastguard Worker 	 */
123*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < hdr->e_phnum; i++)
124*49cdfc7eSAndroid Build Coastguard Worker 	{
125*49cdfc7eSAndroid Build Coastguard Worker 		if (pt[i].p_type == PT_LOAD && !found_vaddr) {
126*49cdfc7eSAndroid Build Coastguard Worker 			found_vaddr = true;
127*49cdfc7eSAndroid Build Coastguard Worker 			vdso_info.load_offset =	base
128*49cdfc7eSAndroid Build Coastguard Worker 				+ (uintptr_t)pt[i].p_offset
129*49cdfc7eSAndroid Build Coastguard Worker 				- (uintptr_t)pt[i].p_vaddr;
130*49cdfc7eSAndroid Build Coastguard Worker 		} else if (pt[i].p_type == PT_DYNAMIC) {
131*49cdfc7eSAndroid Build Coastguard Worker 			dyn = (ELF(Dyn)*)(base + pt[i].p_offset);
132*49cdfc7eSAndroid Build Coastguard Worker 		}
133*49cdfc7eSAndroid Build Coastguard Worker 	}
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker 	if (!found_vaddr || !dyn)
136*49cdfc7eSAndroid Build Coastguard Worker 		return;  /* Failed */
137*49cdfc7eSAndroid Build Coastguard Worker 
138*49cdfc7eSAndroid Build Coastguard Worker 	/*
139*49cdfc7eSAndroid Build Coastguard Worker 	 * Fish out the useful bits of the dynamic table.
140*49cdfc7eSAndroid Build Coastguard Worker 	 */
141*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Word) *hash = 0;
142*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.symstrings = 0;
143*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.symtab = 0;
144*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.versym = 0;
145*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.verdef = 0;
146*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
147*49cdfc7eSAndroid Build Coastguard Worker 		switch (dyn[i].d_tag) {
148*49cdfc7eSAndroid Build Coastguard Worker 		case DT_STRTAB:
149*49cdfc7eSAndroid Build Coastguard Worker 			vdso_info.symstrings = (const char *)
150*49cdfc7eSAndroid Build Coastguard Worker 				((uintptr_t)dyn[i].d_un.d_ptr
151*49cdfc7eSAndroid Build Coastguard Worker 				 + vdso_info.load_offset);
152*49cdfc7eSAndroid Build Coastguard Worker 			break;
153*49cdfc7eSAndroid Build Coastguard Worker 		case DT_SYMTAB:
154*49cdfc7eSAndroid Build Coastguard Worker 			vdso_info.symtab = (ELF(Sym) *)
155*49cdfc7eSAndroid Build Coastguard Worker 				((uintptr_t)dyn[i].d_un.d_ptr
156*49cdfc7eSAndroid Build Coastguard Worker 				 + vdso_info.load_offset);
157*49cdfc7eSAndroid Build Coastguard Worker 			break;
158*49cdfc7eSAndroid Build Coastguard Worker 		case DT_HASH:
159*49cdfc7eSAndroid Build Coastguard Worker 			hash = (ELF(Word) *)
160*49cdfc7eSAndroid Build Coastguard Worker 				((uintptr_t)dyn[i].d_un.d_ptr
161*49cdfc7eSAndroid Build Coastguard Worker 				 + vdso_info.load_offset);
162*49cdfc7eSAndroid Build Coastguard Worker 			break;
163*49cdfc7eSAndroid Build Coastguard Worker 		case DT_VERSYM:
164*49cdfc7eSAndroid Build Coastguard Worker 			vdso_info.versym = (ELF(Versym) *)
165*49cdfc7eSAndroid Build Coastguard Worker 				((uintptr_t)dyn[i].d_un.d_ptr
166*49cdfc7eSAndroid Build Coastguard Worker 				 + vdso_info.load_offset);
167*49cdfc7eSAndroid Build Coastguard Worker 			break;
168*49cdfc7eSAndroid Build Coastguard Worker 		case DT_VERDEF:
169*49cdfc7eSAndroid Build Coastguard Worker 			vdso_info.verdef = (ELF(Verdef) *)
170*49cdfc7eSAndroid Build Coastguard Worker 				((uintptr_t)dyn[i].d_un.d_ptr
171*49cdfc7eSAndroid Build Coastguard Worker 				 + vdso_info.load_offset);
172*49cdfc7eSAndroid Build Coastguard Worker 			break;
173*49cdfc7eSAndroid Build Coastguard Worker 		}
174*49cdfc7eSAndroid Build Coastguard Worker 	}
175*49cdfc7eSAndroid Build Coastguard Worker 	if (!vdso_info.symstrings || !vdso_info.symtab || !hash)
176*49cdfc7eSAndroid Build Coastguard Worker 		return;  /* Failed */
177*49cdfc7eSAndroid Build Coastguard Worker 
178*49cdfc7eSAndroid Build Coastguard Worker 	if (!vdso_info.verdef)
179*49cdfc7eSAndroid Build Coastguard Worker 		vdso_info.versym = 0;
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker 
182*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.nbucket = get_hash_val(hash, 0);
183*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.nchain = get_hash_val(hash, 1);
184*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.bucket = get_hash_ptr(hash, 2);
185*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.chain = get_hash_ptr(hash, vdso_info.nbucket + 2);
186*49cdfc7eSAndroid Build Coastguard Worker 
187*49cdfc7eSAndroid Build Coastguard Worker 	/* That's all we need. */
188*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.valid = true;
189*49cdfc7eSAndroid Build Coastguard Worker }
190*49cdfc7eSAndroid Build Coastguard Worker 
vdso_match_version(ELF (Versym)ver,const char * name,ELF (Word)hash)191*49cdfc7eSAndroid Build Coastguard Worker static bool vdso_match_version(ELF(Versym) ver,
192*49cdfc7eSAndroid Build Coastguard Worker 			       const char *name, ELF(Word) hash)
193*49cdfc7eSAndroid Build Coastguard Worker {
194*49cdfc7eSAndroid Build Coastguard Worker 	/*
195*49cdfc7eSAndroid Build Coastguard Worker 	 * This is a helper function to check if the version indexed by
196*49cdfc7eSAndroid Build Coastguard Worker 	 * ver matches name (which hashes to hash).
197*49cdfc7eSAndroid Build Coastguard Worker 	 *
198*49cdfc7eSAndroid Build Coastguard Worker 	 * The version definition table is a mess, and I don't know how
199*49cdfc7eSAndroid Build Coastguard Worker 	 * to do this in better than linear time without allocating memory
200*49cdfc7eSAndroid Build Coastguard Worker 	 * to build an index.  I also don't know why the table has
201*49cdfc7eSAndroid Build Coastguard Worker 	 * variable size entries in the first place.
202*49cdfc7eSAndroid Build Coastguard Worker 	 *
203*49cdfc7eSAndroid Build Coastguard Worker 	 * For added fun, I can't find a comprehensible specification of how
204*49cdfc7eSAndroid Build Coastguard Worker 	 * to parse all the weird flags in the table.
205*49cdfc7eSAndroid Build Coastguard Worker 	 *
206*49cdfc7eSAndroid Build Coastguard Worker 	 * So I just parse the whole table every time.
207*49cdfc7eSAndroid Build Coastguard Worker 	 */
208*49cdfc7eSAndroid Build Coastguard Worker 
209*49cdfc7eSAndroid Build Coastguard Worker 	/* First step: find the version definition */
210*49cdfc7eSAndroid Build Coastguard Worker 	ver &= 0x7fff;  /* Apparently bit 15 means "hidden" */
211*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Verdef) *def = vdso_info.verdef;
212*49cdfc7eSAndroid Build Coastguard Worker 	while(true) {
213*49cdfc7eSAndroid Build Coastguard Worker 		if ((def->vd_flags & VER_FLG_BASE) == 0
214*49cdfc7eSAndroid Build Coastguard Worker 		    && (def->vd_ndx & 0x7fff) == ver)
215*49cdfc7eSAndroid Build Coastguard Worker 			break;
216*49cdfc7eSAndroid Build Coastguard Worker 
217*49cdfc7eSAndroid Build Coastguard Worker 		if (def->vd_next == 0)
218*49cdfc7eSAndroid Build Coastguard Worker 			return false;  /* No definition. */
219*49cdfc7eSAndroid Build Coastguard Worker 
220*49cdfc7eSAndroid Build Coastguard Worker 		def = (ELF(Verdef) *)((char *)def + def->vd_next);
221*49cdfc7eSAndroid Build Coastguard Worker 	}
222*49cdfc7eSAndroid Build Coastguard Worker 
223*49cdfc7eSAndroid Build Coastguard Worker 	/* Now figure out whether it matches. */
224*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Verdaux) *aux = (ELF(Verdaux)*)((char *)def + def->vd_aux);
225*49cdfc7eSAndroid Build Coastguard Worker 	return def->vd_hash == hash
226*49cdfc7eSAndroid Build Coastguard Worker 		&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
227*49cdfc7eSAndroid Build Coastguard Worker }
228*49cdfc7eSAndroid Build Coastguard Worker 
vdso_sym(const char * version,const char * name)229*49cdfc7eSAndroid Build Coastguard Worker void *vdso_sym(const char *version, const char *name)
230*49cdfc7eSAndroid Build Coastguard Worker {
231*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long ver_hash;
232*49cdfc7eSAndroid Build Coastguard Worker 	if (!vdso_info.valid)
233*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
234*49cdfc7eSAndroid Build Coastguard Worker 
235*49cdfc7eSAndroid Build Coastguard Worker 	ver_hash = elf_hash((const void*)version);
236*49cdfc7eSAndroid Build Coastguard Worker 	ELF(Word) chain = get_hash_val(vdso_info.bucket,
237*49cdfc7eSAndroid Build Coastguard Worker 		elf_hash((const void*)name) % vdso_info.nbucket);
238*49cdfc7eSAndroid Build Coastguard Worker 
239*49cdfc7eSAndroid Build Coastguard Worker 	for (; chain != STN_UNDEF; chain = get_hash_val(vdso_info.chain, chain)) {
240*49cdfc7eSAndroid Build Coastguard Worker 		ELF(Sym) *sym = &vdso_info.symtab[chain];
241*49cdfc7eSAndroid Build Coastguard Worker 
242*49cdfc7eSAndroid Build Coastguard Worker 		/* Check for a defined global or weak function w/ right name. */
243*49cdfc7eSAndroid Build Coastguard Worker 		if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
244*49cdfc7eSAndroid Build Coastguard Worker 			continue;
245*49cdfc7eSAndroid Build Coastguard Worker 		if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
246*49cdfc7eSAndroid Build Coastguard Worker 		    ELF64_ST_BIND(sym->st_info) != STB_WEAK)
247*49cdfc7eSAndroid Build Coastguard Worker 			continue;
248*49cdfc7eSAndroid Build Coastguard Worker 		if (sym->st_shndx == SHN_UNDEF)
249*49cdfc7eSAndroid Build Coastguard Worker 			continue;
250*49cdfc7eSAndroid Build Coastguard Worker 		if (strcmp(name, vdso_info.symstrings + sym->st_name))
251*49cdfc7eSAndroid Build Coastguard Worker 			continue;
252*49cdfc7eSAndroid Build Coastguard Worker 
253*49cdfc7eSAndroid Build Coastguard Worker 		/* Check symbol version. */
254*49cdfc7eSAndroid Build Coastguard Worker 		if (vdso_info.versym
255*49cdfc7eSAndroid Build Coastguard Worker 		    && !vdso_match_version(vdso_info.versym[chain],
256*49cdfc7eSAndroid Build Coastguard Worker 					   version, ver_hash))
257*49cdfc7eSAndroid Build Coastguard Worker 			continue;
258*49cdfc7eSAndroid Build Coastguard Worker 
259*49cdfc7eSAndroid Build Coastguard Worker 		return (void *)(vdso_info.load_offset + sym->st_value);
260*49cdfc7eSAndroid Build Coastguard Worker 	}
261*49cdfc7eSAndroid Build Coastguard Worker 
262*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
263*49cdfc7eSAndroid Build Coastguard Worker }
264*49cdfc7eSAndroid Build Coastguard Worker 
vdso_init_from_auxv(void * auxv)265*49cdfc7eSAndroid Build Coastguard Worker void vdso_init_from_auxv(void *auxv)
266*49cdfc7eSAndroid Build Coastguard Worker {
267*49cdfc7eSAndroid Build Coastguard Worker 	int i;
268*49cdfc7eSAndroid Build Coastguard Worker 
269*49cdfc7eSAndroid Build Coastguard Worker 	ELF(auxv_t) *elf_auxv = auxv;
270*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; elf_auxv[i].a_type != AT_NULL; i++) {
271*49cdfc7eSAndroid Build Coastguard Worker 		if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
272*49cdfc7eSAndroid Build Coastguard Worker 			vdso_init_from_sysinfo_ehdr(elf_auxv[i].a_un.a_val);
273*49cdfc7eSAndroid Build Coastguard Worker 			return;
274*49cdfc7eSAndroid Build Coastguard Worker 		}
275*49cdfc7eSAndroid Build Coastguard Worker 	}
276*49cdfc7eSAndroid Build Coastguard Worker 
277*49cdfc7eSAndroid Build Coastguard Worker 	vdso_info.valid = false;
278*49cdfc7eSAndroid Build Coastguard Worker }
279