diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index c61b28f69a..c932a1f2d6 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -3790,5 +3790,5 @@ the absolutes paths found in the current PATH environment variable setting. This is untested and not yet hooked into the binfmt exec() logic on initial check-in - - + * binfmt/binfmt_loadmodule.c: load_module() will now traverse the PATH + variable to locate files from their relative path. diff --git a/nuttx/Documentation/NuttXBinfmt.html b/nuttx/Documentation/NuttXBinfmt.html index 71c5b0a003..830a05caa3 100644 --- a/nuttx/Documentation/NuttXBinfmt.html +++ b/nuttx/Documentation/NuttXBinfmt.html @@ -8,7 +8,7 @@

NuttX Binary Loader

-

Last Updated: October 30, 2012

+

Last Updated: December 17, 2012

@@ -141,7 +141,7 @@ 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 *filename; /* Full path to the binary to be loaded1 */ FAR const char **argv; /* Argument list */ FAR const struct symtab_s *exports; /* Table of exported symbols */ int nexports; /* The number of symbols in exports[] */ @@ -164,6 +164,14 @@ struct binary_s }; + + +

+

Where the types binfmt_ctor_t and binfmt_dtor_t define the type of one C++ constructor or destructor:

@@ -175,15 +183,31 @@ typedef FAR void (*binfmt_dtor_t)(void);

2.3 Binary Loader Function Interfaces

+

+ Binary format management: +

+

+ Basic module management: +

+ +

+ PATH traversal logic: +

+

2.3.1 register_binfmt()

@@ -224,7 +248,15 @@ int load_module(FAR struct binary_s *bin);

Description:

Returned Value:

Description:

Input Parameters:

Returned Value:

+ +

2.3.8 exepath_init()

+

Function Prototype:

+ +

Description:

+ +

Input Parameters: None

+

Returned Value:

+ + +

2.3.9 exepath_next()

+

Function Prototype:

+ +

Description:

+ +

Input Parameters:

+ +

Returned Value:

+ + +

2.3.10- exepath_release()

+

Function Prototype:

+ +

Description:

+ +

Input Parameters:

+ +

Returned Value: None

diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index 0ed46cba16..5361a28665 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -12,7 +12,7 @@

NuttX RTOS Porting Guide

-

Last Updated: December 11, 2012

+

Last Updated: December 17, 2012

