📄 loader.cxx
字号:
case DT_REL: /* address of rel. tbl. w addends */ rel = (Elf32_Rel *)(dynamic->d_un.d_ptr + base); break; case DT_RELSZ: /* size of DT_REL relocation table */ relsize = dynamic->d_un.d_val; break; case DT_RELENT: /* size of DT_REL relocation entry */ relent = dynamic->d_un.d_val; break; case DT_PLTREL: /* PLT referenced relocation entry */ pltrel = dynamic->d_un.d_val; break; case DT_DEBUG: /* Debug data */ break; /* ignore for now */ case DT_TEXTREL: /* Allow rel. mod. to unwritable seg */ flags |= DF_TEXTREL; break; case DT_JMPREL: /* add. of PLT's relocation entries */ jmprel = dynamic->d_un.d_ptr + base; break; case DT_BIND_NOW: /* Bind now regardless of env setting */ flags |= DF_BIND_NOW; break; case DT_INIT_ARRAY: /* init array address */ init_array = (Elf32_Addr *)(dynamic->d_un.d_ptr + base); break; case DT_FINI_ARRAY: /* fini array address */ fini_array = (Elf32_Addr *)(dynamic->d_un.d_ptr + base); break; case DT_INIT_ARRAYSZ: /* init array size */ init_array_sz = dynamic->d_un.d_val; break; case DT_FINI_ARRAYSZ: /* fini array size */ fini_array_sz = dynamic->d_un.d_val; break; case DT_FLAGS: /* flags */ flags |= dynamic->d_un.d_val; break; case DT_PREINIT_ARRAY: /* preinit array address */ pre_init_array = (Elf32_Addr *)(dynamic->d_un.d_ptr + base); break; case DT_PREINIT_ARRAYSZ: /* preinit array size */ pre_init_array_sz = dynamic->d_un.d_val; break; default: // handle format-specific entries break; } } CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Get the symbol name from the current object's symbol table, look it// up in the hash tables of the loaded objects, and return its address.CYG_ADDRESS Cyg_LoadObject_Base::get_sym_addr_from_ix( Elf32_Word ix ){ Elf32_Sym *sym = get_sym( ix ); if( sym == NULL ) return 0; const char *name = get_name( sym->st_name ); // If the symbol has local binding, we must look for // it in this object only. if( ELF32_ST_BIND(sym->st_info) == STB_LOCAL ) return hash_lookup_addr( name ); // Otherwise search the loaded objects in load order return Cyg_Loader::loader->hash_lookup_addr( name );}// -------------------------------------------------------------------------// Lookup the name in our hash table and return the symbol table entryElf32_Sym *Cyg_LoadObject_Base::hash_lookup( const char *name ){ Elf32_Sym *ret = NULL; if( hash == NULL ) { error = CYG_LOADERR_NO_HASHTABLE; return NULL; } error = CYG_LOADERR_NO_SYMBOL; Elf32_Word ix = elf_hash( (const unsigned char *)name ); ix %= hash->nbucket; // get head of chain Elf32_Word iy = bucket[ ix ]; while( iy != STN_UNDEF ) { Elf32_Sym *sym = get_sym( iy ); const char *sname = get_name( sym->st_name ); if( streq( name, sname ) ) { ret = sym; error = CYG_LOADERR_NOERROR; break; } iy = chain[ iy ]; } return ret;}// -------------------------------------------------------------------------// Lookup the given name in our symbol table and return it's value// relocated to our load address.CYG_ADDRESS Cyg_LoadObject_Base::hash_lookup_addr( const char *name ){ Elf32_Sym *sym = hash_lookup( name ); if( sym == NULL ) return CYG_LOADER_NULLSYMADDR; // Check that this symbol is for a defined object, if its type is // NOTYPE then it is undefined, here, and we cannot take its address. // Hopefully it is defined in some other object. if( ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE ) { error = CYG_LOADERR_NO_SYMBOL; return CYG_LOADER_NULLSYMADDR; } return sym->st_value + base;}// -------------------------------------------------------------------------// ELF hash function// This is the standard hash function used for indexing the bucket// array in the hash table.unsigned long Cyg_LoadObject_Base::elf_hash( const unsigned char *name ){ unsigned long h = 0, g; while( *name ) { h = ( h << 4 ) + *name++; if( (g = h & 0xf0000000) != 0 ) h ^= g >> 24; h &= ~g; } return h;}// -------------------------------------------------------------------------//Elf32_Sym *Cyg_LoadObject_Base::get_sym( Elf32_Word ix ){ if( symtab == NULL ) return NULL; return &symtab[ix];}char *Cyg_LoadObject_Base::get_name( Elf32_Word offset ){ if( strtab == NULL || offset > strsize ) return NULL; return (char *)(&strtab[offset]);}// -------------------------------------------------------------------------// Destructor// -------------------------------------------------------------------------// Cyg_LoadObject_Base destructorCyg_LoadObject_Base::~Cyg_LoadObject_Base(){ CYG_REPORT_FUNCTION(); // empty out segments list while( !segs.empty() ) { Cyg_LoaderMemBlock *block = segs.rem_head(); block->free(); } CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Translate a symbol into its address.void *Cyg_LoadObject_Base::symbol( const char *name ){ CYG_REPORT_FUNCTION(); Elf32_Addr addr = hash_lookup_addr( name ); if( addr == CYG_LOADER_NULLSYMADDR ) addr = 0; CYG_REPORT_RETVAL( addr ); return (void *)addr;}// -------------------------------------------------------------------------// Start the given executable object runningcyg_code Cyg_LoadObject_Base::exec(int argc, char **argv, char **envv){ CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG3XV( argc, argv, envv ); cyg_code error = 0; CYG_REPORT_RETVAL(error); return error;}// =========================================================================// Cyg_LoadObject members// -------------------------------------------------------------------------// Apply relocationsvoid Cyg_LoadObject::relocate(){ CYG_REPORT_FUNCTION(); if( rel != NULL ) { Elf32_Rel *r = rel; for( int i = relsize; i > 0 && error == 0; i -= relent, r++ ) error = apply_rel( ELF32_R_TYPE(r->r_info), ELF32_R_SYM(r->r_info), r->r_offset); } if( error == 0 && rela != NULL ) { Elf32_Rela *r = rela; for( int i = relasize; i > 0 && error == 0; i -= relaent, r++ ) error = apply_rela( ELF32_R_TYPE(r->r_info), ELF32_R_SYM(r->r_info), r->r_offset, r->r_addend); } CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Apply JMPREL relocations for the PLTvoid Cyg_LoadObject::relocate_plt(){ CYG_REPORT_FUNCTION(); if( pltrel == DT_REL ) { Elf32_Rel *r = (Elf32_Rel *)jmprel; for( int i = pltrelsz; i > 0 && error == 0; i -= sizeof(Elf32_Rel), r++ ) error = apply_rel( ELF32_R_TYPE(r->r_info), ELF32_R_SYM(r->r_info), r->r_offset); } if( error == 0 && pltrel == DT_RELA ) { Elf32_Rela *r = (Elf32_Rela *)jmprel; for( int i = pltrelsz; i > 0 && error == 0; i -= sizeof(Elf32_Rela), r++ ) error = apply_rela( ELF32_R_TYPE(r->r_info), ELF32_R_SYM(r->r_info), r->r_offset, r->r_addend); } CYG_REPORT_RETURN();}// =========================================================================// Loader memory allocator default class methods.// The default behaviour of this class is to use malloc/realloc/free// to handle memory.// -------------------------------------------------------------------------Cyg_LoaderMemAlloc::Cyg_LoaderMemAlloc(){ // no initialization needed}// -------------------------------------------------------------------------Cyg_LoaderMemAlloc::~Cyg_LoaderMemAlloc(){ // No destruction needed}// -------------------------------------------------------------------------// Allocate memory of the supplied size and alignment.// size - size in bytes// alignment - alignment expressed as a power of 2Cyg_LoaderMemBlock *Cyg_LoaderMemAlloc::alloc( cyg_int32 size, cyg_int32 alignment){#if CYGINT_ISO_MALLOC Cyg_LoaderMemBlock *block; cyg_uint8 *mem; cyg_uint32 acsize = sizeof(Cyg_LoaderMemBlock) + size + alignment; mem = (cyg_uint8 *)::malloc( acsize ); if( mem == NULL ) return NULL; block = (Cyg_LoaderMemBlock *)mem; // set up aligned block address block->address = (void *)((((CYG_ADDRWORD)mem+sizeof(Cyg_LoaderMemBlock))+alignment) & ~(alignment-1)); block->size = size; block->alignment = alignment; block->mem = this; block->actual_address = (CYG_ADDRESS) mem; block->actual_size = acsize; return block;#else return 0;#endif }// -------------------------------------------------------------------------// Reallocate blockCyg_LoaderMemBlock *Cyg_LoaderMemAlloc::realloc( Cyg_LoaderMemBlock *oblock, cyg_int32 size, cyg_int32 alignment){#if CYGINT_ISO_MALLOC Cyg_LoaderMemBlock *block; cyg_uint8 *mem; if( alignment == -1 ) alignment = oblock->alignment; cyg_uint32 acsize = sizeof(Cyg_LoaderMemBlock) + size + alignment; mem = (cyg_uint8 *)::realloc( (void *)(oblock->actual_address), acsize ); if( mem == NULL ) return NULL; block = (Cyg_LoaderMemBlock *)mem; // set up aligned block address block->address = (void *)((((CYG_ADDRWORD)mem+sizeof(Cyg_LoaderMemBlock))+alignment) & (alignment-1)); block->size = size; block->alignment = alignment; block->mem = this; block->actual_address = (CYG_ADDRESS) mem; block->actual_size = acsize; return block;#else return NULL;#endif} // -------------------------------------------------------------------------// Free a previously allocated memory segment.void Cyg_LoaderMemAlloc::free( Cyg_LoaderMemBlock *block ){#if CYGINT_ISO_MALLOC ::free( (void *)block->actual_address );#endif }// =========================================================================// Loader stream functionsCyg_LoaderStream::Cyg_LoaderStream(){}Cyg_LoaderStream::~Cyg_LoaderStream(){}cyg_code Cyg_LoaderStream::get_byte(CYG_BYTE *val){ return CYG_LOADERR_EOF;}cyg_code Cyg_LoaderStream::get_data(CYG_BYTE *addr, CYG_ADDRWORD size){ return CYG_LOADERR_EOF;}cyg_code Cyg_LoaderStream::seek(CYG_ADDRWORD pos){ return CYG_LOADERR_SEEK; }// =========================================================================// Memory based loader streamCyg_LoaderStream_Mem::Cyg_LoaderStream_Mem( const void *addr, cyg_int32 size ){ base = pos = (CYG_ADDRESS)addr; end = base + size;}Cyg_LoaderStream_Mem::~Cyg_LoaderStream_Mem(){ // nothing to do} cyg_code Cyg_LoaderStream_Mem::get_byte(CYG_BYTE *val){ if( pos == end ) return CYG_LOADERR_EOF; *val = *(CYG_BYTE *)pos; pos++; return CYG_LOADERR_NOERROR;}cyg_code Cyg_LoaderStream_Mem::get_data(CYG_BYTE *addr, CYG_ADDRWORD size){ if( pos == end || (pos+size) > end ) return CYG_LOADERR_EOF; memcpy( (void *)addr, (void *)pos, size ); pos += size; return CYG_LOADERR_NOERROR;}cyg_code Cyg_LoaderStream_Mem::seek(CYG_ADDRWORD apos){ CYG_ADDRWORD npos = base+apos; if( npos > end || npos < base ) return CYG_LOADERR_SEEK; pos = npos; return CYG_LOADERR_NOERROR;}// =========================================================================// file based loader stream#ifdef CYGPKG_IO_FILEIO#include <unistd.h>Cyg_LoaderStream_File::Cyg_LoaderStream_File( int afd ){ fd = afd;}Cyg_LoaderStream_File::~Cyg_LoaderStream_File(){ // nothing to do fd = 0;} cyg_code Cyg_LoaderStream_File::get_byte(CYG_BYTE *val){ ssize_t got = read( fd, (void *)val, 1 ); if( got == 0 ) return CYG_LOADERR_EOF; return CYG_LOADERR_NOERROR;}cyg_code Cyg_LoaderStream_File::get_data(CYG_BYTE *addr, CYG_ADDRWORD size){ ssize_t got = read( fd, (void *)addr, size ); if( got != (ssize_t)size ) return CYG_LOADERR_EOF; return CYG_LOADERR_NOERROR;}cyg_code Cyg_LoaderStream_File::seek(CYG_ADDRWORD apos){ off_t npos = lseek( fd, apos, SEEK_SET ); if( npos != apos ) return CYG_LOADERR_SEEK; return CYG_LOADERR_NOERROR;}#endif// =========================================================================// EOF loader.cxx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -