This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Porting libsanitizer to Solaris (Was: Re: [PATCH][Revised] Enable libsanitizer on darwin)


Hi Alex,

> The quick answer is no, although the expansion into GCC world may
> require such a guideline.
> We've initially implemented ASan on Linux and then ported it to
> Android (which is very similar to Linux) and Mac (which is very
> different), so we have little experience with porting yet.
> I've summarized the differences between Linux and Mac here:
> https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForMacImplementationDetails
>
> The core things to pay attention at are function wrapping (e.g. dlsym
> on Linux, mach_override on Mac), hooking the allocations/deallocations
> in the program, stack unwinding (already done for x86 and ARM), thread
> creation, early initialization, debug info and symbolization. Maybe
> something else. In fact if any of these points work on your platform
> differently than they do on Linux/Mac, you'll have to re-implement
> those.
>
> Regarding mach_override, it's a Mac OS-specific thing that we use
> because dlsym doesn't reliably override functions (keywords: two-level
> namespace)
> This only works on x86/x86_64 and is just a bunch of ad-hoc hacks to
> hot-patch the library code.
> Extending the instruction table in mach_override.c is irrelevant to
> porting, it's just a mean of making it work with some newer libraries
> provided by Apple.
> It won't work on any other OS (well, without some refactoring; in fact
> it's possible to use it on Linux) or any other arch (one could rewrite
> mach_override.c for ARM, but iOS doesn't allow code patching).
>
> I'm working on a replacement for mach_override, which will compile
> libasan as a dynamic library on Mac OS and preload it before running
> the program.
> It's not ready yet, so the easiest thing for GCC will be to add some
> more instructions to mach_override and stick to it for now.

Thanks for those hints.  After a first start at a Solaris port of
libsanitizer when it was first integrated into the GCC tree, I've now
made very good progress.

I'm now down to just a few testsuite failures on Solaris 11.2 Beta:

* g++, 32-bit:

  c-c++-common/asan/misalign-1.c
  c-c++-common/asan/misalign-2.c
  c-c++-common/asan/null-deref-1.c
  c-c++-common/asan/swapcontext-test-1.c
  g++.dg/asan/deep-tail-call-1.C

* g++, 64-bit:

  c-c++-common/asan/global-overflow-1.c
  c-c++-common/asan/heap-overflow-1.c
  c-c++-common/asan/memcmp-1.c
  c-c++-common/asan/misalign-1.c
  c-c++-common/asan/misalign-2.c
  c-c++-common/asan/null-deref-1.c
  c-c++-common/asan/pr61530.c
  c-c++-common/asan/rlimit-mmap-test-1.c
  c-c++-common/asan/sanity-check-pure-c-1.c
  c-c++-common/asan/sleep-before-dying-1.c
  c-c++-common/asan/stack-overflow-1.c
  c-c++-common/asan/strip-path-prefix-1.c
  c-c++-common/asan/strlen-overflow-1.c
  c-c++-common/asan/strncpy-overflow-1.c
  c-c++-common/asan/swapcontext-test-1.c
  c-c++-common/asan/use-after-free-1.c
  c-c++-common/asan/use-after-return-1.c
  g++.dg/asan/deep-stack-uaf-1.C
  g++.dg/asan/deep-tail-call-1.C
  g++.dg/asan/deep-thread-stack-1.C
  g++.dg/asan/default-options-1.C
  g++.dg/asan/interception-failure-test-1.C
  g++.dg/asan/interception-test-1.C
  g++.dg/asan/large-func-test-1.C
  g++.dg/asan/pr55617.C
  c-c++-common/ubsan/float-cast-overflow-2.c
  c-c++-common/ubsan/float-cast-overflow-4.c

* gcc, 32-bit:

  c-c++-common/asan/misalign-1.c
  c-c++-common/asan/misalign-2.c
  c-c++-common/asan/null-deref-1.c
  c-c++-common/asan/swapcontext-test-1.c

* gcc, 64-bit:

  c-c++-common/asan/global-overflow-1.c
  c-c++-common/asan/heap-overflow-1.c
  c-c++-common/asan/memcmp-1.c
  c-c++-common/asan/misalign-1.c
  c-c++-common/asan/misalign-2.c
  c-c++-common/asan/null-deref-1.c
  c-c++-common/asan/pr61530.c
  c-c++-common/asan/rlimit-mmap-test-1.c
  c-c++-common/asan/sanity-check-pure-c-1.c
  c-c++-common/asan/sleep-before-dying-1.c
  c-c++-common/asan/stack-overflow-1.c
  c-c++-common/asan/strip-path-prefix-1.c
  c-c++-common/asan/strlen-overflow-1.c
  c-c++-common/asan/strncpy-overflow-1.c
  c-c++-common/asan/swapcontext-test-1.c
  c-c++-common/asan/use-after-free-1.c
  c-c++-common/asan/use-after-return-1.c
  gcc.dg/asan/nosanitize-and-inline.c
  c-c++-common/ubsan/float-cast-overflow-2.c
  c-c++-common/ubsan/float-cast-overflow-4.c

That's not too bad, I believe, and the 64-bit failures seem to be mostly
due to a single error.

The question is how best to proceed from here.  I'm attaching the
current patch for reference, though it's far from ready for submission
(no ChangeLog, no explanations for the issues found, several hacks that
need cleaning up), but it certainly is a start.

