Skip to content
Snippets Groups Projects
Commit 3e3fe762 authored by Jason Hiser's avatar Jason Hiser :tractor:
Browse files

arm32 support

parent 7dd13a74
No related branches found
No related tags found
No related merge requests found
#ifndef ARCHARM32_HPP
#define ARCHARM32_HPP
class ZiprArchitectureHelperARM32_t : public ZiprArchitectureHelperBase_t
{
public:
ZiprArchitectureHelperARM32_t(Zipr_SDK::Zipr_t* p_zipr_obj) : ZiprArchitectureHelperBase_t(p_zipr_obj)
{
}
virtual IRDB_SDK::Instruction_t* createNewJumpInstruction(IRDB_SDK::FileIR_t *p_firp, IRDB_SDK::Instruction_t* p_existing) override
{
// An arm32 brand in binary is: cond 1 0 1 L signed_immed_24
//
// where cond is the 4-bit condition field. for an uncond branch, we want cond=0b1110
// and L is whether the link register is set.
//
// so, bytes = 0b11101010 0b00000000 0b00000000 0b00000000
//
const auto bits =string("\x00\x00\x00\x0ea",4);
auto ret=IRDB_SDK::addNewDataBits(p_firp, p_existing, bits);
const auto d=IRDB_SDK::DecodedInstruction_t::factory(ret);
assert(d->valid());
return ret;
}
virtual IRDB_SDK::Instruction_t* createNewHaltInstruction(IRDB_SDK::FileIR_t *p_firp, IRDB_SDK::Instruction_t* p_existing) override
{
// for arm32, we are using a mov pc, #0 as a halt insn.
// 0xe3a0f000
const auto bits =string("\x00\xf0\xa0\xe3",4);
auto ret=IRDB_SDK::addNewDataBits(p_firp, p_existing, bits);
const auto d=IRDB_SDK::DecodedInstruction_t::factory(ret);
assert(d->valid());
return ret;
}
};
#endif
/***************************************************************************
* Copyright (c) 2014 Zephyr Software LLC. All rights reserved.
*
* This software is furnished under a license and/or other restrictive
* terms and may be used and copied only in accordance with such terms
* and the inclusion of the above copyright notice. This software or
* any other copies thereof may not be provided or otherwise made
* available to any other person without the express written consent
* of an authorized representative of Zephyr Software LCC. Title to,
* ownership of, and all rights in the software is retained by
* Zephyr Software LCC.
*
* Zephyr Software LLC. Proprietary Information
*
* Unless otherwise specified, the information contained in this
* directory, following this legend, and/or referenced herein is
* Zephyr Software LLC. (Zephyr) Proprietary Information.
*
* CONTACT
*
* For technical assistance, contact Zephyr Software LCC. at:
*
*
* Zephyr Software, LLC
* 2040 Tremont Rd
* Charlottesville, VA 22911
*
* E-mail: jwd@zephyr-software.com
**************************************************************************/
#ifndef PATCHER_ARM32
#define PATCHER_ARM32
class ZiprPatcherARM32_t : public ZiprPatcherBase_t
{
// data
zipr::ZiprImpl_t* m_parent;
IRDB_SDK::FileIR_t* m_firp;
Zipr_SDK::MemorySpace_t &memory_space;
std::map<RangeAddress_t, RangeAddress_t> redirect_map;
public:
ZiprPatcherARM32_t(Zipr_SDK::Zipr_t* p_parent);
void ApplyNopToPatch(RangeAddress_t addr) override;
void ApplyPatch(RangeAddress_t from_addr, RangeAddress_t to_addr) override;
void PatchJump(RangeAddress_t at_addr, RangeAddress_t to_addr) override;
void PatchCall(RangeAddress_t at_addr, RangeAddress_t to_addr) override;
void CallToNop(RangeAddress_t at_addr) override;
};
#endif
......@@ -30,8 +30,8 @@
#ifndef PATCHER_ARM
#define PATCHER_ARM
#ifndef PATCHER_ARM64
#define PATCHER_ARM64
class ZiprPatcherARM64_t : public ZiprPatcherBase_t
{
......
......@@ -34,7 +34,10 @@
class ZiprPatcherBase_t
{
protected:
ZiprPatcherBase_t(){}
public:
virtual ~ZiprPatcherBase_t() { }
static unique_ptr<ZiprPatcherBase_t> factory(Zipr_SDK::Zipr_t* p_parent);
virtual void ApplyNopToPatch(RangeAddress_t addr)=0;
virtual void ApplyPatch(RangeAddress_t from_addr, RangeAddress_t to_addr)=0;
......
#ifndef ZIPR_PINNER_ARM32
#define ZIPR_PINNER_ARM32
class ZiprPinnerARM32_t : public ZiprPinnerBase_t
{
public:
ZiprPinnerARM32_t(Zipr_SDK::Zipr_t* p_parent);
virtual void doPinning() override;
private:
zipr::ZiprImpl_t* m_parent;
IRDB_SDK::FileIR_t* m_firp;
Zipr_SDK::MemorySpace_t &memory_space;
Zipr_SDK::DollopManager_t &m_dollop_mgr;
Zipr_SDK::PlacementQueue_t &placement_queue;
};
#endif
......@@ -3,9 +3,12 @@
class ZiprPinnerBase_t
{
protected:
ZiprPinnerBase_t() { }
public:
virtual void doPinning()=0;
static unique_ptr<ZiprPinnerBase_t> factory(Zipr_SDK::Zipr_t* parent);
virtual ~ZiprPinnerBase_t() { }
};
......
#ifndef SIZERARM32_HPP
#define SIZERARM32_HPP
class ZiprSizerARM32_t : public ZiprSizerBase_t
{
private:
RangeAddress_t TBZPlopDollopEntryWithTarget (Zipr_SDK::DollopEntry_t *entry, RangeAddress_t override_place, RangeAddress_t override_target) const;
RangeAddress_t DefaultPlopDollopEntryWithTarget(Zipr_SDK::DollopEntry_t *entry, RangeAddress_t override_place, RangeAddress_t override_target) const;
public:
ZiprSizerARM32_t(Zipr_SDK::Zipr_t* p_zipr_obj);
size_t DetermineInsnSize(IRDB_SDK::Instruction_t*, bool account_for_jump = true) const override;
virtual RangeAddress_t PlopDollopEntryWithTarget(Zipr_SDK::DollopEntry_t *entry, RangeAddress_t override_place, RangeAddress_t override_target) const override;
};
#endif
......@@ -16,6 +16,7 @@ class ZiprSizerBase_t
ZiprMemorySpace_t &memory_space;
ZiprImpl_t &m_zipr_obj;
public:
virtual ~ZiprSizerBase_t() {}
// methods
/** Calculate entire size of a dollop and it's fallthroughs.
*
......
......@@ -27,14 +27,17 @@ files= '''
ehwrite.cpp
arch_base.cpp
pinner_arm64.cpp
pinner_arm32.cpp
pinner_base.cpp
pinner_x86.cpp
patcher_arm64.cpp
patcher_arm32.cpp
patcher_base.cpp
patcher_x86.cpp
sizer_base.cpp
sizer_x86.cpp
sizer_arm64.cpp
sizer_arm32.cpp
range.cpp
'''
......
......@@ -6,6 +6,7 @@ namespace zipr
{
#include <arch/arch_x86.hpp>
#include <arch/arch_arm64.hpp>
#include <arch/arch_arm32.hpp>
}
#include <memory>
......@@ -27,6 +28,7 @@ unique_ptr<ZiprArchitectureHelperBase_t> ZiprArchitectureHelperBase_t::factory(Z
auto ret= l_firp->getArchitecture()->getMachineType() == admtX86_64 ? (ZiprArchitectureHelperBase_t*)new ZiprArchitectureHelperX86_t (p_zipr_obj) :
l_firp->getArchitecture()->getMachineType() == admtI386 ? (ZiprArchitectureHelperBase_t*)new ZiprArchitectureHelperX86_t (p_zipr_obj) :
l_firp->getArchitecture()->getMachineType() == admtAarch64 ? (ZiprArchitectureHelperBase_t*)new ZiprArchitectureHelperARM64_t(p_zipr_obj) :
l_firp->getArchitecture()->getMachineType() == admtArm32 ? (ZiprArchitectureHelperBase_t*)new ZiprArchitectureHelperARM32_t(p_zipr_obj) :
throw domain_error("Cannot init architecture");
return unique_ptr<ZiprArchitectureHelperBase_t>(ret);
......
/***************************************************************************
* Copyright (c) 2014 Zephyr Software LLC. All rights reserved.
*
* This software is furnished under a license and/or other restrictive
* terms and may be used and copied only in accordance with such terms
* and the inclusion of the above copyright notice. This software or
* any other copies thereof may not be provided or otherwise made
* available to any other person without the express written consent
* of an authorized representative of Zephyr Software LCC. Title to,
* ownership of, and all rights in the software is retained by
* Zephyr Software LCC.
*
* Zephyr Software LLC. Proprietary Information
*
* Unless otherwise specified, the information contained in this
* directory, following this legend, and/or referenced herein is
* Zephyr Software LLC. (Zephyr) Proprietary Information.
*
* CONTACT
*
* For technical assistance, contact Zephyr Software LCC. at:
*
*
* Zephyr Software, LLC
* 2040 Tremont Rd
* Charlottesville, VA 22911
*
* E-mail: jwd@zephyr-software.com
**************************************************************************/
#include <zipr_all.h>
namespace zipr
{
#include "patcher/patcher_arm32.hpp"
}
#include <irdb-core>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <map>
#include <assert.h>
#include <sys/mman.h>
#include <ctype.h>
#include <iostream> // std::cout
#include <string> // std::string, std::to_string
#include <fstream>
#define ALLOF(a) begin(a),end(a)
using namespace IRDB_SDK;
using namespace std;
using namespace zipr;
ZiprPatcherARM32_t::ZiprPatcherARM32_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(*p_parent->getMemorySpace())
{
}
void ZiprPatcherARM32_t::ApplyNopToPatch(RangeAddress_t addr)
{ assert(0); }
void ZiprPatcherARM32_t::ApplyPatch(RangeAddress_t from_addr, RangeAddress_t to_addr)
{
const auto first_byte = (uint8_t)memory_space[from_addr+3];
const auto new_offset = (int32_t)((to_addr) - (from_addr+8)) >> 2;
// A Branch in binary is: op= cond4 1010 imm24=00 00000000 00000000 00000000
// it includes a 24-bit immediate, which is +/- 32mb, which should be a good enough "jump anywhere"
// for now.
const auto mask3 = (0b111);
const auto is_branch = ((first_byte >> 1) & mask3) == (0b101); // any type of branch.
if(is_branch)
{
// cout<<"Applying uncond branch patch from "<<hex<<from_addr<<" to "<<to_addr<<endl;
const auto non_imm_bits = 32U-24U; // 32 bits - imm24
// assert there's no overflow.
assert((int64_t)(new_offset << non_imm_bits) == ((int64_t)new_offset) << non_imm_bits);
// or in opcode for first byte. set remaining bytes.
const auto mask24 = ((1<<24)-1);
const auto trimmed_offset = new_offset & mask24;
memory_space[from_addr+0] = (trimmed_offset>> 0)&0xff;
memory_space[from_addr+1] = (trimmed_offset>> 8)&0xff;
memory_space[from_addr+2] = (trimmed_offset>>16)&0xff;
// no need to write 4th byte.
}
else
assert(0);
}
void ZiprPatcherARM32_t::PatchJump(RangeAddress_t at_addr, RangeAddress_t to_addr)
{
return this->ApplyPatch(at_addr,to_addr);
}
void ZiprPatcherARM32_t::PatchCall(RangeAddress_t at_addr, RangeAddress_t to_addr)
{
assert(0);
}
void ZiprPatcherARM32_t::CallToNop(RangeAddress_t at_addr)
{
assert(0);
}
......@@ -32,6 +32,7 @@
namespace zipr
{
#include "patcher/patcher_arm32.hpp"
#include "patcher/patcher_arm64.hpp"
#include "patcher/patcher_x86.hpp"
}
......@@ -60,6 +61,7 @@ unique_ptr<ZiprPatcherBase_t> ZiprPatcherBase_t::factory(Zipr_SDK::Zipr_t* p_par
auto ret= l_firp->getArchitecture()->getMachineType() == admtX86_64 ? (ZiprPatcherBase_t*)new ZiprPatcherX86_t (p_parent) :
l_firp->getArchitecture()->getMachineType() == admtI386 ? (ZiprPatcherBase_t*)new ZiprPatcherX86_t (p_parent) :
l_firp->getArchitecture()->getMachineType() == admtAarch64 ? (ZiprPatcherBase_t*)new ZiprPatcherARM64_t(p_parent) :
l_firp->getArchitecture()->getMachineType() == admtArm32 ? (ZiprPatcherBase_t*)new ZiprPatcherARM32_t(p_parent) :
throw domain_error("Cannot init architecture");
return unique_ptr<ZiprPatcherBase_t>(ret);
......
#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++)
{
assert(memory_space.find(ibta_addr+i) == memory_space.end() );
memory_space[ibta_addr+i]=bytes[i];
memory_space.splitFreeRange(ibta_addr+i);
}
// 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);
}
}
......@@ -3,6 +3,7 @@
namespace zipr
{
#include <pinner/pinner_x86.hpp>
#include <pinner/pinner_arm32.hpp>
#include <pinner/pinner_arm64.hpp>
}
#include <memory>
......@@ -16,6 +17,7 @@ unique_ptr<ZiprPinnerBase_t> ZiprPinnerBase_t::factory(Zipr_SDK::Zipr_t *p_paren
auto ret= p_parent->getFileIR()->getArchitecture()->getMachineType() == admtX86_64 ? (ZiprPinnerBase_t*)new ZiprPinnerX86_t (p_parent) :
p_parent->getFileIR()->getArchitecture()->getMachineType() == admtI386 ? (ZiprPinnerBase_t*)new ZiprPinnerX86_t (p_parent) :
p_parent->getFileIR()->getArchitecture()->getMachineType() == admtAarch64 ? (ZiprPinnerBase_t*)new ZiprPinnerARM64_t(p_parent) :
p_parent->getFileIR()->getArchitecture()->getMachineType() == admtArm32 ? (ZiprPinnerBase_t*)new ZiprPinnerARM32_t(p_parent) :
throw domain_error("Cannot init architecture");
return unique_ptr<ZiprPinnerBase_t>(ret);
......
#include <zipr_all.h>
namespace zipr
{
#include <sizer/sizer_arm32.hpp>
}
using namespace zipr ;
using namespace IRDB_SDK;
ZiprSizerARM32_t::ZiprSizerARM32_t(Zipr_SDK::Zipr_t* p_zipr_obj) : ZiprSizerBase_t(p_zipr_obj,4,4,4,4,4)
{
}
size_t ZiprSizerARM32_t::DetermineInsnSize(Instruction_t* insn, bool account_for_jump) const
{
// need 4 bytes for insn, plus 4 bytes for a jump
const auto size = 4u;
const auto jmp_size = account_for_jump ? 4 : 0;
return size + jmp_size;
}
RangeAddress_t ZiprSizerARM32_t::PlopDollopEntryWithTarget(
Zipr_SDK::DollopEntry_t *entry,
RangeAddress_t override_place,
RangeAddress_t override_target) const
{
const auto addr = (override_place == 0) ? entry->getPlace() : override_place;
const auto target_addr = (override_target == 0) ? entry->getTargetDollop()->getPlace() : override_target;
const auto insn = entry->getInstruction();
// plop instruction an d make it target the right address.
memory_space.PlopBytes(addr, insn->getDataBits().c_str(), 4);
m_zipr_obj.GetPatcher()->ApplyPatch(addr, target_addr);
return addr+4;
}
......@@ -6,6 +6,7 @@ namespace zipr
{
#include <sizer/sizer_x86.hpp>
#include <sizer/sizer_arm64.hpp>
#include <sizer/sizer_arm32.hpp>
}
#include <memory>
......@@ -20,6 +21,7 @@ unique_ptr<ZiprSizerBase_t> ZiprSizerBase_t::factory(Zipr_SDK::Zipr_t* p_zipr_ob
auto ret= l_firp->getArchitecture()->getMachineType() == admtX86_64 ? (ZiprSizerBase_t*)new ZiprSizerX86_t (p_zipr_obj) :
l_firp->getArchitecture()->getMachineType() == admtI386 ? (ZiprSizerBase_t*)new ZiprSizerX86_t (p_zipr_obj) :
l_firp->getArchitecture()->getMachineType() == admtAarch64 ? (ZiprSizerBase_t*)new ZiprSizerARM64_t(p_zipr_obj) :
l_firp->getArchitecture()->getMachineType() == admtArm32 ? (ZiprSizerBase_t*)new ZiprSizerARM32_t(p_zipr_obj) :
throw domain_error("Cannot init architecture");
return unique_ptr<ZiprSizerBase_t>(ret);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment