Changeset 156 for trunk/kernel
- Timestamp:
- Jul 7, 2017, 1:40:30 PM (7 years ago)
- Location:
- trunk/kernel/libk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/libk/elf.c
r23 r156 33 33 #include <syscalls.h> 34 34 35 36 35 /////////////////////////////////////////////////////////////////// 37 36 // This static function checks the .elf header. … … 41 40 static bool_t elf_isValidHeader(Elf32_Ehdr *header) 42 41 { 43 if((header->e_ident[EI_CLASS] == ELFCLASS32) 44 && (header->e_ident[EI_DATA] == ELFDATA2LSB) 42 if((header->e_ident[EI_CLASS] == ELFCLASS32) 43 && (header->e_ident[EI_DATA] == ELFDATA2LSB) 45 44 && (header->e_ident[EI_VERSION] == EV_CURRENT) 46 45 && (header->e_ident[EI_OSABI] == ELFOSABI_NONE) 47 && ((header->e_machine == EM_MIPS) || 46 && ((header->e_machine == EM_MIPS) || 48 47 (header->e_machine == EM_MIPS_RS3_LE) || 49 48 (header->e_machine == EM_386)) 50 && (header->e_type == ET_EXEC)) return true; 51 49 && (header->e_type == ET_EXEC)) 50 return true; 51 52 52 if( header->e_ident[EI_CLASS] != ELFCLASS32 ) 53 53 printk("\n[ERROR] in %s : Elf is not 32-Binary\n", __FUNCTION__ ); 54 54 55 55 if( header->e_ident[EI_DATA] != ELFDATA2LSB ) 56 57 58 if( header->e_ident[EI_VERSION] != EV_CURRENT ) 59 56 printk("\n[ERROR] in %s : Elf is not 2's complement, little endian\n", __FUNCTION__ ); 57 58 if( header->e_ident[EI_VERSION] != EV_CURRENT ) 59 printk("\n[ERROR] in %s : Elf is not in Current Version\n", __FUNCTION__); 60 60 61 61 if( header->e_ident[EI_OSABI] != ELFOSABI_NONE ) 62 63 64 if( (header->e_machine == EM_MIPS) || 65 (header->e_machine == EM_MIPS_RS3_LE) ||66 (header->e_machine == EM_386) ) 67 printk("\n[ERROR] in %s : unexpected core / accept only MIPS or 80386\n", __FUNCTION__ );62 printk("\n[ERROR] in %s : Unexpected Elf ABI, need UNIX System V ABI\n", __FUNCTION__ ); 63 64 if( (header->e_machine == EM_MIPS) || 65 (header->e_machine == EM_MIPS_RS3_LE) || 66 (header->e_machine == EM_386) ) 67 printk("\n[ERROR] in %s : unexpected core / accept only MIPS or 80386\n", __FUNCTION__ ); 68 68 69 69 if( header->e_type == ET_EXEC ) 70 printk("\n[ERROR] in %s : Elf is not executable binary\n", __FUNCTION__ );70 printk("\n[ERROR] in %s : Elf is not executable binary\n", __FUNCTION__ ); 71 71 72 72 return false; … … 74 74 75 75 /////////////////////////////////////////////////////////////////////////////////////// 76 // This function load the .elf header in the buffer allocated by the caller.76 // This function loads the .elf header in the buffer allocated by the caller. 77 77 // @ file : extended pointer on the remote file descriptor. 78 78 // @ buffer : pointer on buffer allocated by the caller. … … 82 82 void * buffer, 83 83 uint32_t size ) 84 { 85 86 87 // load .elf header 84 { 85 uint32_t count; 86 87 // load .elf header 88 88 count = vfs_move( true , 89 90 91 89 file_xp, 90 buffer, 91 size ); 92 92 93 93 if( count != size ) … … 97 97 } 98 98 99 100 99 Elf32_Ehdr * header = (Elf32_Ehdr *)buffer; 100 101 101 if( (header->e_ident[EI_MAG0] != ELFMAG0) || 102 102 (header->e_ident[EI_MAG1] != ELFMAG1) || … … 114 114 } 115 115 return 0; 116 } // end elf_header_read()116 } 117 117 118 118 /////////////////////////////////////////////////////////////////////////////////////// … … 124 124 /////////////////////////////////////////////////////////////////////////////////////// 125 125 static error_t elf_segments_load( xptr_t file_xp, 126 126 void * segs_base, 127 127 uint32_t nb_segs, 128 128 process_t * process ) 129 129 { 130 130 error_t error; 131 131 uint32_t index; 132 132 uint32_t file_size; 133 133 uint32_t mem_size; 134 134 intptr_t start; 135 135 uint32_t type; 136 136 uint32_t flags; 137 137 uint32_t offset; 138 vseg_t * vseg; 139 140 Elf32_Phdr * seg_ptr = (Elf32_Phdr *)segs_base; 141 142 // loop on segments 143 for( index = 0 ; index < nb_segs ; index++ , seg_ptr++ ) 144 { 145 if( seg_ptr->p_type != PT_LOAD) continue; 146 147 // get segment attributes 138 vseg_t * vseg; 139 140 Elf32_Phdr * seg_ptr = (Elf32_Phdr *)segs_base; 141 142 // loop on segments 143 for( index = 0 ; index < nb_segs ; index++ , seg_ptr++ ) 144 { 145 if( seg_ptr->p_type != PT_LOAD) 146 continue; 147 148 // get segment attributes 148 149 start = seg_ptr->p_vaddr; 149 150 151 152 153 154 150 offset = seg_ptr->p_offset; 151 file_size = seg_ptr->p_filesz; 152 mem_size = seg_ptr->p_memsz; 153 flags = seg_ptr->p_flags; 154 155 // check alignment 155 156 if( start & CONFIG_PPM_PAGE_MASK ) 156 157 { … … 159 160 } 160 161 161 162 162 // check size 163 if( file_size != mem_size ) 163 164 { 164 165 printk("\n[WARNING] in %s : base = %x / mem_size = %x / file_size = %x\n", … … 166 167 } 167 168 168 169 // set seek on segment base in file 169 170 error = vfs_lseek( file_xp, 170 171 172 171 offset, 172 SEEK_SET, 173 NULL ); 173 174 174 175 if( error ) … … 180 181 if( flags & PF_X ) // found CODE segment 181 182 { 182 183 type = VSEG_TYPE_CODE; 183 184 process->vmm.code_vpn_base = start >> CONFIG_PPM_PAGE_SHIFT; 184 185 185 186 elf_dmsg("\n[INFO] %s found CODE vseg / base = %x / size = %x\n", 186 187 } 188 else 189 { 190 187 __FUNCTION__ , start , mem_size ); 188 } 189 else // found DATA segment 190 { 191 type = VSEG_TYPE_DATA; 191 192 process->vmm.data_vpn_base = start >> CONFIG_PPM_PAGE_SHIFT; 192 193 193 194 elf_dmsg("\n[INFO] %s found DATA vseg / base = %x / size = %x\n", 194 195 } 196 197 198 vseg = (vseg_t *)vmm_create_vseg( process, 199 200 mem_size,201 195 __FUNCTION__, start , mem_size ); 196 } 197 198 // register vseg in VMM 199 vseg = (vseg_t *)vmm_create_vseg( process, 200 start, 201 mem_size, 202 type ); 202 203 if( vseg == NULL ) 203 204 { … … 211 212 212 213 return 0; 213 } // end elf_load_segments()214 } 214 215 215 216 /////////////////////////////////////////////// … … 217 218 process_t * process) 218 219 { 219 220 char path_copy[CONFIG_VFS_MAX_PATH_LENGTH]; 220 221 kmem_req_t req; // kmem request for program header 221 222 uint32_t length; // actual path length 222 223 Elf32_Ehdr header; // local buffer for .elf header 223 224 void * segs_base; // pointer on buffer for segment descriptors array 224 uint32_t segs_size; // size of buffer for segment descriptors array 225 uint32_t segs_size; // size of buffer for segment descriptors array 225 226 xptr_t file_xp; // extended pointer on created file descriptor 226 227 227 uint32_t file_id; // file descriptor index (unused) 228 uint32_t count; // bytes counter 228 229 error_t error; 229 230 230 231 // get path length from user space 231 232 length = hal_strlen_from_uspace( pathname ); 232 233 233 234 235 236 237 238 239 240 241 242 243 244 245 246 error = vfs_open( process->vfs_cwd_xp, 247 248 249 250 251 234 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) 235 { 236 printk("\n[ERROR] in %s : pathname length too long\n", __FUNCTION__ ); 237 return -1; 238 } 239 240 // make a local copy for pathname 241 hal_copy_from_uspace( path_copy , pathname , length+1 ); 242 243 // open file 244 file_xp = XPTR_NULL; // avoid GCC warning 245 file_id = -1; 246 247 error = vfs_open( process->vfs_cwd_xp, 248 path_copy, 249 O_RDONLY, 250 0, 251 &file_xp, 252 &file_id ); 252 253 if( error ) 253 254 { 254 255 printk("\n[ERROR] in %s : failed to open executable file %s\n", 255 256 return -1; 257 } 258 259 260 error = elf_header_read( file_xp , 261 262 263 if( error ) 264 265 266 267 256 __FUNCTION__ , path_copy ); 257 return -1; 258 } 259 260 // load header in local buffer 261 error = elf_header_read( file_xp , 262 &header, 263 sizeof(Elf32_Ehdr) ); 264 if( error ) 265 { 266 vfs_close( file_xp , file_id ); 267 return -1; 268 } 268 269 269 270 elf_dmsg("\n[INFO] %s loaded elf header for %s\n", __FUNCTION__ , path_copy ); … … 272 273 { 273 274 printk("\n[ERROR] in %s : no segments found\n", __FUNCTION__ ); 274 275 return -1; 276 } 277 278 275 vfs_close( file_xp , file_id ); 276 return -1; 277 } 278 279 // compute buffer size for segment descriptors array 279 280 segs_size = sizeof(Elf32_Phdr) * header.e_phnum; 280 281 281 282 // allocate memory for segment descriptors array 282 283 req.type = KMEM_GENERIC; 283 284 req.size = segs_size; … … 286 287 287 288 if( segs_base == NULL ) 288 289 { 289 290 printk("\n[ERROR] in %s : no memory for segment descriptors\n", __FUNCTION__ ); 290 291 292 293 294 291 vfs_close( file_xp , file_id ); 292 return -1; 293 } 294 295 // set seek pointer in file descriptor to access segment descriptors array 295 296 error = vfs_lseek( file_xp , header.e_phoff, SEEK_SET , NULL ); 296 297 … … 298 299 { 299 300 printk("\n[ERROR] in %s : cannot seek for descriptors array\n", __FUNCTION__ ); 300 301 302 303 return -1; 304 } 305 306 // load seg descriptors array to local buffer 301 vfs_close( file_xp , file_id ); 302 req.ptr = segs_base; 303 kmem_free( &req ); 304 return -1; 305 } 306 307 // load seg descriptors array to local buffer 307 308 count = vfs_move( true, 308 file_xp, 309 310 309 file_xp, 310 segs_base, 311 segs_size ); 311 312 312 313 if( count != segs_size ) 313 314 { 314 315 printk("\n[ERROR] in %s : cannot read segments descriptors\n", __FUNCTION__ ); 315 316 317 316 vfs_close( file_xp , file_id ); 317 req.ptr = segs_base; 318 kmem_free( &req ); 318 319 return -1; 319 320 } … … 321 322 elf_dmsg("\n[INFO] %s loaded segments descriptors for %s \n", __FUNCTION__ , path_copy ); 322 323 323 324 error = elf_segments_load( file_xp, 325 326 327 324 // register loadable segments in process VMM 325 error = elf_segments_load( file_xp, 326 segs_base, 327 header.e_phnum, 328 process ); 328 329 if( error ) 329 330 331 332 333 return -1; 334 335 336 330 { 331 vfs_close( file_xp , file_id ); 332 req.ptr = segs_base; 333 kmem_free( &req ); 334 return -1; 335 } 336 337 // register process entry point in VMM 337 338 process->vmm.entry_point = (intptr_t)header.e_entry; 338 339 339 // register extended pointer on .elf file descriptor 340 341 342 340 // register extended pointer on .elf file descriptor 341 process->vfs_bin_xp = file_xp; 342 343 // release allocated memory for program header 343 344 req.ptr = segs_base; 344 345 kmem_free(&req); 345 346 346 elf_dmsg("\n[INFO] %s successfully completed / entry point = %x for %s]\n", 347 elf_dmsg("\n[INFO] %s successfully completed / entry point = %x for %s]\n", 347 348 __FUNCTION__, (uint32_t) header.e_entry , path_copy ); 348 349 349 350 return 0; 350 } // end elf_load_process()351 351 } 352 -
trunk/kernel/libk/elf.h
r1 r156 71 71 Elf32_Half e_shnum; /* Section header table entry count */ 72 72 Elf32_Half e_shstrndx; /* Section header string table index */ 73 } 73 } 74 74 Elf32_Ehdr; 75 75 … … 150 150 Elf32_Word p_flags; /* Segment flags */ 151 151 Elf32_Word p_align; /* Segment alignment */ 152 } 152 } 153 153 Elf32_Phdr; 154 154 … … 187 187 188 188 /**************************************************************************************** 189 * This function register in VMM the CODE and DATA vsegs defined in the .elf file.189 * This function registers in VMM the CODE and DATA vsegs defined in the .elf file. 190 190 * The segments are not loaded in memory. 191 * It register alsothe process entry point in VMM.191 * It also registers the process entry point in VMM. 192 192 **************************************************************************************** 193 193 * @ pathname : .elf file pathname (in user space => must use hal_uspace API). … … 197 197 process_t * process); 198 198 199 200 199 #endif /* elf.h */
Note: See TracChangeset
for help on using the changeset viewer.