]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/services/objloader/v2_0/src/objloader.c
unified MX27, MX25, MX37 trees
[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):    Anthony Tonizzo (atonizzo@gmail.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 char *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, 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     int 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_uint32 
145 *cyg_ldr_load_elf_section(PELF_OBJECT p, cyg_uint32 idx)
146 {
147     cyg_uint32 *addr = (cyg_uint32 *)cyg_ldr_malloc(p->p_sechdr[idx].sh_size);
148     CYG_ASSERT(addr != 0, "Cannot malloc() section");
149     if (addr == 0)
150     {
151         cyg_ldr_last_error = "ERROR IN MALLOC";
152         return (void*)0;
153     }
154     p->seek(p, p->p_sechdr[idx].sh_offset);
155     p->read(p, sizeof(char), p->p_sechdr[idx].sh_size, addr);
156     return addr;
157 }    
158
159 // Returns the starting address of a section. If the section is not already
160 //  loaded in memory, area for it will be allocated and the section will be
161 //  loaded.
162 cyg_uint32 
163 *cyg_ldr_section_address(PELF_OBJECT p, cyg_uint32 idx)
164 {
165     if (p->sections[idx] == 0)
166         p->sections[idx] = cyg_ldr_load_elf_section(p, idx);
167
168     return p->sections[idx];
169 }
170
171 void
172 *cyg_ldr_find_symbol(void* handle, char* sym_name)
173 {
174     PELF_OBJECT p = (PELF_OBJECT)handle;
175     int         i;
176     char *p_strtab = (char*)p->sections[p->hdrndx_strtab];
177     Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
178  
179     int symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size / 
180                                p->p_sechdr[p->hdrndx_symtab].sh_entsize;
181
182     for (i = 0; i < symtab_entries; i++)
183     {
184         char* tmp2 = p_strtab + p_symtab[i].st_name;
185         if (!strcmp(tmp2, sym_name))
186             return cyg_ldr_symbol_address(p, i);
187     }
188
189     // Symbol not found.
190     cyg_ldr_last_error = "SYMBOL NOT FOUND";
191     return 0;
192 }
193
194 static char
195 *cyg_ldr_sanity_check(PELF_OBJECT p)
196 {
197     if ((p->p_elfhdr->e_ident[EI_MAG0] != ELFMAG0)  || 
198          (p->p_elfhdr->e_ident[EI_MAG1] != ELFMAG1)  ||
199          (p->p_elfhdr->e_ident[EI_MAG2] != ELFMAG2 ) || 
200          (p->p_elfhdr->e_ident[EI_MAG3] != ELFMAG3)  || 
201          (p->p_elfhdr->e_ident[EI_CLASS] != ELFCLASS32))
202         return "INVALID ELF HEADER";
203
204     // We only work with relocatable files. No dynamic linking.
205     if (p->p_elfhdr->e_type != ET_REL)
206         return "NOT RELOCATABLE";
207         
208     // These #defines are sitting in the hal.
209     if (p->p_elfhdr->e_machine != ELF_ARCH_MACHINE_TYPE)
210         return "INVALID ARCHITECTURE";
211
212     if (p->p_elfhdr->e_ident[EI_DATA] != ELF_ARCH_ENDIANNESS)
213         return "INVALID ENDIAN";
214     return 0;  }     
215
216 // Load only the ELF header and the sections header. These are the only
217 //  sections loaded during library initialization. All the other sections
218 //  will be loaded on demand when needed during the relocation process and,
219 //  when possible, dumped after use.
220 static cyg_int32 
221 cyg_ldr_load_sections(PELF_OBJECT p)
222 {
223     char      *error_string;
224     cyg_int32  idx;
225
226     // Load the ELF header.
227     p->p_elfhdr = (Elf32_Ehdr*)cyg_ldr_malloc(sizeof(Elf32_Ehdr));
228     CYG_ASSERT(p->p_elfhdr != 0, "Cannot malloc() p->p_elfhdr");
229     if (p->p_elfhdr == 0)
230         return -1;
231     p->seek(p, 0);
232     p->read(p, sizeof(char), sizeof(Elf32_Ehdr), p->p_elfhdr );
233     error_string = cyg_ldr_sanity_check(p);
234     if (error_string != 0)
235     {
236         cyg_ldr_last_error = "ERROR IN ELF HEADER";
237         return -1;
238     }    
239     
240     // Allocate an array that can hold an address to all the section of this
241     //  library. This is not strictly optimal, since some sections do not
242     //  need to be loaded all the time. Allocate an extra pointer for the
243     //  COMMON area. 
244     p->sections = cyg_ldr_malloc((p->p_elfhdr->e_shnum + 1) * 
245                                                      sizeof(cyg_uint32));
246     CYG_ASSERT(p->sections != 0, "Cannot malloc() p->sections");
247     if (p->sections == 0)
248     {
249         cyg_ldr_last_error = "ERROR IN MALLOC";
250         return -1;
251     }
252     memset(p->sections, 0, (p->p_elfhdr->e_shnum + 1) * 
253                                                      sizeof(cyg_uint32));
254     
255     // Now that the header is loaded, load the sections header.
256     p->p_sechdr = (Elf32_Shdr*)cyg_ldr_malloc(
257                              p->p_elfhdr->e_shnum * p->p_elfhdr->e_shentsize);
258     CYG_ASSERT(p->p_sechdr != 0, "Cannot malloc() p->p_sechdr");
259     if (p->p_sechdr == 0)
260     {
261         cyg_ldr_last_error = "ERROR IN MALLOC";
262         return -1;
263     }
264     p->seek(p, p->p_elfhdr->e_shoff);
265     p->read(p, p->p_elfhdr->e_shentsize, p->p_elfhdr->e_shnum, p->p_sechdr);
266     
267     // Load the section header string table. This is a byte oriented table,
268     //  so alignment is not an issue.
269     idx = p->p_elfhdr->e_shstrndx;
270     p->sections[idx] = cyg_ldr_load_elf_section(p, idx);
271     return 0;
272 }
273
274 PELF_OBJECT
275 cyg_ldr_open_library(CYG_ADDRWORD ptr, cyg_int32 mode)
276 {
277     int (*fn)(void);
278     int         i;
279
280     // In the future there might be a switch() (against 'mode') that calls an
281     //  open function other than cyg_ldr_open_library_fs(). These function
282     //  fetch and open a library using ftp, http or libraries that are already 
283     //  in ROM.
284     PELF_OBJECT e_obj = cyg_ldr_open_library_fs((char*)ptr);
285     if (e_obj == 0)
286         return 0;
287     int rc = cyg_ldr_load_sections(e_obj);
288     if (rc != 0)
289     {
290         cyg_ldr_free_elf_object(e_obj);
291         return 0;
292     }    
293
294     // Find the section index for the .shstrtab section. The names of the 
295     //  sections are held here, and are the only way to identify them.
296     char *p_shstrtab = (char*)cyg_ldr_section_address(e_obj, 
297                                                 e_obj->p_elfhdr->e_shstrndx);
298     if (p_shstrtab == 0)
299     {
300         cyg_ldr_free_elf_object(e_obj);
301         return 0;
302     }    
303
304     // .symtab section and .strtab. We have to go through the section names
305     //  to find where they are.
306     for (i = 1; i < e_obj->p_elfhdr->e_shnum; i++)
307     {
308         // Now look for the index of .symtab. These are the symbols needed for 
309         //  the symbol retrieval as well as relocation.
310         if (!strcmp(p_shstrtab + e_obj->p_sechdr[i].sh_name, ELF_STRING_symtab))
311         {              
312             e_obj->hdrndx_symtab = i;
313             e_obj->sections[i] = cyg_ldr_load_elf_section(e_obj, i);
314             if (e_obj->sections[i] == 0)
315             {
316                 cyg_ldr_free_elf_object(e_obj);
317                 return 0;
318             }    
319         }    
320         
321         // Load the table with the names of all the symbols. We need this
322         //  to compare the name of external references symbols against the
323         //  names in the in the CYG_HAL_TABLE provided by the user.
324         if (!strcmp(p_shstrtab + e_obj->p_sechdr[i].sh_name, ELF_STRING_strtab))
325         {              
326             e_obj->hdrndx_strtab = i;
327             e_obj->sections[i] = cyg_ldr_load_elf_section(e_obj, i);
328             if (e_obj->sections[i] == 0)
329             {
330                 cyg_ldr_free_elf_object(e_obj);
331                 return 0;
332             }    
333         }    
334     }                                              
335
336     CYG_ASSERT(e_obj->hdrndx_symtab != 0, "No symtab index found");
337     CYG_ASSERT(e_obj->hdrndx_strtab != 0, "No strtab index found");
338
339     // Now look for symbols in the COMMON area. The COMMON symbols are a 
340     //  special case, because the area they reside in must be sized up
341     //  and allocated separately from the other sections, which appear in
342     //  the sections header and can be read out of the library itself.
343     // Extra room in the 'sections' array has already been allocated to hold 
344     //  the pointer to the commons area.
345     cyg_uint32 common_size = cyg_ldr_find_common_size(e_obj); 
346     if (common_size != 0)
347     {
348         cyg_uint32 com_shndx = e_obj->p_elfhdr->e_shnum;
349         cyg_int32  com_offset = 0;
350         
351         e_obj->sections[com_shndx] = (cyg_uint32*)cyg_ldr_malloc(common_size);
352         CYG_ASSERT(e_obj->sections[com_shndx] != 0, 
353                     "Cannot malloc() the COMMONS");
354    
355         if (e_obj->sections[com_shndx] == 0)
356         {
357             cyg_ldr_free_elf_object(e_obj);
358             return 0;
359         }    
360
361         // Now find all the symbols in the SHN_COMMON area and make 
362         //  them  point to the newly allocated COM area.
363         int symtab_entries = e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_size / 
364                               e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_entsize;
365         Elf32_Sym *p_symtab = (Elf32_Sym*)e_obj->sections[e_obj->hdrndx_symtab];
366     
367 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
368         diag_printf("Num   Value   Size Ndx Name\n"); 
369 #endif
370         for (i = 1; i < symtab_entries; i++)
371         {
372 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
373             cyg_uint8 *p_strtab = (cyg_uint8*)cyg_ldr_section_address(e_obj, 
374                                                         e_obj->hdrndx_strtab);
375 #endif        
376             if (p_symtab[i].st_shndx == SHN_COMMON)
377             {             
378                 cyg_uint32 boundary = p_symtab[i].st_value - 1;
379                 // Calculate the next byte boundary.
380                 com_offset = (com_offset + boundary) & ~boundary;
381                 p_symtab[i].st_shndx = com_shndx;
382                 p_symtab[i].st_value = com_offset;
383                 com_offset += p_symtab[i].st_size;
384             }
385     
386 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
387             diag_printf("%03d  %08X %04X %03d %s\n", 
388                          i, 
389                          p_symtab[i].st_value,
390                          p_symtab[i].st_size,
391                          p_symtab[i].st_shndx,
392                          p_strtab + p_symtab[i].st_name);
393 #endif        
394         }    
395     }
396
397 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
398     cyg_ldr_print_section_data(e_obj);
399 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
400     cyg_ldr_print_symbol_names(e_obj);
401 #endif    
402 #endif    
403
404     for (i = 1; i < e_obj->p_elfhdr->e_shnum; i++)
405     {
406         // Find all the '.rel' or '.rela' sections and relocate them.
407         if ((e_obj->p_sechdr[i].sh_type == SHT_REL) ||
408                                   (e_obj->p_sechdr[i].sh_type == SHT_RELA))
409         {
410             // Load and relocate the section.
411             rc = cyg_ldr_relocate_section(e_obj, i);
412             if (rc < 0)
413             { 
414 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
415                 ELFDEBUG("Relocation unsuccessful\n");
416 #endif
417                 cyg_ldr_free_elf_object(e_obj);
418                 return 0;
419             }    
420         }    
421     }    
422
423     // Synch up the caches before calling any function in the library.
424     cyg_ldr_flush_cache();
425
426     // Run the library initialization code.
427     fn = cyg_ldr_find_symbol(e_obj, "library_open");
428     if (fn != 0)
429         fn();
430     return ((void*)e_obj);
431 }
432
433 char
434 *cyg_ldr_error(void)
435 {
436     char* p = cyg_ldr_last_error;
437     cyg_ldr_last_error = NULL;
438     return p;
439 }
440
441 void cyg_ldr_close_library(void* handle)
442 {
443     void (*fn)(void);
444
445     PELF_OBJECT p = (PELF_OBJECT)handle;
446     fn = cyg_ldr_find_symbol(p, "library_close");
447     if (fn != 0)
448         fn();
449
450     cyg_ldr_free_elf_object(p);
451     p = 0;
452 }
453