binfmt_exec.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /****************************************************************************
  2. * binfmt/binfmt_exec.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <string.h>
  25. #include <debug.h>
  26. #include <errno.h>
  27. #include <nuttx/kmalloc.h>
  28. #include <nuttx/sched.h>
  29. #include <nuttx/binfmt/binfmt.h>
  30. #include "binfmt.h"
  31. #ifndef CONFIG_BINFMT_DISABLE
  32. /****************************************************************************
  33. * Public Functions
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Name: exec_spawn
  37. *
  38. * Description:
  39. * exec() configurable version, delivery the spawn attribute if this
  40. * process has special customization.
  41. *
  42. * Input Parameters:
  43. * filename - The path to the program to be executed. If
  44. * CONFIG_LIB_ENVPATH is defined in the configuration, then
  45. * this may be a relative path from the current working
  46. * directory. Otherwise, path must be the absolute path to the
  47. * program.
  48. * argv - A pointer to an array of string arguments. The end of the
  49. * array is indicated with a NULL entry.
  50. * exports - The address of the start of the caller-provided symbol
  51. * table. This symbol table contains the addresses of symbols
  52. * exported by the caller and made available for linking the
  53. * module into the system.
  54. * nexports - The number of symbols in the exports table.
  55. * attr - The spawn attributes.
  56. *
  57. * Returned Value:
  58. * It returns the PID of the exec'ed module. On failure, it returns
  59. * the negative errno value appropriately.
  60. *
  61. ****************************************************************************/
  62. int exec_spawn(FAR const char *filename, FAR char * const *argv,
  63. FAR const struct symtab_s *exports, int nexports,
  64. FAR const posix_spawnattr_t *attr)
  65. {
  66. FAR struct binary_s *bin;
  67. int pid;
  68. int ret;
  69. /* Allocate the load information */
  70. bin = (FAR struct binary_s *)kmm_zalloc(sizeof(struct binary_s));
  71. if (!bin)
  72. {
  73. berr("ERROR: Failed to allocate binary_s\n");
  74. ret = -ENOMEM;
  75. goto errout;
  76. }
  77. /* Initialize the binary structure */
  78. bin->filename = filename;
  79. bin->exports = exports;
  80. bin->nexports = nexports;
  81. /* Copy the argv[] list */
  82. ret = binfmt_copyargv(bin, argv);
  83. if (ret < 0)
  84. {
  85. berr("ERROR: Failed to copy argv[]: %d\n", ret);
  86. goto errout_with_bin;
  87. }
  88. /* Load the module into memory */
  89. ret = load_module(bin);
  90. if (ret < 0)
  91. {
  92. berr("ERROR: Failed to load program '%s': %d\n", filename, ret);
  93. goto errout_with_argv;
  94. }
  95. /* Update the spawn attribute */
  96. if (attr)
  97. {
  98. if (attr->priority > 0)
  99. {
  100. bin->priority = attr->priority;
  101. }
  102. #ifndef CONFIG_BUILD_KERNEL
  103. if (attr->stacksize > 0)
  104. {
  105. bin->stacksize = attr->stacksize;
  106. }
  107. #endif
  108. }
  109. /* Disable pre-emption so that the executed module does
  110. * not return until we get a chance to connect the on_exit
  111. * handler.
  112. */
  113. sched_lock();
  114. /* Then start the module */
  115. pid = exec_module(bin);
  116. if (pid < 0)
  117. {
  118. ret = pid;
  119. berr("ERROR: Failed to execute program '%s': %d\n",
  120. filename, ret);
  121. goto errout_with_lock;
  122. }
  123. #ifdef CONFIG_BINFMT_LOADABLE
  124. /* Set up to unload the module (and free the binary_s structure)
  125. * when the task exists.
  126. */
  127. ret = group_exitinfo(pid, bin);
  128. if (ret < 0)
  129. {
  130. berr("ERROR: Failed to schedule unload '%s': %d\n", filename, ret);
  131. }
  132. #else
  133. /* Free the binary_s structure here */
  134. binfmt_freeargv(bin);
  135. kmm_free(bin);
  136. /* TODO: How does the module get unloaded in this case? */
  137. #endif
  138. sched_unlock();
  139. return pid;
  140. errout_with_lock:
  141. sched_unlock();
  142. unload_module(bin);
  143. errout_with_argv:
  144. binfmt_freeargv(bin);
  145. errout_with_bin:
  146. kmm_free(bin);
  147. errout:
  148. return ret;
  149. }
  150. /****************************************************************************
  151. * Name: exec
  152. *
  153. * Description:
  154. * This is a convenience function that wraps load_ and exec_module into
  155. * one call. If CONFIG_BINFMT_LOADABLE is defined, this function will
  156. * schedule to unload the module when task exits.
  157. *
  158. * This non-standard, NuttX function is similar to execv() and
  159. * posix_spawn() but differs in the following ways;
  160. *
  161. * - Unlike execv() and posix_spawn() this function accepts symbol table
  162. * information as input parameters. This means that the symbol table
  163. * used to link the application prior to execution is provided by the
  164. * caller, not by the system.
  165. * - Unlike execv(), this function always returns.
  166. *
  167. * This non-standard interface is included as a official NuttX API only
  168. * because it is needed in certain build modes: exec() is probably the
  169. * only way to load programs in the PROTECTED mode. Other file execution
  170. * APIs rely on a symbol table provided by the OS. In the PROTECTED build
  171. * mode, the OS cannot provide any meaningful symbolic information for
  172. * execution of code in the user-space blob so that is the exec() function
  173. * is really needed in that build case
  174. *
  175. * The interface is available in the FLAT build mode although it is not
  176. * really necessary in that case. It is currently used by some example
  177. * code under the apps/ that that generate their own symbol tables for
  178. * linking test programs. So although it is not necessary, it can still
  179. * be useful.
  180. *
  181. * The interface would be completely useless and will not be supported in
  182. * in the KERNEL build mode where the contrary is true: An application
  183. * process cannot provide any meaningful symbolic information for use in
  184. * linking a different process.
  185. *
  186. * NOTE: This function is flawed and useless without CONFIG_BINFMT_LOADABLE
  187. * because without that features there is then no mechanism to unload the
  188. * module once it exits.
  189. *
  190. * Input Parameters:
  191. * filename - The path to the program to be executed. If
  192. * CONFIG_LIB_ENVPATH is defined in the configuration, then
  193. * this may be a relative path from the current working
  194. * directory. Otherwise, path must be the absolute path to the
  195. * program.
  196. * argv - A pointer to an array of string arguments. The end of the
  197. * array is indicated with a NULL entry.
  198. * exports - The address of the start of the caller-provided symbol
  199. * table. This symbol table contains the addresses of symbols
  200. * exported by the caller and made available for linking the
  201. * module into the system.
  202. * nexports - The number of symbols in the exports table.
  203. *
  204. * Returned Value:
  205. * This is an end-user function, so it follows the normal convention:
  206. * It returns the PID of the exec'ed module. On failure, it returns
  207. * -1 (ERROR) and sets errno appropriately.
  208. *
  209. ****************************************************************************/
  210. int exec(FAR const char *filename, FAR char * const *argv,
  211. FAR const struct symtab_s *exports, int nexports)
  212. {
  213. int ret;
  214. ret = exec_spawn(filename, argv, exports, nexports, NULL);
  215. if (ret < 0)
  216. {
  217. set_errno(-ret);
  218. ret = ERROR;
  219. }
  220. return ret;
  221. }
  222. #endif /* !CONFIG_BINFMT_DISABLE */