nxflat.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /****************************************************************************
  2. * binfmt/nxflat.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 <sys/types.h>
  25. #include <stdint.h>
  26. #include <string.h>
  27. #include <nxflat.h>
  28. #include <debug.h>
  29. #include <errno.h>
  30. #include <arpa/inet.h>
  31. #include <nuttx/kmalloc.h>
  32. #include <nuttx/binfmt/binfmt.h>
  33. #include <nuttx/binfmt/nxflat.h>
  34. #ifdef CONFIG_NXFLAT
  35. /****************************************************************************
  36. * Pre-processor Definitions
  37. ****************************************************************************/
  38. /* CONFIG_DEBUG_FEATURES, CONFIG_DEBUG_INFO, and CONFIG_DEBUG_BINFMT
  39. * have to be defined or CONFIG_NXFLAT_DUMPBUFFER does nothing.
  40. */
  41. #if !defined(CONFIG_DEBUG_INFO) || !defined (CONFIG_DEBUG_BINFMT)
  42. # undef CONFIG_NXFLAT_DUMPBUFFER
  43. #endif
  44. #ifdef CONFIG_NXFLAT_DUMPBUFFER
  45. # define nxflat_dumpbuffer(m,b,n) binfodumpbuffer(m,b,n)
  46. #else
  47. # define nxflat_dumpbuffer(m,b,n)
  48. #endif
  49. #ifndef MIN
  50. # define MIN(a,b) (a < b ? a : b)
  51. #endif
  52. /****************************************************************************
  53. * Private Function Prototypes
  54. ****************************************************************************/
  55. static int nxflat_loadbinary(FAR struct binary_s *binp,
  56. FAR const char *filename,
  57. FAR const struct symtab_s *exports,
  58. int nexports);
  59. static int nxflat_unloadbinary(FAR struct binary_s *binp);
  60. #if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_BINFMT)
  61. static void nxflat_dumploadinfo(FAR struct nxflat_loadinfo_s *loadinfo);
  62. #endif
  63. /****************************************************************************
  64. * Private Data
  65. ****************************************************************************/
  66. static struct binfmt_s g_nxflatbinfmt =
  67. {
  68. NULL, /* next */
  69. nxflat_loadbinary, /* load */
  70. nxflat_unloadbinary, /* unload */
  71. };
  72. /****************************************************************************
  73. * Private Functions
  74. ****************************************************************************/
  75. /****************************************************************************
  76. * Name: nxflat_dumploadinfo
  77. ****************************************************************************/
  78. #if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_BINFMT)
  79. static void nxflat_dumploadinfo(FAR struct nxflat_loadinfo_s *loadinfo)
  80. {
  81. unsigned long dsize = loadinfo->datasize + loadinfo->bsssize;
  82. binfo("LOAD_INFO:\n");
  83. binfo(" ISPACE:\n");
  84. binfo(" ispace: %08lx\n", loadinfo->ispace);
  85. binfo(" entryoffs: %08lx\n", loadinfo->entryoffs);
  86. binfo(" isize: %08lx\n", loadinfo->isize);
  87. binfo(" DSPACE:\n");
  88. binfo(" dspace: %08lx\n", loadinfo->dspace);
  89. if (loadinfo->dspace != NULL)
  90. {
  91. binfo(" crefs: %d\n", loadinfo->dspace->crefs);
  92. binfo(" region: %08lx\n", loadinfo->dspace->region);
  93. }
  94. binfo(" datasize: %08lx\n", loadinfo->datasize);
  95. binfo(" bsssize: %08lx\n", loadinfo->bsssize);
  96. binfo(" (pad): %08lx\n", loadinfo->dsize - dsize);
  97. binfo(" stacksize: %08lx\n", loadinfo->stacksize);
  98. binfo(" dsize: %08lx\n", loadinfo->dsize);
  99. binfo(" RELOCS:\n");
  100. binfo(" relocstart: %08lx\n", loadinfo->relocstart);
  101. binfo(" reloccount: %d\n", loadinfo->reloccount);
  102. }
  103. #else
  104. # define nxflat_dumploadinfo(i)
  105. #endif
  106. /****************************************************************************
  107. * Name: nxflat_loadbinary
  108. *
  109. * Description:
  110. * Verify that the file is an NXFLAT binary and, if so, load the NXFLAT
  111. * binary into memory
  112. *
  113. ****************************************************************************/
  114. static int nxflat_loadbinary(FAR struct binary_s *binp,
  115. FAR const char *filename,
  116. FAR const struct symtab_s *exports,
  117. int nexports)
  118. {
  119. struct nxflat_loadinfo_s loadinfo; /* Contains globals for libnxflat */
  120. int ret;
  121. binfo("Loading file: %s\n", filename);
  122. /* Initialize the xflat library to load the program binary. */
  123. ret = nxflat_init(filename, &loadinfo);
  124. nxflat_dumploadinfo(&loadinfo);
  125. if (ret != 0)
  126. {
  127. berr("Failed to initialize for load of NXFLAT program: %d\n", ret);
  128. goto errout;
  129. }
  130. /* Load the program binary */
  131. ret = nxflat_load(&loadinfo);
  132. nxflat_dumploadinfo(&loadinfo);
  133. if (ret != 0)
  134. {
  135. berr("Failed to load NXFLAT program binary: %d\n", ret);
  136. goto errout_with_init;
  137. }
  138. /* Bind the program to the exported symbol table */
  139. ret = nxflat_bind(&loadinfo, exports, nexports);
  140. if (ret != 0)
  141. {
  142. berr("Failed to bind symbols program binary: %d\n", ret);
  143. goto errout_with_load;
  144. }
  145. /* Return the load information. By convention, D-space address
  146. * space is stored as the first allocated memory.
  147. */
  148. binp->entrypt = (main_t)(loadinfo.ispace + loadinfo.entryoffs);
  149. binp->mapped = (FAR void *)loadinfo.ispace;
  150. binp->mapsize = loadinfo.isize;
  151. binp->stacksize = loadinfo.stacksize;
  152. /* Add the ELF allocation to the alloc[] only if there is no address
  153. * environment. If there is an address environment, it will automatically
  154. * be freed when the function exits
  155. *
  156. * REVISIT: If the module is loaded then unloaded, wouldn't this cause
  157. * a memory leak?
  158. */
  159. #ifdef CONFIG_ARCH_ADDRENV
  160. # warning "REVISIT"
  161. #else
  162. binp->alloc[0] = (FAR void *)loadinfo.dspace;
  163. #endif
  164. #ifdef CONFIG_ARCH_ADDRENV
  165. /* Save the address environment in the binfmt structure. This will be
  166. * needed when the module is executed.
  167. */
  168. up_addrenv_clone(&loadinfo.addrenv, &binp->addrenv);
  169. #endif
  170. nxflat_dumpbuffer("Entry code", (FAR const uint8_t *)binp->entrypt,
  171. MIN(loadinfo.isize - loadinfo.entryoffs, 512));
  172. nxflat_uninit(&loadinfo);
  173. return OK;
  174. errout_with_load:
  175. nxflat_unload(&loadinfo);
  176. errout_with_init:
  177. nxflat_uninit(&loadinfo);
  178. errout:
  179. return ret;
  180. }
  181. /****************************************************************************
  182. * Name: nxflat_unloadbinary
  183. *
  184. * Description:
  185. * Verify that the file is an NXFLAT binary and, if so, load the NXFLAT
  186. * binary into memory
  187. *
  188. ****************************************************************************/
  189. static int nxflat_unloadbinary(FAR struct binary_s *binp)
  190. {
  191. FAR struct dspace_s *dspace = (FAR struct dspace_s *)binp->alloc[0];
  192. /* Check if this is the last reference to dspace. It may still be needed
  193. * by other threads. In that case, it must persist after this thread
  194. * terminates.
  195. */
  196. if (dspace != NULL && dspace->crefs == 1)
  197. {
  198. /* Free the dspace region */
  199. kumm_free(dspace->region);
  200. dspace->region = NULL;
  201. /* Mark alloc[0] (dspace) as freed */
  202. binp->alloc[0] = NULL;
  203. /* The reference count will be decremented to zero and the dspace
  204. * container will be freed in sched/nxsched_release_tcb.c
  205. */
  206. }
  207. return OK;
  208. }
  209. /****************************************************************************
  210. * Public Functions
  211. ****************************************************************************/
  212. /****************************************************************************
  213. * Name: nxflat_initialize
  214. *
  215. * Description:
  216. * In order to use the NxFLAT binary format, this function must be called
  217. * during system initialization to register the NXFLAT binary
  218. * format.
  219. *
  220. * Returned Value:
  221. * This is a NuttX internal function so it follows the convention that
  222. * 0 (OK) is returned on success and a negated errno is returned on
  223. * failure.
  224. *
  225. ****************************************************************************/
  226. int nxflat_initialize(void)
  227. {
  228. int ret;
  229. /* Register ourselves as a binfmt loader */
  230. binfo("Registering NXFLAT\n");
  231. ret = register_binfmt(&g_nxflatbinfmt);
  232. if (ret != 0)
  233. {
  234. berr("Failed to register binfmt: %d\n", ret);
  235. }
  236. return ret;
  237. }
  238. /****************************************************************************
  239. * Name: nxflat_uninitialize
  240. *
  241. * Description:
  242. * Unregister the NXFLAT binary loader
  243. *
  244. * Returned Value:
  245. * None
  246. *
  247. ****************************************************************************/
  248. void nxflat_uninitialize(void)
  249. {
  250. unregister_binfmt(&g_nxflatbinfmt);
  251. }
  252. #endif /* CONFIG_NXFLAT */