With this patch I introduced new gold plugin option "relocation-pic".
This option sets PIC dynamic model for generated code.
This mode is needed for executables on Android.
Details
- Reviewers
samsonov volkalexey srhines • rafael - Commits
- rG6468f5d30947: Add comments regarding isPIEDefault usage for r207520
rG06921036536d: Pass -pie to linker when generating executable on Android This fixes problem…
rC207521: Add comments regarding isPIEDefault usage for r207520
rC207520: Pass -pie to linker when generating executable on Android
rL207521: Add comments regarding isPIEDefault usage for r207520
rL207520: Pass -pie to linker when generating executable on Android
Diff Detail
Event Timeline
Hi Rafael,
I've rewritten my patch with "-pie" linker option.
Unfortunately I couldn't use isPIEDefault function since PIE will be turned on for all objects generated in Clang::ConstructJob.
Analysis of compiler options is not sufficient since the same object can be used for library or for executable.
I think this is OK.
Peter, can you just confirm that the handling of hasZeroBaseShadow is
correct? In particular, its interaction with -static.
I'm not sure if this is correct. If an executable is being linked statically I think it will still need to be a PIE if a sanitizer which needs the lower pages is enabled. But then again libc or other system static libraries may have been built as non-PIC so PIE linking might fail. I think the right thing to do might be to always try to link a PIE if the sanitizer needs it, and let the linker complain if it doesn't work, i.e. rewrite like this:
const bool IsPIE = !Args.hasArg(options::OPT_shared) && (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow() || (isAndroid && !Args.hasArg(options::OPT_static)));
Adding Alexey Samsonov, who may be able to confirm the correct behavior here (also since there aren't enough Alexeys on this thread).
Unfortunately my last patch cannot work with -Wl compiler option.
E.g. passing -Wl,-shared will not set OPT_shared variable and so -shared and -pie both passed to linker.
Linker will complain about incompatible options.
I am not sure if parsing -Wl option value for shared, static, etc is acceptable here.
In my first patch addition of new gold plugin option does not have such problems.
I updated patch to the current trunk.
Alexey, could you check if interaction between -static and Sanitize.hasZeroBaseShadow() is correct?
In general, sanitizers don't work with -static flag at all, so there shouldn't be any problems with "interaction".
lib/Driver/Tools.cpp | ||
---|---|---|
6919 | I don't understand this part - effectively you're making -pie the default on Android. Is it really the intended behavior? If yes, shouldn't you implement it in ToolChain.isPIEDefault() instead? |
lib/Driver/Tools.cpp | ||
---|---|---|
6919 | Flag -pie passed to linker solved original problem with LTO on Android. |
lib/Driver/Tools.cpp | ||
---|---|---|
6919 | Ok. I also see that you can probably do this because -fpic/-fPIC flags are implied for Android on certain architectures (in Clang::ConstructJob method). But, anyway, unconditionally ignoring the presence/absence of -pie flag on Android is a serious change, which might be surprising for end-user. Is it possible to imply "-pie" iff LTO is enabled? |
lib/Driver/Tools.cpp | ||
---|---|---|
6919 | Yes, it is possible to use -pie only with -flto. |
Ok. I also see that you can probably do this because -fpic/-fPIC flags are implied for Android on certain architectures (in Clang::ConstructJob method). But, anyway, unconditionally ignoring the presence/absence of -pie flag on Android is a serious change, which might be surprising for end-user. Is it possible to imply "-pie" iff LTO is enabled?
Yes, it is possible to use -pie only with -flto.
Raphael, do you have any objections?
I am probably missing something.
From the previous comments I was under the impression that non-pie
executable were not supported at all on android. If that is the case,
passing -pie would be nop, except for working around a linker bug (it
not passing LDPO_PIE to the plugin).
If that is the case, we should just always pass -pie. If that is not
the case, I don't understand the patch. When building a pie executable
the user has to pass -fPIE to clang and -pie gets passed to the linker
already, no?
Cheers,
Rafael
On Android user doesn't have to pass -fPIC or -fPIE option.
Clang is turning on PIC mode (not PIE) without any user input when targeting to Android.
However when producing executable compiler has no special options (-pie) for linker.
So linker produces executable from PIC objects without -pie option.
So final executable is not pure PIE, it's executable formed from PIC code.
This is what we have now on Android.
Adding -pie option to linker could change produced code which could be surprising to user.
Since -pie needed only to fix or workaround this bug I propose to have -pie only with LTO enabled.
Getting close. LGTM with a comment about why we can't use
isPIEDefault: It would enable PIE only logic, like which TLS model to
use, when compiling. That actually looks like a bug in the driver, but
can be fixed in another commit.
Cheers,
Rafael
2014-04-28 20:38 GMT+04:00 Rafael Ávila de Espíndola <
rafael.espindola@gmail.com>:
Getting close. LGTM with a comment about why we can't use
isPIEDefault: It would enable PIE only logic, like which TLS model to
use, when compiling. That actually looks like a bug in the driver, but
can be fixed in another commit.
I don't understand how it could be fixed.
When compiler generates object it has no information regarding further
usage of object: executable or library.
Function isPIEDefault turns on PIE for every object for specific target.
So it seems to be useful only for targets with no shared libraries.
Cheers,
Rafael
What happened to guarding this to only be enabled with LTO? Enabling it for all Android targets isn't correct, as anything before Jelly Bean (~15% of devices) doesn't even support PIE. It currently is not possible to build an Android executable with clang that works on ICS or earlier.
Since there is no way to override this behavior, I'd much prefer to just require that build tools supply -pie on their own.
BTW, srhines should really be added as a reviewer for any Android related clang change.
I don't understand this part - effectively you're making -pie the default on Android. Is it really the intended behavior?
If yes, shouldn't you implement it in ToolChain.isPIEDefault() instead?