You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译Linux内核时如何生成所有.c对应的.o及自定义Bitcode文件?

问题:编译Linux内核时无法生成所有.c对应的.bc文件

为满足分析需求,我修改了Clang的llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp文件,添加了生成Bitcode(.bc)文件的代码,代码修改如下:

--- llvm-project2/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp   2020-02-03 20:57:16.473409308 +0000
+++ llvm-project/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp    2020-02-03 20:44:32.478661999 +0000
@@ -49,6 +49,10 @@
 #include <utility>
 #include <vector>
 
+
+#include "llvm/Bitcode/BitcodeWriter.h"
+#include "llvm/Support/ToolOutputFile.h"
+
 using namespace llvm;
 
 #define DEBUG_TYPE "deadargelim"
@@ -1084,6 +1088,22 @@
 
 PreservedAnalyses DeadArgumentEliminationPass::run(Module &M,
                                                    ModuleAnalysisManager &) {
+ 
+  // write out bitcode
+  
+  //outs() << "DeadArg Elimination on " << M.getName() << "\n";
+  std::string FileName = M.getSourceFileName();
+  if(FileName.find(".c") != FileName.npos){
+    std::string Path = M.getSourceFileName() + ".bc";
+    outs() << "Writing to " << Path << "\n";
+    std::error_code EC;
+    raw_fd_ostream out(Path, EC, sys::fs::F_None);
+    WriteBitcodeToFile(M, out);
+    out.flush();
+    out.close();
+    outs() << "Write Done";
+  }
+
   bool Changed = false;
 
   // First pass: Do a simple check to see if any functions can have their "..."

随后使用指令make CC="/path/to/clang" -j$(nproc)编译Linux内核,但未获取到所有.c文件对应的.bc文件。请问该编译指令是否存在问题?如何才能生成所有.c对应的.o文件及目标.bc文件?


解答

现有方法的问题

  • Pass触发条件限制:你添加代码的DeadArgumentElimination是IPO(过程间优化)级别的优化Pass,只有当LLVM启用-O2及以上优化级别,且编译单元触发该Pass时,你的代码才会执行。内核编译中,部分编译单元可能因优化选项、特殊编译流程(如部分模块用-O0编译)等原因,不会运行到这个Pass,因此无法生成.bc文件。
  • 文件名判断逻辑缺陷:代码中仅判断文件名包含.c才生成.bc,但内核编译中部分编译单元的源文件可能经过预处理(如生成.i文件)或使用其他后缀,会被你的判断逻辑跳过。
  • 编译指令未指定优化级别:你使用的make CC="/path/to/clang"指令本身无语法错误,但未指定优化级别,默认情况下部分编译单元可能以-O0编译,不会触发DAE Pass。

推荐解决方案:直接通过Clang选项生成Bitcode(无需修改LLVM源码)

这是最可靠的方式,无需修改LLVM/Clang,直接利用Clang自带选项生成.bc文件,同时保留正常的.o文件生成:

  • 使用-emit-llvm选项:该选项会让Clang在编译每个.c文件时,同步生成对应的Bitcode文件和目标文件。
  • 编译指令修改为:
    make CC="/path/to/clang" KCFLAGS="-emit-llvm" -j$(nproc)
    
    其中KCFLAGS是内核专用的编译选项变量,用于传递针对C代码的编译参数。添加后,每个.c文件编译时会同步生成.bc和.o文件(例如foo.c会生成foo.bc和foo.o)。

若坚持使用修改LLVM Pass的方式(不推荐)

如果必须通过你修改的DAE Pass生成.bc文件,需做以下调整:

  1. 强制优化级别:内核编译时指定-O2及以上优化级别,确保DAE Pass被触发:
    make CC="/path/to/clang" KCFLAGS="-O2" -j$(nproc)
    
  2. 修正文件名判断逻辑:扩大匹配范围,避免因后缀问题跳过编译单元,例如:
    std::string FileName = M.getSourceFileName();
    // 移除原有后缀,直接添加.bc后缀
    size_t dotPos = FileName.find_last_of('.');
    std::string baseName = (dotPos != std::string::npos) ? FileName.substr(0, dotPos) : FileName;
    std::string Path = baseName + ".bc";
    
  3. 确保Clang编译正确:修改LLVM源码后,必须重新完整编译Clang/LLVM项目,确保你的代码被编译进clang二进制文件中,否则修改不会生效。

内容的提问来源于stack exchange,提问作者Sheng Wu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 07:30:26