📄 elf.c.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 + -