OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [services/] [objloader/] [current/] [src/] [objelf.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/* =================================================================
2
 *
3
 *      objelf.c
4
 *
5
 *      Relocation routine for eCos loader.
6
 *
7
 * =================================================================
8
 * ####ECOSGPLCOPYRIGHTBEGIN####
9
 * -------------------------------------------
10
 * This file is part of eCos, the Embedded Configurable Operating System.
11
 * Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
12
 *
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
15
 * Software Foundation; either version 2 or (at your option) any later
16
 * version.
17
 *
18
 * eCos is distributed in the hope that it will be useful, but WITHOUT
19
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
 * for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with eCos; if not, write to the Free Software Foundation, Inc.,
25
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26
 *
27
 * As a special exception, if other files instantiate templates or use
28
 * macros or inline functions from this file, or you compile this file
29
 * and link it with other works to produce a work based on this file,
30
 * this file does not by itself cause the resulting work to be covered by
31
 * the GNU General Public License. However the source code for this file
32
 * must still be made available in accordance with section (3) of the GNU
33
 * General Public License v2.
34
 *
35
 * This exception does not invalidate any other reasons why a work based
36
 * on this file might be covered by the GNU General Public License.
37
 * -------------------------------------------
38
 * ####ECOSGPLCOPYRIGHTEND####
39
 * =================================================================
40
 * #####DESCRIPTIONBEGIN####
41
 *
42
 *  Author(s):    Anthony Tonizzo (atonizzo@gmail.com)
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 <cyg/hal/hal_tables.h>
56
#include <stdio.h>
57
 
58
#include <pkgconf/objloader.h>
59
#include <cyg/objloader/elf.h>
60
#include <cyg/objloader/objelf.h>
61
 
62
CYG_HAL_TABLE_BEGIN(cyg_ldr_table, ldr_table);
63
CYG_HAL_TABLE_END(cyg_ldr_table_end, ldr_table);
64
 
65
__externC cyg_ldr_table_entry cyg_ldr_table[];
66
__externC cyg_ldr_table_entry cyg_ldr_table_end[];
67
 
68
#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
69
void
70
cyg_ldr_print_section_data(PELF_OBJECT p)
71
{
72
    int    i;
73
    char   strname[32];
74
    char  *p_strtab = (char*)p->sections[p->p_elfhdr->e_shstrndx];
75
 
76
    diag_printf("Section Headers:\n");
77
    diag_printf("----------------------------------------------------------\n");
78
    diag_printf("[Nr]  Name                  Addr    Offset"
79
                                                         "    Size     Info\n");
80
    for (i = 0; i < p->p_elfhdr->e_shnum; i++)
81
    {
82
        sprintf(strname, "%s", p_strtab + p->p_sechdr[i].sh_name);
83
        while (strlen(strname) < 20)
84
            strcat(strname, " ");
85
        diag_printf("[%2d] %s %08X %08X %08X %08X\n",
86
                     i,
87
                     strname,
88
                     p->p_sechdr[i].sh_addr,
89
                     p->p_sechdr[i].sh_offset,
90
                     p->p_sechdr[i].sh_size,
91
                     p->p_sechdr[i].sh_info);
92
    }
93
    diag_printf("\n");
94
}
95
 
96
void
97
cyg_ldr_print_symbol_names(PELF_OBJECT p)
98
{
99
    int        i;
100
    Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
101
    char      *p_strtab = (char*)p->sections[p->hdrndx_strtab];
102
//    char       strname[32];
103
 
104
    // Total number of entries in the symbol table.
105
    int symtab_entries = p->p_sechdr[p->hdrndx_symtab].sh_size /
106
                                p->p_sechdr[p->hdrndx_symtab].sh_entsize;
107
    diag_printf("Symbol Table Entries\n");
108
    diag_printf("----------------------------------------\n");
109
    diag_printf("[Nr]   Value   Size  Ndx     Name\n");
110
    for (i = 1; i < symtab_entries; i++)
111
        diag_printf("[%3d] %08X %04d %5d %s\n",
112
                    i,
113
                    p_symtab[i].st_value,
114
                    p_symtab[i].st_size,
115
                    p_symtab[i].st_shndx,
116
                    p_strtab + p_symtab[i].st_name);
117
    diag_printf("\n");
118
}
119
 
120
cyg_int32
121
cyg_ldr_print_rel_names(PELF_OBJECT p)
122
{
123
    int        i, j, r_entries, sym_index;
124
    Elf32_Sym *p_symtab = (Elf32_Sym*)p->sections[p->hdrndx_symtab];
125
    char      *p_strtab = (char*)p->sections[p->hdrndx_strtab];
126
    char      *p_shstrtab = (char*)p->sections[p->p_elfhdr->e_shstrndx];
127
#if ELF_ARCH_RELTYPE == Elf_Rela        
128
    Elf32_Rela*   p_rela;
129
#else
130
    Elf32_Rel*    p_rel;
131
#endif
132
    char       strname[32];
133
 
134
    for (i = 1; i < p->p_elfhdr->e_shnum; i++)
135
    {
136
        if ((p->p_sechdr[i].sh_type == SHT_REL) ||
137
                                  (p->p_sechdr[i].sh_type == SHT_RELA))
138
        {
139
            // Calculate the total number of entries in the .rela/.rel section.
140
            r_entries = p->p_sechdr[i].sh_size / p->p_sechdr[i].sh_entsize;
141
 
142
            diag_printf("\n\nSymbols at: %s\n\n",
143
                         p_shstrtab + p->p_sechdr[i].sh_name);
144
#if ELF_ARCH_RELTYPE == Elf_Rela        
145
            p_rela = (Elf32_Rela *)cyg_ldr_load_elf_section(p, i);
146
            if (p_rela == 0)
147
                return -1;
148
            printf("Offset    Info      Name [+ Addend]\n");
149
#else
150
            p_rel = (Elf32_Rel *)cyg_ldr_load_elf_section(p, i);
151
            if (p_rel == 0)
152
                return -1;
153
            printf("Offset    Info     Name\n");
154
#endif
155
 
156
            for (j = 0; j < r_entries; j++)
157
            {
158
                sprintf(strname,
159
                         "%08X  %08X  ",
160
#if ELF_ARCH_RELTYPE == Elf_Rela        
161
                        p_rela[j].r_offset,
162
                        p_rela[j].r_info
163
#else
164
                        p_rel[j].r_offset,
165
                        p_rel[j].r_info
166
#endif
167
                        );
168
 
169
                diag_printf(strname);
170
 
171
#if ELF_ARCH_RELTYPE == Elf_Rela        
172
                cyg_uint8 sym_type = ELF32_R_SYM(p_rela[j].r_info);
173
#else
174
                cyg_uint8 sym_type = ELF32_R_SYM(p_rel[j].r_info);
175
#endif
176
                if (strlen (p_strtab + p_symtab[sym_type].st_name) > 0)
177
                    diag_printf(p_strtab + p_symtab[sym_type].st_name);
178
                else
179
                {
180
                    // If the symbol name is not available, then print
181
                    //  the name of the section.
182
                    sym_index = p_symtab[sym_type].st_shndx;
183
                    diag_printf(p_shstrtab + p->p_sechdr[sym_index].sh_name);
184
                }
185
#if ELF_ARCH_RELTYPE == Elf_Rela        
186
                if (p_rela[j].r_addend != 0)
187
                    diag_printf(" + %08X", p_rela[j].r_addend);
188
#endif
189
                diag_printf("\n");
190
            }
191
            // After all the printing is done, the relocation table can 
192
            //  be dumped.
193
            cyg_ldr_delete_elf_section(p, i);
194
        }
195
    }
196
}
197
#endif // DEBUG_PRINT
198
 
199
static void
200
*cyg_ldr_local_address(PELF_OBJECT p, cyg_uint32 sym_index)
201
{
202
    cyg_uint32 data_sec, addr;
203
    Elf32_Sym *p_symtab;
204
 
205
    p_symtab = (Elf32_Sym*)cyg_ldr_section_address(p, p->hdrndx_symtab);
206
 
207
    // Find out the section number in which the data for this symbol is 
208
    //  located.
209
    data_sec = p_symtab[sym_index].st_shndx;
210
 
211
    // From the section number we get the start of the memory area in 
212
    //  memory.
213
    addr = (cyg_uint32)cyg_ldr_section_address(p, data_sec);
214
 
215
    // And now return the address of the data.
216
    return (void*)(addr + p_symtab[sym_index].st_value);
217
}
218
 
219
void
220
*cyg_ldr_external_address(PELF_OBJECT p, cyg_uint32 sym_index)
221
{
222
    cyg_uint8*    tmp2;
223
    Elf32_Sym *p_symtab;
224
    cyg_uint8 *p_strtab;
225
    cyg_ldr_table_entry *entry = cyg_ldr_table;
226
 
227
 
228
    p_symtab = (Elf32_Sym*)cyg_ldr_section_address(p, p->hdrndx_symtab);
229
    p_strtab = (cyg_uint8*)cyg_ldr_section_address(p, p->hdrndx_strtab);
230
 
231
    // This is the name of the external reference to search.
232
    tmp2 = p_strtab + p_symtab[sym_index].st_name;
233
    while (entry != cyg_ldr_table_end)
234
    {
235
        if (!strcmp((const char*)tmp2, entry->symbol_name ))
236
            return entry->handler;
237
        entry++;
238
    }
239
 
240
    // Symbol not found.
241
    return 0;
242
}
243
 
244
// input:
245
// p          : Pointer to the elf file object
246
// sym_index  : Index of the symbol to be searched (in the SYMTAB)
247
//
248
// out:
249
// 0          : Symbol not found
250
// Other      : Address of the symbol in absolute memory.
251
void
252
*cyg_ldr_symbol_address(PELF_OBJECT p, cyg_uint32 sym_index)
253
{
254
    cyg_uint32 addr;
255
    Elf32_Sym *p_symtab = (Elf32_Sym*)cyg_ldr_section_address(p,
256
                                                              p->hdrndx_symtab);
257
    cyg_uint8 sym_info = p_symtab[sym_index].st_info;
258
    switch (ELF32_ST_TYPE(sym_info))
259
    {
260
    case STT_NOTYPE:
261
    case STT_FUNC:
262
    case STT_OBJECT:
263
        switch (ELF32_ST_BIND(sym_info))
264
        {
265
        case STB_LOCAL:
266
        case STB_GLOBAL:
267
            if (p_symtab[sym_index].st_shndx == SHN_UNDEF)
268
                return cyg_ldr_external_address(p, sym_index);
269
            else
270
                return cyg_ldr_local_address(p, sym_index);
271
        case STB_WEAK:
272
            addr = (cyg_uint32)cyg_ldr_external_address(p, sym_index);
273
            if (addr != 0)
274
                return (void*)addr;
275
            else
276
                return cyg_ldr_local_address(p, sym_index);
277
        default:
278
            return 0;
279
        }
280
        break;
281
    case STT_SECTION:
282
        // Return the starting address of a section, given its index.
283
        return (void*)cyg_ldr_section_address(p, p_symtab[sym_index].st_shndx);
284
    default:
285
        return 0;
286
    }
287
}
288
 
289
// Loads the relocation information, relocates, and dumps the relocation
290
//  information once the process is complete.
291
cyg_int32
292
cyg_ldr_relocate_section(PELF_OBJECT p, cyg_uint32 r_shndx)
293
{
294
    int         i, rc;
295
#if ELF_ARCH_RELTYPE == Elf_Rela        
296
    Elf32_Rela *p_rela = (Elf32_Rela *)cyg_ldr_load_elf_section(p, r_shndx);
297
    if (p_rela == 0)
298
        return -1;
299
#else
300
    Elf32_Rel *p_rel = (Elf32_Rel *)cyg_ldr_load_elf_section(p, r_shndx);
301
    if (p_rel == 0)
302
        return -1;
303
#endif
304
 
305
#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
306
    Elf32_Sym *p_symtab = (Elf32_Sym *)cyg_ldr_section_address(p,
307
                                                           p->hdrndx_symtab);
308
    char *p_strtab = (char *)cyg_ldr_section_address(p, p->hdrndx_strtab);
309
    char *p_shstrtab = (char *)cyg_ldr_section_address(p,
310
                                                       p->p_elfhdr->e_shstrndx);
311
#endif
312
 
313
    // Now we can get the address of the contents of the section to modify.
314
    cyg_uint32 r_target_shndx = p->p_sechdr[r_shndx].sh_info;
315
    cyg_uint32 r_target_addr  = (cyg_uint32)cyg_ldr_section_address(p,
316
                                                                r_target_shndx);
317
 
318
#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 0
319
    diag_printf("Relocating section \"%s\"\n",
320
            p_shstrtab + p->p_sechdr[r_target_shndx].sh_name);
321
    diag_printf("----------------------------------------\n");
322
#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
323
    diag_printf(" Ndx  Type             Offset    Name\n");
324
#endif
325
#endif
326
 
327
    // Perform relocatation for each of the members of this table.
328
    cyg_uint32 r_entries = p->p_sechdr[r_shndx].sh_size /
329
                                             p->p_sechdr[r_shndx].sh_entsize;
330
    for (i = 0; i < r_entries; i++)
331
    {
332
#if ELF_ARCH_RELTYPE == Elf_Rela        
333
        Elf32_Addr  r_offset = p_rela[i].r_offset;
334
        Elf32_Word  r_type   = ELF32_R_TYPE(p_rela[i].r_info);
335
        cyg_uint32  sym_index = ELF32_R_SYM(p_rela[i].r_info);
336
        Elf32_Sword r_addend  = p_rela[i].r_addend;
337
#else
338
        Elf32_Addr  r_offset  = p_rel[i].r_offset;
339
        Elf32_Word  r_type    = ELF32_R_TYPE(p_rel[i].r_info);
340
        cyg_uint32  sym_index = ELF32_R_SYM(p_rel[i].r_info);
341
        Elf32_Sword r_addend  = 0;
342
#endif
343
 
344
        cyg_uint32 sym_value = (cyg_uint32)cyg_ldr_symbol_address(p, sym_index);
345
 
346
        // This is architecture dependent, and deals with whether we have
347
        //  '.rel' or '.rela' sections.
348
#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
349
        diag_printf("%5d %s %08X  ",
350
                     sym_index,
351
                     relocation_name[r_type],
352
                     r_offset);
353
        if (strlen(p_strtab + p_symtab[sym_index].st_name) > 0)
354
            diag_printf(p_strtab + p_symtab[sym_index].st_name);
355
        else
356
        {
357
            // If the symbol name is not available, then print
358
            //  the name of the section.
359
            cyg_uint32 sec_ndx = p_symtab[sym_index].st_shndx;
360
            diag_printf(p_shstrtab + p->p_sechdr[sec_ndx].sh_name);
361
        }
362
        diag_printf("\n");
363
#endif
364
        rc = cyg_ldr_relocate(r_type,
365
                              r_target_addr + r_offset,
366
                              sym_value + r_addend);
367
        if (rc != 0)
368
        {
369
#if CYGPKG_SERVICES_OBJLOADER_DEBUG_LEVEL > 1
370
            diag_printf("Error while relocating symbol: %s\n",
371
                        p_strtab + p_symtab[sym_index].st_name);
372
#endif
373
            return -1;
374
        }
375
    }
376
 
377
    // After the relocation is done, the relocation table can be dumped.
378
    cyg_ldr_delete_elf_section(p, r_shndx);
379
    return 0;
380
}
381
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.