[swift-dev] Build Error: Relocation R_X86_64_PC32

Ryan Lovelett swift-dev at ryan.lovelett.me
Tue Mar 22 15:36:06 CDT 2016

On Tue, Mar 22, 2016, at 01:26 PM, William Dillon wrote:
>> Phew. Well I finally got everything ready to where I could bisect
>> binutils. I won't bore with the details of what it took to actually be
>> able to bisect binutils (unless someone actually wants to know).
> I would be interested if it’s not too much trouble.  I’ve been in a similar predicament with LLVM before.  I’d love to have another tool in the chest in case I have to do such a thing again.
> - Will

Not too much trouble at all. In fact, I kind of just want to tell
someone; so I'm glad you asked!

The biggest challenge of the whole thing was just getting reproducable
builds using binutils. For the better part of a week I was unable to
build a linker that could link even the most basic "Hello World" source.
Eventually I ended up contacting the binutils package maintainer, Allan

He pointed out that in order to build binutils on Arch there was a
specific order of operations. You have to build the
linux-api-headers->glibc->binutils->gcc->binutils->glibc. This was
especially true because of the change in the way that relocations occurs
in the newer binutils. Since Arch is "rolling release" distribution I
ended up having to make a VM that had a configuration of Arch from early
February, when I knew all this stuff worked. Once I could compile newer
versions of binutils and that made all the difference.

Now that I had a stable process for building binutils the next parts
were relatively straight forward. When I set out to do this I had
_thought_ what I am about to describe would be all I'd need to do.

Effectively I went back to a version/commit of binutils that I new
worked. I new the last version that worked was package 2.25.1-3; so I
got the commit hash from the PKGBUILD script [1] that was used to make
that package. Which turned out to be 2bd25930. Next I wanted the commit
hash of the package that I knew didn't work 2.26-3; so I got the commit
hash from PKGBUILD script [2] that was used to make that package. Which
turned out to be 71090e7a.

Generally speaking that would have been enough to actually do the
bisecting. However since I knew the compilation loops were going to be
long I realized this could take a few hours of compiling and rinse and
repeat to actually find the script. Luckily `git bisect run` exists.

`git bisect run` is effectively like manual `git bisect` except you can
write a script that performs the action you'd perform at each step of
the bisect.

>From there I wrote a script that provided the steps to build binutils
from source. Then install that new binutils and compile Swift with that
updated version. The actual script that I used is right here [3].

The script ensures that the system gets back to a "pristine" state
between bisection steps and then compiles and installs binutils. It then
compiles Swift.

If anything goes wrong compiling binutils then its considered a
skippable commit and the script returns 125. If Swift fails to compile
it was considered a "bad" commit and the script returns 1. If Swift
compiled cleanly it was a "good" commit and the script returns 0.

The most important advice I can give you is don't forget the 125 return
code. If something goes wrong and you prematurely mark a commit as "bad"
then the entire bisect can complete but erroneously tell you which
commit was actually the first bad commit. In my opinion its better to
skip than prematurely mark as bad.

Once the script was written the hard part was over.

$ cd /directory/with/binutils/source
$ git bisect start 71090e7a9dde8d28ff5c4b44d6d83e270d1088e4
$ git bisect run ~/binutils-bisect.sh |& tee -a ~/bisect-output.log

I put all of the logs and scripts in a Gist just in-case I ever need
them again in the future [4].

Hope that was enough information Will.

[4] https://gist.github.com/RLovelett/f73fb5f701035b33417c

More information about the swift-dev mailing list