📄 elf_loader.cpp
字号:
/* -*- C++ -*- */
/**
* Copyright (c) 2005 Zhejiang University, P.R.China
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
///==================================================
/**
* @file Elf_Loader.cpp
* @brief just do a little modification on ARM_ELF_Loader.cpp
* @author lijiecong <lijiecong@yahoo.com.cn> 2004/11/10
Wei He <hwzd1997@163.com>
*
* $Id: Elf_Loader.cpp,v 1.10 2005/04/06 07:44:05 zhoucf Exp $
*/
///==================================================
#include "stdafx.h"
#include "Core/Global.h"
#include "Core/Datatype.h"
#include "Core/Memory.h"
#include "Core/Processor.h"
#include "Core/Log.h"
#include "Core/System.h"
#include "ELF_Loader.h"
#include <iostream>
namespace ELF_LOADER{
//! load elf file
bool ELF_Loader::load_binary(std::string filepath)
{
in_elf_file.open( filepath.c_str(),std::ios::binary);
if( in_elf_file.fail())
{
WUKONG_ERROR<<"The file you want to debug can't open.Error occur\
at ELF_Loader::read_static_elf"<<std::endl;
throw( std::invalid_argument("file open error!"));
}
if (read_exec_elf() == -2)
return false;
in_elf_file.close();
return true;
}
//! read executable elf file
Core::s32 ELF_Loader::read_exec_elf(void)
{
//! judge whether this file can execute.
if ( is_executable_file( ) == NOTEXECUTABLEFILE)
{
WUKONG_ERROR<<"The loading file is not executable"<<std::endl;
return NOTEXECUTABLEFILE;
}
return load_static_elf();
}
// !can only read static compiled executable file on arm.
// !and,return the value of entry point.if this function read file failed
// !it returns a minus digit.
Core::u32 ELF_Loader::load_static_elf()
{
std::vector<Core::u8> buffer;
//!read program header
in_elf_file.seekg( elf_header.e_phoff,std::ios_base::beg);
Core::u32 program_header_num = elf_header.e_phnum;
program_header = new Elf32_Phdr[program_header_num];
in_elf_file.read((char *)program_header, sizeof(Elf32_Phdr)*program_header_num);
if(elf_header.e_ident[EI_DATA] == BIG_ENDIAN)
{//it is big end lijiecong 2005/3/16
for( int i = 0 ; i<program_header_num; i++)
program_head_big2small( program_header+i );
}
//! additional for test memory
in_elf_file.seekg( elf_header.e_shoff,std::ios_base::beg);
Elf32_Shdr *section_header = new Elf32_Shdr[elf_header.e_shnum];
in_elf_file.read((char *)section_header, sizeof(Elf32_Shdr)* elf_header.e_shnum);
if(elf_header.e_ident[EI_DATA] == BIG_ENDIAN)
{//it is big end lijiecong 2005/3/16
for( int i=0; i<elf_header.e_shnum; i++)
section_head_big2small( section_header+i);
}
Core::u32 end ,start;
start = 0x0fffffff ; end = 0;
for( Core::u32 snum = 0 ; snum<elf_header.e_shnum; snum++)
{
if ( ((section_header[snum].sh_flags)&SHF_WRITE) == SHF_WRITE)
{
start = (start > section_header[snum].sh_addr)?section_header[snum].sh_addr:start;
end = (end<section_header[snum].sh_addr+section_header[snum].sh_size)?\
section_header[snum].sh_addr+section_header[snum].sh_size:end;
}
}
delete []section_header;
for( Core::u32 i=0; i<program_header_num; i++)
{
char *p_segment;
Core::u32 memsz_after_align;//memory size after alignment
Core::u32 p_align = program_header[i].p_align;
Core::u32 p_filesz = program_header[i].p_filesz;
Core::u32 p_memsz = program_header[i].p_memsz;
Core::u32 p_offset = program_header[i].p_offset;
Core::u32 p_vaddr = program_header[i].p_vaddr;
if(program_header[i].p_type == PT_LOAD)
{
memsz_after_align = ((p_memsz + p_align-1)/p_align)*p_align;
// p_segment = new char[memsz_after_align];
buffer.clear();
buffer.resize(memsz_after_align);
in_elf_file.seekg(p_offset,std::ios_base::beg);
// in_elf_file.read( p_segment, p_filesz);
in_elf_file.read( (char *)&buffer[0], p_filesz);
// for( ; p_memsz<memsz_after_align; p_memsz++)
// {
//
// p_segment[p_memsz] = 0;
//
// }
//
//!copy to the memory,using the p_vaddr
if (p_vaddr<LOAD_ADDRESS)
{
std::string msg = "error:";
msg += __LINE__;msg += "lines";
msg += __FILE__;
WUKONG_ERROR<<msg<<std::endl;
return LOADADDRESSERROR;
}
Core::u32 start_vaddr = p_vaddr-LOAD_ADDRESS;
// buffer.clear();
// for( Core::u32 bytes=0; bytes<memsz_after_align;bytes++)
// {
//
// buffer.push_back( p_segment[bytes] );
//
// }
//
if( memsz_after_align>0 )
{
Core::MMU<Core::u32>& mmu = ((Core::CPU<Core::u32>*)(Core::Wukong_Get_System().get_cpu()))->get_mmu();
//get memory
mmu.access(Core::Memory<Core::u32>::MEMORY_WRITE,start_vaddr,memsz_after_align, buffer);
}
// delete [] p_segment;
}
}
Core::u32 pc = elf_header.e_entry;
this->set_pc( (pc - LOAD_ADDRESS) );
return elf_header.e_entry;
}
// !if the file you want to load is executable, the function return true ,else return false
Core::s32 ELF_Loader::is_executable_file(void)
{
in_elf_file.read( (char *)&elf_header, sizeof(Elf32_Ehdr));
//! judge whether or not the file is elf format and executable
if( elf_header.e_ident[EI_MAG1] != 'E' || elf_header.e_ident [EI_MAG2] != 'L'\
|| elf_header.e_ident [EI_MAG3]!='F')
{
return NOTEXECUTABLEFILE;
}
if(elf_header.e_ident[EI_DATA] == BIG_ENDIAN)
{//it is big end lijiecong 2005/3/16
elf_head_big2small( );
}
if( elf_header.e_entry <= 0 )
{
return NOTEXECUTABLEFILE;
}
return EXECUTABLEFILE;
}
void ELF_Loader::set_pc(Core::u32 pc)
{
((Core::CPU<Core::u32>*)(Core::Wukong_Get_System().get_cpu()))->set_pc(pc);
}
Core::s32 ELF_Loader::big_to_small( Core::s32 temp,Core::s32 size)
{
if( size == 2)
{
return ((temp>>8) & 0x00ff) | ((temp<<8)&0x00ff00);
}
else if(size == 4)
{
return ( (temp<<24) | ((temp<<8) & 0x00ff0000)\
|((temp>>8)&0x0000ff00) | ((temp>>24)&0x000000ff));
}
std::cout<<"There is an error in line:"<<__LINE__<<"file: "<<__FILE__<<std::endl;
}
//convert elf header stored in big-endian to little-endian
void ELF_Loader::elf_head_big2small()
{
elf_header.e_ehsize = big_to_small(elf_header.e_ehsize,sizeof(elf_header.e_ehsize));
elf_header.e_entry = big_to_small(elf_header.e_entry,sizeof(elf_header.e_entry));
elf_header.e_flags = big_to_small(elf_header.e_flags,sizeof(elf_header.e_flags));
elf_header.e_machine = big_to_small(elf_header.e_machine,sizeof(elf_header.e_machine));
elf_header.e_phentsize = big_to_small(elf_header.e_phentsize,sizeof(elf_header.e_phentsize));
elf_header.e_phnum = big_to_small(elf_header.e_phnum,sizeof(elf_header.e_phnum));
elf_header.e_phoff = big_to_small(elf_header.e_phoff,sizeof(elf_header.e_phoff));
elf_header.e_shentsize = big_to_small(elf_header.e_shentsize,sizeof(elf_header.e_shentsize));
elf_header.e_shnum = big_to_small(elf_header.e_shnum,sizeof(elf_header.e_shentsize));
elf_header.e_shoff = big_to_small(elf_header.e_shoff,sizeof(elf_header.e_shoff));
elf_header.e_shstrndx = big_to_small(elf_header.e_shstrndx,sizeof(elf_header.e_shstrndx));
elf_header.e_type = big_to_small(elf_header.e_type,sizeof(elf_header.e_type));
elf_header.e_version = big_to_small(elf_header.e_version,sizeof(elf_header.e_version));
}
//convert ONE program header stored in big-endian to little-endian
void ELF_Loader::program_head_big2small( Elf32_Phdr *program_header )
{
if( program_header != NULL)
{
program_header->p_align = big_to_small(program_header->p_align,sizeof(program_header->p_align));
program_header->p_filesz = big_to_small(program_header->p_filesz,sizeof(program_header->p_filesz));
program_header->p_flags = big_to_small(program_header->p_flags,sizeof(program_header->p_flags));
program_header->p_memsz = big_to_small(program_header->p_memsz,sizeof(program_header->p_memsz));
program_header->p_offset = big_to_small(program_header->p_offset,sizeof(program_header->p_offset));
program_header->p_paddr = big_to_small(program_header->p_paddr,sizeof(program_header->p_paddr));
program_header->p_type = big_to_small(program_header->p_type,sizeof(program_header->p_type));
program_header->p_vaddr = big_to_small(program_header->p_vaddr,sizeof(program_header->p_vaddr));
}
}
//convert ONE section header stored in big-endian to little-endian
void ELF_Loader::section_head_big2small(Elf32_Shdr *section_header)
{
if( section_header != NULL)
{
section_header->sh_addr = big_to_small(section_header->sh_addr,sizeof(section_header->sh_addr));
section_header->sh_addralign = big_to_small(section_header->sh_addralign,sizeof(section_header->sh_addralign));
section_header->sh_entsize = big_to_small(section_header->sh_entsize,sizeof(section_header->sh_entsize));
section_header->sh_flags = big_to_small(section_header->sh_flags,sizeof(section_header->sh_flags));
section_header->sh_info = big_to_small(section_header->sh_info,sizeof(section_header->sh_info));
section_header->sh_link = big_to_small(section_header->sh_link,sizeof(section_header->sh_link));
section_header->sh_name = big_to_small(section_header->sh_name,sizeof(section_header->sh_name));
section_header->sh_offset = big_to_small(section_header->sh_offset,sizeof(section_header->sh_offset));
section_header->sh_size = big_to_small(section_header->sh_size,sizeof(section_header->sh_size));
section_header->sh_type = big_to_small(section_header->sh_type,sizeof(section_header->sh_type));
}
}
}//namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -