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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      loader.cxx
4
//
5
//      Loader class implementation
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 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):           nickg
43
// Contributors:        nickg
44
// Date:                2000-11-03
45
// Purpose:             Loader class implementation
46
// Description:         This file contains the implementation of the ELF loader
47
//                      classes.
48
//              
49
//              
50
//
51
//####DESCRIPTIONEND####
52
//
53
//==========================================================================
54
 
55
#include <pkgconf/hal.h>
56
#include <pkgconf/kernel.h>
57
#include <pkgconf/isoinfra.h>
58
 
59
#include <cyg/kernel/ktypes.h>          // base kernel types
60
#include <cyg/infra/cyg_trac.h>         // tracing macros
61
#include <cyg/infra/cyg_ass.h>          // assertion macros
62
 
63
#include <string.h>
64
 
65
#include <cyg/loader/loader.hxx>        // our header
66
 
67
#if CYGINT_ISO_MALLOC
68
#include <stdlib.h>                     // for malloc() etc
69
#endif
70
 
71
// ----------------------------------------------------------------------------
72
 
73
#ifdef CYGPKG_LIBC_STRING
74
 
75
#define streq( a, b ) (strcmp(a,b) == 0)
76
 
77
#else
78
 
79
static int streq( const char *s1, const char *s2 )
80
{
81
    while( *s1 == *s2 && *s1 && *s2 ) s1++,s2++;
82
 
83
    return !(*s2-*s1);
84
}
85
 
86
#endif
87
 
88
// ----------------------------------------------------------------------------
89
// new operator to allow us to invoke constructors on previously allocated
90
// memory.
91
 
92
inline void *operator new(size_t size,  void *ptr) { return ptr; };
93
 
94
 
95
// =========================================================================
96
// Static objects
97
 
98
// Default memory allocator
99
static Cyg_LoaderMemAlloc memalloc;
100
 
101
// Loader object
102
static Cyg_Loader loader(&memalloc);
103
 
104
Cyg_Loader *Cyg_Loader::loader = &::loader;
105
 
106
 
107
// =========================================================================
108
// Main loader class members
109
 
110
// -------------------------------------------------------------------------
111
// Constructor
112
 
113
Cyg_Loader::Cyg_Loader( Cyg_LoaderMemAlloc *memalloc )
114
{
115
    CYG_REPORT_FUNCTION();
116
 
117
    error = 0;
118
    mem_default = memalloc;
119
 
120
    // build an object for the main program
121
    Cyg_LoaderMemBlock *obj = mem_default->alloc( sizeof(Cyg_LoadObject));
122
 
123
    main = new(obj->address) Cyg_LoadObject( );
124
 
125
    // Add to load list
126
    loadlist.add_head(main);
127
 
128
    error = main->get_error();
129
 
130
    CYG_REPORT_RETURN();
131
}
132
 
133
// -------------------------------------------------------------------------
134
// Destructor
135
 
136
Cyg_Loader::~Cyg_Loader()
137
{
138
    CYG_REPORT_FUNCTION();
139
 
140
    CYG_REPORT_RETURN();
141
}
142
 
143
// -------------------------------------------------------------------------
144
// Load an object and all its dependencies.
145
 
146
cyg_code Cyg_Loader::load( Cyg_LoaderStream& stream,
147
                           cyg_uint32 mode,
148
                           Cyg_LoadObject **object)
149
{
150
    CYG_REPORT_FUNCTION();
151
    CYG_REPORT_FUNCARG3XV( &stream, mode, object );
152
 
153
    cyg_code error = 0;
154
 
155
    Cyg_LoaderMemBlock *obj = mem_default->alloc( sizeof(Cyg_LoadObject));
156
    Cyg_LoadObject *pobj = NULL;
157
 
158
    pobj = new(obj->address) Cyg_LoadObject( stream, mode, mem_default, obj );
159
 
160
    error = pobj->get_error();
161
 
162
    if( error != 0 )
163
        goto finish;
164
 
165
    // Add this object to list before we do any relocations to make
166
    // the symbol lookups work.
167
 
168
    loadlist.add_tail(pobj);
169
 
170
 
171
    // The object is now loaded. We must now do any relocations.
172
 
173
    pobj->relocate();
174
 
175
    error = pobj->get_error();
176
 
177
    if( error != 0 )
178
        goto finish;
179
 
180
    // Handle PLT relocations if we are told to do so
181
 
182
// We always do this for now..    
183
//    if( mode & RTLD_NOW )
184
        pobj->relocate_plt();
185
 
186
    error = pobj->get_error();
187
 
188
 finish:
189
 
190
    if( error != 0 )
191
    {
192
        // remove object from list.
193
        loadlist.remove( pobj );
194
 
195
        pobj->~Cyg_LoadObject();
196
        mem_default->free( obj );
197
    }
198
    else
199
    {
200
        // return it from this function.
201
        *object = pobj;
202
    }
203
 
204
    CYG_REPORT_RETVAL(error);
205
 
206
    return error;
207
}
208
 
