binfmt_exec.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /****************************************************************************
  2. * binfmt/binfmt_exec.c
  3. *
  4. * Copyright (C) 2009, 2013-2014, 2017-2018 Gregory Nutt. All rights
  5. * reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. * 3. Neither the name NuttX nor the names of its contributors may be
  19. * used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ****************************************************************************/
  36. /****************************************************************************
  37. * Included Files
  38. ****************************************************************************/
  39. #include <nuttx/config.h>
  40. #include <string.h>
  41. #include <debug.h>
  42. #include <errno.h>
  43. #include <nuttx/kmalloc.h>
  44. #include <nuttx/sched.h>
  45. #include <nuttx/binfmt/binfmt.h>
  46. #include "binfmt.h"
  47. #ifndef CONFIG_BINFMT_DISABLE
  48. /****************************************************************************
  49. * Public Functions
  50. ****************************************************************************/
  51. /****************************************************************************
  52. * Name: exec
  53. *
  54. * Description:
  55. * This is a convenience function that wraps load_ and exec_module into
  56. * one call. If CONFIG_BINFMT_LOADABLE is defined, this function will
  57. * schedule to unload the module when task exits.
  58. *
  59. * This non-standard, NuttX function is similar to execv() and
  60. * posix_spawn() but differs in the following ways;
  61. *
  62. * - Unlike execv() and posix_spawn() this function accepts symbol table
  63. * information as input parameters. This means that the symbol table
  64. * used to link the application prior to execution is provided by the
  65. * caller, not by the system.
  66. * - Unlike execv(), this function always returns.
  67. *
  68. * This non-standard interface is included as a official NuttX API only
  69. * because it is needed in certain build modes: exec() is probably the
  70. * only want to load programs in the PROTECTED mode. Other file execution
  71. * APIs rely on a symbol table provided by the OS. In the PROTECTED build
  72. * mode, the OS cannot provide any meaningful symbolic information for
  73. * execution of code in the user-space blob so that is the exec() function
  74. * is really needed in that build case
  75. *
  76. * The interface is available in the FLAT build mode although it is not
  77. * really necessary in that case. It is currently used by some example
  78. * code under the apps/ that that generate their own symbol tables for
  79. * linking test programs. So althought it is not necessary, it can still
  80. * be useful.
  81. *
  82. * The interface would be completely useless and will not be supported in
  83. * in the KERNEL build mode where the contrary is true: An application
  84. * process cannot provide any meaning symbolic information for use in
  85. * linking a different process.
  86. *
  87. * NOTE: This function is flawed and useless without CONFIG_BINFMT_LOADABLE
  88. * because without that features there is then no mechanism to unload the
  89. * module once it exits.
  90. *
  91. * Input Parameters:
  92. * filename - The path to the program to be executed. If
  93. * CONFIG_LIB_ENVPATH is defined in the configuration, then
  94. * this may be a relative path from the current working
  95. * directory. Otherwise, path must be the absolute path to the
  96. * program.
  97. * argv - A pointer to an array of string arguments. The end of the
  98. * array is indicated with a NULL entry.
  99. * exports - The address of the start of the caller-provided symbol
  100. * table. This symbol table contains the addresses of symbols
  101. * exported by the caller and made available for linking the
  102. * module into the system.
  103. * nexports - The number of symbols in the exports table.
  104. *
  105. * Returned Value:
  106. * This is an end-user function, so it follows the normal convention:
  107. * It returns the PID of the exec'ed module. On failure, it returns
  108. * -1 (ERROR) and sets errno appropriately.
  109. *
  110. ****************************************************************************/
  111. int exec(FAR const char *filename, FAR char * const *argv,
  112. FAR const struct symtab_s *exports, int nexports)
  113. {
  114. FAR struct binary_s *bin;
  115. int pid;
  116. int errcode;
  117. int ret;
  118. /* Allocate the load information */
  119. bin = (FAR struct binary_s *)kmm_zalloc(sizeof(struct binary_s));
  120. if (!bin)
  121. {
  122. berr("ERROR: Failed to allocate binary_s\n");
  123. errcode = ENOMEM;
  124. goto errout;
  125. }
  126. /* Initialize the binary structure */
  127. bin->filename = filename;
  128. bin->exports = exports;
  129. bin->nexports = nexports;
  130. /* Copy the argv[] list */
  131. ret = binfmt_copyargv(bin, argv);
  132. if (ret < 0)
  133. {
  134. errcode = -ret;
  135. berr("ERROR: Failed to copy argv[]: %d\n", errcode);
  136. goto errout_with_bin;
  137. }
  138. /* Load the module into memory */
  139. ret = load_module(bin);
  140. if (ret < 0)
  141. {
  142. errcode = -ret;
  143. berr("ERROR: Failed to load program '%s': %d\n", filename, errcode);
  144. goto errout_with_argv;
  145. }
  146. /* Disable pre-emption so that the executed module does
  147. * not return until we get a chance to connect the on_exit
  148. * handler.
  149. */
  150. sched_lock();
  151. /* Then start the module */
  152. pid = exec_module(bin);
  153. if (pid < 0)
  154. {
  155. errcode = -pid;
  156. berr("ERROR: Failed to execute program '%s': %d\n",
  157. filename, errcode);
  158. goto errout_with_lock;
  159. }
  160. #ifdef CONFIG_BINFMT_LOADABLE
  161. /* Set up to unload the module (and free the binary_s structure)
  162. * when the task exists.
  163. */
  164. ret = group_exitinfo(pid, bin);
  165. if (ret < 0)
  166. {
  167. berr("ERROR: Failed to schedule unload '%s': %d\n", filename, ret);
  168. }
  169. #else
  170. /* Free the binary_s structure here */
  171. binfmt_freeargv(bin);
  172. kmm_free(bin);
  173. /* TODO: How does the module get unloaded in this case? */
  174. #endif
  175. sched_unlock();
  176. return pid;
  177. errout_with_lock:
  178. sched_unlock();
  179. (void)unload_module(bin);
  180. errout_with_argv:
  181. binfmt_freeargv(bin);
  182. errout_with_bin:
  183. kmm_free(bin);
  184. errout:
  185. set_errno(errcode);
  186. return ERROR;
  187. }
  188. #endif /* !CONFIG_BINFMT_DISABLE */