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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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