209
// -------------------------------------------------------------------------
210
// Close object and remove it from memory
211
 
212
cyg_code Cyg_Loader::close( Cyg_LoadObject *object )
213
{
214
    CYG_REPORT_FUNCTION();
215
 
216
    cyg_code error = 0;
217
 
218
    Cyg_LoaderMemBlock *block = object->get_block();
219
 
220
    object->~Cyg_LoadObject();
221
 
222
    if( block )
223
        block->free();
224
 
225
    CYG_REPORT_RETVAL(error);
226
 
227
    return error;
228
}
229
 
230
// -------------------------------------------------------------------------
231
// Translate current error code into a string.
232
 
233
const char *Cyg_Loader::error_string( )
234
{
235
    CYG_REPORT_FUNCTION();
236
 
237
    char *ret = "";
238
 
239
    CYG_REPORT_RETVAL(ret);
240
    return ret;
241
}
242
 
243
// -------------------------------------------------------------------------
244
// Look up a named symbol in loadlist
245
 
246
CYG_ADDRESS Cyg_Loader::hash_lookup_addr( const char *name )
247
{
248
    CYG_ADDRESS addr = 0;
249
    Cyg_LoadObject *object = loadlist.get_head();
250
 
251
    do
252
    {
253
        addr = object->hash_lookup_addr( name );
254
 
255
        if( addr != CYG_LOADER_NULLSYMADDR )
256
            break;
257
 
258
        object = object->get_next();
259
 
260
    } while( object != loadlist.get_head() );
261
 
262
    if( addr == CYG_LOADER_NULLSYMADDR )
263
        error = CYG_LOADERR_NO_SYMBOL;
264
 
265
    return addr;
266
}
267
 
268
// =========================================================================
269
// Loader Object class members
270
 
271
Cyg_LoadObject_Base::Cyg_LoadObject_Base()
272
{
273
    e_type = ET_EXEC;
274
    e_entry = 0;
275
    base = 0;
276
 
277
    dynamic = _DYNAMIC;
278
 
279
    parse_dynamic( dynamic );
280
}
281
 
282
// -------------------------------------------------------------------------
283
// Constructor - reads and allocates the executable.
284
 
285
Cyg_LoadObject_Base::Cyg_LoadObject_Base( Cyg_LoaderStream& stream,
286
                                cyg_uint32 amode,
287
                                Cyg_LoaderMemAlloc *mem )
