radr://12777299, "potential pthread/eh bug exposed by libsanitizer"

Nick,
   Can you take a quick look at the asan_eh_bug.tar.bz testcase
I uploaded into the newly opened radr://12777299, "potential
pthread/eh bug exposed by libsanitizer". The FSF gcc developers
have ported llvm.org's asan code into FSF gcc (and are keeping
it synced to the upstream llvm.org code). I have been helping
with the darwin build and testing -fsanitize=address against the
complete FSF gcc testsuite. This seems to have exposed a potential
bug in pthread or eh on darwin under libasan. Hundreds of test cases
in the g++ and libstdc++ testsuites fail under -fsanitize=address
in the following manner...

ASAN:SIGSEGV

+glider
The compiler hardly matters here, I would expect the same failures with clang.
Alex, could you please take a look?

–kcc

Jack, can you please upload this test somewhere?

If this is the same test:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/eh/cond1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1,
then it doesn't fail for me on Mac OS 10.8 with ASan (Clang r168632)
Have you tried symbolizing the report?

+glider
The compiler hardly matters here, I would expect the same failures with
clang.
Alex, could you please take a look?

--kcc

Kostya,
    The problem is that clang uses a very different and older libstdc++ than FSF gcc so
that the code exection path is very different. For example...

% /sw/opt/llvm-3.2/bin/clang++ -fsanitize=address -std=c++98 cond1.C -g -O0 -o cond1_asan_clang.exe
% gdb ./cond1_asan_clang.exe
...
(gdb) break main
Breakpoint 1 at 0x100001bc4: file cond1.C, line 21.
(gdb) r
...
Breakpoint 1, main (argc=<value temporarily unavailable, due to optimizations>, argv=0x7fff5fbfe5a0) at cond1.C:21
21 (argc+1 ? has_destructor() : throw 0);
(gdb) s
has_destructor::~has_destructor (this=<value temporarily unavailable, due to optimizations>) at cond1.C:10
10 ~has_destructor() { }
(gdb)
has_destructor::~has_destructor (this=<value temporarily unavailable, due to optimizations>) at cond1.C:10
10 ~has_destructor() { }
(gdb)
0x00000001000084e8 in has_destructor::~has_destructor (this=<value temporarily unavailable, due to optimizations>) at cond1.C:10
10 ~has_destructor() { }
(gdb)
main (argc=<value temporarily unavailable, due to optimizations>, argv=<value temporarily unavailable, due to optimizations>) at cond1.C:22
22 CI((argc+1 ? throw 0 : has_destructor()));
(gdb)

Program exited normally.

whereas for FSF gcc...

% g++-fsf-4.8 -static-libasan -fsanitize=address -std=c++98 cond1.C -g -O0 -o cond1_asan.exe
% gdb ./cond1_asan.exe
...
(gdb) break main
Breakpoint 1 at 0x100001b35: file cond1.C, line 21.
(gdb) r
Starting program: /Users/howarth/asan_eh_bug/cond1_asan.exe
Reading symbols for shared libraries ++++................................. done

