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