]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/services/objloader/v2_0/src/objloader.c
f8f55eed16679760d3b52e831c0d1dc8a2d95f68
[karo-tx-redboot.git] / packages / services / objloader / v2_0 / src / objloader.c
1 /* =================================================================
2  *
3  *      objelf.c
4  *
5  *      An object loader for eCos
6  *
7  * ================================================================= 
8  * ####ECOSGPLCOPYRIGHTBEGIN####
9  * -------------------------------------------
10  * This file is part of eCos, the Embedded Configurable Operating
11  * System.
12  * Copyright (C) 2005 eCosCentric Ltd.
13  * 
14  * eCos is free software; you can redistribute it and/or modify it
15  * under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 or (at your option)
17  * any later version.
18  * 
19  * eCos is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with eCos; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27  * 
28  * As a special exception, if other files instantiate templates or
29  * use macros or inline functions from this file, or you compile this
30  * file and link it with other works to produce a work based on this
31  * file, this file does not by itself cause the resulting work to be
32  * covered by the GNU General Public License. However the source code
33  * for this file must still be made available in accordance with
34  * section (3) of the GNU General Public License.
35  * 
36  * This exception does not invalidate any other reasons why a work
37  * based on this file might be covered by the GNU General Public
38  * License.
39  *
40  * -------------------------------------------
41  * ####ECOSGPLCOPYRIGHTEND####
42  * =================================================================
43  * #####DESCRIPTIONBEGIN####
44  * 
45  *  Author(s):    atonizzo@lycos.com
46  *  Contributors: nickg@ecoscentric.com
47  *  Date:         2005-05-13
48  *  Purpose:      
49  *  Description:  
50  *               
51  * ####DESCRIPTIONEND####
52  * 
53  * =================================================================
54  */
55
56 #include <cyg/infra/diag.h>     // For diagnostic printing.
57 #include <cyg/infra/cyg_ass.h>
58 #include <stdlib.h>
59 #include <string.h>
60
61 #include <pkgconf/objloader.h>
62
63 #include <cyg/objloader/elf.h>
64 #include <cyg/objloader/objelf.h>
65 #include <cyg/objloader/loader_fs.h>
66
67 cyg_uint8 *cyg_ldr_last_error;
68
69 void *cyg_ldr_malloc( size_t ) CYGBLD_ATTRIB_WEAK;
70 void
71 *cyg_ldr_malloc( size_t s )
72 {
73     return malloc( s );
74 }
75
76 void cyg_ldr_free( void * ) CYGBLD_ATTRIB_WEAK;
77 void
78 cyg_ldr_free( void *s )
79 {
80     free( s );
81 }
82
83 void
84 cyg_ldr_delete_elf_section( PELF_OBJECT p, cyg_uint32 idx )
85 {
86     cyg_ldr_free( p->sections[idx] );
87     p->sections[idx] = 0; 
88 }    
89
90 // Frees all the memory allocated for a particular ELF object. Also calls
91 //  the close() function to close files or sockets, and finally frees up
92 //  the ELF object altogether.
93 static void
94 cyg_ldr_free_elf_object( PELF_OBJECT p )
95 {
96     cyg_int32 i;
97         
98     for ( i = 0; i < p->p_elfhdr->e_shnum + 1; i++ )
99         if ( p->sections[i] )
100             cyg_ldr_delete_elf_section( p, i );
101
102     if ( p->sections != 0 )
103         cyg_ldr_free( p->sections ); 
104
105     if ( p->p_sechdr != 0 )
106         cyg_ldr_free( p->p_sechdr ); 
107
108     if ( p->p_elfhdr != 0 )
109         cyg_ldr_free( p->p_elfhdr ); 
110
111     p->close( p );    
112     cyg_ldr_free( p );
113 }        
114
115 static cyg_uint32 
116 cyg_ldr_find_common_size( PELF_OBJECT p )
117 {
118     cyg_int32 i, symtab_entries, common_size = 0;
119     Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
120      
121     // Total number of entries in the symbol table.
122     symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size / 
123                                 p->p_sechdr[p->hdrndx_symtab].sh_entsize;
124     for ( i = 1; i < symtab_entries; i++ )
125         if ( p_symtab[i].st_shndx == SHN_COMMON )
126         {
127             // In the case of an SHN_COMMON symbol the st_value field holds 
128             //  alignment constraints.
129             cyg_uint32 boundary = p_symtab[i].st_value - 1;
130
131             // Calculate the next byte boundary.
132             common_size = ( common_size + boundary ) & ~boundary;
133             common_size += p_symtab[i].st_size;
134         }    
135
136 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
137     diag_printf( "common_size = %d\n", common_size );
138 #endif
139     return common_size;
140 }
141
142 // Allocates memory and loads the contents of a specific ELF section.
143 // Returns the address of the newly allocated memory, of 0 for any error.
144 cyg_int32 
145 *cyg_ldr_load_elf_section( PELF_OBJECT p, cyg_uint32 idx )
146 {
147     cyg_uint32 *addr;
148     
149     addr = cyg_ldr_malloc( p->p_sechdr[idx].sh_size );
150     CYG_ASSERT( addr != 0, "Cannot malloc() section" );
151     if ( addr == 0 )
152     {
153         cyg_ldr_last_error = "ERROR IN MALLOC";
154         return (void*)0;
155     }
156     p->seek( p, p->p_sechdr[idx].sh_offset );
157     p->read( p, sizeof( char ), p->p_sechdr[idx].sh_size, addr );
158     return addr;
159 }    
160
161 // Returns the starting address of a section. If the section is not already
162 //  loaded in memory, area for it will be allocated and the section will be
163 //  loaded.
164 cyg_int32 
165 *cyg_ldr_section_address( PELF_OBJECT p, cyg_uint32 idx )
166 {
167     if ( p->sections[idx] == 0 )
168         p->sections[idx] = cyg_ldr_load_elf_section( p, idx );
169
170     return p->sections[idx];
171 }
172
173 void
174 *cyg_ldr_find_symbol( void* handle, cyg_uint8* sym_name )
175 {
176     PELF_OBJECT p = (PELF_OBJECT)handle;
177     cyg_uint8* tmp2;
178     cyg_int32  i, symtab_entries;
179     cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->hdrndx_strtab];
180     Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
181   
182     symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size / 
183                                p->p_sechdr[p->hdrndx_symtab].sh_entsize;
184
185     for ( i = 0; i < symtab_entries; i++ )
186     {
187         tmp2 = p_strtab + p_symtab[i].st_name;
188         if ( !strcmp( tmp2, sym_name ) )
189             return cyg_ldr_symbol_address( p, i );
190     }
191
192     // Symbol not found.
193     cyg_ldr_last_error = "SYMBOL NOT FOUND";
194     return 0;
195 }
196
197 static cyg_uint8
198 *cyg_ldr_sanity_check( PELF_OBJECT p )
199 {
200     if ( ( p->p_elfhdr->e_ident[EI_MAG0] != ELFMAG0 )  || 
201          ( p->p_elfhdr->e_ident[EI_MAG1] != ELFMAG1 )  ||
202          ( p->p_elfhdr->e_ident[EI_MAG2] != ELFMAG2  ) || 
203          ( p->p_elfhdr->e_ident[EI_MAG3] != ELFMAG3 )  || 
204          ( p->p_elfhdr->e_ident[EI_CLASS] != ELFCLASS32 ) )
205         return "INVALID ELF HEADER";
206
207     // We only work with relocatable files. No dynamic linking.
208     if ( p->p_elfhdr->e_type != ET_REL )
209         return "NOT RELOCATABLE";
210         
211     // These #defines are sitting in the hal.
212     if ( p->p_elfhdr->e_machine != ELF_ARCH_MACHINE_TYPE )
213         return "INVALID ARCHITECTURE";
214
215     if ( p->p_elfhdr->e_ident[EI_DATA] != ELF_ARCH_ENDIANNESS )
216         return "INVALID ENDIAN";
217     return 0;  }     
218
219 // Load only the ELF header and the sections header. These are the only
220 //  sections loaded during library initialization. All the other sections
221 //  will be loaded on demand when needed during the relocation process and,
222 //  when possible, dumped after use.
223 static cyg_int32 
224 cyg_ldr_load_sections( PELF_OBJECT p )
225 {
226     cyg_uint8  *error_string;
227     cyg_int32  idx;
228
229     // Load the ELF header.
230     p->p_elfhdr = (Elf32_Ehdr*)cyg_ldr_malloc( sizeof( Elf32_Ehdr ) );
231     CYG_ASSERT( p->p_elfhdr != 0, "Cannot malloc() p->p_elfhdr" );
232     if ( p->p_elfhdr == 0 )
233         return -1;
234     p->seek( p, 0 );
235     p->read( p, sizeof( char ), sizeof( Elf32_Ehdr ), p->p_elfhdr  );
236     error_string = cyg_ldr_sanity_check( p );
237     if ( error_string != 0 )
238     {
239         cyg_ldr_last_error = "ERROR IN ELF HEADER";
240         return -1;
241     }    
242     
243     // Allocate an array that can hold an address to all the section of this
244     //  library. This is not strictly optimal, since some sections do not
245     //  need to be loaded all the time. Allocate an extra pointer for the
246     //  COMMON area. 
247     p->sections = cyg_ldr_malloc( ( p->p_elfhdr->e_shnum + 1 ) * 
248                                                      sizeof( cyg_uint32 ) );
249     CYG_ASSERT( p->sections != 0, "Cannot malloc() p->sections" );
250     if ( p->sections == 0 )
251     {
252         cyg_ldr_last_error = "ERROR IN MALLOC";
253         return -1;
254     }
255     memset( p->sections, 0, ( p->p_elfhdr->e_shnum + 1 ) * 
256                                                      sizeof( cyg_uint32 ) );
257     
258     // Now that the header is loaded, load the sections header.
259     p->p_sechdr = (Elf32_Shdr*)cyg_ldr_malloc( 
260                              p->p_elfhdr->e_shnum * p->p_elfhdr->e_shentsize );
261     CYG_ASSERT( p->p_sechdr != 0, "Cannot malloc() p->p_sechdr" );
262     if ( p->p_sechdr == 0 )
263     {
264         cyg_ldr_last_error = "ERROR IN MALLOC";
265         return -1;
266     }
267     p->seek( p, p->p_elfhdr->e_shoff );
268     p->read( p, p->p_elfhdr->e_shentsize, p->p_elfhdr->e_shnum, p->p_sechdr );
269     
270     // Load the section header string table. This is a byte oriented table,
271     //  so alignment is not an issue.
272     idx = p->p_elfhdr->e_shstrndx;
273     p->sections[idx] = cyg_ldr_load_elf_section( p, idx );
274     return 0;
275 }
276
277 PELF_OBJECT
278 cyg_ldr_open_library( CYG_ADDRWORD ptr, cyg_int32 mode )
279 {
280     Elf32_Sym *p_symtab;
281     cyg_uint8 *p_shstrtab;
282     PELF_OBJECT e_obj; 
283     int (*fn)(void);
284     cyg_int32   i, rc, symtab_entries;
285     cyg_uint32  common_size;
286
287     // In the future there might be a switch() (against 'mode') that calls an
288     //  open function other than cyg_ldr_open_library_fs(). These function
289     //  fetch and open a library using ftp, http or libraries that are already 
290     //  in ROM.
291     e_obj = cyg_ldr_open_library_fs( (cyg_uint8*)ptr );
292     if ( e_obj == 0 )
293         return 0;
294     rc = cyg_ldr_load_sections( e_obj );
295     if ( rc != 0 )
296     {
297         cyg_ldr_free_elf_object( e_obj );
298         return 0;
299     }    
300
301     // Find the section index for the .shstrtab section. The names of the 
302     //  sections are held here, and are the only way to identify them.
303     p_shstrtab = (cyg_uint8*)cyg_ldr_section_address( e_obj, 
304                                                  e_obj->p_elfhdr->e_shstrndx );
305     if ( p_shstrtab == 0 )
306     {
307         cyg_ldr_free_elf_object( e_obj );
308         return 0;
309     }    
310
311     // .symtab section and .strtab. We have to go through the section names
312     //  to find where they are.
313     for ( i = 1; i < e_obj->p_elfhdr->e_shnum; i++ )
314     {
315         // Now look for the index of .symtab. These are the symbols needed for 
316         //  the symbol retrieval as well as relocation.
317         if ( !strcmp( p_shstrtab + e_obj->p_sechdr[i].sh_name, 
318                       ELF_STRING_symtab ) )
319         {              
320             e_obj->hdrndx_symtab = i;
321             e_obj->sections[i] = cyg_ldr_load_elf_section( e_obj, i );
322             if ( e_obj->sections[i] == 0 )
323             {
324                 cyg_ldr_free_elf_object( e_obj );
325                 return 0;
326             }    
327         }    
328         
329         // Load the table with the names of all the symbols. We need this
330         //  to compare the name of external references symbols against the
331         //  names in the in the CYG_HAL_TABLE provided by the user.
332         if ( !strcmp( p_shstrtab + e_obj->p_sechdr[i].sh_name, 
333                       ELF_STRING_strtab ) )
334         {              
335             e_obj->hdrndx_strtab = i;
336             e_obj->sections[i] = cyg_ldr_load_elf_section( e_obj, i );
337             if ( e_obj->sections[i] == 0 )
338             {
339                 cyg_ldr_free_elf_object( e_obj );
340                 return 0;
341             }    
342         }    
343     }                                              
344
345     CYG_ASSERT( e_obj->hdrndx_symtab != 0, "No symtab index found" );
346     CYG_ASSERT( e_obj->hdrndx_strtab != 0, "No strtab index found" );
347
348     // Now look for symbols in the COMMON area. The COMMON symbols are a 
349     //  special case, because the area they reside in must be sized up
350     //  and allocated separately from the other sections, which appear in
351     //  the sections header and can be read out of the library itself.
352     // Extra room in the 'sections' array has already been allocated to hold 
353     //  the pointer to the commons area.
354     common_size = cyg_ldr_find_common_size( e_obj ); 
355     if ( common_size != 0 )
356     {
357         cyg_uint32 com_shndx = e_obj->p_elfhdr->e_shnum;
358         cyg_int32  com_offset = 0;
359         
360         e_obj->sections[com_shndx] = (cyg_uint32*)cyg_ldr_malloc( common_size );
361         CYG_ASSERT( e_obj->sections[com_shndx] != 0, 
362                     "Cannot malloc() the COMMONS" );
363    
364         if ( e_obj->sections[com_shndx] == 0 )
365         {
366             cyg_ldr_free_elf_object( e_obj );
367             return 0;
368         }    
369
370         // Now find all the symbols in the SHN_COMMON area and make 
371         //  them  point to the newly allocated COM area.
372         symtab_entries = e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_size / 
373                               e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_entsize;
374         p_symtab = (Elf32_Sym*)e_obj->sections[e_obj->hdrndx_symtab];
375     
376 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
377         diag_printf( "Num   Value   Size Ndx Name\n" ); 
378 #endif
379         for ( i = 1; i < symtab_entries; i++ )
380         {
381 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
382             cyg_uint8 *p_strtab = (cyg_uint8*)cyg_ldr_section_address( e_obj, 
383                                                         e_obj->hdrndx_strtab );
384 #endif        
385             if ( p_symtab[i].st_shndx == SHN_COMMON )
386             {             
387                 cyg_uint32 boundary = p_symtab[i].st_value - 1;
388                 // Calculate the next byte boundary.
389                 com_offset = ( com_offset + boundary ) & ~boundary;
390                 p_symtab[i].st_shndx = com_shndx;
391                 p_symtab[i].st_value = com_offset;
392                 com_offset += p_symtab[i].st_size;
393             }
394     
395 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
396             diag_printf( "%03d  %08X %04X %03d %s\n", 
397                          i, 
398                          p_symtab[i].st_value,
399                          p_symtab[i].st_size,
400                          p_symtab[i].st_shndx,
401                          p_strtab + p_symtab[i].st_name );
402 #endif        
403         }    
404     }
405
406 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
407     cyg_ldr_print_section_data( e_obj );
408 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
409     cyg_ldr_print_symbol_names( e_obj );
410 #endif    
411 #endif    
412
413     for ( i = 1; i < e_obj->p_elfhdr->e_shnum; i++ )
414     {
415         // Find all the '.rel' or '.rela' sections and relocate them.
416         if ( ( e_obj->p_sechdr[i].sh_type == SHT_REL ) ||
417                                   ( e_obj->p_sechdr[i].sh_type == SHT_RELA ) )
418         {
419             // Load and relocate the section.
420             rc = cyg_ldr_relocate_section( e_obj, i );
421             if ( rc < 0 )
422             { 
423 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
424                 ELFDEBUG( "Relocation unsuccessful\n" );
425 #endif
426                 cyg_ldr_free_elf_object( e_obj );
427                 return 0;
428             }    
429         }    
430     }    
431
432     // Synch up the caches before calling any function in the library.
433     cyg_ldr_flush_cache();
434
435     // Run the library initialization code.
436     fn = cyg_ldr_find_symbol( e_obj, "library_open" );
437     if ( fn != 0 )
438         fn();
439     return ((void*)e_obj);
440 }
441
442 cyg_uint8
443 *cyg_ldr_error( void )
444 {
445     cyg_uint8* p = cyg_ldr_last_error;
446     cyg_ldr_last_error = NULL;
447     return p;
448 }
449
450 void cyg_ldr_close_library( void* handle )
451 {
452     void (*fn)(void);
453
454     PELF_OBJECT p = (PELF_OBJECT)handle;
455     fn = cyg_ldr_find_symbol( p, "library_close" );
456     if ( fn != 0 )
457         fn();
458
459     cyg_ldr_free_elf_object( p );
460     p = 0;
461 }
462