Breakpoint 1, main (argc=1, argv=0x7fff5fbff898) at cond1.C:21
21 (argc+1 ? has_destructor() : throw 0);
(gdb) s
has_destructor::~has_destructor (this=0x7fff5fbff7cf) at cond1.C:10
10 ~has_destructor() { }
(gdb)
main (argc=1, argv=0x7fff5fbff898) at cond1.C:22
22 CI((argc+1 ? throw 0 : has_destructor()));
(gdb)
__cxa_allocate_exception (thrown_size=132) at ../../../../gcc-4.8-20121127/libstdc++-v3/libsupc++/eh_alloc.cc:102
102 ret = malloc (thrown_size);
(gdb)
0x00000001022b60da in dyld_stub_malloc () at ../../../../gcc-4.8-20121127/libstdc++-v3/libsupc++/eh_alloc.cc:204
204 __cxxabiv1::__cxa_free_dependent_exception
(gdb)
0x00007fff8bd80878 in dyld_stub_binder ()
(gdb)
Single stepping until exit from function dyld_stub_binder,
which has no line number information.
0x00007fff8bd808a5 in misaligned_stack_error_entering_dyld_stub_binder ()
(gdb)
Single stepping until exit from function misaligned_stack_error_entering_dyld_stub_binder,
which has no line number information.
0x00007fff8bd808e1 in dyld_stub_binder_ ()
(gdb)
Single stepping until exit from function dyld_stub_binder_,
which has no line number information.
0x00007fff8bd81f61 in _dyld_fast_stub_entry ()
(gdb)
Single stepping until exit from function _Z21_dyld_fast_stub_entryPvl,
which has no line number information.
0x00007fff5fc03fbd in __dyld__ZN4dyld18fastBindLazySymbolEPP11ImageLoaderm ()
(gdb)
Single stepping until exit from function __dyld__ZN4dyld18fastBindLazySymbolEPP11ImageLoaderm,
which has no line number information.
0x00007fff8bd808ee in dyld_stub_binder_ ()
(gdb)
Single stepping until exit from function dyld_stub_binder_,
which has no line number information.
0x00007fff94c3bb7e in malloc ()
(gdb)
Single stepping until exit from function malloc,
which has no line number information.
__cxa_allocate_exception (thrown_size=132) at ../../../../gcc-4.8-20121127/libstdc++-v3/libsupc++/eh_alloc.cc:104
104 if (! ret)
(gdb)
102 ret = malloc (thrown_size);
(gdb)
104 if (! ret)
(gdb)
132 __cxa_eh_globals *globals = __cxa_get_globals ();
(gdb)
__cxa_get_globals () at ../../../../gcc-4.8-20121127/libstdc++-v3/libsupc++/eh_globals.cc:63
63 { return get_global(); }
(gdb)
0x00000001022b6254 in dyld_stub___emutls_get_address () at ../../../../gcc-4.8-20121127/libstdc++-v3/libsupc++/eh_alloc.cc:204
204 __cxxabiv1::__cxa_free_dependent_exception
(gdb)
0x00007fff8bd80878 in dyld_stub_binder ()
(gdb)
Single stepping until exit from function dyld_stub_binder,
which has no line number information.
0x00007fff8bd808a5 in misaligned_stack_error_entering_dyld_stub_binder ()
(gdb)
Single stepping until exit from function misaligned_stack_error_entering_dyld_stub_binder,
which has no line number information.
0x00007fff8bd808e1 in dyld_stub_binder_ ()
(gdb)
Single stepping until exit from function dyld_stub_binder_,
which has no line number information.
0x00007fff8bd81f61 in _dyld_fast_stub_entry ()
(gdb)
Single stepping until exit from function _Z21_dyld_fast_stub_entryPvl,
which has no line number information.
0x00007fff5fc03fbd in __dyld__ZN4dyld18fastBindLazySymbolEPP11ImageLoaderm ()
(gdb)
Single stepping until exit from function __dyld__ZN4dyld18fastBindLazySymbolEPP11ImageLoaderm,
which has no line number information.
0x00007fff8bd808ee in dyld_stub_binder_ ()
(gdb)
Single stepping until exit from function dyld_stub_binder_,
which has no line number information.
__emutls_get_address (obj=0x1022f9520) at ../../../gcc-4.8-20121127/libgcc/emutls.c:128
128 {
(gdb)
Current language: auto; currently c
139 pointer offset = obj->loc.offset;
(gdb)
141 if (__builtin_expect (offset == 0, 0))
(gdb)
700 return __gthrw_(pthread_once) (__once, __func);
(gdb)
0x00000001023f842a in dyld_stub_pthread_once ()
(gdb)
Single stepping until exit from function dyld_stub_pthread_once,
which has no line number information.

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000ffd27000
0x00000000ffd27000 in ?? ()
(gdb)

I did try....

% /sw/opt/llvm-3.2/bin/clang++ -fsanitize=address -std=c++98 cond1.C -g -O0 -stdlib=libc++ -o cond1_asan_clang.exe

using the libc++ from Mountain Lion. It doesn't trigger the bug either and executes without calling pthread...

% ./cond1_asan_clang.exe
% gdb ./cond1_asan_clang.exe
...
(gdb) break main
Breakpoint 1 at 0x100001bc4: file cond1.C, line 21.
(gdb) r
Starting program: /Users/howarth/asan_eh_bug/cond1_asan_clang.exe
Reading symbols for shared libraries +++................................ done

Breakpoint 1, main (argc=<value temporarily unavailable, due to optimizations>, argv=0x7fff5fbfe5a0) at cond1.C:21
21 (argc+1 ? has_destructor() : throw 0);
(gdb) s
has_destructor::~has_destructor (this=<value temporarily unavailable, due to optimizations>) at cond1.C:10
10 ~has_destructor() { }
(gdb)
has_destructor::~has_destructor (this=<value temporarily unavailable, due to optimizations>) at cond1.C:10
10 ~has_destructor() { }
(gdb)
0x00000001000084e8 in has_destructor::~has_destructor (this=<value temporarily unavailable, due to optimizations>) at cond1.C:10
10 ~has_destructor() { }
(gdb)
main (argc=<value temporarily unavailable, due to optimizations>, argv=<value temporarily unavailable, due to optimizations>) at cond1.C:22
22 CI((argc+1 ? throw 0 : has_destructor()));
(gdb)

Program exited normally.

Note that we have run into pthread bugs in the past which Apple has slowly fixed. Also, IMHO anything
that uses the unwinder is always suspect on FSF gcc because we are the only target that uses a system
which has subsumed the unwinder and libgcc calls out of libgcc (ie we don't run the unwinder and the
libgcc calls present in the libgcc_s.10.5 stub from the FSF gcc files but rather those from libSystem).
               Jack

If this is the same test:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/eh/cond1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1,
then it doesn't fail for me on Mac OS 10.8 with ASan (Clang r168632)
Have you tried symbolizing the report?

Alexander,
    Which c++ compiler are you testing with? You won't reproduce the problem on clang++
because it is using a wildly different libstdc++ than FSF g++ 4.8 (see the gdb traces
I posted earlier in reply to Kostya). I have reproduced this failure with...

g++-fsf-4.8 -fsanitize=address -std=c++98 cond1.C -o cond1_asan.exe

on darwin10, darwin11 and darwin12 against current FSF gcc trunk's libasan. I also
verified that switching the FSF gcc X86_64 Fedora 15 to use emutls (like darwin)
via --disable-tls doesn't trigger the bug on linux. I would also note that the
gdb trace for the FSF gcc build of cond1.C seems to execute exactly the same
compared the -fsanitize=address build with FSF gcc except latter crashes at the
final call to dyld_stub_pthread_once()...

0x00000001023f842a in dyld_stub_pthread_once ()
(gdb)
Single stepping until exit from function dyld_stub_pthread_once,
which has no line number information.

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000ffd27000
0x00000000ffd27000 in ?? ()

                     Jack

I debugged this a bit and it seems the mach_override patching of __cxa_throw is bogus. The start of that function is patched to jump to garbage.

Breakpoint 1, 0x0000000100001c19 in main ()
(gdb) display/i $pc
2: x/i $pc 0x100001c19 <main+318>: callq 0x100016386 <dyld_stub___cxa_throw>
(gdb) si
0x0000000100016386 in dyld_stub___cxa_throw ()
2: x/i $pc 0x100016386 <dyld_stub___cxa_throw>: jmpq *0xae1c(%rip) # 0x1000211a8
(gdb)
0x0000000102244870 in __cxa_throw ()
2: x/i $pc 0x102244870 <__cxa_throw>: jmpq 0xffd27000
(gdb) # the above its __cxa_throw in gcc's libstdc++.6.dylib. The first instruction has been patch to jump to a garbage address.

(gdb) x/8i 0x102244870-8
0x102244868 <_ZL23__gxx_exception_cleanup19_Unwind_Reason_CodeP17_Unwind_Exception+56>: std
0x102244869 <_ZL23__gxx_exception_cleanup19_Unwind_Reason_CodeP17_Unwind_Exception+57>: (bad)
0x10224486a <_ZL23__gxx_exception_cleanup19_Unwind_Reason_CodeP17_Unwind_Exception+58>: decl (%rdi)
0x10224486c <_ZL23__gxx_exception_cleanup19_Unwind_Reason_CodeP17_Unwind_Exception+60>: (bad)
0x10224486d <_ZL23__gxx_exception_cleanup19_Unwind_Reason_CodeP17_Unwind_Exception+61>: add %r8b,(%rax)
0x102244870 <__cxa_throw>: jmpq 0xffd27000
0x102244875 <__cxa_throw+5>: or (%rax),%eax
0x102244877 <__cxa_throw+7>: push %rbx
(gdb)
(gdb) watch *0x102244870
Hardware watchpoint 2: *4330899568
(gdb) r

Old value = -788165304
New value = -1373139991
0x0000000100016203 in __asan_mach_override_ptr_custom ()
(gdb) bt
#0 0x0000000100016203 in __asan_mach_override_ptr_custom ()
#1 0x0000000100015a9e in __interception::OverrideFunction ()
#2 0x00007fff5fc13378 in ImageLoaderMachO::doModInitFunctions ()
#3 0x00007fff5fc13762 in ImageLoaderMachO::doInitialization ()
#4 0x00007fff5fc1006e in ImageLoader::recursiveInitialization ()
#5 0x00007fff5fc0feba in ImageLoader::runInitializers ()
#6 0x00007fff5fc01fc0 in dyld::initializeMainExecutable ()
#7 0x00007fff5fc05b04 in dyld::_main ()
#8 0x00007fff5fc01397 in dyldbootstrap::start ()
#9 0x00007fff5fc0105e in _dyld_start ()
(gdb) x/8i 0x102244870
0x102244870 <__cxa_throw>: jmpq 0xffd27000
0x102244875 <__cxa_throw+5>: or (%rax),%eax
0x102244877 <__cxa_throw+7>: push %rbx
0x102244878 <__cxa_throw+8>: lea -0x20(%rdi),%rbx
0x10224487c <__cxa_throw+12>: mov %rsi,-0x70(%rdi)
# Here is where the patching is being done

-Nick

In case it helps at all, I've attached the output from an executable with a debug
version of mach_override in libasan linked in. I am unclear if all of the patching
is done prior to code execution or on the fly. In any case, the local context of the
error appears to be...

Replacing function at 0x7fff91c19830
First 16 bytes of the function: 55 48 89 e5 41 57 41 56 41 55 41 54 53 48 81 ec
To disassemble, save the following function as disas.c and run:
  gcc -c disas.c && gobjdump -d disas.o
The first 16 bytes of the original function will start after four nop instructions.

void foo() {
  asm volatile("nop;nop;nop;nop;");
  asm volatile(".byte 0x55, 0x48, 0x89, 0xe5, 0x41, 0x57, 0x41, 0x56;");
  asm volatile(".byte 0x41, 0x55, 0x41, 0x54, 0x53, 0x48, 0x81, 0xec;");
}

Matching: 55 FAIL
Matching: 55 FAIL
Matching: 55 OK
Matching: 48 FAIL
Matching: 48 FAIL
Matching: 48 FAIL
Matching: 48 FAIL
Matching: 48 89 e5 OK
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 FAIL
Matching: 41 57 OK
BEFORE FIXING:
55 48 89 E5 41 57 41 56 41 55 41 54 53 48 81 EC
55 48 89 E5 41 57 90 90 90 90 90 90 90 90 90 90
AFTER_FIXING:
55 48 89 E5 41 57 41 56 41 55 41 54 53 48 81 EC
55 48 89 E5 41 57 90 90 90 90 90 90 90 90 90 90
First 16 bytes of the function after slicing: e9 cb f7 11 6e 57 41 56 41 55 41 54 53 48 81 ec
ASAN:SIGSEGV

debug_asan_cond1_run.log.bz2 (3.77 KB)

Looks like this happens on x86_64 because the position of __cxa_throw
is too far from the allocated branch island (should be <2G). This can
be solved by allocating the branch islands somewhere near the text
segment (look for kIslandEnd in asan_mac.cc, this is currently
0x7fffffdf0000) or by patching the function with a longer instruction
sequence that stores the jump target in a register and jumps to that
target (which is a bit more complex to implement).

Once this problem is fixed, another one is going to arise. This is how
the first bytes of __cxa_throw look like:

0x0020c49ba5d916e0 <__cxa_throw+0>: lea 0xb4f01(%rip),%rax #
0x20c49ba5e465e8 <_ZN10__cxxabiv120__unexpected_handlerE>
0x0020c49ba5d916e7 <__cxa_throw+7>: push %rbx
0x0020c49ba5d916e8 <__cxa_throw+8>: lea -0x20(%rdi),%rbx

If we move the relative LEA instruction somewhere, we must fix the
constant in order to keep it pointing to the same address.
mach_override already does this for relative CALL and JMP
instructions, but not for LEA. This should be fairly simple to fix.

Note that the 32-bit variant crashes on another invalid address:

ASAN:SIGSEGV

Just want to remind everyone that we plan to stop using mach_override in asanin favor of OSX’s native function interposition.
So, we probably don’t want to spend too much effort fixing mach_override.

–kcc

Just want to remind everyone that we plan to stop using mach_override in
asanin favor of OSX's native function interposition.
So, we probably don't want to spend too much effort fixing mach_override.

--kcc

Kostya,
    Is the native function interposition that is being adopted based on...

https://github.com/rentzsch/mach_inject

? I assume that any method used will be transparent to the user and not require
manually setting DYLD_INSERT_LIBRARIES, correct?
          Jack

No, we are not going to use mach_inject. This isn't portable and may
be even harder to set up than mach_override.
The new ASan runtime will use the dylib interposition and will in fact
require DYLD_INSERT_LIBRARIES to work. However ASan already handles it
correctly itself: if the corresponding env var is missing the app is
just re-execed.
Dylib interposition is supported by Apple and should work on iOS as
well as Mac OS. It will also probably simplify hooking the memory
allocations in ASan, which is now very tricky.

Just want to remind everyone that we plan to stop using mach_override in
asanin favor of OSX's native function interposition.
So, we probably don't want to spend too much effort fixing mach_override.

--kcc

Kostya,
    Unless I am misunderstanding the code in asan/asan_intercepted_functions.h,
using MAC_INTERPOSE_FUNCTIONS on FSF gcc will require the missing blocks support
to be implemented. I did a quick and dirty attempt to build libasan using
libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc imported from llvm svn.
The bootstrap chokes on...

/bin/sh ../libtool --tag=CXX --mode=compile /sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/xg++ -B/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/ -nostdinc++ -nostdinc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include/x86_64-apple-darwin12.2.0 -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc++-v3/libsupc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc++-v3/include/backward -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc++-v3/testsuite/util -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src/.libs -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/bin/ -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/lib/ -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/include -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/sys-include -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 -DASAN_NEEDS_SEGV=1 -DMAC_INTERPOSE_FUNCTIONS -I. -I../../../../gcc-4.8-20121130/libsanitizer/asan -I ../../../../gcc-4.8-20121130/libsanitizer/include -I ../../../../gcc-4.8-20121130/libsanitizer -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -Wno-c99-extensions -g -O2 -MT asan_interceptors.lo -MD -MP -MF .deps/asan_interceptors.Tpo -c -o asan_interceptors.lo ../../../../gcc-4.8-20121130/libsanitizer/asan/asan_interceptors.cc
libtool: compile: /sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/xg++ -B/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/ -nostdinc++ -nostdinc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include/x86_64-apple-darwin12.2.0 -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/include -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc++-v3/libsupc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc++-v3/include/backward -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc++-v3/testsuite/util -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc++-v3/src/.libs -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/bin/ -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/lib/ -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/include -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/sys-include -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 -DASAN_NEEDS_SEGV=1 -DMAC_INTERPOSE_FUNCTIONS -I. -I../../../../gcc-4.8-20121130/libsanitizer/asan -I ../../../../gcc-4.8-20121130/libsanitizer/include -I ../../../../gcc-4.8-20121130/libsanitizer -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -Wno-c99-extensions -g -O2 -MT asan_interceptors.lo -MD -MP -MF .deps/asan_interceptors.Tpo -c ../../../../gcc-4.8-20121130/libsanitizer/asan/asan_interceptors.cc -fno-common -DPIC -o .libs/asan_interceptors.o
In file included from ../../../../gcc-4.8-20121130/libsanitizer/asan/asan_interceptors.cc:15:0:
../../../../gcc-4.8-20121130/libsanitizer/asan/asan_intercepted_functions.h:209:57: error: expected ‘)’ before ‘^’ token
                              dispatch_queue_t dq, void (^work)(void));
                                                         ^
