#include bastard

/* -------------------------------------------------------- elf structs  */
struct ELF_HDR{
  char    e_ident[16]; /* Magic number and other info */
  short   e_type;         /* Object file type */
  short   e_machine;      /* Architecture */
  int     e_version;      /* Object file version */
  int     e_entry;        /* Entry point virtual address */
  int     e_phoff;        /* Program header table file offset */
  int     e_shoff;        /* Section header table file offset */
  int     e_flags;        /* Processor-specific flags */
  short   e_ehsize;       /* ELF header size in bytes */
  short   e_phentsize;        /* Program header table entry size */
  short   e_phnum;        /* Program header table entry count */
  short   e_shentsize;        /* Section header table entry size */
  short   e_shnum;        /* Section header table entry count */
  short   e_shstrndx;     /* Section header string table index */
};

struct ELF_SECT{
  int    sh_name;        /* Section name (string tbl index) */
  int    sh_type;        /* Section type */
  int    sh_flags;       /* Section flags */
  int    sh_addr;        /* Section virtual addr at execution */
  int    sh_offset;      /* Section file offset */
  int    sh_size;        /* Section size in bytes */
  int    sh_link;        /* Link to another section */
  int    sh_info;        /* Additional section information */
  int    sh_addralign;       /* Section alignment */
  int    sh_entsize;     /* Entry size if section holds table */
};


struct ELF_PROG{
  int    p_type;         /* Segment type */
  int    p_offset;       /* Segment file offset */
  int    p_vaddr;        /* Segment virtual address */
  int    p_paddr;        /* Segment physical address */
  int    p_filesz;       /* Segment size in file */
  int    p_memsz;        /* Segment size in memory */
  int    p_flags;        /* Segment flags */
  int    p_align;        /* Segment alignment */
};

struct DYN{
	int tag;
	int val;
};

struct ELF_SYM{
	int	st_name;
	int	st_value;
	int	st_size;
	char	st_info;
	char	st_other;
	short	st_shndx;
};

/* ------------------------------------------------------------ ProgHdr LL */
struct PHDR{
	int rva;
	int pa;
	int size;
	PHDR *next;
} ;

/* ---------------------------------------------------------- symbol types */
#define STT_NOTYPE       0
#define STT_OBJECT       1
#define STT_FUNC         2
#define STT_SECTION      3
#define STT_FILE         4
#define STT_LOPROC      13
#define STT_HIPROC      15


/* --------------------------------------------------------------- globals */
char *HeaderStr = NULL, *strNote = NULL;
ELF_HDR  *File_hdr = NULL;
ELF_SECT *Sec_hdr = NULL, *strSec = NULL;
ELF_PROG *Prog_hdr = NULL, *Dyn_hdr = NULL;
DYN *dyn = NULL;
int *secTable = NULL;
int *progTable = NULL;
PHDR phdr_start;


/* ----------------------------------------------------- phdr linked list */
int AddPhdr( int rva, int pa, int size){
	PHDR *p;

	p =  &phdr_start;
	while (p->next != NULL) {
		p = p->next;
	}
	p->next = malloc(sizeof(PHDR));
	p->next->rva = rva;
	p->next->pa = pa;
	p->next->size = size;
	p->next->next = NULL;
	return(0);
}

int CleanPhdr(){
	PHDR *p, *tmp;

	p =  &phdr_start;
	while (p->next != NULL) {
		tmp = p->next;
		p->next = p->next->next;
		free(tmp);
	}
}

