Skip to content

Commit

Permalink
Fix redhat arm64 (#52244)
Browse files Browse the repository at this point in the history
* Fix RHEL 8 ARM64

Clang on ARM64 places the .rodata section into the same segment
as .text. On RHEL 8 ARM64, the kernel is configured for 64kB
memory pages. When we flip the page protection of the page containing
the GS cookie to RW and back to RO, we assume that the cookie lives
in a non-executable memory. This assumption is broken on RHEL 8 and
we end up setting protection of a part of the coreclr code to read
only instead of back to RX.

This change switches the linker we use to lld from the previously
used gnu linker. That linker places .rodata into a different segment
than .text by default. Moreover, I was planning to move to using
lld anyways to use all build tools from LLVM.

* Fix ARM build to use PC relative addresses only

The lld linker has revealed that we were using absolute addresses in some
asm helpers and so load time relocation was necessary. This change fixes
it by replacing all of those by PC relative ones.

* Update docker images used for building runtime

Use new images that have lld linker

* Disable lld linker for s390x
  • Loading branch information
janvorli authored Jul 28, 2021
1 parent beaea95 commit 39803d4
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 27 deletions.
2 changes: 1 addition & 1 deletion eng/common/templates/jobs/source-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ parameters:
# This is the default platform provided by Arcade, intended for use by a managed-only repo.
defaultManagedPlatform:
name: 'Managed'
container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343'
container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-20210714125435-9b5bbc2'

# Defines the platforms on which to run build jobs. One job is created for each platform, and the
# object in this array is sent to the job template as 'platform'. If no platforms are specified,
Expand Down
6 changes: 4 additions & 2 deletions eng/native/configuretools.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@ endif()

if (NOT CLR_CMAKE_HOST_WIN32)
# detect linker
set(ldVersion ${CMAKE_C_COMPILER};-Wl,--version)
separate_arguments(ldVersion UNIX_COMMAND "${CMAKE_C_COMPILER} ${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version")
execute_process(COMMAND ${ldVersion}
ERROR_QUIET
OUTPUT_VARIABLE ldVersionOutput)

if("${ldVersionOutput}" MATCHES "GNU ld" OR "${ldVersionOutput}" MATCHES "GNU gold" OR "${ldVersionOutput}" MATCHES "GNU linkers")
if("${ldVersionOutput}" MATCHES "LLD")
set(LD_LLVM 1)
elseif("${ldVersionOutput}" MATCHES "GNU ld" OR "${ldVersionOutput}" MATCHES "GNU gold" OR "${ldVersionOutput}" MATCHES "GNU linkers")
set(LD_GNU 1)
elseif("${ldVersionOutput}" MATCHES "Solaris Link")
set(LD_SOLARIS 1)
Expand Down
2 changes: 1 addition & 1 deletion eng/native/functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function(preprocess_files PreprocessedFilesList)
endfunction()

function(set_exports_linker_option exports_filename)
if(LD_GNU OR LD_SOLARIS)
if(LD_GNU OR LD_SOLARIS OR LD_LLVM)
# Add linker exports file option
if(LD_SOLARIS)
set(EXPORTS_LINKER_OPTION -Wl,-M,${exports_filename} PARENT_SCOPE)
Expand Down
12 changes: 11 additions & 1 deletion eng/native/init-compiler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ minorVersion="$4"
# clear the existing CC and CXX from environment
CC=
CXX=
LDFLAGS=

if [[ "$compiler" == "gcc" ]]; then cxxCompiler="g++"; fi

Expand Down Expand Up @@ -106,6 +107,15 @@ if [[ -z "$CC" ]]; then
exit 1
fi

if [[ "$compiler" == "clang" ]]; then
if command -v "lld$desired_version" > /dev/null; then
# Only lld version >= 9 can be considered stable
if [[ "$majorVersion" -ge 9 ]]; then
LDFLAGS="-fuse-ld=lld"
fi
fi
fi

SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version")"

export CC CXX SCAN_BUILD_COMMAND
export CC CXX LDFLAGS SCAN_BUILD_COMMAND
14 changes: 7 additions & 7 deletions eng/pipelines/common/platform-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
targetRid: linux-arm
platform: Linux_arm
container:
image: ubuntu-16.04-cross-20200413125008-09ec757
image: ubuntu-16.04-cross-20210719121212-8a8d3be
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand All @@ -64,7 +64,7 @@ jobs:
targetRid: linux-arm64
platform: Linux_arm64
container:
image: ubuntu-16.04-cross-arm64-20201022204150-b2c2436
image: ubuntu-16.04-cross-arm64-20210719121212-8a8d3be
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand All @@ -91,7 +91,7 @@ jobs:
targetRid: linux-musl-x64
platform: Linux_musl_x64
container:
image: alpine-3.9-WithNode-20200602002639-0fc54a3
image: alpine-3.9-WithNode-20210714125437-9b5bbc2
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand All @@ -116,7 +116,7 @@ jobs:
targetRid: linux-musl-arm
platform: Linux_musl_arm
container:
image: ubuntu-16.04-cross-arm-alpine-20210409142327-044d5b9
image: ubuntu-16.04-cross-arm-alpine-20210719121212-044d5b9
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand All @@ -143,7 +143,7 @@ jobs:
targetRid: linux-musl-arm64
platform: Linux_musl_arm64
container:
image: ubuntu-16.04-cross-arm64-alpine-20200413125008-406629a
image: ubuntu-16.04-cross-arm64-alpine-20210719121212-b2c2436
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand All @@ -169,7 +169,7 @@ jobs:
targetRid: linux-x64
platform: Linux_x64
container:
image: centos-7-20201227183837-5fe0e50
image: centos-7-20210714125435-9b5bbc2
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand All @@ -193,7 +193,7 @@ jobs:
targetRid: linux-x64
platform: Linux_x64
container:
image: centos-7-source-build-20210408124356-5d87b80
image: centos-7-source-build-20210714125450-5d87b80
registry: mcr
jobParameters:
runtimeFlavor: ${{ parameters.runtimeFlavor }}
Expand Down
10 changes: 8 additions & 2 deletions src/coreclr/pgosupport.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ function(add_pgo TargetName)
else(CLR_CMAKE_HOST_WIN32)
if(UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELEASE OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELWITHDEBINFO)
target_compile_options(${TargetName} PRIVATE -flto -fprofile-instr-generate)
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-ld=gold -fprofile-instr-generate")
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fprofile-instr-generate")
if(NOT LD_LLVM)
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS " -fuse-ld=gold")
endif()
endif(UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELEASE OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELWITHDEBINFO)
endif(CLR_CMAKE_HOST_WIN32)
elseif(CLR_CMAKE_PGO_OPTIMIZE)
Expand Down Expand Up @@ -61,7 +64,10 @@ function(add_pgo TargetName)
if((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.6))
if(HAVE_LTO)
target_compile_options(${TargetName} PRIVATE -flto -fprofile-instr-use=${ProfilePath} -Wno-profile-instr-out-of-date -Wno-profile-instr-unprofiled)
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fuse-ld=gold -fprofile-instr-use=${ProfilePath}")
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS " -flto -fprofile-instr-use=${ProfilePath}")
if(NOT LD_LLVM)
set_property(TARGET ${TargetName} APPEND_STRING PROPERTY LINK_FLAGS " -fuse-ld=gold")
endif()
else(HAVE_LTO)
message(WARNING "LTO is not supported, skipping profile guided optimizations")
endif(HAVE_LTO)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,6 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
set(VM_SOURCES_DAC_AND_WKS_ARCH
${ARCH_SOURCES_DIR}/stubs.cpp
exceptionhandling.cpp
gcinfodecoder.cpp
)