288
{
289
    CYG_REPORT_FUNCTION();
290
    CYG_REPORT_FUNCARG3XV( &stream, mode, mem );
291
 
292
    Cyg_LoaderMemBlock *phblock = NULL;
293
    Cyg_LoaderMemBlock *block = NULL;
294
    Elf32_Phdr *phdr;
295
    Elf32_Phdr *dynhdr = NULL;
296
    cyg_uint32 memsize = 0;
297
    cyg_uint32 maxalign = 0;
298
    CYG_BYTE *memaddr;
299
    Elf32_Addr vaddr_low = 0x7FFFFFFF;
300
    Elf32_Addr vaddr_hi = 0;
301
 
302
    mode = amode;
303
    memalloc = mem;
304
    error = CYG_LOADERR_NOERROR;
305
 
306
    // OK, let's start by getting the ELF header...
307
 
308
    Elf32_Ehdr elf_hdr;
309
 
310
    error = stream.get_data( (CYG_BYTE *)&elf_hdr, sizeof( elf_hdr ) );
311
 
312
    if( error != 0 )
313
        goto finish;
314
 
315
    // Check that this is a valid ELF file and that the various header
316
    // fields match what we expect for our current architecture and
317
    // platform.
318
 
319
    if( !IS_ELF( elf_hdr ) )
320
        error = CYG_LOADERR_NOT_ELF;
321
    else if( elf_hdr.e_ident[EI_CLASS] != ELFCLASS32 )
322
        error = CYG_LOADERR_INVALID_CLASS;
323
#if CYG_BYTEORDER == CYG_LSBFIRST 
324
    else if( elf_hdr.e_ident[EI_DATA] != ELFDATA2LSB )
325
#else
326
    else if( elf_hdr.e_ident[EI_DATA] != ELFDATA2MSB )
327
#endif        
328
        error = CYG_LOADERR_INVALID_BYTEORDER;
329
    else if( elf_hdr.e_ident[EI_VERSION] != EV_CURRENT )
330
        error = CYG_LOADERR_INVALID_VERSION;
331
    else if( elf_hdr.e_machine != CYG_ELF_MACHINE )
332
        error = CYG_LOADERR_INVALID_MACHINE;
333
    else if( elf_hdr.e_version != EV_CURRENT )
334
        error = CYG_LOADERR_INVALID_VERSION;
335
    else if( elf_hdr.e_phentsize != sizeof(Elf32_Phdr) )
336
        error = CYG_LOADERR_INVALID_VERSION;
337
 
338
    if( error != 0 )
339
        goto finish;
340
 
341
    // OK that all seems in order, save some fields away for later.
342
 
343
    e_type = elf_hdr.e_type;
344
    e_entry = elf_hdr.e_entry;
345
 
346
    // Now we must read the program header and prepare to read the
347
    // object file into memory.
348
 
349
    error = stream.seek( elf_hdr.e_phoff );
350
 
351
    if( error != 0 )
352
        goto finish;
353
 
354
 
355
    // Allocate space for the header
356
 
357
    phblock = memalloc->alloc( elf_hdr.e_phentsize * elf_hdr.e_phnum );
358
 
359
    if( phblock == NULL )
360
    {
361
        error = CYG_LOADERR_NO_MEMORY;
362
        goto finish;
363
    }
364
 
365
    error = stream.get_data( (CYG_BYTE *)phblock->address, sizeof(Elf32_Phdr)*elf_hdr.e_phnum );
366
 
367
    if( error != 0 )
368
        goto finish;
369
 
370
    phdr = (Elf32_Phdr *)phblock->address;
371
 
372
    // Loop over the program headers, totalling the sizes of the the
373
    // PT_LOAD entries and saving a pointer to the PT_DYNAMIC entry
374
    // when we find it.
375
    // Since the segments must retain the same relationship to
376
    // eachother in memory that their virtual addresses do in the
377
    // headers, we determine the amount of memory needed by finding
378
    // the extent of the virtual addresses covered by the executable.
379
 
380
    for( int i = 0; i < elf_hdr.e_phnum; i++,phdr++ )
381
    {
382
        if( phdr->p_type == PT_DYNAMIC )
383
        {
384
            dynhdr = phdr;
385
            continue;
386
        }
387
        if( phdr->p_type != PT_LOAD )
388
            continue;
389
 
390
        if( phdr->p_vaddr < vaddr_low )
391
            vaddr_low = phdr->p_vaddr;
392
 
393
        if( (phdr->p_vaddr+phdr->p_memsz) > vaddr_hi )
394
            vaddr_hi = phdr->p_vaddr+phdr->p_memsz;
395
 
396
        if( phdr->p_align > maxalign )
397
            maxalign = phdr->p_align;
398
    }
399
 
400
    // Calculate how much memory we need and allocate it
401
    memsize = vaddr_hi - vaddr_low;
402
 
403
    block = memalloc->alloc( memsize, maxalign );
404
 
405
    if( block == NULL )
406
    {
407
        error = CYG_LOADERR_NO_MEMORY;
408
        goto finish;
409
    }
410
 
411
    // Attach to segments list
412
    segs.add_tail( block );
413
 
414
    // Calculate the base address for this executable. This is the
415
    // difference between the actual address the executable is loaded
416
    // at and its lowest virtual address. This value must be added to
417
    // all addresses derived from the executable to relocate them into
418
    // the real memory space.
419
 
420
    base = (CYG_ADDRESS)block->address - vaddr_low;
421
 
422
    // Loop over the program headers again, this time loading them
423
    // into the memory segment we have allocated and clearing any
424
    // unused areas to zero.
425
 
426
    phdr = (Elf32_Phdr *)phblock->address;
427
 
428
    memaddr = (CYG_BYTE *)block->address;
429
 
430
    for( int i = 0; i < elf_hdr.e_phnum; i++,phdr++ )
431
    {
432
        if( phdr->p_type != PT_LOAD )
433
            continue;
434
 
435
        error = stream.seek( phdr->p_offset );
436
 
437
        if( error != 0 ) break;
438
 
439
        // Calculate the actual load address for this segment.
440
        CYG_BYTE *loadaddr = (CYG_BYTE *)(phdr->p_vaddr + base);
441
 
442
        error = stream.get_data( loadaddr, phdr->p_filesz );
443
 
444
        if( error != 0 ) break;
445
 
446
        // If the memory size is more than we got from the file, zero the remainder.
447
 
448
        if( phdr->p_filesz < phdr->p_memsz )
449
            memset( loadaddr+phdr->p_filesz,
450
                    0,
451
                    phdr->p_memsz-phdr->p_filesz );
452
    }
453
 
454
 
455
    dynamic = (Elf32_Dyn *)(dynhdr->p_vaddr + base);
456
 
457
    parse_dynamic( dynamic );
458
 
459
 finish:
460
 
461
    if( phblock != NULL )
462
        memalloc->free( phblock );
463
 
464
    CYG_REPORT_RETURN();
465
}
466
 
