diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-12-17 14:43:31 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-12-17 14:43:31 +0000 |
commit | fe4bf6f555a1a453c16a7c671cef3625902d2991 (patch) | |
tree | 6b0d22d8b656818e6ec7414e329f73a9f1d7adbf /nuttx | |
parent | 14a896b20509dfc4657778fa21246cffb2ec2b55 (diff) | |
download | px4-firmware-fe4bf6f555a1a453c16a7c671cef3625902d2991.tar.gz px4-firmware-fe4bf6f555a1a453c16a7c671cef3625902d2991.tar.bz2 px4-firmware-fe4bf6f555a1a453c16a7c671cef3625902d2991.zip |
Integrate PATH traversal logic and binary format logic
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5441 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r-- | nuttx/ChangeLog | 4 | ||||
-rw-r--r-- | nuttx/Documentation/NuttXBinfmt.html | 139 | ||||
-rw-r--r-- | nuttx/Documentation/NuttxPortingGuide.html | 8 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_dumpmodule.c | 2 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_exepath.c | 6 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_loadmodule.c | 125 | ||||
-rw-r--r-- | nuttx/include/nuttx/binfmt/binfmt.h | 19 |
7 files changed, 260 insertions, 43 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index c61b28f69..c932a1f2d 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 71c5b0a00..830a05caa 100644 --- a/nuttx/Documentation/NuttXBinfmt.html +++ b/nuttx/Documentation/NuttXBinfmt.html @@ -8,7 +8,7 @@ <tr align="center" bgcolor="#e4e4e4"> <td> <h1><big><font color="#3c34ec"><i>NuttX Binary Loader</i></font></big></h1> - <p>Last Updated: October 30, 2012</p> + <p>Last Updated: December 17, 2012</p> </td> </tr> </table> @@ -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 loaded<sup>1</sup> */ 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 }; </pre></ul> +<ul><p><small> + <sup>1</sup>The <code>filename</code> must be the full, absolute path to the file to be executed unless <code>CONFIG_BINFMT_EXEPATH</code> is defined. + In that case, <code>filename</code> may be a relative path; + a set of candidate absolute paths will be generated using the <code>PATH</code> environment variable and <a href="#load_module"><code>load_module()</code></a> will attempt to load each file that is found at those absolute paths. +</small></p></ul> + +</p> + <p> Where the types <code>binfmt_ctor_t</code> and <code>binfmt_dtor_t</code> define the type of one C++ constructor or destructor: </p> @@ -175,15 +183,31 @@ typedef FAR void (*binfmt_dtor_t)(void); <h2>2.3 <a name="binfmtfuncif">Binary Loader Function Interfaces</a></h2> +<h3> + Binary format management: +</h3> <ul> <a href="#register_binfmt">2.3.1 <code>register_binfmt()</code></a><br> - <a href="#unregister_binfmt">2.3.2 <code>unregister_binfmt()</code></a><br> + <a href="#unregister_binfmt">2.3.2 <code>unregister_binfmt()</code></a> +</ul> +<h3> + Basic module management: +</h3> +<ul> <a href="#load_module">2.3.3 <code>load_module()</code></a><br> <a href="#unload_module">2.3.4 <code>unload_module()</code></a><br> <a href="#exec_module">2.3.5 <code>exec_module()</code></a><br> <a href="#exec">2.3.6 <code>exec()</code></a><br> <a href="#exec">2.3.7 <code>exec()</code></a> </ul> +<h3> + <code>PATH</code> traversal logic: +</h3> +<ul> + <a href="#exepath_init">2.3.8 <code>exepath_init()</code></a><br> + <a href="#exepath_next">2.3.9 <code>exepath_next()</code></a><br> + <a href="#exepath_release">2.3.10 <code>exepath_release()</code></a> +</ul> <h3>2.3.1 <a name="register_binfmt"><code>register_binfmt()</code></a></h3> @@ -224,7 +248,15 @@ int load_module(FAR struct binary_s *bin); </pre></ul> <p><b>Description:</b></p> <ul> -Load a module into memory, bind it to an exported symbol take, and prep the module for execution. + <p> + Load a module into memory, bind it to an exported symbol take, and prep the module for execution. + </p> + <p> + <code>load_module()</code> will use the <code>filename</code> field in the <a href="#binfmtdata"><code>struct binary_s</code></a> in order to locate the module to be loaded from the file system. + The <code>filename</code> must be the full, absolute path to the file to be executed unless <code>CONFIG_BINFMT_EXEPATH</code> is defined. + In that case, <code>filename</code> may be a relative path; + a set of candidate absolute paths will be generated using the <code>PATH</code> environment variable and <code>load_module()</code> will attempt to load each file that is found at those absolute paths. + </p> </ul> <p><b>Returned Value:</b></p> <ul> @@ -281,21 +313,110 @@ int exec(FAR const char *filename, FAR const char **argv, </pre></ul> <p><b>Description:</b></p> <ul> -This is a convenience function that wraps <code>load_</code> and <code>exec_module()</code> into one call. + This is a convenience function that wraps <code>load_</code> and <code>exec_module()</code> into one call. </ul> <p><b>Input Parameters:</b></p> <ul> - <li><code>filename</code>: Fulll path to the binary to be loaded.</li> + <li><code>filename</code>: Full path to the binary to be loaded.</li> <li><code>argv</code>: Argument list.</li> <li><code>exports</code>: Table of exported symbols.</li> <li><code>exports</code>: The number of symbols in exports.</li> </ul> <p><b>Returned Value:</b></p> <ul> -This is an end-user function, so it follows the normal convention: -Returns 0 (<code>OK</code>) on success. -On failure, it returns -1 (<code>ERROR</code>) with <code>errno</code> set appropriately. + This is an end-user function, so it follows the normal convention: + Returns 0 (<code>OK</code>) on success. + On failure, it returns -1 (<code>ERROR</code>) with <code>errno</code> set appropriately. +</ul> + +<h3>2.3.8 <a name="exepath_init"><code>exepath_init()</code></a></h3> +<p><b>Function Prototype:</b></p> +<ul><pre> +#include <:nuttx/binfmt/binfmt.h> +#ifdef CONFIG_BINFMT_EXEPATH +EXEPATH_HANDLE exepath_init(void); +#endif +</pre></ul> +<p><b>Description:</b></p> +<ul> + <p> + Initialize for the traversal of each value in the <code>PATH</code> variable. + The usage is sequence is as follows: + </p> + <ol> + <li> + Call <code>exepath_init()</code> to initialize for the traversal. + <code>exepath_init()</code> will return an opaque handle that can then be provided to <code>exepath_next()</code> and <code>exepath_release()</code>. + </li> + <li> + Call <code>exepath_next()</code> repeatedly to examine every file that lies in the directories of the <code>PATH</code> variable. + </li> + <li> + Call <code>exepath_release()</code> to free resources set aside by <code>exepath_init()</code>. + </li> + </ol> +</ul> +<p><b>Input Parameters:</b> <i>None</i></p> +<p><b>Returned Value:</b></p> +<ul> + On success, <code>exepath_init()</code> return a non-<code>NULL</code>, opaque handle that may subsequently be used in calls to <code>exepath_next()</code> and <code>exepath_release()</code>. + On error, a <code>NULL</code> handle value will be returned. + The most likely cause of an error would be that the there is no value associated with the <code>PATH</code> variable. +</ul> + +<h3>2.3.9 <a name="exepath_next"><code>exepath_next()</code></a></h3> +<p><b>Function Prototype:</b></p> +<ul><pre> +#include <:nuttx/binfmt/binfmt.h> +#ifdef CONFIG_BINFMT_EXEPATH +FAR char *exepath_next(EXEPATH_HANDLE handle, FAR const char *relpath); +#endif +</pre></ul> +<p><b>Description:</b></p> +<ul> + Traverse all possible values in the <code>PATH</code> variable in attempt to find the full path to an executable file when only a relative path is provided. +</ul> +<p><b>Input Parameters:</b></p> +<ul> + <li><code>handle</code>: The handle value returned by <code>exepath_init()</code>.</li> + <li><code>relpath</code>: The relative path to the file to be found.</li> +</ul> +<p><b>Returned Value:</b></p> +<ul> + <p> + On success, a non-<code>NULL</code> 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). + </p> + <p> + NOTE: The string pointer return in the success case points to allocated memory. + This memory must be freed by the called by calling <code>kfree()</code>. + </p> + <p> + <code>NULL</code is returned if no path is found to any file with the provided <code>relpath</colde> from any absolute path in the <code>PATH</code> variable. + In this case, there is no point in calling <code>exepath_next()</code> further; <code>exepath_release()</code> must be called to release resources set aside by <code>expath_init()</code>. + </p> +</ul> + +<h3>2.3.10- <a name="exepath_release"><code>exepath_release()</code></a></h3> +<p><b>Function Prototype:</b></p> +<ul><pre> +#include <:nuttx/binfmt/binfmt.h> +#ifdef CONFIG_BINFMT_EXEPATH +void exepath_release(EXEPATH_HANDLE handle); +#endif +</pre></ul> +<p><b>Description:</b></p> +<ul> + Release all resources set aside by <code>exepath_init</code> when the handle value was created. + The handle value is invalid on return from this function. + Attempts to all <code>exepath_next()</code> or <code>exepath_release()</code> with such a <i>stale</i> handle will result in undefined (i.e., not good) behavior. +</ul> +<p><b>Input Parameters:</b></p> +<ul> + <li><code>handle</code>: The handle value returned by <code>exepath_init()</code>.</li> </ul> +<p><b>Returned Value:</b> <i>None</i></p> <table width ="100%"> <tr bgcolor="#e4e4e4"> diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index 0ed46cba1..5361a2866 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -12,7 +12,7 @@ <h1><big><font color="#3c34ec"> <i>NuttX RTOS Porting Guide</i> </font></big></h1> - <p>Last Updated: December 11, 2012</p> + <p>Last Updated: December 17, 2012</p> </td> </tr> </table> @@ -4164,6 +4164,12 @@ build This logic may be suppressed be defining this setting. </li> <li> + <code>CONFIG_BINFMT_EXEPATH</code>: Use the contents of the <code>PATH</code> environment variable to locate executable files. Default: n + </li> + <li> + <code>CONFIG_PATH_INITIAL</code>: The initial value of the <code>PATH</code> variable. This is the colon-separated list of absolute paths. E.g., <code>"/bin:/usr/bin:/sbin"</code> + </li> + <li> <code>CONFIG_BINFMT_CONSTRUCTORS</code>: Build in support for C++ constructors in loaded modules. </li> <li> diff --git a/nuttx/binfmt/binfmt_dumpmodule.c b/nuttx/binfmt/binfmt_dumpmodule.c index 40cbe4b21..cd52136b0 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 c81588975..24903e26d 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 e87075aa9..8a691edc7 100644 --- a/nuttx/binfmt/binfmt_loadmodule.c +++ b/nuttx/binfmt/binfmt_loadmodule.c @@ -43,6 +43,7 @@ #include <debug.h> #include <errno.h> +#include <nuttx/kmalloc.h> #include <nuttx/binfmt/binfmt.h> #include "binfmt_internal.h" @@ -66,6 +67,57 @@ ****************************************************************************/ /**************************************************************************** + * 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 80c0e7c7b..200823bb8 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. |