set(VM_HEADERS_DAC_AND_WKS_ARCH
Expand All @@ -865,6 +864,7 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM64)

set(VM_SOURCES_WKS_ARCH
${ARCH_SOURCES_DIR}/profiler.cpp
gcinfodecoder.cpp
)

if(CLR_CMAKE_HOST_UNIX)
Expand Down
9 changes: 6 additions & 3 deletions src/coreclr/vm/arm/asmhelpers.S
Original file line number Diff line number Diff line change
Expand Up @@ -928,8 +928,9 @@ LOCAL_LABEL(CallCppHelper3):
.endm

.macro JIT_WRITEBARRIER_DESCRIPTOR name
.word \name
.word \name\()_End
1:
.word \name-1b
.word \name\()_End-1b
.word __\name\()__g_lowest_address_offset
.word __\name\()__g_highest_address_offset
.word __\name\()__g_ephemeral_low_offset
Expand Down Expand Up @@ -983,7 +984,9 @@ g_rgWriteBarrierDescriptors:
LEAF_ENTRY JIT_WriteBarrier_Callable

// Branch to the write barrier
ldr r2, =JIT_WriteBarrier_Loc // or R3? See targetarm.h
ldr r2, =JIT_WriteBarrier_Loc-(1f+4) // or R3? See targetarm.h
1:
add r2, pc
ldr pc, [r2]

