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): Anthony Tonizzo (atonizzo@gmail.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)
77 char *p_strtab = (char*)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)
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)
101 Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
102 char *p_strtab = (char*)p->sections[p->hdrndx_strtab];
105 // Total number of entries in the symbol table.
106 int 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 int i, j, r_entries, sym_index;
142 Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
143 char *p_strtab = (char*)p->sections[p->hdrndx_strtab];
144 char *p_shstrtab = (char*)p->sections[p->p_elfhdr->e_shstrndx];
145 #if ELF_ARCH_RELTYPE == Elf_Rela
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)
269 Elf32_Sym *p_symtab = (Elf32_Sym*)cyg_ldr_section_address(p,
271 cyg_uint8 sym_info = p_symtab[sym_index].st_info;
272 switch (ELF32_ST_TYPE(sym_info))
277 switch (ELF32_ST_BIND(sym_info))
281 if (p_symtab[sym_index].st_shndx == SHN_UNDEF)
282 return cyg_ldr_external_address(p, sym_index);
284 return cyg_ldr_local_address(p, sym_index);
286 addr = (cyg_uint32)cyg_ldr_external_address(p, sym_index);
290 return cyg_ldr_local_address(p, sym_index);
296 // Return the starting address of a section, given its index.
297 return (void*)cyg_ldr_section_address(p, p_symtab[sym_index].st_shndx);
303 // Loads the relocation information, relocates, and dumps the relocation
304 // information once the process is complete.
306 cyg_ldr_relocate_section(PELF_OBJECT p, cyg_uint32 r_shndx)
309 #if ELF_ARCH_RELTYPE == Elf_Rela
310 Elf32_Rela* p_rela = (Elf32_Rela*)cyg_ldr_load_elf_section(p, r_shndx);
312 Elf32_Rel* p_rel = (Elf32_Rel*)cyg_ldr_load_elf_section(p, r_shndx);
315 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
316 Elf32_Sym *p_symtab = (Elf32_Sym*)cyg_ldr_section_address(p,
318 char *p_strtab = (char*)cyg_ldr_section_address(p, p->hdrndx_strtab);
319 char *p_shstrtab = (char*)cyg_ldr_section_address(p,
320 p->p_elfhdr->e_shstrndx);
323 // Now we can get the address of the contents of the section to modify.
324 cyg_uint32 r_target_shndx = p->p_sechdr[r_shndx].sh_info;
325 cyg_uint32 r_target_addr = (cyg_uint32)cyg_ldr_section_address(p,
328 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
329 diag_printf("Relocating section \"%s\"\n",
330 p_shstrtab + p->p_sechdr[r_target_shndx].sh_name);
331 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
332 diag_printf("Ndx Type Offset Name\"\n");
336 // Perform relocatation for each of the members of this table.
337 cyg_uint32 r_entries = p->p_sechdr[r_shndx].sh_size /
338 p->p_sechdr[r_shndx].sh_entsize;
339 for (i = 0; i < r_entries; i++)
341 #if ELF_ARCH_RELTYPE == Elf_Rela
342 Elf32_Addr r_offset = p_rela[i].r_offset;
343 Elf32_Word r_type = ELF32_R_TYPE(p_rela[i].r_info);
344 cyg_uint32 sym_index = ELF32_R_SYM(p_rela[i].r_info);
345 Elf32_Sword r_addend = p_rela[i].r_addend;
347 Elf32_Addr r_offset = p_rel[i].r_offset;
348 Elf32_Word r_type = ELF32_R_TYPE(p_rel[i].r_info);
349 cyg_uint32 sym_index = ELF32_R_SYM(p_rel[i].r_info);
350 Elf32_Sword r_addend = 0;
353 cyg_uint32 sym_value = (cyg_uint32)cyg_ldr_symbol_address(p, sym_index);
356 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
357 diag_printf("Unknown symbol value: %s Index: %d\n",
358 p_strtab + p_symtab[sym_index].st_name,
364 // This is architecture dependent, and deals with whether we have
365 // '.rel' or '.rela' sections.
366 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
367 diag_printf("%04X %04X %08X ",
371 if (strlen(p_strtab + p_symtab[sym_index].st_name) > 0)
372 diag_printf(p_strtab + p_symtab[sym_index].st_name);
375 // If the symbol name is not available, then print
376 // the name of the section.
377 cyg_uint32 sec_ndx = p_symtab[sym_index].st_shndx;
378 diag_printf(p_shstrtab + p->p_sechdr[sec_ndx].sh_name);
382 rc = cyg_ldr_relocate(r_type,
383 r_target_addr + r_offset,
384 sym_value + r_addend);
387 #if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
388 diag_printf("Relocation error: Cannot find symbol: %s\n",
389 p_strtab + p_symtab[sym_index].st_name);
395 // After the relocation is done, the relocation table can be dumped.
396 cyg_ldr_delete_elf_section(p, r_shndx);