etc. So we may be stuck with mach_override until someone steps up to implement the missing blocks support for darwin in FSF gcc.
             Jack

+kremenek, ganna

Just want to remind everyone that we plan to stop using mach_override in
asanin favor of OSX’s native function interposition.
So, we probably don’t want to spend too much effort fixing mach_override.

–kcc

Kostya,
Unless I am misunderstanding the code in asan/asan_intercepted_functions.h,
using MAC_INTERPOSE_FUNCTIONS on FSF gcc will require the missing blocks support
to be implemented. I did a quick and dirty attempt to build libasan using
libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc imported from llvm svn.
The bootstrap chokes on…

Alex is the expert in the OSX side of things, hopefully he can comment.

But our situation wrt asan on OSX is as I see it:

  • mach_override does not work: we spent more time fighting with mach_override’s stability than we spent on implementing all of asan for linux. And there are still bugs we don’t know how to fix.
  • mach_override does not work: it is not supported on iOS and (may not be supported) on later versions of OSX
    So, there is no choice for us but to use the Apple-blessed mechanism.

Do we want to support both?
No, that’s too expensive. And very likely once we move to function interposition, mach_override will rot very soon.

/bin/sh …/libtool --tag=CXX --mode=compile /sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/xg++ -B/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/ -nostdinc++ -nostdinc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/include/x86_64-apple-darwin12.2.0 -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/include -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc+±v3/libsupc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc+±v3/include/backward -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc+±v3/testsuite/util -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/src -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/src/.libs -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/bin/ -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/lib/ -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/include -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/sys-include -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 -DASAN_NEEDS_SEGV=1 -DMAC_INTERPOSE_FUNCTIONS -I. -I…/…/…/…/gcc-4.8-20121130/libsanitizer/asan -I …/…/…/…/gcc-4.8-20121130/libsanitizer/include -I …/…/…/…/gcc-4.8-20121130/libsanitizer -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -Wno-c99-extensions -g -O2 -MT asan_interceptors.lo -MD -MP -MF .deps/asan_interceptors.Tpo -c -o asan_interceptors.lo …/…/…/…/gcc-4.8-20121130/libsanitizer/asan/asan_interceptors.cc
libtool: compile: /sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/xg++ -B/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/./gcc/ -nostdinc++ -nostdinc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/include/x86_64-apple-darwin12.2.0 -I/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/include -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc+±v3/libsupc++ -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc+±v3/include/backward -I/sw/src/fink.build/gcc48-4.8.0-1000/gcc-4.8-20121130/libstdc+±v3/testsuite/util -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/src -L/sw/src/fink.build/gcc48-4.8.0-1000/darwin_objdir/x86_64-apple-darwin12.2.0/libstdc+±v3/src/.libs -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/bin/ -B/sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/lib/ -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/include -isystem /sw/lib/gcc4.8/x86_64-apple-darwin12.2.0/sys-include -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 -DASAN_NEEDS_SEGV=1 -DMAC_INTERPOSE_FUNCTIONS -I. -I…/…/…/…/gcc-4.8-20121130/libsanitizer/asan -I …/…/…/…/gcc-4.8-20121130/libsanitizer/include -I …/…/…/…/gcc-4.8-20121130/libsanitizer -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -Wno-c99-extensions -g -O2 -MT asan_interceptors.lo -MD -MP -MF .deps/asan_interceptors.Tpo -c …/…/…/…/gcc-4.8-20121130/libsanitizer/asan/asan_interceptors.cc -fno-common -DPIC -o .libs/asan_interceptors.o
In file included from …/…/…/…/gcc-4.8-20121130/libsanitizer/asan/asan_interceptors.cc:15:0:
…/…/…/…/gcc-4.8-20121130/libsanitizer/asan/asan_intercepted_functions.h:209:57: error: expected ‘)’ before ‘^’ token
dispatch_queue_t dq, void (^work)(void));
^
etc. So we may be stuck with mach_override until someone steps up to implement the missing blocks support for darwin in FSF gcc.