@@ -4163,6 +4163,12 @@ build CONFIG_BINFMT_DISABLE: By default, support for loadable binary formats is built. This logic may be suppressed be defining this setting. +
  • + CONFIG_BINFMT_EXEPATH: Use the contents of the PATH environment variable to locate executable files. Default: n +
  • +
  • + CONFIG_PATH_INITIAL: The initial value of the PATH variable. This is the colon-separated list of absolute paths. E.g., "/bin:/usr/bin:/sbin" +
  • CONFIG_BINFMT_CONSTRUCTORS: Build in support for C++ constructors in loaded modules.
  • diff --git a/nuttx/binfmt/binfmt_dumpmodule.c b/nuttx/binfmt/binfmt_dumpmodule.c index 40cbe4b213..cd52136b08 100644 --- a/nuttx/binfmt/binfmt_dumpmodule.c +++ b/nuttx/binfmt/binfmt_dumpmodule.c @@ -70,7 +70,7 @@ ***********************************************************************/ /*********************************************************************** - * Name: load_module + * Name: dump_module * * Description: * Load a module into memory and prep it for execution. diff --git a/nuttx/binfmt/binfmt_exepath.c b/nuttx/binfmt/binfmt_exepath.c index c81588975b..24903e26dc 100644 --- a/nuttx/binfmt/binfmt_exepath.c +++ b/nuttx/binfmt/binfmt_exepath.c @@ -85,7 +85,7 @@ struct exepath_s * Initialize for the traversal of each value in the PATH variable. The * usage is sequence is as follows: * - * 1) Call exepath_init() to initialze for the traversal. exepath_init() + * 1) Call exepath_init() to initialize for the traversal. exepath_init() * will return an opaque handle that can then be provided to * exepath_next() and exepath_release(). * 2) Call exepath_next() repeatedly to examine every file that lies @@ -163,7 +163,7 @@ EXEPATH_HANDLE exepath_init(void) * memory. This memory must be freed by the called by calling kfree(). * * NULL is returned if no path is found to any file with the provided - * 'relpath' from any absolute path in the file variable. In this case, + * 'relpath' from any absolute path in the PATH variable. In this case, * there is no point in calling exepath_next() further; exepath_release() * must be called to release resources set aside by expath_init(). * @@ -263,7 +263,7 @@ FAR char *exepath_next(EXEPATH_HANDLE handle, FAR const char *relpath) * Name: exepath_release * * Description: - * Release all resources set aside by exepath_release when the handle value + * Release all resources set aside by exepath_init() when the handle value * was created. The handle value is invalid on return from this function. * Attempts to all exepath_next() or exepath_release() with such a 'stale' * handle will result in undefined (i.e., not good) behavior. diff --git a/nuttx/binfmt/binfmt_loadmodule.c b/nuttx/binfmt/binfmt_loadmodule.c index e87075aa90..8a691edc73 100644 --- a/nuttx/binfmt/binfmt_loadmodule.c +++ b/nuttx/binfmt/binfmt_loadmodule.c @@ -43,6 +43,7 @@ #include #include +#include #include #include "binfmt_internal.h" @@ -65,6 +66,57 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: load_absmodule + * + * Description: + * Load a module into memory, bind it to an exported symbol take, and + * prep the module for execution. bin->filename is known to be an absolute + * path to the file to be loaded. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int load_absmodule(FAR struct binary_s *bin) +{ + FAR struct binfmt_s *binfmt; + int ret = -ENOENT; + + bdbg("Loading %s\n", bin->filename); + + /* Disabling pre-emption should be sufficient protection while accessing + * the list of registered binary format handlers. + */ + + sched_lock(); + + /* Traverse the list of registered binary format handlers. Stop + * when either (1) a handler recognized and loads the format, or + * (2) no handler recognizes the format. + */ + + for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next) + { + /* Use this handler to try to load the format */ + + ret = binfmt->load(bin); + if (ret == OK) + { + /* Successfully loaded -- break out with ret == 0 */ + + bvdbg("Successfully loaded module %s\n", bin->filename); + dump_module(bin); + break; + } + } + + sched_unlock(); + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -85,42 +137,72 @@ int load_module(FAR struct binary_s *bin) { - FAR struct binfmt_s *binfmt; - int ret = -ENOENT; + int ret = -EINVAL; + + /* Verify that we were provided something to work with */ #ifdef CONFIG_DEBUG if (bin && bin->filename) #endif { - bdbg("Loading %s\n", bin->filename); - - /* Disabling pre-emption should be sufficient protection while - * accessing the list of registered binary format handlers. + /* Were we given a relative path? Or an absolute path to the file to + * be loaded. */ - sched_lock(); +#ifdef CONFIG_BINFMT_EXEPATH + if (bin->filename[0] == '/') + { + FAR const char *relpath; + FAR char *fullpath; + EXEPATH_HANDLE handle; - /* Traverse the list of registered binary format handlers. Stop - * when either (1) a handler recognized and loads the format, or - * (2) no handler recognizes the format. - */ + /* Set aside the relative path */ - for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next) - { - /* Use this handler to try to load the format */ + relpath = bin->filename; + ret = -ENOENT; + + /* Initialize to traverse the PATH variable */ - ret = binfmt->load(bin); - if (ret == OK) + handle = exepath_init(); + if (handle) { - /* Successfully loaded -- break out with ret == 0 */ + /* Get the next absolute file path */ - bvdbg("Successfully loaded module %s\n", bin->filename); - dump_module(bin); - break; + while ((fullpath = exepath_next(handle, relpath))) + { + /* Try to load the file at this path */ + + bin->filename = fullpath; + ret = load_absmodule(bin); + + /* Free the allocated fullpath */ + + kfree(fullpath); + + /* Break out of the loop with ret == OK on success */ + + if (ret == OK) + { + break; + } + } } + + /* Restore the relative path. This is not needed for anything + * but debug output after the file has been loaded. + */ + + bin->filename = relpath; } + else +#endif + { + /* We already have the one and only absolute path to the file to + * be loaded. + */ - sched_unlock(); + ret = load_absmodule(bin); + } } /* This is an end-user function. Return failures via errno */ @@ -131,6 +213,7 @@ int load_module(FAR struct binary_s *bin) errno = -ret; return ERROR; } + return OK; } diff --git a/nuttx/include/nuttx/binfmt/binfmt.h b/nuttx/include/nuttx/binfmt/binfmt.h index 80c0e7c7b7..200823bb84 100644 --- a/nuttx/include/nuttx/binfmt/binfmt.h +++ b/nuttx/include/nuttx/binfmt/binfmt.h @@ -67,14 +67,21 @@ typedef FAR void *EXEPATH_HANDLE; typedef FAR void (*binfmt_ctor_t)(void); typedef FAR void (*binfmt_dtor_t)(void); -/* This describes the file to be loaded */ +/* This describes the file to be loaded. + * + * NOTE: The 'filename' must be the full, absolute path to the file to be + * executed unless CONFIG_BINFMT_EXEPATH 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. + */ 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 *filename; /* Full path to the binary to be loaded (See NOTE above) */ FAR const char **argv; /* Argument list */ FAR const struct symtab_s *exports; /* Table of exported symbols */ int nexports; /* The number of symbols in exports[] */ @@ -229,7 +236,7 @@ int exec(FAR const char *filename, FAR const char **argv, * Initialize for the traversal of each value in the PATH variable. The * usage is sequence is as follows: * - * 1) Call exepath_init() to initialze for the traversal. exepath_init() + * 1) Call exepath_init() to initialize for the traversal. exepath_init() * will return an opaque handle that can then be provided to * exepath_next() and exepath_release(). * 2) Call exepath_next() repeatedly to examine every file that lies @@ -252,7 +259,7 @@ int exec(FAR const char *filename, FAR const char **argv, EXEPATH_HANDLE exepath_init(void); #endif - /**************************************************************************** +/**************************************************************************** * Name: exepath_next * * Description: @@ -274,7 +281,7 @@ EXEPATH_HANDLE exepath_init(void); * memory. This memory must be freed by the called by calling kfree(). * * NULL is returned if no path is found to any file with the provided - * 'relpath' from any absolute path in the file variable. In this case, + * 'relpath' from any absolute path in the PATH variable. In this case, * there is no point in calling exepath_next() further; exepath_release() * must be called to release resources set aside by expath_init(). * @@ -288,7 +295,7 @@ FAR char *exepath_next(EXEPATH_HANDLE handle, FAR const char *relpath); * Name: exepath_release * * Description: - * Release all resources set aside by exepath_release when the handle value + * Release all resources set aside by exepath_init() when the handle value * was created. The handle value is invalid on return from this function. * Attempts to all exepath_next() or exepath_release() with such a 'stale' * handle will result in undefined (i.e., not good) behavior.