Changeset 683 for trunk/kernel/syscalls/sys_exec.c
- Timestamp:
- Jan 13, 2021, 12:36:17 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/syscalls/sys_exec.c
r670 r683 38 38 #include <syscalls.h> 39 39 40 ////////////////////////////////////////////////i//////////////////////////////////////// 41 // This static function is called twice by the sys_exec() function : 42 // - to register the main() arguments (args) in the process <exec_info> structure. 43 // - to register the environment variables (envs) in the <exec_info> structure. 44 // In both cases the input is an array of NULL terminated string pointers in user space, 45 // identified by the <u_pointers> argument. The strings can be dispatched anywhere in 46 // the calling user process space. The max number of envs, and the max number of args 47 // are defined by the CONFIG_PROCESS_ARGS_NR and CONFIG_PROCESS_ENVS_MAX_NR parameters. 48 ////////////////////////////////////////////////i//////////////////////////////////////// 49 // Implementation Note: 50 // Both the array of pointers and the strings themselve are stored in kernel space in one 51 // single, dynamically allocated, kernel buffer containing an integer number of pages, 52 // defined by the CONFIG_VMM_ENVS_SIZE and CONFIG_VMM_STACK_SIZE parameters. 53 // These two kernel buffers contains : 54 // - in the first bytes a fixed size kernel array of kernel pointers on the strings. 55 // - in the following bytes the strings themselves. 56 // The exec_info_t structure is defined in the <process.h> file. 57 ////////////////////////////////////////////////i//////////////////////////////////////// 58 // @ is_args : [in] true if called for (args) / false if called for (envs). 59 // @ u_pointers : [in] array of pointers on the strings (in user space). 60 // @ exec_info : [inout] pointer on the exec_info structure. 61 // @ return 0 if success / non-zero if too many strings or no memory. 62 ////////////////////////////////////////////////i//////////////////////////////////////// 63 static error_t exec_get_strings( bool_t is_args, 64 char ** u_pointers, 65 exec_info_t * exec_info ) 66 { 67 uint32_t index; // slot index in pointers array 68 uint32_t length; // string length (in bytes) 69 uint32_t pointers_bytes; // number of bytes to store pointers 70 uint32_t max_index; // max size of pointers array 71 char ** k_pointers; // base of kernel array of pointers 72 char * k_buf_ptr; // pointer on first empty slot in strings buffer 73 uint32_t k_buf_space; // number of bytes available in string buffer 74 char * k_buf; // kernel buffer for both pointers & strings 75 76 #if DEBUG_SYS_EXEC 77 thread_t * this = CURRENT_THREAD; 78 uint32_t cycle = (uint32_t)hal_get_cycles(); 79 #endif 80 81 // Allocate one block of physical memory for both the pointers and the strings 82 83 if( is_args ) 84 { 85 k_buf = kmem_alloc( bits_log2(CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_ORDER), AF_ZERO ); 86 87 pointers_bytes = (CONFIG_PROCESS_ARGS_MAX_NR + 1) * sizeof(char *); 88 k_pointers = (char **)k_buf; 89 k_buf_ptr = k_buf + pointers_bytes; 90 k_buf_space = (CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_ORDER) - pointers_bytes; 91 max_index = CONFIG_PROCESS_ARGS_MAX_NR + 1; 92 93 #if DEBUG_SYS_EXEC 94 if( DEBUG_SYS_EXEC < cycle ) 95 printk("\n[%s] thread[%x,%x] for args / u_buf %x / k_buf %x\n", 96 __FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf ); 97 #endif 98 99 } 100 else // envs 101 { 102 k_buf = kmem_alloc( bits_log2(CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_ORDER), AF_ZERO ); 103 104 pointers_bytes = (CONFIG_PROCESS_ENVS_MAX_NR + 1) * sizeof(char *); 105 k_pointers = (char **)k_buf; 106 k_buf_ptr = k_buf + pointers_bytes; 107 k_buf_space = (CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_ORDER) - pointers_bytes; 108 max_index = CONFIG_PROCESS_ENVS_MAX_NR + 1; 109 110 #if DEBUG_SYS_EXEC 111 if( DEBUG_SYS_EXEC < cycle ) 112 printk("\n[%s] thread[%x,%x] for envs / u_buf %x / k_buf %x\n", 113 __FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf ); 114 #endif 115 116 } 117 118 // copy the user array of pointers to kernel buffer 119 hal_copy_from_uspace( XPTR( local_cxy , k_pointers ), 120 u_pointers, 121 pointers_bytes ); 122 123 // WARNING : the pointers copied in the k_pointers[] array are user pointers, 124 // after the loop below, the k_pointers[] array contains kernel pointers. 125 126 #if DEBUG_SYS_EXEC 127 if( DEBUG_SYS_EXEC < cycle ) 128 printk("\n[%s] thread[%x,%x] moved u_ptr array of pointers to k_ptr array\n", 129 __FUNCTION__, this->process->pid, this->trdid ); 130 #endif 131 132 // scan kernel array of pointers to copy strings to kernel buffer 133 for( index = 0 ; index < max_index ; index++ ) 134 { 135 // exit loop if (k_pointers[index] == NUll) 136 if( k_pointers[index] == NULL ) break; 137 138 // compute string length (without the NUL character) 139 length = hal_strlen_from_uspace( k_pointers[index] ); 140 141 // return error if overflow in kernel buffer 142 if( length > k_buf_space ) return -1; 143 144 // copy the string itself to kernel buffer 145 hal_copy_from_uspace( XPTR( local_cxy , k_buf_ptr ), 146 k_pointers[index], 147 length + 1 ); 148 149 #if DEBUG_SYS_EXEC 150 if( DEBUG_SYS_EXEC < cycle ) 151 printk("\n[%s] thread[%x,%x] copied string[%d] <%s> to kernel buffer / length %d\n", 152 __FUNCTION__, this->process->pid, this->trdid, index, k_buf_ptr, length ); 153 #endif 154 155 // replace the user pointer by a kernel pointer in the k_pointer[] array 156 k_pointers[index] = k_buf_ptr; 157 158 // increment loop variables 159 k_buf_ptr += (length + 1); 160 k_buf_space -= (length + 1); 161 162 #if DEBUG_SYS_EXEC 163 if( DEBUG_SYS_EXEC < cycle ) 164 { 165 if( k_pointers[0] != NULL ) 166 printk("\n[%s] thread[%x,%x] : &arg0 = %x / arg0 = <%s>\n", 167 __FUNCTION__, this->process->pid, this->trdid, k_pointers[0], k_pointers[0] ); 168 else 169 printk("\n[%s] thread[%x,%x] : unexpected NULL value for &arg0\n", 170 __FUNCTION__, this->process->pid, this->trdid ); 171 } 172 #endif 173 174 } // end loop on index 175 176 // update into exec_info structure 177 if( is_args ) 178 { 179 exec_info->args_pointers = k_pointers; 180 exec_info->args_nr = index; 181 } 182 else 183 { 184 exec_info->envs_pointers = k_pointers; 185 exec_info->envs_buf_free = k_buf_ptr; 186 exec_info->envs_nr = index; 187 } 188 189 #if DEBUG_SYS_EXEC 190 if( DEBUG_SYS_EXEC < cycle ) 191 printk("\n[%s] thread[%x,%x] copied %d strings to kernel buffer\n", 192 __FUNCTION__, this->process->pid, this->trdid, index ); 193 #endif 194 195 return 0; 196 197 } // end exec_get_strings() 198 199 40 200 /////////////////////////////// 41 int sys_exec( char * pathname, 42 char ** user_args, // pointer onprocess arguments in user space43 char ** user_envs ) // pointer onenv variables in user space201 int sys_exec( char * pathname, // .elf file pathname in user space 202 char ** user_args, // pointer on array of process arguments in user space 203 char ** user_envs ) // pointer on array of env variables in user space 44 204 { 45 205 error_t error; … … 96 256 97 257 #if DEBUG_SYSCALLS_ERROR 258 if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start ) 98 259 printk("\n[ERROR] in %s for thread[%x,%] : user_args pointer %x unmapped\n", 99 260 __FUNCTION__, pid, trdid, user_args ); … … 115 276 return -1; 116 277 } 117 118 #if DEBUG_SYS_EXEC119 if( DEBUG_SYS_EXEC < (uint32_t)tm_start )120 printk("\n[%s] thread[%x,%x] enter / path <%s> / args %x / envs %x / cycle %d\n",121 __FUNCTION__, pid, trdid, &process->exec_info.path[0], user_args, user_envs, cycle );122 #endif123 278 124 279 // 1. copy "pathname" in kernel exec_info structure … … 127 282 CONFIG_VFS_MAX_PATH_LENGTH ); 128 283 284 #if DEBUG_SYS_EXEC 285 if( DEBUG_SYS_EXEC < (uint32_t)tm_start ) 286 printk("\n[%s] thread[%x,%x] enter / path <%s> / args %x / envs %x / cycle %d\n", 287 __FUNCTION__, pid, trdid, &process->exec_info.path[0], 288 user_args, user_envs, (uint32_t)tm_start ); 289 #endif 290 129 291 // 2. copy "arguments" pointers & strings in process exec_info if required 130 292 if( user_args != NULL ) 131 293 { 132 if( process_exec_get_strings( true , user_args , &process->exec_info ) )294 if( exec_get_strings( true , user_args , &process->exec_info ) ) 133 295 { 134 296 135 297 #if DEBUG_SYSCALLS_ERROR 136 298 if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start ) 137 printk("\n[ERROR] in %s : thread[%x,%] get arguments for <%s>\n",299 printk("\n[ERROR] in %s : thread[%x,%] cannot get arguments for <%s>\n", 138 300 __FUNCTION__, pid, trdid, pathname ); 139 301 #endif … … 144 306 #if DEBUG_SYS_EXEC 145 307 if( DEBUG_SYS_EXEC < (uint32_t)tm_start ) 146 printk("\n[%s] thread[%x,%x] got arguments/ arg[0] = <%s>\n",308 printk("\n[%s] thread[%x,%x] set arguments in exec_info / arg[0] = <%s>\n", 147 309 __FUNCTION__, pid, trdid, process->exec_info.args_pointers[0] ); 148 310 #endif … … 153 315 if( user_envs != NULL ) 154 316 { 155 if( process_exec_get_strings( false , user_envs , &process->exec_info ) )317 if( exec_get_strings( false , user_envs , &process->exec_info ) ) 156 318 { 157 319 158 320 #if DEBUG_SYSCALLS_ERROR 159 321 if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start ) 160 printk("\n[ERROR] in %s : thread[%x,%] get env variables for <%s>\n",322 printk("\n[ERROR] in %s : thread[%x,%] cannot get env variables for <%s>\n", 161 323 __FUNCTION__, pid, trdid, pathname ); 162 324 #endif … … 167 329 #if DEBUG_SYS_EXEC 168 330 if( DEBUG_SYS_EXEC < (uint32_t)tm_start ) 169 printk("\n[%s] thread[%x,%x] got envs/ env[0] = <%s>\n",331 printk("\n[%s] thread[%x,%x] set envs in exec_info / env[0] = <%s>\n", 170 332 __FUNCTION__, pid, trdid, process->exec_info.envs_pointers[0] ); 171 333 #endif
Note: See TracChangeset
for help on using the changeset viewer.