⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 elf.c

📁 嵌入式linux(arm9)的平台下
💻 C
字号:
/*********************************************************************
 *
 * Copyright:
 *	MOTOROLA, INC. All Rights Reserved.
 *  You are hereby granted a copyright license to use, modify, and
 *  distribute the SOFTWARE so long as this entire notice is
 *  retained without alteration in any modified and/or redistributed
 *  versions, and that such modified versions are clearly identified
 *  as such. No licenses are granted by implication, estoppel or
 *  otherwise under any patents or trademarks of Motorola, Inc. This
 *  software is provided on an "AS IS" basis and without warranty.
 *
 *  To the maximum extent permitted by applicable law, MOTOROLA
 *  DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING
 *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
 *  PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE
 *  SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY
 *  ACCOMPANYING WRITTEN MATERIALS.
 *
 *  To the maximum extent permitted by applicable law, IN NO EVENT
 *  SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING
 *  WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
 *  INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
 *  LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
 *
 *  Motorola assumes no responsibility for the maintenance and support
 *  of this software
 ********************************************************************/

/*
 * File:		elf.c
 * Purpose:		Data definitions and routines for downloading ELF files.
 *
 * Notes:
 *
 *
 * Modifications:
 *				06-17-99 EJD Use Section Headers rather than Program Headers
 *
 */

/*#include "dbug.h"
#include "libdbug.h"*/
#include "elf.h"
#include "example.h"
#include "util.h"

DataFunctions fileAccessFunctions;
/********************************************************************/
#define MAX_FILENAME	13

#define ET_EXEC			2
#define EM_MIPS			8
#define EV_CURRENT		1

#define SHT_NULL		0
#define SHT_PROGBITS	1
#define SHT_SYMTAB		2
#define SHT_STRTAB		3
#define SHT_RELA		4
#define SHT_NOBITS		8

#define EI_IDENT_PAD_SIZE 9

#define ELF_MAX_HDR		30

// #define DEBUG_MSG 		1
typedef uint32	Elf32_Addr;
typedef uint32	Elf32_Word;
typedef uint16	Elf32_Half;
typedef uint32	Elf32_Off;
typedef int32	Elf32_Sword;

typedef struct
{
	unsigned char	EI_MAG[4];
	uint8			EI_CLASS;
	uint8			EI_DATA;
	uint8			EI_VERSION;
	unsigned char	EI_PAD[EI_IDENT_PAD_SIZE];
} Elf32_Ident;

typedef struct
{
	Elf32_Ident		e_ident;
	Elf32_Half		e_type;
	Elf32_Half		e_machine;
	Elf32_Word		e_version;
	Elf32_Addr		e_entry;
	Elf32_Off		e_phoff;
	Elf32_Off		e_shoff;
	Elf32_Word		e_flags;
	Elf32_Half		e_ehsize;
	Elf32_Half		e_phentsize;
	Elf32_Half		e_phnum;
	Elf32_Half		e_shentsize;
	Elf32_Half		e_shnum;
	Elf32_Half		e_shstrndx;
} Elf32_Ehdr;

typedef struct
{
	Elf32_Word		p_type;
	Elf32_Off		p_offset;
	Elf32_Addr		p_vaddr;
	Elf32_Addr		p_paddr;
	Elf32_Word		p_filesz;
	Elf32_Word		p_memsz;
	Elf32_Word		p_flags;
	Elf32_Word		p_align;
} Elf32_Phdr;

typedef struct
{
	Elf32_Word		sh_name;
	Elf32_Word		sh_type;
	Elf32_Word		sh_flags;
	Elf32_Addr		sh_addr;
	Elf32_Off		sh_offset;
	Elf32_Word		sh_size;
	Elf32_Word		sh_link;
	Elf32_Word		sh_info;
	Elf32_Word		sh_addralign;
	Elf32_Word		sh_entsize;
} Elf32_Shdr;


typedef struct
{
	Elf32_Addr		r_offset;
	Elf32_Word		r_info;
	Elf32_Sword		r_addend;
} Elf32_Rel;

typedef struct
{
	Elf32_Word		st_name;
	Elf32_Addr		st_value;
	Elf32_Word		st_size;
	unsigned char	st_info;
	unsigned char	st_other;
	Elf32_Half		st_shndx;
} Elf32_Sym;


/********************************************************************/
static volatile int elfBytesRead;
static int symndx, strndx;
static Elf32_Ehdr elfhdr;
static Elf32_Shdr scnhdr[ELF_MAX_HDR];
static uint32 scn_foffset;
static char elfFileName[MAX_FILENAME];
static volatile int progress;
static dots;
static uint32 startadd;
/********************************************************************/