int GetPA(int rva){
	/* use PHDR llist to convert rva to pa */
	PHDR *p;

	p =  &phdr_start;
	while (p->next != NULL) {
		if ( rva > p->next->rva && rva < (p->next->rva + p->next->size)){
			return( p->next->pa + (rva - p->next->rva) );
		}
		p = p->next;
	}
	return(0);
}
/*  ----------------------------------------------------doDynamic( int offset )
	-- Parse .dynamic section
*/
int doDynamic( int offset, int size ){
	struct DYNSTR{
		int offset;
		DYNSTR *next;
	} hNeeded, hSoName, hRPath, *cNeeded, *cSoName, *cRPath, *tmpDynStr;
	ELF_SYM *sym;
	ELF_PROG *tmpPH;
	void *strtable;
	char *c, *tmp;
	int str_addr, str_size, sym_addr, sym_size, hash_addr;
	int plt_addr, plt_size, plt_rel, rela_addr, rela_size, rela_ent;
	int rel_addr, rel_size, rel_ent, x, pos = 0, jnk=0;
	dyn = malloc( sizeof(DYN));
	hNeeded.next = hSoName.next = hRPath.next = NULL;
	cNeeded = &hNeeded; cSoName = &hSoName; cRPath = &hRPath;
	

	lseek( target.FD, offset, 0);
	while( pos < size) {
		pos += read( target.FD, dyn, sizeof( DYN));
		switch (dyn->tag){
			case 0:
				//DT_NULL : ignore
				break;
			case 1:
				//DT_NEEDED: strname of req lib [opt]
				tmpDynStr = malloc(sizeof(hNeeded));
				tmpDynStr->offset = dyn->val;
				tmpDynStr->next = NULL;
				cNeeded->next = tmpDynStr;
				cNeeded = tmpDynStr;
				break;
			case 2:
				//DT_PLTRELSZ : val == size of relocs in PLT [opt]
				plt_size = dyn->val;
				break;
			case 3:
				//DT_PLTGOT : val == ptr to PLT/GOT [opt]
				plt_addr = dyn->val;
				break;
			case 4:
				//DT_HASH : addr of symbol hash table [req]
				hash_addr = dyn->val;
				break;
			case 5:
				//DT_STRTAB : addr of string table [req]
				str_addr = dyn->val;
				break;
			case 6:
				//DT_SYMTAB : val = addr of symbol table [req]
				sym_addr = dyn->val;
				break;
			case 7:
				//DT_RELA : val = addr of reloc table [req]
				rela_addr - dyn->val;
				break;
			case 8:
				//DT_RELASZ : size of RELA reloc table [reg]
				rela_size - dyn->val;
				break;
			case 9:
				//DT_RELAENT : size of RELA reloc entry [req]
				rela_ent - dyn->val;
				break;
			case 10:
				//DT_STRSZ : size of str table [req]
				str_size = dyn->val;
				break;
			case 11:
				//DT_SYMENT : size of sym table entry [req]
				sym_size = dyn->val;
				break;
			case 12:
				//DT_INIT : val = addr of init function [opt]
				sprintf(strNote, "%s init routine at %08X\n", strNote,  dyn->val);
				break;
			case 13:
				//DT_FINI : val = addr of term function [opt]
				sprintf(strNote, "%s term routine at %08X\n", strNote, dyn->val);
				break;
			case 14:
				//DT_SONAME : strtable offset of file's soname [ig]
				tmpDynStr = malloc(sizeof(hSoName));
				tmpDynStr->offset = dyn->val;
				tmpDynStr->next = NULL;
				cSoName->next = tmpDynStr;
				cSoName = tmpDynStr;
				break;
			case 15:
				//DT_RPATH : val = strtable offset of lib path [opt]
				tmpDynStr = malloc(sizeof(hRPath));
				tmpDynStr->offset = dyn->val;
				tmpDynStr->next = NULL;
				cRPath->next = tmpDynStr;
				cRPath = tmpDynStr;
				break;
			case 16:
				//DT_SYMBOLIC : change dyn-link behavior [ig]
				break;
			case 17:
				//DT_REL : val = addr of reloc table [req]
				rel_addr = dyn->val;
				break;
			case 18:
				//DT_RELSZ : size of DT_REL table [req]
				rel_size = dyn->val;
				break;
			case 19:
				//DT_RELENT : size of DT_REL entry [req]
				rel_ent = dyn->val;
				break;
			case 20:
				//DT_PLTREL : val = type of PLT relocs (REL/RELA) [opt]
				break;
			case 21:
				//DT_DEBUG [opt]
				break;
			case 22:
				//DT_TEXTREL : relocs present in .text [opt]
				break;
			case 23:
				//DT_JMPREL : val = addr of PLT relocs [opt]
				plt_rel = dyn->val;
				break;
			case 0x70000000:
				//DT_LOPROC [ig]
				break;
			case 0x7FFFFFFF:
				//DT_HIPROC [ig]
				break;
			default:
				//printf("%d: %08X\n", dyn->tag, dyn->val);
		}
	}

	/* do PLT/GOT */
	if (plt_addr){
		sprintf(strNote, "%sPLT size: %08X reloc: %08X rva: %08X\n", 
				strNote, plt_size, plt_rel, plt_addr);
	}

	if (hash_addr){
		sprintf(strNote, "%sSymbol Hash Table rva: %08X\n", strNote, hash_addr);
	}

	if (rel_addr){
		sprintf(strNote, "%sREL size: %08X entry size: %08X rva: %08X\n", strNote,
					rel_size, rel_ent, rel_addr);
	}

	if (rela_addr){
		sprintf(strNote, "%sRELA size: %08X entry size: %08X rva: %08X\n",strNote,
					rela_size, rela_ent, rela_addr);
	}

	if (str_addr) {
		/*  Get offset of dynstr table */
		for (x = 0; x < File_hdr->e_phnum; x++) {
			tmpPH = progTable[x];
			if (str_addr >= tmpPH->p_vaddr && 
				str_addr < (tmpPH->p_vaddr + tmpPH->p_filesz))
					str_addr -= (tmpPH->p_vaddr - tmpPH->p_offset);	
		}

		sprintf( strNote, "%sString Table .dynstr of size %08X at offset %08X\n",
					strNote, str_size, str_addr);
		strtable = malloc( str_size );
		lseek (target.FD, str_addr, 0);
		read(target.FD, strtable, str_size);
		cNeeded = &hNeeded;
		while (cNeeded->next != NULL){
			DefineLibrary( strtable + cNeeded->next->offset, 0, 0);
			sprintf(strNote, "%s   Target requires %s\n", strNote, 
						strtable + cNeeded->next->offset);
			cNeeded = cNeeded->next;
           }
		cSoName = &hSoName;
		while (cSoName->next != NULL) {
			sprintf( strNote, "%s   Target has .so name of %s\n", strNote, 
					strtable + cSoName->offset);
			cSoName = cSoName->next;
		}
		cRPath = &hRPath;
		while (cRPath->next != NULL) {
			cRPath = cRPath->next;
			sprintf(strNote, "%s   Target has a library path of %s\n", strNote,
					strtable + cRPath->offset);
		}
	}  

	if (sym_addr){
		/*  Get offset of symbol table */
		for (x = 0; x < File_hdr->e_phnum; x++) {
			tmpPH = progTable[x];
			if (sym_addr >= tmpPH->p_vaddr && 
				sym_addr < (tmpPH->p_vaddr + tmpPH->p_filesz))
					sym_addr -= (tmpPH->p_vaddr - tmpPH->p_offset);	
		}
		sym = malloc(sizeof(ELF_SYM));
		pos = lseek(target.FD, sym_addr, 0);

		while ( pos < str_addr) {
			pos += read(target.FD, sym, sizeof( ELF_SYM));
			/* if it is a valid freaken name.... */
			c = strtable + sym->st_name;
			if (sym->st_name > 0  && c[0] > 31  && c[0] < 127) { 
				switch ( (sym->st_info & 0xf) ) {
					/* SYMBOL constants:
						NAME_AUTO    0x01
						NAME_SUB     0x02
						NAME_USER    0x10
						NAME_SYMBOL  0x20
					*/
					case STT_OBJECT :
						// pa == jnk + strtable + sym->st_size ??
						DefineAddr(sym->st_value, sym->st_size, GetPA(sym->st_value), 
										ADDR_SYMBOL & ADDR_DATA);
						SetName( sym->st_value, strtable + sym->st_name, 0x21);		
						break;
					case STT_FUNC :
						DefineAddr(sym->st_value, sym->st_size, GetPA(sym->st_value), 
										ADDR_SYMBOL & ADDR_CODE);
						SetName( sym->st_value, strtable + sym->st_name, 0x23);		
						if (sym->st_shndx == 0){
							/* this is an imported function */
							/* check to see which DT_NEEDED this falls under */
							tmp = NULL;
							cNeeded = &hNeeded;
							while (cNeeded->next != NULL){
								if ( sym->st_name > cNeeded->next->offset){
									if (! cNeeded->next->next ||  
										   cNeeded->next->next->offset > sym->st_name ){
				       					tmp = strtable + cNeeded->next->offset;
										}
								}
								cNeeded = cNeeded->next;
      					}
							DefineImport(sym->st_value, tmp, strtable+sym->st_name, 0);
						} else {
							/* Not an imported function */
							DefineFunc(sym->st_value, strtable + sym->st_name, 
											sym->st_size);
						}
						break;
					case STT_FILE :
						sprintf(strNote, "%sSource File: %s\n", strNote, 
												strtable + sym->st_name);
						break;
					case STT_SECTION :
					case STT_NOTYPE :
						/* add extra symbols [those w/o rva's are discarded] */
						SetName( sym->st_value, strtable + sym->st_name, 0x20);		
					case STT_LOPROC :
					case STT_HIPROC :
					default:
						//	printf("Symbol %s val %08X type %d size %d \n", strtable + 
						//			sym->st_name, sym->st_value, (sym->st_info & 0xf), 
						//			sym->st_size);
						break;

				}
			}
		}
		free(sym);	
		sprintf(strNote, "%sSymbol Table entry size: %08X offset: %08X\n", 
					strNote, sym_size, sym_addr);
	}


	/* free the linked lists if they have anything in them... */
	if ( hNeeded.next != NULL){
		cNeeded = hNeeded.next;
		while (cNeeded->next != NULL) {
			tmpDynStr = cNeeded;
			cNeeded = cNeeded->next;
			free(tmpDynStr);
		}
		free(cNeeded);
	}
	if ( hSoName.next != NULL){
		cSoName = hSoName.next;
		while (cSoName->next != NULL) {
			tmpDynStr = cSoName;
			cSoName = cSoName->next;
			free(tmpDynStr);
		}
		free(cSoName);
	}
	if ( hRPath.next != NULL){
		cRPath = hRPath.next;
		while (cRPath->next != NULL) {
			tmpDynStr = cRPath;
			cRPath = cRPath->next;
			free(tmpDynStr);
		}
		free(cRPath);
	}
	free(strtable);
	
	free(dyn); 
}