467
// -------------------------------------------------------------------------
468
// Parse the dynamic segment 
469
 
470
void Cyg_LoadObject_Base::parse_dynamic( Elf32_Dyn *dynamic )
471
{
472
    CYG_REPORT_FUNCTION();
473
 
474
    flags = 0;
475
 
476
    for(;; dynamic++)
477
    {
478
        switch( dynamic->d_tag )
479
        {
480
        case DT_NULL:                   /* marks end of _DYNAMIC array */
481
            return;
482
        case DT_NEEDED:                 /* string table offset of needed lib */
483
            break;                      // ignore for now
484
        case DT_PLTRELSZ:               /* size of relocation entries in PLT */
485
            pltrelsz = dynamic->d_un.d_val;
486
            break;
487
        case DT_PLTGOT:                 /* address PLT/GOT */
488
            pltgot = dynamic->d_un.d_ptr + base;
489
            break;
490
        case DT_HASH:                   /* address of symbol hash table */
491
            hash = (Elf_Hash *)(dynamic->d_un.d_ptr + base);
492
            bucket = (Elf32_Word *)(hash+1);
493
            chain = bucket+hash->nbucket;
494
            break;
495
        case DT_STRTAB:                 /* address of string table */
496
            strtab = (unsigned char *)(dynamic->d_un.d_ptr + base);
497
            break;
498
        case DT_SYMTAB:                 /* address of symbol table */
499
            symtab = (Elf32_Sym *)(dynamic->d_un.d_ptr + base);
500
            break;
501
        case DT_RELA:                   /* address of relocation table */
502
            rela = (Elf32_Rela *)(dynamic->d_un.d_ptr + base);
503
            break;
504
        case DT_RELASZ:                 /* size of relocation table */
505
            relasize = dynamic->d_un.d_val;
506
            break;
507
        case DT_RELAENT:                /* size of relocation entry */
508
            relaent = dynamic->d_un.d_val;
509
            break;
510
        case DT_STRSZ:                  /* size of string table */
511
            strsize = dynamic->d_un.d_val;
512
            break;
513
        case DT_SYMENT:                 /* size of symbol table entry */
514
            syment = dynamic->d_un.d_val;
515
            break;
516
        case DT_INIT:                   /* address of initialization func. */
517
            init = dynamic->d_un.d_ptr + base;
518
            break;
519
        case DT_FINI:                   /* address of termination function */
520
            fini = dynamic->d_un.d_ptr + base;
521
            break;
522
        case DT_SONAME:                 /* string table offset of shared obj */
523
            soname = dynamic->d_un.d_val;
524
            break;
525
        case DT_SYMBOLIC:               /* start sym search in shared obj. */
526
            flags |= DF_SYMBOLIC;
527
            break;
528
        case DT_REL:                    /* address of rel. tbl. w addends */
529
            rel = (Elf32_Rel *)(dynamic->d_un.d_ptr + base);
530
            break;
531
        case DT_RELSZ:                  /* size of DT_REL relocation table */
532
            relsize = dynamic->d_un.d_val;
533
            break;
534
        case DT_RELENT:                 /* size of DT_REL relocation entry */
535
            relent = dynamic->d_un.d_val;
536
            break;
537
        case DT_PLTREL:                 /* PLT referenced relocation entry */
538
            pltrel = dynamic->d_un.d_val;
539
            break;
540
        case DT_DEBUG:                  /* Debug data */
541
            break;                      /* ignore for now */
542
        case DT_TEXTREL:                /* Allow rel. mod. to unwritable seg */
543
            flags |= DF_TEXTREL;
544
            break;
545
        case DT_JMPREL:                 /* add. of PLT's relocation entries */
546
            jmprel = dynamic->d_un.d_ptr + base;
547
            break;
548
        case DT_BIND_NOW:               /* Bind now regardless of env setting */
549
            flags |= DF_BIND_NOW;
550
            break;
551
        case DT_INIT_ARRAY:             /* init array address */
552
            init_array = (Elf32_Addr *)(dynamic->d_un.d_ptr + base);
553
            break;
554
        case DT_FINI_ARRAY:             /* fini array address */
555
            fini_array = (Elf32_Addr *)(dynamic->d_un.d_ptr + base);
556
            break;
557
        case DT_INIT_ARRAYSZ:           /* init array size */
558
            init_array_sz = dynamic->d_un.d_val;
559
            break;
560
        case DT_FINI_ARRAYSZ:           /* fini array size */
561
            fini_array_sz = dynamic->d_un.d_val;
562
            break;
563
        case DT_FLAGS:                  /* flags */
564
            flags |= dynamic->d_un.d_val;
565
            break;
566
        case DT_PREINIT_ARRAY:          /* preinit array address */
567
            pre_init_array = (Elf32_Addr *)(dynamic->d_un.d_ptr + base);
568
            break;
569
        case DT_PREINIT_ARRAYSZ:        /* preinit array size */
570
            pre_init_array_sz = dynamic->d_un.d_val;
571
            break;
572
 
573
        default:
574
            // handle format-specific entries
575
            break;
576
        }
577
    }
578
 
579
    CYG_REPORT_RETURN();
580
}
581
 