–kcc

+kremenek, ganna

> > Just want to remind everyone that we plan to stop using mach_override in
> > asanin favor of OSX's native function interposition.
> > So, we probably don't want to spend too much effort fixing mach_override.
> >
> > --kcc
>
> Kostya,
> Unless I am misunderstanding the code in
> asan/asan_intercepted_functions.h,
> using MAC_INTERPOSE_FUNCTIONS on FSF gcc will require the missing blocks
> support
> to be implemented. I did a quick and dirty attempt to build libasan using
> libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc imported from llvm
> svn.
> The bootstrap chokes on...
>

Alex is the expert in the OSX side of things, hopefully he can comment.

But our situation wrt asan on OSX is as I see it:
   - mach_override does not work: we spent more time fighting with
mach_override's stability than we spent on implementing all of asan for
linux. And there are still bugs we don't know how to fix.
   - mach_override does not work: it is not supported on iOS and (may not
be supported) on later versions of OSX
So, there is no choice for us but to use the Apple-blessed mechanism.

Do we want to support both?
No, that's too expensive. And very likely once we move to function
interposition, mach_override will rot very soon.

Kostya,
   Okay. Looking back through the available threads...

http://code.google.com/p/address-sanitizer/issues/detail?id=64
http://code.google.com/p/chromium/issues/detail?id=99879
https://github.com/adobe/chromium/blob/master/content/plugin/plugin_carbon_interpose_mac.cc

