Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Linux improvements (fixing linker args & Documentation updates) #6843

Merged
merged 4 commits into from
Jan 19, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions Documentation/prerequisites-for-building.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,47 @@ sudo zypper install cmake libuuid-devel icu libcurl-devel zlib-devel
Make sure you run with Ubuntu 16.04 Xenial userland (this is the default after Windows 10 Creators Update, but if you enabled the "Bash on Ubuntu on Windows" feature before the Creators Update, you need to [upgrade manually](https://blogs.msdn.microsoft.com/commandline/2017/04/11/windows-10-creators-update-whats-new-in-bashwsl-windows-console/)). Running `lsb_release -a` will give you the version.

Then follow the Ubuntu 16.04 instructions above.

# clang 3.9 not found on Linux

If you encounter this error, CoreRT could not find the clang executable
```
error : Platform linker ('clang-3.9') not found. Try installing clang-3.9 or the appropriate package for your platform to resolve the problem.
```

CoreRT expect by default clang-3.9 installed (see above). You can override this by setting an environment variable.

```
export CppCompilerAndLinker=clang
```

This works for building CoreCR itself as well as building with CoreRT.
When filing bugs, please make sure to mention the clang version you are using, if you override this.

# libObjWriter.so not found on Linux

```
EXEC : error : Unable to load shared library 'objwriter' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libobjwriter: cannot open shared object file: No such file or directory
```

This is the default error message when a `[DllImport]` could not be loaded. CoreRT nuget packages distribute this file, but it might be failing to load dependencies.
Make sure to install all dependencies. If the error persists, use ldd to find out if you lack any dependencies.

```
ldd /home/<username>/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/<nuget_package_version>/tools/libobjwriter.so
linux-vdso.so.1 (0x00007ffe9bbea000)
librt.so.1 => /usr/lib/librt.so.1 (0x00007f8f52142000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f8f5213d000)
libtinfo.so.5 => not found
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f8f5211c000)
libz.so.1 => /usr/lib/libz.so.1 (0x00007f8f51f05000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f8f51d80000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f8f51bef000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f8f51bd5000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f8f51a11000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007f8f53358000)
```

In this Arch Linux example, libtinfo.so.5 is missing. Its part of ncurses5 but AUR has a compatibility package here:
https://aur.archlinux.org/packages/ncurses5-compat-libs/
After installing it should work fine
1 change: 1 addition & 0 deletions src/BuildIntegration/Microsoft.NETCore.Native.Unix.props
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ See the LICENSE file in the project root for more information.
<LinkerArg Include="-lm" />
<LinkerArg Include="-lcurl" />
<LinkerArg Include="-lz" />
<LinkerArg Include="-nopie" Condition="'$(TargetOS)' == 'Linux'" />
Copy link
Member

Choose a reason for hiding this comment

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

What is the error you are working around with -nopie?

If I understand it correctly, -nopie disables ASLR and thus makes the binaries less secure. We do not really want the CoreRT binaries to be less secure...

Copy link
Contributor Author

@sebastianulm sebastianulm Jan 17, 2019

Choose a reason for hiding this comment

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

Oh, I totally agree, and I hope you guys will be able to fix it "propper".
Here is what I pieced together so far:
The current binary distributed by the nuget package segfaults for me. To investigate, I checked out the repo and tried to build it. However, while compilation succeeded, all JIT-Tests fail with:
R_X86_64_PC32 against symbol `memcpy@@GLIBC_2.14' can not be used
at the Linking stage.

The reason behind this seems to be this, but I am unable to tell you if that is true.
https://stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linux

Arch Linux (the distribution I use) ships with compilers that assume -use-pie by default, for security reasons. I assume that the build machine does not, (hence tests working)
Mainly because the distributed ILC itself has PIE switched off:

> checksec --file /home/yasuo/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/1.0.0-alpha-27317-01/tools/ilc
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable  FILE
Partial RELRO   Canary found      NX enabled    No PIE          RPATH     No RUNPATH   No Symbols      Yes	0		5	/home/yasuo/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/1.0.0-alpha-27317-01/tools/ilc

So I decided to make a pull request, with this work around. AFAIK it does not make things works.
But I'd like a different fix much more, PIE adds a lot of benefits for a tiny performance hit.

I use this script: https://github.com/slimm609/checksec.sh to check if files are made with PIE.

I hope this information helps.
Edit: Adding a gist to the linker output here https://gist.github.com/sebastianulm/f1bba12ec15bd5cb707f04388b171edd

Copy link
Member

Choose a reason for hiding this comment

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

R_X86_64_PC32

We had several reports of this https://github.com/dotnet/corert/search?q=R_X86_64_PC32&type=Issues . It is a bug in the objectwriter component. #538 has best hints about what the fix may be.

AFAIK it does not make things works.

How this does not work? Is the binary crashing when you try to run it?

Copy link
Contributor Author

@sebastianulm sebastianulm Jan 18, 2019

Choose a reason for hiding this comment

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

Yes, object writer emits only 32 bit Symbols, which can not be relocated in 64 bit memory, hence it cannot link with -fPIE. I don't consider this a bug. They are not broken, there are valid considerations to disable this for some builds. For example if you build render software or a bitcoin miner or anything very CPU intensive, you want to use 32 bit symbols.
They are a bit faster, even on 64 bit platforms.

Aside from these special cases virtually everybody wants to build full 64 bits, because its required to randomize the address space.

So, in a perfect world, libObjWriter would have a flag that switches between the two. I consider it more a missing feature the a Bug. There are genuine reasons for making this a parameter (which is why all linux compilers offer this flag)

AFAIK it does not make things works.

Sorry, this is a typo. I meant to write, "AFAIK it does not make things worse".
Currently, if I check out clang-3.9, build it and use it as a linker, it will not produce PIC-Binaries by default.
The Microsoft.NETCore.Native.Unix.props file does not state -fPIC nor -Fno-PIC. It simply uses what ever has been set as the default when building clang.
Most modern distribution ship binaries of clang with –enable-default-pie, which changes the default from -Fno-PIC to -fPIC. Ubuntu started doing this in with 16.10 https://wiki.ubuntu.com/SecurityTeam/PIE

I think the build machine either has an older version, or does not use the binary from the distribution. Hence all the tests are passing on the build machine, but fail out in the wild.

I may be wrong here, so this is something you should check. Grabbing an artifact from the build machine and checking if it was build with PIC enabled should be enough to find out.

The people from the issues you linked all have the same issue as me, and I know not nearly enough to add that missing feature to objWriter.

Copy link
Member

Choose a reason for hiding this comment

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

Could you please exclude this change from this PR?

Hopefully, #6847 will land soon and we will have proper fix for this issue.

Copy link
Contributor Author

@sebastianulm sebastianulm Jan 19, 2019

Choose a reason for hiding this comment

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

Done!

I'll try to help with testing on those new changes asap.
Unfortunately I know very little about clang and assembler. I know a bit about the elf file format, and linux tools, so testing things is probably something I can do.

<LinkerArg Include="-lgssapi_krb5" Condition="'$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-lrt" Condition="'$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-licucore" Condition="'$(TargetOS)' == 'OSX'" />
Expand Down
1 change: 1 addition & 0 deletions tests/src/Simple/StaticLibrary/StaticLibrary.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<NativeRunnerLinkerArg Include="-lm" />
<NativeRunnerLinkerArg Include="-lcurl" />
<NativeRunnerLinkerArg Include="-lz" />
<NativeRunnerLinkerArg Include="-nopie" Condition="'$(TargetOS)' == 'Linux'" />
<NativeRunnerLinkerArg Include="-lrt" Condition="'$(TargetOS)' != 'OSX'" />
<NativeRunnerLinkerArg Include="-licucore" Condition="'$(TargetOS)' == 'OSX'" />
</ItemGroup>
Expand Down