A few random observations about the port:

* From a porting point, I find it nightmarish that libsanitizer is
  completely platform-based (SANITIZER_<PLATFORM> all over the place)
  rather than feature-based (HAVE_<XYX>, irrespective of how the
  features are detected).

* Even this is not consistent: many places use SANITIZER_<PLATFORM>,
  others still __linux__/__FreeBSD__/...

* I couldn't find any explanation on the semantics and requirements of
  some of the runtime functions, like GetEnv and especially
  BlockingMutex.  Porting is mostly guesswork here, looking at other
  ports and hoping that what you infer from them is right.

Please note that I'll be moving to a new flat next week, so I will be
busy with other stuff for some time.  I just wanted to get this out of
the door for comments and suggestions.

	Rainer


# HG changeset patch
# Parent fed53c0b971e99ae5bf8f6143fa6ff42ca0bc404
Port to Solaris

diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
--- a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
@@ -96,71 +96,71 @@ main (void)
 /* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 128.5 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 132 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 256.5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 260 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -32773 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -32769.5 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 32768.5 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 32772 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 65536.5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 65540 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
@@ -176,10 +176,10 @@ main (void)
 /* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
@@ -198,7 +198,7 @@ main (void)
 /* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
 /* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Nn\]a\[Nn\] is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?\[Nn\]a\[Nn\] is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[Ii\]n\[Ff\] is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -\[Ii\]n\[Ff\] is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/libsanitizer/asan/asan_interceptors.h b/libsanitizer/asan/asan_interceptors.h
--- a/libsanitizer/asan/asan_interceptors.h
+++ b/libsanitizer/asan/asan_interceptors.h
@@ -22,18 +22,22 @@
 # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
 # define ASAN_INTERCEPT__LONGJMP 1
 # define ASAN_INTERCEPT_STRDUP 1
-# define ASAN_INTERCEPT_INDEX 1
 # define ASAN_INTERCEPT_PTHREAD_CREATE 1
 # define ASAN_INTERCEPT_MLOCKX 1
 #else
 # define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
 # define ASAN_INTERCEPT__LONGJMP 0
 # define ASAN_INTERCEPT_STRDUP 0
-# define ASAN_INTERCEPT_INDEX 0
 # define ASAN_INTERCEPT_PTHREAD_CREATE 0
 # define ASAN_INTERCEPT_MLOCKX 0
 #endif
 
+#if !SANITIZER_WINDOWS && !SANITIZER_SOLARIS
+# define ASAN_INTERCEPT_INDEX 1
+#else
+# define ASAN_INTERCEPT_INDEX 0
+#endif
+
 #if SANITIZER_FREEBSD || SANITIZER_LINUX
 # define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
 #else
diff --git a/libsanitizer/asan/asan_linux.cc b/libsanitizer/asan/asan_linux.cc
--- a/libsanitizer/asan/asan_linux.cc
+++ b/libsanitizer/asan/asan_linux.cc
@@ -11,7 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "sanitizer_common/sanitizer_platform.h"
-#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 
 #include "asan_interceptors.h"
 #include "asan_internal.h"
@@ -35,7 +35,11 @@
 #include <sys/link_elf.h>
 #endif
 
-#if SANITIZER_ANDROID || SANITIZER_FREEBSD
+#ifdef SANITIZER_SOLARIS
+#include <link.h>
+#endif
+
+#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
 #include <ucontext.h>
 extern "C" void* _DYNAMIC;
 #else
@@ -93,6 +97,17 @@ static int FindFirstDSOCallback(struct d
   if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
     return 0;
 
+#if SANITIZER_SOLARIS
+  if (0)
+    Report("info->dlpi_name = %s\tinfo->dlpi_addr = %x\n",
+	   info->dlpi_name, info->dlpi_addr);
+  return 0;
+
+  // Ignore executable on Solaris
+  if (info->dlpi_addr == 0)
+    return 0;
+#endif
+  
   *(const char **)data = info->dlpi_name;
   return 1;
 }
@@ -186,6 +201,15 @@ void GetPcSpBp(void *context, uptr *pc, 
   *sp = ucontext->uc_mcontext.mc_esp;
 # else
   ucontext_t *ucontext = (ucontext_t*)context;
+# ifndef REG_EIP
+#  define REG_EIP REG_PC
+# endif
+# ifndef REG_EBP
+#  define REG_EBP REG_FP
+# endif
+# ifndef REG_ESP
+#  define REG_ESP REG_SP
+# endif
   *pc = ucontext->uc_mcontext.gregs[REG_EIP];
   *bp = ucontext->uc_mcontext.gregs[REG_EBP];
   *sp = ucontext->uc_mcontext.gregs[REG_ESP];
@@ -243,4 +267,4 @@ void ReadContextStack(void *context, upt
 
 }  // namespace __asan
 
-#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
+#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
diff --git a/libsanitizer/asan/asan_malloc_linux.cc b/libsanitizer/asan/asan_malloc_linux.cc
--- a/libsanitizer/asan/asan_malloc_linux.cc
+++ b/libsanitizer/asan/asan_malloc_linux.cc
@@ -13,7 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "sanitizer_common/sanitizer_platform.h"
-#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 
 #include "sanitizer_common/sanitizer_tls_get_addr.h"
 #include "asan_allocator.h"
@@ -151,4 +151,4 @@ INTERCEPTOR(void, malloc_stats, void) {
   __asan_print_accumulated_stats();
 }
 
-#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
+#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
diff --git a/libsanitizer/asan/asan_poisoning.cc b/libsanitizer/asan/asan_poisoning.cc
--- a/libsanitizer/asan/asan_poisoning.cc
+++ b/libsanitizer/asan/asan_poisoning.cc
@@ -21,9 +21,13 @@ namespace __asan {
 void PoisonShadow(uptr addr, uptr size, u8 value) {
   if (!flags()->poison_heap) return;
   CHECK(AddrIsAlignedByGranularity(addr));
+#if !(SANITIZER_SOLARIS && defined(_LP64))
   CHECK(AddrIsInMem(addr));
+#endif
   CHECK(AddrIsAlignedByGranularity(addr + size));
+#if !(SANITIZER_SOLARIS && defined(_LP64))
   CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY));
+#endif
   CHECK(REAL(memset));
   FastPoisonShadow(addr, size, value);
 }
diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc
--- a/libsanitizer/asan/asan_rtl.cc
+++ b/libsanitizer/asan/asan_rtl.cc
@@ -555,6 +555,8 @@ static void AsanInitInternal() {
   CHECK(!asan_init_is_running && "ASan init calls itself!");
   asan_init_is_running = true;
 
+  InitializeAsanInterceptors();
+
   // Initialize flags. This must be done early, because most of the
   // initialization steps look at flags().
   const char *options = GetEnv("ASAN_OPTIONS");
@@ -591,7 +593,7 @@ static void AsanInitInternal() {
   // Setup internal allocator callback.
   SetLowLevelAllocateCallback(OnLowLevelAllocate);
 
-  InitializeAsanInterceptors();
+  //InitializeAsanInterceptors();
 
   ReplaceSystemMalloc();
 
diff --git a/libsanitizer/configure.tgt b/libsanitizer/configure.tgt
--- a/libsanitizer/configure.tgt
+++ b/libsanitizer/configure.tgt
@@ -38,6 +38,8 @@ case "${target}" in
   x86_64-*-darwin[1]* | i?86-*-darwin[1]*)
 	TSAN_SUPPORTED=no
 	;;
+  x86_64-*-solaris2* | i?86-*-solaris2*)
+	;;
   *)
 	UNSUPPORTED=1
 	;;
diff --git a/libsanitizer/interception/interception.h b/libsanitizer/interception/interception.h
--- a/libsanitizer/interception/interception.h
+++ b/libsanitizer/interception/interception.h
@@ -14,7 +14,8 @@
 #define INTERCEPTION_H
 
 #if !defined(__linux__) && !defined(__FreeBSD__) && \
-  !defined(__APPLE__) && !defined(_WIN32)
+  !defined(__APPLE__) && !defined(_WIN32) && \
+  !(defined(__sun__) && defined(__svr4__))
 # error "Interception doesn't work on this operating system."
 #endif
 
@@ -234,7 +235,7 @@ typedef unsigned long uptr;  // NOLINT
 
 #define INCLUDED_FROM_INTERCEPTION_LIB
 
-#if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) || (defined(__sun__) && defined(__svr4__))
 # include "interception_linux.h"
 # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
 # define INTERCEPT_FUNCTION_VER(func, symver) \
diff --git a/libsanitizer/interception/interception_linux.cc b/libsanitizer/interception/interception_linux.cc
--- a/libsanitizer/interception/interception_linux.cc
+++ b/libsanitizer/interception/interception_linux.cc
@@ -10,7 +10,7 @@
 // Linux-specific interception methods.
 //===----------------------------------------------------------------------===//
 
-#if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) || (defined(__sun__) && defined(__svr4__))
 #include "interception.h"
 
 #include <dlfcn.h>   // for dlsym() and dlvsym()
@@ -22,13 +22,14 @@ bool GetRealFunctionAddress(const char *
   return real == wrapper;
 }
 
-#if !defined(__ANDROID__)  // android does not have dlvsym
+// Android and Solaris do not have dlvsym
+#if !defined(__ANDROID__) && !(defined(__sun__) && defined(__svr4__))
 void *GetFuncAddrVer(const char *func_name, const char *ver) {
   return dlvsym(RTLD_NEXT, func_name, ver);
 }
-#endif  // !defined(__ANDROID__)
+#endif  // !__ANDROID__ && !(__sun__ && __svr4__)
 
 }  // namespace __interception
 
 
-#endif  // __linux__ || __FreeBSD__
+#endif  // __linux__ || __FreeBSD__ || (__sun__ && __svr4__)
diff --git a/libsanitizer/interception/interception_linux.h b/libsanitizer/interception/interception_linux.h
--- a/libsanitizer/interception/interception_linux.h
+++ b/libsanitizer/interception/interception_linux.h
@@ -10,7 +10,7 @@
 // Linux-specific interception methods.
 //===----------------------------------------------------------------------===//
 
-#if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) || (defined(__sun__) && defined(__svr4__))
 
 #if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
 # error "interception_linux.h should be included from interception library only"
@@ -32,14 +32,15 @@ void *GetFuncAddrVer(const char *func_na
       (::__interception::uptr) & (func),                                   \
       (::__interception::uptr) & WRAP(func))
 
-#if !defined(__ANDROID__)  // android does not have dlvsym
+// Android and Solaris do not have dlvsym
+#if !defined(__ANDROID__) && !(defined(__sun__) && defined(__svr4__))
 # define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
      ::__interception::real_##func = (func##_f)(unsigned long) \
          ::__interception::GetFuncAddrVer(#func, symver)
 #else
 # define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
      INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
-#endif  // !defined(__ANDROID__)
+#endif  // !__ANDROID__ && !(__sun__ && __svr4__)
 
 #endif  // INTERCEPTION_LINUX_H
-#endif  // __linux__ || __FreeBSD__
+#endif  // __linux__ || __FreeBSD__ || (__sun__ && __svr4__)
diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am
--- a/libsanitizer/sanitizer_common/Makefile.am
+++ b/libsanitizer/sanitizer_common/Makefile.am
@@ -37,6 +37,7 @@ sanitizer_common_files = \
 	sanitizer_printf.cc \
 	sanitizer_procmaps_linux.cc \
 	sanitizer_procmaps_mac.cc \
+	sanitizer_solaris.cc \
 	sanitizer_stackdepot.cc \
 	sanitizer_stacktrace.cc \
 	sanitizer_stacktrace_libcdep.cc \
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h
--- a/libsanitizer/sanitizer_common/sanitizer_common.h
+++ b/libsanitizer/sanitizer_common/sanitizer_common.h
@@ -511,7 +511,7 @@ const uptr kPthreadDestructorIterations 
 // Callback type for iterating over a set of memory ranges.
 typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
 
-#if (SANITIZER_FREEBSD || SANITIZER_LINUX) && !defined(SANITIZER_GO)
+#if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && !defined(SANITIZER_GO)
 extern uptr indirect_call_wrapper;
 void SetIndirectCallWrapper(uptr wrapper);
 
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -537,12 +537,14 @@ INTERCEPTOR(unsigned long, time, unsigne
 #if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
 static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
+#if !SANITIZER_SOLARIS
   if (tm->tm_zone) {
     // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
     // can point to shared memory and tsan would report a data race.
     COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
                                         REAL(strlen(tm->tm_zone)) + 1);
   }
+#endif
 }
 INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
   void *ctx;
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
@@ -45,7 +45,9 @@ static void ioctl_table_fill() {
     ++ioctl_table_size;                                  \
   }
 
+#if !SANITIZER_SOLARIS
   _(FIOASYNC, READ, sizeof(int));
+#endif
   _(FIOCLEX, NONE, 0);
   _(FIOGETOWN, WRITE, sizeof(int));
   _(FIONBIO, READ, sizeof(int));
@@ -71,7 +73,9 @@ static void ioctl_table_fill() {
   _(SIOCSIFMTU, READ, struct_ifreq_sz);
   _(SIOCSIFNETMASK, READ, struct_ifreq_sz);
   _(SIOCSPGRP, READ, sizeof(int));
+#if !SANITIZER_SOLARIS
   _(TIOCCONS, NONE, 0);
+#endif
   _(TIOCEXCL, NONE, 0);
   _(TIOCGETD, WRITE, sizeof(int));
   _(TIOCGPGRP, WRITE, pid_t_sz);
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc
--- a/libsanitizer/sanitizer_common/sanitizer_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc
@@ -24,7 +24,7 @@
 #include "sanitizer_stacktrace.h"
 #include "sanitizer_symbolizer.h"
 
-#if !SANITIZER_FREEBSD
+#if !SANITIZER_FREEBSD && !SANITIZER_SOLARIS
 #include <asm/param.h>
 #endif
 
@@ -37,7 +37,9 @@
 #include <pthread.h>
 #include <sched.h>
 #include <sys/mman.h>
+#if !SANITIZER_SOLARIS
 #include <sys/ptrace.h>
+#endif
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.h b/libsanitizer/sanitizer_common/sanitizer_linux.h
--- a/libsanitizer/sanitizer_common/sanitizer_linux.h
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.h
@@ -12,7 +12,7 @@
 #define SANITIZER_LINUX_H
 
 #include "sanitizer_platform.h"
-#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 #include "sanitizer_common.h"
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_platform_limits_posix.h"
@@ -87,5 +87,5 @@ void CacheBinaryName();
 void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
 }  // namespace __sanitizer
 
-#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
+#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 #endif  // SANITIZER_LINUX_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
--- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -11,7 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "sanitizer_platform.h"
-#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 
 #include "sanitizer_common.h"
 #include "sanitizer_flags.h"
@@ -35,6 +35,10 @@
 #define pthread_getattr_np pthread_attr_get_np
 #endif
 
+#if SANITIZER_SOLARIS
+#include <thread.h>
+#endif
+
 #if SANITIZER_LINUX
 #include <sys/prctl.h>
 #endif
@@ -72,7 +76,7 @@ void GetThreadStackTopAndBottom(bool at_
                                 uptr *stack_bottom) {
   CHECK(stack_top);
   CHECK(stack_bottom);
-  if (at_initialization) {
+  if (at_initialization && !SANITIZER_SOLARIS) {
     // This is the main thread. Libpthread may not be initialized yet.
     struct rlimit rl;
     CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
@@ -102,15 +106,22 @@ void GetThreadStackTopAndBottom(bool at_
     *stack_bottom = end - stacksize;
     return;
   }
+  uptr stacksize = 0;
+  void *stackaddr = 0;
+#if SANITIZER_SOLARIS
+  stack_t ss;
+  CHECK_EQ(thr_stksegment(&ss), 0);
+  stacksize = ss.ss_size;
+  stackaddr = ss.ss_sp - stacksize;
+#else // !SANITIZER_SOLARIS
   pthread_attr_t attr;
   pthread_attr_init(&attr);
   CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
-  uptr stacksize = 0;
-  void *stackaddr = 0;
   my_pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
   pthread_attr_destroy(&attr);
+  CHECK_LE(stacksize, kMaxThreadStackSize);  // Sanity check.
+#endif
 
-  CHECK_LE(stacksize, kMaxThreadStackSize);  // Sanity check.
   *stack_top = (uptr)stackaddr + stacksize;
   *stack_bottom = (uptr)stackaddr;
 }
@@ -279,7 +290,7 @@ static uptr g_tls_size;
 #endif
 
 void InitTlsSize() {
-#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID
+#if !SANITIZER_FREEBSD && !SANITIZER_SOLARIS && !SANITIZER_ANDROID
   typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
   get_tls_func get_tls;
   void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
@@ -291,7 +302,7 @@ void InitTlsSize() {
   size_t tls_align = 0;
   IndirectExternCall(get_tls)(&tls_size, &tls_align);
   g_tls_size = tls_size;
-#endif  // !SANITIZER_FREEBSD && !SANITIZER_ANDROID
+#endif  // !SANITIZER_FREEBSD && !SANITIZER_SOLARIS && !SANITIZER_ANDROID
 }
 
 #if (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX
@@ -399,6 +410,10 @@ static void GetTls(uptr *addr, uptr *siz
     *addr = (uptr) dtv[2];
     *size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]);
   }
+#elif SANITIZER_SOLARIS
+  // FIXME
+  *addr = 0;
+  *size = 0;
 #else
 # error "Unknown OS"
 #endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform.h b/libsanitizer/sanitizer_common/sanitizer_platform.h
--- a/libsanitizer/sanitizer_common/sanitizer_platform.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform.h
@@ -12,7 +12,8 @@
 #define SANITIZER_PLATFORM_H
 
 #if !defined(__linux__) && !defined(__FreeBSD__) && \
-  !defined(__APPLE__) && !defined(_WIN32)
+  !defined(__APPLE__) && !defined(_WIN32) && \
+  !(defined(__sun__) && defined(__svr4__))
 # error "This operating system is not supported"
 #endif
 
@@ -28,6 +29,12 @@
 # define SANITIZER_FREEBSD 0
 #endif
 
+#if defined(__sun__) && defined(__svr4__)
+# define SANITIZER_SOLARIS 1
+#else
+# define SANITIZER_SOLARIS 0
+#endif
+
 #if defined(__APPLE__)
 # define SANITIZER_MAC     1
 # include <TargetConditionals.h>
@@ -53,7 +60,7 @@
 # define SANITIZER_ANDROID 0
 #endif
 
-#define SANITIZER_POSIX (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC)
+#define SANITIZER_POSIX (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || SANITIZER_SOLARIS)
 
 #if __LP64__ || defined(_WIN64)
 #  define SANITIZER_WORDSIZE 64
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
--- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
@@ -45,6 +45,12 @@
 # define SI_IOS 0
 #endif
 
+#if SANITIZER_SOLARIS
+# define SI_SOLARIS 1
+#else
+# define SI_SOLARIS 0
+#endif
+
 #define SANITIZER_INTERCEPT_STRCMP 1
 #define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_STRCASECMP SI_NOT_WINDOWS
@@ -146,7 +152,7 @@
 #define SANITIZER_INTERCEPT_BACKTRACE SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_GETMNTENT SI_LINUX
 #define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID
-#define SANITIZER_INTERCEPT_STATFS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_STATFS SI_NOT_WINDOWS && !SI_SOLARIS
 #define SANITIZER_INTERCEPT_STATFS64 \
   (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_STATVFS SI_LINUX_NOT_ANDROID
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -12,7 +12,7 @@
 
 
 #include "sanitizer_platform.h"
-#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_SOLARIS
 
 #include <arpa/inet.h>
 #include <dirent.h>
@@ -160,6 +160,13 @@
 #include <sys/sockio.h>
 #endif
 
+#if SANITIZER_SOLARIS
+#include <sys/filio.h>
+#include <sys/sockio.h>
+#include <sys/ptyvar.h>
+#include <sys/ethernet.h>
+#endif
+
 // Include these after system headers to avoid name clashes and ambiguities.
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_platform_limits_posix.h"
@@ -189,7 +196,9 @@ namespace __sanitizer {
   unsigned struct_tms_sz = sizeof(struct tms);
   unsigned struct_sigevent_sz = sizeof(struct sigevent);
   unsigned struct_sched_param_sz = sizeof(struct sched_param);
+#if !SANITIZER_SOLARIS
   unsigned struct_statfs_sz = sizeof(struct statfs);
+#endif
 
 #if SANITIZER_MAC && !SANITIZER_IOS
   unsigned struct_statfs64_sz = sizeof(struct statfs64);
@@ -391,14 +400,16 @@ namespace __sanitizer {
   unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
 #endif  // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
 
-#if !SANITIZER_ANDROID && !SANITIZER_MAC
+#if !SANITIZER_ANDROID && !SANITIZER_MAC && !SANITIZER_SOLARIS
   unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
   unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
 #endif
 
   unsigned IOCTL_NOT_PRESENT = 0;
 
+#if !SANITIZER_SOLARIS
   unsigned IOCTL_FIOASYNC = FIOASYNC;
+#endif
   unsigned IOCTL_FIOCLEX = FIOCLEX;
   unsigned IOCTL_FIOGETOWN = FIOGETOWN;
   unsigned IOCTL_FIONBIO = FIONBIO;
@@ -424,7 +435,9 @@ namespace __sanitizer {
   unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
   unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
   unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+#if !SANITIZER_SOLARIS
   unsigned IOCTL_TIOCCONS = TIOCCONS;
+#endif
   unsigned IOCTL_TIOCEXCL = TIOCEXCL;
   unsigned IOCTL_TIOCGETD = TIOCGETD;
   unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
@@ -1013,8 +1026,10 @@ CHECK_SIZE_AND_OFFSET(tm, tm_year);
 CHECK_SIZE_AND_OFFSET(tm, tm_wday);
 CHECK_SIZE_AND_OFFSET(tm, tm_yday);
 CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
+#if !SANITIZER_SOLARIS
 CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
 CHECK_SIZE_AND_OFFSET(tm, tm_zone);
+#endif
 
 #if SANITIZER_LINUX
 CHECK_TYPE_SIZE(mntent);
@@ -1062,7 +1077,7 @@ CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next)
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
-#if SANITIZER_LINUX || SANITIZER_FREEBSD
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_SOLARIS
 // Compare against the union, because we can't reach into the union in a
 // compliant way.
 #ifdef ifa_dstaddr
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -254,7 +254,12 @@ namespace __sanitizer {
   struct __sanitizer_ifaddrs {
     struct __sanitizer_ifaddrs *ifa_next;
     char *ifa_name;
+#if SANITIZER_SOLARIS
+    // uint64_t
+    u64 ifa_flags;
+#else
     unsigned int ifa_flags;
+#endif
     void *ifa_addr;    // (struct sockaddr *)
     void *ifa_netmask; // (struct sockaddr *)
     // This is a union on Linux.
@@ -291,8 +296,17 @@ namespace __sanitizer {
   struct __sanitizer_passwd {
     char *pw_name;
     char *pw_passwd;
+#if !SANITIZER_SOLARIS
     int pw_uid;
     int pw_gid;
+#else
+    // uid_t
+    unsigned int pw_uid;
+    // gid_t
+    unsigned int pw_gid;
+    char *pw_age;
+    char *pw_comment;
+#endif 
 #if SANITIZER_MAC || SANITIZER_FREEBSD
     long pw_change;
     char *pw_class;
@@ -344,8 +358,10 @@ namespace __sanitizer {
     int tm_wday;
     int tm_yday;
     int tm_isdst;
+#if !SANITIZER_SOLARIS
     long int tm_gmtoff;
     const char *tm_zone;
+#endif
   };
 
 #if SANITIZER_LINUX
@@ -359,7 +375,7 @@ namespace __sanitizer {
   };
 #endif
 
-#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD
+#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_SOLARIS
   struct __sanitizer_msghdr {
     void *msg_name;
     unsigned msg_namelen;
@@ -488,24 +504,35 @@ namespace __sanitizer {
      // uint32_t * 4
      unsigned int __bits[4];
   };
+#elif SANITIZER_SOLARIS
+  // From <sys/signal.h>.
+  struct __sanitizer_sigset_t {
+    unsigned int __bits[4];
+  };
 #endif
 
   // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
   struct __sanitizer_sigaction {
+#if SANITIZER_SOLARIS
+    int sa_flags;
+#endif
     union {
       void (*sigaction)(int sig, void *siginfo, void *uctx);
       void (*handler)(int sig);
     };
 #if SANITIZER_FREEBSD
     int sa_flags;
+#endif
     __sanitizer_sigset_t sa_mask;
-#else
-    __sanitizer_sigset_t sa_mask;
+#if !SANITIZER_FREEBSD && !SANITIZER_SOLARIS
     int sa_flags;
 #endif
 #if SANITIZER_LINUX
     void (*sa_restorer)();
 #endif
+#if SANITIZER_SOLARIS && !defined(_LP64)
+    int sa_resv[2];
+#endif
   };
 
 #if SANITIZER_FREEBSD
@@ -553,7 +580,7 @@ namespace __sanitizer {
     int ai_family;
     int ai_socktype;
     int ai_protocol;
-#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD
+#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_SOLARIS
     unsigned ai_addrlen;
     char *ai_canonname;
     void *ai_addr;
@@ -631,6 +658,10 @@ namespace __sanitizer {
     char *we_strings;
     uptr we_nbytes;
 #endif
+#if SANITIZER_SOLARIS
+    char **we_wordp;
+    int we_wordn;
+#endif
   };
 
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
@@ -860,7 +891,9 @@ struct __sanitizer_obstack {
   extern unsigned IOCTL_SIOCSIFMTU;
   extern unsigned IOCTL_SIOCSIFNETMASK;
   extern unsigned IOCTL_SIOCSPGRP;
+#if !SANITIZER_SOLARIS
   extern unsigned IOCTL_TIOCCONS;
+#endif
   extern unsigned IOCTL_TIOCEXCL;
   extern unsigned IOCTL_TIOCGETD;
   extern unsigned IOCTL_TIOCGPGRP;
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
--- a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
@@ -39,7 +39,12 @@ uptr GetThreadSelf() {
 }
 
 void FlushUnneededShadowMemory(uptr addr, uptr size) {
+#if SANITIZER_SOLARIS
+  // FIXME: explain
+  madvise((caddr_t)addr, size, MADV_DONTNEED);
+#else
   madvise((void*)addr, size, MADV_DONTNEED);
+#endif
 }
 
 void DisableCoreDumper() {
diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps.h b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
--- a/libsanitizer/sanitizer_common/sanitizer_procmaps.h
+++ b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
@@ -18,13 +18,13 @@
 
 namespace __sanitizer {
 
-#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 struct ProcSelfMapsBuff {
   char *data;
   uptr mmaped_size;
   uptr len;
 };
-#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
+#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 
 class MemoryMappingLayout {
  public:
@@ -53,7 +53,7 @@ class MemoryMappingLayout {
 
   // FIXME: Hide implementation details for different platforms in
   // platform-specific files.
-# if SANITIZER_FREEBSD || SANITIZER_LINUX
+# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
   ProcSelfMapsBuff proc_self_maps_;
   char *current_;
 
diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc b/libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc
--- a/libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc
@@ -9,7 +9,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "sanitizer_platform.h"
-#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
 #include "sanitizer_common.h"
 #include "sanitizer_placement_new.h"
 #include "sanitizer_procmaps.h"
@@ -20,6 +20,11 @@
 #include <sys/user.h>
 #endif
 
+#if SANITIZER_SOLARIS
+#include <procfs.h>
+#include <limits.h>
+#endif
+
 namespace __sanitizer {
 
 // Linker initialized.
@@ -43,6 +48,9 @@ static void ReadProcMaps(ProcSelfMapsBuf
   proc_maps->data = (char*)VmMap;
   proc_maps->mmaped_size = MmapedSize;
   proc_maps->len = Size;
+#elif SANITIZER_SOLARIS
+  proc_maps->len = ReadFileToBuffer("/proc/self/xmap", &proc_maps->data,
+                                    &proc_maps->mmaped_size, 1 << 26);
 #else
   proc_maps->len = ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
                                     &proc_maps->mmaped_size, 1 << 26);
@@ -187,7 +195,29 @@ bool MemoryMappingLayout::Next(uptr *sta
   }
 
   current_ += VmEntry->kve_structsize;
-#else  // !SANITIZER_FREEBSD
+#elif SANITIZER_SOLARIS
+  prxmap_t *xmapentry = (prxmap_t*)current_;
+
+  *start = (uptr)xmapentry->pr_vaddr;
+  *end = (uptr)(xmapentry->pr_vaddr + xmapentry->pr_size);
+  *offset = (uptr)xmapentry->pr_offset;
+
+  *protection = 0;
+  if ((xmapentry->pr_mflags & MA_READ) != 0)
+    *protection |= kProtectionRead;
+  if ((xmapentry->pr_mflags & MA_WRITE) != 0)
+    *protection |= kProtectionWrite;
+  if ((xmapentry->pr_mflags & MA_EXEC) != 0)
+    *protection |= kProtectionExecute;
+
+  if (filename != NULL && filename_size > 0) {
+    internal_snprintf(filename,
+                      Min(filename_size, (uptr)PATH_MAX),
+                      "%s", xmapentry->pr_mapname);
+  }
+
+  current_ += sizeof(prxmap_t);
+#else  // !SANITIZER_FREEBSD && !SANITIZER_SOLARIS
   char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
   if (next_line == 0)
     next_line = last;
diff --git a/libsanitizer/sanitizer_common/sanitizer_solaris.cc b/libsanitizer/sanitizer_common/sanitizer_solaris.cc
new file mode 100644
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_solaris.cc
@@ -0,0 +1,215 @@
+//===-- sanitizer_solaris.cc ----------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries and
+// implements Solaris-specific functions.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_SOLARIS
+
+#include <stdio.h>
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+namespace __sanitizer {
+
+#include "sanitizer_syscall_generic.inc"
+
+// ---------------------- sanitizer_libc.h
+uptr internal_mmap(void *addr, uptr /*size_t*/ length, int prot, int flags,
+                   int fd, u64 offset) {
+  return (uptr)mmap(addr, length, prot, flags, fd, offset);
+}
+
+uptr internal_munmap(void *addr, uptr length) {
+  return munmap(addr, length);
+}
+
+uptr internal_close(fd_t fd) {
+  return close(fd);
+}
+
+uptr internal_open(const char *filename, int flags) {
+  return open(filename, flags);
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+  return open(filename, flags, mode);
+}
+
+uptr OpenFile(const char *filename, bool write) {
+  return internal_open(filename,
+      write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
+}
+
+uptr internal_read(fd_t fd, void *buf, uptr count) {
+  return read(fd, buf, count);
+}
+
+uptr internal_write(fd_t fd, const void *buf, uptr count) {
+  return write(fd, buf, count);
+}
+
+uptr internal_stat(const char *path, void *buf) {
+  return stat(path, (struct stat *)buf);
+}
+
+uptr internal_lstat(const char *path, void *buf) {
+  return lstat(path, (struct stat *)buf);
+}
+
+uptr internal_fstat(fd_t fd, void *buf) {
+  return fstat(fd, (struct stat *)buf);
+}
+
+uptr internal_filesize(fd_t fd) {
+  struct stat st;
+  if (internal_fstat(fd, &st))
+    return -1;
+  return (uptr)st.st_size;
+}
+
+uptr internal_dup2(int oldfd, int newfd) {
+  return dup2(oldfd, newfd);
+}
+
+uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
+  return readlink(path, buf, bufsize);
+}
+
+uptr internal_sched_yield() {
+  return sched_yield();
+}
+
+void internal__exit(int exitcode) {
+  _exit(exitcode);
+}
+
+uptr internal_getpid() {
+  return getpid();
+}
+
+int internal_fork() {
+  // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
+  return fork();
+}
+
+// ----------------- sanitizer_common.h
+bool FileExists(const char *filename) {
+  struct stat st;
+  if (stat(filename, &st))
+    return false;
+  // Sanity check: filename is a regular file.
+  return S_ISREG(st.st_mode);
+}
+
+uptr GetTid() {
+  return (uptr)pthread_self();
+}
+
+const char *GetEnv(const char *name) {
+  // FIXME: Need non-libc implementation?
+  return getenv(name);
+}
+
+void ReExec() {
+  UNIMPLEMENTED();
+}
+
+void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
+  (void)args;
+  // Nothing here for now.
+}
+
+uptr GetPageSize() {
+  return sysconf(_SC_PAGESIZE);
+}
+
+BlockingMutex::BlockingMutex(LinkerInitialized) {
+  CHECK_EQ(owner_, 0);
+  CHECK_EQ(pthread_mutex_init((pthread_mutex_t *)&opaque_storage_, NULL), 0);
+}
+
+BlockingMutex::BlockingMutex() {
+  internal_memset(this, 0, sizeof(*this));
+  CHECK_EQ(pthread_mutex_init((pthread_mutex_t *)&opaque_storage_, NULL), 0);
+}
+
+void BlockingMutex::Lock() {
+  CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_));
+  CHECK_NE(owner_, (uptr)pthread_self());
+  CHECK_EQ(pthread_mutex_lock((pthread_mutex_t *)&opaque_storage_), 0);
+  CHECK(!owner_);
+  owner_ = (uptr)pthread_self();
+}
+
+void BlockingMutex::Unlock() {
+  CHECK(owner_ == (uptr)pthread_self());
+  owner_ = 0;
+  CHECK_EQ(pthread_mutex_unlock((pthread_mutex_t *)&opaque_storage_), 0);
+}
+
+void BlockingMutex::CheckLocked() {
+  CHECK_EQ((uptr)pthread_self(), owner_);
+}
+
+u64 NanoTime() {
+  return gethrtime();
+}
+
+bool IsDeadlySignal(int signum) {
+  return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
+}
+
+static char proc_self_exe_cache_str[kMaxPathLength];
+static uptr proc_self_exe_cache_len = 0;
+
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+  const char *execname = getexecname();
+  uptr module_name_len;
+  if (execname != 0) {
+    module_name_len = internal_snprintf(buf, buf_len, execname);
+  } else {
+    if (proc_self_exe_cache_len) {
+      // If available, use the cached module name.
+      CHECK_LE(proc_self_exe_cache_len, buf_len);
+      internal_strncpy(buf, proc_self_exe_cache_str, buf_len);
+      module_name_len = internal_strlen(proc_self_exe_cache_str);
+    } else {
+      // We can't determine execname for some reason, assume the name of the
+      // binary is unknown.
+      Report("WARNING: getexecname() failed, "
+             "some stack frames may not be symbolized\n");
+      module_name_len = 0;
+    }
+    CHECK_LT(module_name_len, buf_len);
+    buf[module_name_len] = '\0';
+  }
+  return module_name_len;
+}
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_SOLARIS
diff --git a/libsanitizer/ubsan/ubsan_value.h b/libsanitizer/ubsan/ubsan_value.h
--- a/libsanitizer/ubsan/ubsan_value.h
+++ b/libsanitizer/ubsan/ubsan_value.h
@@ -12,9 +12,10 @@
 #ifndef UBSAN_VALUE_H
 #define UBSAN_VALUE_H
 
-// For now, only support Linux, FreeBSD and Darwin. Other platforms should
-// be easy to add, and probably work as-is.
-#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__APPLE__)
+// For now, only support Linux, FreeBSD, Darwin, and Solaris. Other platforms
+// should be easy to add, and probably work as-is.
+#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__APPLE__) && \
+  !(defined(__sun__) && defined(__svr4__))
 #error "UBSan not supported for this platform!"
 #endif
 
-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]