/*  ----------------------------------------------------doSectionTable( void )
	-- Parse ELF Section Header table and add to HeaderStr
	-- Create Sections in DB if the section headers exist
*/
int doSectionTable( ){
	int x, len, pos; 
	int jnk=0;
	int retVal=0;
	char secType[16], secFlags[4], *secName, *strTable;
	char pad[3], noName[7] = "(null)";

	sprintf(HeaderStr, "%s\n\n__Section_Table___________________\n", HeaderStr);

	/* Make array of pointers to section headers */
	if (File_hdr->e_shnum == 0) return(0);
	secTable = calloc( 4, jnk + File_hdr->e_shnum);
	for (x = 0; x < File_hdr->e_shnum; x++) {
		Sec_hdr = secTable[x] = malloc(sizeof(ELF_SECT));

		pos = lseek(target.FD, File_hdr->e_shoff + ( File_hdr->e_shentsize * x),
                    0);
		read(target.FD, Sec_hdr, sizeof(ELF_SECT));
	}

	/* Load String Index */
	if (File_hdr->e_shstrndx){ 
			strSec  = secTable[File_hdr->e_shstrndx];
			strTable = malloc(strSec->sh_size);
			lseek(target.FD, strSec->sh_offset, 0);
			read(target.FD, strTable, jnk + strSec->sh_size);
	}

	for (x = 0; x < File_hdr->e_shnum; x++) {
		Sec_hdr = secTable[x];

		/* get section name from string table */
		if (File_hdr->e_shstrndx) secName = strTable + Sec_hdr->sh_name;
		else secName = &noName;
		len = strlen(secName);
		if (len < 7) sprintf(pad, "\t\t");
		else if (len > 13) sprintf(pad, " ");
		else sprintf(pad, "\t");

		/*   Convert Type to printable string    */
		switch(Sec_hdr->sh_type){
			case 0:
				strcpy(secType, "SHT_NULL"); break;
			case 1:
				strcpy(secType, "SHT_PROGBITS"); break;
			case 2:
				strcpy(secType, "SHT_SYMTAB"); break;
			case 3:
				strcpy(secType, "SHT_STRTAB"); break;
			case 4:
				strcpy(secType, "SHT_RELA"); break;
			case 5:
				strcpy(secType, "SHT_HASH"); break;
			case 6:
				strcpy(secType, "SHT_DYNAMIC"); break;
			case 7:
				strcpy(secType, "SHT_NOTE"); break;
			case 8:
				strcpy(secType, "SHT_NOBITS"); break;
			case 9:
				strcpy(secType, "SHT_REL"); break;
			case 10:
				strcpy(secType, "SHT_SHLIB"); break;
			case 11:
				strcpy(secType, "SHT_DYNSYM"); break;
			case 12:
				strcpy(secType,"SHT_NUM"); break;
			case 0x60000000:
				strcpy(secType, "SHT_LOOS"); break;
			case 0x6fffffff:
				strcpy(secType, "SHT_HIOS"); break;
			case 0x70000000:
				strcpy(secType, "SHT_LOPROC"); break;
			case 0x7fffffff:
				strcpy(secType, "SHT_HIPROC"); break;
			case 0x80000000:
				strcpy(secType, "SHT_LOUSER"); break;
			case 0x8fffffff:
				strcpy(secType, "SHT_HIUSER"); break;
			default:
				strcpy(secType, "unknown"); break;
		}

		/*   Convert Flags to printable string    */
		memset(secFlags, '-', 3);
		if ( Sec_hdr->sh_flags & 1) secFlags[0]='w';
		if ( Sec_hdr->sh_flags & 2) secFlags[1]='a';
		if ( Sec_hdr->sh_flags & 4) secFlags[2]='x';

		/* Note entry point */
		if ( target.entry >= Sec_hdr->sh_addr && 
			 target.entry <  Sec_hdr->sh_addr + Sec_hdr->sh_size){
				sprintf(strNote, "%s Section %s contains entry point\n",
						strNote, secName);
		}

		/* Create Sections */
		/* compare in order of 'most common' to minimize calls */
		if (! strcmp(secName, ".text")){
			CreateSection(".text", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1100 | 0x01 );
			/* if .text exists, header is OK */
			retVal = 1;
		} else if (! strcmp(secName, ".data")) 	{
			CreateSection(".data", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1200 | 0x02 | 0x06);
		} else if (! strcmp(secName, ".rodata")) 	{
			CreateSection(".rodata", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1200 | 0x04);
		} else if (! strcmp(secName, ".bss")) 	{
			// handle bss section [?]
			CreateSection(".bss", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1200 | 0x06);
		} else if (! strcmp(secName, ".note")) 	{
			// make note of this info in strNote
			CreateSection(".note", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1700 );
		} else if (! strcmp(secName, ".comment")) {
			// make note of this info in strNote
			CreateSection(".comment", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1700 );
		} else if (! strcmp(secName, ".dynamic"))	{
			// handle dynamic link info
			CreateSection(".dynamic", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1800 );
		} else if (! strcmp(secName, ".dynsym")) 	{
			// handle dynamic link info
			CreateSection(".dynsym", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1800 );
		} else if (! strcmp(secName, ".dynstr")) 	{
			// handle dynamic link info
			CreateSection(".dynstr", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1800);
	 	} else if (! strcmp(secName, ".symtab")) 	{
			// handle symbol table
			CreateSection(".symtab", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1600 );
		} else if (! strcmp(secName, ".strtab")) 	{
			CreateSection(".strtab", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1600 );
		} else if (! strncmp(secName, ".rel", 4))	{
			// handle relocations for section
			CreateSection(secName, Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1800 );
		} else if (! strcmp(secName, ".got")) 	{
			// handle global offsets
			CreateSection(".got", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1800 );
		} else if (! strcmp(secName, ".data1")) 	{
			CreateSection(".data1", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1200 | 0x02 | 0x04);
		} else if (! strcmp(secName, ".rodata1")) {
			CreateSection(".rodata1", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1200 | 0x04);
		} else if (! strcmp(secName, ".debug")) 	{
			// handle debug symbols
			CreateSection(".debug", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1600 );
		} else if (! strcmp(secName, ".line")) 	{
			// handle line# information
			CreateSection(".line", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1600 );
		} else if (! strcmp(secName, ".interp")) 	{
			// make note of this info in strNote
			CreateSection(".interp", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1000 );
		} else if (! strcmp(secName, ".init")) 	{
			// create section for init code
			CreateSection(".init", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1000 );
		} else if (! strcmp(secName, ".fini")){
			// create section for cleanup code
			CreateSection(".fini", Sec_hdr->sh_addr, Sec_hdr->sh_size, 
						  Sec_hdr->sh_offset, 0x1000 );
		}
	
		sprintf(HeaderStr, "%s %s%s%s \t%s \tOffset %8X VA %08X Size %X\n",
				HeaderStr, secName, pad, secType, secFlags, Sec_hdr->sh_offset,
				Sec_hdr->sh_addr, Sec_hdr->sh_size);
	}
	free(strTable);
	return(retVal);
}



