From 3e3fe7626e861f3e01ed4f56e35ef1a8c4ce5a3d Mon Sep 17 00:00:00 2001
From: Jason Hiser <jdhiser@gmail.com>
Date: Thu, 2 May 2019 17:29:24 -0400
Subject: [PATCH] arm32 support

---
 include/arch/arch_arm32.hpp       |  38 ++++++++++
 include/patcher/patcher_arm32.hpp |  57 +++++++++++++++
 include/patcher/patcher_arm64.hpp |   4 +-
 include/patcher/patcher_base.hpp  |   3 +
 include/pinner/pinner_arm32.hpp   |  22 ++++++
 include/pinner/pinner_base.hpp    |   3 +
 include/sizer/sizer_arm32.hpp     |  17 +++++
 include/sizer/sizer_base.hpp      |   1 +
 src/SConscript                    |   3 +
 src/arch_base.cpp                 |   2 +
 src/patcher_arm32.cpp             | 111 ++++++++++++++++++++++++++++++
 src/patcher_base.cpp              |   2 +
 src/pinner_arm32.cpp              |  58 ++++++++++++++++
 src/pinner_base.cpp               |   2 +
 src/sizer_arm32.cpp               |  40 +++++++++++
 src/sizer_base.cpp                |   2 +
 16 files changed, 363 insertions(+), 2 deletions(-)
 create mode 100644 include/arch/arch_arm32.hpp
 create mode 100644 include/patcher/patcher_arm32.hpp
 create mode 100644 include/pinner/pinner_arm32.hpp
 create mode 100644 include/sizer/sizer_arm32.hpp
 create mode 100644 src/patcher_arm32.cpp
 create mode 100644 src/pinner_arm32.cpp
 create mode 100644 src/sizer_arm32.cpp

diff --git a/include/arch/arch_arm32.hpp b/include/arch/arch_arm32.hpp
new file mode 100644
index 000000000..3b6c3f45e
--- /dev/null
+++ b/include/arch/arch_arm32.hpp
@@ -0,0 +1,38 @@
+#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
diff --git a/include/patcher/patcher_arm32.hpp b/include/patcher/patcher_arm32.hpp
new file mode 100644
index 000000000..2e455c788
--- /dev/null
+++ b/include/patcher/patcher_arm32.hpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * 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
diff --git a/include/patcher/patcher_arm64.hpp b/include/patcher/patcher_arm64.hpp
index 00127da04..96f38f92d 100644
--- a/include/patcher/patcher_arm64.hpp
+++ b/include/patcher/patcher_arm64.hpp
@@ -30,8 +30,8 @@
 
 
 
-#ifndef PATCHER_ARM
-#define PATCHER_ARM
+#ifndef PATCHER_ARM64
+#define PATCHER_ARM64
 
 class ZiprPatcherARM64_t : public ZiprPatcherBase_t
 {
diff --git a/include/patcher/patcher_base.hpp b/include/patcher/patcher_base.hpp
index 25e11af6d..1609b3dea 100644
--- a/include/patcher/patcher_base.hpp
+++ b/include/patcher/patcher_base.hpp
@@ -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;
diff --git a/include/pinner/pinner_arm32.hpp b/include/pinner/pinner_arm32.hpp
new file mode 100644
index 000000000..0a598d5c9
--- /dev/null
+++ b/include/pinner/pinner_arm32.hpp
@@ -0,0 +1,22 @@
+#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
diff --git a/include/pinner/pinner_base.hpp b/include/pinner/pinner_base.hpp
index e894ae4ee..81ca40b1b 100644
--- a/include/pinner/pinner_base.hpp
+++ b/include/pinner/pinner_base.hpp
@@ -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() { }
 };
 
 
diff --git a/include/sizer/sizer_arm32.hpp b/include/sizer/sizer_arm32.hpp
new file mode 100644
index 000000000..82950bf2e
--- /dev/null
+++ b/include/sizer/sizer_arm32.hpp
@@ -0,0 +1,17 @@
+#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
diff --git a/include/sizer/sizer_base.hpp b/include/sizer/sizer_base.hpp
index 2dbbe71de..93069e25a 100644
--- a/include/sizer/sizer_base.hpp
+++ b/include/sizer/sizer_base.hpp
@@ -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.
 		 *
diff --git a/src/SConscript b/src/SConscript
index 629332457..73bef2a6f 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -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
 	'''
 
diff --git a/src/arch_base.cpp b/src/arch_base.cpp
index 4bc17ecb3..5c724289e 100644
--- a/src/arch_base.cpp
+++ b/src/arch_base.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);
diff --git a/src/patcher_arm32.cpp b/src/patcher_arm32.cpp
new file mode 100644
index 000000000..bf27ee2f1
--- /dev/null
+++ b/src/patcher_arm32.cpp
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * 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);
+}
+
+
diff --git a/src/patcher_base.cpp b/src/patcher_base.cpp
index 769a01f9e..9a0f32f5e 100644
--- a/src/patcher_base.cpp
+++ b/src/patcher_base.cpp
@@ -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);
diff --git a/src/pinner_arm32.cpp b/src/pinner_arm32.cpp
new file mode 100644
index 000000000..806b0b584
--- /dev/null
+++ b/src/pinner_arm32.cpp
@@ -0,0 +1,58 @@
+#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);
+        }
+}
diff --git a/src/pinner_base.cpp b/src/pinner_base.cpp
index 534ffebd5..e14dd0215 100644
--- a/src/pinner_base.cpp
+++ b/src/pinner_base.cpp
@@ -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);
diff --git a/src/sizer_arm32.cpp b/src/sizer_arm32.cpp
new file mode 100644
index 000000000..40f57f930
--- /dev/null
+++ b/src/sizer_arm32.cpp
@@ -0,0 +1,40 @@
+#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;
+}
+
diff --git a/src/sizer_base.cpp b/src/sizer_base.cpp
index 1d5847c4c..792eba582 100644
--- a/src/sizer_base.cpp
+++ b/src/sizer_base.cpp
@@ -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);
-- 
GitLab