summaryrefslogtreecommitdiff
path: root/packaging/0004-Change-relocations-in-ngen-ed-code-with-PC-relative-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/0004-Change-relocations-in-ngen-ed-code-with-PC-relative-.patch')
-rw-r--r--packaging/0004-Change-relocations-in-ngen-ed-code-with-PC-relative-.patch467
1 files changed, 467 insertions, 0 deletions
diff --git a/packaging/0004-Change-relocations-in-ngen-ed-code-with-PC-relative-.patch b/packaging/0004-Change-relocations-in-ngen-ed-code-with-PC-relative-.patch
new file mode 100644
index 0000000..09d836a
--- /dev/null
+++ b/packaging/0004-Change-relocations-in-ngen-ed-code-with-PC-relative-.patch
@@ -0,0 +1,467 @@
+From 381ca0894a01e9bd83ab39d6163c947531051e17 Mon Sep 17 00:00:00 2001
+From: Ruben Ayrapetyan <r.ayrapetyan@samsung.com>
+Date: Wed, 3 May 2017 17:01:07 +0300
+Subject: [PATCH 04/32] Change relocations in ngen-ed code with PC-relative
+ constants for Linux ARM32.
+
+---
+ src/inc/corinfo.h | 15 +++++++++++++++
+ src/inc/corjit.h | 6 ++++++
+ src/inc/zapper.h | 2 ++
+ src/jit/codegen.h | 4 ++++
+ src/jit/codegenarm.cpp | 12 ++++--------
+ src/jit/codegencommon.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ src/jit/codegenlegacy.cpp | 9 +++------
+ src/jit/emit.cpp | 23 +++++++++++++++++++++++
+ src/jit/emit.h | 5 +++++
+ src/jit/emitarm.cpp | 4 ++--
+ src/jit/instr.cpp | 3 +--
+ src/jit/jitee.h | 12 ++++++++++++
+ src/zap/zapinfo.cpp | 19 +++++++++++++++++++
+ src/zap/zapper.cpp | 18 ++++++++++++++----
+ src/zap/zaprelocs.cpp | 17 +++++++++++++++++
+ 15 files changed, 174 insertions(+), 22 deletions(-)
+ mode change 100755 => 100644 src/jit/codegen.h
+
+diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h
+index 97f3958..2495de2 100644
+--- a/src/inc/corinfo.h
++++ b/src/inc/corinfo.h
+@@ -3074,4 +3074,19 @@ public:
+ #define IMAGE_REL_BASED_REL32 0x10
+ #define IMAGE_REL_BASED_THUMB_BRANCH24 0x13
+
++// The identifier for ARM32-specific PC-relative address
++// computation corresponds to the following instruction
++// sequence:
++// l0: movw rX, #imm_lo // 4 byte
++// l4: movt rX, #imm_hi // 4 byte
++// l8: add rX, pc <- after this instruction rX = relocTarget
++//
++// Program counter at l8 is address of l8 + 4
++// Address of relocated movw/movt is l0
++// So, imm should be calculated as the following:
++// imm = relocTarget - (l8 + 4) = relocTarget - (l0 + 8 + 4) = relocTarget - (l_0 + 12)
++// So, the value of offset correction is 12
++//
++#define IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL 0x14
++
+ #endif // _COR_INFO_H_
+diff --git a/src/inc/corjit.h b/src/inc/corjit.h
+index e6d067c..e6e8257 100644
+--- a/src/inc/corjit.h
++++ b/src/inc/corjit.h
+@@ -148,6 +148,12 @@ public:
+ CORJIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code
+ CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible
+ CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code
++
++#if defined(_TARGET_ARM_)
++ CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records
++#else // !defined(_TARGET_ARM_)
++ CORJIT_FLAG_UNUSED11 = 41
++#endif // !defined(_TARGET_ARM_)
+ };
+
+ CORJIT_FLAGS()
+diff --git a/src/inc/zapper.h b/src/inc/zapper.h
+index a55ddbe..b846274 100644
+--- a/src/inc/zapper.h
++++ b/src/inc/zapper.h
+@@ -448,6 +448,8 @@ class ZapperOptions
+
+ bool m_fNoMetaData; // Do not copy metadata and IL to native image
+
++ void SetCompilerFlags(void);
++
+ ZapperOptions();
+ ~ZapperOptions();
+ };
+diff --git a/src/jit/codegen.h b/src/jit/codegen.h
+old mode 100755
+new mode 100644
+index e50e640..471434c
+--- a/src/jit/codegen.h
++++ b/src/jit/codegen.h
+@@ -361,6 +361,10 @@ protected:
+ /* IN OUT */ bool* pUnwindStarted,
+ bool jmpEpilog);
+
++ void genMov32RelocatableDisplacement(BasicBlock* block, regNumber reg);
++ void genMov32RelocatableDataLabel(unsigned value, regNumber reg);
++ void genMov32RelocatableImmediate(emitAttr size, unsigned value, regNumber reg);
++
+ bool genUsedPopToReturn; // True if we use the pop into PC to return,
+ // False if we didn't and must branch to LR to return.
+
+diff --git a/src/jit/codegenarm.cpp b/src/jit/codegenarm.cpp
+index 40371e3..8f98343 100644
+--- a/src/jit/codegenarm.cpp
++++ b/src/jit/codegenarm.cpp
+@@ -44,8 +44,7 @@ BasicBlock* CodeGen::genCallFinally(BasicBlock* block)
+
+ // Load the address where the finally funclet should return into LR.
+ // The funclet prolog/epilog will do "push {lr}" / "pop {pc}" to do the return.
+- getEmitter()->emitIns_R_L(INS_movw, EA_4BYTE_DSP_RELOC, bbFinallyRet, REG_LR);
+- getEmitter()->emitIns_R_L(INS_movt, EA_4BYTE_DSP_RELOC, bbFinallyRet, REG_LR);
++ genMov32RelocatableDisplacement(bbFinallyRet, REG_LR);
+
+ // Jump to the finally BB
+ inst_JMP(EJ_jmp, block->bbJumpDest);
+@@ -63,8 +62,7 @@ BasicBlock* CodeGen::genCallFinally(BasicBlock* block)
+ // genEHCatchRet:
+ void CodeGen::genEHCatchRet(BasicBlock* block)
+ {
+- getEmitter()->emitIns_R_L(INS_movw, EA_4BYTE_DSP_RELOC, block->bbJumpDest, REG_INTRET);
+- getEmitter()->emitIns_R_L(INS_movt, EA_4BYTE_DSP_RELOC, block->bbJumpDest, REG_INTRET);
++ genMov32RelocatableDisplacement(block->bbJumpDest, REG_INTRET);
+ }
+
+ //------------------------------------------------------------------------
+@@ -82,8 +80,7 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm,
+
+ if (EA_IS_RELOC(size))
+ {
+- getEmitter()->emitIns_R_I(INS_movw, size, reg, imm);
+- getEmitter()->emitIns_R_I(INS_movt, size, reg, imm);
++ genMov32RelocatableImmediate(size, imm, reg);
+ }
+ else if (imm == 0)
+ {
+@@ -681,8 +678,7 @@ void CodeGen::genJumpTable(GenTree* treeNode)
+
+ getEmitter()->emitDataGenEnd();
+
+- getEmitter()->emitIns_R_D(INS_movw, EA_HANDLE_CNS_RELOC, jmpTabBase, treeNode->gtRegNum);
+- getEmitter()->emitIns_R_D(INS_movt, EA_HANDLE_CNS_RELOC, jmpTabBase, treeNode->gtRegNum);
++ genMov32RelocatableDataLabel(jmpTabBase, treeNode->gtRegNum);
+
+ genProduceReg(treeNode);
+ }
+diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
+index 50f43fa..9613e4d 100644
+--- a/src/jit/codegencommon.cpp
++++ b/src/jit/codegencommon.cpp
+@@ -6380,6 +6380,53 @@ void CodeGen::genFreeLclFrame(unsigned frameSize, /* IN OUT */ bool* pUnwindStar
+
+ /*-----------------------------------------------------------------------------
+ *
++ * Move of relocatable displacement value to register
++ */
++void CodeGen::genMov32RelocatableDisplacement(BasicBlock* block, regNumber reg)
++{
++ getEmitter()->emitIns_R_L(INS_movw, EA_4BYTE_DSP_RELOC, block, reg);
++ getEmitter()->emitIns_R_L(INS_movt, EA_4BYTE_DSP_RELOC, block, reg);
++
++ if (compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
++ {
++ getEmitter()->emitIns_R_R_R(INS_add, EA_4BYTE_DSP_RELOC, reg, reg, REG_PC);
++ }
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * Move of relocatable data-label to register
++ */
++void CodeGen::genMov32RelocatableDataLabel(unsigned value, regNumber reg)
++{
++ getEmitter()->emitIns_R_D(INS_movw, EA_HANDLE_CNS_RELOC, value, reg);
++ getEmitter()->emitIns_R_D(INS_movt, EA_HANDLE_CNS_RELOC, value, reg);
++
++ if (compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
++ {
++ getEmitter()->emitIns_R_R_R(INS_add, EA_HANDLE_CNS_RELOC, reg, reg, REG_PC);
++ }
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * Move of relocatable immediate to register
++ */
++void CodeGen::genMov32RelocatableImmediate(emitAttr size, unsigned value, regNumber reg)
++{
++ _ASSERTE(EA_IS_RELOC(size));
++
++ getEmitter()->emitIns_R_I(INS_movw, size, reg, value);
++ getEmitter()->emitIns_R_I(INS_movt, size, reg, value);
++
++ if (compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
++ {
++ getEmitter()->emitIns_R_R_R(INS_add, size, reg, reg, REG_PC);
++ }
++}
++
++/*-----------------------------------------------------------------------------
++ *
+ * Returns register mask to push/pop to allocate a small stack frame,
+ * instead of using "sub sp" / "add sp". Returns RBM_NONE if either frame size
+ * is zero, or if we should use "sub sp" / "add sp" instead of push/pop.
+diff --git a/src/jit/codegenlegacy.cpp b/src/jit/codegenlegacy.cpp
+index b8a239a..178be54 100644
+--- a/src/jit/codegenlegacy.cpp
++++ b/src/jit/codegenlegacy.cpp
+@@ -13095,8 +13095,7 @@ void CodeGen::genCodeForBBlist()
+ // Load the address where the finally funclet should return into LR.
+ // The funclet prolog/epilog will do "push {lr}" / "pop {pc}" to do
+ // the return.
+- getEmitter()->emitIns_R_L(INS_movw, EA_4BYTE_DSP_RELOC, bbFinallyRet, REG_LR);
+- getEmitter()->emitIns_R_L(INS_movt, EA_4BYTE_DSP_RELOC, bbFinallyRet, REG_LR);
++ genMov32RelocatableDisplacement(bbFinallyRet, REG_LR);
+ regTracker.rsTrackRegTrash(REG_LR);
+ #endif // 0
+
+@@ -13123,8 +13122,7 @@ void CodeGen::genCodeForBBlist()
+
+ case BBJ_EHCATCHRET:
+ // set r0 to the address the VM should return to after the catch
+- getEmitter()->emitIns_R_L(INS_movw, EA_4BYTE_DSP_RELOC, block->bbJumpDest, REG_R0);
+- getEmitter()->emitIns_R_L(INS_movt, EA_4BYTE_DSP_RELOC, block->bbJumpDest, REG_R0);
++ genMov32RelocatableDisplacement(block->bbJumpDest, REG_R0);
+ regTracker.rsTrackRegTrash(REG_R0);
+
+ __fallthrough;
+@@ -15509,8 +15507,7 @@ void CodeGen::genTableSwitch(regNumber reg, unsigned jumpCnt, BasicBlock** jumpT
+ // Pick any register except the index register.
+ //
+ regNumber regTabBase = regSet.rsGrabReg(RBM_ALLINT & ~genRegMask(reg));
+- getEmitter()->emitIns_R_D(INS_movw, EA_HANDLE_CNS_RELOC, jmpTabBase, regTabBase);
+- getEmitter()->emitIns_R_D(INS_movt, EA_HANDLE_CNS_RELOC, jmpTabBase, regTabBase);
++ genMov32RelocatableDataLabel(jmpTabBase, regTabBase);
+ regTracker.rsTrackRegTrash(regTabBase);
+
+ // LDR PC, [regTableBase + reg * 4] (encoded as LDR PC, [regTableBase, reg, LSL 2]
+diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp
+index d2aa29f..29f79f0 100644
+--- a/src/jit/emit.cpp
++++ b/src/jit/emit.cpp
+@@ -7103,6 +7103,29 @@ void emitter::emitRecordRelocation(void* location, /* IN */
+ #endif // defined(LATE_DISASM)
+ }
+
++#ifdef _TARGET_ARM_
++/*****************************************************************************
++ * A helper for handling a Thumb-Mov32 of position-independent (PC-relative) value
++ *
++ * This routine either records relocation for the location with the EE,
++ * or creates a virtual relocation entry to perform offset fixup during
++ * compilation without recording it with EE - depending on which of
++ * absolute/relocative relocations mode are used for code section.
++ */
++void emitter::emitHandlePCRelativeMov32(void* location, /* IN */
++ void* target) /* IN */
++{
++ if (emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
++ {
++ emitRecordRelocation(location, target, IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL);
++ }
++ else
++ {
++ emitRecordRelocation(location, target, IMAGE_REL_BASED_THUMB_MOV32);
++ }
++}
++#endif // _TARGET_ARM_
++
+ /*****************************************************************************
+ * A helper for recording a call site with the EE.
+ */
+diff --git a/src/jit/emit.h b/src/jit/emit.h
+index 5ec8a6a..a925f1f 100644
+--- a/src/jit/emit.h
++++ b/src/jit/emit.h
+@@ -2183,6 +2183,11 @@ public:
+ WORD slotNum = 0, /* IN */
+ INT32 addlDelta = 0); /* IN */
+
++#ifdef _TARGET_ARM_
++ void emitHandlePCRelativeMov32(void* location, /* IN */
++ void* target); /* IN */
++#endif
++
+ void emitRecordCallSite(ULONG instrOffset, /* IN */
+ CORINFO_SIG_INFO* callSig, /* IN */
+ CORINFO_METHOD_HANDLE methodHandle); /* IN */
+diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp
+index 2b8eb25..9ec8e07 100644
+--- a/src/jit/emitarm.cpp
++++ b/src/jit/emitarm.cpp
+@@ -5387,7 +5387,7 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
+ {
+ assert(ins == INS_movt || ins == INS_movw);
+ if ((ins == INS_movt) && emitComp->info.compMatchedVM)
+- emitRecordRelocation((void*)(dst - 8), (void*)distVal, IMAGE_REL_BASED_THUMB_MOV32);
++ emitHandlePCRelativeMov32((void*)(dst - 8), (void*)distVal);
+ }
+ }
+ else
+@@ -6011,7 +6011,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
+ assert((ins == INS_movt) || (ins == INS_movw));
+ dst += emitOutput_Thumb2Instr(dst, code);
+ if ((ins == INS_movt) && emitComp->info.compMatchedVM)
+- emitRecordRelocation((void*)(dst - 8), (void*)imm, IMAGE_REL_BASED_THUMB_MOV32);
++ emitHandlePCRelativeMov32((void*)(dst - 8), (void*)imm);
+ }
+ else
+ {
+diff --git a/src/jit/instr.cpp b/src/jit/instr.cpp
+index 5bbfdde..670a709 100644
+--- a/src/jit/instr.cpp
++++ b/src/jit/instr.cpp
+@@ -3915,8 +3915,7 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm,
+
+ if (EA_IS_RELOC(size))
+ {
+- getEmitter()->emitIns_R_I(INS_movw, size, reg, imm);
+- getEmitter()->emitIns_R_I(INS_movt, size, reg, imm);
++ genMov32RelocatableImmediate(size, imm, reg);
+ }
+ else if (arm_Valid_Imm_For_Mov(imm))
+ {
+diff --git a/src/jit/jitee.h b/src/jit/jitee.h
+index 7b0e4a0..7a03dd6 100644
+--- a/src/jit/jitee.h
++++ b/src/jit/jitee.h
+@@ -80,6 +80,12 @@ public:
+ JIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code
+ JIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible
+ JIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code
++
++#if defined(_TARGET_ARM_)
++ JIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records
++#else // !defined(_TARGET_ARM_)
++ JIT_FLAG_UNUSED11 = 41
++#endif // !defined(_TARGET_ARM_)
+ };
+ // clang-format on
+
+@@ -192,6 +198,12 @@ public:
+ FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TIER0, JIT_FLAG_TIER0);
+ FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TIER1, JIT_FLAG_TIER1);
+
++#if defined(_TARGET_ARM_)
++
++ FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS, JIT_FLAG_RELATIVE_CODE_RELOCS);
++
++#endif // _TARGET_ARM_
++
+ #undef FLAGS_EQUAL
+ }
+
+diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp
+index 40d14ae..60e03af 100644
+--- a/src/zap/zapinfo.cpp
++++ b/src/zap/zapinfo.cpp
+@@ -2481,7 +2481,25 @@ void ZapInfo::recordRelocation(void *location, void *target,
+
+ #if defined(_TARGET_ARM_)
+ case IMAGE_REL_BASED_THUMB_MOV32:
++ case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
+ case IMAGE_REL_BASED_THUMB_BRANCH24:
++
++# ifdef _DEBUG
++ {
++ CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags;
++
++ if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS))
++ {
++ _ASSERTE(fRelocType == IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL
++ || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
++ }
++ else
++ {
++ _ASSERTE(fRelocType == IMAGE_REL_BASED_THUMB_MOV32
++ || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
++ }
++ }
++# endif // _DEBUG
+ break;
+ #endif
+
+@@ -2584,6 +2602,7 @@ void ZapInfo::recordRelocation(void *location, void *target,
+
+ #if defined(_TARGET_ARM_)
+ case IMAGE_REL_BASED_THUMB_MOV32:
++ case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
+ PutThumb2Mov32((UINT16 *)location, targetOffset);
+ break;
+
+diff --git a/src/zap/zapper.cpp b/src/zap/zapper.cpp
+index 4d1330e..6b45bc2 100644
+--- a/src/zap/zapper.cpp
++++ b/src/zap/zapper.cpp
+@@ -278,8 +278,7 @@ ZapperOptions::ZapperOptions() :
+ m_legacyMode(false)
+ ,m_fNoMetaData(s_fNGenNoMetaData)
+ {
+- m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELOC);
+- m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PREJIT);
++ SetCompilerFlags();
+
+ m_zapSet = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ZapSet);
+ if (m_zapSet != NULL && wcslen(m_zapSet) > 3)
+@@ -319,6 +318,18 @@ ZapperOptions::~ZapperOptions()
+ delete [] m_repositoryDir;
+ }
+
++void ZapperOptions::SetCompilerFlags(void)
++{
++ m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELOC);
++ m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PREJIT);
++
++#if defined(_TARGET_ARM_)
++# if defined(PLATFORM_UNIX)
++ m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS);
++# endif // defined(PLATFORM_UNIX)
++#endif // defined(_TARGET_ARM_)
++}
++
+ /* --------------------------------------------------------------------------- *
+ * Zapper class
+ * --------------------------------------------------------------------------- */
+@@ -370,8 +381,7 @@ Zapper::Zapper(NGenOptions *pOptions, bool fromDllHost)
+ pOptions = &currentVersionOptions;
+
+ zo->m_compilerFlags.Reset();
+- zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELOC);
+- zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PREJIT);
++ zo->SetCompilerFlags();
+ zo->m_autodebug = true;
+
+ if (pOptions->fDebug)
+diff --git a/src/zap/zaprelocs.cpp b/src/zap/zaprelocs.cpp
+index 04708c2..059d9a5 100644
+--- a/src/zap/zaprelocs.cpp
++++ b/src/zap/zaprelocs.cpp
+@@ -84,6 +84,22 @@ void ZapBaseRelocs::WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int ta
+ break;
+ }
+
++ case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
++ {
++ TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva;
++
++ // For details about how the value is calculated, see
++ // description of IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL
++ const UINT32 offsetCorrection = 12;
++
++ UINT32 imm32 = pActualTarget - (pSite + offsetCorrection);
++
++ PutThumb2Mov32((UINT16 *)pLocation, imm32);
++
++ // IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL does not need base reloc entry
++ return;
++ }
++
+ case IMAGE_REL_BASED_THUMB_BRANCH24:
+ {
+ TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva;
+@@ -282,6 +298,7 @@ void ZapBlobWithRelocs::Save(ZapWriter * pZapWriter)
+
+ #if defined(_TARGET_ARM_)
+ case IMAGE_REL_BASED_THUMB_MOV32:
++ case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
+ targetOffset = (int)GetThumb2Mov32((UINT16 *)pLocation);
+ break;
+
+--
+2.7.4
+