#include <errno.h>
#include <elf.h>
#include <gpxe/uaccess.h>
#include <gpxe/segment.h>
#include <gpxe/image.h>
#include <gpxe/elf.h>
Go to the source code of this file.
Typedefs | |
| typedef Elf32_Ehdr | Elf_Ehdr |
| typedef Elf32_Phdr | Elf_Phdr |
| typedef Elf32_Off | Elf_Off |
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static int | elf_load_segment (struct image *image, Elf_Phdr *phdr, Elf_Ehdr *ehdr) |
| Load ELF segment into memory. | |
| int | elf_load (struct image *image) |
| Load ELF image into memory. | |
A "pure" ELF image is not a bootable image. There are various bootable formats based upon ELF (e.g. Multiboot), which share common ELF-related functionality.
Definition in file elf.c.
| typedef Elf32_Ehdr Elf_Ehdr |
| typedef Elf32_Phdr Elf_Phdr |
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
Load ELF segment into memory.
| image | ELF file | |
| phdr | ELF program header | |
| ehdr | ELF executable header |
| rc | Return status code |
Definition at line 50 of file elf.c.
References image::data, DBGC, dest, Elf32_Ehdr::e_entry, ENOEXEC, image::len, memcpy_user(), Elf32_Phdr::p_filesz, Elf32_Phdr::p_memsz, Elf32_Phdr::p_offset, Elf32_Phdr::p_paddr, Elf32_Phdr::p_type, Elf32_Phdr::p_vaddr, image::phys, phys_to_user(), prep_segment(), image::priv, PT_LOAD, and strerror().
Referenced by elf_load().
00051 { 00052 physaddr_t dest; 00053 userptr_t buffer; 00054 unsigned long e_offset; 00055 int rc; 00056 00057 /* Do nothing for non-PT_LOAD segments */ 00058 if ( phdr->p_type != PT_LOAD ) 00059 return 0; 00060 00061 /* Check segment lies within image */ 00062 if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) { 00063 DBGC ( image, "ELF %p segment outside image\n", image ); 00064 return -ENOEXEC; 00065 } 00066 00067 /* Find start address: use physical address for preference, 00068 * fall back to virtual address if no physical address 00069 * supplied. 00070 */ 00071 dest = phdr->p_paddr; 00072 if ( ! dest ) 00073 dest = phdr->p_vaddr; 00074 if ( ! dest ) { 00075 DBGC ( image, "ELF %p segment loads to physical address 0\n", 00076 image ); 00077 return -ENOEXEC; 00078 } 00079 buffer = phys_to_user ( dest ); 00080 00081 DBGC ( image, "ELF %p loading segment [%x,%x) to [%x,%x,%x)\n", image, 00082 phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ), 00083 phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ), 00084 ( phdr->p_paddr + phdr->p_memsz ) ); 00085 00086 /* Verify and prepare segment */ 00087 if ( ( rc = prep_segment ( buffer, phdr->p_filesz, 00088 phdr->p_memsz ) ) != 0 ) { 00089 DBGC ( image, "ELF %p could not prepare segment: %s\n", 00090 image, strerror ( rc ) ); 00091 return rc; 00092 } 00093 00094 /* Copy image to segment */ 00095 memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz ); 00096 00097 /* Set execution address, if it lies within this segment */ 00098 if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) { 00099 image->priv.phys = ehdr->e_entry; 00100 DBGC ( image, "ELF %p found physical entry point at %lx\n", 00101 image, image->priv.phys ); 00102 } else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) ) 00103 < phdr->p_filesz ) { 00104 if ( ! image->priv.phys ) { 00105 image->priv.phys = ( dest + e_offset ); 00106 DBGC ( image, "ELF %p found virtual entry point at %lx" 00107 " (virt %lx)\n", image, image->priv.phys, 00108 ( ( unsigned long ) ehdr->e_entry ) ); 00109 } 00110 } 00111 00112 return 0; 00113 }
| int elf_load | ( | struct image * | image | ) |
Load ELF image into memory.
| image | ELF file |
| rc | Return status code |
Definition at line 121 of file elf.c.
References assert, copy_from_user(), image::data, DBGC, Elf32_Ehdr::e_entry, Elf32_Ehdr::e_ident, Elf32_Ehdr::e_phentsize, Elf32_Ehdr::e_phnum, Elf32_Ehdr::e_phoff, EI_MAG0, elf_load_segment(), ELFMAG, ENOEXEC, image::len, memcmp(), NULL, image::phys, image::priv, SELFMAG, and image::type.
Referenced by elfboot_load(), and multiboot_load_elf().
00121 { 00122 Elf_Ehdr ehdr; 00123 Elf_Phdr phdr; 00124 Elf_Off phoff; 00125 unsigned int phnum; 00126 int rc; 00127 00128 /* Image type must already have been set by caller */ 00129 assert ( image->type != NULL ); 00130 00131 /* Read ELF header */ 00132 copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); 00133 if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) { 00134 DBGC ( image, "ELF %p has invalid signature\n", image ); 00135 return -ENOEXEC; 00136 } 00137 00138 /* Invalidate execution address */ 00139 image->priv.phys = 0; 00140 00141 /* Read ELF program headers */ 00142 for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ; 00143 phoff += ehdr.e_phentsize, phnum-- ) { 00144 if ( phoff > image->len ) { 00145 DBGC ( image, "ELF %p program header %d outside " 00146 "image\n", image, phnum ); 00147 return -ENOEXEC; 00148 } 00149 copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) ); 00150 if ( ( rc = elf_load_segment ( image, &phdr, &ehdr ) ) != 0 ) 00151 return rc; 00152 } 00153 00154 /* Check for a valid execution address */ 00155 if ( ! image->priv.phys ) { 00156 DBGC ( image, "ELF %p entry point %lx outside image\n", 00157 image, ( ( unsigned long ) ehdr.e_entry ) ); 00158 return -ENOEXEC; 00159 } 00160 00161 return 0; 00162 }
1.5.7.1