1 /* =================================================================
5 * An object loader for eCos
7 * =================================================================
8 * ####ECOSGPLCOPYRIGHTBEGIN####
9 * -------------------------------------------
10 * This file is part of eCos, the Embedded Configurable Operating
12 * Copyright (C) 2005 eCosCentric Ltd.
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)
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.
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.
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.
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
40 * -------------------------------------------
41 * ####ECOSGPLCOPYRIGHTEND####
42 * =================================================================
43 * #####DESCRIPTIONBEGIN####
45 * Author(s): Anthony Tonizzo (atonizzo@gmail.com)
46 * Contributors: nickg@ecoscentric.com
51 * ####DESCRIPTIONEND####
53 * =================================================================
56 #include <cyg/infra/diag.h> // For diagnostic printing.
57 #include <cyg/infra/cyg_ass.h>
61 #include <pkgconf/objloader.h>
63 #include <cyg/objloader/elf.h>
64 #include <cyg/objloader/objelf.h>
65 #include <cyg/objloader/loader_fs.h>
67 char *cyg_ldr_last_error;
69 void *cyg_ldr_malloc(size_t) CYGBLD_ATTRIB_WEAK;
71 *cyg_ldr_malloc(size_t s)
76 void cyg_ldr_free(void *) CYGBLD_ATTRIB_WEAK;
84 cyg_ldr_delete_elf_section(PELF_OBJECT p, cyg_uint32 idx)
86 cyg_ldr_free(p->sections[idx]);
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.
94 cyg_ldr_free_elf_object(PELF_OBJECT p)
98 for (i = 0; i < p->p_elfhdr->e_shnum + 1; i++)
100 cyg_ldr_delete_elf_section(p, i);
102 if (p->sections != 0)
103 cyg_ldr_free(p->sections);
105 if (p->p_sechdr != 0)
106 cyg_ldr_free(p->p_sechdr);
108 if (p->p_elfhdr != 0)
109 cyg_ldr_free(p->p_elfhdr);
116 cyg_ldr_find_common_size(PELF_OBJECT p)
118 cyg_int32 i, common_size = 0;
119 Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
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)
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;
131 // Calculate the next byte boundary.
132 common_size = (common_size + boundary) & ~boundary;
133 common_size += p_symtab[i].st_size;
136 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
137 diag_printf("common_size = %d\n", common_size);
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.
145 *cyg_ldr_load_elf_section(PELF_OBJECT p, cyg_uint32 idx)
147 cyg_uint32 *addr = (cyg_uint32 *)cyg_ldr_malloc(p->p_sechdr[idx].sh_size);
148 CYG_ASSERT(addr != 0, "Cannot malloc() section");
151 cyg_ldr_last_error = "ERROR IN MALLOC";
154 p->seek(p, p->p_sechdr[idx].sh_offset);
155 p->read(p, sizeof(char), p->p_sechdr[idx].sh_size, addr);
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
163 *cyg_ldr_section_address(PELF_OBJECT p, cyg_uint32 idx)
165 if (p->sections[idx] == 0)
166 p->sections[idx] = cyg_ldr_load_elf_section(p, idx);
168 return p->sections[idx];
172 *cyg_ldr_find_symbol(void* handle, char* sym_name)
174 PELF_OBJECT p = (PELF_OBJECT)handle;
176 char *p_strtab = (char*)p->sections[p->hdrndx_strtab];
177 Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
179 int symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size /
180 p->p_sechdr[p->hdrndx_symtab].sh_entsize;
182 for (i = 0; i < symtab_entries; i++)
184 char* tmp2 = p_strtab + p_symtab[i].st_name;
185 if (!strcmp(tmp2, sym_name))
186 return cyg_ldr_symbol_address(p, i);
190 cyg_ldr_last_error = "SYMBOL NOT FOUND";
195 *cyg_ldr_sanity_check(PELF_OBJECT p)
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";
204 // We only work with relocatable files. No dynamic linking.
205 if (p->p_elfhdr->e_type != ET_REL)
206 return "NOT RELOCATABLE";
208 // These #defines are sitting in the hal.
209 if (p->p_elfhdr->e_machine != ELF_ARCH_MACHINE_TYPE)
210 return "INVALID ARCHITECTURE";
212 if (p->p_elfhdr->e_ident[EI_DATA] != ELF_ARCH_ENDIANNESS)
213 return "INVALID ENDIAN";
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.
221 cyg_ldr_load_sections(PELF_OBJECT p)
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)
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)
236 cyg_ldr_last_error = "ERROR IN ELF HEADER";
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
244 p->sections = cyg_ldr_malloc((p->p_elfhdr->e_shnum + 1) *
246 CYG_ASSERT(p->sections != 0, "Cannot malloc() p->sections");
247 if (p->sections == 0)
249 cyg_ldr_last_error = "ERROR IN MALLOC";
252 memset(p->sections, 0, (p->p_elfhdr->e_shnum + 1) *
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)
261 cyg_ldr_last_error = "ERROR IN MALLOC";
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);
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);
275 cyg_ldr_open_library(CYG_ADDRWORD ptr, cyg_int32 mode)
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
284 PELF_OBJECT e_obj = cyg_ldr_open_library_fs((char*)ptr);
287 int rc = cyg_ldr_load_sections(e_obj);
290 cyg_ldr_free_elf_object(e_obj);
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);
300 cyg_ldr_free_elf_object(e_obj);
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++)
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))
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)
316 cyg_ldr_free_elf_object(e_obj);
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))
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)
330 cyg_ldr_free_elf_object(e_obj);
336 CYG_ASSERT(e_obj->hdrndx_symtab != 0, "No symtab index found");
337 CYG_ASSERT(e_obj->hdrndx_strtab != 0, "No strtab index found");
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)
348 cyg_uint32 com_shndx = e_obj->p_elfhdr->e_shnum;
349 cyg_int32 com_offset = 0;
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");
355 if (e_obj->sections[com_shndx] == 0)
357 cyg_ldr_free_elf_object(e_obj);
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];
367 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
368 diag_printf("Num Value Size Ndx Name\n");
370 for (i = 1; i < symtab_entries; i++)
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);
376 if (p_symtab[i].st_shndx == SHN_COMMON)
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;
386 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
387 diag_printf("%03d %08X %04X %03d %s\n",
389 p_symtab[i].st_value,
391 p_symtab[i].st_shndx,
392 p_strtab + p_symtab[i].st_name);
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);
404 for (i = 1; i < e_obj->p_elfhdr->e_shnum; i++)
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))
410 // Load and relocate the section.
411 rc = cyg_ldr_relocate_section(e_obj, i);
414 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
415 ELFDEBUG("Relocation unsuccessful\n");
417 cyg_ldr_free_elf_object(e_obj);
423 // Synch up the caches before calling any function in the library.
424 cyg_ldr_flush_cache();
426 // Run the library initialization code.
427 fn = cyg_ldr_find_symbol(e_obj, "library_open");
430 return ((void*)e_obj);
436 char* p = cyg_ldr_last_error;
437 cyg_ldr_last_error = NULL;
441 void cyg_ldr_close_library(void* handle)
445 PELF_OBJECT p = (PELF_OBJECT)handle;
446 fn = cyg_ldr_find_symbol(p, "library_close");
450 cyg_ldr_free_elf_object(p);