Page MenuHomePhabricator

[Tsan] Do not intercept non-FreeBSD functions on FreeBSD
ClosedPublic

Authored by kutuzov.viktor.84 on Oct 18 2014, 3:54 AM.

Diff Detail

Repository
rL LLVM

Event Timeline

kutuzov.viktor.84 retitled this revision from to [Tsan] Do not intercept non-FreeBSD functions on FreeBSD.
kutuzov.viktor.84 updated this object.
kutuzov.viktor.84 edited the test plan for this revision. (Show Details)
kutuzov.viktor.84 added reviewers: kcc, samsonov, glider.
kutuzov.viktor.84 added subscribers: Unknown Object (MLST), emaste.
samsonov edited edge metadata.Oct 20 2014, 4:48 PM

I think we need magic similar to sanitizer_common_interceptors.inc - define TSAN_INTERCEPT_FOO depending on the platform, define or not define TSAN_INTERCEPTOR(foo, ...) depending on its value, and define TSAN_MAYBE_INTERCEPT(foo) to either TSAN_INTERCEPT(foo), or empty statement.

Rewritten via TSAN_MAYBE_INTERCEPT macros.

samsonov accepted this revision.Oct 23 2014, 5:34 PM
samsonov edited edge metadata.

LGTM

This revision is now accepted and ready to land.Oct 23 2014, 5:34 PM
dvyukov edited edge metadata.Oct 23 2014, 9:42 PM

What does happen with the current code? Does the binary crash? Or it works but you don't want unnecessary interceptors in the binary?
That would be useful to understand to evaluate the change.

dvyukov added inline comments.Oct 23 2014, 9:58 PM
lib/tsan/rtl/tsan_interceptors.cc
108 ↗(On Diff #15324)

What's the point in defining these TSAN_INTERCEPT_MMAP64 macros? Looks like an unnecessary level of indirection. They are used exactly once, and now I need to modify 3 places in stead of 2 when working with an interceptor.
Please remove TSAN_INTERCEPT_MMAP64 macros and use the condition (e.g. SANITIZER_LINUX) directly. Looks like a net win to me.

What does happen with the current code? Does the binary crash? Or it works but you don't want unnecessary interceptors in the binary?

With the current code we fail on ThreadSanitizer-Unit :: unit/TsanUnitTest/Mman.CallocOverflow:

FATAL: ThreadSanitizer: failed to intercept __xstat

This is because running the test causes calling stat() the interceptor of which relies on __xstat() that does not exist on FreeBSD.

Removing dead interceptors from the binary is good, but the major point is that we do not define things that do not exist on FreeBSD so the compiler will let us know as soon as we're trying to refer them. Thus, with the __xstat() interceptor removed we have a compile-time error for the original stat() interceptor exposing the invalid dependency.

OK, makes sense. Now I noticed the change to stat interceptor that is very different from the bulk of the changes.

lib/tsan/rtl/tsan_interceptors.cc
108 ↗(On Diff #15324)

What's the point in defining these TSAN_INTERCEPT_MMAP64 macros? Looks like an unnecessary level of indirection. They are used exactly once, and now I need to modify 3 places in stead of 2 when working with an interceptor.

Well, the idea is to control the presence of a given interceptor in a single place. For example, if we want mmap64() to be defined on MAC, then we can do it with a single-line change:

#define TSAN_INTERCEPT_MMAP64 SANITIZER_LINUX || SANITIZER_MAC

and it will affect both the presence of the interceptor's definition and its initialization in InitializeInterceptors() so no need to change them (even though the very macro is used only once indeed).

In contrast, surrounding interceptors and their initializations with #if/#endif means we need to change two lines and also take special care to make sure the conditions for the interceptor itself and its initialization do match.

Please remove TSAN_INTERCEPT_MMAP64 macros and use the condition (e.g. SANITIZER_LINUX) directly. Looks like a net win to me.

Sounds like the previous version?

http://reviews.llvm.org/differential/diff/15120/

I am proposing something in between:

#if SANITIZER_LINUX
TSAN_INTERCEPTOR(int, epoll_create, int size) {

SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
int fd = REAL(epoll_create)(size);
if (fd >= 0)
  FdPollCreate(thr, pc, fd);
return fd;

}
#define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE TSAN_INTERCEPT(epoll_create)
#else
#define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE
#endif

void InitializeInterceptors() {
...

TSAN_MAYBE_INTERCEPT_EPOLL_CREATE;

The original version indeed has unnecessary duplication of information. And the current version has unnecessary dissipation of information -- I need to update 3 places to add an interceptor, and when I am looking at an interceptor I can't understand when it's enabled (TSAN_INTERCEPT_TMPFILE64 name is pointless and does not communicate any useful information to me).

kutuzov.viktor.84 edited edge metadata.

Updated as suggested.

Thanks, Dmitry.

dvyukov accepted this revision.Oct 24 2014, 3:18 AM
dvyukov edited edge metadata.

Much nicer now, thanks
LGTM

Diffusion closed this revision.Oct 24 2014, 4:05 AM
Diffusion updated this revision to Diff 15401.

Closed by commit rL220554 (authored by vkutuzov).