#include <zipr_all.h>

namespace zipr
{
#include <pinner/pinner_arm32.hpp>
}
#include <memory>

using namespace std;
using namespace IRDB_SDK;
using namespace zipr;

ZiprPinnerARM32_t::ZiprPinnerARM32_t(Zipr_SDK::Zipr_t* p_parent) :
	m_parent(dynamic_cast<zipr::ZiprImpl_t*>(p_parent)),     // upcast to ZiprImpl
	m_firp(p_parent->getFileIR()),
	memory_space(*m_parent->getMemorySpace()),
	m_dollop_mgr(*p_parent->getDollopManager()),
        placement_queue(*p_parent->getPlacementQueue())

{
}

void  ZiprPinnerARM32_t::doPinning()
{


	// deal with unpinned IBTs by putting them in the placement queue.
	for(auto &insn : m_firp->getInstructions())
	{
                if(insn->getIndirectBranchTargetAddress()==nullptr)
                        continue;

                if(insn->getIndirectBranchTargetAddress()->getVirtualOffset()==0)
                {
                        // Unpinned IBT. Create dollop and add it to placement
                        // queue straight away--there are no pinning considerations.
                        auto newDoll=m_dollop_mgr.addNewDollops(insn);
                        placement_queue.insert({newDoll, 0});
                        continue;
                }

		auto ibta_addr=(RangeAddress_t)insn-> getIndirectBranchTargetAddress()-> getVirtualOffset();

		// put unconditional branch with 24-bit offset in memory
		// 1110 1010  0000 0000  0000 0000  0000 0000 
                uint8_t bytes[]={'\x00','\x00','\x00',uint8_t('\xea')};
		for(auto i=0U;i<sizeof(bytes);i++)
		{
			const auto ibta_byte_addr = ibta_addr+i;
			if(memory_space.find(ibta_byte_addr) != memory_space.end() )
			{
				cout << "Byte is marked as both code and data at: " << hex << ibta_byte_addr << endl;
				exit(10);
			}
			memory_space[ibta_byte_addr]=bytes[i];
			memory_space.splitFreeRange(ibta_byte_addr);
		}
		// insert a patch to patch the branch later.
		const auto patch=Patch_t(ibta_addr, UnresolvedType_t::UncondJump_rel26);
		const auto uu=UnresolvedUnpinned_t(insn);
		m_parent->AddPatch(uu,patch);
        }
}