Clang: Difference between revisions

From miki
Jump to navigation Jump to search
 
Line 177: Line 177:
* Error <code>undefined reference to typeinfo</code> when linking [https://stackoverflow.com/questions/37358573/why-does-fsanitize-undefined-cause-undefined-reference-to-typeinfo SO]
* Error <code>undefined reference to typeinfo</code> when linking [https://stackoverflow.com/questions/37358573/why-does-fsanitize-undefined-cause-undefined-reference-to-typeinfo SO]
:* Fix is to flag <code>-fno-sanitize=vptr</code>.
:* Fix is to flag <code>-fno-sanitize=vptr</code>.

=== No debug symbols ===
Recent version of clang uses DWARF V5. The old debug info can still be used with compile and link flag j<code>-fdebug-default-version=4</code>.

Latest revision as of 23:00, 11 May 2023

Links

Clang on Windows

LLVM-MinGW

The best port of LLVM/Clang on Windows I tried.

  • No dependency on Visual Studio.
  • Support 32-bit and 64-bit targets.
  • Support sanitizers (ASAN, UBSAN).

MSYS2

MSYS2 now provides clang 9.0 packages.

  • No dependency on Visual Studio.
  • Support 32-bit and 64-bit targets.
  • But does not support sanitizers (ASAN, UBSAN).

Official LLVM

Packages from the official LLVM at http://releases.llvm.org/download.html.

  • DEPEND on Visual Studio for linking
  • Support 32-bit and 64-bit targets.
  • (Maybe) support sanitizers (ASAN, UBSAN).

Tips

Get Stack Pointer

Use this macro [1]:

#define current_stack_pointer ({ \
        register unsigned long esp asm("esp"); \
        asm("" : "=r"(esp)); \
        esp; \
        })

Turn errors into warning

From the manual

-Wno-error=foo Turn warning “foo” into an warning even if -Werror is specified.

Enable all warnings: -Weverything

-Weverything means enable all current and future warnings. See Better Apps with Clang's Weverything or Wall is a Lie!

Make deterministic / reproducible builds

Things to look at:

  • __DATE__ and __TIME__. On clang, we can do export ZERO_AR_DATE=1.
  • __FILE__. On clang, we can add a flag -ffile-prefix-map=/some/local/build/path=..
  • __LINE__.
  • some randomness introduced by compiler: Use flag -frandom-seed=0x${checksum}.

Some script I used:

ag -l __LINE__ | xargs sed -ri 's/__LINE__/1/g'
make NODEBUG=1 some.elf                       # Optional, but ideally build without flag -g
strip --strip-all some.elf
sha256sum some.elf

Get list of standard compiler defines

clang -dM -E -x c /dev/null
# #define _LP64 1
# #define __ATOMIC_ACQUIRE 2
# #define __ATOMIC_ACQ_REL 4
# #define __ATOMIC_CONSUME 1
# #define __ATOMIC_RELAXED 0

Detect optimization levels

This can't detect all levels but at least some of them (from SO):

clang -Xpreprocessor -dM -E - < /dev/null > 1
clang -Xpreprocessor -dM -O -E - < /dev/null > 2
diff 1 2
# 53a54
# > #define __OPTIMIZE__ 1
# 154d155
# < #define __NO_INLINE__ 1

Troubleshoot

iostream not found

This is a funny one. Simple Hello, World program that fails with an

#include <iostream>

using namespace std;

int main() {
    cout << "Hello, World" << endl;
    return 0;
}
clang++ main.cpp
# main.cpp:1:10: fatal error: 'iostream' file not found
# #include <iostream>
#          ^~~~~~~~~~
# 1 error generated.

Luckily StackOverflow comes to the rescue.

The problem is that we have several gcc/g++ installation, and the one selected by clang doesn't have the c++ headers.

$ clang++ -v main.cpp
clang version 7.0.1-8 (tags/RELEASE_701/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/10
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/lib/llvm-7/bin/clang" -cc1 [...]
clang -cc1 version 7.0.1 based upon LLVM 7.0.1 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/backward"
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/include/clang/7.0.1/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++
 /usr/include/clang/7.0.1/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
main.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
         ^~~~~~~~~~
1 error generated.

The simplest for us was to uninstall gcc-9. Another solution is to install g++-9. Also it seems that clang uses some kind of prioritization, so in fact reinstalling gcc-8/g++-8 may work as well.

UBSAN / ASAN troubleshooting

References
Build
  • For ASAN:
  • Use compile and link flags -fsanitize=address.
  • It is also recommended to use compile flag -fno-omit-frame-pointer for better stack trace.
# Compile
clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc
# Link
clang++ -g -fsanitize=address example_UseAfterFree.o
  • For UBSAN:
  • Use compile and link flags -fsanitize=undefined.
Troubleshoot
  • Error undefined reference to typeinfo when linking SO
  • Fix is to flag -fno-sanitize=vptr.

No debug symbols

Recent version of clang uses DWARF V5. The old debug info can still be used with compile and link flag j-fdebug-default-version=4.