1 | .. SPDX-License-Identifier: CC-BY-SA-4.0 |
---|
2 | |
---|
3 | .. Copyright (C) 2019 Chris Johns <chrisj@rtems.org> |
---|
4 | |
---|
5 | .. index:: Dynamic Loader |
---|
6 | |
---|
7 | Dynamic Loader |
---|
8 | ============== |
---|
9 | .. index:: Dynamic Loader |
---|
10 | .. index:: Run-time Loader |
---|
11 | .. index:: RTL |
---|
12 | .. index:: Libdl |
---|
13 | |
---|
14 | RTEMS supports dynamically loading of executable code and data in the form of |
---|
15 | object files into a running system where the run-time loaded code can be |
---|
16 | executed and data accessed |
---|
17 | |
---|
18 | This section describes RTEMS loader, preparing and loading executable code into |
---|
19 | a running system, the supported architectures and any limitation that may exist |
---|
20 | with an architecture. |
---|
21 | |
---|
22 | The RTEMS operating system contains a link editor that runs on the target. The |
---|
23 | link editor supports loading Extendable Linker Format (ELF) relocatable |
---|
24 | executable object files locating the code and data in the target's address space |
---|
25 | as it is loaded. An executable object file's external references to function |
---|
26 | identifiers and data object identifiers are resolved and any external symbols |
---|
27 | can be made available in the global symbol table. The executing performance of |
---|
28 | dynamically loaded code is similar to the same code statically linked into an |
---|
29 | executable. This is a core requirement of the RTEMS link editor. |
---|
30 | |
---|
31 | .. _fig-dl-libdl: |
---|
32 | |
---|
33 | .. figure:: ../../images/user/libdl.png |
---|
34 | :width: 95% |
---|
35 | :alt: Run Time Loader (libdl) |
---|
36 | :figclass: align-center |
---|
37 | |
---|
38 | Run Time Loader (libdl) |
---|
39 | |
---|
40 | The RTEMS operating system's dynamic loader is not the same as the dynamic |
---|
41 | shared library support Unix or Windows have. Those operating systems use dynamic |
---|
42 | loading to share code between processes and this is an important feature in |
---|
43 | their design. RTEMS is a single address space operating system and that means |
---|
44 | there is no ability to share code at run-time. As a result code is loaded in a |
---|
45 | similar manner to static linking removing the need for any overheads sharing |
---|
46 | code may have. |
---|
47 | |
---|
48 | To load an executable object file it must be resident on a target and accessible |
---|
49 | by RTEMS's file system. The executable object file can be a single file or a |
---|
50 | collection in a library stored using the Unix standard archive format. The RTEMS |
---|
51 | loader supports the extended GNU format for long file names in archives. |
---|
52 | |
---|
53 | The RTEMS developers do not see dynamically loading of code as a real-time |
---|
54 | activity. A system should not respond to real-time external events by loading |
---|
55 | code. The loading of code should happen before a system is considered available |
---|
56 | and the activity the system is experiencing is low and stable. |
---|
57 | |
---|
58 | .. index: base image |
---|
59 | |
---|
60 | The statically linked executable that is loaded and run after reset is called |
---|
61 | the *base image*. The *base image* contains your base application that is used |
---|
62 | to dynamically load code, a global symbol table, the parts of the RTEMS |
---|
63 | operating system code used in the base image as well as functions and data from |
---|
64 | the tool suite libraries and packages you are using. Only the software |
---|
65 | referenced is used to create the base image. The parts of the libraries not |
---|
66 | referenced are not part of the executable or present in the global symbol table. |
---|
67 | |
---|
68 | Application software can locate a symbol by name and call the address or |
---|
69 | reference the data at that address. A function identifier located by a symbol |
---|
70 | does not have it's signatures checked, it is the responsibility of the caller to |
---|
71 | make sure the function is called with the correct arguments. It is the same for |
---|
72 | data objects, there is no type checking. Symbol versioning is not supported and |
---|
73 | supporting it does not make sense within the RTEMS operating system. An RTEMS |
---|
74 | target system is closed to normal users and software needs to be built from the |
---|
75 | same tool set and header files used to the build the base image. |
---|
76 | |
---|
77 | An executable object file's text or code has to be built for the target's |
---|
78 | architecture it is loaded on and it must be built with the same ABI flags the |
---|
79 | base image is built with. See :ref:`MachineFlagsandABI`. |
---|
80 | |
---|
81 | System Design |
---|
82 | ------------- |
---|
83 | |
---|
84 | The use of dynamic loading in a project is a system design decision. Some |
---|
85 | systems will have strict requirements where loading code into a live system is |
---|
86 | not allowed while other projects will benefit from the system level flexibility |
---|
87 | dynamically loading code provides. |
---|
88 | |
---|
89 | Code loaded at run time needs to be resident or accessible to the target via |
---|
90 | RTEMS's file system. Targets that have suitable media or a network interface to |
---|
91 | NFS servers to hold the executable object and library files are best suited. |
---|
92 | |
---|
93 | Dynamically loading code uses more memory than statically linking the same code |
---|
94 | into the base image. The link editor maintains symbol tables where each symbol |
---|
95 | is a string, an address, and some additional data. The executable object files |
---|
96 | resident in memory each have data to manage them, the memory they use, and any |
---|
97 | dependencies they might have. The link editor is designed to minimize the memory |
---|
98 | overheads however only statically linked executables have no memory overhead. |
---|
99 | |
---|
100 | The link editor relocates the code and data into RAM fixing it to the load |
---|
101 | address as it is loaded. A target needs to have suitably configured memory |
---|
102 | available for the executable object file to reside in. The memory must be able |
---|
103 | to support read, write and executable type access. Fine control of the memory |
---|
104 | and it's modes can be supported using a customer allocator. Examples are systems |
---|
105 | that have a custom memory map, specialized memory for the execution of code or a |
---|
106 | requirement for read-only executable sections. |
---|
107 | |
---|
108 | The load address of an executable object file is determined by the load order |
---|
109 | and the allocator used. The default allocator for the link editor is the system |
---|
110 | heap which means the location a specific executable object file is loaded at |
---|
111 | depends on the memory allocated before it is loaded and when in the load order |
---|
112 | it is loaded. A statically linked executable's address map is fixed and this is |
---|
113 | considered important in some systems. A dynamically loaded system can be loaded |
---|
114 | in a repeatable manner if the load order is the same and the initialization |
---|
115 | sequence of the system is controlled. A custom allocator may also help. |
---|
116 | |
---|
117 | Management of dynamically loadable object files and libraries adds to the |
---|
118 | configuration management of the hosts in a project. The loadable files need to |
---|
119 | be released and tracked in a suitable configuration management process just like |
---|
120 | the base image is. Executable object files and libraries are specific to a |
---|
121 | version of RTEMS and cannot be mixed or moved and this needs to be carefully |
---|
122 | managed. Currently there are no checks an executable object file matches the |
---|
123 | version of the base image it is being loaded on. These extra configuration |
---|
124 | controlled items add to the overheads of a project and need to be considered. |
---|
125 | |
---|
126 | Dynamically loadable systems have a number of features that benefit some systems |
---|
127 | and products. Systems can be built on a base of trusted or *golden* modules. A |
---|
128 | number of projects using a common base of hardware can make use of proven |
---|
129 | modules reducing the testing and qualification overhead for each new release. A |
---|
130 | tested base image with libraries for common and available boards provides a |
---|
131 | simple and fast way for new users to trial and use RTEMS. |
---|
132 | |
---|
133 | A project can use dynamic loading during development, shipping statically linked |
---|
134 | executables in production. Hardware used by a development team can have more |
---|
135 | memory, extra media for disk drives, or a network interface. |
---|
136 | |
---|
137 | Loader Interface |
---|
138 | ---------------- |
---|
139 | .. index:: Loader Interface |
---|
140 | .. index:: Loading object files |
---|
141 | .. index:: dlfcn.h |
---|
142 | |
---|
143 | Run-time executable object file loading and management is via the standard's |
---|
144 | based calls provided by the header file ``<dlfcn.h>``. The details of the calls |
---|
145 | follow. |
---|
146 | |
---|
147 | .. _dlopen: |
---|
148 | .. index:: dlopen |
---|
149 | ``void* dlopen(const char* path, int mode);`` |
---|
150 | The ``dlopen()`` function makes the symbols (function identifiers and data |
---|
151 | object identifiers) in the executable object file specified by `file` |
---|
152 | available to the calling program. |
---|
153 | |
---|
154 | The executable object files eligible for this operation are in the ELF |
---|
155 | format. |
---|
156 | |
---|
157 | The link loader may load embedded dependencies in executable object files. In |
---|
158 | such cases, a ``dlopen()`` operation may load those dependencies in addition |
---|
159 | to the executable object file specified by `file`. |
---|
160 | |
---|
161 | A successful ``dlopen()`` returns a `handle` which the caller may use on |
---|
162 | subsequent calls to ``dlsym()``, ``dlinfo()`` and ``dlclose()``. |
---|
163 | |
---|
164 | The value of the `handle` should not be interpreted in any way by the caller. |
---|
165 | |
---|
166 | Subsequent calls to ``dlopen()`` for the same executable object file increases |
---|
167 | the references to it. |
---|
168 | |
---|
169 | The `file` argument is used to construct a pathname to the executable object |
---|
170 | file or archive library of executable object files. If the `file` argument |
---|
171 | contains a colon (``:``) the name of the executable object file in the library |
---|
172 | follows and this file name may optionally end with ``@`` followed by a number |
---|
173 | which is the absolute offset in the library file where the executable object |
---|
174 | file starts. If an executable object file is not detected at the offset the |
---|
175 | archive library's file table is searched. |
---|
176 | |
---|
177 | If `file` is a null pointer, ``dlopen()`` returns a global symbol table |
---|
178 | handle. This `handle` provides access to the global symbols from an ordered |
---|
179 | set of executable object files consisting of the original base image file, the |
---|
180 | set of executable object files loaded using ``dlopen()`` operations with the |
---|
181 | ``RTLD_GLOBAL`` flag, and any dependencies loaded. As the latter sets of |
---|
182 | executable object files can change during execution, the set of symbols made |
---|
183 | available by this `handle` can also change dynamically. |
---|
184 | |
---|
185 | Only a single copy of an executable object file is brought into the address |
---|
186 | space, even if ``dlopen()`` is invoked multiple times in reference to the |
---|
187 | executable object file, and even if different pathnames are used to reference |
---|
188 | the executable object file. |
---|
189 | |
---|
190 | Unresolved external symbols do not cause an error to be returned allowing the |
---|
191 | loading of jointly dependent executable object files. |
---|
192 | |
---|
193 | If ``dlopen()`` fails, it returns a null pointer, and sets an error condition |
---|
194 | which may be interrogated with ``dlerror()``. |
---|
195 | |
---|
196 | The `mode` parameter describes how ``dlopen()`` operates upon `file` with |
---|
197 | respect to the processing of relocations and the scope of visibility of the |
---|
198 | symbols provided within `file`. When an executable object file is brought into |
---|
199 | the address space, it may contain references to symbols whose addresses are |
---|
200 | not known until the executable object file is loaded. |
---|
201 | |
---|
202 | If a loaded executable object file and any dependent executable object files |
---|
203 | loaded with it contain any initialiser functions, they are called in the order |
---|
204 | loaded before ``dlopen()`` returns. |
---|
205 | |
---|
206 | The modes ``RTLD_LAZY`` and ``RTLD_NOW`` do not effect the type of relocation |
---|
207 | performed, it is same for both modes. All relocations of an executable object |
---|
208 | file and any dependent executable object files loaded with it are completed |
---|
209 | before the ``dlopen()`` call returns. The execution performance of the code |
---|
210 | loaded can be considered deterministic once ``dlopen()`` has returned. |
---|
211 | |
---|
212 | Any executable object file loaded by ``dlopen()`` can reference global symbols |
---|
213 | in the base image, any executable object files loaded included in the same |
---|
214 | ``dlopen()`` invocation, and any executable object files that were loaded in |
---|
215 | any ``dlopen()`` invocation and which specified the ``RTLD_GLOBAL`` flag. To |
---|
216 | determine the scope of visibility for the symbols loaded with a ``dlopen()`` |
---|
217 | invocation, the `mode` parameter should be a bitwise-inclusive ``OR`` with one |
---|
218 | of the following values: |
---|
219 | |
---|
220 | ``RTLD_GLOBAL`` |
---|
221 | The executable object file's symbols are made available for relocation |
---|
222 | processing of any other executable object file. In addition, symbol lookup |
---|
223 | using ``dlopen(NULL,mode)`` and an associated ``dlsym()`` allows |
---|
224 | executable object files loaded with this mode to be searched. |
---|
225 | |
---|
226 | ``RTLD_LOCAL`` |
---|
227 | The executable object file's symbols shall not be made available for |
---|
228 | relocation processing of any other executable object files. |
---|
229 | |
---|
230 | If neither ``RTLD_GLOBAL`` nor ``RTLD_LOCAL`` is specified, the default |
---|
231 | behavior is unspecified. |
---|
232 | |
---|
233 | If ``RTLD_GLOBAL`` has been specified, the executable object file maintains |
---|
234 | it's ``RTLD_GLOBAL`` status regardless of any previous or future specification |
---|
235 | of ``RTLD_LOCAL``, as long as the executable object file remains in the |
---|
236 | address space. |
---|
237 | |
---|
238 | Symbols introduced through calls to ``dlopen()`` may be used in relocation |
---|
239 | activities. Symbols that duplicate symbols already defined by the base image |
---|
240 | or previous ``dlopen()`` calls are treated as an error and the object file is |
---|
241 | not loaded. Symbols introduced through loading dependent executable object |
---|
242 | files are ignored or not loaded depending on the method used to build the |
---|
243 | executable object files. |
---|
244 | |
---|
245 | The symbols introduced by ``dlopen()`` operations and available through |
---|
246 | ``dlsym()`` are at a minimum those which are exported as identifiers of global |
---|
247 | scope by the executable object file. Typically, such identifiers shall be |
---|
248 | those that were specified in (for example) C source code as having ``extern`` |
---|
249 | linkage. |
---|
250 | |
---|
251 | .. _dlclose: |
---|
252 | .. index:: dlclose |
---|
253 | ``int dlclose(void* handle);`` |
---|
254 | Releases a reference to the executable object file referenced by `handle`. If |
---|
255 | the reference count drops to ``0``, the executable object file's global symbol |
---|
256 | table is made unavailable. When all references to the global symbols the |
---|
257 | executable object file provided have been removed the object file is removed |
---|
258 | from the address space. |
---|
259 | |
---|
260 | If the executable object being removed has any termination routines in it they |
---|
261 | are called. |
---|
262 | |
---|
263 | .. _dlsym: |
---|
264 | .. index:: dlsym |
---|
265 | ``void* dlsym(void* handle, const char* symbol);`` |
---|
266 | The ``dlsym()`` function obtains the address of a symbol (a function identifier |
---|
267 | or a data object identifier) defined in the symbol table identified by the |
---|
268 | handle argument. The handle argument is a symbol table handle returned from a |
---|
269 | call to ``dlopen()`` (and which has not since been released by a call to |
---|
270 | ``dlclose()``), and name is the symbol's name as a character string. The return |
---|
271 | value from ``dlsym()``, cast to a pointer to the type of the named symbol, can |
---|
272 | be used to call (in the case of a function) or access the contents of (in the |
---|
273 | case of a data object) the named symbol. |
---|
274 | |
---|
275 | The ``dlsym()`` function searches for the named symbol in the symbol table |
---|
276 | referenced by handle and returns the address of the code or data location |
---|
277 | specified by the null-terminated character string symbol. Which libraries and |
---|
278 | objects are searched depends on the `handle` parameter. |
---|
279 | |
---|
280 | Upon successful completion, if name names a function identifier, ``dlsym()`` |
---|
281 | returns the address of the function converted from type pointer to function to |
---|
282 | type pointer to ``void``; otherwise, ``dlsym()`` shall return the address of |
---|
283 | the data object associated with the data object identifier named by name |
---|
284 | converted from a pointer to the type of the data object to a pointer to |
---|
285 | ``void``. If `handle` does not refer to a valid symbol table handle or if the |
---|
286 | symbol named by name cannot be found in the symbol table associated with |
---|
287 | `handle`, ``dlsym()`` shall return a null pointer. |
---|
288 | |
---|
289 | .. _dlinfo: |
---|
290 | .. index:: dlinfo |
---|
291 | ``int dlinfo(void* handle, int request, void* args);`` |
---|
292 | |
---|
293 | The ``dlinfo()`` function provides information about dynamically loaded object. |
---|
294 | The action taken by ``dlinfo()`` and exact meaning and type of the argument |
---|
295 | `args` depend on value of the `request` argument provided by the caller. |
---|
296 | |
---|
297 | ``RTLD_DI_UNRESOLVED`` |
---|
298 | Return ``1`` in an indexer value pointed to by `args` if the symbol table |
---|
299 | handle has unresolved relocation records to symbols. If the `handle` is the |
---|
300 | global symbol table handle or ``RTLD_SELF`` return ``1`` if any unresolved |
---|
301 | relocation records to symbols are present in any loaded executable object |
---|
302 | files.. |
---|
303 | |
---|
304 | .. _dlerror: |
---|
305 | .. index:: dlerror |
---|
306 | ``const char *dlerror(void);`` |
---|
307 | The ``dlerror()`` function returns a null-terminated character string (with no |
---|
308 | trailing ``<newline>``) that describes the last error that occurred during |
---|
309 | dynamic linking processing. If no dynamic linking errors have occurred since |
---|
310 | the last invocation of ``dlerror()``, ``dlerror()`` returns ``NULL``. Thus, |
---|
311 | invoking ``dlerror()`` a second time, immediately following a prior |
---|
312 | invocation, results in ``NULL`` being returned. |
---|
313 | |
---|
314 | This example opens an object file, checks for any unresolved symbols the object |
---|
315 | file may have, locates a global symbol in the object file, calls it then closes |
---|
316 | the object file: |
---|
317 | |
---|
318 | .. code-block:: c |
---|
319 | |
---|
320 | #include <stdbool.h> |
---|
321 | #include <stdio.h> |
---|
322 | #include <dlfcn.h> |
---|
323 | |
---|
324 | typedef int (*call_sig)(void); |
---|
325 | |
---|
326 | bool load_object (void) |
---|
327 | { |
---|
328 | void* handle; |
---|
329 | call_sig call; |
---|
330 | int unresolved; |
---|
331 | |
---|
332 | handle = dlopen ("/code.o", RTLD_NOW | RTLD_GLOBAL); |
---|
333 | if (handle == NULL) |
---|
334 | { |
---|
335 | printf ("dlopen failed: %s\n", dlerror ()); |
---|
336 | return false; |
---|
337 | } |
---|
338 | |
---|
339 | if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) < 0) |
---|
340 | { |
---|
341 | printf ("dlinfo failed: %s\n", dlerror ()); |
---|
342 | dlclose (handle); |
---|
343 | return false; |
---|
344 | } |
---|
345 | |
---|
346 | if (unresolved != 0) |
---|
347 | { |
---|
348 | printf ("object.o has unresolved external symbols\n"); |
---|
349 | dlclose (handle); |
---|
350 | return false; |
---|
351 | } |
---|
352 | |
---|
353 | call = dlsym (handle, "foo"); |
---|
354 | if (call == NULL) |
---|
355 | { |
---|
356 | printf("dlsym failed: symbol 'foo' not found\n"); |
---|
357 | dlclose (handle); |
---|
358 | return false; |
---|
359 | } |
---|
360 | |
---|
361 | printf ("'foo()' returns: %i\n", call ()); |
---|
362 | |
---|
363 | if (dlclose (handle) < 0) |
---|
364 | { |
---|
365 | printf("dlclose failed: %s\n", dlerror()); |
---|
366 | return false; |
---|
367 | } |
---|
368 | |
---|
369 | return true; |
---|
370 | } |
---|
371 | |
---|
372 | Symbols |
---|
373 | ------- |
---|
374 | .. index:: symbol |
---|
375 | .. index:: global symbol |
---|
376 | .. index:: function identifier |
---|
377 | .. index:: data object identifier |
---|
378 | |
---|
379 | The RTEMS link editor manages the symbols for the base image and all resident |
---|
380 | executable object files. A symbol is an identifier string and a pointer value to |
---|
381 | a function identifier or a data object identifier. The symbols held in the |
---|
382 | symbol tables are used in the relocation of executable object files or they can |
---|
383 | be accessed by application code using the :ref:`dlsym() <dlsym>` call. |
---|
384 | |
---|
385 | .. index:: orphaned object file |
---|
386 | |
---|
387 | An executable object file's symbols are removed from the global symbol table |
---|
388 | when it is closed or orphaned. An executale object file cannot be unloaded if a |
---|
389 | symbol it provides is referenced by another object and that object is still |
---|
390 | resident. An executable object file that has no references to any of its symbols |
---|
391 | and was not explicitly loaded using the :ref:`dlopen() <dlopen>` call is |
---|
392 | orphaned and automatically removed from the address space. |
---|
393 | |
---|
394 | Base Image Symbols |
---|
395 | ^^^^^^^^^^^^^^^^^^ |
---|
396 | .. index:: base image symbols |
---|
397 | |
---|
398 | The base image symbol table provides access to the function and data objects |
---|
399 | statically linked into the base image. Loaded executable object files can be |
---|
400 | directly linked to the code and data resident in the base image. |
---|
401 | |
---|
402 | A statically linked RTEMS executable does not contain a symbol table, it has to |
---|
403 | be generated and either embedded into the executable or loaded as a specially |
---|
404 | created executable object file. |
---|
405 | |
---|
406 | The base image symbol table is dependent on the contents of the base image and |
---|
407 | this is not known until it has been linked. This means the base image symbol |
---|
408 | table needs to be constructed after the base image executable has been linked |
---|
409 | and the list of global symbols is known. |
---|
410 | |
---|
411 | The RTEMS Tools command :program:`rtems-syms` (see :ref:`RTEMSSymbols`) extracts |
---|
412 | the global and weak symbols from an RTEMS static executable file, creates a C |
---|
413 | file and compiles it creating a relocatable executable object file. This file |
---|
414 | can be linked with the static executable's object files and libraries to create |
---|
415 | a static executables with an embedded symbol table or the executable file can be |
---|
416 | loaded dynamically at run-time. The following needs to be observed: |
---|
417 | |
---|
418 | #. The option ``-e`` or ``--embedded`` to :program:`rtems-syms` creates an |
---|
419 | executable object file to be embedded in the base image and not providing |
---|
420 | either of these options creates a symbols executable object file that is |
---|
421 | loaded at run-time. The same executable object file cannot be used to |
---|
422 | embedded or load. |
---|
423 | |
---|
424 | #. The target C compiler and machine options need to be provided to make sure |
---|
425 | the correct ABI for the target is used. See :ref:`MachineFlagsandABI`. |
---|
426 | |
---|
427 | .. index:: embedded symbol table |
---|
428 | .. _EmbbeddedSymbolTable: |
---|
429 | |
---|
430 | Embedded Symbols |
---|
431 | ^^^^^^^^^^^^^^^^ |
---|
432 | |
---|
433 | An embedded symbol table is *embedded* within the base image executable file and |
---|
434 | loaded when the static executable is loaded into memory by the bootloader. The |
---|
435 | symbol table is automatically added to the link editor's global symbol table |
---|
436 | when the first executable object file is loaded. |
---|
437 | |
---|
438 | The process to embed the symbol table requires linking the base image twice. |
---|
439 | The first link is to create a static executable that collects together the |
---|
440 | symbols to make the symbol table. The RTEMS Tools command `rtems-syms` extracts |
---|
441 | the global and weak symbols from the static executable ELF file, creates a C |
---|
442 | file and compiles it to create an executable object file. The base image is |
---|
443 | linked a second time and this time the symbol table executable object file is |
---|
444 | added to the list of object files. |
---|
445 | |
---|
446 | Embedding the symbol table means the chances of the symbol table and base image |
---|
447 | not matching is low, however it also means the symbol table is always present in |
---|
448 | the kernel image when dynamic loading may be optional. A project's build system |
---|
449 | is made more complex as it needs to have extra steps to link a second time. |
---|
450 | |
---|
451 | This example shows creating an embedded symbol table object file and linking it |
---|
452 | into the base image. |
---|
453 | |
---|
454 | .. code-block:: shell |
---|
455 | |
---|
456 | $ sparc-rtems5-gcc -mcpu=cypress foo.o -lrtemsbsp -lrtemscpu -o foo.pre |
---|
457 | $ rtems-syms -e -C sparc-rtems5-gcc -c "-mcpu=cypress" -o foo-sym.o foo.pre |
---|
458 | $ sparc-rtems5-gcc -mcpu=cypress foo.o foo-sym.o -lrtemsbsp -lrtemscpu -o foo.exe |
---|
459 | |
---|
460 | The link command line steps in this example are not complete. |
---|
461 | |
---|
462 | .. _LoadableSymbolTable: |
---|
463 | |
---|
464 | Loadable Symbols |
---|
465 | ^^^^^^^^^^^^^^^^ |
---|
466 | |
---|
467 | A run-time loaded symbol table is the default for the command |
---|
468 | :program:`rtems-syms`. The symbol table executable object file is packaged with |
---|
469 | the other files to be dynamically loaded at run-time and placed on the target's |
---|
470 | file system. It needs to be loaded before any other executable object file are |
---|
471 | loaded or unresolved symbols can occur that will not be resolved. |
---|
472 | |
---|
473 | A run-time loaded symbol table does not consume any target resources until it is |
---|
474 | loaded. This is useful in a system that optionally needs to dynamically load |
---|
475 | code, for example as a development environment. The symbol table executable |
---|
476 | needs to exactly match the base image loading it or the behavior is |
---|
477 | unpredictable. No checks are made. |
---|
478 | |
---|
479 | The example shows creating and loading a symbol table executable object |
---|
480 | file. First create the symbol table's executable object file: |
---|
481 | |
---|
482 | .. code-block:: shell |
---|
483 | |
---|
484 | $ sparc-rtems5-gcc -mcpu=cypress foo.o -lrtemsbsp -lrtemscpu -o foo.exe |
---|
485 | $ rtems-syms -C sparc-rtems5-gcc -c "-mcpu=cypress" -o foo-sym.o foo.exe |
---|
486 | |
---|
487 | The link command line steps in this example are not complete. |
---|
488 | |
---|
489 | Load the symbol table: |
---|
490 | |
---|
491 | .. code-block:: c |
---|
492 | |
---|
493 | #include <stdbool.h> |
---|
494 | #include <stdio.h> |
---|
495 | #include <dlfcn.h> |
---|
496 | |
---|
497 | bool load (void) |
---|
498 | { |
---|
499 | void* handle = dlopen ("/foo-sym.o", RTLD_NOW | RTLD_GLOBAL); |
---|
500 | if (handle == NULL) |
---|
501 | { |
---|
502 | printf ("failed to load the symbol table: %s\n", dlerror ()); |
---|
503 | return false; |
---|
504 | } |
---|
505 | return true; |
---|
506 | } |
---|
507 | |
---|
508 | Unresolved Symbols |
---|
509 | ------------------ |
---|
510 | |
---|
511 | The RTEMS link editor does not return an error when an executable object file is |
---|
512 | loaded with unresolved symbols. This allows dependent object files to be |
---|
513 | loaded. For example an executable object file :file:`foo.o` contains the |
---|
514 | function ``foo()`` and that function calls ``bar()`` and an executable object |
---|
515 | file :file:`bar.o` contains a function ``bar()`` that calls the function |
---|
516 | ``foo()``. Either of these executable object files can be loaded first as long |
---|
517 | both are loaded before any symbols are accessed. |
---|
518 | |
---|
519 | The link editor defers the resolution of unresolved symbols until the symbol is |
---|
520 | available in the global symbol table. Executing code or accessing data in a |
---|
521 | loaded executable object file with unresolved external symbols results in |
---|
522 | unpredictable behavior. |
---|
523 | |
---|
524 | All unresolved symbols are checked after an executable object file has been |
---|
525 | loaded. If a symbol is found and resolved any relocations that reference the |
---|
526 | symbol are fixed. If valid library files have been configured the symbol table's |
---|
527 | of each library are searched and if the symbol is found the dependent executable |
---|
528 | object file is loaded. This process repeats until no more symbols can be |
---|
529 | resolved. |
---|
530 | |
---|
531 | The ``dlinfo()`` call can be used to see if a loaded executable object file has |
---|
532 | any unresolved symbols: |
---|
533 | |
---|
534 | .. code-block:: c |
---|
535 | |
---|
536 | #include <stdbool.h> |
---|
537 | #include <stdio.h> |
---|
538 | #include <dlfcn.h> |
---|
539 | |
---|
540 | bool has_unresolved(void* handle) |
---|
541 | { |
---|
542 | int unresolved; |
---|
543 | if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) < 0) |
---|
544 | { |
---|
545 | printf ("dlinfo failed: %s\n", dlerror ()); |
---|
546 | return false; |
---|
547 | } |
---|
548 | return unresolved != 0; |
---|
549 | } |
---|
550 | |
---|
551 | The handle ``RTLD_SELF`` checks for any unresolved symbols in all resident |
---|
552 | object files: |
---|
553 | |
---|
554 | .. code-block:: c |
---|
555 | |
---|
556 | if (has_unresolved(RTLD_SELF)) |
---|
557 | printf("system has unsolved symbols\n"); |
---|
558 | |
---|
559 | Libraries |
---|
560 | --------- |
---|
561 | |
---|
562 | The RTEMS link editor supports loading executable object files from |
---|
563 | libraries. Executable object files can be explicitly loaded from a library using |
---|
564 | a specific path to :ref:`dlopen() <dlopen>` and treated the same as loading a |
---|
565 | stand alone executable object file. Libraries can be searched and an executable |
---|
566 | object file containing the search symbol can be loaded automatically as a |
---|
567 | dependent executable object file. A dependent executable object file loaded from |
---|
568 | a library with no symbol references to it's symbols is orphaned and |
---|
569 | automatically unloaded and removed from the address space. |
---|
570 | |
---|
571 | .. _fig-dl-libs: |
---|
572 | |
---|
573 | .. figure:: ../../images/user/libdl-load.png |
---|
574 | :width: 65% |
---|
575 | :alt: Loading Executable Object Files |
---|
576 | :figclass: align-center |
---|
577 | |
---|
578 | Loading Executable Object Files |
---|
579 | |
---|
580 | A library is an archive format file created using the RTEMS architecture |
---|
581 | prefixed :program:`ar` command. The RTEMS tool suite provides the :program:`ar` |
---|
582 | program and system libraries such as :file:`libc.a` and :file:`libm.a` for each |
---|
583 | architecture and ABI. Libraries used by the RTEMS link editor for searching must |
---|
584 | contain a symbol table created by the :program:`ranlib` program from the RTEMS |
---|
585 | tool suite. |
---|
586 | |
---|
587 | Searching a library's symbol table and loading an executable object file |
---|
588 | containing the symbol is called *dependent loading*. Dependent loading provides |
---|
589 | a simple way to manage the dependencies when loading an executable object |
---|
590 | file. If code in an executable object file references functions or data objects |
---|
591 | that are part of a library and the symbols are not part of the base image those |
---|
592 | symbols will not resolve unless the library is on the target and available for |
---|
593 | searching and loading. Dependent loading from libraries on the target provides a |
---|
594 | simple and understandable way to manage the dependency issue between the base |
---|
595 | image, loaded code and the system libraries. |
---|
596 | |
---|
597 | The RTEMS link editor checks for the configuration file :file:`/etc/libdl.conf` |
---|
598 | on each call to :ref:`dlopen() <dlopen>`. If the file has changed since the last |
---|
599 | check it is loaded again and the contents processed. The file format is: |
---|
600 | |
---|
601 | #. Comments start with the ``#`` character. |
---|
602 | #. A line is a wildcard path of libraries to search for. The wildcard search |
---|
603 | uses the ``fnmatch()`` call. The ``fnmatch()`` function matches patterns |
---|
604 | according to the rules used by a shell. |
---|
605 | |
---|
606 | Files that match the search pattern are verified as a library and if a symbol |
---|
607 | table is found it is loaded and the symbols it contains made search-able. |
---|
608 | |
---|
609 | A call to :ref:`dlopen() <dlopen>` checks the global symbols table and any |
---|
610 | references to relocation symbols not found are *unresolved* and added to the |
---|
611 | unresolved symbol table. Once the executable object file is loaded the link |
---|
612 | editor attempts to resolve any unresolved symbols. The unresolved symbol |
---|
613 | resolver checks each unresolved symbol against the global symbol table and if |
---|
614 | not found the available library symbol tables are searched. If a symbol is found |
---|
615 | in a library the dependent executable object file is loaded. The process repeats |
---|
616 | until all unresolved symbols have been resolved and the remaining unresolved |
---|
617 | symbols are not in the global symbol table or any libraries. The loading of a |
---|
618 | library executable object file will resolve at least one symbol and it may add |
---|
619 | more unresolved symbols requiring further searching of the libraries. |
---|
620 | |
---|
621 | .. index:: strip library |
---|
622 | |
---|
623 | A library of executable object files built by the RTEMS Tool suite can contain |
---|
624 | debug information and this should be stripped before loading on to the |
---|
625 | target. The tool suite's command :program:`strip` can strip all the object files |
---|
626 | in a library with a single command. |
---|
627 | |
---|
628 | .. code-block:: shell |
---|
629 | |
---|
630 | $ sparc-rtems5-strip libc.a |
---|
631 | |
---|
632 | Large Memory |
---|
633 | ------------ |
---|
634 | |
---|
635 | The RTEMS link editor supports large memory relocations. Some architectures have |
---|
636 | instructions where the relative branch or jump offset from the instruction to |
---|
637 | the target address is limited. These instructions provide improved performance |
---|
638 | because less code generated compared to larger instructions which contain full |
---|
639 | address space references. The compact code helps lower cache pressure as well |
---|
640 | and providing improved performance for localalized functions and loops. The |
---|
641 | compiler defaults to generating the smaller instruction and as the final address |
---|
642 | map not known when generating the code, linkers need to provide glue code to |
---|
643 | extend the small address range to the enitre address space. This is called a |
---|
644 | trampoline. A trampoline is transparent to the execution of the code. |
---|
645 | |
---|
646 | The link editor parses an executable object file's relocation records to |
---|
647 | determine the number of trampolines needed. Added to this value are all |
---|
648 | unresolved symbols present in an executable object file after it is |
---|
649 | loaded. There is a slot allocated even if the symbol ends up being within range |
---|
650 | as there is no way to determine a symbol's address until it is loaded and the |
---|
651 | range calculated. |
---|
652 | |
---|
653 | The trampoline table is allocated a separate block of memory to the executable |
---|
654 | object file's text, data and constants memory. The trampoline parsing requires |
---|
655 | the executable object file's instructions (text) be in memory as the |
---|
656 | instructions are inspected by the architecture specific relocation support to |
---|
657 | determine an instruction's range. As a result the allocation for the trampoline |
---|
658 | table has to occur after the text memory has been allocated. Most instructions |
---|
659 | have relative offsets and the trampoline table is allocated at one end limiting |
---|
660 | the size of an object to half the maximum range. |
---|
661 | |
---|
662 | Trampolines support is available for the ARM and PowerPC architectures. The |
---|
663 | SPARC and Intel x86 architectures do not need trampolines and MIPS needs support |
---|
664 | added. |
---|
665 | |
---|
666 | Allocator |
---|
667 | --------- |
---|
668 | |
---|
669 | The RTEMS link editor supports custom allocators. A custom allocator lets you |
---|
670 | manage the memory used by the RTEMS link editor as it runs. Allocators could |
---|
671 | provide: |
---|
672 | |
---|
673 | #. Support for the various types of memory that can be allocated allowing |
---|
674 | specialised target support for specific use cases. |
---|
675 | #. Locking of read-only memory. The link editor unlocks read-only memory when it |
---|
676 | needs to write to it. |
---|
677 | #. Separation of memory holding code and data from the heap. |
---|
678 | |
---|
679 | The allocator can be hooked using the ``rtems_rtl_alloc_hook`` call before any |
---|
680 | calls to :ref:`dlopen() <dlopen>` are made. The hook call returns the current |
---|
681 | allocate allowing the allocators to be chained. |
---|
682 | |
---|
683 | The default allocator uses the heap. |
---|
684 | |
---|
685 | .. _rtems_rtl_alloc_tags: |
---|
686 | .. index:: rtems_rtl_alloc_tags |
---|
687 | |
---|
688 | The allocator tags specify the type of memory the allocator is handling. The tag |
---|
689 | used to allocate memory at an address must be used when making allocator |
---|
690 | calls. The ``rtems_rtl_alloc_tags`` are: |
---|
691 | |
---|
692 | .. index:: RTEMS_RTL_ALLOC_OBJECT |
---|
693 | ``RTEMS_RTL_ALLOC_OBJECT`` |
---|
694 | Allocate a generic object. The link editor uses this memory for data |
---|
695 | structures it uses to manage the linking process and resident executable |
---|
696 | object files. |
---|
697 | |
---|
698 | .. index:: RTEMS_RTL_ALLOC_SYMBOL |
---|
699 | ``RTEMS_RTL_ALLOC_SYMBOL`` |
---|
700 | Allocate memory to hold symbol data. |
---|
701 | |
---|
702 | .. index:: RTEMS_RTL_ALLOC_EXTERNAL |
---|
703 | ``RTEMS_RTL_ALLOC_EXTERNAL`` |
---|
704 | Allocate memory for unresolved external symbols. |
---|
705 | |
---|
706 | .. index:: RTEMS_RTL_ALLOC_READ |
---|
707 | ``RTEMS_RTL_ALLOC_READ`` |
---|
708 | Allocate memory for read-only data such as constants and exception tables. |
---|
709 | |
---|
710 | .. index:: RTEMS_RTL_ALLOC_READ_WRITE |
---|
711 | ``RTEMS_RTL_ALLOC_READ_WRITE`` |
---|
712 | Allocate memory for read-write data such as a initialised, uninitialized and |
---|
713 | common variables. |
---|
714 | |
---|
715 | .. index:: RTEMS_RTL_ALLOC_READ_EXEC |
---|
716 | ``RTEMS_RTL_ALLOC_READ_EXEC`` |
---|
717 | Allocate memory for code to be executed in. The address space is configure for |
---|
718 | read and execute. |
---|
719 | |
---|
720 | .. _rtems_rtl_alloc_cmd: |
---|
721 | .. index:: rtems_rtl_alloc_cmd |
---|
722 | |
---|
723 | The commands are used to control the action the allocator performs. The |
---|
724 | ``rtems_rtl_alloc_cmd`` are: |
---|
725 | |
---|
726 | .. index:: RTEMS_RTL_ALLOC_NEW |
---|
727 | ``RTEMS_RTL_ALLOC_NEW`` |
---|
728 | Allocate memory of the ``tag`` type. Returns ``NULL`` if the allocation fails. |
---|
729 | |
---|
730 | .. index:: RTEMS_RTL_ALLOC_DEL |
---|
731 | ``RTEMS_RTL_ALLOC_DEL`` |
---|
732 | Delete a previous allocation freeing the memory. The ``tag`` has to match |
---|
733 | address of the memory being deleted. |
---|
734 | |
---|
735 | .. index:: RTEMS_RTL_ALLOC_WR_ENABLE |
---|
736 | ``RTEMS_RTL_ALLOC_WR_ENABLE`` |
---|
737 | Enable writes to a region of memory previously allocated. The ``tag`` has to |
---|
738 | match the address of the memory being write enabled. The link editor may call |
---|
739 | issue this command for memory that is already write enabled. |
---|
740 | |
---|
741 | .. index:: RTEMS_RTL_ALLOC_WR_DISABLE |
---|
742 | ``RTEMS_RTL_ALLOC_WR_DISABLE`` |
---|
743 | Disable writes to a region of memory previously allocated. The ``tag`` has to |
---|
744 | match address of the memory being write disabled. The link editor may call |
---|
745 | issue this command for memory that is writable and not to be write |
---|
746 | disabled. The allocator need to manage this case. |
---|
747 | |
---|
748 | .. _rtems_rtl_allocator: |
---|
749 | .. index:: rtems_rtl_allocator |
---|
750 | |
---|
751 | The allocator handler is a single call to handle all allocator requests. The |
---|
752 | handler called on evey allocation action made by the link editor. The type of |
---|
753 | the function you need is: |
---|
754 | |
---|
755 | .. code-block:: c |
---|
756 | |
---|
757 | typedef void (*rtems_rtl_allocator)(rtems_rtl_alloc_cmd cmd, |
---|
758 | rtems_rtl_alloc_tag tag, |
---|
759 | void** address, |
---|
760 | size_t size); |
---|
761 | |
---|
762 | |
---|
763 | The arguments are: |
---|
764 | |
---|
765 | ``cmd`` |
---|
766 | The command to action. See :ref:`_rtems_rtl_alloc_cmd`. |
---|
767 | |
---|
768 | ``tag`` |
---|
769 | The type of memory the command is for. The ``tag`` must match the address for |
---|
770 | commands other than ``RTEMS_RTL_ALLOC_OBJECT``. |
---|
771 | |
---|
772 | ``address`` |
---|
773 | Pointer to the address. This is set of the ``RTEMS_RTL_ALLOC_OBJECT`` command |
---|
774 | and read for the other commands. The ``tag`` must match the address for |
---|
775 | commands that read the address from the pointer. |
---|
776 | |
---|
777 | ``size`` |
---|
778 | The size of the memory to allocate. This is only valid for the |
---|
779 | ``RTEMS_RTL_ALLOC_OBJECT`` command. |
---|
780 | |
---|
781 | The call to hook the allocator is: |
---|
782 | |
---|
783 | .. code-block:: c |
---|
784 | |
---|
785 | rtems_rtl_allocator rtems_rtl_alloc_hook (rtems_rtl_allocator handler); |
---|
786 | |
---|
787 | The current allocator is returned. You can provide a full allocator or you can |
---|
788 | filter commands. |
---|
789 | |
---|
790 | Languages |
---|
791 | --------- |
---|
792 | |
---|
793 | C is supported. |
---|
794 | |
---|
795 | C++ is supported. Initializer functions are called when an object is loaded and |
---|
796 | finalizer functions are called before it is unloaded and removed. Static |
---|
797 | constructions are initializer functions and static destructors are finalizer |
---|
798 | functions. |
---|
799 | |
---|
800 | C++ exceptions are handled across modules. The compiler generated exception |
---|
801 | tables present in an executable object file are registered with the architecture |
---|
802 | specific mechanism when loaded and deregistered when unloaded. An exception |
---|
803 | thrown in loaded code can be caught in the base image or another loaded |
---|
804 | module. If you are using C++ and exceptions it is recommended some exception |
---|
805 | code is added to the base image to place the architecture specific support in |
---|
806 | the base image. |
---|
807 | |
---|
808 | Thread Local Storage |
---|
809 | -------------------- |
---|
810 | |
---|
811 | Thread local storage (TLS) is currenly not supported by the RTEMS link |
---|
812 | editor. The RTEMS executive needs to have a special allocator added to manage |
---|
813 | dynamically allocating TLS variables in a thread. |
---|
814 | |
---|
815 | If you need TLS support in dynamically loaded code please consider the RTEMS |
---|
816 | support options. |
---|
817 | |
---|
818 | Architectures |
---|
819 | ------------- |
---|
820 | |
---|
821 | The following architectures are supported: |
---|
822 | |
---|
823 | - ARM |
---|
824 | - Blackfin |
---|
825 | - H8300 |
---|
826 | - Intel x86 (i386) |
---|
827 | - LM32 |
---|
828 | - M68K |
---|
829 | - MIPS |
---|
830 | - Moxie |
---|
831 | - PowerPC |
---|
832 | - SPARC |
---|
833 | - V850 |
---|
834 | |
---|
835 | ARM |
---|
836 | ^^^ |
---|
837 | |
---|
838 | The ARM relocation backend supports veneers which is trampolines. |
---|
839 | |
---|
840 | The veneer implementation is a single instruction and a 32bit target address |
---|
841 | making the overhead 8 bytes for each veneer. The performance overhead is a |
---|
842 | single instruction. |
---|
843 | |
---|
844 | PowerPC |
---|
845 | ^^^^^^^ |
---|
846 | |
---|
847 | The PowerPC relocation backend support trampolines and small data. |
---|
848 | |
---|
849 | The trampoline is four instructions and uses register 12 which the PowerPC ABI |
---|
850 | reserves for scratch use. The implementation loads the counter register and |
---|
851 | branches to the address it contains. The trampoline size is 16 bytes. The |
---|
852 | performance overhead is four instructions. |
---|
853 | |
---|
854 | The PowerPC relocation backend also supports small data. The sections of an |
---|
855 | executable object file are parsed and small data are tagged as needing |
---|
856 | architecture specific allocations. These sections are not allocated as part of |
---|
857 | the standard section allocation. Small data sections are allocated in the global |
---|
858 | small data region of memory. The size of this region is defined in the BSP's |
---|
859 | linker command file by setting ``bsp_section_small_data_area_size`` variable: |
---|
860 | |
---|
861 | .. code-block:: c |
---|
862 | |
---|
863 | bsp_section_small_data_area_size = 65536; |
---|
864 | |
---|
865 | The maximum size of the small data region is 65536 bytes. It is recommended code |
---|
866 | built for loading uses the same settings for small base as the base image. |
---|