Integrate PATH traversal logic and binary format logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5441 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2012-12-17 14:43:31 +00:00
parent c2be20d319
commit a304329d46
7 changed files with 262 additions and 45 deletions
+2 -2
View File
@@ -3790,5 +3790,5 @@
the absolutes paths found in the current PATH environment variable the absolutes paths found in the current PATH environment variable
setting. This is untested and not yet hooked into the binfmt exec() setting. This is untested and not yet hooked into the binfmt exec()
logic on initial check-in logic on initial check-in
* binfmt/binfmt_loadmodule.c: load_module() will now traverse the PATH
variable to locate files from their relative path.
+130 -9
View File
@@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4"> <tr align="center" bgcolor="#e4e4e4">
<td> <td>
<h1><big><font color="#3c34ec"><i>NuttX Binary Loader</i></font></big></h1> <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> </td>
</tr> </tr>
</table> </table>
@@ -141,7 +141,7 @@ struct binary_s
{ {
/* Information provided to the loader to load and bind a module */ /* 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 char **argv; /* Argument list */
FAR const struct symtab_s *exports; /* Table of exported symbols */ FAR const struct symtab_s *exports; /* Table of exported symbols */
int nexports; /* The number of symbols in exports[] */ int nexports; /* The number of symbols in exports[] */
@@ -164,6 +164,14 @@ struct binary_s
}; };
</pre></ul> </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> <p>
Where the types <code>binfmt_ctor_t</code> and <code>binfmt_dtor_t</code> define the type of one C++ constructor or destructor: Where the types <code>binfmt_ctor_t</code> and <code>binfmt_dtor_t</code> define the type of one C++ constructor or destructor:
</p> </p>
@@ -175,15 +183,31 @@ typedef FAR void (*binfmt_dtor_t)(void);
<h2>2.3 <a name="binfmtfuncif">Binary Loader Function Interfaces</a></h2> <h2>2.3 <a name="binfmtfuncif">Binary Loader Function Interfaces</a></h2>
<h3>
Binary format management:
</h3>
<ul> <ul>
<a href="#register_binfmt">2.3.1 <code>register_binfmt()</code></a><br> <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="#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="#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_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.6 <code>exec()</code></a><br>
<a href="#exec">2.3.7 <code>exec()</code></a> <a href="#exec">2.3.7 <code>exec()</code></a>
</ul> </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> <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> </pre></ul>
<p><b>Description:</b></p> <p><b>Description:</b></p>
<ul> <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> </ul>
<p><b>Returned Value:</b></p> <p><b>Returned Value:</b></p>
<ul> <ul>
@@ -281,22 +313,111 @@ int exec(FAR const char *filename, FAR const char **argv,
</pre></ul> </pre></ul>
<p><b>Description:</b></p> <p><b>Description:</b></p>
<ul> <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> </ul>
<p><b>Input Parameters:</b></p> <p><b>Input Parameters:</b></p>
<ul> <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>argv</code>: Argument list.</li>
<li><code>exports</code>: Table of exported symbols.</li> <li><code>exports</code>: Table of exported symbols.</li>
<li><code>exports</code>: The number of symbols in exports.</li> <li><code>exports</code>: The number of symbols in exports.</li>
</ul> </ul>
<p><b>Returned Value:</b></p> <p><b>Returned Value:</b></p>
<ul> <ul>
This is an end-user function, so it follows the normal convention: This is an end-user function, so it follows the normal convention:
Returns 0 (<code>OK</code>) on success. Returns 0 (<code>OK</code>) on success.
On failure, it returns -1 (<code>ERROR</code>) with <code>errno</code> set appropriately. On failure, it returns -1 (<code>ERROR</code>) with <code>errno</code> set appropriately.
</ul> </ul>
<h3>2.3.8 <a name="exepath_init"><code>exepath_init()</code></a></h3>
<p><b>Function Prototype:</b></p>
<ul><pre>
#include &lt:nuttx/binfmt/binfmt.h&gt;
#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 &lt:nuttx/binfmt/binfmt.h&gt;
#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 &lt:nuttx/binfmt/binfmt.h&gt;
#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%"> <table width ="100%">
<tr bgcolor="#e4e4e4"> <tr bgcolor="#e4e4e4">
<td> <td>
+7 -1
View File
@@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec"> <h1><big><font color="#3c34ec">
<i>NuttX RTOS Porting Guide</i> <i>NuttX RTOS Porting Guide</i>
</font></big></h1> </font></big></h1>
<p>Last Updated: December 11, 2012</p> <p>Last Updated: December 17, 2012</p>
</td> </td>
</tr> </tr>
</table> </table>
@@ -4163,6 +4163,12 @@ build
<code>CONFIG_BINFMT_DISABLE</code>: By default, support for loadable binary formats is built. <code>CONFIG_BINFMT_DISABLE</code>: By default, support for loadable binary formats is built.
This logic may be suppressed be defining this setting. This logic may be suppressed be defining this setting.
</li> </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>&quot;/bin:/usr/bin:/sbin&quot;</code>
</li>
<li> <li>
<code>CONFIG_BINFMT_CONSTRUCTORS</code>: Build in support for C++ constructors in loaded modules. <code>CONFIG_BINFMT_CONSTRUCTORS</code>: Build in support for C++ constructors in loaded modules.
</li> </li>
+1 -1
View File
@@ -70,7 +70,7 @@
***********************************************************************/ ***********************************************************************/
/*********************************************************************** /***********************************************************************
* Name: load_module * Name: dump_module
* *
* Description: * Description:
* Load a module into memory and prep it for execution. * Load a module into memory and prep it for execution.
+3 -3
View File
@@ -85,7 +85,7 @@ struct exepath_s
* Initialize for the traversal of each value in the PATH variable. The * Initialize for the traversal of each value in the PATH variable. The
* usage is sequence is as follows: * 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 * will return an opaque handle that can then be provided to
* exepath_next() and exepath_release(). * exepath_next() and exepath_release().
* 2) Call exepath_next() repeatedly to examine every file that lies * 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(). * 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 * 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() * there is no point in calling exepath_next() further; exepath_release()
* must be called to release resources set aside by expath_init(). * 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 * Name: exepath_release
* *
* Description: * 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. * was created. The handle value is invalid on return from this function.
* Attempts to all exepath_next() or exepath_release() with such a 'stale' * Attempts to all exepath_next() or exepath_release() with such a 'stale'
* handle will result in undefined (i.e., not good) behavior. * handle will result in undefined (i.e., not good) behavior.
+99 -16
View File
@@ -43,6 +43,7 @@
#include <debug.h> #include <debug.h>
#include <errno.h> #include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/binfmt.h> #include <nuttx/binfmt/binfmt.h>
#include "binfmt_internal.h" #include "binfmt_internal.h"
@@ -66,36 +67,28 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Public Functions * Name: load_absmodule
****************************************************************************/
/****************************************************************************
* Name: load_module
* *
* Description: * Description:
* Load a module into memory, bind it to an exported symbol take, and * Load a module into memory, bind it to an exported symbol take, and
* prep the module for execution. * prep the module for execution. bin->filename is known to be an absolute
* path to the file to be loaded.
* *
* Returned Value: * Returned Value:
* This is an end-user function, so it follows the normal convention: * Zero (OK) is returned on success; a negated errno value is returned on
* Returns 0 (OK) on success. On failure, it returns -1 (ERROR) with * failure.
* errno set appropriately.
* *
****************************************************************************/ ****************************************************************************/
int load_module(FAR struct binary_s *bin) static int load_absmodule(FAR struct binary_s *bin)
{ {
FAR struct binfmt_s *binfmt; FAR struct binfmt_s *binfmt;
int ret = -ENOENT; int ret = -ENOENT;
#ifdef CONFIG_DEBUG
if (bin && bin->filename)
#endif
{
bdbg("Loading %s\n", bin->filename); bdbg("Loading %s\n", bin->filename);
/* Disabling pre-emption should be sufficient protection while /* Disabling pre-emption should be sufficient protection while accessing
* accessing the list of registered binary format handlers. * the list of registered binary format handlers.
*/ */
sched_lock(); sched_lock();
@@ -121,6 +114,95 @@ int load_module(FAR struct binary_s *bin)
} }
sched_unlock(); sched_unlock();
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: load_module
*
* Description:
* Load a module into memory, bind it to an exported symbol take, and
* prep the module for execution.
*
* Returned Value:
* This is an end-user function, so it follows the normal convention:
* Returns 0 (OK) on success. On failure, it returns -1 (ERROR) with
* errno set appropriately.
*
****************************************************************************/
int load_module(FAR struct binary_s *bin)
{
int ret = -EINVAL;
/* Verify that we were provided something to work with */
#ifdef CONFIG_DEBUG
if (bin && bin->filename)
#endif
{
/* Were we given a relative path? Or an absolute path to the file to
* be loaded.
*/
#ifdef CONFIG_BINFMT_EXEPATH
if (bin->filename[0] == '/')
{
FAR const char *relpath;
FAR char *fullpath;
EXEPATH_HANDLE handle;
/* Set aside the relative path */
relpath = bin->filename;
ret = -ENOENT;
/* Initialize to traverse the PATH variable */
handle = exepath_init();
if (handle)
{
/* Get the next absolute file path */
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.
*/
ret = load_absmodule(bin);
}
} }
/* This is an end-user function. Return failures via errno */ /* This is an end-user function. Return failures via errno */
@@ -131,6 +213,7 @@ int load_module(FAR struct binary_s *bin)
errno = -ret; errno = -ret;
return ERROR; return ERROR;
} }
return OK; return OK;
} }
+13 -6
View File
@@ -67,14 +67,21 @@ typedef FAR void *EXEPATH_HANDLE;
typedef FAR void (*binfmt_ctor_t)(void); typedef FAR void (*binfmt_ctor_t)(void);
typedef FAR void (*binfmt_dtor_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 symtab_s;
struct binary_s struct binary_s
{ {
/* Information provided to the loader to load and bind a module */ /* 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 char **argv; /* Argument list */
FAR const struct symtab_s *exports; /* Table of exported symbols */ FAR const struct symtab_s *exports; /* Table of exported symbols */
int nexports; /* The number of symbols in exports[] */ 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 * Initialize for the traversal of each value in the PATH variable. The
* usage is sequence is as follows: * 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 * will return an opaque handle that can then be provided to
* exepath_next() and exepath_release(). * exepath_next() and exepath_release().
* 2) Call exepath_next() repeatedly to examine every file that lies * 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); EXEPATH_HANDLE exepath_init(void);
#endif #endif
/**************************************************************************** /****************************************************************************
* Name: exepath_next * Name: exepath_next
* *
* Description: * Description:
@@ -274,7 +281,7 @@ EXEPATH_HANDLE exepath_init(void);
* memory. This memory must be freed by the called by calling kfree(). * 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 * 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() * there is no point in calling exepath_next() further; exepath_release()
* must be called to release resources set aside by expath_init(). * 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 * Name: exepath_release
* *
* Description: * 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. * was created. The handle value is invalid on return from this function.
* Attempts to all exepath_next() or exepath_release() with such a 'stale' * Attempts to all exepath_next() or exepath_release() with such a 'stale'
* handle will result in undefined (i.e., not good) behavior. * handle will result in undefined (i.e., not good) behavior.