/*  --------------------------------------------------doProgramHeaders( bool )
	-- Parse ELF Program Header table and add to HeaderStr
	-- If Sections have not been created, create them
*/
int doProgramHeaders( bool create_sections ){
	int x, pos, jnk=0;
	char progType[16], progFlags[4];
	char noName[7] = "(null)";
	Dyn_hdr = NULL;
	Prog_hdr = malloc(sizeof(ELF_PROG));
	phdr_start.next = NULL;

	sprintf(HeaderStr, "%s\n\n__Program_Header_Table____________\n", HeaderStr);

    /*   Load each Program Header   */
	if (File_hdr->e_phnum == 0) return(0);
	progTable = calloc( 4, jnk + File_hdr->e_phnum);
	for (x = 0; x < File_hdr->e_phnum; x++) {
		Prog_hdr = progTable[x] = malloc(sizeof(ELF_PROG));
		pos = lseek(target.FD, File_hdr->e_phoff + ( File_hdr->e_phentsize * x),
					 0);
		read(target.FD, Prog_hdr, sizeof(ELF_PROG));
	}

	for (x = 0; x < File_hdr->e_phnum; x++) {
		Prog_hdr = progTable[x];

		/*    Convert type to string   */
		switch (Prog_hdr->p_type){
			case 0:
				strcpy(progType, "PT_NULL"); break;
			case 1:
				strcpy(progType, "PT_LOAD"); break;
			case 2:
				strcpy(progType, "PT_DYNAMIC"); 
				Dyn_hdr = Prog_hdr;
				break;
			case 3:
				strcpy(progType, "PT_INTERP"); break;
			case 4:
				strcpy(progType, "PT_NOTE"); break;
			case 5:
				strcpy(progType, "PT_SHLIB"); break;
			case 6:
				strcpy(progType, "PT_PHDR"); break;
			case 7:
				strcpy(progType, "PT_NUM "); break;
			case 0x60000000:
				strcpy(progType, "PT_LOOS"); break;
			case 0x6FFFFFFF:
				strcpy(progType, "PT_HIOS"); break;
			case 0x70000000:
				strcpy(progType, "PT_LOWPROC"); break;
			case 0x7FFFFFFF:
				strcpy(progType, "PT_HIPROC"); break;
			default:
				strcpy(progType, "unknown"); break;
		}

		/*   Convert Flags to printable string    */
		memset(progFlags, '-', 3);
		if ( Prog_hdr->p_flags & 1) progFlags[0]='x';
		if ( Prog_hdr->p_flags & 2) progFlags[1]='w';
		if ( Prog_hdr->p_flags & 4) progFlags[2]='r';

		/*  find entry point, create sections */
		if (create_sections){
			sprintf(strNote, "%sUsing Program Headers instead of Sections\n",
					strNote);
			if (target.entry >= Prog_hdr->p_vaddr &&
			    target.entry < Prog_hdr->p_vaddr + Prog_hdr->p_memsz) {
				//Create .text section
				CreateSection(".text", Prog_hdr->p_vaddr, Prog_hdr->p_memsz, 
						  Prog_hdr->p_offset, 0x1100 | 0x01 | 0x04);
				sprintf(strNote, "%s Segment %d contains entry point\n",
						strNote, x);
			} else if ( Prog_hdr->p_type == 1 && progFlags[1] == 'w') {
				CreateSection(".data", Prog_hdr->p_vaddr, Prog_hdr->p_memsz, 
						  Prog_hdr->p_offset, 0x1200 | 0x02 | 0x04);
			} else if ( Prog_hdr->p_type == 1 && progFlags[2] == 'r') {
				CreateSection(".rodata", Prog_hdr->p_vaddr, Prog_hdr->p_memsz, 
						  Prog_hdr->p_offset, 0x1200 | 0x04);
			}
		}
		/* add to linked list for later use */
		AddPhdr(Prog_hdr->p_vaddr, Prog_hdr->p_offset, Prog_hdr->p_filesz);
		sprintf( HeaderStr, "%s %d: \t%s \t%s Offset %8X \tVA %08X Size %X\n",
				 HeaderStr, x, progType, progFlags, Prog_hdr->p_offset,
				 Prog_hdr->p_vaddr, Prog_hdr->p_filesz);	
		pos = lseek(target.FD, jnk + File_hdr->e_phentsize, 1);
	}

	/* do dynamic header last */
	if (Dyn_hdr){ 
			doDynamic(Dyn_hdr->p_offset, Dyn_hdr->p_filesz);
	}

	CleanPhdr();
	return(0);
}


