Mercurial > ecos
comparison packages/services/objloader/current/src/objloader.c @ 2890:f8dd12428f1d
* cdl/objloader.cdl, src/objelf.c, src/relocate_ppc.c,
src/relocate_arm.c: Eliminate dependency on CYGPKG_IO_FILEIO when
the filesystem loader is not required.
* src/relocate_arm.c : Added relocation software for the ARM .
* src/relocate_i386.c : Added a structure containing the relocation names
for every architecture. Only used (and compiled in) for pretty printing.
* src/relocate_ppc.c :
* include/relocate_arm.h : New header file for src/relocate_arm.c
* cdl/objloader.cdl: Added the option to relocate for the ARM.
* src/objloader.c :
* src/objelf.c : Erased some redundant debug printout and improved the
readability of the rest.
* src/loader_memory.c : Added the code to allow the objloader package
to load libraries from ROM memory, instead from a file system. The various
sections of the library are the copied from ROM to RAM and relocated.
* include/loader_memory.h : New header file for src/loader_memory.c
* src/objloader.c : Added a line to include the loader_memory header
file and code to flush the cache when calling cyg_ldr_find_symbol().
* cdl/objloader.cdl: Added one check boxe for each of the supported ways
of loading libraries (two for now) so that the user can compile out the
loading methods not used.
| author | jld |
|---|---|
| date | Fri, 03 Jul 2009 14:49:44 +0000 |
| parents | 74dbf4c3f2e1 |
| children | 7cbaadc92c67 |
comparison
equal
deleted
inserted
replaced
| 2889:8bd21cd19d19 | 2890:f8dd12428f1d |
|---|---|
| 6 * | 6 * |
| 7 * ================================================================= | 7 * ================================================================= |
| 8 * ####ECOSGPLCOPYRIGHTBEGIN#### | 8 * ####ECOSGPLCOPYRIGHTBEGIN#### |
| 9 * ------------------------------------------- | 9 * ------------------------------------------- |
| 10 * This file is part of eCos, the Embedded Configurable Operating System. | 10 * This file is part of eCos, the Embedded Configurable Operating System. |
| 11 * Copyright (C) 2005 Free Software Foundation, Inc. | 11 * Copyright (C) 2005, 2008 Free Software Foundation, Inc. |
| 12 * | 12 * |
| 13 * eCos is free software; you can redistribute it and/or modify it under | 13 * eCos is free software; you can redistribute it and/or modify it under |
| 14 * the terms of the GNU General Public License as published by the Free | 14 * the terms of the GNU General Public License as published by the Free |
| 15 * Software Foundation; either version 2 or (at your option) any later | 15 * Software Foundation; either version 2 or (at your option) any later |
| 16 * version. | 16 * version. |
| 58 #include <pkgconf/objloader.h> | 58 #include <pkgconf/objloader.h> |
| 59 | 59 |
| 60 #include <cyg/objloader/elf.h> | 60 #include <cyg/objloader/elf.h> |
| 61 #include <cyg/objloader/objelf.h> | 61 #include <cyg/objloader/objelf.h> |
| 62 #include <cyg/objloader/loader_fs.h> | 62 #include <cyg/objloader/loader_fs.h> |
| 63 #include <cyg/objloader/loader_memory.h> | |
| 63 | 64 |
| 64 char *cyg_ldr_last_error; | 65 char *cyg_ldr_last_error; |
| 65 | 66 |
| 66 void *cyg_ldr_malloc(size_t) CYGBLD_ATTRIB_WEAK; | 67 void *cyg_ldr_malloc(size_t) CYGBLD_ATTRIB_WEAK; |
| 67 void | 68 void |
| 129 common_size = (common_size + boundary) & ~boundary; | 130 common_size = (common_size + boundary) & ~boundary; |
| 130 common_size += p_symtab[i].st_size; | 131 common_size += p_symtab[i].st_size; |
| 131 } | 132 } |
| 132 | 133 |
| 133 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 | 134 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 |
| 134 diag_printf("common_size = %d\n", common_size); | 135 diag_printf("common_size = %d\n\n", common_size); |
| 135 #endif | 136 #endif |
| 136 return common_size; | 137 return common_size; |
| 137 } | 138 } |
| 138 | 139 |
| 139 // Allocates memory and loads the contents of a specific ELF section. | 140 // Allocates memory and loads the contents of a specific ELF section. |
| 159 cyg_uint32 | 160 cyg_uint32 |
| 160 *cyg_ldr_section_address(PELF_OBJECT p, cyg_uint32 idx) | 161 *cyg_ldr_section_address(PELF_OBJECT p, cyg_uint32 idx) |
| 161 { | 162 { |
| 162 if (p->sections[idx] == 0) | 163 if (p->sections[idx] == 0) |
| 163 p->sections[idx] = cyg_ldr_load_elf_section(p, idx); | 164 p->sections[idx] = cyg_ldr_load_elf_section(p, idx); |
| 164 | |
| 165 return p->sections[idx]; | 165 return p->sections[idx]; |
| 166 } | 166 } |
| 167 | 167 |
| 168 void | 168 void |
| 169 *cyg_ldr_find_symbol(void* handle, char* sym_name) | 169 *cyg_ldr_find_symbol(void* handle, char* sym_name) |
| 178 | 178 |
| 179 for (i = 0; i < symtab_entries; i++) | 179 for (i = 0; i < symtab_entries; i++) |
| 180 { | 180 { |
| 181 char* tmp2 = p_strtab + p_symtab[i].st_name; | 181 char* tmp2 = p_strtab + p_symtab[i].st_name; |
| 182 if (!strcmp(tmp2, sym_name)) | 182 if (!strcmp(tmp2, sym_name)) |
| 183 return cyg_ldr_symbol_address(p, i); | 183 { |
| 184 void *const funcPtr = cyg_ldr_symbol_address(p, i); | |
| 185 | |
| 186 // Synch up the caches before calling any function in the library. | |
| 187 cyg_ldr_flush_cache(); | |
| 188 return funcPtr; | |
| 189 } | |
| 184 } | 190 } |
| 185 | 191 |
| 186 // Symbol not found. | 192 // Symbol not found. |
| 187 cyg_ldr_last_error = "SYMBOL NOT FOUND"; | 193 cyg_ldr_last_error = "SYMBOL NOT FOUND"; |
| 188 return 0; | 194 return 0; |
| 200 | 206 |
| 201 // We only work with relocatable files. No dynamic linking. | 207 // We only work with relocatable files. No dynamic linking. |
| 202 if (p->p_elfhdr->e_type != ET_REL) | 208 if (p->p_elfhdr->e_type != ET_REL) |
| 203 return "NOT RELOCATABLE"; | 209 return "NOT RELOCATABLE"; |
| 204 | 210 |
| 211 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 | |
| 212 diag_printf("Machine type: %d\n", p->p_elfhdr->e_machine); | |
| 213 #endif | |
| 214 | |
| 205 // These #defines are sitting in the hal. | 215 // These #defines are sitting in the hal. |
| 206 if (p->p_elfhdr->e_machine != ELF_ARCH_MACHINE_TYPE) | 216 if (p->p_elfhdr->e_machine != ELF_ARCH_MACHINE_TYPE) |
| 217 { | |
| 207 return "INVALID ARCHITECTURE"; | 218 return "INVALID ARCHITECTURE"; |
| 219 } | |
| 208 | 220 |
| 209 if (p->p_elfhdr->e_ident[EI_DATA] != ELF_ARCH_ENDIANNESS) | 221 if (p->p_elfhdr->e_ident[EI_DATA] != ELF_ARCH_ENDIANNESS) |
| 210 return "INVALID ENDIAN"; | 222 return "INVALID ENDIAN"; |
| 211 return 0; } | 223 return 0; |
| 224 } | |
| 212 | 225 |
| 213 // Load only the ELF header and the sections header. These are the only | 226 // Load only the ELF header and the sections header. These are the only |
| 214 // sections loaded during library initialization. All the other sections | 227 // sections loaded during library initialization. All the other sections |
| 215 // will be loaded on demand when needed during the relocation process and, | 228 // will be loaded on demand when needed during the relocation process and, |
| 216 // when possible, dumped after use. | 229 // when possible, dumped after use. |
| 271 PELF_OBJECT | 284 PELF_OBJECT |
| 272 cyg_ldr_open_library(CYG_ADDRWORD ptr, cyg_int32 mode) | 285 cyg_ldr_open_library(CYG_ADDRWORD ptr, cyg_int32 mode) |
| 273 { | 286 { |
| 274 int (*fn)(void); | 287 int (*fn)(void); |
| 275 int i; | 288 int i; |
| 289 PELF_OBJECT e_obj = (PELF_OBJECT)0; | |
| 276 | 290 |
| 277 // In the future there might be a switch() (against 'mode') that calls an | 291 // In the future there might be a switch() (against 'mode') that calls an |
| 278 // open function other than cyg_ldr_open_library_fs(). These function | 292 // open function other than cyg_ldr_open_library_fs(). These function |
| 279 // fetch and open a library using ftp, http or libraries that are already | 293 // fetch and open a library using ftp, http or libraries that are already |
| 280 // in ROM. | 294 // in ROM. |
| 281 PELF_OBJECT e_obj = cyg_ldr_open_library_fs((char*)ptr); | 295 switch (mode) |
| 296 { | |
| 297 #if defined(CYGOPT_SERVICES_OBJLOADER_LOADERS_FS) | |
| 298 case CYG_LDR_MODE_FILESYSTEM: | |
| 299 // Here the prt is a path to the library to load. | |
| 300 e_obj = cyg_ldr_open_library_fs((char*)ptr); | |
| 301 break; | |
| 302 #endif | |
| 303 #if defined(CYGOPT_SERVICES_OBJLOADER_LOADERS_MEMORY) | |
| 304 case CYG_LDR_MODE_MEMORY: | |
| 305 // In this case the ptr pointer is the location in ROM memory where the | |
| 306 // library has been statically stored. | |
| 307 e_obj = cyg_ldr_open_library_memory(ptr); | |
| 308 break; | |
| 309 #endif | |
| 310 default: | |
| 311 break; | |
| 312 } | |
| 313 | |
| 282 if (e_obj == 0) | 314 if (e_obj == 0) |
| 283 return 0; | 315 return 0; |
| 284 int rc = cyg_ldr_load_sections(e_obj); | 316 int rc = cyg_ldr_load_sections(e_obj); |
| 285 if (rc != 0) | 317 if (rc != 0) |
| 286 { | 318 { |
| 359 // them point to the newly allocated COM area. | 391 // them point to the newly allocated COM area. |
| 360 int symtab_entries = e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_size / | 392 int symtab_entries = e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_size / |
| 361 e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_entsize; | 393 e_obj->p_sechdr[e_obj->hdrndx_symtab].sh_entsize; |
| 362 Elf32_Sym *p_symtab = (Elf32_Sym*)e_obj->sections[e_obj->hdrndx_symtab]; | 394 Elf32_Sym *p_symtab = (Elf32_Sym*)e_obj->sections[e_obj->hdrndx_symtab]; |
| 363 | 395 |
| 364 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 | |
| 365 diag_printf("Num Value Size Ndx Name\n"); | |
| 366 #endif | |
| 367 for (i = 1; i < symtab_entries; i++) | 396 for (i = 1; i < symtab_entries; i++) |
| 368 { | 397 { |
| 369 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 | |
| 370 cyg_uint8 *p_strtab = (cyg_uint8*)cyg_ldr_section_address(e_obj, | |
| 371 e_obj->hdrndx_strtab); | |
| 372 #endif | |
| 373 if (p_symtab[i].st_shndx == SHN_COMMON) | 398 if (p_symtab[i].st_shndx == SHN_COMMON) |
| 374 { | 399 { |
| 375 cyg_uint32 boundary = p_symtab[i].st_value - 1; | 400 cyg_uint32 boundary = p_symtab[i].st_value - 1; |
| 376 // Calculate the next byte boundary. | 401 // Calculate the next byte boundary. |
| 377 com_offset = (com_offset + boundary) & ~boundary; | 402 com_offset = (com_offset + boundary) & ~boundary; |
| 378 p_symtab[i].st_shndx = com_shndx; | 403 p_symtab[i].st_shndx = com_shndx; |
| 379 p_symtab[i].st_value = com_offset; | 404 p_symtab[i].st_value = com_offset; |
| 380 com_offset += p_symtab[i].st_size; | 405 com_offset += p_symtab[i].st_size; |
| 381 } | 406 } |
| 382 | 407 } |
| 383 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 | 408 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 |
| 384 diag_printf("%03d %08X %04X %03d %s\n", | 409 diag_printf("\n"); |
| 385 i, | |
| 386 p_symtab[i].st_value, | |
| 387 p_symtab[i].st_size, | |
| 388 p_symtab[i].st_shndx, | |
| 389 p_strtab + p_symtab[i].st_name); | |
| 390 #endif | 410 #endif |
| 391 } | |
| 392 } | 411 } |
| 393 | 412 |
| 394 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 | 413 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 |
| 395 cyg_ldr_print_section_data(e_obj); | 414 cyg_ldr_print_section_data(e_obj); |
| 396 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 | 415 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 |
| 406 { | 425 { |
| 407 // Load and relocate the section. | 426 // Load and relocate the section. |
| 408 rc = cyg_ldr_relocate_section(e_obj, i); | 427 rc = cyg_ldr_relocate_section(e_obj, i); |
| 409 if (rc < 0) | 428 if (rc < 0) |
| 410 { | 429 { |
| 411 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0 | 430 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1 |
| 412 ELFDEBUG("Relocation unsuccessful\n"); | 431 diag_printf("Relocation unsuccessful\n"); |
| 413 #endif | 432 #endif |
| 414 cyg_ldr_free_elf_object(e_obj); | 433 cyg_ldr_free_elf_object(e_obj); |
| 415 return 0; | 434 return 0; |
| 416 } | 435 } |
| 417 } | 436 } |
