| {{+bindTo:partials.standard_nacl_article}} |
| |
| <b><font color="#cc0000"> |
| NOTE: |
| Deprecation of the technologies described here has been announced |
| for platforms other than ChromeOS.<br/> |
| Please visit our |
| <a href="/native-client/migration">migration guide</a> |
| for details. |
| </font></b> |
| <hr/><section id="dynamic-linking-and-loading-with-glibc"> |
| <h1 id="dynamic-linking-and-loading-with-glibc">Dynamic Linking and Loading with glibc</h1> |
| <div class="contents local" id="contents" style="display: none"> |
| <ul class="small-gap"> |
| <li><a class="reference internal" href="#c-standard-libraries-glibc-and-newlib" id="id1">C standard libraries: glibc and newlib</a></li> |
| <li><a class="reference internal" href="#sdk-toolchains" id="id2">SDK toolchains</a></li> |
| <li><p class="first"><a class="reference internal" href="#specifying-and-delivering-shared-libraries" id="id3">Specifying and delivering shared libraries</a></p> |
| <ul class="small-gap"> |
| <li><a class="reference internal" href="#building-a-dynamically-linked-application" id="id4">Building a dynamically linked application</a></li> |
| <li><a class="reference internal" href="#generating-a-native-client-manifest-file-for-a-dynamically-linked-application" id="id5">Generating a Native Client manifest file for a dynamically linked application</a></li> |
| <li><a class="reference internal" href="#deploying-a-dynamically-linked-application" id="id6">Deploying a dynamically linked application</a></li> |
| <li><a class="reference internal" href="#opening-a-shared-library-at-runtime" id="id7">Opening a shared library at runtime</a></li> |
| <li><a class="reference internal" href="#troubleshooting" id="id8">Troubleshooting</a></li> |
| </ul> |
| </li> |
| </ul> |
| |
| </div><aside class="caution"> |
| Portable Native Client currently only supports static linking, and the |
| only C library available for it is newlib. This page is only valid for |
| Native Client, though PNaCl will eventually support some form of |
| dynamic linking. |
| </aside> |
| <p>This document describes how to create and deploy dynamically linked and loaded |
| applications with the glibc library in the Native Client SDK. Before reading |
| this document, we recommend reading <a class="reference internal" href="/native-client/devguide/devcycle/building.html"><em>Building Native Client Modules</em></a></p> |
| <h2 id="c-standard-libraries-glibc-and-newlib"><span id="c-libraries"></span>C standard libraries: glibc and newlib</h2> |
| <p>The Native Client SDK comes with two C standard libraries — glibc and |
| newlib. These libraries are described in the table below.</p> |
| <table border="1" class="docutils"> |
| <colgroup> |
| </colgroup> |
| <thead valign="bottom"> |
| <tr class="row-odd"><th class="head">Library</th> |
| <th class="head">Linking</th> |
| <th class="head">License</th> |
| </tr> |
| </thead> |
| <tbody valign="top"> |
| <tr class="row-even"><td><dl class="first last docutils"> |
| <dt>glibc</dt> |
| <dd>The GNU implementation of the <a class="reference external" href="http://en.wikipedia.org/wiki/POSIX">POSIX</a> standard |
| runtime library for the C programming language. |
| Designed for portability and performance, glibc is |
| one of the most popular implementations of the C |
| library. It is comprised of a set of interdependent |
| libraries including libc, libpthreads, libdl, and |
| others. For documentation, FAQs, and additional |
| information about glibc, see <a class="reference external" href="http://www.gnu.org/software/libc/index.html">GLIBC</a>.</dd> |
| </dl> |
| </td> |
| <td>dynamic |
| or static</td> |
| <td>GNU Lesser |
| General |
| Public |
| License |
| (LGPL)</td> |
| </tr> |
| <tr class="row-odd"><td><dl class="first last docutils"> |
| <dt>newlib</dt> |
| <dd>newlib is a C library intended for use in embedded |
| systems. Like glibc, newlib is a conglomeration of |
| several libraries. It is available for use under |
| BSD-type free software licenses, which generally |
| makes it more suitable to link statically in |
| commercial, closed-source applications. For |
| documentation, FAQs, and additional information |
| about newlib, see <a class="reference external" href="http://sourceware.org/newlib/">newlib</a>.</dd> |
| </dl> |
| </td> |
| <td>static</td> |
| <td>Berkeley |
| Software |
| Distribution |
| (BSD) type |
| free |
| software |
| licenses</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>For proprietary (closed-source) applications, your options are to either |
| statically link to newlib, or dynamically link to glibc. We recommend |
| dynamically linking to glibc, for a couple of reasons:</p> |
| <ul class="small-gap"> |
| <li>The glibc library is widely distributed (it’s included in Linux |
| distributions), and as such it’s mature, hardened, and feature-rich. Your |
| code is more likely to compile out-of-the-box with glibc.</li> |
| <li>Dynamic loading can provide a big performance benefit for your application if |
| you can structure the application to defer loading of code that’s not needed |
| for initial interaction with the user. It takes some work to put such code in |
| shared libraries and to load the libraries at runtime, but the payoff is |
| usually worth it. In future releases, Chrome may also support caching of |
| common dynamically linked libraries such as libc.so between applications. |
| This could significantly reduce download size and provide a further potential |
| performance benefit (for example, the hello_world example would only require |
| downloading a .nexe file that’s on the order of 30KB, rather than a .nexe |
| file and several libraries, which are on the order of 1.5MB).</li> |
| </ul> |
| <p>Native Client support for dynamic linking and loading is based on glibc. Thus, |
| <strong>if your Native Client application must dynamically link and load code (e.g., |
| due to licensing considerations), we recommend that you use the glibc |
| library.</strong></p> |
| <aside class="note"> |
| <p><strong>Disclaimer:</strong></p> |
| <ul class="small-gap"> |
| <li><strong>None of the above constitutes legal advice, or a description of the legal |
| obligations you need to fulfill in order to be compliant with the LGPL or |
| newlib licenses. The above description is only a technical explanation of |
| the differences between newlib and glibc, and the choice you must make |
| between the two libraries.</strong></li> |
| </ul> |
| |
| </aside> |
| <aside class="note"> |
| <p><strong>Notes:</strong></p> |
| <ul class="small-gap"> |
| <li>Static linking with glibc is rarely used. Use this feature with caution.</li> |
| <li>The standard C++ runtime in Native Client is provided by libstdc++; this |
| library is independent from and layered on top of glibc. Because of |
| licensing restrictions, libstdc++ must be statically linked for commercial |
| uses, even if the rest of an application is dynamically linked.</li> |
| </ul> |
| |
| </aside> |
| <h2 id="sdk-toolchains">SDK toolchains</h2> |
| <p>The Native Client SDK contains multiple toolchains, which are differentiated by |
| <a class="reference internal" href="/native-client/devguide/devcycle/building.html#target-architectures"><em>target architecture</em></a> and C library:</p> |
| <table border="1" class="docutils"> |
| <colgroup> |
| </colgroup> |
| <thead valign="bottom"> |
| <tr class="row-odd"><th class="head">Target architecture</th> |
| <th class="head">C library</th> |
| <th class="head">Toolchain directory</th> |
| </tr> |
| </thead> |
| <tbody valign="top"> |
| <tr class="row-even"><td>x86</td> |
| <td>glibc</td> |
| <td>toolchain/<platform>_x86_glibc</td> |
| </tr> |
| <tr class="row-odd"><td>ARM</td> |
| <td>glibc</td> |
| <td>toolchain/<platform>_arm_glibc</td> |
| </tr> |
| <tr class="row-even"><td>x86</td> |
| <td>newlib</td> |
| <td>toolchain/<platform>_pnacl</td> |
| </tr> |
| <tr class="row-odd"><td>ARM</td> |
| <td>newlib</td> |
| <td>toolchain/<platform>_pnacl</td> |
| </tr> |
| <tr class="row-even"><td>PNaCl</td> |
| <td>newlib</td> |
| <td>toolchain/<platform>_pnacl</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>In the directories listed above, <platform> is the platform of your development |
| machine (i.e., win, mac, or linux). For example, in the Windows SDK, the x86 |
| toolchain that uses glibc is in <code>toolchain/win_x86_glibc</code>.</p> |
| <aside class="note"> |
| <strong>Note:</strong> The PNaCl toolchain is currently restricted to newlib. |
| </aside> |
| <p>To use the glibc library and dynamic linking in your application, you <strong>must</strong> |
| use a glibc toolchain. Note that you must build all code in your application |
| with one toolchain. Code from multiple toolchains cannot be mixed.</p> |
| <h2 id="specifying-and-delivering-shared-libraries">Specifying and delivering shared libraries</h2> |
| <p>One significant difference between newlib and glibc applications is that glibc |
| applications must explicitly list and deploy the shared libraries that they |
| use.</p> |
| <p>In a desktop environment, when the user launches a dynamically linked |
| application, the operating system’s program loader determines the set of |
| libraries the application requires by reading explicit inter-module |
| dependencies from executable file headers, and loads the required libraries |
| into the address space of the application process. Typically the required |
| libraries will have been installed on the system as a part of the application’s |
| installation process. Often the desktop application developer doesn’t know or |
| think about the libraries that are required by an application, as those details |
| are taken care of by the user’s operating system.</p> |
| <p>In the Native Client sandbox, dynamic linking can’t rely in the same way on the |
| operating system or the local file system. Instead, the application developer |
| must identify the set of libraries that are required by an application, list |
| those libraries in a Native Client <a class="reference internal" href="/native-client/devguide/coding/application-structure.html#manifest-file"><em>manifest file</em></a>, and |
| deploy the libraries along with the application. Instructions for how to build |
| a dynamically linked Native Client application, generate a Native Client |
| manifest (.nmf) file, and deploy an application are provided below.</p> |
| <h3 id="building-a-dynamically-linked-application">Building a dynamically linked application</h3> |
| <p>Applications built with the glibc toolchain will by dynamically linked by |
| default. Application that load shared libraries at runtime using <code>dlopen()</code> |
| must link with the libdl library (<code>-ldl</code>).</p> |
| <p>Like other gcc-based toolchains building a dynamic library for NaCl is normally |
| done by linking with the <code>-shared</code> flag and compiling with the <code>-fPIC</code> flag. |
| The SDK build system will do this automatically when the <code>SO_RULE</code> Makefile |
| rule is used.</p> |
| <p>The Native Client SDK includes an example that demonstrates how to build a |
| shared library, and how to use the <code>dlopen()</code> interface to load that library |
| at runtime (after the application is already running). Many applications load |
| and link shared libraries at launch rather than at runtime, and hence do not |
| use the <code>dlopen()</code> interface. The SDK example is nevertheless instructive, as |
| it demonstrates how to build Native Client modules (.nexe files) and shared |
| libraries (.so files) with the x86 glibc toolchain, and how to generate a |
| Native Client manifest file for glibc applications.</p> |
| <p>The SDK example, located in <code>examples/tutorial/dlopen</code>, includes three C++ |
| files:</p> |
| <dl class="docutils"> |
| <dt>eightball.cc</dt> |
| <dd>This file implements the function <code>Magic8Ball()</code>, which is used to provide |
| whimsical answers to user questions. This file is compiled into a shared |
| library called <code>libeightball.so</code>. This library gets included in the |
| .nmf file and is therefore directly loadable with <code>dlopen()</code>.</dd> |
| <dt>reverse.cc</dt> |
| <dd>This file implements the function <code>Reverse()</code>, which returns reversed |
| copies of strings that are passed to it. This file is compiled into a shared |
| library called <code>libreverse.so</code>. This library is <strong>not</strong> included in the |
| .nmf file and is loaded via an http mount using the <a class="reference internal" href="/native-client/devguide/coding/nacl_io.html#nacl-io"><em>nacl_io library</em></a>.</dd> |
| <dt>dlopen.cc</dt> |
| <dd>This file implements the Native Client module, which loads the two shared |
| libraries and handles communcation with with JavaScript. The file is compiled |
| into a Native Client executable (.nexe).</dd> |
| </dl> |
| <p>Run <code>make</code> in the dlopen directory to see the commands the Makefile executes |
| to build x86 32-bit and 64-bit .nexe and .so files, and to generate a .nmf |
| file. These commands are described below.</p> |
| <aside class="note"> |
| <strong>Note:</strong> The Makefiles for most of the examples in the SDK build the |
| examples using multiple toolchains (x86 newlib, x86 glibc, ARM newlib, ARM |
| glibc, and PNaCl). With a few exceptions (listed in the <a class="reference internal" href="/native-client/sdk/release-notes.html#sdk-release-notes"><em>Release Notes</em></a>), running “make” in each example’s directory builds |
| multiple versions of the example using the SDK toolchains. The dlopen example |
| is one of those exceptions – it is only built with the x86 glibc toolchain, |
| as that is currently the only toolchain that supports glibc and thus dynamic |
| linking and loading. Take a look at the example Makefiles and the generated |
| .nmf files for details on how to build dynamically linked applications. |
| </aside> |
| <h3 id="generating-a-native-client-manifest-file-for-a-dynamically-linked-application"><span id="dynamic-loading-manifest"></span>Generating a Native Client manifest file for a dynamically linked application</h3> |
| <p>The Native Client manifest file specifies the name of the executable to run |
| and must also specify any shared libraries that the application directly |
| depends on. For indirect dependencies (such as libraries opened via |
| <code>dlopen()</code>) it is also convenient to list libraries in the manifest file. |
| However it is possile to load arbitrary shared libraries at runtime that |
| are not mentioned in the manifest by using the <a class="reference external" href="nacl_io">nacl_io library</a> |
| to mount a filesystem that contains the shared libraries which will then |
| allow <code>dlopen()</code> to access them.</p> |
| <p>In this example we demonstrate both loading directly from via the manifest |
| file (<code>libeightball.so</code>) and loading indirectly via a http mount |
| (<code>libreverse.so</code>).</p> |
| <p>Take a look at the manifest file in the dlopen example to see how |
| a glibc-style manifest file is structured. (Run <code>make</code> in the dlopen directory to |
| generate the manifest file if you haven’t done so already.) Here is an excerpt |
| from <code>dlopen.nmf</code>:</p> |
| <pre class="prettyprint"> |
| { |
| "files": { |
| "libeightball.so": { |
| "x86-64": { |
| "url": "lib64/libeightball.so" |
| }, |
| "x86-32": { |
| "url": "lib32/libeightball.so" |
| } |
| }, |
| "libstdc++.so.6": { |
| "x86-64": { |
| "url": "lib64/libstdc++.so.6" |
| }, |
| "x86-32": { |
| "url": "lib32/libstdc++.so.6" |
| } |
| }, |
| "libppapi_cpp.so": { |
| "x86-64": { |
| "url": "lib64/libppapi_cpp.so" |
| }, |
| "x86-32": { |
| "url": "lib32/libppapi_cpp.so" |
| } |
| }, |
| ... etc. |
| </pre> |
| <p>In most cases, you can use the <code>create_nmf.py</code> script in the SDK to generate |
| a manifest file for your application. The script is located in the tools |
| directory (e.g. <code>pepper_28/tools</code>).</p> |
| <p>The Makefile in the dlopen example generates the manifest automatically using |
| the <code>NMF_RULE</code> provided by the SDK build system. Running <code>make V=1</code> will |
| show the full command line which is used to generate the nmf:</p> |
| <pre class="prettyprint"> |
| create_nmf.py -o dlopen.nmf glibc/Release/dlopen_x86_32.nexe \ |
| glibc/Release/dlopen_x86_64.nexe glibc/Release/libeightball_x86_32.so \ |
| glibc/Release/libeightball_x86_64.so -s ./glibc/Release \ |
| -n libeightball_x86_32.so,libeightball.so \ |
| -n libeightball_x86_64.so,libeightball.so |
| </pre> |
| <p>Run python <code>create_nmf.py --help</code> to see a full description of the command-line |
| flags. A few of the important flags are described below.</p> |
| <dl class="docutils"> |
| <dt><code>-s</code> <em>directory</em></dt> |
| <dd>use <em>directory</em> to stage libraries (libraries are added to <code>lib32</code> and |
| <code>lib64</code> subfolders)</dd> |
| <dt><code>-L</code> <em>directory</em></dt> |
| <dd>add <em>directory</em> to the library search path. The default search path |
| already includes the toolchain and SDK libraries directories.</dd> |
| </dl> |
| <aside class="note"> |
| <strong>Note:</strong> The <code>create_nmf</code> script can only automatically detect explicit |
| shared library dependencies (for example, dependencies specified with the -l |
| flag for the compiler/linker). If you want to include libraries that you |
| intend to dlopen() at runtime you must explcitly list them in your call to |
| <code>create_nmf</code>. |
| </aside> |
| <p>As an alternative to using <code>create_nmf</code>, it is possible to manually calculate |
| the list of shared library dependencies using tools such as <code>objdump_</code>.</p> |
| <h3 id="deploying-a-dynamically-linked-application">Deploying a dynamically linked application</h3> |
| <p>As described above, an application’s manifest file must explicitly list all the |
| executable code modules that the application directly depends on, including |
| modules from the application itself (<code>.nexe</code> and <code>.so</code> files), modules from |
| the Native Client SDK (e.g., <code>libppapi_cpp.so</code>), and perhaps also modules from |
| <a class="reference external" href="https://chromium.googlesource.com/webports">webports</a> or from <a class="reference external" href="../../community/middleware">middleware |
| systems</a> that the application uses. You must |
| provide all of those modules as part of the application deployment process.</p> |
| <p>As explained in <a class="reference internal" href="/native-client/devguide/distributing.html"><em>Distributing Your Application</em></a>, there |
| are two basic ways to deploy a <a class="reference external" href="/apps">Chrome app</a>:</p> |
| <ul class="small-gap"> |
| <li><strong>hosted application:</strong> all modules are hosted together on a web server of |
| your choice</li> |
| <li><strong>packaged application:</strong> all modules are packaged into one file, hosted in |
| the Chrome Web Store, and downloaded to the user’s machine</li> |
| </ul> |
| <p>The web store documentation contains a handy guide to <a class="reference external" href="https://developer.chrome.com/webstore/choosing">help you choose which to |
| use</a>.</p> |
| <p>You must deploy all the modules listed in your application’s manifest file for |
| either the hosted application or the packaged application case. For hosted |
| applications, you must upload the modules to your web server. For packaged |
| applications, you must include the modules in the application’s Chrome Web Store |
| .crx file. Modules should use URLs/names that are consistent with those in the |
| Native Client manifest file, and be named relative to the location of the |
| manifest file. Remember that some of the libraries named in the manifest file |
| may be located in directories you specified with the <code>-L</code> option to |
| <code>create_nmf.py</code>. You are free to rename/rearrange files and directories |
| referenced by the Native Client manifest file, so long as the modules are |
| available in the locations indicated by the manifest file. If you move or rename |
| modules, it may be easier to re-run <code>create_nmf.py</code> to generate a new manifest |
| file rather than edit the original manifest file. For hosted applications, you |
| can check for name mismatches during testing by watching the request log of the |
| web server hosting your test deployment.</p> |
| <h3 id="opening-a-shared-library-at-runtime">Opening a shared library at runtime</h3> |
| <p>Native Client supports a version of the POSIX standard <code>dlopen()</code> interface |
| for opening libraries explicitly, after an application is already running. |
| Calling <code>dlopen()</code> may cause a library download to occur, and automatically |
| loads all libraries that are required by the named library.</p> |
| <aside class="note"> |
| <strong>Caution:</strong> Since <code>dlopen()</code> can potentially block, you must initially |
| call <code>dlopen()</code> off your application’s main thread. Initial calls to |
| <code>dlopen()</code> from the main thread will always fail in the current |
| implementation of Native Client. |
| </aside> |
| <p>The best practice for opening libraries with <code>dlopen()</code> is to use a worker |
| thread to pre-load libraries asynchronously during initialization of your |
| application, so that the libraries are available when they’re needed. You can |
| call <code>dlopen()</code> a second time when you need to use a library – per the |
| specification, subsequent calls to <code>dlopen()</code> return a handle to the |
| previously loaded library. Note that you should only call <code>dlclose()</code> to |
| close a library when you no longer need the library; otherwise, subsequent |
| calls to <code>dlopen()</code> could cause the library to be fetched again.</p> |
| <p>The dlopen example in the SDK demonstrates how to open a shared libraries |
| at runtime. To reiterate, the example includes three C++ files:</p> |
| <ul class="small-gap"> |
| <li><code>eightball.cc</code>: this is the shared library that implements the function |
| <code>Magic8Ball()</code> (this file is compiled into libeightball.so)</li> |
| <li><code>reverse.cc</code>: this is the shared library that implements the function |
| <code>Reverse()</code> (this file is compiled into libreverse.so)</li> |
| <li><code>dlopen.cc</code>: this is the Native Client module that loads the shared libraries |
| and makes calls to <code>Magic8Ball()</code> and <code>Reverse()</code> in response to requests |
| from JavaScript.</li> |
| </ul> |
| <p>When the Native Client module starts, it kicks off a worker thread that calls |
| <code>dlopen()</code> to load the two shared libraries. Once the module has a handle to |
| the library, it fetches the addresses of the <code>Magic8Ball()</code> and <code>Reverse()</code> |
| functions using <code>dlsym()</code>. When a user types in a query and clicks the ‘ASK!’ |
| button, the module calls <code>Magic8Ball()</code> to generate an answer, and returns |
| the result to the user. Likewise when the user clicks the ‘Reverse’ button |
| it calls the <code>Reverse()</code> function to reverse the string.</p> |
| <h3 id="troubleshooting">Troubleshooting</h3> |
| <p>If your .nexe isn’t loading, the best place to look for information that can |
| help you troubleshoot the JavaScript console and standard output from Chrome. |
| See <a class="reference internal" href="/native-client/devguide/devcycle/debugging.html#devcycle-debugging"><em>Debugging</em></a> for more information.</p> |
| <p>Here are a few common error messages and explanations of what they mean:</p> |
| <dl class="docutils"> |
| <dt><strong>/main.nexe: error while loading shared libraries: /main.nexe: failed to allocate code and data space for executable</strong></dt> |
| <dd>The .nexe may not have been compiled correctly (e.g., the .nexe may be |
| statically linked). Try cleaning and recompiling with the glibc toolchain.</dd> |
| <dt><strong>/main.nexe: error while loading shared libraries: libpthread.so.xxxx: cannot open shared object file: Permission denied</strong></dt> |
| <dd>(xxxx is a version number, for example, 5055067a.) This error can result from |
| having the wrong path in the .nmf file. Double-check that the path in the |
| .nmf file is correct.</dd> |
| <dt><strong>/main.nexe: error while loading shared libraries: /main.nexe: cannot open shared object file: No such file or directory</strong></dt> |
| <dd>If there are no obvious problems with your main.nexe entry in the .nmf file, |
| check where main.nexe is being requested from. Use Chrome’s Developer Tools: |
| Click the menu icon <img alt="menu-icon" src="/native-client/images/menu-icon.png" />, select Tools > Developer Tools, click the |
| Network tab, and look at the path in the Name column.</dd> |
| <dt><strong>NaCl module load failed: ELF executable text/rodata segment has wrong starting address</strong></dt> |
| <dd>This error happens when using a newlib-style .nmf file instead of a |
| glibc-style .nmf file. Make sure you build your application with the glic |
| toolchain, and use the create_nmf.py script to generate your .nmf file.</dd> |
| <dt><strong>NativeClient: NaCl module load failed: Nexe crashed during startup</strong></dt> |
| <dd>This error message indicates that a module crashed while being loaded. You |
| can determine which module crashed by looking at the Network tab in Chrome’s |
| Developer Tools (see above). The module that crashed will be the last one |
| that was loaded.</dd> |
| <dt><strong>/lib/main.nexe: error while loading shared libraries: /lib/main.nexe: only ET_DYN and ET_EXEC can be loaded</strong></dt> |
| <dd>This error message indicates that there is an error with the .so files listed |
| in the .nmf file – either the files are the wrong type or kind, or an |
| expected library is missing.</dd> |
| <dt><strong>undefined reference to ‘dlopen’ collect2: ld returned 1 exit status</strong></dt> |
| <dd>This is a linker ordering problem that usually results from improper ordering |
| of command line flags when linking. Reconfigure your command line string to |
| list libraries after the -o flag.</dd> |
| </dl> |
| </section> |
| |
| {{/partials.standard_nacl_article}} |