This is an archive of the discontinued LLVM Phabricator instance.

[asan] Use dynamic shadow on 32-bit Android.
ClosedPublic

Authored by eugenis on Oct 27 2017, 3:17 PM.

Details

Summary

The following kernel change has moved ET_DYN base to 0x4000000 on arm32:
https://marc.info/?l=linux-kernel&m=149825162606848&w=2

Switch to dynamic shadow base to avoid such conflicts in the future.

In my limited testing, this is causing 1.3% binary size increase, and
from 1% to 6% CPU overhead, depending on the benchmark.

Diff Detail

Repository
rL LLVM

Event Timeline

eugenis created this revision.Oct 27 2017, 3:17 PM
eugenis planned changes to this revision.Oct 31 2017, 1:54 PM
eugenis updated this revision to Diff 121804.Nov 6 2017, 3:21 PM

Reserve shadow range in ifunc.

pcc added a subscriber: pcc.Nov 6 2017, 3:47 PM
pcc added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
970 ↗(On Diff #121805)

Is the ifunc_safe change necessary? If common_flags() is inlined, I would expect the access to go through common_flags_dont_use, which you have marked as hidden. You might want to make common_flags() hidden as well, in case it doesn't get inlined.

vitalybuka added inline comments.Nov 6 2017, 4:05 PM
compiler-rt/lib/asan/asan_linux.cc
99 ↗(On Diff #121805)

why do you need to *8 here?

eugenis added inline comments.Nov 6 2017, 4:07 PM
compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
970 ↗(On Diff #121805)

unfortunately it does into GetKernelAreaSize(), because common_flags()->full_address_space is statically initialized to false. And that is not ifunc-safe.

eugenis added inline comments.Nov 6 2017, 4:08 PM
compiler-rt/lib/asan/asan_linux.cc
99 ↗(On Diff #121805)

I had the same question a while ago :)
Because shadow gap start is calculated as shadow(shadow_start), and needs to be page-aligned, so shadow-start needs to be 8 page aligned.

vitalybuka accepted this revision.Nov 6 2017, 4:15 PM
This revision is now accepted and ready to land.Nov 6 2017, 4:15 PM
pcc added inline comments.Nov 6 2017, 4:26 PM
compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
970 ↗(On Diff #121805)

Oh, right.

I have a mild preference for there to be a separate function that is ifunc-safe (maybe rename this function to GetMaxUserVirtualAddress and then have the ifunc-safe one be GetMaxVirtualAddress), but up to you.

It turns out that clang is exceptionally bad at accessing external variables in PIC code on ARM:
https://bugs.llvm.org/show_bug.cgi?id=35221

This translates to 20% code size regression, and 15% CPU.
I think I'll hold off on this change, and look at the codegen issue in the meantime.

eugenis updated this revision to Diff 122012.Nov 7 2017, 4:23 PM

Lets go ahead with this, but keep using "legacy" dynamic shadow instrumentation.
Performance numbers of that mode aren't that bad and it solves the kernel compatibility issue.
By switching the runtime library to ifunc early, the future switch of instrumentation will not be an ABI break.

Speaking of ABI, I'm bumping the asan_version_mismatch thing on 32-bit android only. It looks a bit ugly,
but I think that not disturbing other platforms users is worth it.

eugenis marked an inline comment as done.Nov 7 2017, 4:23 PM
pcc accepted this revision.Nov 10 2017, 1:17 PM

Can you add a test that uses the -asan-with-ifunc flag?

LGTM with that.

eugenis updated this revision to Diff 122521.Nov 10 2017, 1:57 PM

Add a test.

pcc accepted this revision.Nov 10 2017, 2:00 PM

LGTM

This revision was automatically updated to reflect the committed changes.