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