diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs index 61d5d8d286c32..d055a41883130 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs @@ -163,7 +163,7 @@ private static unsafe int GetThumb2BlRel24(ushort* p) //***************************************************************************** // Returns whether the offset fits into bl instruction //***************************************************************************** - private static bool FitsInThumb2BlRel24(int imm24) + public static bool FitsInThumb2BlRel24(int imm24) { return ((imm24 << 7) >> 7) == imm24; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs index 042cf91bc238c..0de7f8214e509 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.cs @@ -169,8 +169,9 @@ or IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL && // For R_ARM_THM_JUMP24 the thumb bit cannot be encoded, so mask it out. long maskThumbBitOut = relocType is IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL ? 1 : 0; long maskThumbBitIn = relocType is IMAGE_REL_BASED_THUMB_MOV32_PCREL ? 1 : 0; + long adjustedAddend = addend; - addend -= relocType switch + adjustedAddend -= relocType switch { IMAGE_REL_BASED_REL32 => 4, IMAGE_REL_BASED_THUMB_BRANCH24 => 4, @@ -178,11 +179,19 @@ or IMAGE_REL_BASED_THUMB_BRANCH24 or IMAGE_REL_BASED_THUMB_MOV32_PCREL && _ => 0 }; - addend += definedSymbol.Value & ~maskThumbBitOut; - addend += Relocation.ReadValue(relocType, (void*)pData); - addend |= definedSymbol.Value & maskThumbBitIn; - addend -= offset; - Relocation.WriteValue(relocType, (void*)pData, addend); + adjustedAddend += definedSymbol.Value & ~maskThumbBitOut; + adjustedAddend += Relocation.ReadValue(relocType, (void*)pData); + adjustedAddend |= definedSymbol.Value & maskThumbBitIn; + adjustedAddend -= offset; + + if (relocType is IMAGE_REL_BASED_THUMB_BRANCH24 && !Relocation.FitsInThumb2BlRel24((int)adjustedAddend)) + { + EmitRelocation(sectionIndex, offset, data, relocType, symbolName, addend); + } + else + { + Relocation.WriteValue(relocType, (void*)pData, adjustedAddend); + } } } else