/*  -------------------------------------------------------------------main()
*/
int main()
{
	int x, *secPtr;
	int jnk=0;
	char machine[16], elfType[12], strMagic[4] = {0x7F, 'E', 'L', 'F'};
	HeaderStr    = malloc(8192);
	strNote      = malloc(1024);
	File_hdr 	 = malloc(sizeof(ELF_HDR));
	sprintf( strNote, "\n");

	/*  ______Load the ELF File Header_______ */
	lseek(target.FD, 0, 0); 
	read(target.FD, File_hdr, sizeof(ELF_HDR));
	printf("Loading ELF %s\n", target.name);
	/* Check Magic Number */
	if (strncmp(File_hdr->e_ident, strMagic, 4) ) 
		sprintf(strNote,"%sNo valid ELF magic number in header!\n", strNote);

	/* Target Format is Verified */
	strcpy(target.format, "ELF");
	target.entry = File_hdr->e_entry;
	/* get machine type/version/flags into string */
	/* yeah, ugly and primitive; get over it ;) */
	switch (File_hdr->e_machine){
		case 0:
			strcpy(machine, "EM_NONE"); break;	
		case 1:
			strcpy(machine, "EM_M32"); break;	
		case 2:
			strcpy(machine, "EM_SPARC"); break;	
		case 3:
			strcpy(machine, "EM_386"); break;	
		case 4:
			strcpy(machine, "EM_68K"); break;	
		case 5:
			strcpy(machine, "EM_88K"); break;	
		case 6:
			strcpy(machine, "EM_486"); break;	
		case 7:
			strcpy(machine, "EM_860"); break;	
		case 8:
			strcpy(machine, "EM_MIPS"); break;	
		case 9:
			strcpy(machine, "EM_S370"); break;	
		case 10:
			strcpy(machine, "EM_MIPS_RS4_BE"); break;	
		case 11:
			strcpy(machine, "EM_RS6000"); break;	
		case 15:
			strcpy(machine, "EM_PARISC"); break;	
		case 16:
			strcpy(machine, "EM_nCUBE"); break;	
		case 17:
			strcpy(machine, "EM_VPP500"); break;	
		case 18:
			strcpy(machine, "EM_SPARC32PLUS"); break;	
		case 19:
			strcpy(machine, "EM_960"); break;	
		case 20:
			strcpy(machine, "EM_PPC"); break;	
		case 36:
			strcpy(machine, "EM_V800"); break;	
		case 37:
			strcpy(machine, "EM_FR20"); break;	
		case 38:
			strcpy(machine, "EM_RH32"); break;	
		case 39:
			strcpy(machine, "EM_MMA"); break;	
		case 40:
			strcpy(machine, "EM_ARM"); break;	
		case 41:
			strcpy(machine, "EM_FAKE_ALPHA"); break;	
		case 42:
			strcpy(machine, "EM_SH"); break;	
		case 43:
			strcpy(machine, "EM_SPARCV9"); break;	
		case 44:
			strcpy(machine, "EM_TRICORE"); break;	
		case 45:
			strcpy(machine, "EM_ARC"); break;	
		case 46:
			strcpy(machine, "EM_H8_300"); break;	
		case 47:
			strcpy(machine, "EM_H8_300H"); break;	
		case 48:
			strcpy(machine, "EM_H8S"); break;	
		case 49:
			strcpy(machine, "EM_H8_500"); break;	
		case 50:
			strcpy(machine, "EM_IA_64"); break;	
		case 51:
			strcpy(machine, "EM_MIPS_X"); break;	
		case 52:
			strcpy(machine, "EM_COLDFIRE"); break;	
		case 53:
			strcpy(machine, "EM_68HC12"); break;	
		case 54:
			strcpy(machine, "EM_NUM"); break;	
		case 0x9026:
			strcpy(machine, "EM_ALPHA"); break;	
		default:
			strcpy(machine, "unknown");  break;	
	}

	switch (File_hdr->e_type){
		case 0:
			strcpy(elfType, "ET_NONE"); break;	
		case 1:
			strcpy(elfType, "ET_REL"); break;	
		case 2:
			strcpy(elfType, "ET_EXEC"); break;	
		case 3:
			strcpy(elfType, "ET_DYN"); break;	
		case 4:
			strcpy(elfType, "ET_CORE"); break;	
		case 5:
			strcpy(elfType, "ET_NUM"); break;	
		case 0xFF00:
			strcpy(elfType, "ET_LOPROC"); break;	
		case 0xFFFF:
			strcpy(elfType, "ET_HIPROC"); break;	
		default:
			strcpy(elfType, "unknown"); break;	
	}


	/*   Prepare the File Header 'Comment'  */
	sprintf(HeaderStr,"Target: %s\tFile Format: ELF\tType: %s\tMachine: %s\n",
						target.name, elfType, machine);
sprintf(HeaderStr,"%sEntry: %08X\tSection Table: %08X\tProgram Header: %08X\n", 
				HeaderStr, target.entry, File_hdr->e_shoff, File_hdr->e_phoff);

	/* create section for header */
	CreateSection( "header", 0, jnk + File_hdr->e_ehsize, 0, 0x1000); 

	if ( doSectionTable() ) doProgramHeaders( false );
	else doProgramHeaders( true );

	sprintf(HeaderStr, "%s\n\n__Notes_________________________%s\n",
			HeaderStr, strNote);
	// if ( !(disasm_env.flags & 0x1000) > 0) printf("%s", HeaderStr);
	CreateHeader(HeaderStr);

	/* ___________ Cleanup____________ */
	if (strNote) free(strNote);
	if (HeaderStr) free(HeaderStr);
	for (x = 0; x < File_hdr->e_shnum; x++) {
		secPtr = secTable[x];		// Seer does not handle casting well
		if (secPtr) free(secPtr);
	}
	for (x = 0; x < File_hdr->e_phnum; x++) {
		secPtr = progTable[x];	
		if (secPtr) free(secPtr);
	}
	if (secTable) free(secTable);
	if (progTable) free(progTable);
	if (File_hdr) free(File_hdr);
	return(0);
}
