1 /* =================================================================
5 * Relocation routine for eCos loader.
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): atonizzo@lycos.com
46 * Contributors: nickg@ecoscentric.com
51 * ####DESCRIPTIONEND####
53 * =================================================================
56 #include <cyg/infra/diag.h> // For diagnostic printing.
57 #include <pkgconf/io_fileio.h>
58 #include <cyg/hal/hal_tables.h>
61 #include <pkgconf/objloader.h>
62 #include <cyg/objloader/elf.h>
63 #include <cyg/objloader/objelf.h>
65 CYG_HAL_TABLE_BEGIN( cyg_ldr_table, ldr_table );
66 CYG_HAL_TABLE_END( cyg_ldr_table_end, ldr_table );
68 __externC cyg_ldr_table_entry cyg_ldr_table[];
69 __externC cyg_ldr_table_entry cyg_ldr_table_end[];
71 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
73 cyg_ldr_print_section_data( PELF_OBJECT p )
76 cyg_uint8 strname[32];
77 cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->p_elfhdr->e_shstrndx];
79 diag_printf( "\n\nSection Headers:\n" );
80 diag_printf( "[Nr] Name Addr Offset Size Info\n" );
81 for ( i = 0; i < p->p_elfhdr->e_shnum; i++ )
83 sprintf( strname, "%s", p_strtab + p->p_sechdr[i].sh_name );
84 while ( strlen( strname ) < 20 )
85 strcat( strname, " " );
86 diag_printf( "[%02d] %s %08X %08X %08X %08X\n",
89 p->p_sechdr[i].sh_addr,
90 p->p_sechdr[i].sh_offset,
91 p->p_sechdr[i].sh_size,
92 p->p_sechdr[i].sh_info );
98 cyg_ldr_print_symbol_names( PELF_OBJECT p )
100 cyg_int32 i, symtab_entries;
101 Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
102 cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->hdrndx_strtab];
103 cyg_uint8 strname[32];
105 // Total number of entries in the symbol table.
106 symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size /
107 p->p_sechdr[p->hdrndx_symtab].sh_entsize;
108 diag_printf( "Num Value Size Ndx Name\n" );
109 for ( i = 1; i < symtab_entries; i++ )
111 sprintf( strname, "%d", i );
112 while ( strlen( strname ) < 5 )
113 strcat( strname, " " );
114 diag_printf( strname );
118 p_symtab[i].st_value,
119 p_symtab[i].st_size );
120 while ( strlen( strname ) < 15 )
121 strcat( strname, " " );
122 diag_printf( strname );
124 sprintf( strname, "%d", p_symtab[i].st_shndx );
125 while ( strlen( strname ) < 6 )
126 strcat( strname, " " );
127 diag_printf( strname );
130 p_strtab + p_symtab[i].st_name,
131 sizeof( strname ) - 1 );
132 strname[strlen( p_strtab + p_symtab[i].st_name )] = '\0';
133 diag_printf( strname );
139 cyg_ldr_print_rel_names( PELF_OBJECT p )
141 cyg_int32 i, j, r_entries, sym_index;
142 Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
143 cyg_uint8 *p_strtab = (cyg_uint8*)p->sections[p->hdrndx_strtab];
144 cyg_uint8 *p_shstrtab = (cyg_uint8*)p->sections[p->p_elfhdr->e_shstrndx];
145 #if ELF_ARCH_RELTYPE == Elf_Rela
150 cyg_uint8 strname[32];
152 for ( i = 1; i < p->p_elfhdr->e_shnum; i++ )
154 if ( ( p->p_sechdr[i].sh_type == SHT_REL ) ||
155 ( p->p_sechdr[i].sh_type == SHT_RELA ) )
157 // Calculate the total number of entries in the .rela section.
158 r_entries = p->p_sechdr[i].sh_size / p->p_sechdr[i].sh_entsize;
160 diag_printf( "\n\nSymbols at: %s\n\n",
161 p_shstrtab + p->p_sechdr[i].sh_name );
162 #if ELF_ARCH_RELTYPE == Elf_Rela
163 p_rela = (Elf32_Rela*)cyg_ldr_load_elf_section( p, i );
164 printf( "Offset Info Name [+ Addend]\n" );
166 p_rel = (Elf32_Rel*)cyg_ldr_load_elf_section( p, i );
167 printf( "Offset Info Name\n" );
170 for ( j = 0; j < r_entries; j++ )
174 #if ELF_ARCH_RELTYPE == Elf_Rela
183 diag_printf( strname );
185 #if ELF_ARCH_RELTYPE == Elf_Rela
186 cyg_uint8 sym_type = ELF32_R_SYM( p_rela[j].r_info );
188 cyg_uint8 sym_type = ELF32_R_SYM( p_rel[j].r_info );
190 if ( strlen ( p_strtab + p_symtab[sym_type].st_name ) > 0 )
191 diag_printf( p_strtab + p_symtab[sym_type].st_name );
194 // If the symbol name is not available, then print
195 // the name of the section.
196 sym_index = p_symtab[sym_type].st_shndx;
197 diag_printf( p_shstrtab + p->p_sechdr[sym_index].sh_name );
199 #if ELF_ARCH_RELTYPE == Elf_Rela
200 if ( p_rela[j].r_addend != 0 )
201 diag_printf( " + %08X", p_rela[j].r_addend );
205 // After all the printing is done, the relocation table can
207 cyg_ldr_delete_elf_section( p, i );
211 #endif // DEBUG_PRINT
214 *cyg_ldr_local_address( PELF_OBJECT p, cyg_uint32 sym_index )
216 cyg_uint32 data_sec, addr;
219 p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, p->hdrndx_symtab );
221 // Find out the section number in which the data for this symbol is
223 data_sec = p_symtab[sym_index].st_shndx;
225 // From the section number we get the start of the memory area in
227 addr = (cyg_uint32)cyg_ldr_section_address( p, data_sec );
229 // And now return the address of the data.
230 return (void*)( addr + p_symtab[sym_index].st_value);
234 *cyg_ldr_external_address( PELF_OBJECT p, cyg_uint32 sym_index )
239 cyg_ldr_table_entry *entry = cyg_ldr_table;
242 p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, p->hdrndx_symtab );
243 p_strtab = (cyg_uint8*)cyg_ldr_section_address( p, p->hdrndx_strtab );
245 // This is the name of the external reference to search.
246 tmp2 = p_strtab + p_symtab[sym_index].st_name;
247 while ( entry != cyg_ldr_table_end )
249 if ( !strcmp( (const char*)tmp2, entry->symbol_name ) )
250 return entry->handler;
259 // p : Pointer to the elf file object
260 // sym_index : Index of the symbol to be searched (in the SYMTAB)
263 // 0 : Symbol not found
264 // Other : Address of the symbol in absolute memory.
266 *cyg_ldr_symbol_address( PELF_OBJECT p, cyg_uint32 sym_index )
272 p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p, p->hdrndx_symtab );
273 sym_info = p_symtab[sym_index].st_info;
275 switch ( ELF32_ST_TYPE( sym_info ) )
280 switch ( ELF32_ST_BIND( sym_info ) )
284 if ( p_symtab[sym_index].st_shndx == SHN_UNDEF )
285 return cyg_ldr_external_address( p, sym_index );
287 return cyg_ldr_local_address( p, sym_index );
289 addr = (cyg_uint32)cyg_ldr_external_address( p, sym_index );
293 return cyg_ldr_local_address( p, sym_index );
299 // Return the starting address of a section, given its index.
300 return (void*)cyg_ldr_section_address( p,
301 p_symtab[sym_index].st_shndx );
307 // Loads the relocation information, relocates, and dumps the relocation
308 // information once the process is complete.
310 cyg_ldr_relocate_section( PELF_OBJECT p, cyg_uint32 r_shndx )
313 cyg_uint32 r_entries, r_target_shndx, r_target_addr;
314 cyg_uint32 sym_value, sym_index;
317 Elf32_Sword r_addend;
318 #if ELF_ARCH_RELTYPE == Elf_Rela
319 Elf32_Rela* p_rela = (Elf32_Rela*)cyg_ldr_load_elf_section( p, r_shndx );
321 Elf32_Rel* p_rel = (Elf32_Rel*)cyg_ldr_load_elf_section( p, r_shndx );
324 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
325 Elf32_Sym *p_symtab = (Elf32_Sym*)cyg_ldr_section_address( p,
327 cyg_uint8 *p_strtab = (cyg_uint8*)cyg_ldr_section_address( p,
329 cyg_uint8 *p_shstrtab = (cyg_uint8*)cyg_ldr_section_address( p,
330 p->p_elfhdr->e_shstrndx );
333 // Now we can get the address of the contents of the section to modify.
334 r_target_shndx = p->p_sechdr[r_shndx].sh_info;
335 r_target_addr = (cyg_uint32)cyg_ldr_section_address( p, r_target_shndx );
337 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
338 diag_printf( "Relocating section \"%s\"\n",
339 p_shstrtab + p->p_sechdr[r_target_shndx].sh_name );
340 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
341 diag_printf( "Ndx Type Offset Name\"\n" );
345 // Perform relocatation for each of the members of this table.
346 r_entries = p->p_sechdr[r_shndx].sh_size / p->p_sechdr[r_shndx].sh_entsize;
347 for ( i = 0; i < r_entries; i++ )
349 #if ELF_ARCH_RELTYPE == Elf_Rela
350 r_offset = p_rela[i].r_offset;
351 r_type = ELF32_R_TYPE( p_rela[i].r_info );
352 sym_index = ELF32_R_SYM( p_rela[i].r_info );
353 r_addend = p_rela[i].r_addend;
355 r_offset = p_rel[i].r_offset;
356 r_type = ELF32_R_TYPE( p_rel[i].r_info );
357 sym_index = ELF32_R_SYM( p_rel[i].r_info );
361 sym_value = (cyg_uint32)cyg_ldr_symbol_address( p, sym_index );
362 if ( sym_value == 0 )
364 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
365 diag_printf( "Unknown symbol value: %s Index: %d\n",
366 p_strtab + p_symtab[sym_index].st_name,
372 // This is architecture dependent, and deals with whether we have
373 // '.rel' or '.rela' sections.
374 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
375 diag_printf( "%04X %04X %08X ",
379 if ( strlen ( p_strtab + p_symtab[sym_index].st_name ) > 0 )
380 diag_printf( p_strtab + p_symtab[sym_index].st_name );
383 // If the symbol name is not available, then print
384 // the name of the section.
385 cyg_uint32 sec_ndx = p_symtab[sym_index].st_shndx;
386 diag_printf( p_shstrtab + p->p_sechdr[sec_ndx].sh_name );
390 rc = cyg_ldr_relocate( r_type,
391 r_target_addr + r_offset,
392 sym_value + r_addend );
395 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
396 diag_printf( "Relocation error: Cannot find symbol: %s\n",
397 p_strtab + p_symtab[sym_index].st_name );
403 // After the relocation is done, the relocation table can be dumped.
404 cyg_ldr_delete_elf_section( p, r_shndx );