Skip to content

[cmake] Work around relocation R_X86_64_PC32 link error #2012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

RLovelett
Copy link
Contributor

@RLovelett RLovelett commented Apr 1, 2016

What's in this pull request?

This is the first patch to begin working around the dynamic resolution of protected symbols. This behavior was introduced in binutils 2.26.

A more complete discussion of the error and its background can be found in SR-1023.

The brief overview is that in versions of ld that would be effected by this dynamic relocation issue there are two flags: -z nocopyreloc and -z noextern-protected-data. If ld supports the flags then they are sent to the linker. This patch checks that the linker supports the flags and then optionally sets them.

The code to check if ld supports the flags is inspired by this CMake mailing list entry.

https://cmake.org/pipermail/cmake/2011-July/045525.html

Resolves bug number: (SR-1023)

While this pull does not entirely resolve SR-1023 I do think it is a good first step.

Update 1: I've now provided a Driver patch too. This branch should now work on binutils 2.26 (e.g., Ubuntu 16.04). The patch does not work on binutils builds that do not support these flags (e.g., Ubuntu 14.04/15.10). A conditional still needs to be written for the Driver to apply the new flags conditionally. I'm looking for feedback on how to best address that.


Before merging this pull request to apple/swift repository:

  • Test pull request on Swift continuous integration.

Triggering Swift CI

The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:

Smoke Testing

Platform Comment
All supported platforms @swift-ci Please smoke test
OS X platform @swift-ci Please smoke test OS X platform
Linux platform @swift-ci Please smoke test Linux platform

Validation Testing

Platform Comment
All supported platforms @swift-ci Please test
OS X platform @swift-ci Please test OS X platform
Linux platform @swift-ci Please test Linux platform

Note: Only members of the Apple organization can trigger swift-ci.

@jckarter
Copy link
Contributor

jckarter commented Apr 1, 2016

Looks OK to me (though @gribozavr is a better CMake-r than me). We'll also need something in the driver to pass these flags if the linker needs them too. That would need to be some kind of runtime check, though.

@@ -1774,6 +1787,18 @@ function(_add_swift_executable_single name)
list(APPEND link_flags "-fuse-ld=gold")
endif()

INCLUDE(CheckCXXCompilerFlag)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't think this block is required. I merely included it because I think it might be. Someone who understands the CMake scripts a little better might be able to quickly deduce its necessity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this block is necessary. This function is used to configure compiler executables, which don't have any Swift code in them.

@RLovelett
Copy link
Contributor Author

@jckarter I don't yet understand how the driver works in order to write that code. I'm interested in trying to fix that piece as well (as a separate pull). I just figured I'd start with the piece I do somewhat understand and can test and validate.

@jckarter
Copy link
Contributor

jckarter commented Apr 1, 2016

