/*
 * parse_vdso.c: Linux reference vDSO parser
 * Written by Andrew Lutomirski, 2011-2014.
 *
 * This code is meant to be linked in to various programs that run on Linux.
 * As such, it is available with as few restrictions as possible.  This file
 * is licensed under the Creative Commons Zero License, version 1.0,
 * available at http://creativecommons.org/publicdomain/zero/1.0/legalcode
 *
 * The vDSO is a regular ELF DSO that the kernel maps into user space when
 * it starts a program.  It works equally well in statically and dynamically
 * linked binaries.
 *
 * This code is tested on x86.  In principle it should work on any
 * architecture that has a vDSO.
 */

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <linux/auxvec.h>
#include <linux/elf.h>

#include "parse_vdso.h"

/* And here's the code. */
#ifndef ELF_BITS
# if __SIZEOF_LONG__ >= 8
#  define ELF_BITS 64
# else
#  define ELF_BITS 32
# endif
#endif

#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
#define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)

#ifdef __s390x__
#define ELF_HASH_ENTRY ELF(Xword)
#else
#define ELF_HASH_ENTRY ELF(Word)
#endif

static struct vdso_info
{
	bool valid;

	/* Load information */
	uintptr_t load_addr;
	uintptr_t load_offset;  /* load_addr - recorded vaddr */

	/* Symbol table */
	ELF(Sym) *symtab;
	const char *symstrings;
	ELF(Word) *gnu_hash, *gnu_bucket;
	ELF_HASH_ENTRY *bucket, *chain;
	ELF_HASH_ENTRY nbucket, nchain;

	/* Version table */
	ELF(Versym) *versym;
	ELF(Verdef) *verdef;
} vdso_info;

/*
 * Straight from the ELF specification...and then tweaked slightly, in order to
 * avoid a few clang warnings.
 */
static unsigned long elf_hash(const char *name)
{
	unsigned long h = 0, g;
	const unsigned char *uch_name = (const unsigned char *)name;

	while (*uch_name)
	{
		h = (h << 4) + *uch_name++;
		g = h & 0xf0000000;
		if (g)
			h ^= g >> 24;
		h &= ~g;
	}
	return h;
}

static uint32_t gnu_hash(const char *name)
{
	const unsigned char *s = (void *)name;
	uint32_t h = 5381;

	for (; *s; s++)
		h += h * 32 + *s;
	return h;
}

void vdso_init_from_sysinfo_ehdr(uintptr_t base)
{
	size_t i;
	bool found_vaddr = false;

	vdso_info.valid = false;

	vdso_info.load_addr = base;

	ELF(Ehdr) *hdr = (ELF(Ehdr)*)base;
	if (hdr->e_ident[EI_CLASS] !=
	    (ELF_BITS == 32 ? ELFCLASS32 : ELFCLASS64)) {
		return;  /* Wrong ELF class -- check ELF_BITS */
	}

	ELF(Phdr) *pt = (ELF(Phdr)*)(vdso_info.load_addr + hdr->e_phoff);
	ELF(Dyn) *dyn = 0;

	/*
	 * We need two things from the segment table: the load offset
	 * and the dynamic table.
	 */
	for (i = 0; i < hdr->e_phnum; i++)
	{
		if (pt[i].p_type == PT_LOAD && !found_vaddr) {
			found_vaddr = true;
			vdso_info.load_offset =	base
				+ (uintptr_t)pt[i].p_offset
				- (uintptr_t)pt[i].p_vaddr;
		} else if (pt[i].p_type == PT_DYNAMIC) {
			dyn = (ELF(Dyn)*)(base + pt[i].p_offset);
		}
	}

	if (!found_vaddr || !dyn)
		return;  /* Failed */

	/*
	 * Fish out the useful bits of the dynamic table.
	 */
	ELF_HASH_ENTRY *hash = 0;
	vdso_info.symstrings = 0;
	vdso_info.gnu_hash = 0;
	vdso_info.symtab = 0;
	vdso_info.versym = 0;
	vdso_info.verdef = 0;
	for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
		switch (dyn[i].d_tag) {
		case DT_STRTAB:
			vdso_info.symstrings = (const char *)
				((uintptr_t)dyn[i].d_un.d_ptr
				 + vdso_info.load_offset);
			break;
		case DT_SYMTAB:
			vdso_info.symtab = (ELF(Sym) *)
				((uintptr_t)dyn[i].d_un.d_ptr
				 + vdso_info.load_offset);
			break;
		case DT_HASH:
			hash = (ELF_HASH_ENTRY *)
				((uintptr_t)dyn[i].d_un.d_ptr
				 + vdso_info.load_offset);
			break;
		case DT_GNU_HASH:
			vdso_info.gnu_hash =
				(ELF(Word) *)((uintptr_t)dyn[i].d_un.d_ptr +
					      vdso_info.load_offset);
			break;
		case DT_VERSYM:
			vdso_info.versym = (ELF(Versym) *)
				((uintptr_t)dyn[i].d_un.d_ptr
				 + vdso_info.load_offset);
			break;
		case DT_VERDEF:
			vdso_info.verdef = (ELF(Verdef) *)
				((uintptr_t)dyn[i].d_un.d_ptr
				 + vdso_info.load_offset);
			break;
		}
	}
	if (!vdso_info.symstrings || !vdso_info.symtab ||
	    (!hash && !vdso_info.gnu_hash))
		return;  /* Failed */

	if (!vdso_info.verdef)
		vdso_info.versym = 0;

	/* Parse the hash table header. */
	if (vdso_info.gnu_hash) {
		vdso_info.nbucket = vdso_info.gnu_hash[0];
		/* The bucket array is located after the header (4 uint32) and the bloom
		 * filter (size_t array of gnu_hash[2] elements).
		 */
		vdso_info.gnu_bucket = vdso_info.gnu_hash + 4 +
				       sizeof(size_t) / 4 * vdso_info.gnu_hash[2];
	} else {
		vdso_info.nbucket = hash[0];
		vdso_info.nchain = hash[1];
		vdso_info.bucket = &hash[2];
		vdso_info.chain = &hash[vdso_info.nbucket + 2];
	}

	/* That's all we need. */
	vdso_info.valid = true;
}