582
// -------------------------------------------------------------------------
583
// Get the symbol name from the current object's symbol table, look it
584
// up in the hash tables of the loaded objects, and return its address.
585
 
586
CYG_ADDRESS Cyg_LoadObject_Base::get_sym_addr_from_ix( Elf32_Word ix )
587
{
588
    Elf32_Sym *sym = get_sym( ix );
589
 
590
    if( sym == NULL ) return 0;
591
 
592
    const char *name = get_name( sym->st_name );
593
 
594
    // If the symbol has local binding, we must look for
595
    // it in this object only.
596
    if( ELF32_ST_BIND(sym->st_info) == STB_LOCAL )
597
         return hash_lookup_addr( name );
598
 
599
    // Otherwise search the loaded objects in load order
600
    return Cyg_Loader::loader->hash_lookup_addr( name );
601
 
602
}
603
 
604
// -------------------------------------------------------------------------
605
// Lookup the name in our hash table and return the symbol table entry
606
 
607
Elf32_Sym *Cyg_LoadObject_Base::hash_lookup( const char *name )
608
{
609
    Elf32_Sym *ret = NULL;
610
 
611
    if( hash == NULL )
612
    {
613
        error = CYG_LOADERR_NO_HASHTABLE;
614
        return NULL;
615
    }
616
 
617
    error = CYG_LOADERR_NO_SYMBOL;
618
 
619
    Elf32_Word ix = elf_hash( (const unsigned char *)name );
620
 
621
    ix %= hash->nbucket;
622
 
623
    // get head of chain
624
    Elf32_Word iy = bucket[ ix ];
625
 
626
    while( iy != STN_UNDEF )
627
    {
628
        Elf32_Sym *sym = get_sym( iy );
629
        const char *sname = get_name( sym->st_name );
630
 
631
        if( streq( name, sname ) )
632
        {
633
            ret = sym;
634
            error = CYG_LOADERR_NOERROR;
635
            break;
636
        }
637
 
638
        iy = chain[ iy ];
639
    }
640
 
641
    return ret;
642
}
643
 
644
// -------------------------------------------------------------------------
645
// Lookup the given name in our symbol table and return it's value
646
// relocated to our load address.
647
 
648
CYG_ADDRESS Cyg_LoadObject_Base::hash_lookup_addr( const char *name )
649
{
650
    Elf32_Sym *sym = hash_lookup( name );
651
 
652
    if( sym == NULL )
653
        return CYG_LOADER_NULLSYMADDR;
654
 
655
    // Check that this symbol is for a defined object, if its type is
656
    // NOTYPE then it is undefined, here, and we cannot take its address.
657
    // Hopefully it is defined in some other object.
658
 
659
    if( ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE )
660
    {
661
        error = CYG_LOADERR_NO_SYMBOL;
662
        return CYG_LOADER_NULLSYMADDR;
663
    }
664
 
665
    return sym->st_value + base;
666
}
667
 
