⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.cxx

📁 eCos操作系统源码
💻 CXX
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////      loader.cxx////      Loader class implementation////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):           nickg// Contributors:        nickg// Date:                2000-11-03// Purpose:             Loader class implementation// Description:         This file contains the implementation of the ELF loader//                      classes.//              //              ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/hal.h>#include <pkgconf/kernel.h>#include <pkgconf/isoinfra.h>#include <cyg/kernel/ktypes.h>          // base kernel types#include <cyg/infra/cyg_trac.h>         // tracing macros#include <cyg/infra/cyg_ass.h>          // assertion macros#include <string.h>#include <cyg/loader/loader.hxx>        // our header#if CYGINT_ISO_MALLOC#include <stdlib.h>                     // for malloc() etc#endif// ----------------------------------------------------------------------------#ifdef CYGPKG_LIBC_STRING#define streq( a, b ) (strcmp(a,b) == 0)#elsestatic int streq( const char *s1, const char *s2 ){    while( *s1 == *s2 && *s1 && *s2 ) s1++,s2++;    return !(*s2-*s1);}#endif// ----------------------------------------------------------------------------// new operator to allow us to invoke constructors on previously allocated// memory.inline void *operator new(size_t size,  void *ptr) { return ptr; };// =========================================================================// Static objects// Default memory allocatorstatic Cyg_LoaderMemAlloc memalloc;// Loader objectstatic Cyg_Loader loader(&memalloc);Cyg_Loader *Cyg_Loader::loader = &::loader;// =========================================================================// Main loader class members// -------------------------------------------------------------------------// ConstructorCyg_Loader::Cyg_Loader( Cyg_LoaderMemAlloc *memalloc ){    CYG_REPORT_FUNCTION();    error = 0;    mem_default = memalloc;    // build an object for the main program    Cyg_LoaderMemBlock *obj = mem_default->alloc( sizeof(Cyg_LoadObject));        main = new(obj->address) Cyg_LoadObject( );    // Add to load list    loadlist.add_head(main);        error = main->get_error();    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// DestructorCyg_Loader::~Cyg_Loader(){    CYG_REPORT_FUNCTION();    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Load an object and all its dependencies.cyg_code Cyg_Loader::load( Cyg_LoaderStream& stream,                           cyg_uint32 mode,                           Cyg_LoadObject **object){    CYG_REPORT_FUNCTION();    CYG_REPORT_FUNCARG3XV( &stream, mode, object );    cyg_code error = 0;    Cyg_LoaderMemBlock *obj = mem_default->alloc( sizeof(Cyg_LoadObject));    Cyg_LoadObject *pobj = NULL;        pobj = new(obj->address) Cyg_LoadObject( stream, mode, mem_default, obj );    error = pobj->get_error();    if( error != 0 )        goto finish;    // Add this object to list before we do any relocations to make    // the symbol lookups work.        loadlist.add_tail(pobj);        // The object is now loaded. We must now do any relocations.    pobj->relocate();    error = pobj->get_error();    if( error != 0 )        goto finish;    // Handle PLT relocations if we are told to do so// We always do this for now..    //    if( mode & RTLD_NOW )        pobj->relocate_plt();    error = pobj->get_error();     finish:        if( error != 0 )    {        // remove object from list.        loadlist.remove( pobj );                pobj->~Cyg_LoadObject();        mem_default->free( obj );    }    else    {        // return it from this function.        *object = pobj;    }        CYG_REPORT_RETVAL(error);    return error;}// -------------------------------------------------------------------------// Close object and remove it from memorycyg_code Cyg_Loader::close( Cyg_LoadObject *object ){    CYG_REPORT_FUNCTION();        cyg_code error = 0;    Cyg_LoaderMemBlock *block = object->get_block();        object->~Cyg_LoadObject();    if( block )        block->free();        CYG_REPORT_RETVAL(error);    return error;}// -------------------------------------------------------------------------// Translate current error code into a string.const char *Cyg_Loader::error_string( ){    CYG_REPORT_FUNCTION();    char *ret = "";    CYG_REPORT_RETVAL(ret);        return ret;}// -------------------------------------------------------------------------// Look up a named symbol in loadlistCYG_ADDRESS Cyg_Loader::hash_lookup_addr( const char *name ){    CYG_ADDRESS addr = 0;    Cyg_LoadObject *object = loadlist.get_head();       do    {        addr = object->hash_lookup_addr( name );        if( addr != CYG_LOADER_NULLSYMADDR )            break;                object = object->get_next();            } while( object != loadlist.get_head() );    if( addr == CYG_LOADER_NULLSYMADDR )        error = CYG_LOADERR_NO_SYMBOL;        return addr;}// =========================================================================// Loader Object class membersCyg_LoadObject_Base::Cyg_LoadObject_Base(){    e_type = ET_EXEC;    e_entry = 0;    base = 0;        dynamic = _DYNAMIC;    parse_dynamic( dynamic );}// -------------------------------------------------------------------------// Constructor - reads and allocates the executable.Cyg_LoadObject_Base::Cyg_LoadObject_Base( Cyg_LoaderStream& stream,                                cyg_uint32 amode,                                Cyg_LoaderMemAlloc *mem ){    CYG_REPORT_FUNCTION();    CYG_REPORT_FUNCARG3XV( &stream, mode, mem );    Cyg_LoaderMemBlock *phblock = NULL;    Cyg_LoaderMemBlock *block = NULL;    Elf32_Phdr *phdr;    Elf32_Phdr *dynhdr = NULL;    cyg_uint32 memsize = 0;    cyg_uint32 maxalign = 0;    CYG_BYTE *memaddr;    Elf32_Addr vaddr_low = 0x7FFFFFFF;    Elf32_Addr vaddr_hi = 0;        mode = amode;    memalloc = mem;    error = CYG_LOADERR_NOERROR;        // OK, let's start by getting the ELF header...    Elf32_Ehdr elf_hdr;        error = stream.get_data( (CYG_BYTE *)&elf_hdr, sizeof( elf_hdr ) );    if( error != 0 )        goto finish;    // Check that this is a valid ELF file and that the various header    // fields match what we expect for our current architecture and    // platform.    if( !IS_ELF( elf_hdr ) )        error = CYG_LOADERR_NOT_ELF;    else if( elf_hdr.e_ident[EI_CLASS] != ELFCLASS32 )        error = CYG_LOADERR_INVALID_CLASS;#if CYG_BYTEORDER == CYG_LSBFIRST     else if( elf_hdr.e_ident[EI_DATA] != ELFDATA2LSB )#else    else if( elf_hdr.e_ident[EI_DATA] != ELFDATA2MSB )#endif                error = CYG_LOADERR_INVALID_BYTEORDER;    else if( elf_hdr.e_ident[EI_VERSION] != EV_CURRENT )        error = CYG_LOADERR_INVALID_VERSION;    else if( elf_hdr.e_machine != CYG_ELF_MACHINE )        error = CYG_LOADERR_INVALID_MACHINE;    else if( elf_hdr.e_version != EV_CURRENT )        error = CYG_LOADERR_INVALID_VERSION;    else if( elf_hdr.e_phentsize != sizeof(Elf32_Phdr) )        error = CYG_LOADERR_INVALID_VERSION;    if( error != 0 )        goto finish;        // OK that all seems in order, save some fields away for later.    e_type = elf_hdr.e_type;    e_entry = elf_hdr.e_entry;    // Now we must read the program header and prepare to read the    // object file into memory.    error = stream.seek( elf_hdr.e_phoff );    if( error != 0 )        goto finish;    // Allocate space for the header        phblock = memalloc->alloc( elf_hdr.e_phentsize * elf_hdr.e_phnum );    if( phblock == NULL )    {        error = CYG_LOADERR_NO_MEMORY;        goto finish;    }    error = stream.get_data( (CYG_BYTE *)phblock->address, sizeof(Elf32_Phdr)*elf_hdr.e_phnum );    if( error != 0 )        goto finish;        phdr = (Elf32_Phdr *)phblock->address;    // Loop over the program headers, totalling the sizes of the the    // PT_LOAD entries and saving a pointer to the PT_DYNAMIC entry    // when we find it.    // Since the segments must retain the same relationship to    // eachother in memory that their virtual addresses do in the    // headers, we determine the amount of memory needed by finding    // the extent of the virtual addresses covered by the executable.        for( int i = 0; i < elf_hdr.e_phnum; i++,phdr++ )    {        if( phdr->p_type == PT_DYNAMIC )        {            dynhdr = phdr;            continue;        }        if( phdr->p_type != PT_LOAD )            continue;        if( phdr->p_vaddr < vaddr_low )            vaddr_low = phdr->p_vaddr;        if( (phdr->p_vaddr+phdr->p_memsz) > vaddr_hi )            vaddr_hi = phdr->p_vaddr+phdr->p_memsz;        if( phdr->p_align > maxalign )            maxalign = phdr->p_align;            }    // Calculate how much memory we need and allocate it    memsize = vaddr_hi - vaddr_low;        block = memalloc->alloc( memsize, maxalign );    if( block == NULL )    {        error = CYG_LOADERR_NO_MEMORY;        goto finish;    }        // Attach to segments list    segs.add_tail( block );        // Calculate the base address for this executable. This is the    // difference between the actual address the executable is loaded    // at and its lowest virtual address. This value must be added to    // all addresses derived from the executable to relocate them into    // the real memory space.    base = (CYG_ADDRESS)block->address - vaddr_low;            // Loop over the program headers again, this time loading them    // into the memory segment we have allocated and clearing any    // unused areas to zero.    phdr = (Elf32_Phdr *)phblock->address;    memaddr = (CYG_BYTE *)block->address;        for( int i = 0; i < elf_hdr.e_phnum; i++,phdr++ )    {        if( phdr->p_type != PT_LOAD )            continue;        error = stream.seek( phdr->p_offset );        if( error != 0 ) break;        // Calculate the actual load address for this segment.        CYG_BYTE *loadaddr = (CYG_BYTE *)(phdr->p_vaddr + base);                error = stream.get_data( loadaddr, phdr->p_filesz );        if( error != 0 ) break;        // If the memory size is more than we got from the file, zero the remainder.                if( phdr->p_filesz < phdr->p_memsz )            memset( loadaddr+phdr->p_filesz,                    0,                    phdr->p_memsz-phdr->p_filesz );    }    dynamic = (Elf32_Dyn *)(dynhdr->p_vaddr + base);    parse_dynamic( dynamic );     finish:        if( phblock != NULL )        memalloc->free( phblock );    CYG_REPORT_RETURN();    }// -------------------------------------------------------------------------// Parse the dynamic segment void Cyg_LoadObject_Base::parse_dynamic( Elf32_Dyn *dynamic ){    CYG_REPORT_FUNCTION();    flags = 0;        for(;; dynamic++)    {        switch( dynamic->d_tag )        {        case DT_NULL:                   /* marks end of _DYNAMIC array */            return;        case DT_NEEDED:                 /* string table offset of needed lib */            break;                      // ignore for now        case DT_PLTRELSZ:               /* size of relocation entries in PLT */            pltrelsz = dynamic->d_un.d_val;            break;        case DT_PLTGOT:                 /* address PLT/GOT */            pltgot = dynamic->d_un.d_ptr + base;            break;        case DT_HASH:                   /* address of symbol hash table */            hash = (Elf_Hash *)(dynamic->d_un.d_ptr + base);            bucket = (Elf32_Word *)(hash+1);            chain = bucket+hash->nbucket;            break;        case DT_STRTAB:                 /* address of string table */            strtab = (unsigned char *)(dynamic->d_un.d_ptr + base);            break;        case DT_SYMTAB:                 /* address of symbol table */            symtab = (Elf32_Sym *)(dynamic->d_un.d_ptr + base);            break;        case DT_RELA:                   /* address of relocation table */            rela = (Elf32_Rela *)(dynamic->d_un.d_ptr + base);            break;        case DT_RELASZ:                 /* size of relocation table */            relasize = dynamic->d_un.d_val;            break;        case DT_RELAENT:                /* size of relocation entry */            relaent = dynamic->d_un.d_val;            break;        case DT_STRSZ:                  /* size of string table */            strsize = dynamic->d_un.d_val;            break;        case DT_SYMENT:                 /* size of symbol table entry */            syment = dynamic->d_un.d_val;            break;        case DT_INIT:                   /* address of initialization func. */            init = dynamic->d_un.d_ptr + base;            break;        case DT_FINI:                   /* address of termination function */            fini = dynamic->d_un.d_ptr + base;            break;        case DT_SONAME:                 /* string table offset of shared obj */            soname = dynamic->d_un.d_val;            break;        case DT_SYMBOLIC:               /* start sym search in shared obj. */            flags |= DF_SYMBOLIC;            break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -