123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /****************************************************************************
- * binfmt/binfmt_exec.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <nuttx/config.h>
- #include <string.h>
- #include <debug.h>
- #include <errno.h>
- #include <nuttx/kmalloc.h>
- #include <nuttx/sched.h>
- #include <nuttx/binfmt/binfmt.h>
- #include "binfmt.h"
- #ifndef CONFIG_BINFMT_DISABLE
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: exec_spawn
- *
- * Description:
- * exec() configurable version, delivery the spawn attribute if this
- * process has special customization.
- *
- * Input Parameters:
- * filename - The path to the program to be executed. If
- * CONFIG_LIB_ENVPATH is defined in the configuration, then
- * this may be a relative path from the current working
- * directory. Otherwise, path must be the absolute path to the
- * program.
- * argv - A pointer to an array of string arguments. The end of the
- * array is indicated with a NULL entry.
- * exports - The address of the start of the caller-provided symbol
- * table. This symbol table contains the addresses of symbols
- * exported by the caller and made available for linking the
- * module into the system.
- * nexports - The number of symbols in the exports table.
- * attr - The spawn attributes.
- *
- * Returned Value:
- * It returns the PID of the exec'ed module. On failure, it returns
- * the negative errno value appropriately.
- *
- ****************************************************************************/
- int exec_spawn(FAR const char *filename, FAR char * const *argv,
- FAR const struct symtab_s *exports, int nexports,
- FAR const posix_spawnattr_t *attr)
- {
- FAR struct binary_s *bin;
- int pid;
- int ret;
- /* Allocate the load information */
- bin = (FAR struct binary_s *)kmm_zalloc(sizeof(struct binary_s));
- if (!bin)
- {
- berr("ERROR: Failed to allocate binary_s\n");
- ret = -ENOMEM;
- goto errout;
- }
- /* Initialize the binary structure */
- bin->filename = filename;
- bin->exports = exports;
- bin->nexports = nexports;
- /* Copy the argv[] list */
- ret = binfmt_copyargv(bin, argv);
- if (ret < 0)
- {
- berr("ERROR: Failed to copy argv[]: %d\n", ret);
- goto errout_with_bin;
- }
- /* Load the module into memory */
- ret = load_module(bin);
- if (ret < 0)
- {
- berr("ERROR: Failed to load program '%s': %d\n", filename, ret);
- goto errout_with_argv;
- }
- /* Update the spawn attribute */
- if (attr)
- {
- if (attr->priority > 0)
- {
- bin->priority = attr->priority;
- }
- #ifndef CONFIG_BUILD_KERNEL
- if (attr->stacksize > 0)
- {
- bin->stacksize = attr->stacksize;
- }
- #endif
- }
- /* Disable pre-emption so that the executed module does
- * not return until we get a chance to connect the on_exit
- * handler.
- */
- sched_lock();
- /* Then start the module */
- pid = exec_module(bin);
- if (pid < 0)
- {
- ret = pid;
- berr("ERROR: Failed to execute program '%s': %d\n",
- filename, ret);
- goto errout_with_lock;
- }
- #ifdef CONFIG_BINFMT_LOADABLE
- /* Set up to unload the module (and free the binary_s structure)
- * when the task exists.
- */
- ret = group_exitinfo(pid, bin);
- if (ret < 0)
- {
- berr("ERROR: Failed to schedule unload '%s': %d\n", filename, ret);
- }
- #else
- /* Free the binary_s structure here */
- binfmt_freeargv(bin);
- kmm_free(bin);
- /* TODO: How does the module get unloaded in this case? */
- #endif
- sched_unlock();
- return pid;
- errout_with_lock:
- sched_unlock();
- unload_module(bin);
- errout_with_argv:
- binfmt_freeargv(bin);
- errout_with_bin:
- kmm_free(bin);
- errout:
- return ret;
- }
- /****************************************************************************
- * Name: exec
- *
- * Description:
- * This is a convenience function that wraps load_ and exec_module into
- * one call. If CONFIG_BINFMT_LOADABLE is defined, this function will
- * schedule to unload the module when task exits.
- *
- * This non-standard, NuttX function is similar to execv() and
- * posix_spawn() but differs in the following ways;
- *
- * - Unlike execv() and posix_spawn() this function accepts symbol table
- * information as input parameters. This means that the symbol table
- * used to link the application prior to execution is provided by the
- * caller, not by the system.
- * - Unlike execv(), this function always returns.
- *
- * This non-standard interface is included as a official NuttX API only
- * because it is needed in certain build modes: exec() is probably the
- * only way to load programs in the PROTECTED mode. Other file execution
- * APIs rely on a symbol table provided by the OS. In the PROTECTED build
- * mode, the OS cannot provide any meaningful symbolic information for
- * execution of code in the user-space blob so that is the exec() function
- * is really needed in that build case
- *
- * The interface is available in the FLAT build mode although it is not
- * really necessary in that case. It is currently used by some example
- * code under the apps/ that that generate their own symbol tables for
- * linking test programs. So although it is not necessary, it can still
- * be useful.
- *
- * The interface would be completely useless and will not be supported in
- * in the KERNEL build mode where the contrary is true: An application
- * process cannot provide any meaningful symbolic information for use in
- * linking a different process.
- *
- * NOTE: This function is flawed and useless without CONFIG_BINFMT_LOADABLE
- * because without that features there is then no mechanism to unload the
- * module once it exits.
- *
- * Input Parameters:
- * filename - The path to the program to be executed. If
- * CONFIG_LIB_ENVPATH is defined in the configuration, then
- * this may be a relative path from the current working
- * directory. Otherwise, path must be the absolute path to the
- * program.
- * argv - A pointer to an array of string arguments. The end of the
- * array is indicated with a NULL entry.
- * exports - The address of the start of the caller-provided symbol
- * table. This symbol table contains the addresses of symbols
- * exported by the caller and made available for linking the
- * module into the system.
- * nexports - The number of symbols in the exports table.
- *
- * Returned Value:
- * This is an end-user function, so it follows the normal convention:
- * It returns the PID of the exec'ed module. On failure, it returns
- * -1 (ERROR) and sets errno appropriately.
- *
- ****************************************************************************/
- int exec(FAR const char *filename, FAR char * const *argv,
- FAR const struct symtab_s *exports, int nexports)
- {
- int ret;
- ret = exec_spawn(filename, argv, exports, nexports, NULL);
- if (ret < 0)
- {
- set_errno(-ret);
- ret = ERROR;
- }
- return ret;
- }
- #endif /* !CONFIG_BINFMT_DISABLE */
|