1 |
786 |
skrzyp |
These are very preliminary notes on the design and use of the object loader.
|
2 |
|
|
Users should be aware that the package is still undergoing some changes.
|
3 |
|
|
Feedback is appreciated.
|
4 |
|
|
|
5 |
|
|
--------------------------------------------------------------------------------
|
6 |
|
|
Creating libraries
|
7 |
|
|
--------------------------------------------------------------------------------
|
8 |
|
|
Libraries can be created by simply compiling the sources into .o files.
|
9 |
|
|
The typical command line will look something like this:
|
10 |
|
|
|
11 |
|
|
-gcc -c -I$(ECOS_DIRECTORY)/include -Wall hello.c
|
12 |
|
|
|
13 |
|
|
The eCos "include" directory is needed to get the header files for the API.
|
14 |
|
|
Multiple object files can be compiled into a single object with the
|
15 |
|
|
|
16 |
|
|
-ld -r -o out.o file1.o file2.o file3.o
|
17 |
|
|
|
18 |
|
|
It must be noted that the use of a linker to collect multiple object files
|
19 |
|
|
into a single one considerably increases the size of the symbol table.
|
20 |
|
|
|
21 |
|
|
--------------------------------------------------------------------------------
|
22 |
|
|
Init/fini functions
|
23 |
|
|
--------------------------------------------------------------------------------
|
24 |
|
|
When the library is loaded the loader will look for a symbol with the name of
|
25 |
|
|
"library_open" and, if found, will call the symbol with a prototype of
|
26 |
|
|
|
27 |
|
|
void library_open(void)
|
28 |
|
|
|
29 |
|
|
When the cyg_ldr_close_library() function is called, the loader will also
|
30 |
|
|
look for a function called library close() and call it. The prototype is the
|
31 |
|
|
same as library_open().
|
32 |
|
|
|
33 |
|
|
--------------------------------------------------------------------------------
|
34 |
|
|
External references.
|
35 |
|
|
--------------------------------------------------------------------------------
|
36 |
|
|
External references are the calls that the library makes to the eCos. These
|
37 |
|
|
calls are resolved by the loader if the function name is available in a table
|
38 |
|
|
provided by the user which maps a function name with its pointer. The loader
|
39 |
|
|
provides an empty table so that the user need only provide additional entry
|
40 |
|
|
required by the relocator.
|
41 |
|
|
|
42 |
|
|
In order to keep the size of the table to a minimum, the user can selectively
|
43 |
|
|
include only those functions that are expected to be used by the loader to
|
44 |
|
|
resolve all references.
|
45 |
|
|
|
46 |
|
|
The following is an example of how to add an entry to the external references
|
47 |
|
|
table:
|
48 |
|
|
|
49 |
|
|
CYG_LDR_TABLE_ENTRY(diag_printf_entry, "diag_printf", diag_printf);
|
50 |
|
|
|
51 |
|
|
The first parameter is a unique identifier, the second is a string containing
|
52 |
|
|
the name of the function, and the third is the pointer to the function itself.
|
53 |
|
|
The entries can be added anywhere in the file.
|
54 |
|
|
|
55 |
|
|
The objelf.h file contains a number of macros that collect groups of
|
56 |
|
|
functions together as a convenient way to include blocks of
|
57 |
|
|
functionality.
|
58 |
|
|
|
59 |
|
|
|
60 |
|
|
--------------------------------------------------------------------------------
|
61 |
|
|
Writing the relocator for a new architecture
|
62 |
|
|
--------------------------------------------------------------------------------
|
63 |
|
|
A relocator for a new architecture must provide a function with the following
|
64 |
|
|
prototype:
|
65 |
|
|
|
66 |
|
|
cyg_int32
|
67 |
|
|
cyg_ldr_relocate(cyg_int32 sym_type, cyg_uint32 mem, cyg_int32 sym_value)
|
68 |
|
|
|
69 |
|
|
The sym type is the type of relocation to apply. This value is architecture
|
70 |
|
|
dependent and it is obtained from the r_info field of the relocation entry.
|
71 |
|
|
The mem address is the memory location to relocate. The sym_value is the
|
72 |
|
|
value to use for the relocation. The size of the write operation is dependent
|
73 |
|
|
on the sym_type value.
|
74 |
|
|
|
75 |
|
|
The relocate_xxx.h file must provide definitions for:
|
76 |
|
|
|
77 |
|
|
1) the machine ELF type
|
78 |
|
|
2) the endianness of the architecture
|
79 |
|
|
ELFDATA2MSB : Big endian
|
80 |
|
|
ELFDATA2LSB : Little endian
|
81 |
|
|
3) The relocation type
|
82 |
|
|
Elf_Rela : With addend
|
83 |
|
|
Elf_Rel : Without addend
|
84 |
|
|
|
85 |
|
|
An example of the definition for the PowerPC processor is the following:
|
86 |
|
|
|
87 |
|
|
#define ELF_ARCH_MACHINE_TYPE 20 // PowerPC.
|
88 |
|
|
#define ELF_ARCH_ENDIANNESS ELFDATA2MSB // Big Endian.
|
89 |
|
|
#define ELF_ARCH_RELTYPE Elf_Rela // With explicit addend.
|
90 |
|
|
|
91 |
|
|
These definitions can be found in the relocate_ppc.h file.
|
92 |
|
|
|
93 |
|
|
The user must also provide a function with the following prototype:
|
94 |
|
|
|
95 |
|
|
void cyg_ldr_flush_cache(void)
|
96 |
|
|
|
97 |
|
|
tha is used to flush the data and address caches. This is architecture
|
98 |
|
|
dependent and usually the macros to do this are already part of the eCos HAL.
|
99 |
|
|
An empty function can be used is caches are not available.
|
100 |
|
|
|
101 |
|
|
--------------------------------------------------------------------------------
|
102 |
|
|
CDL File
|
103 |
|
|
--------------------------------------------------------------------------------
|
104 |
|
|
|
105 |
|
|
The CDL file allows the selective compilation of the architecture dependent
|
106 |
|
|
file. If a new architecture is added or a new loader is added, the CDL file
|
107 |
|
|
must be updated to include the architecture dependent files.
|
108 |
|
|
|
109 |
|
|
--------------------------------------------------------------------------------
|
110 |
|
|
Test program
|
111 |
|
|
--------------------------------------------------------------------------------
|
112 |
|
|
|
113 |
|
|
The 'tests' directory contains a simple/sample application that shows how to
|
114 |
|
|
use the object loader. The application loads a couple of symbols and runs
|
115 |
|
|
the functions pointed by those symbols. In particular, the second symbol is
|
116 |
|
|
a function which, in the library, is declared with the CYGBLD_ATTRIB_WEAK. If
|
117 |
|
|
the entry
|
118 |
|
|
|
119 |
|
|
CYG_LDR_TABLE_ENTRY( weak_function_entry, "weak_function", weak_function );
|
120 |
|
|
|
121 |
|
|
is found in the application then the function in the application is called.
|
122 |
|
|
Otherwise, the function in the library is.
|
123 |
|
|
|
124 |
|
|
The source code for the library used for this example can be found under the
|
125 |
|
|
'library' directory.
|
126 |
|
|
|
127 |
|
|
The library shows a number of concepts, including external references and WEAK
|
128 |
|
|
references. The ubiquitous "twothreads' application is also included, and run
|
129 |
|
|
by the main application. Notice the initialization of the semaphore in the
|
130 |
|
|
library_open() call.
|
131 |
|
|
|
132 |
|
|
The library can be compiled with the command
|
133 |
|
|
|
134 |
|
|
-gcc -c -Wall -o hello.o hello.c
|
135 |
|
|
|
136 |
|
|
and then be put into some file system and loaded. In the specific example
|
137 |
|
|
provided, the library was placed in the root directory of a FAT partition.
|
138 |
|
|
JFFS2 is also an option.
|
139 |
|
|
|
140 |
|
|
If the CDL option CYGBLD_SERVICES_OBJLOADER_BUILD_TESTS is enabled,
|
141 |
|
|
then the test program and the library will be compiled automatically
|
142 |
|
|
and placed in the install tree bin directory.
|
143 |
|
|
|
144 |
|
|
--------------------------------------------------------------------------------
|
145 |
|
|
Final musings
|
146 |
|
|
--------------------------------------------------------------------------------
|
147 |
|
|
|
148 |
|
|
The cyg_ldr_open_library() call can be modified so that the user can use a
|
149 |
|
|
library that is already in memory, or one that must be retrieved via ftp or
|
150 |
|
|
tftp. In order to do this some functions must be added:
|
151 |
|
|
|
152 |
|
|
- A function to open the file. In the simplest case of a file system, this
|
153 |
|
|
function would be a wrapper for fopen(). See loader_fs.c for a possible
|
154 |
|
|
implementation for a file system
|
155 |
|
|
- Function to read, seek and close the library.
|
156 |
|
|
- In case you have a statically allocated memory pool, you might want to
|
157 |
|
|
define your own cyg_ldr_malloc() and cyg_ldr_free(). Currently they are
|
158 |
|
|
defined as weak bindings to wrappers of the malloc() and free() functions
|
159 |
|
|
- The relocator for the ARM architecture only works for ARMv4T cores and
|
160 |
|
|
later ones. The problem arises from the fact that without the Thumb
|
161 |
|
|
instruction set the loader should replace every "BX Rm" in the library
|
162 |
|
|
with "MOV PC, Rm". This assumes that the library can find out what core it
|
163 |
|
|
is running on at runtime, which is not possible at the moment. Given that
|
164 |
|
|
ARMv4T cores are the ones used by most IC suppliers (Atmel, NXP, ST just
|
165 |
|
|
to name a few) it is expected that the current code will work for nearly
|
166 |
|
|
everyone.
|
167 |
|
|
|