nxflat.rst 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. .. _nxflat:
  2. ======
  3. NXFLAT
  4. ======
  5. Overview
  6. ========
  7. Functionality
  8. -------------
  9. NXFLAT is a customized and simplified version of binary format
  10. implemented a few years ago called
  11. `XFLAT <http://xflat.sourceforge.net/>`__ With the NXFLAT binary format
  12. you will be able to do the following:
  13. - Place separately linked programs in a file system, and
  14. - Execute those programs by dynamically linking them to the base NuttX
  15. code.
  16. This allows you to extend the NuttX base code after it has been written
  17. into FLASH. One motivation for implementing NXFLAT is support clean CGI
  18. under an HTTPD server.
  19. This feature is especially attractive when combined with the NuttX ROMFS
  20. support: ROMFS allows you to execute programs in place (XIP) in flash
  21. without copying anything other than the .data section to RAM. In fact,
  22. the initial NXFLAT release only worked on ROMFS. Later extensions also
  23. support execution NXFLAT binaries from an SRAM copy as well.
  24. This NuttX feature includes:
  25. - A dynamic loader that is built into the NuttX core (See
  26. `GIT <https://github.com/apache/incubator-nuttx/blob/master/binfmt/>`__).
  27. - Minor changes to RTOS to support position independent code, and
  28. - A linker to bind ELF binaries to produce the NXFLAT binary format
  29. (See GIT).
  30. Background
  31. ----------
  32. NXFLAT is derived from `XFLAT <http://xflat.sourceforge.net/>`__. XFLAT
  33. is a toolchain add that provides full shared library and XIP executable
  34. support for processors that have no Memory Management Unit
  35. (MMU:sup:`1`). NXFLAT is greatly simplified for the deeply embedded
  36. environment targeted by NuttX:
  37. - NXFLAT does not support shared libraries, because
  38. - NXFLAT does not support *exportation* of symbol values from a module
  39. Rather, the NXFLAT module only *imports* symbol values. In the NXFLAT
  40. model, the (PIC:sup:`2`) NXFLAT module resides in a FLASH file system
  41. and when it is loaded at run time, it is dynamically linked only to the
  42. (non-PIC) base NuttX code: The base NuttX *exports* a symbol table; the
  43. NXFLAT module *imports* those symbol value to dynamically bind the
  44. module to the base code.
  45. Limitations
  46. -----------
  47. - **ROMFS (or RAM mapping) Only**:
  48. The current NXFLAT release will work only with either (1) NXFLAT
  49. executable modules residing on a ROMFS file system, or (2) executables
  50. residing on other file systems provided that CONFIG_FS_RAMMAP is
  51. defined. This limitation is because the loader depends on the capability
  52. to mmap() the code segment. See the NuttX User Guide for further information.
  53. NUTTX does not provide any general kind of file mapping capability.
  54. In fact, true file mapping is only possible with MCUs that provide an MMU1.
  55. Without an MMU, file system may support eXecution In Place (XIP) to mimic
  56. file mapping. Only the ROMFS file system supports that kind of XIP execution
  57. need by NXFLAT.
  58. It is also possible to simulate file mapping by allocating memory, copying
  59. the NXFLAT binary file into memory, and executing from the copy of the
  60. executable file in RAM. That capability can be enabled with the CONFIG_FS_RAMMAP
  61. configuration option. With that option enabled, NXFLAT will work that kind
  62. of file system but will require copying of all NXFLAT executables to RAM.
  63. - **GCC/ARM/Cortex-M3/4 Only**:
  64. At present, the NXFLAT toolchain is only available for ARM and Cortex-M3/4 (thumb2) targets.
  65. - **Read-Only Data in RAM**:
  66. With older GCC compilers (at least up to 4.3.3), read-only data must
  67. reside in RAM. In code generated by GCC, all data references are
  68. indexed by the PIC2 base register (that is usually R10 or sl for the
  69. ARM processors). The includes read-only data (.rodata). Embedded
  70. firmware developers normally like to keep .rodata in FLASH with
  71. the code sections. But because all data is referenced with the
  72. PIC base register, all of that data must lie in RAM. A NXFLAT
  73. change to work around this is under investigation3.
  74. Newer GCC compilers (at least from 4.6.3), read-only data is
  75. no long GOT-relative, but is now accessed PC-relative.
  76. With PC relative addressing, read-only data must reside in the I-Space.
  77. - **Globally Scoped Function Function Pointers**:
  78. If a function pointer is taken to a statically defined function,
  79. then (at least for ARM) GCC will generate a relocation that NXFLAT
  80. cannot handle. The workaround is make all such functions global in
  81. scope. A fix would involve a change to the GCC compiler as described
  82. in Appendix B.
  83. - **Special Handling of Callbacks**:
  84. Callbacks through function pointers must be avoided or, when
  85. then cannot be avoided, handled very specially. The reason
  86. for this is that the PIC module requires setting of a special
  87. value in a PIC register. If the callback does not set the PIC
  88. register, then the called back function will fail because it
  89. will be unable to correctly access data memory. Special logic
  90. is in place to handle some NuttX callbacks: Signal callbacks
  91. and watchdog timer callbacks. But other callbacks (like those
  92. used with qsort() must be avoided in an NXFLAT module.
  93. Supported Processors
  94. --------------------
  95. As mentioned `above <#limitations>`__, the NXFLAT toolchain is only
  96. available for ARM and Cortex-M3 (thumb2) targets. Furthermore, NXFLAT
  97. has only been tested on the Eagle-100 LMS6918 Cortex-M3 board.
  98. Development Status
  99. ------------------
  100. The initial release of NXFLAT was made in NuttX version 0.4.9. Testing
  101. is limited to the tests found under ``apps/examples/nxflat`` in the
  102. source tree. Some known problems exist (see the
  103. `TODO <https://github.com/apache/incubator-nuttx/blob/master/TODO>`__ list). As
  104. such, NXFLAT is currently in an early alpha phase.
  105. NXFLAT Toolchain
  106. ================
  107. Building the NXFLAT Toolchain
  108. -----------------------------
  109. In order to use NXFLAT, you must use special NXFLAT tools to create the
  110. binary module in FLASH. To do this, you will need to download the
  111. buildroot package and build it on your Linux or Cygwin machine. The
  112. buildroot can be downloaded from
  113. `Bitbucket.org <https://bitbucket.org/nuttx/buildroot/downloads>`__. You
  114. will need version 0.1.7 or later.
  115. Here are some general build instructions:
  116. - You must have already configured NuttX in ``<some-dir>/nuttx``
  117. - Download the buildroot package ``buildroot-0.x.y`` into
  118. ``<some-dir>``
  119. - Unpack ``<some-dir>/buildroot-0.x.y.tar.gz`` using a command like ``tar zxf buildroot-0.x.y``. This will result in a new directory like ``<some-dir>/buildroot-0.x.y``
  120. - Move this into position:
  121. ``mv <some-dir>/buildroot-0.x.y``\ <some-dir>/buildroot
  122. - ``cd``\ <some-dir>/buildroot
  123. - Copy a configuration file into the top buildroot directory:
  124. ``cp boards/abc-defconfig-x.y.z .config``.
  125. - Enable building of the NXFLAT tools by ``make menuconfig``. Select to
  126. build the NXFLAT toolchain with GCC (you can also select omit
  127. building GCC with and only build the NXFLAT toolchain for use with
  128. your own GCC toolchain).
  129. - Make the toolchain: ``make``. When the make completes, the tool
  130. binaries will be available under
  131. ``<some-dir>/buildroot/build_abc/staging_dir/bin``
  132. mknxflat
  133. --------
  134. ``mknxflat`` is used to build a *thunk* file. See below
  135. for usage::
  136. Usage: mknxflat [options] <bfd-filename>
  137. Where options are one or more of the following. Note
  138. that a space is always required between the option and
  139. any following arguments.
  140. -d Use dynamic symbol table. [symtab]
  141. -f <cmd-filename>
  142. Take next commands from <cmd-filename> [cmd-line]
  143. -o <out-filename>
  144. Output to [stdout]
  145. -v Verbose output [no output]
  146. -w Import weakly declared functions, i.e., weakly
  147. declared functions are expected to be provided at
  148. load-time [not imported]
  149. ldnxflat
  150. --------
  151. ``ldnxflat`` is use to link your object files along with the *thunk*
  152. file generated by ``mknxflat`` to produce the NXFLAT
  153. binary module. See below for usage::
  154. Usage: ldnxflat [options] <bfd-filename>
  155. Where options are one or more of the following. Note
  156. that a space is always required between the option and
  157. any following arguments.
  158. -d Use dynamic symbol table [Default: symtab]
  159. -e <entry-point>
  160. Entry point to module [Default: _start]
  161. -o <out-filename>
  162. Output to <out-filename> [Default: <bfd-filename>.nxf]
  163. -s <stack-size>
  164. Set stack size to <stack-size> [Default: 4096]
  165. -v Verbose output. If -v is applied twice, additional
  166. debug output is enabled [Default: no verbose output].
  167. mksymtab
  168. --------
  169. There is a small helper program available in ``nuttx/tools`` call
  170. ``mksymtab``. ``mksymtab`` can be sued to generate symbol tables for the
  171. NuttX base code that would be usable by the typical NXFLAT application.
  172. ``mksymtab`` builds symbol tables from common-separated value (CSV)
  173. files. In particular, the CSV files:
  174. #. ``nuttx/syscall/syscall.csv`` that describes the NuttX RTOS
  175. interface, and
  176. #. ``nuttx/libc/libc.csv`` that describes the NuttX C library interface.
  177. #. ``nuttx/libc/math.cvs`` that descirbes any math library.
  178. ::
  179. USAGE: ./mksymtab <cvs-file> <symtab-file>
  180. Where:
  181. <cvs-file> : The path to the input CSV file
  182. <symtab-file>: The path to the output symbol table file
  183. -d : Enable debug output
  184. For example,
  185. ::
  186. cd nuttx/tools
  187. cat ../syscall/syscall.csv ../libc/libc.csv | sort >tmp.csv
  188. ./mksymtab.exe tmp.csv tmp.c
  189. Making an NXFLAT module
  190. -----------------------
  191. Below is a snippet from an NXFLAT make file (simplified from NuttX
  192. `Hello,
  193. World! <https://github.com/apache/incubator-nuttx-apps/blob/master/examples/nxflat/tests/hello/Makefile>`__
  194. example).
  195. * Target 1:
  196. .. code-block:: makefile
  197. hello.r1: hello.o
  198. abc-nuttx-elf-ld -r -d -warn-common -o $@ $^
  199. * Target 2:
  200. .. code-block:: makefile
  201. hello-thunk.S: hello.r1
  202. mknxflat -o $@ $^
  203. * Target 3:
  204. .. code-block:: makefile
  205. hello.r2: hello-thunk.S
  206. abc-nuttx-elf-ld -r -d -warn-common -T binfmt/libnxflat/gnu-nxflat-gotoff.ld -no-check-sections -o $@ hello.o hello-thunk.o
  207. * Target 4:
  208. .. code-block:: makefile
  209. hello: hello.r2
  210. ldnxflat -e main -s 2048 -o $@ $^
  211. **Target 1**. This target links all of the module's object files
  212. together into one relocatable object. Two relocatable objects will be
  213. generated; this is the first one (hence, the suffic ``.r1``). In this
  214. "Hello, World!" case, there is only a single object file, ``hello.o``,
  215. that is linked to produce the ``hello.r1`` object.
  216. When the module's object files are compiled, some special compiler
  217. CFLAGS must be provided. First, the option ``-fpic`` is required to tell
  218. the compiler to generate position independent code (other GCC options,
  219. like ``-fno-jump-tables`` might also be desirable). For ARM compilers,
  220. two additional compilation options are required: ``-msingle-pic-base``
  221. and ``-mpic-register=r10``.
  222. **Target 2**. Given the ``hello.r1`` relocatable object, this target
  223. will invoke ```mknxflat`` <#mknxflat>`__ to make the *thunk* file,
  224. ``hello-thunk.S``. This *thunk* file contains all of the information
  225. needed to create the imported function list.
  226. **Target 3** This target is similar to **Target 1**. In this case, it
  227. will link together the module's object files (only ``hello.o`` here)
  228. along with the assembled *thunk* file, ``hello-thunk.o`` to create the
  229. second relocatable object, ``hello.r2``. The linker script,
  230. ``gnu-nxflat-gotoff.ld`` is required at this point to correctly position
  231. the sections. This linker script produces two segments: An *I-Space*
  232. (Instruction Space) segment containing mostly ``.text`` and a *D-Space*
  233. (Data Space) segment containing ``.got``, ``.data``, and ``.bss``
  234. sections. The I-Space section must be origined at address 0 (so that the
  235. segment's addresses are really offsets into the I-Space segment) and the
  236. D-Space section must also be origined at address 0 (so that segment's
  237. addresses are really offsets into the I-Space segment). The option
  238. ``-no-check-sections`` is required to prevent the linker from failing
  239. because these segments overlap.
  240. **NOTE:** There are two linker scripts located at ``binfmt/libnxflat/``.
  241. #. ``binfmt/libnxflat/gnu-nxflat-gotoff.ld``. Older versions of GCC
  242. (at least up to GCC 4.3.3), use GOT-relative addressing to access RO
  243. data. In that case, read-only data (.rodata) must reside in D-Space
  244. and this linker script should be used.
  245. #. ``binfmt/libnxflat/gnu-nxflat-pcrel.ld``. Newer versions of GCC
  246. (at least as of GCC 4.6.3), use PC-relative addressing to access RO
  247. data. In that case, read-only data (.rodata) must reside in I-Space
  248. and this linker script should be used.
  249. **Target 4**. Finally, this target will use the ``hello.r2`` relocatable
  250. object to create the final, NXFLAT module ``hello`` by executing
  251. ``ldnxflat``.
  252. **binfmt Registration** NXFLAT calls :c:func:`register_binfmt` to
  253. incorporate itself into the system.
  254. Appendix A: No GOT Operation
  255. ============================
  256. When GCC generate position independent code, new code sections will
  257. appear in your programs. One of these is the GOT (Global Offset Table)
  258. and, in ELF environments, another is the PLT (Procedure Lookup Table.
  259. For example, if your C code generated (ARM) assembly language like this
  260. without PIC:
  261. .. code-block:: asm
  262. ldr r1, .L0 /* Fetch the offset to 'x' */
  263. ldr r0, [r10, r1] /* Load the value of 'x' with PIC offset */
  264. /* ... */
  265. .L0: .word x /* Offset to 'x' */
  266. Then when PIC is enabled (say with the -fpic compiler option), it will
  267. generate code like this:
  268. .. code-block:: asm
  269. ldr r1, .L0 /* Fetch the offset to the GOT entry */
  270. ldr r1, [r10, r1] /* Fetch the (relocated) address of 'x' from the GOT */
  271. ldr r0, [r1, #0] /* Fetch the value of 'x' */
  272. /* ... */
  273. .L1 .word x(GOT) /* Offset to entry in the GOT */
  274. See
  275. `reference <http://xflat.sourceforge.net/NoMMUSharedLibs.html#shlibsgot>`__
  276. Notice that the generates an extra level of indirection through the GOT.
  277. This indirection is not needed by NXFLAT and only adds more RAM usage
  278. and execution time.
  279. NXFLAT (like `XFLAT <http://xflat.sourceforge.net/>`__) can work even
  280. better without the GOT. Patches against older version of GCC exist to
  281. eliminate the GOT indirections. Several are available
  282. `here <http://xflat.cvs.sourceforge.net/viewvc/xflat/xflat/gcc/>`__ if
  283. you are inspired to port them to a new GCC version.
  284. Appendix B: PIC Text Workaround
  285. ===============================
  286. There is a problem with the memory model in GCC that prevents it from
  287. being used as you need to use it in the NXFLAT context. The problem is
  288. that GCC PIC model assumes that the executable lies in a flat,
  289. contiguous (virtual) address space like::
  290. Virtual
  291. .text
  292. .got
  293. .data
  294. .bss
  295. It assumes that the PIC base register (usually r10 for ARM) points to
  296. the base of ``.text`` so that any address in ``.text``, ``.got``,
  297. ``.data``, ``.bss`` can be found with an offset from the same base
  298. address. But that is not the memory arrangement that we need in the XIP
  299. embedded environment. We need two memory regions, one in FLASH
  300. containing shared code and on per task in RAM containing task-specific
  301. data::
  302. Flash RAM
  303. .text .got
  304. .data
  305. .bss
  306. The PIC base register needs to point to the base of the ``.got`` and
  307. only addresses in the ``.got``, ``.data``, and ``.bss`` sections can be
  308. accessed as an offset from the PIC base register. See also this `XFLAT
  309. discussion <http://xflat.cvs.sourceforge.net/viewvc/*checkout*/xflat/xflat/gcc/README?revision=1.1.1.1>`__.
  310. Patches against older version of GCC exist to correct this GCC behavior.
  311. Several are available
  312. `here <http://xflat.cvs.sourceforge.net/viewvc/xflat/xflat/gcc/>`__ if
  313. you are inspired to port them to a new GCC version.