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

📄 elf.c

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 C
字号:
/*
 * File:		elf.c
 * Purpose:		Data definitions and routines for downloading ELF files.
 *
 * Notes:
 *
 */

#include "src/include/dbug.h"
#include "src/uif/uif.h"

/********************************************************************/

typedef uint32	Elf32_Addr;
typedef uint32	Elf32_Word;
typedef uint16	Elf32_Half;
typedef uint32	Elf32_Off;
typedef int32	Elf32_Sword;

#define EI_NIDENT 16

#define ELF_IDENT			(0x7F454C46)	/* _ELF */
#define ELF_ETYPE_RELO		(1)
#define ELF_ETYPE_EXEC		(2)
#define ELF_EMACHINE_68K	(6)
#define ELF_EMACHINE_PPC	(20)
#define ELF_EVERSION		(1)

typedef struct
{
	unsigned char	e_ident[EI_NIDENT];
	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;

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

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;

#define STB_LOCAL	(0)
#define STB_GLOBAL	(1)
#define STB_WEAK	(2)

#define STT_NOTYPE	(0)
#define STT_OBJECT	(1)
#define STT_FUNC	(2)
#define STT_SECTION	(3)
#define STT_FILE	(4)

#define SHN_UNDEF	(0)
#define SHN_ABS		(0xfff1)
#define SHN_COMMON	(0xfff2)

/********************************************************************/

#ifndef ELF_MAX_HDR
#define ELF_MAX_HDR (20)
#endif

static volatile int elf_bytes_read;
static int symndx, strndx;
static Elf32_Ehdr elfhdr;
static Elf32_Shdr scnhdr[ELF_MAX_HDR];
static uint32 scn_foffset;

/********************************************************************/
static void
elf_read (char *buf, int size)
{
	int i;

	for (i = 0; i < size; i++)
	{
		buf[i] = (char)board_dlio_getchar();
		++elf_bytes_read;
	}
}

/********************************************************************/
static void
elf_read_scndata (Elf32_Ehdr *elfhdr)
{
	Elf32_Shdr *scn;
	Elf32_Sym syment;
	char c, *p;
	int i, j, offset, symloaded = FALSE;
	uint32 foffset;
	char buffer[100];

	while (TRUE)
	{
		/*
		 * Locate next sequential section using sh_offset
		 */
		foffset = (uint32)~0;
		scn = NULL;
		for (i = 0; i < elfhdr->e_shnum; ++i)
		{
			if (scnhdr[i].sh_offset != 0)
			{
				if (scnhdr[i].sh_offset < foffset)
				{
					scn = &scnhdr[i];
					foffset = scn->sh_offset;
#ifdef HOST_DEBUG
printf("ScnData: %d\n", i);
#endif
				}
			}
		}

		if ((foffset == (uint32)~0) || (scn == NULL))
		{
			do 
			{ 
				elf_read(&c, 1); 
			} while (c != (char)-1);

			break; /* done! no more sections */
		}

		/*
 		 * Seek to Section data.
 		 */
 		for (i = elf_bytes_read; i < foffset; i++)
 			elf_read(&c, 1);

	   	switch (scn->sh_type)
		{
			case SHT_NULL:
				break;
			case SHT_PROGBITS:
				p = (char *)scn->sh_addr;
				if (board_dlio_vda((ADDRESS)p) && scn->sh_size)
				{
					for (j = 0; j < scn->sh_size; ++j)
					{
						elf_read((char *)&c, 1);
#ifndef HOST_DEBUG
						*p++ = c;
#else
						;
#endif
					}
				}
#if 0
				else
				{
					printf("\bError: Invalid download address: %#08X\n", p);
				}
#endif
				break;
			case SHT_SYMTAB:
				while (elf_bytes_read < (scn->sh_offset + scn->sh_size))
				{
					elf_read((char *)&syment, sizeof(Elf32_Sym));
#ifdef HOST_DEBUG
        printf(" st_name:  %08X\n",syment.st_name);
        printf(" st_value: %08X\n",syment.st_value);
        printf(" st_size:  %08X\n",syment.st_size);
        printf(" st_info:  %08X\n",syment.st_info);
        printf(" st_other: %08X\n",syment.st_other);
        printf(" st_shndx: %08X\n",syment.st_shndx);
#endif
					if (((syment.st_info >> 4) == STB_GLOBAL) &&
						(((syment.st_info & 15) == STT_OBJECT) ||
						((syment.st_info & 15) == STT_NOTYPE) ||
						((syment.st_info & 15) == STT_FUNC)))
					{
						symtab_add_incomplete(syment.st_name,syment.st_value);
					}
				}
				symloaded = TRUE;
				break;
			case SHT_STRTAB:
			    if (symloaded)
				{
				while (elf_bytes_read < (scn->sh_offset + scn->sh_size))
				{
					p = &buffer[0];
					i = 0;
					offset = elf_bytes_read - scn->sh_offset;

					/* All strings in section are NULL terminated */
					c = 'X';	/* non-NULL */
					while (c != '\0')
					{
						elf_read(&c, 1);
						if (++i < 100)
						{
							*p++ = c;
						}
						else
						{
							*p = '\0';
						}
					}
					symtab_add_complete(buffer,offset);
#ifdef HOST_DEBUG
					printf("String %08X %s\n",offset,buffer);
#endif
				}
				}
				break;
			case SHT_RELA:
				break;
			case SHT_NOBITS:
#if 1
				p = (char *)scn->sh_addr;
				if (board_dlio_vda((ADDRESS)p))
				{
					for (j = 0; j < scn->sh_size; ++j)
#ifndef HOST_DEBUG
						*p++ = 0;
#else
						;
#endif
				}
#if 0
				else
				{
					printf("\bError: Invalid download address: %#08X\n", p);
				}
#endif
#endif
				break;
			default:
				/* unknown section type */
				break;
		}
		scn->sh_offset = 0;	/* marked section as used */
	}
}

/********************************************************************/
static int
elf_read_scnhdr (Elf32_Ehdr *elfhdr)
{
	int i;
	char c;

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

	if (elfhdr->e_shnum)
	{
		/*
 		 * Seek to Section Headers.
 		 */
 		for (i = elf_bytes_read; i < elfhdr->e_shoff; i++)
 			elf_read(&c, 1);
	}
	else
		return FALSE;

#ifdef HOST_DEBUG
	printf("elf_bytes_read: %08X %d\n", elf_bytes_read, elf_bytes_read);
#endif

	printf("\bSection Headers:\n");
	for (i = 0; i < elfhdr->e_shnum; ++i)
	{
		elf_read((char *)&scnhdr[i], sizeof(Elf32_Shdr));

		printf(" Section %d (Type: %08X, Addr: %08X, Size: %08X)\n",
			i, scnhdr[i].sh_type, scnhdr[i].sh_addr, scnhdr[i].sh_size);

#ifdef HOST_DEBUG
        printf(" sh_name:    %08X\n",scnhdr[i].sh_name);
        printf(" sh_type:    %08X\n",scnhdr[i].sh_type);
        printf(" sh_flags:   %08X\n",scnhdr[i].sh_flags);
        printf(" sh_addr:    %08X\n",scnhdr[i].sh_addr);
        printf(" sh_offset:  %08X\n",scnhdr[i].sh_offset);
        printf(" sh_size:    %08X\n",scnhdr[i].sh_size);
        printf(" sh_link:    %08X\n",scnhdr[i].sh_link);
        printf(" sh_info:    %08X\n",scnhdr[i].sh_info);
        printf(" sh_addalgn: %08X\n",scnhdr[i].sh_addralign);
        printf(" sh_entsize: %08X\n",scnhdr[i].sh_entsize);
#endif

		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:
			default:
				/* unknown section type */
				break;
		}
	}

#ifdef HOST_DEBUG
	printf("elf_bytes_read: %08X %d\n", elf_bytes_read, elf_bytes_read);
#endif

	/*
	 * 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;
	}
}

/********************************************************************/
static void
elf_read_pgmhdr(Elf32_Ehdr *elfhdr)
{
	Elf32_Phdr pgmhdr;
	int i;
	char c;

	if (elfhdr->e_phnum)
	{
		/*
		 * Seek to Program Headers.
		 */
		for (i = elf_bytes_read; i < elfhdr->e_phoff; i++)
			elf_read(&c, 1);

#ifdef HOST_DEBUG
	printf("elf_bytes_read: %08X %d\n", elf_bytes_read, elf_bytes_read);
#endif

 		printf("\bProgram Headers:\n");
		for (i = 0; i < elfhdr->e_phnum; ++i)
		{
			elf_read((char *)&pgmhdr, sizeof(Elf32_Phdr));
			printf(" Segment #%d (Vaddr: %08X, Paddr: %08X, Size: %08X)\n",
				i, pgmhdr.p_vaddr, pgmhdr.p_paddr, pgmhdr.p_memsz);

#ifdef HOST_DEBUG
        printf(" p_type:    %08X\n",pgmhdr.p_type);
        printf(" p_offset:  %08X\n",pgmhdr.p_offset);
        printf(" p_vaddr:   %08X\n",pgmhdr.p_vaddr);
        printf(" p_paddr:   %08X\n",pgmhdr.p_paddr);
        printf(" p_filesz:  %08X\n",pgmhdr.p_filesz);
        printf(" p_memsz:   %08X\n",pgmhdr.p_memsz);
        printf(" p_flags:   %08X\n",pgmhdr.p_flags);
        printf(" p_align:   %08X\n",pgmhdr.p_align);
#endif
		}
	}
}

/********************************************************************/
static int
elf_read_filehdr (Elf32_Ehdr *elfhdr)
{
	/*
	 * Copy ELF file header
	 */
	elf_read((char *)elfhdr, sizeof(Elf32_Ehdr));

#ifdef HOST_DEBUG
	{
		int i;
	    for (i = 0; i < EI_NIDENT; ++i)
	    {
	        printf("%02X ",elfhdr->e_ident[i]);
	    }
	    printf("\n");

	    printf("e_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);
	}
#endif

	/*
	 * Check for basic problems
	 */
	if (elfhdr->e_ident[0] != 0x7F)
		goto error;
	if (elfhdr->e_ident[1] != 'E')
		goto error;
	if (elfhdr->e_ident[2] != 'L')
		goto error;
	if (elfhdr->e_ident[3] != 'F')
		goto error;
	if (!(elfhdr->e_type & ELF_ETYPE_EXEC))
		goto error;

#if 0
#if		(defined(CPU_ARCH_CF))
	if (elfhdr->e_machine != ELF_EMACHINE_68K)
		goto error;
#elif	(defined(CPU_ARCH_PPC))
	if (elfhdr->e_machine != ELF_EMACHINE_PPC)
		goto error;
#else
#error "Unsupported machine"
#endif
#endif

	if (elfhdr->e_ehsize != sizeof(Elf32_Ehdr))
		goto error;

	if (elfhdr->e_phentsize != sizeof(Elf32_Phdr))
		goto error;

	if (elfhdr->e_shentsize != sizeof(Elf32_Shdr))
		goto error;

	if (elfhdr->e_shnum > ELF_MAX_HDR)
	{
		printf("\bError: Too many Section Headers!!!\n");
		goto error;
	}

	/*noerror:*/
		cpu_pc_modify(elfhdr->e_entry);
		return TRUE;

	error:
		printf("\bError: Not a recognized ELF file!\n");
		return FALSE;
}

/********************************************************************/
int
download_elf (int passno)
{
	elf_bytes_read = 0;

	/*
	 * Pass # 1:  Obtain headers.
	 */
	if (passno == 1)
	{
		/*
		 * Step 1) Obtain the ELF file header.
		 */
		if (elf_read_filehdr(&elfhdr) != TRUE)
			return -1;
 
		/*
		 * Step 2) Obtain the Program and Section Headers.
		 */
		if (elfhdr.e_phoff < elfhdr.e_shoff)
		{
			elf_read_pgmhdr(&elfhdr);
			elf_read_scnhdr(&elfhdr);
		}
		else
		{
			elf_read_scnhdr(&elfhdr);
			elf_read_pgmhdr(&elfhdr);
		}

		/*
		 * The section data follows all headers in the ELF file
		 */
		if (elf_bytes_read <= scn_foffset)
		{
			elf_read_scndata(&elfhdr);
			return FALSE;
		}

		return TRUE;
	}
	else
	{
		/*
		 * Pass #2 - Get data
		 */
		elf_read_scndata(&elfhdr);
		return TRUE;
	}
}

#ifdef HOST_DEBUG
/********************************************************************/
int
main (int argc, char **argv)
{
    int passno;

    if (argc != 2)
    {
        printf("specify filename!\n");
        return -1;
    }

    for (passno = 1; passno <= 2; ++passno)
    {
        if ((fp = open(argv[1],O_RDONLY)) < 0)
        {
            printf("Error opening file: %s\n", argv[1]);
            return -1;
        }
        if (download_elf(passno) != TRUE)
        {
            close(fp);
            return;
        }
        close(fp);
    }
    return 0;
}

/********************************************************************/
#endif

⌨️ 快捷键说明

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