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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [loader/] [v2_0/] [src/] [loader.cxx] - Blame information for rev 228

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

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

powered by: WebSVN 2.1.0

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