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

📄 elf.c.svn-base

📁 RT-Thread是发展中的下一代微内核嵌入式实时操作系统
💻 SVN-BASE
字号:
/* * elf.c - ELF file format support */#include "elf.h"#include "arch.h"#include "lib.h"#include "mkservice.h"/* Architecture dependent routines */extern int relocate_rel (Elf32_Rel *, Elf32_Addr, char *);extern int relocate_rela (Elf32_Rela *, Elf32_Addr, char *);#ifdef DEBUG_BOOT_IMAGE#define elf_dbg(x,y...) kprintf(x, ##y)#else#define elf_dbg(x,y...)#endif#define SHF_VALID	(SHF_ALLOC | SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE)static int nr_img = 0;		/* Number of images */static rt_uint32 load_base = 0;	/* Current load address */static char *sect_addr[32];	/* Array of section address */static int load_executable (char *img, struct mk_service_entry *entry){	Elf32_Ehdr *ehdr;	Elf32_Phdr *phdr;	rt_uint32 phys_base;	int i;	ehdr = (Elf32_Ehdr *) img;	phdr = (Elf32_Phdr *) ((rt_uint32) ehdr + ehdr->e_phoff);	entry->phys = load_base;	phys_base = load_base;	elf_dbg ("phys addr=%x\n", phys_base);	for (i = 0; i < ehdr->e_phnum; i++, phdr++)	{		if (phdr->p_type != PT_LOAD) continue;		elf_dbg ("p_flags=%x\n", (int) phdr->p_flags);		elf_dbg ("p_align=%x\n", (int) phdr->p_align);		elf_dbg ("p_paddr=%x\n", (int) phdr->p_paddr);		if (phdr->p_flags & PF_X)		{			/* Text */			entry->text = phdr->p_vaddr;			entry->text_size = phdr->p_memsz;		}		else		{			/* Data & BSS */			entry->data = phdr->p_vaddr;			entry->data_size = phdr->p_filesz;			entry->bss_size = phdr->p_memsz - phdr->p_filesz;			load_base = phys_base + (entry->data - entry->text);		}		if (phdr->p_filesz > 0)		{			memcpy ( (char *) load_base, img + phdr->p_offset,			         phdr->p_filesz);			elf_dbg ("load: offset=%x size=%x\n",			         load_base, (int) phdr->p_filesz);		}		if (! (phdr->p_flags & PF_X) )		{			if (entry->bss_size > 0)			{				/* zero fill bss */				memset ( (char *) load_base + entry->data_size,				         0, entry->bss_size);			}			load_base += phdr->p_memsz;		}	}	load_base = PAGE_ALIGN (load_base);	entry->size = load_base - entry->phys;	entry->entry = ehdr->e_entry;	elf_dbg ("entry size=%x entry=%x\n", entry->size, entry->entry);	return 0;}static int relocate_section (char *img, Elf32_Shdr *shdr){	Elf32_Sym *sym_table, *sym;	Elf32_Rel *rel;	Elf32_Rela *rela;	Elf32_Addr sym_val;	char *target_sect;	int i, nr_reloc;	if (shdr->sh_entsize == 0)		return 0;	if ( (target_sect = sect_addr[shdr->sh_info]) == 0)		return -1;	if ( (sym_table = (Elf32_Sym *) sect_addr[shdr->sh_link]) == 0)		return -1;	nr_reloc = shdr->sh_size / shdr->sh_entsize;	rel = (Elf32_Rel *) (img + shdr->sh_offset);	rela = (Elf32_Rela *) (img + shdr->sh_offset);	for (i = 0; i < nr_reloc; i++)	{		if (shdr->sh_type == SHT_REL)		{			sym = &sym_table[ELF32_R_SYM (rel->r_info) ];			sym_val = (Elf32_Addr) sect_addr[sym->st_shndx] + sym->st_value;			if (relocate_rel (rel, sym_val, target_sect) != 0)				return -1;		}		else		{			sym = &sym_table[ELF32_R_SYM (rela->r_info) ];			sym_val = (Elf32_Addr) sect_addr[sym->st_shndx] + sym->st_value;			if (relocate_rela (rela, sym_val, target_sect) != 0)				return -1;		}		rel++;		rela++;	}	return 0;}static int load_relocatable (char *img, struct mk_service_entry *entry){	Elf32_Ehdr *ehdr;	Elf32_Shdr *shdr;	rt_uint32 sect_base, bss_base;	int i;	ehdr = (Elf32_Ehdr *) img;	shdr = (Elf32_Shdr *) ( (rt_uint32) ehdr + ehdr->e_shoff);	bss_base = 0;	entry->phys = load_base;	elf_dbg ("phys addr=%x\n", load_base);	/* Copy sections */	for (i = 0; i < ehdr->e_shnum; i++, shdr++)	{		sect_addr[i] = 0;		if (shdr->sh_type == SHT_PROGBITS)		{			elf_dbg ("sh_addr=%x\n", shdr->sh_addr);			elf_dbg ("sh_size=%x\n", shdr->sh_size);			elf_dbg ("sh_offset=%x\n", shdr->sh_offset);			elf_dbg ("sh_flags=%x\n", shdr->sh_flags);			switch (shdr->sh_flags & SHF_VALID)			{			case (SHF_ALLOC | SHF_EXECINSTR) :							/* Text */							entry->text = (rt_uint32) phys_to_virt (load_base);				break;			case (SHF_ALLOC | SHF_WRITE) :							/* Data */							if (entry->data == 0)								entry->data =								    (rt_uint32) phys_to_virt (load_base + shdr->sh_addr);				break;			case SHF_ALLOC:				/* rodata */				/* Note: rodata is treated as text. */				break;			default:				continue;			}			sect_base = load_base + shdr->sh_addr;			memcpy ( (char *) sect_base, img + shdr->sh_offset,			         shdr->sh_size);			elf_dbg ("load: offset=%x size=%x\n",			         sect_base, (int) shdr->sh_size);			sect_addr[i] = (char *) sect_base;		}		else if (shdr->sh_type == SHT_NOBITS)		{			/* BSS */			entry->bss_size = shdr->sh_size;			sect_base = load_base + shdr->sh_addr;			bss_base = sect_base;			/* Zero fill BSS */			memset ( (char *) sect_base, 0, shdr->sh_size);			sect_addr[i] = (char *) sect_base;		}		else if (shdr->sh_type == SHT_SYMTAB)		{			/* Symbol table */			sect_addr[i] = img + shdr->sh_offset;		}	}	entry->text_size = entry->data - entry->text;	entry->data_size = bss_base - entry->data;	load_base = bss_base + entry->bss_size;	load_base = PAGE_ALIGN (load_base);	elf_dbg ("entry load_base=%x entry->text=%x\n",	         load_base, entry->text);	entry->size = load_base - (rt_uint32) virt_to_phys (entry->text);	entry->entry = (rt_uint32) phys_to_virt (ehdr->e_entry + entry->phys);	elf_dbg ("entry size=%x entry=%x\n", entry->size, entry->entry);	/* Process relocation */	shdr = (Elf32_Shdr *) ( (rt_uint32) ehdr + ehdr->e_shoff);	for (i = 0; i < ehdr->e_shnum; i++, shdr++)	{		if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)		{			if (relocate_section (img, shdr) != 0)				return -1;		}	}	return 0;}/* * Load the program from specified ELF image data stored in memory. * The boot information is filled after loading the program. */int elf_load (char *elf, struct mk_service_entry* entry){	Elf32_Ehdr *ehdr;	Elf32_Phdr *phdr;	elf_dbg ("\nelf_load\n");	ehdr = (Elf32_Ehdr *) elf;	/*  Check ELF header */	if ((ehdr->e_ident[EI_MAG0] != ELFMAG0) ||		(ehdr->e_ident[EI_MAG1] != ELFMAG1) ||		(ehdr->e_ident[EI_MAG2] != ELFMAG2) ||		(ehdr->e_ident[EI_MAG3] != ELFMAG3) )		return -1;	phdr = (Elf32_Phdr *) ( (rt_uint32) ehdr + ehdr->e_ehsize);	if (nr_img == 0)	{		/*  Initialize the load address */		load_base = (rt_uint32) virt_to_phys (phdr->p_paddr);		if (load_base == 0) return -1;		elf_dbg ("kernel base=%x\n", load_base);	}	else	{		/* Other images => Boot tasks */		elf_dbg ("task base=%x\n", load_base);	}	switch (ehdr->e_type)	{	case ET_EXEC:		if (load_executable (elf, entry) != 0) return -1;		break;	case ET_REL:		if (load_relocatable (elf, entry) != 0) return -1;		break;	default:		elf_dbg ("Unsupported file type\n");		return -1;	}	nr_img++;	return 0;}

⌨️ 快捷键说明

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