static bool vdso_match_version(ELF(Versym) ver,
			       const char *name, ELF(Word) hash)
{
	/*
	 * This is a helper function to check if the version indexed by
	 * ver matches name (which hashes to hash).
	 *
	 * The version definition table is a mess, and I don't know how
	 * to do this in better than linear time without allocating memory
	 * to build an index.  I also don't know why the table has
	 * variable size entries in the first place.
	 *
	 * For added fun, I can't find a comprehensible specification of how
	 * to parse all the weird flags in the table.
	 *
	 * So I just parse the whole table every time.
	 */

	/* First step: find the version definition */
	ver &= 0x7fff;  /* Apparently bit 15 means "hidden" */
	ELF(Verdef) *def = vdso_info.verdef;
	while(true) {
		if ((def->vd_flags & VER_FLG_BASE) == 0
		    && (def->vd_ndx & 0x7fff) == ver)
			break;

		if (def->vd_next == 0)
			return false;  /* No definition. */

		def = (ELF(Verdef) *)((char *)def + def->vd_next);
	}

	/* Now figure out whether it matches. */
	ELF(Verdaux) *aux = (ELF(Verdaux)*)((char *)def + def->vd_aux);
	return def->vd_hash == hash
		&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
}

static bool check_sym(ELF(Sym) *sym, ELF(Word) i, const char *name,
		      const char *version, unsigned long ver_hash)
{
	/* Check for a defined global or weak function w/ right name. */
	if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
		return false;
	if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
	    ELF64_ST_BIND(sym->st_info) != STB_WEAK)
		return false;
	if (strcmp(name, vdso_info.symstrings + sym->st_name))
		return false;

	/* Check symbol version. */
	if (vdso_info.versym &&
	    !vdso_match_version(vdso_info.versym[i], version, ver_hash))
		return false;

	return true;
}

void *vdso_sym(const char *version, const char *name)
{
	unsigned long ver_hash;
	if (!vdso_info.valid)
		return 0;

	ver_hash = elf_hash(version);
	ELF(Word) i;

	if (vdso_info.gnu_hash) {
		uint32_t h1 = gnu_hash(name), h2, *hashval;

		i = vdso_info.gnu_bucket[h1 % vdso_info.nbucket];
		if (i == 0)
			return 0;
		h1 |= 1;
		hashval = vdso_info.gnu_bucket + vdso_info.nbucket +
			  (i - vdso_info.gnu_hash[1]);
		for (;; i++) {
			ELF(Sym) *sym = &vdso_info.symtab[i];
			h2 = *hashval++;
			if (h1 == (h2 | 1) &&
			    check_sym(sym, i, name, version, ver_hash))
				return (void *)(vdso_info.load_offset +
						sym->st_value);
			if (h2 & 1)
				break;
		}
	} else {
		i = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
		for (; i; i = vdso_info.chain[i]) {
			ELF(Sym) *sym = &vdso_info.symtab[i];
			if (sym->st_shndx != SHN_UNDEF &&
			    check_sym(sym, i, name, version, ver_hash))
				return (void *)(vdso_info.load_offset +
						sym->st_value);
		}
	}

	return 0;
}
