Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Support Solaris in sanitizers #32246

Open Quuxplusone opened 7 years ago

Quuxplusone commented 7 years ago
Bugzilla Link PR33274
Status NEW
Importance P enhancement
Reported by Rainer Orth (ro@gcc.gnu.org)
Reported on 2017-06-02 01:25:07 -0700
Last modified on 2019-07-08 15:29:16 -0700
Version unspecified
Hardware All Solaris
CC alekseyshlgit@gmail.com, fedor.v.sergeev@gmail.com, kcc@google.com, llvm-bugs@lists.llvm.org, n54@gmx.com, petr.sumbera@oracle.com
Fixed by commit(s)
Attachments libsanitizer-interception-macros.patch (11437 bytes, text/plain)
sol2-libsanitizer-basic.patch (75721 bytes, text/plain)
solx86-sanitizer-basic-compiler-rt.patch (5142 bytes, text/plain)
clang.patch (2237 bytes, text/plain)
Blocks
Blocked by
See also
Over the last 3 years, I've been working on and off on a port of the sanitizers
to Solaris (both sparc and x86).  This work has mostly been done within gcc
(firstly since I'm most familiar with that development environment; I happen to
be the GCC Solaris maintainer, but also as it turns out that Solaris support in
LLVM is in a bad state to be almost unusable as a foundation for the sanitizer
port).

