Home | History | Annotate | Download | only in devcycle
      1 ######################################
      2 Dynamic Linking and Loading with glibc
      3 ######################################
      4 
      5 .. contents::
      6   :local:
      7   :backlinks: none
      8   :depth: 2
      9 
     10 .. Note::
     11   :class: caution
     12 
     13   Portable Native Client currently only supports static linking, and the
     14   only C library available for it is newlib. This page is only valid for
     15   Native Client, though PNaCl will eventually support some form of
     16   dynamic linking.
     17 
     18 This document describes how to create and deploy dynamically linked and loaded
     19 applications with the glibc library in the Native Client SDK. Before reading
     20 this document, we recommend reading :doc:`Building Native Client Modules
     21 <building>`
     22 
     23 .. _c_libraries:
     24 
     25 C standard libraries: glibc and newlib
     26 --------------------------------------
     27 
     28 The Native Client SDK comes with two C standard libraries --- glibc and
     29 newlib. These libraries are described in the table below.
     30 
     31 +-----------------------------------------------------+----------+-------------+
     32 | Library                                             | Linking  | License     |
     33 +=====================================================+==========+=============+
     34 |glibc                                                | dynamic  | GNU Lesser  |
     35 |  The GNU implementation of the POSIX_ standard      | or static| General     |
     36 |  runtime library for the C programming language.    |          | Public      |
     37 |  Designed for portability and performance, glibc is |          | License     |
     38 |  one of the most popular implementations of the C   |          | (LGPL)      |
     39 |  library. It is comprised of a set of interdependent|          |             |
     40 |  libraries including libc, libpthreads, libdl, and  |          |             |
     41 |  others. For documentation, FAQs, and additional    |          |             |
     42 |  information about glibc, see GLIBC_.               |          |             |
     43 +-----------------------------------------------------+----------+-------------+
     44 |newlib                                               | static   | Berkeley    |
     45 |  newlib is a C library intended for use in embedded |          | Software    |
     46 |  systems. Like glibc, newlib is a conglomeration of |          | Distribution|
     47 |  several libraries. It is available for use under   |          | (BSD) type  |
     48 |  BSD-type free software licenses, which generally   |          | free        |
     49 |  makes it more suitable to link statically in       |          | software    |
     50 |  commercial, closed-source applications. For        |          | licenses    |
     51 |  documentation, FAQs, and additional information    |          |             |
     52 |  about newlib, see newlib_.                         |          |             |
     53 +-----------------------------------------------------+----------+-------------+
     54 
     55 
     56 For proprietary (closed-source) applications, your options are to either
     57 statically link to newlib, or dynamically link to glibc. We recommend
     58 dynamically linking to glibc, for a couple of reasons:
     59 
     60 * The glibc library is widely distributed (it's included in Linux
     61   distributions), and as such it's mature, hardened, and feature-rich. Your
     62   code is more likely to compile out-of-the-box with glibc.
     63 
     64 * Dynamic loading can provide a big performance benefit for your application if
     65   you can structure the application to defer loading of code that's not needed
     66   for initial interaction with the user. It takes some work to put such code in
     67   shared libraries and to load the libraries at runtime, but the payoff is
     68   usually worth it. In future releases, Chrome may also support caching of
     69   common dynamically linked libraries such as libc.so between applications.
     70   This could significantly reduce download size and provide a further potential
     71   performance benefit (for example, the hello_world example would only require
     72   downloading a .nexe file that's on the order of 30KB, rather than a .nexe
     73   file and several libraries, which are on the order of 1.5MB).
     74 
     75 Native Client support for dynamic linking and loading is based on glibc. Thus,
     76 **if your Native Client application must dynamically link and load code (e.g.,
     77 due to licensing considerations), we recommend that you use the glibc
     78 library.**
     79 
     80 .. Note::
     81   :class: note
     82 
     83   **Disclaimer:**
     84 
     85   * **None of the above constitutes legal advice, or a description of the legal
     86     obligations you need to fulfill in order to be compliant with the LGPL or
     87     newlib licenses. The above description is only a technical explanation of
     88     the differences between newlib and glibc, and the choice you must make
     89     between the two libraries.**
     90 
     91 
     92 
     93 .. Note::
     94   :class: note
     95 
     96   **Notes:**
     97 
     98   * Static linking with glibc is rarely used. Use this feature with caution.
     99 
    100   * The standard C++ runtime in Native Client is provided by libstdc++; this
    101     library is independent from and layered on top of glibc. Because of
    102     licensing restrictions, libstdc++ must be statically linked for commercial
    103     uses, even if the rest of an application is dynamically linked.
    104 
    105 SDK toolchains
    106 --------------
    107 
    108 The Native Client SDK contains multiple toolchains, which are differentiated by
    109 :ref:`target architecture <target_architectures>` and C library:
    110 
    111 =================== ========= ===============================
    112 Target architecture C library Toolchain directory
    113 =================== ========= ===============================
    114 x86                 newlib    toolchain/<platform>_x86_newlib
    115 x86                 glibc     toolchain/<platform>_x86_glibc
    116 ARM                 newlib    toolchain/<platform>_arm_newlib
    117 PNaCl               newlib    toolchain/<platform>_pnacl
    118 =================== ========= ===============================
    119 
    120 In the directories listed above, <platform> is the platform of your development
    121 machine (i.e., win, mac, or linux). For example, in the Windows SDK, the x86
    122 toolchain that uses glibc is in ``toolchain/win_x86_glibc``.
    123 
    124 .. Note::
    125   :class: note
    126 
    127   **Note:** The ARM and PNaCl toolchains are currently restricted to newlib.
    128 
    129 To use the glibc library and dynamic linking in your application, you **must**
    130 use a glibc toolchain. (Currently the only glibc toolchain is
    131 ``<platform>_x86_glibc``.) Note that you must build all code in your application
    132 with one toolchain. Code from multiple toolchains cannot be mixed.
    133 
    134 Specifying and delivering shared libraries
    135 ------------------------------------------
    136 
    137 One significant difference between newlib and glibc applications is that glibc
    138 applications must explicitly list and deploy the shared libraries that they
    139 use.
    140 
    141 In a desktop environment, when the user launches a dynamically linked
    142 application, the operating system's program loader determines the set of
    143 libraries the application requires by reading explicit inter-module
    144 dependencies from executable file headers, and loads the required libraries
    145 into the address space of the application process. Typically the required
    146 libraries will have been installed on the system as a part of the application's
    147 installation process. Often the desktop application developer doesn't know or
    148 think about the libraries that are required by an application, as those details
    149 are taken care of by the user's operating system.
    150 
    151 In the Native Client sandbox, dynamic linking can't rely in the same way on the
    152 operating system or the local file system. Instead, the application developer
    153 must identify the set of libraries that are required by an application, list
    154 those libraries in a Native Client :ref:`manifest file <manifest_file>`, and
    155 deploy the libraries along with the application. Instructions for how to build
    156 a dynamically linked Native Client application, generate a Native Client
    157 manifest (.nmf) file, and deploy an application are provided below.
    158 
    159 Building a dynamically linked application
    160 =========================================
    161 
    162 Applications built with the glibc toolchain will by dynamically linked by
    163 default. Application that load shared libraries at runtime using ``dlopen()``
    164 must link with the libdl library (``-ldl``).
    165 
    166 Like other gcc-based toolchains building a dynamic library for NaCl is normally
    167 done by linking with the ``-shared`` flag and compiling with the ``-fPIC`` flag.
    168 The SDK build system will do this automatically when the ``SO_RULE`` Makefile
    169 rule is used.
    170 
    171 The Native Client SDK includes an example that demonstrates how to build a
    172 shared library, and how to use the ``dlopen()`` interface to load that library
    173 at runtime (after the application is already running). Many applications load
    174 and link shared libraries at launch rather than at runtime, and hence do not
    175 use the ``dlopen()`` interface. The SDK example is nevertheless instructive, as
    176 it demonstrates how to build Native Client modules (.nexe files) and shared
    177 libraries (.so files) with the x86 glibc toolchain, and how to generate a
    178 Native Client manifest file for glibc applications.
    179 
    180 The SDK example, located in ``examples/tutorial/dlopen``, includes three C++
    181 files:
    182 
    183 eightball.cc
    184   This file implements the function ``Magic8Ball()``, which is used to provide
    185   whimsical answers to user questions. This file is compiled into a shared
    186   library called ``libeightball.so``. This library gets included in the
    187   .nmf file and is therefore directly loadable with ``dlopen()``.
    188 
    189 reverse.cc
    190   This file implements the function ``Reverse()``, which returns reversed
    191   copies of strings that are passed to it. This file is compiled into a shared
    192   library called ``libreverse.so``. This library is **not** included in the
    193   .nmf file and is loaded via an http mount using the :ref:`nacl_io library
    194   <nacl_io>`.
    195 
    196 dlopen.cc
    197   This file implements the Native Client module, which loads the two shared
    198   libraries and handles communcation with with JavaScript. The file is compiled
    199   into a Native Client executable (.nexe).
    200 
    201 Run ``make`` in the dlopen directory to see the commands the Makefile executes
    202 to build x86 32-bit and 64-bit .nexe and .so files, and to generate a .nmf
    203 file. These commands are described below.
    204 
    205 .. Note::
    206   :class: note
    207 
    208   **Note:** The Makefiles for most of the examples in the SDK build the
    209   examples using multiple toolchains (x86 newlib, x86 glibc, ARM, and PNaCl).
    210   With a few exceptions (listed in the :ref:`Release Notes
    211   <sdk-release-notes>`), running "make" in each example's directory builds
    212   multiple versions of the example using the SDK toolchains. The dlopen example
    213   is one of those exceptions  it is only built with the x86 glibc toolchain,
    214   as that is currently the only toolchain that supports glibc and thus dynamic
    215   linking and loading. Take a look at the example Makefiles and the generated
    216   .nmf files for details on how to build dynamically linked applications.
    217 
    218 .. _dynamic_loading_manifest:
    219 
    220 Generating a Native Client manifest file for a dynamically linked application
    221 =============================================================================
    222 
    223 The Native Client manifest file specifies the name of the executable to run
    224 and must also specify any shared libraries that the application directly
    225 depends on. For indirect dependencies (such as libraries opened via
    226 ``dlopen()``) it is also convenient to list libraries in the manifest file.
    227 However it is possile to load arbitrary shared libraries at runtime that
    228 are not mentioned in the manifest by using the `nacl_io library <nacl_io>`_
    229 to mount a filesystem that contains the shared libraries which will then
    230 allow ``dlopen()`` to access them.
    231 
    232 In this example we demonstrate both loading directly from via the manifest
    233 file (``libeightball.so``) and loading indirectly via a http mount
    234 (``libreverse.so``).
    235 
    236 Take a look at the manifest file in the dlopen example to see how
    237 a glibc-style manifest file is structured. (Run ``make`` in the dlopen directory to
    238 generate the manifest file if you haven't done so already.) Here is an excerpt
    239 from ``dlopen.nmf``::
    240 
    241   {
    242     "files": {
    243       "libeightball.so": {
    244         "x86-64": {
    245           "url": "lib64/libeightball.so"
    246         },
    247         "x86-32": {
    248           "url": "lib32/libeightball.so"
    249         }
    250       },
    251       "libstdc++.so.6": {
    252         "x86-64": {
    253           "url": "lib64/libstdc++.so.6"
    254         },
    255         "x86-32": {
    256           "url": "lib32/libstdc++.so.6"
    257         }
    258       },
    259       "libppapi_cpp.so": {
    260         "x86-64": {
    261           "url": "lib64/libppapi_cpp.so"
    262         },
    263         "x86-32": {
    264           "url": "lib32/libppapi_cpp.so"
    265         }
    266       },
    267   ... etc.
    268 
    269 In most cases, you can use the ``create_nmf.py`` script in the SDK to generate
    270 a manifest file for your application. The script is located in the tools
    271 directory (e.g. ``pepper_28/tools``).
    272 
    273 The Makefile in the dlopen example generates the manifest automatically using
    274 the ``NMF_RULE`` provided by the SDK build system. Running ``make V=1`` will
    275 show the full command line which is used to generate the nmf::
    276 
    277   create_nmf.py -o dlopen.nmf glibc/Release/dlopen_x86_32.nexe \
    278      glibc/Release/dlopen_x86_64.nexe glibc/Release/libeightball_x86_32.so \
    279      glibc/Release/libeightball_x86_64.so  -s ./glibc/Release \
    280      -n libeightball_x86_32.so,libeightball.so \
    281      -n libeightball_x86_64.so,libeightball.so
    282 
    283 Run python ``create_nmf.py --help`` to see a full description of the command-line
    284 flags. A few of the important flags are described below.
    285 
    286 ``-s`` *directory*
    287   use *directory* to stage libraries (libraries are added to ``lib32`` and
    288   ``lib64`` subfolders)
    289 
    290 ``-L`` *directory*
    291   add *directory* to the library search path. The default search path
    292   already includes the toolchain and SDK libraries directories.
    293 
    294 .. Note::
    295   :class: note
    296 
    297   **Note:** The ``create_nmf`` script can only automatically detect explicit
    298   shared library dependencies (for example, dependencies specified with the -l
    299   flag for the compiler/linker). If you want to include libraries that you
    300   intend to dlopen() at runtime you must explcitly list them in your call to
    301   ``create_nmf``.
    302 
    303 As an alternative to using ``create_nmf``, it is possible to manually calculate
    304 the list of shared library dependencies using tools such as ``objdump_``.
    305 
    306 Deploying a dynamically linked application
    307 ==========================================
    308 
    309 As described above, an application's manifest file must explicitly list all the
    310 executable code modules that the application directly depends on, including
    311 modules from the application itself (.nexe and .so files), modules from the
    312 Native Client SDK (e.g., libppapi_cpp.so), and perhaps also modules from
    313 `naclports <http://code.google.com/p/naclports/>`_ or from
    314 `middleware systems <../../community/middleware>`_ that
    315 the application uses. You must provide all of those modules as part of the
    316 application deployment process.
    317 
    318 As explained in :doc:`Distributing Your Application
    319 <../distributing>`, there are two basic ways to deploy an application:
    320 
    321 * **hosted application:** all modules are hosted together on a web server of
    322   your choice
    323 
    324 * **packaged application:** all modules are packaged into one file, hosted in
    325   the Chrome Web Store, and downloaded to the user's machine
    326 
    327 You must deploy all the modules listed in your application's manifest file for
    328 either the hosted application or the packaged application case. For hosted
    329 applications, you must upload the modules to your web server. For packaged
    330 applications, you must include the modules in the application's Chrome Web
    331 Store .crx file. Modules should use URLs/names that are consistent with those
    332 in the Native Client manifest file, and be named relative to the location of
    333 the manifest file. Remember that some of the libraries named in the manifest
    334 file may be located in directories you specified with the -L option to
    335 ``create_nmf.py``. You are free to rename/rearrange files and directories
    336 referenced by the Native Client manifest file, so long as the modules are
    337 available in the locations indicated by the manifest file. If you move or
    338 rename modules, it may be easier to re-run ``create_nmf.py`` to generate a new
    339 manifest file rather than edit the original manifest file. For hosted
    340 applications, you can check for name mismatches during testing by watching the
    341 request log of the web server hosting your test deployment.
    342 
    343 Opening a shared library at runtime
    344 ===================================
    345 
    346 Native Client supports a version of the POSIX standard ``dlopen()`` interface
    347 for opening libraries explicitly, after an application is already running.
    348 Calling ``dlopen()`` may cause a library download to occur, and automatically
    349 loads all libraries that are required by the named library.
    350 
    351 .. Note::
    352   :class: note
    353 
    354   **Caution:** Since ``dlopen()`` can potentially block, you must initially
    355   call ``dlopen()`` off your application's main thread. Initial calls to
    356   ``dlopen()`` from the main thread will always fail in the current
    357   implementation of Native Client.
    358 
    359 The best practice for opening libraries with ``dlopen()`` is to use a worker
    360 thread to pre-load libraries asynchronously during initialization of your
    361 application, so that the libraries are available when they're needed. You can
    362 call ``dlopen()`` a second time when you need to use a library -- per the
    363 specification, subsequent calls to ``dlopen()`` return a handle to the
    364 previously loaded library. Note that you should only call ``dlclose()`` to
    365 close a library when you no longer need the library; otherwise, subsequent
    366 calls to ``dlopen()`` could cause the library to be fetched again.
    367 
    368 The dlopen example in the SDK demonstrates how to open a shared libraries
    369 at runtime. To reiterate, the example includes three C++ files:
    370 
    371 * ``eightball.cc``: this is the shared library that implements the function
    372   ``Magic8Ball()`` (this file is compiled into libeightball.so)
    373 * ``reverse.cc``: this is the shared library that implements the function
    374   ``Reverse()`` (this file is compiled into libreverse.so)
    375 * ``dlopen.cc``: this is the Native Client module that loads the shared libraries
    376   and makes calls to ``Magic8Ball()`` and ``Reverse()`` in response to requests
    377   from JavaScript.
    378 
    379 When the Native Client module starts, it kicks off a worker thread that calls
    380 ``dlopen()`` to load the two shared libraries. Once the module has a handle to
    381 the library, it fetches the addresses of the ``Magic8Ball()`` and ``Reverse()``
    382 functions using ``dlsym()``. When a user types in a query and clicks the 'ASK!'
    383 button, the module calls ``Magic8Ball()`` to generate an answer, and returns
    384 the result to the user. Likewise when the user clicks the 'Reverse' button
    385 it calls the ``Reverse()`` function to reverse the string.
    386 
    387 Troubleshooting
    388 ===============
    389 
    390 If your .nexe isn't loading, the best place to look for information that can
    391 help you troubleshoot the JavaScript console and standard output from Chrome.
    392 See :ref:`Debugging <devcycle-debugging>` for more information.
    393 
    394 Here are a few common error messages and explanations of what they mean:
    395 
    396 **/main.nexe: error while loading shared libraries: /main.nexe: failed to allocate code and data space for executable**
    397   The .nexe may not have been compiled correctly (e.g., the .nexe may be
    398   statically linked). Try cleaning and recompiling with the glibc toolchain.
    399 
    400 **/main.nexe: error while loading shared libraries: libpthread.so.xxxx: cannot open shared object file: Permission denied**
    401   (xxxx is a version number, for example, 5055067a.) This error can result from
    402   having the wrong path in the .nmf file. Double-check that the path in the
    403   .nmf file is correct.
    404 
    405 **/main.nexe: error while loading shared libraries: /main.nexe: cannot open shared object file: No such file or directory**
    406   If there are no obvious problems with your main.nexe entry in the .nmf file,
    407   check where main.nexe is being requested from. Use Chrome's Developer Tools:
    408   Click the menu icon |menu-icon|, select Tools > Developer Tools, click the
    409   Network tab, and look at the path in the Name column.
    410 
    411 **NaCl module load failed: ELF executable text/rodata segment has wrong starting address**
    412   This error happens when using a newlib-style .nmf file instead of a
    413   glibc-style .nmf file. Make sure you build your application with the glic
    414   toolchain, and use the create_nmf.py script to generate your .nmf file.
    415 
    416 **NativeClient: NaCl module load failed: Nexe crashed during startup**
    417   This error message indicates that a module crashed while being loaded. You
    418   can determine which module crashed by looking at the Network tab in Chrome's
    419   Developer Tools (see above). The module that crashed will be the last one
    420   that was loaded.
    421 
    422 **/lib/main.nexe: error while loading shared libraries: /lib/main.nexe: only ET_DYN and ET_EXEC can be loaded**
    423   This error message indicates that there is an error with the .so files listed
    424   in the .nmf file -- either the files are the wrong type or kind, or an
    425   expected library is missing.
    426 
    427 **undefined reference to 'dlopen' collect2: ld returned 1 exit status**
    428   This is a linker ordering problem that usually results from improper ordering
    429   of command line flags when linking. Reconfigure your command line string to
    430   list libraries after the -o flag.
    431 
    432 .. |menu-icon| image:: /images/menu-icon.png
    433 .. _objdump: http://en.wikipedia.org/wiki/Objdump
    434 .. _GLIBC: http://www.gnu.org/software/libc/index.html
    435 .. _POSIX: http://en.wikipedia.org/wiki/POSIX
    436 .. _newlib: http://sourceware.org/newlib/
    437