668
// -------------------------------------------------------------------------
669
// ELF hash function
670
// This is the standard hash function used for indexing the bucket
671
// array in the hash table.
672
 
673
unsigned long Cyg_LoadObject_Base::elf_hash( const unsigned char *name )
674
{
675
    unsigned long h = 0, g;
676
 
677
    while( *name )
678
    {
679
        h = ( h << 4 ) + *name++;
680
        if( (g = h & 0xf0000000) != 0 )
681
            h ^= g >> 24;
682
        h &= ~g;
683
    }
684
    return h;
685
}
686
 
687
// -------------------------------------------------------------------------
688
//
689
 
690
Elf32_Sym *Cyg_LoadObject_Base::get_sym( Elf32_Word ix )
691
{
692
    if( symtab == NULL )
693
        return NULL;
694
 
695
    return &symtab[ix];
696
}
697
 
698
char *Cyg_LoadObject_Base::get_name( Elf32_Word offset )
699
{
700
    if( strtab == NULL || offset > strsize )
701
        return NULL;
702
 
703
    return (char *)(&strtab[offset]);
704
}
705
 
706
// -------------------------------------------------------------------------
707
// Destructor
708
 
709
// -------------------------------------------------------------------------
710
// Cyg_LoadObject_Base destructor
711
 
712
Cyg_LoadObject_Base::~Cyg_LoadObject_Base()
713
{
714
    CYG_REPORT_FUNCTION();
715
    // empty out segments list
716
    while( !segs.empty() )
717
    {
718
        Cyg_LoaderMemBlock *block = segs.rem_head();
719
 
720
        block->free();
721
    }
722
    CYG_REPORT_RETURN();
723
}
724
 
725
// -------------------------------------------------------------------------
726
// Translate a symbol into its address.
727
 
728
void *Cyg_LoadObject_Base::symbol( const char *name )
729
{
730
    CYG_REPORT_FUNCTION();
731
 
732
    Elf32_Addr addr = hash_lookup_addr( name );
733
 
734
    if( addr == CYG_LOADER_NULLSYMADDR )
735
        addr = 0;
736
 
737
    CYG_REPORT_RETVAL( addr );
738
 
739
    return (void *)addr;
740
}
741
 
742
// -------------------------------------------------------------------------
743
// Start the given executable object running
744
 
745
cyg_code Cyg_LoadObject_Base::exec(int argc, char **argv, char **envv)
746
{
747
    CYG_REPORT_FUNCTION();
748
    CYG_REPORT_FUNCARG3XV( argc, argv, envv );
749
 
750
    cyg_code error = 0;
751
 
752
    CYG_REPORT_RETVAL(error);
753
 
754
    return error;
755
}
756
 
757
// =========================================================================
758
// Cyg_LoadObject members
759
 
760
// -------------------------------------------------------------------------
761
// Apply relocations
762
 
763
void Cyg_LoadObject::relocate()
764
{
765
    CYG_REPORT_FUNCTION();
766
 
767
    if( rel != NULL )
768
    {
769
        Elf32_Rel *r = rel;
770
        for( int i = relsize; i > 0 && error == 0; i -= relent, r++ )
771
            error = apply_rel( ELF32_R_TYPE(r->r_info),
772
                               ELF32_R_SYM(r->r_info),
773
                               r->r_offset);
774
    }
775
 
776
 
777
    if( error == 0 && rela != NULL )
778
    {
779
        Elf32_Rela *r = rela;
780
        for( int i = relasize; i > 0 && error == 0; i -= relaent, r++ )
781
            error = apply_rela( ELF32_R_TYPE(r->r_info),
782
                                ELF32_R_SYM(r->r_info),
783
                                r->r_offset,
784
                                r->r_addend);
785
    }
786
 
787
    CYG_REPORT_RETURN();
788
}
789
 
790
// -------------------------------------------------------------------------
791
// Apply JMPREL relocations for the PLT
792
 
