#include <elf.h>
#include <stdio.h>
#include <stdint.h>
#include <link.h>

#include "hash_lookup.c"

int main()
{
	Elf32_Dyn *dyn;
	uint32_t *pltgot = NULL, init;
	struct link_map *link_map;
	void *libc_hash, *libc_dsym, *libc_dstr;
	int i;
	
	for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn)
		if (dyn->d_tag == DT_PLTGOT)
			pltgot = (uint32_t*)dyn->d_un.d_ptr;
		else
		if (dyn->d_tag == DT_INIT)
			init = dyn->d_un.d_val;
	if (pltgot == NULL || (link_map = (struct link_map*)pltgot[1]) == NULL)
		return 2;
	if ((uint32_t)link_map > init) {
		puts("GOT[1] pointer links to .plt");
		return 2;
	}
	for (dyn = NULL ; link_map != NULL; link_map = link_map->l_next)
		if (link_map->l_name && strstr(link_map->l_name, "libc")) {
			dyn = link_map->l_ld;
			break;
		}
	libc_hash = libc_dstr = libc_dsym = NULL;
	for (i = 0; dyn[i].d_tag != DT_NULL; i++)
		if (dyn[i].d_tag == DT_HASH)
			libc_hash = (void*)dyn[i].d_un.d_ptr;
		else
		if (dyn[i].d_tag == DT_STRTAB)
			libc_dstr = (void*)dyn[i].d_un.d_ptr;
		else
		if (dyn[i].d_tag == DT_SYMTAB)
			libc_dsym = (void*)dyn[i].d_un.d_ptr;
	if (libc_hash == NULL || libc_dsym == NULL || libc_dstr == NULL)
		return 2;
	int (*printf_ptr)(char *,...) = (int(*)(char*,...))lookup("printf", libc_hash, libc_dsym, libc_dstr);
	printf_ptr("printf = %08x\n", printf_ptr);
	return 0;
}
