转载

使用 musl 和 clang 编译 C 程序

假设你正在使用基于 Debian 的 Linux 发行版,你可以使用如下命令安装 musl:

sudo apt-get install musl-dev

创建一个最简单的 main.c 文件:

#include <stdio.h>  int main() {   printf("glibc is shit/n"); }

使用如下命令编译:

clang main.c -static -nostdinc -nostdlib -I/usr/include/x86_64-linux-musl -L/usr/lib/x86_64-linux-musl /usr/lib/x86_64-linux-musl/crt1.o /usr/lib/x86_64-linux-musl/crti.o /usr/lib/x86_64-linux-musl/crtn.o -lc

就是这样,这将会生成一个 18.9k 大小的二进制文件,并将打印一句众所皆知的事实。

要让 clang 的 snaitizers 可用,需要修改 LLVM 源。这里有一个补丁和脚本可从头开始克隆和构建 Clang 3.6(要求 Clang、CMake 和 Ninja 构建系统)

musl.patch:

--- a/llvm/projects/compiler-rt/lib/interception/interception_linux.cc +++ b/llvm/projects/compiler-rt/lib/interception/interception_linux.cc @@ -24,7 +24,7 @@  return real == wrapper;  } -#if !defined(__ANDROID__)  // android does not have dlvsym +#if 0  void *GetFuncAddrVer(const char *func_name, const char *ver) {  return dlvsym(RTLD_NEXT, func_name, ver);  } --- a/llvm/projects/compiler-rt/lib/lsan/lsan_common.cc +++ b/llvm/projects/compiler-rt/lib/lsan/lsan_common.cc @@ -231,7 +231,7 @@    ForEachExtraStackRange(os_id, ForEachExtraStackRangeCb, frontier);    } -  if (flags()->use_tls) { +  if (0) {    LOG_THREADS("TLS at %p-%p./n", tls_begin, tls_end);    if (cache_begin == cache_end) {    ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable); --- a/llvm/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/llvm/projects/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -163,7 +163,7 @@ static uptr g_tls_size;  #endif  void InitTlsSize() { -#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID +#if 0  typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;  get_tls_func get_tls;  void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); 

build.sh:

#!/bin/bash cd `dirname $(readlink -f $0)` if [ ! -d llvm ] then git clone --depth 1 -b release_36 https://github.com/llvm-mirror/llvm   git clone --depth 1 -b release_36 https://github.com/llvm-mirror/clang llvm/tools/clang   git clone --depth 1 -b release_36 https://github.com/llvm-mirror/compiler-rt llvm/projects/compiler-rt fi patch -Np1 -i musl.patch  mkdir -p build cd build  cmake ../llvm -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ninja

当你搞定了 compiler-rt 补丁并替换系统文件,就可以通过下面命令来编译 main.c 文件,但这次我们启用了 LeakSanitizer :

clang main.c -g -fsanitize=leak -static -nostdinc -nostdlib -I/usr/include/x86_64-linux-musl -L/usr/lib/x86_64-linux-musl -L/usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/x86_64-linux-musl/crt1.o /usr/lib/x86_64-linux-musl/crti.o /usr/lib/x86_64-linux-musl/crtn.o -lgcc_eh -lc

注意其中一个路径指向 GCC 4.8 版本,替换成你本机的版本。

正文到此结束
Loading...