LEAF_END JIT_WriteBarrier_Callable
Expand Down
15 changes: 9 additions & 6 deletions src/coreclr/vm/arm/pinvokestubs.S
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,19 @@

PROLOG_PUSH "{r4, lr}"

ldr r1, =s_gsCookie
ldr r1, =s_gsCookie-(1f+4)
1:
add r1, pc
ldr r1, [r1]
str r1, [r0]
add r4, r0, SIZEOF__GSCookie

// r4 = pFrame

// set first slot to the value of InlinedCallFrame::`vftable' (checked by runtime code)
ldr r1, .L12
ldr r1, =_ZTV16InlinedCallFrame+8-(2f+4)
2:
add r1, pc
str r1, [r4]

mov r1, 0
Expand Down Expand Up @@ -123,9 +127,6 @@

NESTED_END JIT_PInvokeBegin, _TEXT

.L12:
.word _ZTV16InlinedCallFrame+8

// ------------------------------------------------------------------
// IN:
// InlinedCallFrame (r0) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right
Expand All @@ -145,7 +146,9 @@
str r2, [r1, #Thread_m_fPreemptiveGCDisabled]

// Check return trap
ldr r2, =g_TrapReturningThreads
ldr r2, =g_TrapReturningThreads-(1f+4)
1:
add r2, pc
ldr r2, [r2]
cbnz r2, LOCAL_LABEL(RarePath)

Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/vm/arm/stubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ void StubLinkerCPU::Init(void)
// value of the global into a register.
struct WriteBarrierDescriptor
{
BYTE * m_pFuncStart; // Pointer to the start of the barrier function
BYTE * m_pFuncEnd; // Pointer to the end of the barrier function
DWORD m_pFuncStart; // Offset to the start of the barrier function relative to this struct address
DWORD m_pFuncEnd; // Offset to the end of the barrier function relative to this struct address
DWORD m_dw_g_lowest_address_offset; // Offset of the instruction reading g_lowest_address
DWORD m_dw_g_highest_address_offset; // Offset of the instruction reading g_highest_address
DWORD m_dw_g_ephemeral_low_offset; // Offset of the instruction reading g_ephemeral_low
Expand Down Expand Up @@ -440,7 +440,7 @@ void UpdateGCWriteBarriers(bool postGrow = false)
{
// If the write barrier is being currently used (as in copied over to the patchable site)
// then read the patch location from the table and use the offset to patch the target asm code
PBYTE to = FindWBMapping(pDesc->m_pFuncStart);
PBYTE to = FindWBMapping((BYTE *)pDesc + pDesc->m_pFuncStart);
if(to)
{
to = (PBYTE)PCODEToPINSTR((PCODE)GetWriteBarrierCodeLocation(to));
Expand Down

0 comments on commit 39803d4

Please sign in to comment.