使用 musl 和 clang 编译 C 程序

红薯 发布于 2015/06/28 08:09
阅读 3K+
收藏 18

假设你正在使用基于 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 版本,替换成你本机的版本。

加载中
0
GunsNRose
GunsNRose
最近看到好像musl的势头要盖过uclibc
0
Force武装卫队
Force武装卫队
musl 代码干净多了,
0
我的上铺叫路遥
我的上铺叫路遥
并将打印一句众所皆知的事实——“glibc is shit”
0
句龙胤
句龙胤
printf("changcheng fire is shit\n");
0
Le_Guto
Le_Guto
你今天改这个,明天改那个,看它会不会变成shit
返回顶部
顶部