Yesterday, I've made a new attempt after a year, based on libsanitizer in GCC
mainline (which is a mostly unmodified import from LLVM r285547) and achieved
good (i386-pc-solaris2.12) and reasonable (sparc-sun-solaris2.12) results with
the GCC sanitizer testsuite ({g++.dg,gcc.dg}/*san/*san.exp) (32-bit only):

On Solaris 12/x86, the remaining failures are:

* g++:

c-c++-common/asan/swapcontext-test-1.c
g++.dg/asan/default-options-1.C

* gcc:

c-c++-common/asan/swapcontext-test-1.c

On Solaris 12/SPARC, there are some more:

* g++:

c-c++-common/asan/global-overflow-1.c
c-c++-common/asan/heap-overflow-1.c
c-c++-common/asan/misalign-1.c
c-c++-common/asan/misalign-2.c
c-c++-common/asan/stack-overflow-1.c
c-c++-common/asan/use-after-free-1.c
g++.dg/asan/default-options-1.C
g++.dg/asan/large-func-test-1.C

* gcc:

c-c++-common/asan/global-overflow-1.c
c-c++-common/asan/heap-overflow-1.c
c-c++-common/asan/misalign-1.c
c-c++-common/asan/misalign-2.c
c-c++-common/asan/stack-overflow-1.c
c-c++-common/asan/use-after-free-1.c

which are mostly due to line number mismatches.

As mentioned above, the port is currently 32-bit-only.  This is due to the fact
that Solaris uses a discontinuous address space layout on 64-bit

http://docs.oracle.com/cd/E53394_01/html/E61689/advanced-2.html#SSFDGadvanced-5
http://docs.oracle.com/cd/E53394_01/html/E61689/fcowb.html#SSFDGfcpaf

and the shadow memory calculation cannot currently cope with that AFAICS.
However, on a recent Solaris 12 build, the x86 port changed to continuous
layout, so a 64-port should be relatively easy.  This won't help for sparc,
though, neither for Solaris 10 and 11.  To make matters worse, the exact
location of the VA hole is dependent on the exact platform at least on sparc.

To get the ball rolling, I'll be attaching my current set of patches (based,
as I said, on what's currently in GCC mainline's libsanitizer directory), so
we can discuss if they are (if updated for LLVM trunk) in any way appropriate
for commit into compiler-rt).  Otherwise, I believe there's no way to get them
into GCC.

On the LLVM side of things, I understand that there's currently work going on
to provide patches for proper Solaris support on LLVM mainline.  Once that
lands, I can see to beat my current patches for sanitizer support outside of
compiler-rt into a usable form.

  Rainer
Quuxplusone commented 7 years ago

Attached libsanitizer-interception-macros.patch (11437 bytes, text/plain): ``` Use SANITIZER_* macros in libsanitizer/interception

Quuxplusone commented 7 years ago

Attached sol2-libsanitizer-basic.patch (75721 bytes, text/plain): Basic libsanitizer Solaris support

Quuxplusone commented 7 years ago

Attached solx86-sanitizer-basic-compiler-rt.patch (5142 bytes, text/plain): Basic sanitizer Solaris support: x86 compiler-rt side

Quuxplusone commented 7 years ago

Attached clang.patch (2237 bytes, text/plain): Basic sanitizer Solaris support: x86 clang side

Quuxplusone commented 7 years ago
Hi Rainer,

I'm afraid that no one will be looking at the patches here.
Our work flow for the patches is to use http://llvm.org/docs/Phabricator.html

Some guidelines:
* the smaller the individual patch is the better.
* for files that have no #ifdefs don't add new #ifdefs
* you may need to add some files named *_solaris.cc
* add tests

Will there be a public build bot with solaris?
W/o such, the effort is a moot point because we will break it quickly and won't
even notice.
Quuxplusone commented 7 years ago
(In reply to Kostya Serebryany from comment #5)
Hi Kostya,

> I'm afraid that no one will be looking at the patches here.

I suspected that much, but given that they are not yet based on llvm
trunk and the latter is practically unusable on Solaris, I feared there
would yet not be much point in posting them to llvm-commits or ...

> Our work flow for the patches is to use http://llvm.org/docs/Phabricator.html

... Phabricator.  In fact, I'm currently trying to get my first one-line
patch through the system there (https://reviews.llvm.org/D33716).  Right
now I'm looking for guidance on how to proceed.  Or do you think there's
any point in posting the current state of the patch there to get some
feedback early?

What I could try is merge llvm trunk libsanitizer into the gcc tree
(which should be readily doable since the ASan ABI is unchanged between
current gcc mainline and llvm trunk).  Then I'd have an environment
where I can readily check a trunk port.

> Some guidelines:
> * the smaller the individual patch is the better.

Fully understood.  However, I fear there's no good way to split the main
sanitizer patch further.  A large part of is mechanical (adding
"|| SANITIZER_SOLARIS" in the appropriate places) .

> * for files that have no #ifdefs don't add new #ifdefs

I think I've avoided that, but will double-check.

> * you may need to add some files named *_solaris.cc

Sure: already done with sanitizer_common/sanitizer_solaris.cc.  There
was no other point

> * add tests

What tests would that be?  Currently, this is just a straightforward
port to another OS, so functionality should be well tested by the
regular testsuite.

> Will there be a public build bot with solaris?

I'm in no position to run such a thing.  While I do run daily gcc
bootstraps, I certainly cannot act as Solaris maintainer for yet another
compiler (which this would boil down to).

I expect that once Oracle is ready to submit their clean port of llvm to
Solaris, they will be running such a thing.  Once this happens, the
sanitizers will be tested adequately, too.  I'll probably manually run
an llvm build (say) once in a fortnight or something.

> W/o such, the effort is a moot point because we will break it quickly and
won't
> even notice.

Understood.  You already mention that on
https://github.com/google/sanitizers/wiki/AddressSanitizerHowToContribute.
At the very latest, I'd notice breakage as soon as another merge into
gcc happens.  And while llvm is in no good state on Solaris, there's not
much point in testing there.

I'll certainly be around in case the Solaris port causes problems for
other platforms.

    Rainer
Quuxplusone commented 7 years ago
> > Will there be a public build bot with solaris?
> I expect that once Oracle is ready to submit their clean port of llvm to
> Solaris, they will be running such a thing.
This is true.
We just started discussions about build bot with Anton Korobeynikov.

I do not expect this to happen super fast, but hopefully in a matter of a month
or two.
Quuxplusone commented 7 years ago

Please send it to http://reviews.llvm.org/ with "git diff -U999"

I'm just starting to work on sanitizers for NetBSD and I would like to base on your cleanups.

For Solaris please keep using "#ifdef sun", rather than "sun__", as this is more portable to older/other SunOS systems.

Quuxplusone commented 5 years ago
I see that this was partially committed here:

https://github.com/llvm/llvm-project/commit/85da0f6fb5e8009721c5079ab78c531bd5d55733

And probably because of it simple clang (LLVM/CLANG 8.0) fails for both Intel
and SPARC:

$ clang test.c
ld: fatal: file /usr/lib/amd64/clang/8.0.0/lib/sunos/libclang_rt.sancov_begin-
x86_64.a: open failed: No such file or directory
ld: fatal: file /usr/lib/amd64/clang/8.0.0/lib/sunos/libclang_rt.sancov_end-
x86_64.a: open failed: No such file or directory
clang-8: error: linker command failed with exit code 1 (use -v to see
invocation)

Following helps:

--- llvm-8.0.0/tools/clang/lib/Driver/ToolChains/Solaris.cpp
+++ llvm-8.0.0/tools/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -97,12 +97,14 @@
         Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
   }

+#if 0
   // Provide __start___sancov_guards.  Solaris ld doesn't automatically create
   // __start_SECNAME labels.
   CmdArgs.push_back("--whole-archive");
   CmdArgs.push_back(
       getToolChain().getCompilerRTArgString(Args, "sancov_begin", false));
   CmdArgs.push_back("--no-whole-archive");
+#endif

   getToolChain().AddFilePathLibArgs(Args, CmdArgs);

@@ -132,12 +134,14 @@
       linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
   }

+#if 0
   // Provide __stop___sancov_guards.  Solaris ld doesn't automatically create
   // __stop_SECNAME labels.
   CmdArgs.push_back("--whole-archive");
   CmdArgs.push_back(
       getToolChain().getCompilerRTArgString(Args, "sancov_end", false));
   CmdArgs.push_back("--no-whole-archive");
+#endif

   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
     CmdArgs.push_back(

Any idea for proper fix?
Quuxplusone commented 5 years ago
(In reply to Petr Sumbera from comment #9)
> I see that this was partially committed here:
>
> https://github.com/llvm/llvm-project/commit/
> 85da0f6fb5e8009721c5079ab78c531bd5d55733
>
> And probably because of it simple clang (LLVM/CLANG 8.0) fails for both
> Intel and SPARC:
>
> $ clang test.c
> ld: fatal: file
> /usr/lib/amd64/clang/8.0.0/lib/sunos/libclang_rt.sancov_begin-x86_64.a: open
> failed: No such file or directory
> ld: fatal: file
> /usr/lib/amd64/clang/8.0.0/lib/sunos/libclang_rt.sancov_end-x86_64.a: open
> failed: No such file or directory
> clang-8: error: linker command failed with exit code 1 (use -v to see
> invocation)

That's weird: in a self-compiled llvm 8.0.0, I have those files for both i386
and x86_64 and the above command works fine.

In a sparc build, I see the same, which is no wonder given that compiler-rt
isn't built on sparc (yet).

> Following helps:
>
> --- llvm-8.0.0/tools/clang/lib/Driver/ToolChains/Solaris.cpp
> +++ llvm-8.0.0/tools/clang/lib/Driver/ToolChains/Solaris.cpp
> @@ -97,12 +97,14 @@
>          Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
>    }
>
> +#if 0
>    // Provide __start___sancov_guards.  Solaris ld doesn't automatically
> create
>    // __start_SECNAME labels.
>    CmdArgs.push_back("--whole-archive");
>    CmdArgs.push_back(
>        getToolChain().getCompilerRTArgString(Args, "sancov_begin", false));
>    CmdArgs.push_back("--no-whole-archive");
> +#endif
>
>    getToolChain().AddFilePathLibArgs(Args, CmdArgs);
>
> @@ -132,12 +134,14 @@
>        linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
>    }
>
> +#if 0
>    // Provide __stop___sancov_guards.  Solaris ld doesn't automatically
> create
>    // __stop_SECNAME labels.
>    CmdArgs.push_back("--whole-archive");
>    CmdArgs.push_back(
>        getToolChain().getCompilerRTArgString(Args, "sancov_end", false));
>    CmdArgs.push_back("--no-whole-archive");
> +#endif
>
>    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
>      CmdArgs.push_back(
>

It would and is ok on Solaris 11.4 and beyond where ld provides those
__{start,stop}___sancov_guards symbols out of the box.

> Any idea for proper fix?

There are other issues with that change, and given that LLVM already uses
a couple of Solaris 11.4+ only features, I've submitted two patches to get
rid of those archives:

        https://reviews.llvm.org/D63601
        https://reviews.llvm.org/D63602

I'll ping them in time and hope to get them into LLVM 9.0.0 this August.

  Rainer
Quuxplusone commented 5 years ago

Both of those patches just went into LLVM trunk, so will be in the 9.0.0 release.