Created for Wine's memset by clang or mingw-gcc,
the latter places it quite at the start of the function:
```
0x00006ffffb67e210 <memset+0>: 0f b6 d2 movzbl %dl,%edx
0x00006ffffb67e213 <memset+3>: 48 b8 01 01 01 01 01 01 01 01 movabs $0x101010101010101,%rax
```
`3200 uint64_t v = 0x101010101010101ull * (unsigned char)c;`
290fd532ee/dlls/msvcrt/string.c (L3200)
Fixes:
```
[6113/7139] Building CXX object projects\compiler-rt\lib\interception\CMakeFiles\RTInterception.x86_64.dir\interception_win.cpp.obj
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
746 | case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
| ^
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): note: insert 'FALLTHROUGH;' to silence this warning
746 | case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
| ^
| FALLTHROUGH;
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): note: insert 'break;' to avoid fall-through
746 | case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
| ^
| break;
1 warning generated.
```
Observed in Wine when trying to intercept `ExitThread`, which forwards
to `ntdll.RtlExitUserThread`.
`gdb` interprets it as `xchg %ax,%ax`.
`llvm-mc` outputs simply `nop`.
```
==Asan-i386-calls-Dynamic-Test.exe==964==interception_win: unhandled instruction at 0x7be27cf0: 66 90 55 89 e5 56 50 8b
```
```
Wine-gdb> bt
#0 0x789a1766 in __interception::GetInstructionSize (address=<optimized out>, rel_offset=<optimized out>) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:983
#1 0x789ab480 in __sanitizer::SharedPrintfCode(bool, char const*, char*) () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp:311
#2 0x789a18e7 in __interception::OverrideFunctionWithHotPatch (old_func=2078440688, new_func=2023702608, orig_old_func=warning: (Internal error: pc 0x792f1a2c in read in CU, but not in symtab.)warning: (Error: pc 0x792f1a2c in address map, but not in symtab.)0x792f1a2c) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:1118
#3 0x789a1f34 in __interception::OverrideFunction (old_func=2078440688, new_func=2023702608, orig_old_func=warning: (Internal error: pc 0x792f1a2c in read in CU, but not in symtab.)warning: (Error: pc 0x792f1a2c in address map, but not in symtab.)0x792f1a2c) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:1224
#4 0x789a24ce in __interception::OverrideFunction (func_name=0x78a0bc43 <vtable for __asan::AsanThreadContext+1163> "ExitThread", new_func=2023702608, orig_old_func=warning: (Internal error: pc 0x792f1a2c in read in CU, but not in symtab.)warning: (Error: pc 0x792f1a2c in address map, but not in symtab.)0x792f1a2c) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:1369
#5 0x789f40ef in __asan::InitializePlatformInterceptors () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_win.cpp:190
#6 0x789e0c3c in __asan::InitializeAsanInterceptors () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:802
#7 0x789ee6b5 in __asan::AsanInitInternal () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:442
#8 0x789eefb0 in __asan::AsanInitFromRtl () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:522
#9 __asan::AsanInitializer::AsanInitializer (this=<optimized out>) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:542
#10 __cxx_global_var_init () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:546
...
Wine-gdb> disassemble /r 2078440688,2078440688+20
Dump of assembler code from 0x7be27cf0 to 0x7be27d04:
0x7be27cf0 <_RtlExitUserThread@4+0>: 66 90 xchg %ax,%ax
...
```
When ntdll was added to the list of of "interesting DLLs" list (in
d58230b9dcb3b312a2da8f874daa0cc8dc27da9b), the intention was not to
intercept the "mini CRT" functions it exports. OverrideFunction would
only intercept the *first* function it found when searching the list of
DLLs, and ntdll was put last in that list.
However, after 42cdfbcf3e92466754c175cb0e1e237e9f66749e,
OverrideFunction intercepts *all* matching functions in those DLLs. As
a side-effect, the runtime would now intercept functions like memset
etc. also in ntdll.
This causes a problem when ntdll-internal functions like
RtlDispatchException call the intercepted memset, which tries to
inspect uncommitted shadow memory, raising an exception, and getting
stuck in that loop until the stack overflows.
Since we never intended to intercept ntdll's memset etc., the simplest
fix seems to be to actively ignore ntdll when intercepting those
functions.
Fixes#114793
Since the sanitizer merge in commit r15-5164-gfa321004f3f628 of GCC
which entails LLVM commit 61a6439f35b6de28ff4aff4450d6fca970292fd5, GCCs
bootstrap is broken on s390 -m31. This is due to commit
ec68dc1ca4d967b599f1202855917d5ec9cae52f which introduces stricter type
checking which is why GCC bootstrap fails with
```
In file included from /gcc/src/libsanitizer/interception/interception.h:18,
from /gcc/src/libsanitizer/interception/interception_type_test.cpp:14:
/gcc/src/libsanitizer/interception/interception_type_test.cpp:30:61: error: static assertion failed
30 | COMPILER_CHECK((__sanitizer::is_same<::SSIZE_T, ::ssize_t>::value));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
/gcc/src/libsanitizer/sanitizer_common/sanitizer_internal_defs.h:363:44: note: in definition of macro 'COMPILER_CHECK'
363 | #define COMPILER_CHECK(pred) static_assert(pred, "")
| ^~~~
make[8]: *** [Makefile:469: interception_type_test.lo] Error 1
```
The culprit seems to be that we don't check for equality of type sizes
anymore but rather whether the types are indeed the same. On s390 -m31
we have that `sizeof(int)==sizeof(long)` holds which is why previously
the checks succeeded. They fail now because
```
size_t => unsigned long
ssize_t => long
ptrdiff_t => int
::SSIZE_T => __sanitizer::sptr => int
::PTRDIFF_T => __sanitizer::sptr => int
```
This is fixed by mapping `SSIZE_T` to `long` in the end.
```
#if defined(__s390__) && !defined(__s390x__)
typedef long ssize;
#else
typedef sptr ssize;
#endif
#define SSIZE_T __sanitizer::ssize
```
warning: format specifies type 'void *' but the argument has type 'uptr'
(aka 'unsigned long long') [-Wformat] (observed at x86_64, in
AllocateTrampolineRegion)
warning: format specifies type 'char *' but the argument has type
'RVAPtr<char>' [-Wformat] (observed at x86_64, in
InternalGetProcAddress)
It appears already some lines above with this comment:
"Cannot overwrite control-instruction. Return 0 to indicate failure.".
Replacing just the comment in the first appearance.
Found after creating the test in #113085.
There may not always be available virtual memory at higher addresses
than the target function. Therefore, search also lower addresses while
ensuring that we stay within the accessible memory range.
Additionally, add more ReportError calls to make the reasons for
interception failure more clear.
The instruction is present in some library in the 24H2 update for
Windows 11:
==8508==interception_win: unhandled instruction at 0x7ff83e193a40: 44 0f
b6 1a 4c 8b d2 48
This could be generalized, but getting all the ModR/M byte combinations
right is tricky. Many other classes of instructions handled in this file
could use some generalization too.
MSVC can sometimes generate instructions in function prologues that asan
previously didn't know the size of. This teaches asan those sizes. This isn't
super useful for using ASAN with non-msvc compilers, but it does stand alone.
From https://reviews.llvm.org/D151008
Since we may copy code (see CopyInstructions) to the trampoline which
could reference data inside the original module, we really want the
trampoline to be within 2 GB of not just the original function, but
within anything that function may have rip-relative accesses to, i.e.
within 2 GB of that function's whole module.
This fixes interception failures like the following scenario:
1. Intercept `CreateProcess` in kernel32.dll, allocating a trampoline
region right after
2. Start intercepting `memcpy` in the main executable, which is loaded
at a lower address than kernel32.dll, but still within 2 GB of the
trampoline region so we keep using it.
3. Try to copy instructions from `memcpy` to the trampoline. Turns out
one instruction references data that is more than 2GB away from the
trampoline, so it can't be relocated.
4. The process exits due to a CHECK failure
(Full story at https://crbug.com/341936875#comment45 and following.)
This reapplies 8fa66c6ca7272268747835a0e86805307b62399c ([asan][windows]
Eliminate the static asan runtime on windows) for a second time.
That PR bounced off the tests because it caused failures in the other
sanitizer runtimes, these have been fixed by only building interception,
sanitizer_common, and asan with /MD, and continuing to build the rest of
the runtimes with /MT. This does mean that any usage of the static
ubsan/fuzzer/etc runtimes will mean you're mixing different runtime
library linkages in the same app, the interception, sanitizer_common,
and asan runtimes are designed for this, however it does result in some
linker warnings.
Additionally, it turns out when building in release-mode with
LLVM_ENABLE_PDBs the build system forced /OPT:ICF. This totally breaks
asan's "new" method of doing "weak" functions on windows, and so
/OPT:NOICF was explicitly added to asan's link flags.
---------
Co-authored-by: Amy Wishnousky <amyw@microsoft.com>
This works for MinGW, but the MSVC linker apparently doens't pull in
those symbols. Reverting for now since I won't be able to reproduce it today.
https://lab.llvm.org/buildbot/#/builders/107/builds/2337
This reverts commit 9df92cbd1addb03c7169f05cf3b628f88c610224.
The interceptor types are supposed to match size_t (and the non-Windows
ssize_t) exactly, but on 32-bit Windows `size_t` uses `unsigned int`
whereas `SIZE_T` is `unsigned long`. The current definition results in
`uptr` not matching `uintptr_t` since we otherwise get typedef
redefinition errors. Work around this by using a #define instead of
a typedef when defining SIZE_T.
It would probably be cleaner to stop using these uppercase types, but
that is a rather invasive change and this one is the minimal change to
allow uptr to match uintptr_t on Windows.
To ensure this compiles on Windows, we also remove the interceptor.h
defines of uptr (that do not always match __sanitizer::uptr) and rely
on __sanitizer::uptr instead. The interceptor types most likely predate
those other types so clean up the unnecessary definition while here.
This also reverts commit 18e06e3e2f3d47433e1ed323b8725c76035fc1ac and
commit bb27dd853a713866c025a94ead8f03a1e25d1b6e.
Reviewed By: mstorsjo, vitalybuka
Pull Request: https://github.com/llvm/llvm-project/pull/106311
Since glibc 2.40 some functions like openat make use of overloads when
built with `-D_FORTIFY_SOURCE=2`, see:
https://github.com/bminor/glibc/blob/master/io/bits/fcntl2.h
This means that doing something like `(uintptr_t) openat` or `(void *)
openat` is now ambiguous, breaking the compiler-rt build on new glibc
versions.
Fix this by explicitly casting the symbol to the expected function type
before casting it to an intptr. The expected type is obtained as
`decltype(REAL(func))` so we don't have to repeat the signature from
INTERCEPTOR in the INTERCEPT_FUNTION macro.
Fixes https://github.com/llvm/llvm-project/issues/100754.
Update the folder titles for targets in the monorepository that have not
seen taken care of for some time. These are the folders that targets are
organized in Visual Studio and XCode
(`set_property(TARGET <target> PROPERTY FOLDER "<title>")`)
when using the respective CMake's IDE generator.
* Ensure that every target is in a folder
* Use a folder hierarchy with each LLVM subproject as a top-level folder
* Use consistent folder names between subprojects
* When using target-creating functions from AddLLVM.cmake, automatically
deduce the folder. This reduces the number of
`set_property`/`set_target_property`, but are still necessary when
`add_custom_target`, `add_executable`, `add_library`, etc. are used. A
LLVM_SUBPROJECT_TITLE definition is used for that in each subproject's
root CMakeLists.txt.
This makes it so we'll be able to decode the instructions used in the
weak function stubs from
https://github.com/llvm/llvm-project/pull/81677. This code doesn't
technically require those changes.
Co-authored-by: Amy Wishnousky <amyw@microsoft.com>
All these unit tests already include ${COMPILER_RT_GTEST_SOURCE} as an
input source file and the target llvm_gtest does not exist for
standalone builds. Currently the DEPS argument is ignored for standalone
builds so the missing target is not a problem, but as part of fixing a
build race for standalone builds I am planning to include those
dependencies in COMPILER_RT_TEST_STANDALONE_BUILD_LIBS configurations.
Reviewed By: vitalybuka
Pull Request: https://github.com/llvm/llvm-project/pull/83649
On AArch64 with BTI, we have to start functions with the appropriate
BTI hint to indicate that the function is a valid call target.
To support interceptors with AArch64 BTI, add "BTI c".
The `_DYNAMIC` reference from `AsanDoesNotSupportStaticLinkage` ensures
that `clang++ -fsanitize=address -static` gets a linker error.
`MemprofDoesNotSupportStaticLinkage` is similar for `-fmemory-profile`.
Move the functions to sanitizer_common.h to be used by more sanitizers
on ELF platforms.
Fuchsia does not use interposition and opts out the check (its
`AsanDoesNotSupportStaticLinkage` is a no-op).
Currently, almost all of the shared libraries of MIPS, rely on $t9
to get the address of current function, instead of PCREL instructions,
even on MIPSr6. So we have to set $t9 properly.
To get the address of preemptible function, we need the help of GOT.
MIPS/O32 has .cpload, which can help to generate 3 instructions to get GOT.
For __mips64, we can get GOT by:
lui $t8, %hi(%neg(%gp_rel(SANITIZER_STRINGIFY(TRAMPOLINE(func)))))
daddu $t8, $t8, $t9
daddiu $t8, $t8, %hi(%neg(%gp_rel(SANITIZER_STRINGIFY(TRAMPOLINE(func)))))
And then get the address of __interceptor_func, and jump to it
ld $t9, %got_disp(_interceptor" SANITIZER_STRINGIFY(func) ")($t8)
jr $t9
Fixes#74047
Co-authored-by: YunQiang Su <yunqiang.su@cipunited.com>
It turns out this works _mostly_ fine, even when mixing debug versions
of asan with programs built with the release runtime. Using /MT (or
/MTd) with a dynamically linked asan has never really worked that well,
and I am planning on opening a PR that will completely remove the
static-asan configuration for windows and make programs linked with the
static CRT/runtime work with the DLL version of asan. This is better
than the current situation because the static linked version of asan
doesn't work well on windows if there are multiple DLLs in the process
using it.
The check for building asan with only /MD or /MT has been removed. It
was in AsanDoesNotSupportStaticLinkage, but was checking for debug CRTs,
not static linkage. The kind of static linkage this function is supposed
to check for (on linux for example) doesn't really exist on windows.
Note: There is one outstanding issue with this approach, if you mix a
/MDd DLLs and /MD dlls in the same process then the "real" function
called by asan interceptors will be the same for calls from both
contexts, potentially screwing up things like errno. This only happens
if you mix /MD and /MDd in the same process, because otherwise asan
won't find functions from both runtimes to intercept. We are working on
a fix for this, and it mainly hits with the CRT functions exported from
both ucrtbase and ntdll.
This change is being upstreamed from Microsoft's fork.
1. Differentiate SANITIZER_WINDOWS64 for x64 and arm64
2. turn off interception tests that expect x86 assembly
---------
Co-authored-by: Farzon Lotfi <farzon@farzon.com>
Jakub Jelínek reports:
As mentioned in https://gcc.gnu.org/PR112563, the new DECLARE_WRAPPER
macro
added in 37445e9 and ammended in 85d3873 doesn't work on SPARC/Solaris
with
Solaris as.
While clang and GNU as when used from GCC seems to be forgiving on most
architectures and allow both %function and @function (with the latter
not being
allowed on ARM/AArch64 I believe because @ is assembler comment start
there),
Solaris as doesn't allow the %function form.
Fix it by using %function only for ARM.
Co-developed-by: Jakub Jelínek <jakub@redhat.com>
Reported-by: Jakub Jelínek <jakub@redhat.com>
Closes: https://github.com/llvm/llvm-project/issues/72970
This instruction is present in memcpy in the latest vcruntime
This PR has been opened for @AndrewDeanMS (a teammate inside Microsoft)
who made the PR to our internal branch.
Co-authored-by: Andrew Dean <Andrew.Dean@microsoft.com>
The old code incorrectly checked what relative offsets were allowed.
The correct check is that the offset from the target to the instruction
pointer should be within $[-2^{31}, 2^{31})$; however, the check that
was originally written was that the offset was within $[0, 2^{31})$.
Negative offsets are certainly allowable (as long as they fit in 32
bits), and this change fixes that.