Skip to content
Snippets Groups Projects
mg.cpp 71.7 KiB
Newer Older
#include "mg.hpp"


#include <assert.h>
#include <stdexcept>
#include <unistd.h>
#include <memory>
#include <inttypes.h>
#include <algorithm>
#include <elf.h>
#include <cctype>
#include <iomanip>
#include <cstdlib>
#include <random>


using namespace std;
using namespace IRDB_SDK;
using namespace EXEIO;

#define ALLOF(s) begin(s), end(s)

// use this to determine whether a scoop has a given name.
static struct ScoopFinder : binary_function<DataScoop_t*,string,bool>
{
	// declare a simple scoop finder function that finds scoops by name
	bool operator()(const DataScoop_t* scoop, const string word)  const
	{
		return (scoop->getName() == word);
	};
} finder;

template<class S, class T> inline
static bool contains(const S &container, const T& value)
{
	return find(container.begin(), container.end(), value) != container.end();
}



static bool arg_has_memory(const DecodedOperand_t &arg)
{
	/* if it's relative memory, watch out! */
	if(arg.isMemory())
		return true;

	return false;
}

static bool arg_has_relative(const DecodedOperand_t &arg)
{
	/* if it's relative memory, watch out! */
	if(arg.isMemory() && arg.isPcrel())
		return true;
	return false;
}

static DecodedOperandVector_t::iterator find_memory_operand(DecodedOperandVector_t &operands)
{
	// const auto operands=disasm.getOperands();
	auto the_arg=operands.end();
	if(operands.size()>0 && arg_has_memory(*operands[0]))
		the_arg=next(operands.begin(),0);
	if(operands.size()>1 && arg_has_memory(*operands[1]))
		the_arg=next(operands.begin(),1);
	if(operands.size()>2 && arg_has_memory(*operands[2]))
		the_arg=next(operands.begin(),2);
	if(operands.size()>3 && arg_has_memory(*operands[3]))
		the_arg=next(operands.begin(),3);
	return the_arg;
}


template< typename T >
static std::string to_hex_string( T i )
{
	std::stringstream stream;
	stream << "0x"
		<< std::hex << i;
	return stream.str();
}


Jason Hiser's avatar
Jason Hiser committed
template <class T_Sym, class  T_Rela, class T_Rel, class T_Dyn, class T_Extractor>
bool MoveGlobals_t<T_Sym,T_Rela,T_Rel,T_Dyn,T_Extractor>::is_elftable(DataScoop_t* ret)
{ 
	return find(ALLOF(elftable_names), ret->getName()) != elftable_names.end() ;  
}; 

template <class T_Sym, class  T_Rela, class T_Rel, class T_Dyn, class T_Extractor>
bool MoveGlobals_t<T_Sym,T_Rela,T_Rel,T_Dyn,T_Extractor>::is_noptr_table(DataScoop_t* ret)
{ 
	return find(ALLOF(elftable_nocodeptr_names), ret->getName()) != elftable_nocodeptr_names.end() ;  
}; 

template <class T_Sym, class  T_Rela, class T_Rel, class T_Dyn, class T_Extractor>
MoveGlobals_t<T_Sym,T_Rela,T_Rel,T_Dyn,T_Extractor>::MoveGlobals_t(
	VariantID_t *p_variantID, 
	FileIR_t *p_variantIR, 
	const string &p_dont_move, 
	const string &p_move_only, 
	const int p_max_mov,
        const bool p_random,
	const bool p_aggressive,
	const bool p_use_stars)
	:
	exe_reader(NULL),
	tied_unpinned(0),
	tied_pinned(0),
	tied_nochange(0),
	ties_for_folded_constants(0),
	dont_move(p_dont_move),
	move_only(p_move_only),
	max_moveables(p_max_mov),
        random(p_random),
	aggressive(p_aggressive),
	m_use_stars(p_use_stars),
	m_verbose(getenv("MG_VERBOSE") != nullptr) 
{ 
}

template <class T_Sym, class  T_Rela, class T_Rel, class T_Dyn, class T_Extractor>
int MoveGlobals_t<T_Sym,T_Rela,T_Rel,T_Dyn,T_Extractor>::execute(pqxxDB_t &pqxx_interface)
{

	// read the executeable file

	// load the executable.
Jason Hiser's avatar
Jason Hiser committed
	exe_reader = new EXEIO::exeio;
	assert(exe_reader);
	exe_reader->load((char*)"a.ncexe");

	if(m_use_stars)
	{
		auto deep_analysis=DeepAnalysis_t::factory(getFileIR(), aeSTARS,  {"SetDeepLoopAnalyses=true", "SetConstantPropagation=true"});
		deep_global_static_ranges = deep_analysis -> getStaticGlobalRanges();
		sentinels                 = deep_analysis -> getRangeSentinels();
		cout<<dec;
		cout<<"#ATTRIBUTE "<<deep_global_static_ranges->size() <<" num_global_static_range_annotations" <<endl;
		cout<<"#ATTRIBUTE "<<sentinels->size()                 <<" num_sentinel_annotations"            <<endl;
	}




Jason Hiser's avatar
Jason Hiser committed
	ParseSyms(exe_reader);
	SetupScoopMap();
	FilterScoops();
	TieScoops();
	FindInstructionReferences();	// may record some scoops are tied together
	FindDataReferences();
	FilterAndCoalesceTiedScoops();
	UpdateScoopLocations();
	PrintStats();

	return 0;
}

// go through the .symtab and .dynsym bits of the table and make scoops for each symbol.
template <class T_Sym, class  T_Rela, class T_Rel, class T_Dyn, class T_Extractor>
void MoveGlobals_t<T_Sym,T_Rela,T_Rel,T_Dyn,T_Extractor>::SetupScoopMap()
{
	for(auto &s : getFileIR()->getDataScoops())
	{
		if(s->getStart()->getVirtualOffset() == 0)
			continue;
		if(s->getName() == ".tdata")
			continue;
		if(s->getName() == ".tbss")
			continue;
		RangePair_t p(s->getStart()->getVirtualOffset(), s->getEnd()->getVirtualOffset());
		scoop_map[p]=s;
	}
}

template <class T_Sym, class  T_Rela, class T_Rel, class T_Dyn, class T_Extractor>
DataScoop_t* MoveGlobals_t<T_Sym,T_Rela,T_Rel,T_Dyn,T_Extractor>::findScoopByAddress(const IRDB_SDK::VirtualOffset_t a) const
{
	RangePair_t p(a,a);
	auto smit=scoop_map.find(p);
	if(smit==scoop_map.end())
		return NULL;
	return smit->second;
}

template <class T_Sym, class  T_Rela, class T_Rel, class T_Dyn, class T_Extractor>
bool MoveGlobals_t<T_Sym, T_Rela, T_Rel, T_Dyn, T_Extractor>::AreScoopsAdjacent(const DataScoop_t *a, const DataScoop_t *b) const
{
	bool adjacent = true;
	const IRDB_SDK::VirtualOffset_t aStart = a->getStart()->getVirtualOffset();
	const IRDB_SDK::VirtualOffset_t aEnd = a->getEnd()->getVirtualOffset();
	const IRDB_SDK::VirtualOffset_t bStart = b->getStart()->getVirtualOffset();
	const IRDB_SDK::VirtualOffset_t bEnd = b->getEnd()->getVirtualOffset();
	IRDB_SDK::VirtualOffset_t FirstEnd, SecondStart;
	if (aStart > bStart)
	{
Loading
Loading full blame...