/* elfy.c - anthony lineberry 
 *
 * this is just a quick little hack
 * to show how to dump information from
 * an elf header. it is nowhere near complete
 * and is missing a lot of features. but 
 * this will do for now.
 * as usual, this is gpl licensed code.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

typedef struct _elf_file_t
{
	unsigned int magic;
	unsigned char bitness;
	unsigned char endian;
	unsigned char elf_ver_1;
	unsigned char reserved[9];
	unsigned short file_type;
	unsigned short machine;
	unsigned int elf_ver_2;
	unsigned int entry;
	unsigned int phtab_offset; //program header
	unsigned int shtab_offset; //section header
	unsigned int flags;
	unsigned short file_hdr_size;
	unsigned short ph_size;
	unsigned short num_ph;
	unsigned short sh_size;
	unsigned short num_sects;
	unsigned short shstrtab_index;
} elf_file_t __attribute__ ((packed));

typedef struct _elf_sect_t
{
	unsigned int sect_name;
	unsigned int type;
	unsigned int flags;
	unsigned int virt_adr;
	unsigned int offset;
	unsigned int size;
	unsigned int link;
	unsigned int info;
	unsigned int align;
	unsigned int ent_size;
} elf_sect_t __attribute__ ((packed));

typedef struct _elf_seg_t
{
	unsigned int type;
	unsigned int offset;
	unsigned int virt_adr;
	unsigned int phys_adr;
	unsigned int disk_size;
	unsigned int mem_size;
	unsigned int flags;
	unsigned int align;
} elf_seg_t __attribute__ ((packed));


int main(int argc, char *argv[])
{
		FILE *fd;
		char *image;
		
		if(argc < 2)
		{
			printf("usage: %s <filename>\n", argv[0]);
			return 0;
		}
		
		fd=fopen(argv[1], "r");
		
		struct stat *statptr;
		statptr = (struct stat *)malloc(sizeof(struct stat));
		stat(argv[1], statptr);
		image = (char *)malloc(statptr->st_size);
		printf("%s - %dbytes", argv[1], statptr->st_size);
		fread(image, 1, statptr->st_size, fd);
		
		elf_file_t *elf_file;
		elf_sect_t *elf_sect;
		elf_file = (elf_file_t *)image;
		printf("elf dump -- (%s)\n", argv[1]);
		printf("\tmagic: %x\n", elf_file->magic);
		printf("\tbits:  %s\n", elf_file->bitness ? "32bit" : "64bit");
		printf("\tendian: %s\n", elf_file->endian ? "little" : "big");
		printf("\tver1: %s\n", elf_file->elf_ver_1 ? "yes" : "no");
		printf("\tfile: %s\n", elf_file->file_type == 1 ? "relocatable" : 
					   			elf_file->file_type == 2 ? "executable" : "DLL");
		printf("\tmach: %s\n", elf_file->machine == 3 ? "i386 elf" : "other");
		printf("\tentry: 0x%x\n", elf_file->entry);
		printf("\tnum sects: %d\n", elf_file->num_sects);
		printf("\tsh strtab: 0x%08x\n", elf_file->shstrtab_index);
		
		printf("\nSections:\n");
		
		elf_sect_t *strtab;
		
		// create a pointer to the section header string table
		strtab = (elf_sect_t *)(image+elf_file->shtab_offset);
		strtab += elf_file->shstrtab_index; 
		
		printf("strtab->offset: %x\n", strtab->offset);	
		int s;
		for(s = 0; s < elf_file->num_sects; s++)
		{
	
			elf_sect = (elf_sect_t *)(image + elf_file->shtab_offset + 
									 elf_file->sh_size * s);
			if(elf_sect->size <= 0 ) continue;	
			printf("%d %s:\n", s, image+strtab->offset+elf_sect->sect_name);
			printf("\tsize: 0x%08x\n", s, elf_sect->size);
			printf("\toffset: 0x%08x\n", elf_sect->offset);
			printf("\tvirtadr: 0x%08x\n", elf_sect->virt_adr);
		}
		return(0);
}