it would appear that using blocks is not essential to this but that the llvm
developers leveraged that feature. So asan/dynamic/asan_interceptors_dynamic.cc
will need to be rewritten for use in FSF gcc to provide an alternate code path
that doesn't require blocks. I have seen no evidence of any effort to add blocks
support to FSF gcc so waiting for that may be a non-starter. Also, I'm not
sure the license for the necessary libblocksruntime for linux would be acceptable for merging...

http://packages.debian.org/changelogs/pool/main/libb/libblocksruntime/libblocksruntime_0.1-1/copyright

        Jack

+kremenek, ganna

> > Just want to remind everyone that we plan to stop using mach_override in
> > asanin favor of OSX's native function interposition.
> > So, we probably don't want to spend too much effort fixing mach_override.
> >
> > --kcc
>
> Kostya,
> Unless I am misunderstanding the code in
> asan/asan_intercepted_functions.h,
> using MAC_INTERPOSE_FUNCTIONS on FSF gcc will require the missing blocks
> support
> to be implemented. I did a quick and dirty attempt to build libasan using
> libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc imported from llvm
> svn.
> The bootstrap chokes on...
>

Alex is the expert in the OSX side of things, hopefully he can comment.

But our situation wrt asan on OSX is as I see it:
   - mach_override does not work: we spent more time fighting with
