|
|
/*------------------------------------------------------------------------------
|
|
|
-- This file is a part of the SocExplorer Software
|
|
|
-- Copyright (C) 2014, Plasma Physics Laboratory - CNRS
|
|
|
--
|
|
|
-- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
-------------------------------------------------------------------------------*/
|
|
|
/*-- Author :
|
|
|
Alexis Jeandet
|
|
|
-- Mail :
|
|
|
alexis.jeandet@member.fsf.org
|
|
|
----------------------------------------------------------------------------*/
|
|
|
#include "elffile.h"
|
|
|
#include "srecfile.h"
|
|
|
#include "binaryfile.h"
|
|
|
#include <stdint.h>
|
|
|
|
|
|
ElfFile::ElfFile()
|
|
|
:abstractBinFile()
|
|
|
{
|
|
|
this->opened = false;
|
|
|
this->type_elf = false;
|
|
|
this->elfFile = (int)NULL;
|
|
|
this->e = NULL;
|
|
|
}
|
|
|
|
|
|
ElfFile::ElfFile(const QString &File)
|
|
|
:abstractBinFile()
|
|
|
{
|
|
|
this->opened = false;
|
|
|
this->type_elf = false;
|
|
|
this->elfFile = (int)NULL;
|
|
|
this->e = NULL;
|
|
|
this->p_fileName = File;
|
|
|
openFile(File);
|
|
|
}
|
|
|
|
|
|
ElfFile::~ElfFile()
|
|
|
{
|
|
|
closeFile();
|
|
|
if(scn)free(scn);
|
|
|
if(data)free(data);
|
|
|
for(int i=0;i<this->sections.count();i++)
|
|
|
{
|
|
|
delete this->sections.at(i);
|
|
|
}
|
|
|
this->sections.clear();
|
|
|
for(int i=0;i<this->Segments.count();i++)
|
|
|
{
|
|
|
free(this->Segments.at(i));
|
|
|
}
|
|
|
this->Segments.clear();
|
|
|
for(int i=0;i<symbols.count();i++)
|
|
|
{
|
|
|
delete this->symbols.at(i);
|
|
|
}
|
|
|
this->symbols.clear();
|
|
|
}
|
|
|
|
|
|
bool ElfFile::openFile(const QString &File)
|
|
|
{
|
|
|
this->p_fileName = File;
|
|
|
this->closeFile();
|
|
|
if(elf_version(EV_CURRENT)==EV_NONE)return 0;
|
|
|
#ifdef _ELF_WINDOWS_
|
|
|
this->elfFile = open(File.toStdString().c_str(),O_RDONLY|O_BINARY ,0);
|
|
|
#else
|
|
|
this->elfFile = open(File.toStdString().c_str(),O_RDONLY ,0);
|
|
|
#endif
|
|
|
if(this->elfFile==(int)NULL)return 0;
|
|
|
this->e = elf_begin(this->elfFile,ELF_C_READ,NULL);
|
|
|
if(this->e==NULL)return 0;
|
|
|
this->ek = elf_kind(this->e);
|
|
|
gelf_getehdr (this->e, &this->ehdr );
|
|
|
elf_getshdrstrndx (this->e, &this->shstrndx);
|
|
|
this->updateSegments();
|
|
|
this->updateSections();
|
|
|
this->updateSymbols();
|
|
|
this->opened = true;
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
bool ElfFile::isopened()
|
|
|
{
|
|
|
return this->opened;
|
|
|
}
|
|
|
|
|
|
int ElfFile::closeFile()
|
|
|
{
|
|
|
if(this->elfFile!=(int)NULL)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
elf_end(this->e);
|
|
|
this->e = NULL;
|
|
|
}
|
|
|
close(this->elfFile);
|
|
|
this->elfFile = (int)NULL;
|
|
|
}
|
|
|
this->opened = false;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
QList<codeFragment*> ElfFile::getFragments(QStringList fragmentList)
|
|
|
{
|
|
|
QList<codeFragment*> fragments;
|
|
|
if (isopened())
|
|
|
{
|
|
|
for(int i =0;i<fragmentList.count();i++)
|
|
|
{
|
|
|
fragments.append(getFragment(fragmentList.at(i)));
|
|
|
}
|
|
|
}
|
|
|
return fragments;
|
|
|
}
|
|
|
|
|
|
QList<codeFragment*> ElfFile::getFragments()
|
|
|
{
|
|
|
return getFragments(QStringList()<<".data"<<".text");
|
|
|
}
|
|
|
|
|
|
codeFragment *ElfFile::getFragment(const QString &name)
|
|
|
{
|
|
|
codeFragment* fragment= new codeFragment();
|
|
|
for(int i=0;i<getSectionCount();i++)
|
|
|
{
|
|
|
if(getSectionName(i) == name)
|
|
|
{
|
|
|
fragment->data =NULL;
|
|
|
fragment->size = getSectionDatasz(i);
|
|
|
fragment->address = getSectionPaddr(i);
|
|
|
getSectionData(i,&fragment->data);
|
|
|
}
|
|
|
}
|
|
|
return fragment;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString elfresolveMachine(Elf64_Half e_machine)
|
|
|
{
|
|
|
QString machineName;
|
|
|
//Update from with bash script don't write it by yourself!
|
|
|
switch(e_machine)
|
|
|
{
|
|
|
case EM_NONE:
|
|
|
machineName = " No machine ";
|
|
|
break;
|
|
|
case EM_M32:
|
|
|
machineName = " AT&T WE 32100 ";
|
|
|
break;
|
|
|
case EM_SPARC:
|
|
|
machineName = " SUN SPARC ";
|
|
|
break;
|
|
|
case EM_386:
|
|
|
machineName = " Intel 80386 ";
|
|
|
break;
|
|
|
case EM_68K:
|
|
|
machineName = " Motorola m68k family ";
|
|
|
break;
|
|
|
case EM_88K:
|
|
|
machineName = " Motorola m88k family ";
|
|
|
break;
|
|
|
case EM_860:
|
|
|
machineName = " Intel 80860 ";
|
|
|
break;
|
|
|
case EM_MIPS:
|
|
|
machineName = " MIPS R3000 big-endian ";
|
|
|
break;
|
|
|
case EM_S370:
|
|
|
machineName = " IBM System/370 ";
|
|
|
break;
|
|
|
case EM_MIPS_RS3_LE:
|
|
|
machineName = " MIPS R3000 little-endian ";
|
|
|
break;
|
|
|
case EM_PARISC:
|
|
|
machineName = " HPPA ";
|
|
|
break;
|
|
|
case EM_VPP500:
|
|
|
machineName = " Fujitsu VPP500 ";
|
|
|
break;
|
|
|
case EM_SPARC32PLUS:
|
|
|
machineName = " Sun's \"v8plus\" ";
|
|
|
break;
|
|
|
case EM_960:
|
|
|
machineName = " Intel 80960 ";
|
|
|
break;
|
|
|
case EM_PPC:
|
|
|
machineName = " PowerPC ";
|
|
|
break;
|
|
|
case EM_PPC64:
|
|
|
machineName = " PowerPC 64-bit ";
|
|
|
break;
|
|
|
case EM_S390:
|
|
|
machineName = " IBM S390 ";
|
|
|
break;
|
|
|
case EM_V800:
|
|
|
machineName = " NEC V800 series ";
|
|
|
break;
|
|
|
case EM_FR20:
|
|
|
machineName = " Fujitsu FR20 ";
|
|
|
break;
|
|
|
case EM_RH32:
|
|
|
machineName = " TRW RH-32 ";
|
|
|
break;
|
|
|
case EM_RCE:
|
|
|
machineName = " Motorola RCE ";
|
|
|
break;
|
|
|
case EM_ARM:
|
|
|
machineName = " ARM ";
|
|
|
break;
|
|
|
case EM_FAKE_ALPHA:
|
|
|
machineName = " Digital Alpha ";
|
|
|
break;
|
|
|
case EM_SH:
|
|
|
machineName = " Hitachi SH ";
|
|
|
break;
|
|
|
case EM_SPARCV9:
|
|
|
machineName = " SPARC v9 64-bit ";
|
|
|
break;
|
|
|
case EM_TRICORE:
|
|
|
machineName = " Siemens Tricore ";
|
|
|
break;
|
|
|
case EM_ARC:
|
|
|
machineName = " Argonaut RISC Core ";
|
|
|
break;
|
|
|
case EM_H8_300:
|
|
|
machineName = " Hitachi H8/300 ";
|
|
|
break;
|
|
|
case EM_H8_300H:
|
|
|
machineName = " Hitachi H8/300H ";
|
|
|
break;
|
|
|
case EM_H8S:
|
|
|
machineName = " Hitachi H8S ";
|
|
|
break;
|
|
|
case EM_H8_500:
|
|
|
machineName = " Hitachi H8/500 ";
|
|
|
break;
|
|
|
case EM_IA_64:
|
|
|
machineName = " Intel Merced ";
|
|
|
break;
|
|
|
case EM_MIPS_X:
|
|
|
machineName = " Stanford MIPS-X ";
|
|
|
break;
|
|
|
case EM_COLDFIRE:
|
|
|
machineName = " Motorola Coldfire ";
|
|
|
break;
|
|
|
case EM_68HC12:
|
|
|
machineName = " Motorola M68HC12 ";
|
|
|
break;
|
|
|
case EM_MMA:
|
|
|
machineName = " Fujitsu MMA Multimedia Accelerator";
|
|
|
break;
|
|
|
case EM_PCP:
|
|
|
machineName = " Siemens PCP ";
|
|
|
break;
|
|
|
case EM_NCPU:
|
|
|
machineName = " Sony nCPU embeeded RISC ";
|
|
|
break;
|
|
|
case EM_NDR1:
|
|
|
machineName = " Denso NDR1 microprocessor ";
|
|
|
break;
|
|
|
case EM_STARCORE:
|
|
|
machineName = " Motorola Start*Core processor ";
|
|
|
break;
|
|
|
case EM_ME16:
|
|
|
machineName = " Toyota ME16 processor ";
|
|
|
break;
|
|
|
case EM_ST100:
|
|
|
machineName = " STMicroelectronic ST100 processor ";
|
|
|
break;
|
|
|
case EM_TINYJ:
|
|
|
machineName = " Advanced Logic Corp. Tinyj emb.fam";
|
|
|
break;
|
|
|
case EM_X86_64:
|
|
|
machineName = " AMD x86-64 architecture ";
|
|
|
break;
|
|
|
case EM_PDSP:
|
|
|
machineName = " Sony DSP Processor ";
|
|
|
break;
|
|
|
case EM_FX66:
|
|
|
machineName = " Siemens FX66 microcontroller ";
|
|
|
break;
|
|
|
case EM_ST9PLUS:
|
|
|
machineName = " STMicroelectronics ST9+ 8/16 mc ";
|
|
|
break;
|
|
|
case EM_ST7:
|
|
|
machineName = " STmicroelectronics ST7 8 bit mc ";
|
|
|
break;
|
|
|
case EM_68HC16:
|
|
|
machineName = " Motorola MC68HC16 microcontroller ";
|
|
|
break;
|
|
|
case EM_68HC11:
|
|
|
machineName = " Motorola MC68HC11 microcontroller ";
|
|
|
break;
|
|
|
case EM_68HC08:
|
|
|
machineName = " Motorola MC68HC08 microcontroller ";
|
|
|
break;
|
|
|
case EM_68HC05:
|
|
|
machineName = " Motorola MC68HC05 microcontroller ";
|
|
|
break;
|
|
|
case EM_SVX:
|
|
|
machineName = " Silicon Graphics SVx ";
|
|
|
break;
|
|
|
case EM_ST19:
|
|
|
machineName = " STMicroelectronics ST19 8 bit mc ";
|
|
|
break;
|
|
|
case EM_VAX:
|
|
|
machineName = " Digital VAX ";
|
|
|
break;
|
|
|
case EM_CRIS:
|
|
|
machineName = " Axis Communications 32-bit embedded processor ";
|
|
|
break;
|
|
|
case EM_JAVELIN:
|
|
|
machineName = " Infineon Technologies 32-bit embedded processor ";
|
|
|
break;
|
|
|
case EM_FIREPATH:
|
|
|
machineName = " Element 14 64-bit DSP Processor ";
|
|
|
break;
|
|
|
case EM_ZSP:
|
|
|
machineName = " LSI Logic 16-bit DSP Processor ";
|
|
|
break;
|
|
|
case EM_MMIX:
|
|
|
machineName = " Donald Knuth's educational 64-bit processor ";
|
|
|
break;
|
|
|
case EM_HUANY:
|
|
|
machineName = " Harvard University machine-independent object files ";
|
|
|
break;
|
|
|
case EM_PRISM:
|
|
|
machineName = " SiTera Prism ";
|
|
|
break;
|
|
|
case EM_AVR:
|
|
|
machineName = " Atmel AVR 8-bit microcontroller ";
|
|
|
break;
|
|
|
case EM_FR30:
|
|
|
machineName = " Fujitsu FR30 ";
|
|
|
break;
|
|
|
case EM_D10V:
|
|
|
machineName = " Mitsubishi D10V ";
|
|
|
break;
|
|
|
case EM_D30V:
|
|
|
machineName = " Mitsubishi D30V ";
|
|
|
break;
|
|
|
case EM_V850:
|
|
|
machineName = " NEC v850 ";
|
|
|
break;
|
|
|
case EM_M32R:
|
|
|
machineName = " Mitsubishi M32R ";
|
|
|
break;
|
|
|
case EM_MN10300:
|
|
|
machineName = " Matsushita MN10300 ";
|
|
|
break;
|
|
|
case EM_MN10200:
|
|
|
machineName = " Matsushita MN10200 ";
|
|
|
break;
|
|
|
case EM_PJ:
|
|
|
machineName = " picoJava ";
|
|
|
break;
|
|
|
case EM_OPENRISC:
|
|
|
machineName = " OpenRISC 32-bit embedded processor ";
|
|
|
break;
|
|
|
case EM_ARC_A5:
|
|
|
machineName = " ARC Cores Tangent-A5 ";
|
|
|
break;
|
|
|
case EM_XTENSA:
|
|
|
machineName = " Tensilica Xtensa Architecture ";
|
|
|
break;
|
|
|
case EM_AARCH64:
|
|
|
machineName = " ARM AARCH64 ";
|
|
|
break;
|
|
|
case EM_TILEPRO:
|
|
|
machineName = " Tilera TILEPro ";
|
|
|
break;
|
|
|
case EM_MICROBLAZE:
|
|
|
machineName = " Xilinx MicroBlaze ";
|
|
|
break;
|
|
|
case EM_TILEGX:
|
|
|
machineName = " Tilera TILE-Gx ";
|
|
|
break;
|
|
|
case EM_NUM:
|
|
|
machineName = "";
|
|
|
break;
|
|
|
default:
|
|
|
machineName ="Unknow Machine";
|
|
|
break;
|
|
|
}
|
|
|
return machineName;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString ElfFile::getClass()
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
int eclass = gelf_getclass(this->e);
|
|
|
if(eclass==ELFCLASS32)return "ELF32";
|
|
|
if(eclass==ELFCLASS64)return "ELF64";
|
|
|
}
|
|
|
return "none";
|
|
|
}
|
|
|
|
|
|
|
|
|
bool ElfFile::iself()
|
|
|
{
|
|
|
return (this->getType()!="Unknow");
|
|
|
}
|
|
|
|
|
|
QString ElfFile::getArchitecture()
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
return elfresolveMachine(this->ehdr.e_machine);
|
|
|
}
|
|
|
return "";
|
|
|
}
|
|
|
|
|
|
|
|
|
QString ElfFile::getType()
|
|
|
{
|
|
|
QString kind("");
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
switch(this->ek)
|
|
|
{
|
|
|
case ELF_K_AR:
|
|
|
kind = "Archive";
|
|
|
break;
|
|
|
case ELF_K_ELF:
|
|
|
kind = "Elf";
|
|
|
break;
|
|
|
case ELF_K_COFF:
|
|
|
kind = "COFF";
|
|
|
break;
|
|
|
case ELF_K_NUM:
|
|
|
kind = "NUM";
|
|
|
break;
|
|
|
case ELF_K_NONE:
|
|
|
kind = "Data";
|
|
|
break;
|
|
|
default:
|
|
|
kind = "Unknow";
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
return kind;
|
|
|
}
|
|
|
|
|
|
QString ElfFile::getEndianness()
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(this->ehdr.e_ident[EI_DATA]==ELFDATA2LSB)return "2's complement, little endian";
|
|
|
if(this->ehdr.e_ident[EI_DATA]==ELFDATA2MSB)return "2's complement, big endian";
|
|
|
}
|
|
|
return "none";
|
|
|
}
|
|
|
|
|
|
QString ElfFile::getABI()
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_NONE)return "UNIX System V ABI";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_SYSV)return "Alias";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_HPUX)return "HP-UX";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_NETBSD)return "NetBSD";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_LINUX)return "Object uses GNU ELF extensions";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_SOLARIS)return "Sun Solaris";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_AIX)return "IBM AIX";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_IRIX)return "SGI Irix";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_FREEBSD)return "FreeBSD";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_TRU64)return "Compaq TRU64 UNIX";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_MODESTO)return " Novell Modesto";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_OPENBSD)return "OpenBSD";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_ARM_AEABI)return "ARM EABI";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_ARM)return "ARM";
|
|
|
if(this->ehdr.e_ident[EI_OSABI]==ELFOSABI_STANDALONE)return "Standalone (embedded) application";
|
|
|
}
|
|
|
return "none";
|
|
|
}
|
|
|
|
|
|
|
|
|
qint64 ElfFile::getVersion()
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
return this->ehdr.e_version;
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
qint64 ElfFile::getEntryPointAddress()
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
return this->ehdr.e_entry;
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
|
|
|
int ElfFile::getSectionCount()
|
|
|
{
|
|
|
return (int)this->SectionCount;
|
|
|
}
|
|
|
|
|
|
int ElfFile::getSymbolCount()
|
|
|
{
|
|
|
return (int)this->SymbolCount;
|
|
|
}
|
|
|
|
|
|
|
|
|
int ElfFile::getSegmentCount()
|
|
|
{
|
|
|
return (int)this->SegmentCount;
|
|
|
}
|
|
|
|
|
|
|
|
|
QString ElfFile::getSegmentType(int index)
|
|
|
{
|
|
|
QString type("");
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->Segments.count())
|
|
|
{
|
|
|
switch(this->Segments.at(index)->p_type)
|
|
|
{
|
|
|
case PT_NULL:
|
|
|
type = "Program header table entry unused";
|
|
|
break;
|
|
|
case PT_LOAD:
|
|
|
type = "Loadable program segment";
|
|
|
break;
|
|
|
case PT_DYNAMIC :
|
|
|
type = "Dynamic linking information";
|
|
|
break;
|
|
|
case PT_INTERP:
|
|
|
type ="Program interpreter";
|
|
|
break;
|
|
|
case PT_NOTE:
|
|
|
type = "Auxiliary information";
|
|
|
break;
|
|
|
case PT_SHLIB:
|
|
|
type = "Reserved";
|
|
|
break;
|
|
|
case PT_PHDR:
|
|
|
type = "Entry for header table itself";
|
|
|
break;
|
|
|
case PT_TLS:
|
|
|
type = "Thread-local storage segment";
|
|
|
break;
|
|
|
case PT_NUM:
|
|
|
type = "Number of defined types";
|
|
|
break;
|
|
|
case PT_LOOS:
|
|
|
type = "Start of OS-specific";
|
|
|
break;
|
|
|
case PT_SUNWSTACK:
|
|
|
type = "Stack segment";
|
|
|
break;
|
|
|
case PT_LOPROC:
|
|
|
type = "Start of processor-specific";
|
|
|
break;
|
|
|
case PT_HIPROC:
|
|
|
type = "End of processor-specific";
|
|
|
break;
|
|
|
default:
|
|
|
type = "Unknow Section Type";
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return type;
|
|
|
}
|
|
|
|
|
|
|
|
|
qint64 ElfFile::getSegmentOffset(int index)
|
|
|
{
|
|
|
qint64 Offset = -1;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->Segments.count())
|
|
|
{
|
|
|
Offset = (qint64)this->Segments.at(index)->p_offset;
|
|
|
}
|
|
|
}
|
|
|
return Offset;
|
|
|
}
|
|
|
|
|
|
|
|
|
qint64 ElfFile::getSegmentVaddr(int index)
|
|
|
{
|
|
|
int64_t Vaddr = 0;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->Segments.count())
|
|
|
{
|
|
|
Vaddr = (int64_t)this->Segments.at(index)->p_vaddr;
|
|
|
}
|
|
|
}
|
|
|
return Vaddr;
|
|
|
}
|
|
|
|
|
|
|
|
|
qint64 ElfFile::getSegmentPaddr(int index)
|
|
|
{
|
|
|
int64_t Paddr=0;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->Segments.count())
|
|
|
{
|
|
|
Paddr = (int64_t)this->Segments.at(index)->p_paddr;
|
|
|
}
|
|
|
}
|
|
|
return Paddr;
|
|
|
}
|
|
|
|
|
|
qint64 ElfFile::getSectionPaddr(int index)
|
|
|
{
|
|
|
int64_t Paddr=0;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->sections.count())
|
|
|
{
|
|
|
Paddr = (int64_t)this->sections.at(index)->section_header->sh_addr;
|
|
|
}
|
|
|
}
|
|
|
return Paddr;
|
|
|
}
|
|
|
|
|
|
|
|
|
qint64 ElfFile::getSegmentFilesz(int index)
|
|
|
{
|
|
|
int64_t FileSz=0;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->Segments.count())
|
|
|
{
|
|
|
FileSz = (int64_t)this->Segments.at(index)->p_filesz;
|
|
|
}
|
|
|
}
|
|
|
return FileSz;
|
|
|
}
|
|
|
|
|
|
qint64 ElfFile::getSectionDatasz(int index)
|
|
|
{
|
|
|
int64_t DataSz=0;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->sections.count())
|
|
|
{
|
|
|
if(this->sections.at(index)->section_header->sh_type==SHT_NOBITS)
|
|
|
{
|
|
|
DataSz=0;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
DataSz = (int64_t)this->sections.at(index)->data->d_size;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return DataSz;
|
|
|
}
|
|
|
|
|
|
bool ElfFile::getSectionData(int index, char **buffer)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->sections.count())
|
|
|
{
|
|
|
*buffer = (char *)malloc(this->sections.at(index)->data->d_size);
|
|
|
memcpy(*buffer,this->sections.at(index)->data->d_buf,this->sections.at(index)->data->d_size);
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
|
|
|
qint64 ElfFile::getSegmentMemsz(int index)
|
|
|
{
|
|
|
int64_t MemSz=0;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->Segments.count())
|
|
|
{
|
|
|
MemSz = (int64_t)this->Segments.at(index)->p_memsz;
|
|
|
}
|
|
|
}
|
|
|
return MemSz;
|
|
|
}
|
|
|
|
|
|
qint64 ElfFile::getSectionMemsz(int index)
|
|
|
{
|
|
|
int64_t MemSz=0;
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->sections.count())
|
|
|
{
|
|
|
MemSz = (int64_t)this->sections.at(index)->section_header->sh_size;
|
|
|
}
|
|
|
}
|
|
|
return MemSz;
|
|
|
}
|
|
|
|
|
|
|
|
|
QString ElfFile::getSegmentFlags(int index)
|
|
|
{
|
|
|
QString flags("");
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->Segments.count())
|
|
|
{
|
|
|
if((this->Segments.at(index)->p_flags&PF_X) == PF_X)flags+="x";
|
|
|
if((this->Segments.at(index)->p_flags&PF_W) == PF_W)flags+="w";
|
|
|
if((this->Segments.at(index)->p_flags&PF_R) == PF_R)flags+="r";
|
|
|
if((this->Segments.at(index)->p_flags&PF_MASKOS) == PF_MASKOS)flags+=" OS-specific";
|
|
|
if((this->Segments.at(index)->p_flags&PF_MASKPROC) == PF_MASKPROC)flags+=" Processor-specific";
|
|
|
}
|
|
|
}
|
|
|
return flags;
|
|
|
}
|
|
|
|
|
|
|
|
|
QString ElfFile::getSectionName(int index)
|
|
|
{
|
|
|
if((index<sections.count()) && (index>=0))
|
|
|
{
|
|
|
char* nameChr = elf_strptr(this->e , this->shstrndx , this->sections.at(index)->section_header->sh_name);
|
|
|
return QString(nameChr);
|
|
|
}
|
|
|
return "";
|
|
|
}
|
|
|
|
|
|
|
|
|
void ElfFile::updateSections()
|
|
|
{
|
|
|
for(int i=0;i<this->sections.count();i++)
|
|
|
{
|
|
|
delete this->sections.at(i);
|
|
|
}
|
|
|
this->sections.clear();
|
|
|
this->scn = elf_nextscn (this->e , NULL );
|
|
|
this->SectionCount = 0;
|
|
|
while( this->scn != NULL )
|
|
|
{
|
|
|
GElf_Shdr* shdr = (GElf_Shdr*)malloc(sizeof(GElf_Shdr));
|
|
|
gelf_getshdr ( this->scn , shdr );
|
|
|
Elf_Data* data = elf_getdata(this->scn, NULL);
|
|
|
this->sections.append(new Elf_Section(data,shdr));
|
|
|
this->SectionCount+=1;
|
|
|
this->scn = elf_nextscn(e , scn);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
void ElfFile::updateSegments()
|
|
|
{
|
|
|
elf_getphdrnum (this->e , &this->SegmentCount);
|
|
|
for(int i=0;i<this->Segments.count();i++)
|
|
|
{
|
|
|
free(this->Segments.at(i));
|
|
|
}
|
|
|
this->Segments.clear();
|
|
|
for(int i=0;i<(int)this->SegmentCount;i++)
|
|
|
{
|
|
|
GElf_Phdr* header=(GElf_Phdr*)malloc(sizeof(GElf_Phdr));
|
|
|
gelf_getphdr (this->e , i , header );
|
|
|
this->Segments.append(header);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void ElfFile::updateSymbols()
|
|
|
{
|
|
|
for(int i=0;i<symbols.count();i++)
|
|
|
{
|
|
|
delete this->symbols.at(i);
|
|
|
}
|
|
|
this->symbols.clear();
|
|
|
updateSections(); //Useless in most case but safer to do it
|
|
|
for(int i=0;i<(int)SectionCount;i++)
|
|
|
{
|
|
|
//First find Symbol table
|
|
|
if(this->getSectionName(i)==".symtab")
|
|
|
{
|
|
|
Elf_Section* sec = sections.at(i);
|
|
|
this->SymbolCount = sec->section_header->sh_size / sec->section_header->sh_entsize;
|
|
|
//Then list all symbols
|
|
|
for(int j=0;j<(int)this->SymbolCount;j++)
|
|
|
{
|
|
|
GElf_Sym* esym = (GElf_Sym*)malloc(sizeof(GElf_Sym));
|
|
|
gelf_getsym(sec->data, j, esym);
|
|
|
QString name = elf_strptr(this->e,sec->section_header->sh_link,esym->st_name);
|
|
|
Elf_Symbol* sym = new Elf_Symbol(name,esym);
|
|
|
symbols.append(sym);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString ElfFile::getSectionType(int index)
|
|
|
{
|
|
|
QString type("");
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->sections.count())
|
|
|
{
|
|
|
switch(this->sections.at(index)->section_header->sh_type)
|
|
|
{
|
|
|
case SHT_NULL : type = "Section header table entry unused"; break;
|
|
|
case SHT_PROGBITS : type = "Program data"; break;
|
|
|
case SHT_SYMTAB : type = "Symbol table"; break;
|
|
|
case SHT_STRTAB : type = "String table"; break;
|
|
|
case SHT_RELA : type = "Relocation entries with addends"; break;
|
|
|
case SHT_HASH : type = "Symbol hash table"; break;
|
|
|
case SHT_DYNAMIC : type = "Dynamic linking information"; break;
|
|
|
case SHT_NOTE : type = "Notes"; break;
|
|
|
case SHT_NOBITS :type = "Program space with no data (bss)"; break;
|
|
|
case SHT_REL :type = "Relocation entries, no addends"; break;
|
|
|
case SHT_SHLIB : type = "Reserved"; break;
|
|
|
case SHT_DYNSYM : type = "Dynamic linker symbol table"; break;
|
|
|
case SHT_INIT_ARRAY : type = "Array of constructors"; break;
|
|
|
case SHT_FINI_ARRAY : type = "Array of destructors"; break;
|
|
|
case SHT_PREINIT_ARRAY : type = "Array of pre-constructors"; break;
|
|
|
case SHT_GROUP : type = "Section group"; break;
|
|
|
case SHT_SYMTAB_SHNDX : type = "Extended section indeces"; break;
|
|
|
case SHT_NUM : type = "Number of defined types. "; break;
|
|
|
case SHT_LOOS : type = "Start OS-specific. "; break;
|
|
|
case SHT_LOSUNW : type = "Sun-specific low bound. "; break;
|
|
|
case SHT_SUNW_COMDAT : type = " "; break;
|
|
|
case SHT_SUNW_syminfo : type = " "; break;
|
|
|
case SHT_GNU_verdef : type = "Version definition section. "; break;
|
|
|
case SHT_GNU_verneed : type = "Version needs section. "; break;
|
|
|
case SHT_GNU_versym : type = "Version symbol table. "; break;
|
|
|
case SHT_LOPROC : type = "Start of processor-specific"; break;
|
|
|
case SHT_HIPROC : type = "End of processor-specific"; break;
|
|
|
case SHT_HIUSER : type = "End of application-specific"; break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return type;
|
|
|
}
|
|
|
|
|
|
int ElfFile::getSectionIndex(QString name)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
for(int i=0;i<sections.count();i++)
|
|
|
{
|
|
|
if(getSectionName(i)==name)
|
|
|
return i;
|
|
|
}
|
|
|
}
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
bool ElfFile::sectionIsNobits(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->sections.count())
|
|
|
{
|
|
|
return this->sections.at(index)->section_header->sh_type== SHT_NOBITS;
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QString ElfFile::getSymbolName(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->symbols.count())
|
|
|
{
|
|
|
return symbols.at(index)->name;
|
|
|
}
|
|
|
}
|
|
|
return "";
|
|
|
}
|
|
|
|
|
|
QString ElfFile::getSymbolType(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->symbols.count())
|
|
|
{
|
|
|
int type = GELF_ST_TYPE(symbols.at(index)->sym->st_info);
|
|
|
switch(type)
|
|
|
{
|
|
|
case STT_NOTYPE:
|
|
|
return "No Type";
|
|
|
break;
|
|
|
case STT_OBJECT:
|
|
|
return "Object";
|
|
|
break;
|
|
|
case STT_FUNC:
|
|
|
return "Function";
|
|
|
break;
|
|
|
case STT_SECTION:
|
|
|
return "Section";
|
|
|
break;
|
|
|
case STT_FILE:
|
|
|
return "File";
|
|
|
break;
|
|
|
case STT_COMMON:
|
|
|
return "Common data object";
|
|
|
break;
|
|
|
case STT_TLS:
|
|
|
return "Thread-local data object";
|
|
|
break;
|
|
|
case STT_NUM:
|
|
|
return "Number of defined types";
|
|
|
break;
|
|
|
case STT_LOOS:
|
|
|
return "Start of OS-specific";
|
|
|
break;
|
|
|
case STT_HIOS:
|
|
|
return "End of OS-specific";
|
|
|
break;
|
|
|
case STT_LOPROC:
|
|
|
return "Start of processor-specific";
|
|
|
break;
|
|
|
case STT_HIPROC:
|
|
|
return "End of processor-specific";
|
|
|
break;
|
|
|
default:
|
|
|
return "none";
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return "none";
|
|
|
}
|
|
|
|
|
|
quint64 ElfFile::getSymbolSize(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if((index < this->symbols.count()) && (index>=0))
|
|
|
{
|
|
|
return symbols.at(index)->sym->st_size;
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
QString ElfFile::getSymbolSectionName(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if((index < this->symbols.count()) && (index>=0))
|
|
|
{
|
|
|
return getSectionName(symbols.at(index)->sym->st_shndx-1);
|
|
|
}
|
|
|
}
|
|
|
return "none";
|
|
|
}
|
|
|
|
|
|
int ElfFile::getSymbolSectionIndex(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if((index < this->symbols.count()) && (index>=0))
|
|
|
{
|
|
|
return symbols.at(index)->sym->st_shndx;
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
quint64 ElfFile::getSymbolAddress(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if((index < this->symbols.count()) && (index>=0))
|
|
|
{
|
|
|
return symbols.at(index)->sym->st_value;
|
|
|
}
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
QString ElfFile::getSymbolLinkType(int index)
|
|
|
{
|
|
|
if(this->e!=NULL)
|
|
|
{
|
|
|
if(index < this->symbols.count())
|
|
|
{
|
|
|
int btype = GELF_ST_BIND(symbols.at(index)->sym->st_info);
|
|
|
switch(btype)
|
|
|
{
|
|
|
case STB_LOCAL:
|
|
|
return "Local";
|
|
|
break;
|
|
|
case STB_GLOBAL:
|
|
|
return "Global";
|
|
|
break;
|
|
|
case STB_WEAK:
|
|
|
return "Weak";
|
|
|
break;
|
|
|
case STB_NUM:
|
|
|
return "Number of defined types";
|
|
|
break;
|
|
|
case STB_LOOS:
|
|
|
return "Start of OS-specific";
|
|
|
break;
|
|
|
case STB_HIOS:
|
|
|
return "End of OS-specific";
|
|
|
break;
|
|
|
case STB_LOPROC:
|
|
|
return "Start of processor-specific";
|
|
|
break;
|
|
|
case STB_HIPROC:
|
|
|
return "End of processor-specific";
|
|
|
break;
|
|
|
default:
|
|
|
return "none";
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return "none";
|
|
|
}
|
|
|
|
|
|
bool ElfFile::isElf(const QString &File)
|
|
|
{
|
|
|
int file =0;
|
|
|
#ifdef _ELF_WINDOWS_
|
|
|
file = open(File.toStdString().c_str(),O_RDONLY|O_BINARY ,0);
|
|
|
#else
|
|
|
file = open(File.toStdString().c_str(),O_RDONLY ,0);
|
|
|
#endif
|
|
|
char Magic[4];
|
|
|
if(file!=-1)
|
|
|
{
|
|
|
size_t res = read(file,Magic,4);
|
|
|
close(file);
|
|
|
if((res==4) && (Magic[0]==0x7f) && (Magic[1]==0x45) && (Magic[2]==0x4c) && (Magic[3]==0x46))
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
bool ElfFile::toSrec(const QString &File)
|
|
|
{
|
|
|
return srecFile::toSrec(this->getFragments(),File);
|
|
|
}
|
|
|
|
|
|
bool ElfFile::toBinary(const QString &File)
|
|
|
{
|
|
|
return binaryFile::toBinary(getFragments(),File);
|
|
|
}
|
|
|
|