793
void Cyg_LoadObject::relocate_plt()
794
{
795
    CYG_REPORT_FUNCTION();
796
 
797
    if( pltrel == DT_REL )
798
    {
799
        Elf32_Rel *r = (Elf32_Rel *)jmprel;
800
        for( int i = pltrelsz; i > 0 && error == 0; i -= sizeof(Elf32_Rel), r++ )
801
            error = apply_rel( ELF32_R_TYPE(r->r_info),
802
                               ELF32_R_SYM(r->r_info),
803
                               r->r_offset);
804
    }
805
 
806
 
807
    if( error == 0 && pltrel == DT_RELA )
808
    {
809
        Elf32_Rela *r = (Elf32_Rela *)jmprel;
810
        for( int i = pltrelsz; i > 0 && error == 0; i -= sizeof(Elf32_Rela), r++ )
811
            error = apply_rela( ELF32_R_TYPE(r->r_info),
812
                                ELF32_R_SYM(r->r_info),
813
                                r->r_offset,
814
                                r->r_addend);
815
    }
816
 
817
    CYG_REPORT_RETURN();
818
}
819
 
820
// =========================================================================
821
// Loader memory allocator default class methods.
822
// The default behaviour of this class is to use malloc/realloc/free
823
// to handle memory.
824
 
825
// -------------------------------------------------------------------------
826
 
827
Cyg_LoaderMemAlloc::Cyg_LoaderMemAlloc()
828
{
829
    // no initialization needed
830
}
831
 
832
// -------------------------------------------------------------------------
833
 
834
Cyg_LoaderMemAlloc::~Cyg_LoaderMemAlloc()
835
{
836
    // No destruction needed
837
}
838
 
839
// -------------------------------------------------------------------------
840
// Allocate memory of the supplied size and alignment.
841
// size      - size in bytes
842
// alignment - alignment expressed as a power of 2
843
 
844
Cyg_LoaderMemBlock *Cyg_LoaderMemAlloc::alloc( cyg_int32 size,
845
                                               cyg_int32 alignment)
846
{
847
#if CYGINT_ISO_MALLOC    
848
    Cyg_LoaderMemBlock *block;
849
    cyg_uint8 *mem;
850
    cyg_uint32 acsize = sizeof(Cyg_LoaderMemBlock) + size + alignment;
851
 
852
    mem = (cyg_uint8 *)::malloc( acsize );
853
 
854
    if( mem == NULL )
855
        return NULL;
856
 
857
    block = (Cyg_LoaderMemBlock *)mem;
858
 
859
    // set up aligned block address
860
    block->address      = (void *)((((CYG_ADDRWORD)mem+sizeof(Cyg_LoaderMemBlock))+alignment) & ~(alignment-1));
861
    block->size         = size;
862
    block->alignment    = alignment;
863
    block->mem          = this;
864
    block->actual_address = (CYG_ADDRESS) mem;
865
    block->actual_size    = acsize;
866
 
867
    return block;
868
 
869
#else
870
 
871
    return 0;
872
 
873
#endif
874
 
875
}
876
 
877
// -------------------------------------------------------------------------
878
// Reallocate block
879
 
880
Cyg_LoaderMemBlock *Cyg_LoaderMemAlloc::realloc( Cyg_LoaderMemBlock *oblock,
881
                                                 cyg_int32 size,
882
                                                 cyg_int32 alignment)
883
{
884
#if CYGINT_ISO_MALLOC
885
 
886
    Cyg_LoaderMemBlock *block;
887
    cyg_uint8 *mem;
888
 
889
    if( alignment == -1 )
890
        alignment = oblock->alignment;
891
 
892
    cyg_uint32 acsize = sizeof(Cyg_LoaderMemBlock) + size + alignment;
893
 
894
    mem = (cyg_uint8 *)::realloc( (void *)(oblock->actual_address), acsize );
895
 
896
    if( mem == NULL )
897
        return NULL;
898
 
899
    block = (Cyg_LoaderMemBlock *)mem;
900
 
901
    // set up aligned block address
902
    block->address      = (void *)((((CYG_ADDRWORD)mem+sizeof(Cyg_LoaderMemBlock))+alignment) & (alignment-1));
903
    block->size         = size;
904
    block->alignment    = alignment;
905
    block->mem          = this;
906
    block->actual_address = (CYG_ADDRESS) mem;
907
    block->actual_size    = acsize;
908
 
909
    return block;
910
 
911
#else
912
 
913
    return NULL;
914
 
915
#endif
916
}
917
 
918
// -------------------------------------------------------------------------
919
// Free a previously allocated memory segment.
920
 
