Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

elf32.c

Go to the documentation of this file.
00001 /*!     \file kernel/elf32.c
00002  *      \brief ELF32 file format loader.
00003  *      \author Andrea Righi <drizzt@inwind.it>
00004  *      \date Last update:\n
00005  *              2003-01-24 Andrea Righi:
00006  *                      Skip NULL sections when copying them to
00007  *                      memory.\n
00008  *      \note Copyright (&copy;) 2003 Andrea Righi
00009  */
00010 
00011 #include <const.h>
00012 #include <errno.h>
00013 
00014 #include <arch/mem.h>
00015 
00016 #include <kernel/console.h>
00017 #include <kernel/fat.h>
00018 #include <kernel/kernel_map.h>
00019 #include <kernel/keyboard.h>
00020 #include <kernel/kmalloc.h>
00021 
00022 #include <kernel/elf32.h>
00023 
00024 //! \brief
00025 //!     Check if a file has a valid elf32 header.
00026 //! \param f The file header.
00027 //! \return
00028 //!     \li 0 if success;
00029 //!     \li -ENOEXEC if \p f is not a valid ELF32 header.
00030 int elf32_check(elf32_hdr_t *f)
00031 {
00032 // Check if "f" is a valid ELF32 header                                 //
00033         #ifdef ELF32_DEBUG
00034                 kprintf("\n\rFile header:");
00035                 kprintf("\n\rmagic[]=%c%c%c%c class=%u data=%u",
00036                         f->e_ident[EI_MAG0],
00037                         f->e_ident[EI_MAG1],
00038                         f->e_ident[EI_MAG2],
00039                         f->e_ident[EI_MAG3],
00040                         f->e_ident[EI_CLASS],
00041                         f->e_ident[EI_DATA]
00042                 );
00043         #endif
00044         // Magic number check                                           //
00045         if (
00046                 (f->e_ident[EI_MAG0] != ELF_MAG0) ||
00047                 (f->e_ident[EI_MAG1] != ELF_MAG1) ||
00048                 (f->e_ident[EI_MAG2] != ELF_MAG2) ||
00049                 (f->e_ident[EI_MAG3] != ELF_MAG3)
00050         )
00051                 return( -ENOEXEC );
00052 
00053         // Class check                                                  //
00054         if ( f->e_ident[EI_CLASS] != ELF_CLASS32 )
00055                 return( -ENOEXEC );
00056 
00057         // Data encoding check                                          //
00058         if ( f->e_ident[EI_DATA] != ELF_DATA2LSB )
00059                 return( -ENOEXEC );
00060 
00061         // Check OK!                                                    //
00062         return(0);
00063 }
00064 
00065 //! \brief
00066 //!     Copy the ELF32 sections at the right locations in memory.
00067 //! \param f The buffer where the ELF32 file is located.
00068 //! \return
00069 //!     \li the entry point address on success;
00070 //!     \li NULL if an error occurs.
00071 uint32_t elf32_copy_sections(elf32_hdr_t *f)
00072 {
00073         elf32_shdr_t *sec;
00074         int     sec_num;
00075         int     sec_entsize;
00076         int     i;
00077 
00078         void copy_section(elf32_shdr_t *sec)
00079         {
00080                 #ifdef ELF32_DEBUG
00081                 kprintf("\n\rsh_name      = %#010x", sec->sh_name);
00082                 kprintf("\n\rsh_type      = %#010x", sec->sh_type);
00083                 kprintf("\n\rsh_flags     = %#010x", sec->sh_flags);
00084                 kprintf("\n\rsh_addr      = %#010x", sec->sh_addr);
00085                 kprintf("\n\rsh_offset    = %#010x", sec->sh_offset);
00086                 kprintf("\n\rsh_size      = %#010x", sec->sh_size);
00087                 kprintf("\n\rsh_link      = %#010x", sec->sh_link);
00088                 kprintf("\n\rsh_info      = %#010x", sec->sh_info);
00089                 kprintf("\n\rsh_addralign = %#010x", sec->sh_addralign);
00090                 kprintf("\n\rsh_entsize   = %#010x", sec->sh_entsize);
00091                 kprintf("\n\r");
00092                 #endif
00093 
00094                 // Skip NULL sections.
00095                 if( (sec->sh_addr==NULL) || (sec->sh_offset==NULL) )
00096                         return;
00097 
00098                 // Copy this section into the current address space.
00099                 memcpy( (void *)(sec->sh_addr),
00100                         (void *)((uint32_t)f + sec->sh_offset),
00101                         sec->sh_size );
00102         }
00103 
00104         // Check if it is a valid ELF32 file                            //
00105         if ( elf32_check(f)<0 )
00106                 return(NULL);
00107 
00108         // Get the section informations                                 //
00109         sec_num =       f->e_shnum;
00110         sec_entsize =   f->e_shentsize;
00111         #ifdef ELF32_DEBUG
00112         kprintf("\n\rEntry point @ %#010x", f->e_entry);
00113         kprintf("\n\rsec_num=%#010x, sec_entsize=%#010x\n\r", sec_num, sec_entsize);
00114         #endif
00115 
00116         // First of all check if the sections are not in the user space
00117         // boundaries.
00118         // ----- User Sections          (4KB - 1GB)
00119         // ----- User Heap              (1GB - 2GB)
00120         // ----- User Stack             (2GB - 3GB)
00121         sec = (elf32_shdr_t *)((uint32_t)f->e_shoff + (uint32_t)f);
00122         for (i=0; i<sec_num; i++)
00123         {
00124                 if ( (sec->sh_addr >= K_VIR_START) || (sec->sh_addr + sec->sh_size) >= K_VIR_START )
00125                         return( NULL );
00126                 (uint32_t)sec += sec_entsize;
00127         }
00128 
00129         // Copy the sections in memory                                  //
00130         sec = (elf32_shdr_t *)((uint32_t)f->e_shoff + (uint32_t)f);
00131         for (i=0; i<sec_num; i++)
00132         {
00133                 copy_section( sec );
00134                 (uint32_t)sec += sec_entsize;
00135         }
00136         return( f->e_entry );
00137 }
00138 
00139 //! \brief
00140 //!     Load an ELF32 file into a buffer.
00141 //! \param file_name The name of the file to be loaded.
00142 //! \param file_buffer The buffer where the file will be loaded.
00143 //! \return
00144 //!     \li 0 on success;
00145 //!     \li -ENOENT if the file doesn't exist;
00146 //!     \li -ENOEXEC if the file is not a valid ELF32 file.
00147 int elf32_load_file(char *file_name, void *file_buffer)
00148 {
00149         // Load the file into the buffer                                //
00150         // TODO: replace with:
00151         //      int fread(void *buf, size_t size, size_t count, FILE *stream);
00152         if ( !(load_file(file_name, file_buffer)) )
00153                 return( -ENOENT );
00154 
00155         // Check if it is a valid ELF file                              //
00156         if ( elf32_check((elf32_hdr_t *)file_buffer) < 0 )
00157                 return( -ENOEXEC );
00158 
00159         // The ELF32 file is successfully loaded                        //
00160         return(0);
00161 }
00162 
00163 //! \brief Execute a file.
00164 int elf32_exec(void *f, int argc, char **argv)
00165 {
00166         int (*entry)(int argc, char **argv) = (int(*)(int argc, char **argv))(((elf32_hdr_t *)f)->e_entry);
00167         return( entry(argc, argv) );
00168 }

Generated on Fri Feb 20 15:32:15 2004 for Minirighi by doxygen1.2.18