123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- .. _binfmt:
- =============
- Binary Loader
- =============
- The purpose of a *binary loader* is to load and
- execute modules in various *binary formats* that reside in a file
- system. Loading refers instantiating the binary module in some fashion,
- usually copy all or some of the binary module into memory and then
- linking the module with other components. In most architectures, it is
- the base FLASH code that is the primary component that the binary module
- must link with because that is where the RTOS and primary tasks reside.
- Program modules can then be executed after they have been loaded.
- **Binary Formats**. The binary loader provides generic support for
- different binary formats. It supports a *registration interface* that
- allows the number of support binary formats to be loaded at run time.
- Each binary format provides a common, interface for use by the binary
- loader. When asked to load a binary, the binary loader will query each
- registered binary format, providing it with the path of the binary
- object to be loaded. The binary loader will stop when first binary
- format the recognizes the binary object and successfully loads it or
- when all registered binary formats have attempt loading the binary
- object and failed.
- At present, the following binary formats are support by NuttX:
- - **ELF**. Standard ELF formatted files.
- - **NXFLAT**. NuttX NXFLAT formatted files. More information about the
- NXFLAT binary format can be found in the :ref:`NXFLAT
- documentation <nxflat>`.
- **Executables and Libraries** The generic binary loader logic does not
- care what it is that it being loaded. It could load an executable
- program or a library. There are no strict rules, but a library will tend
- to export symbols and a program will tend to import symbols: The program
- will use the symbols exported by the library. However, at this point in
- time, none of the supported binary formats support exporting of symbols.
- **binfmt**. In the NuttX source code, the short name ``binfmt`` is used
- to refer to the NuttX binary loader. This is the name of the directory
- containing the binary loader and the name of the header files and
- variables used by the binary loader.
- The name ``binfmt`` is the same name used by the Linux binary loader.
- However, the NuttX binary loader is an independent development and
- shares nothing with the Linux binary loader other the same name and the
- same basic functionality.
- Binary Loader Interface
- =======================
- Header Files
- ------------
- The interface to the binary loader is described in the header file
- ``include/nuttx/binfmt/binfmt.h``.
- A brief summary of the data structurs and interfaces prototyped in that
- header file are listed below.
- Data Structures
- ---------------
- When a binary format registers with the binary loader, it provides a
- pointer to a write-able instance of :c:struct:`binfmt_s`.
- .. c:struct:: binfmt_s
- .. code-block:: c
- struct binfmt_s
- {
- FAR struct binfmt_s *next; /* Supports a singly-linked list */
- int (*load)(FAR struct binary_s *bin); /* Verify and load binary into memory */
- };
- The ``load`` method is used to load the binary format into memory. It
- returns either ``OK`` (0) meaning that the binary object was loaded
- successfully, or a negated ``errno`` indicating why the object was not
- loaded.
- .. c:struct:: binary_s
- The type ``struct binary_s`` is use both to (1) describe the binary
- object to be loaded, and if successfully loaded, (2) to provide
- information about where and how the binary object was loaded. That
- structure is shown below:
- .. code-block:: c
- struct symtab_s;
- struct binary_s
- {
- /* Information provided to the loader to load and bind a module */
- FAR const char *filename; /* Full path to the binary to be loaded */
- FAR const char **argv; /* Argument list */
- FAR const struct symtab_s *exports; /* Table of exported symbols */
- int nexports; /* The number of symbols in exports[] */
- /* Information provided from the loader (if successful) describing the
- * resources used by the loaded module.
- */
- main_t entrypt; /* Entry point into a program module */
- FAR void *mapped; /* Memory-mapped, address space */
- FAR void *alloc[BINFMT_NALLOC]; /* Allocated address spaces */
- /* Constructors/destructors */
- #ifdef CONFIG_BINFMT_CONSTRUCTORS
- FAR binfmt_ctor_t *ctors; /* Pointer to a list of constructors */
- FAR binfmt_dtor_t *dtors; /* Pointer to a list of destructors */
- uint16_t nctors; /* Number of constructors in the list */
- uint16_t ndtors; /* Number of destructors in the list */
- #endif
- /* Address environment.
- *
- * addrenv - This is the handle created by up_addrenv_create() that can be
- * used to manage the tasks address space.
- */
- #ifdef CONFIG_ARCH_ADDRENV
- group_addrenv_t addrenv; /* Task group address environment */
- #endif
- size_t mapsize; /* Size of the mapped address region (needed for munmap) */
- /* Start-up information that is provided by the loader, but may be modified
- * by the caller between load_module() and exec_module() calls.
- */
- uint8_t priority; /* Task execution priority */
- size_t stacksize; /* Size of the stack in bytes (unallocated) */
- };
- Where the types ``binfmt_ctor_t`` and ``binfmt_dtor_t`` define the type
- of one C++ constructor or destructor:
- .. code-block:: c
- typedef FAR void (*binfmt_ctor_t)(void);
- typedef FAR void (*binfmt_dtor_t)(void);
- Function Interfaces
- -------------------
- Binary format management
- ~~~~~~~~~~~~~~~~~~~~~~~~
- .. c:function:: int register_binfmt(FAR struct binfmt_s *binfmt)
- Register a loader for a binary format.
- :return: This is a NuttX internal function so it follows the convention
- that 0 (OK) is returned on success and a negated errno is returned on
- failure.
- .. c:function:: int unregister_binfmt(FAR struct binfmt_s *binfmt)
- Register a loader for a binary format.
- :return:
- This is a NuttX internal function so it follows the convention
- that 0 (OK) is returned on success and a negated errno is returned on
- failure.
- Basic module management
- ~~~~~~~~~~~~~~~~~~~~~~~
- .. c:function:: int load_module(FAR struct binary_s *bin)
- Load a module into memory, bind it to an exported symbol take,
- and prep the module for execution.
- :param bin:
- The ``filename`` field will be used
- in order to locate the module to be loaded from the file system.
- The filename must be the full, absolute path to the file to be executed
- unless ``CONFIG_LIB_ENVPATH`` is defined. In that case, filename may be
- a relative path; a set of candidate absolute paths will be generated using
- the ``PATH`` environment variable and ``load_module()`` will attempt to load each
- file that is found at those absolute paths.
- :return:
- This is a NuttX internal function so it follows the convention that 0 (``OK``)
- is returned on success and a negated ``errno`` is returned on failure.
- .. c:function:: int unload_module(FAR struct binary_s *bin)
- Unload a (non-executing) module from memory. If the module has been started
- (via :c:func:`exec_module`) and has not exited, calling this will be fatal.
- However, this function must be called after the module exist. How this is
- done is up to your logic. Perhaps you register it to be called by :c:func:`on_exit`?
- :return:
- This is a NuttX internal function so it follows the convention that 0 (``OK``)
- is returned on success and a negated ``errno`` is returned on failure.
- .. c:function:: int exec_module(FAR const struct binary_s *bin);
- Execute a module that has been loaded into memory by :c:func:`load_module`.
- :return:
- This is a NuttX internal function so it follows the convention that 0 (``OK``)
- is returned on success and a negated ``errno`` is returned on failure.
- .. tip::
- The function :c:func:`exec` is a convenience function that wraps
- :c:func:`load_module` and :c:func:`exec_module` into one call.
- ``PATH`` traversal logic
- ~~~~~~~~~~~~~~~~~~~~~~~~
- .. c:function:: ENVPATH_HANDLE envpath_init(void);
- Initialize for the traversal of each value in the ``PATH`` variable. The
- usage is sequence is as follows:
- #. Call :c:func:`envpath_init` to initialize for the traversal.
- ``envpath_init()`` will return an opaque handle that can then be
- provided to :c:func:`envpath_next` and :c:func:`envpath_release`.
- #. Call :c:func:`envpath_next` repeatedly to examine every file that lies in
- the directories of the ``PATH`` variable.
- #. Call :c:func:`envpath_release` to free resources set aside by
- :c:func:`envpath_init`.
- :return:
- On success, :c:func:`envpath_init` return a non-``NULL``, opaque handle
- that may subsequently be used in calls to :c:func:`envpath_next` and
- :c:func:`envpath_release`. On error, a ``NULL`` handle value will be returned.
- The most likely cause of an error would be that there is no value
- associated with the ``PATH`` variable.
- .. c:function:: FAR char *envpath_next(ENVPATH_HANDLE handle, FAR const char *relpath)
- Traverse all possible values in the PATH variable in attempt to find the
- full path to an executable file when only a relative path is provided.
- :param handle: The handle value returned by :c:func:`envpath_init`.
- :param relpath: The relative path to the file to be found.
- :return:
- On success, a non-``NULL`` pointer to a null-terminated string is provided.
- This is the full path to a file that exists in the file system.
- This function will verify that the file exists (but will not verify that it is marked executable).
- .. note::
- The string pointer return in the success case points to allocated memory.
- This memory must be freed by the called by calling :c:func:`kmm_free`.
- ``NULL`` relpath from any absolute path in the ``PATH`` variable.
- In this case, there is no point in calling :c:func:`envpath_next` further;
- :c:func:`envpath_release` must be called to release resources set aside by
- :c:func:`envpath_init`.
- .. c:function:: void envpath_release(ENVPATH_HANDLE handle)
- Release all resources set aside by envpath_init when the
- handle value was created. The handle value is invalid on
- return from this function. Attempts to all :c:func:`envpath_next`
- or :c:func:`envpath_release` with such a stale handle will result
- in undefined (i.e., not good) behavior.
- :param handle: The handle value returned by :c:func:`envpath_init`.
- Symbol Tables
- =============
- **Symbol Tables**. Symbol tables are lists of name value mappings: The
- name is a string that identifies a symbol, and the value is an address
- in memory where the symbol of that name has been positioned. In most
- NuttX architectures symbol tables are required, as a minimum, in order
- to dynamically link the loaded binary object with the base code on
- FLASH. Since the binary object was separately built and separately
- linked, these symbols will appear as *undefined* symbols in the binary
- object. The binary loader will use the symbol table to look up the
- symbol by its name and to provide the address associated with the symbol
- as needed to perform the dynamic linking of the binary object to the
- base FLASH code.
- Symbol Table Header Files
- -------------------------
- The interface to the symbol table logic is described in the header file
- ``include/nuttx/binfmt/symtab.h``.
- A brief summary of the data structurs and interfaces prototyped in that
- header file are listed below.
- Symbol Table Data Structures
- ----------------------------
- .. c:struct:: symbtab_s
- Describes one entry in the symbol table.
- .. code-block:: c
- struct symtab_s
- {
- FAR const char *sym_name; /* A pointer to the symbol name string */
- FAR const void *sym_value; /* The value associated with the string */
- };
- A symbol table is a fixed size array of ``struct symtab_s``. The
- information is intentionally minimal and supports only:
- #. Function pointers as ``sym_values``. Of other kinds of values need to
- be supported, then typing information would also need to be included
- in the structure.
- #. Fixed size arrays. There is no explicit provisional for dynamically
- adding or removing entries from the symbol table (realloc might be
- used for that purpose if needed). The intention is to support only
- fixed size arrays completely defined at compilation or link time.
- Symbol Table Function Interfaces
- --------------------------------
- .. c:function:: FAR const struct symtab_s *symtab_findbyname(FAR const struct symtab_s *symtab, FAR const char *name, int nsyms);
- Find the symbol in the symbol table with the matching name.
- This version assumes that table is not ordered with respect to
- symbol name and, hence, access time will be linear with respect
- to ``nsyms``.
- :return:
- A reference to the symbol table entry if an entry with the matching name is found; NULL is returned if the entry is not found.
- .. c:function:: FAR const struct symtab_s *symtab_findorderedbyname(FAR const struct symtab_s *symtab, FAR const char *name, int nsyms);
- Find the symbol in the symbol table with the matching name.
- This version assumes that table ordered with respect to symbol name.
- :return:
- A reference to the symbol table entry if an entry with
- the matching name is found; NULL is returned if the entry is not found.
- .. c:function:: FAR const struct symtab_s *symtab_findbyvalue(FAR const struct symtab_s *symtab, FAR void *value, int nsyms);
- Find the symbol in the symbol table whose value closest
- (but not greater than), the provided value. This version assumes
- that table is not ordered with respect to symbol name and, hence,
- access time will be linear with respect to ``nsyms``.
- :return:
- A reference to the symbol table entry if an entry with the matching
- name is found; ``NULL`` is returned if the entry is not found.
- Configuration Variables
- =======================
- - ``CONFIG_BINFMT_DISABLE``: By default, support for loadable binary formats is built.
- This logic may be suppressed be defining this setting.
- - ``CONFIG_BINFMT_CONSTRUCTORS``: Build in support for C++ constructors in loaded modules.
- - ``CONFIG_SYMTAB_ORDEREDBYNAME``: Symbol tables are order by name (rather than value).
- Additional configuration options may be required for the each enabled
- binary format.
|