921
void Cyg_LoaderMemAlloc::free( Cyg_LoaderMemBlock *block )
922
{
923
#if CYGINT_ISO_MALLOC        
924
    ::free( (void *)block->actual_address );
925
#endif    
926
}
927
 
928
// =========================================================================
929
// Loader stream functions
930
 
931
Cyg_LoaderStream::Cyg_LoaderStream()
932
{
933
}
934
 
935
Cyg_LoaderStream::~Cyg_LoaderStream()
936
{
937
}
938
 
939
cyg_code Cyg_LoaderStream::get_byte(CYG_BYTE *val)
940
{
941
    return CYG_LOADERR_EOF;
942
}
943
 
944
cyg_code Cyg_LoaderStream::get_data(CYG_BYTE *addr, CYG_ADDRWORD size)
945
{
946
    return CYG_LOADERR_EOF;
947
}
948
 
949
cyg_code Cyg_LoaderStream::seek(CYG_ADDRWORD pos)
950
{
951
    return CYG_LOADERR_SEEK;
952
}
953
 
954
// =========================================================================
955
// Memory based loader stream
956
 
957
Cyg_LoaderStream_Mem::Cyg_LoaderStream_Mem( const void *addr, cyg_int32 size )
958
{
959
    base = pos = (CYG_ADDRESS)addr;
960
    end = base + size;
961
}
962
 
963
Cyg_LoaderStream_Mem::~Cyg_LoaderStream_Mem()
964
{
965
    // nothing to do
966
}
967
 
968
cyg_code Cyg_LoaderStream_Mem::get_byte(CYG_BYTE *val)
969
{
970
    if( pos == end )
971
        return CYG_LOADERR_EOF;
972
 
973
    *val = *(CYG_BYTE *)pos;
974
    pos++;
975
 
976
    return CYG_LOADERR_NOERROR;
977
}
978
 
979
cyg_code Cyg_LoaderStream_Mem::get_data(CYG_BYTE *addr, CYG_ADDRWORD size)
980
{
981
    if( pos == end || (pos+size) > end )
982
        return CYG_LOADERR_EOF;
983
 
984
    memcpy( (void *)addr, (void *)pos, size );
985
 
986
    pos += size;
987
 
988
    return CYG_LOADERR_NOERROR;
989
}
990
 
991
cyg_code Cyg_LoaderStream_Mem::seek(CYG_ADDRWORD apos)
992
{
993
    CYG_ADDRWORD npos = base+apos;
994
 
995
    if( npos > end || npos < base )
996
        return CYG_LOADERR_SEEK;
997
 
998
    pos = npos;
999
 
1000
    return CYG_LOADERR_NOERROR;
1001
}
1002
 
1003
// =========================================================================
1004
// file based loader stream
1005
 
1006
#ifdef CYGPKG_IO_FILEIO
1007
 
1008
#include <unistd.h>
1009
 
1010
Cyg_LoaderStream_File::Cyg_LoaderStream_File( int afd )
1011
{
1012
    fd = afd;
1013
}
1014
 
1015
Cyg_LoaderStream_File::~Cyg_LoaderStream_File()
1016
{
1017
    // nothing to do
1018
    fd = 0;
1019
}
1020
 
1021
cyg_code Cyg_LoaderStream_File::get_byte(CYG_BYTE *val)
1022
{
1023
    ssize_t got = read( fd, (void *)val, 1 );
1024
 
1025
    if( got == 0 )
1026
        return CYG_LOADERR_EOF;
1027
 
1028
    return CYG_LOADERR_NOERROR;
1029
}
1030
 
1031
cyg_code Cyg_LoaderStream_File::get_data(CYG_BYTE *addr, CYG_ADDRWORD size)
1032
{
1033
    ssize_t got = read( fd, (void *)addr, size );
1034
 
1035
    if( got != (ssize_t)size )
1036
        return CYG_LOADERR_EOF;
1037
 
1038
    return CYG_LOADERR_NOERROR;
1039
}
1040
 
1041
cyg_code Cyg_LoaderStream_File::seek(CYG_ADDRWORD apos)
1042
{
1043
    off_t npos = lseek( fd, apos, SEEK_SET );
1044
 
1045
    if( npos != apos )
1046
        return CYG_LOADERR_SEEK;
1047
 
1048
    return CYG_LOADERR_NOERROR;
1049
}
1050
 
1051
#endif
1052
 
1053
// =========================================================================
1054
// EOF loader.cxx

powered by: WebSVN 2.1.0

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