static int
elfRead (void *buffer, int bytes)
{
#ifdef DEBUG_MSG
	if(bytes > 1){
		printf("\n elfRead: buffer address is %x", buffer);
		printf("\tsize is %d ", bytes);
	}
#endif

	int bytesRead = fileAccessFunctions.read(buffer, bytes);

#ifdef DEBUG_MSG
	if(bytes > 1){
		printf("\tbytesRead is %d ", bytesRead);
	}
#endif

	elfBytesRead += bytesRead;

	updateProgress(bytesRead);

	return bytesRead;
}

static int
elfRead2 (void *buffer, int bytes, uint32 offset)
{
#ifdef DEBUG_MSG
		printf("\n elfRead2: buffer address is %x", buffer);
		printf(" size is %x ", bytes);
		printf(" Flash offset is %x", offset);
#endif

	memCopy((void *)(startadd + offset), buffer, bytes); //src, dest, bytes

	elfBytesRead += bytes;

	updateProgress(bytes);

	return bytes;
}

static int
elfOpen(const char* fileName)
{
	elfBytesRead = 0;
	return fileAccessFunctions.open(fileName);
}

void elfClose()
{
	fileAccessFunctions.close();
}

/********************************************************************/
static int
elfReadSectionData()
{
	char ch;
	char* address;
	int i;
	// get the start address
	startadd = stringToInt(elfFileName);

	for(i = 0; i < elfhdr.e_shnum; ++i)
	{
		while(elfBytesRead < scnhdr[i].sh_offset)		//seek to beginning of section
			elfRead(&ch, 1);

	   	switch (scnhdr[i].sh_type)
		{
			case SHT_NULL:
				break;
			case SHT_PROGBITS:
				address = (char *)scnhdr[i].sh_addr;
				if (address && scnhdr[i].sh_size)
					if(!elfRead2(address, scnhdr[i].sh_size, scnhdr[i].sh_offset))
						return 0;
				break;
			case SHT_SYMTAB:
				break;
			case SHT_STRTAB:
				break;
			case SHT_RELA:
				break;
			case SHT_NOBITS:
				address = (char *)scnhdr[i].sh_addr;
				if(address && scnhdr[i].sh_size)
					memFill(address, scnhdr[i].sh_size, 0x00);	//zero memory
				break;
			default:
				/* unknown section type */
				break;
		}
	}
}

void displaySectionHeader(Elf32_Shdr* header)
{
	printf(" sh_name:    %08X\n",header->sh_name);
	printf(" sh_type:    %08X\n",header->sh_type);
	printf(" sh_flags:   %08X\n",header->sh_flags);
	printf(" sh_addr:    %08X\n",header->sh_addr);
	printf(" sh_offset:  %08X\n",header->sh_offset);
	printf(" sh_size:    %08X\n",header->sh_size);
	printf(" sh_link:    %08X\n",header->sh_link);
	printf(" sh_info:    %08X\n",header->sh_info);
	printf(" sh_addalgn: %08X\n",header->sh_addralign);
	printf(" sh_entsize: %08X\n",header->sh_entsize);
}