mach_override's stability than we spent on implementing all of asan for
linux. And there are still bugs we don't know how to fix.
   - mach_override does not work: it is not supported on iOS and (may not
be supported) on later versions of OSX
So, there is no choice for us but to use the Apple-blessed mechanism.

Do we want to support both?
No, that's too expensive. And very likely once we move to function
interposition, mach_override will rot very soon.

Kostya,
   I have managed to craft a mockup patch to switch libsanitizer to use mac
interpose function support from dynamic/asan_interceptors_dynamic.cc while
disabling the use of any dispatch calls that require the missing blocks
support...

http://gcc.gnu.org/bugzilla/attachment.cgi?id=28847

The resulting libasan passes all of the asan.exp tests without regressions
and eliminates PR55521 by avoiding the use of mach_override. It still needs
some cleanup (as I used 'if 0''s to avoid the unsupported dispatch calls).
         Jack

+kremenek, ganna

> > Just want to remind everyone that we plan to stop using mach_override in
> > asanin favor of OSX's native function interposition.
> > So, we probably don't want to spend too much effort fixing mach_override.
> >
> > --kcc
>
> Kostya,
> Unless I am misunderstanding the code in
> asan/asan_intercepted_functions.h,
> using MAC_INTERPOSE_FUNCTIONS on FSF gcc will require the missing blocks
> support
> to be implemented. I did a quick and dirty attempt to build libasan using
> libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc imported from llvm
> svn.
> The bootstrap chokes on...
>

Alex is the expert in the OSX side of things, hopefully he can comment.

But our situation wrt asan on OSX is as I see it:
   - mach_override does not work: we spent more time fighting with
mach_override's stability than we spent on implementing all of asan for
linux. And there are still bugs we don't know how to fix.
   - mach_override does not work: it is not supported on iOS and (may not
be supported) on later versions of OSX
So, there is no choice for us but to use the Apple-blessed mechanism.

Do we want to support both?
No, that's too expensive. And very likely once we move to function
interposition, mach_override will rot very soon.

Kostya,
    I've updated the proposed patch for switching from mach_override to
mac function interposition on http://gcc.gnu.org/bugzilla/attachment.cgi?id=28849
with the addition of the usage of -DMISSING_BLOCKS_SUPPORT and the appropriate
tests on that to avoid the missing blocks support on FSF gcc.
          Jack

+glider
Hi Jack,

All OSX-related changes in asan should go to Alex (in CC)

Thanks!
--kcc

This is interesting! I had some difficulties with mach_override myself
in firefox. Don't you have to disable the two-level namespace to be
able to override the functions you want? What currently blocks using
DYLD_INSERT_LIBRARIES instead of mach_override?

Cheers,
Rafael

+kledzik@apple.com
The dynamic runtime is using dylib interposition (google for
"__DATA,__interpose).
If I'm understanding correctly (Nick, can you please confirm this?)
this allows to interpose the function regardless of the two-level
namespace.
The support for dynamic runtime in ASan is almost there. But the new
interposition method has revealed some issues with the allocator which
were corked here and there before. Most of those are caused by a
CoreFoundation dependency, which I'm trying to eliminate now.