Attempt to modify memory sanitizer for support of X86

Hello,

I’m quite new to LLVM, but I’m interested in memory sanitizer. The petty thing is, that 32bit addressing on Linux is not supported. Thus I tried to take the latest version of the software and to modify it, using Ubuntu 16.04 as operating system. Given the example

example.c:

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char **argv) {

int *a = (int )malloc(10sizeof(10));

a[5] = 0;

if (a[argc])

printf(“xx\n”);

return 0;

}

which I compiled with the command

clang -fsanitize=memory -m32 -fPIE -pie -fno-omit-frame-pointer -g -Wl,-Map,example32.map example.c -oexample32.out

I get now a segmentation fault during the execution:

(gdb) r

Starting program: /home/pusl/code/example32.out

[Thread debugging using libthread_db enabled]

Using host libthread_db library “/lib/x86_64-linux-gnu/libthread_db.so.1”.

Program received signal SIGSEGV, Segmentation fault.

0x565e14f9 in main (argc=1448445640, argv=0xf7f1d3dc) at example.c:4

I tried to figure out the issue, but as a newcomer to LLVM I don’t have any further idea now to get nearer to the root cause. Any new idea is welcome.

I changed 5 files. The diffs are:

  • cmake/config-ix.cmake:

diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake

index 04e33a0…d02e319 100644

— a/cmake/config-ix.cmake

+++ b/cmake/config-ix.cmake

@@ -149,7 +149,7 @@ set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}

${MIPS32} ${MIPS64} ${PPC64})

set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})

set(ALL_LSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})

-set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})

+set(ALL_MSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64})

set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64}

${MIPS32} ${MIPS64})

set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})

  • lib/msan/msan.h:

diff --git a/lib/msan/msan.h b/lib/msan/msan.h

index be74f6e…10b5b05 100644

— a/lib/msan/msan.h

+++ b/lib/msan/msan.h

@@ -147,6 +147,26 @@ const MappingDesc kMemoryLayout[] = {

#define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x100000000000ULL)

#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x280000000000)

+#elif SANITIZER_LINUX && SANITIZER_WORDSIZE == 32

+eugenis (the msan co-author and current maintainer)

I don’t remember any hard blockers for 32-bit msan.
Soft blockers are:

  • extra work and extra maintenance
  • too little address space, hard to fit any non-trivial application.

You may start looking at /proc//maps to see what is the memory region you
are failing on and how it is related to kMemoryLayout.

Just curious, why are you trying to do this?

–kcc

Hello,

thanks for your comments.

I know, that there is not so much address space in case of 32-bit addressing, but for a lot of applications it is enough. I used address sanitizer with 32-bit addressing and due to the good performance I wanted to use memory sanitizer with 32-bit addressing.

Instead of looking at /proc//maps I changed msan.cc to print out the process mapping every time:

diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc

index d2981f0…97f97c4 100644

— a/lib/msan/msan.cc

+++ b/lib/msan/msan.cc

@@ -408,6 +408,8 @@ void __msan_init() {

Die();

}

+ DumpProcessMap();

It's hard to say based on these code snippets, but it looks like you
have changed the memory mapping (i.e. app-to-shadow address
calculation) without updating the compiler side (MemorySanitizer.cpp).