/********************************************************************/
static int
elfReadSectionHeader()
{
	int i;
	char c;

	scn_foffset = (uint32)~0;
	symndx = -1;
	strndx = -1;

	if (!elfhdr.e_shnum)
		return 0;

	for(i = elfBytesRead; i < elfhdr.e_shoff; ++i)	//seek to header
		if(!elfRead(&c, 1))
			return 0;

	for (i = 0; i < elfhdr.e_shnum; ++i)
	{
		elfRead(&scnhdr[i], sizeof(Elf32_Shdr));
//		displaySectionHeader(&scnhdr[i]);
		switch (scnhdr[i].sh_type)
		{
			case SHT_NULL:
				break;
			case SHT_PROGBITS:
				if (scnhdr[i].sh_offset < scn_foffset)
					scn_foffset = scnhdr[i].sh_offset;
				break;
			case SHT_SYMTAB:
				if (symndx < 0)
					 symndx = i;
				if (scnhdr[i].sh_offset < scn_foffset)
					scn_foffset = scnhdr[i].sh_offset;
				break;
			case SHT_STRTAB:
				if ((strndx < 0) && (i != elfhdr.	e_shstrndx))
					strndx = i;
				if (scnhdr[i].sh_offset < scn_foffset)
					scn_foffset = scnhdr[i].sh_offset;
				break;
			case SHT_RELA:
				break;
			case SHT_NOBITS:
				break;
			default:
				/* unknown section type */
				break;
		}
	}

	/*
	 * Check for symbol table existence and for string
	 * table existence AFTER symbol table.
	 */
	if ((symndx < 0) || (strndx < 0))
	{
		return FALSE;
	}

	if (symndx < strndx)
	{
		/*
		 * The symbol table entries MUST exist before the string
		 * entries, or else this information comes too late.
		 * (Unless you want to do a third pass!??  Not!
		 */
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}


void displayProgramHeader(Elf32_Phdr* header)
{
	printf(" p_type:    %08X\n",header->p_type);
	printf(" p_offset:  %08X\n",header->p_offset);
	printf(" p_vaddr:   %08X\n",header->p_vaddr);
	printf(" p_paddr:   %08X\n",header->p_paddr);
	printf(" p_filesz:  %08X\n",header->p_filesz);
	printf(" p_memsz:   %08X\n",header->p_memsz);
	printf(" p_flags:   %08X\n",header->p_flags);
	printf(" p_align:   %08X\n",header->p_align);
}
/********************************************************************/
static void
elfReadProgramHeader()
{
	Elf32_Phdr pgmhdr;
	int i;
	char c;

	if (elfhdr.e_phnum)
	{
		/*
		 * Seek to Program Headers.
		 */

		for (i = elfBytesRead; i < elfhdr.e_phoff; i++)
			elfRead(&c, 1);

		for (i = 0; i < elfhdr.e_phnum; ++i)
		{
			elfRead((char *)&pgmhdr, sizeof(Elf32_Phdr));
//			displayProgramHeader(&pgmhdr);
		}
	}
}


void displayHeader()
{
	printf("\ne_type:    %08X\n",elfhdr.e_type);
	printf("e_machine: %08X\n",elfhdr.e_machine);
	printf("e_version: %08X\n",elfhdr.e_version);
	printf("e_entry:   %08X\n",elfhdr.e_entry);
	printf("e_phoff:   %08X\n",elfhdr.e_phoff);
	printf("e_shoff:   %08X\n",elfhdr.e_shoff);
	printf("e_flags:   %08X\n",elfhdr.e_flags);
	printf("e_ehsize:  %04X\n",elfhdr.e_ehsize);
	printf("e_phentsize:  %04X\n",elfhdr.e_phentsize);
	printf("e_phnum:  %04X\n",elfhdr.e_phnum);
	printf("e_shentsize:  %04X\n",elfhdr.e_shentsize);
	printf("e_shnum:  %04X\n",elfhdr.e_shnum);
	printf("e_shstrndx:  %04X\n",elfhdr.e_shstrndx);
}

int elfValidateHeader()
{
	if(elfhdr.e_type != ET_EXEC)
	{
		printf("\nUnsupported ELF type (non executable)\n");
		return 0;
	}

	if(elfhdr.e_machine != EM_MIPS)
	{
		printf("\nUnsuported Machine type (non MIPS)\n");
		return 0;
	}

	if(elfhdr.e_version != EV_CURRENT)
	{
		printf("\nInvalid ELF version\n");
		return 0;
	}

	if (elfhdr.e_ehsize != sizeof(Elf32_Ehdr))
	{
		printf("\nInvalid File Header Size\n");
		return 0;
	}

	if (elfhdr.e_phentsize != sizeof(Elf32_Phdr))
	{
		printf("\nInvalid Program Header Size\n");
		return 0;
	}

	if (elfhdr.e_shentsize != sizeof(Elf32_Shdr))
	{
		printf("\nInvalid Section Header Size\n");
		return 0;
	}

	if (elfhdr.e_shnum > ELF_MAX_HDR)
	{
		printf("\bError: Too many Section Headers!!!\n");
		return 0;
	}

//	displayHeader();
}

int isElf()
{
	return	elfhdr.e_ident.EI_MAG[0] == 0x7f &&
			elfhdr.e_ident.EI_MAG[1] == 'E'  &&
			elfhdr.e_ident.EI_MAG[2] == 'L'  &&
			elfhdr.e_ident.EI_MAG[3] == 'F';
}

int elfReadHeader()
{
	elfBytesRead = 0;
	return elfRead(&elfhdr, sizeof(Elf32_Ehdr));
}

void* readElf()
{
	if(elfValidateHeader())
	{
		if (elfhdr.e_phoff < elfhdr.e_shoff)
		{
			elfReadProgramHeader();
			if(!elfReadSectionHeader())
				return (void*) 0;
		}
		else
		{
			if(!elfReadSectionHeader())
				return (void*) 0;
			elfReadProgramHeader();
		}

		if (elfBytesRead > scn_foffset)
		{
			elfClose();
			elfOpen(elfFileName);			//start at beginning of file
		}
		if(elfReadSectionData(&elfhdr))
			return (void*) elfhdr.e_entry;
	}

	return 0;
}
/********************************************************************/

void* elfLoadImage(DataFunctions dataFunctions, const char* fileName)
{
	void* entryPoint = (void*) 0;
	fileAccessFunctions = dataFunctions;

	stringCopy(fileName, elfFileName);
	showProgress(0);	//dont show status dots

	if(elfOpen(elfFileName) && elfReadHeader() && isElf())
	{
		showProgress(1);
		printf("\n---------------------------------------------\n");
		printf("Loading Image: %12s    (Format = ELF)\n", fileName);

		if(entryPoint = readElf())
			printf("\nImage Loaded Successfully.\n");
		else
			printf("\nError Loading Image File.\n");

		printf("---------------------------------------------\n");
	}

	elfClose();
	return entryPoint;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -