struct thread_info {
	struct task_struct	*task;		 
};
struct task_struct {
	int uid;
	int euid;
	int gid;
	int egid;
};
struct linux_binprm{
        unsigned long p;
        int argc, envc;
};
struct elfhdr {
  unsigned char	e_ident[16 ];
  unsigned short  	e_type;
  unsigned short  	e_machine;
  unsigned int  	e_version;
  unsigned int  	e_entry;   
  unsigned int  	e_phoff;
  unsigned int  	e_shoff;
  unsigned int  	e_flags;
  unsigned short  	e_ehsize;
  unsigned short  	e_phentsize;
  unsigned short  	e_phnum;
  unsigned short  	e_shentsize;
  unsigned short  	e_shnum;
  unsigned short  	e_shstrndx;
};
struct elf_phdr{
  unsigned int  	p_type;
  unsigned int  	p_offset;
  unsigned int  	p_vaddr;
  unsigned int  	p_paddr;
  unsigned int  	p_filesz;
  unsigned int  	p_memsz;
  unsigned int  	p_flags;
  unsigned int  	p_align;
};

static inline struct thread_info *current_thread_info(void)
{
	register unsigned long sp asm ("sp");
	return (struct thread_info *)(sp & ~0x1fff);
}

static inline struct task_struct *get_current(void)
{
	return (void *)current_thread_info();
}

static int ELF_HWCAP;

void foo(struct linux_binprm *bprm, struct elfhdr * exec, void *f, int interp_aout, unsigned long load_addr, unsigned long interp_load_addr)
{
	unsigned long p = bprm->p;
	int argc = bprm->argc;
	int envc = bprm->envc;
	unsigned long *argv, *envp;
	unsigned long *sp, *u_platform;
	const char *k_platform = "foo";
	int items;
	unsigned int elf_info[40];
	int ei_index = 0;

	u_platform = 0;
	if (k_platform) {
		int len = strlen(k_platform) + 1;
		u_platform = (unsigned long *)  p  -=   len  ;
	}

	elf_info[ei_index++] = 16;
	elf_info[ei_index++] = ELF_HWCAP;
	elf_info[ei_index++] = 6;
	elf_info[ei_index++] = 4096;
	elf_info[ei_index++] = 17;
	elf_info[ei_index++] = 100;
	elf_info[ei_index++] = 3;
	elf_info[ei_index++] = load_addr;
	elf_info[ei_index++] = 4;
	elf_info[ei_index++] = sizeof(struct elf_phdr);
	elf_info[ei_index++] = 5;
	elf_info[ei_index++] = exec->e_phnum;
	elf_info[ei_index++] = 7;
	elf_info[ei_index++] = interp_load_addr;
	elf_info[ei_index++] = 8;
	elf_info[ei_index++] = 0;
	elf_info[ei_index++] = 9;
	elf_info[ei_index++] = 42;
	elf_info[ei_index++] = 11;
	elf_info[ei_index++] = (unsigned long) get_current()->uid;
	elf_info[ei_index++] = 12;
	elf_info[ei_index++] = (unsigned long) get_current()->euid;
	elf_info[ei_index++] = 13;
	elf_info[ei_index++] = (unsigned long) get_current()->gid;
	if (k_platform) {
		elf_info[ei_index++] =  15;
		elf_info[ei_index++] = (unsigned long)(long)u_platform;
	}
	elf_info[ei_index++] = 0;
	elf_info[ei_index++] = 0;

	sp = ((unsigned long *)( p ) - (  ei_index )) ;

	items = (argc + 1) + (envc + 1);
	if (interp_aout) {
		items += 3;  
	} else {
		items += 1;  
	}

	bprm->p = (((unsigned long) ( sp  -   items )) &~ 15UL) ;
	memcpy(f, elf_info, sizeof(elf_info));
}

static struct elfhdr e;
unsigned char arry[32768];

int main()
{
	struct linux_binprm b;
	unsigned int t[40];
	int i;

	b.p = (unsigned long)arry + 32768;

	memset(t, 0, sizeof(t));

	foo(&b, &e, t, 0, 0x12345678, 0x87654321);

	for (i = 0; i < 20; i++)
		printf("%02d: %08x %02x\n", i, t[i * 2], t[i * 2 + 1]);
	return 0;
}
