编译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文件,需做以下调整:
- 强制优化级别:内核编译时指定-O2及以上优化级别,确保DAE Pass被触发:
make CC="/path/to/clang" KCFLAGS="-O2" -j$(nproc) - 修正文件名判断逻辑:扩大匹配范围,避免因后缀问题跳过编译单元,例如:
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"; - 确保Clang编译正确:修改LLVM源码后,必须重新完整编译Clang/LLVM项目,确保你的代码被编译进clang二进制文件中,否则修改不会生效。
内容的提问来源于stack exchange,提问作者Sheng Wu
相关产品推荐
相关产品推荐