One thing, there's no reason to do this check when building to target OS X; it's only necessary if targeting ELF platforms (or maybe only Linux, if the binutils brain damage didn't make it out to *BSD).

@jckarter
Copy link
Contributor

jckarter commented Apr 1, 2016

Fair enough about making the driver change separately. It'd be good to note that in the PR.

CHECK_CXX_COMPILER_FLAG("" LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA)
IF(LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA)
list(APPEND link_flags ${CMAKE_REQUIRED_FLAGS})
ENDIF()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you should include() or run tests in this function. This function is executed many times.

You should run the test once in the top-level CMakeLists.txt.

Also, our CMake code uses lowercase for function names, and two spaces for indentation, could you make it consistent?

@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch 2 times, most recently from b2fc5eb to ca5808d Compare April 5, 2016 02:36
@RLovelett
Copy link
Contributor Author

I've rebased on master and pushed up a new attempt that incorporates the feedback.

@jckarter I've moved the test for the linker flag inside of an if that only executes on Linux.

@gribozavr I've created a new CMake module, CheckLinkerDynamicRelocationFlags, that defines a function that allows for testing the linker. This function is executed in the CMakeLists.txt and sets two variables LINKER_SUPPORTS_NOCOPYRELOC and LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA. AddSwift.cmake merely checks that those variables evalute to true and then turns on the appropriate flags.

I believe I've also addressed the styling changes you've requested.

@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch from ca5808d to 84de260 Compare April 5, 2016 02:42
@gribozavr
Copy link
Contributor

Thank you! Could you prefix global variables with SWIFT_*? LGTM with that.

@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch from 84de260 to 63c702c Compare April 5, 2016 12:32
@RLovelett
Copy link
Contributor Author

Updated to SWIFT_LINKER_SUPPORTS_NOCOPYRELOC and SWIFT_LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA.

Thank you for taking the time to review @jckarter and @gribozavr.

@@ -419,6 +420,12 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(SWIFT_HOST_VARIANT_SDK "LINUX")
set(SWIFT_PRIMARY_VARIANT_SDK_default "LINUX")

# Support dynamic relocation in binutils >= 2.26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More precisely, we're supporting "relative relocation against protected symbols in binutils 2.26". Give them the benefit of the doubt that 2.27 might be fixed.

@jckarter
Copy link
Contributor

jckarter commented Apr 5, 2016

LGTM too, with a fix to the comment.

function(check_linker_supports_flag flag_to_test var_name)
set(CMAKE_REQUIRED_FLAGS "${flag_to_test}")
check_cxx_compiler_flag("" LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA)
if(LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable name LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA is not relevant for here.
result would be sufficient I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I could have swore I replied to this already but apparently not.)

If I change it to result than the check in the CMake output is less meaningful. It displays something like

...
Performing Test result
Performing Test result - Success
...

as opposed to

...
Performing Test LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA
Performing Test LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA - Success
...

If you still think it is worth it than I'm amenable to the change but I think it provides a less clear description of what is going on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I understand that.
And I found CMake caches the result of check_cxx_compiler_flag associated with the variable name.
Because of that, if "-Wl,-z,nocopyreloc" failed, then "-Wl,-z,noextern-protected-data" fails without actual test.
To prevent that, <var> for every tests must have unique names.

For example:

function(check_linker_supports_flag flag_to_test var_name)                        
    set(CMAKE_REQUIRED_FLAGS "${flag_to_test}")                                   
    check_cxx_compiler_flag("" ${var_name})                                       
    if(${${var_name}})                                                            
        set("${var_name}" TRUE PARENT_SCOPE)                                      
    else()                                                                        
        set("${var_name}" FALSE PARENT_SCOPE)                                     
    endif()                                                                       
endfunction()                                                                     

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I should clarify the problem. For example:

cmake_minimum_required(VERSION 2.8.12)                                            
include(CheckCXXCompilerFlag)                                                     

check_cxx_compiler_flag("-static" RESULT)                                         
message("RESULT_STATIC: ${RESULT}")                                               
check_cxx_compiler_flag("-FOO-BAR" RESULT)                                        
message("RESULT_FOOBAR: ${RESULT}")                                               

This CMakeLists.txt outputs:

-- Performing Test RESULT
-- Performing Test RESULT - Success
RESULT_STATIC: 1
RESULT_FOOBAR: 1

The second check_cxx_compiler_flag() is no-op and just returns cached RESULT value.
Generated CMakeCache.txt contains

//Test RESULT                                                                     
RESULT:INTERNAL=1                                                                 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rintaro wonderful catch! Yes.

-- Performing Test SWIFT_LINKER_SUPPORTS_NOCOPYRELOC
-- Performing Test SWIFT_LINKER_SUPPORTS_NOCOPYRELOC - Success
-- Performing Test SWIFT_LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA
-- Performing Test SWIFT_LINKER_SUPPORTS_NOEXTERN_PROTECTED_DATA - Success

Much, much better. Thank you.

@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch 2 times, most recently from 5c81539 to 63ae486 Compare April 6, 2016 19:08
@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch 2 times, most recently from 281b050 to 59d2e56 Compare April 15, 2016 12:44
@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch 2 times, most recently from b15f541 to 2ff13c6 Compare April 26, 2016 13:40
@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch from 2ff13c6 to 650791d Compare April 29, 2016 18:04
A more complete discussion of the error and its background can be found
in SR-1023.

The brief overview is that in versions of `ld` that would be effected by
this dynamic relocation issue there are two flags: `-z nocopyreloc` and
`-z noextern-protected-data`. If `ld` supports the flags then they are
sento to the linker. This patch checks that the linker supports the
flags and then optionally sets them.

The code to check if `ld` supports the flags is inspired by this CMake
mailing list entry.

https://cmake.org/pipermail/cmake/2011-July/045525.html
@RLovelett RLovelett force-pushed the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch from 650791d to cabe7c4 Compare May 23, 2016 13:02
@RLovelett
Copy link
Contributor Author

With #2609 going in I now think this change is over-come by events. The problem that it was trying to fix was solved by #2609.

I am going to close it.

@RLovelett RLovelett closed this May 25, 2016
@RLovelett RLovelett deleted the bugfix/SR-1023-Build-Error-Relocation-R_X86_64_PC32 branch July 26, 2016 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants