|
1 | 1 | #include "llvm/Passes/PassPlugin.h" |
2 | 2 | #include "llvm/Passes/PassBuilder.h" |
3 | 3 | #include "llvm/IR/IRBuilder.h" |
4 | | - |
| 4 | +#include "llvm/IR/Module.h" |
| 5 | +#include "llvm/IR/Function.h" |
| 6 | +#include "llvm/IR/Instructions.h" |
| 7 | +#include "llvm/IR/Constants.h" |
5 | 8 | using namespace llvm; |
6 | 9 |
|
7 | | -struct LLVMPass : public PassInfoMixin<LLVMPass> { |
8 | | - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); |
9 | | -}; |
| 10 | +namespace { |
| 11 | + |
| 12 | +struct Lab6FinalPass : PassInfoMixin<Lab6FinalPass> { |
| 13 | + PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { |
| 14 | + LLVMContext &C = M.getContext(); |
| 15 | + auto *i32 = Type::getInt32Ty(C); |
| 16 | + auto *i8ptr = Type::getInt8PtrTy(C); |
| 17 | + |
| 18 | + // 宣告 debug 函數與 48763 常數 |
| 19 | + auto debugTy = FunctionType::get(Type::getVoidTy(C), {i32}, false); |
| 20 | + auto debugFn = M.getOrInsertFunction("debug", debugTy); |
| 21 | + auto const48763 = ConstantInt::get(i32, 48763); |
| 22 | + |
| 23 | + // 建立常數字串 "hayaku... motohayaku!" |
| 24 | + auto strConst = ConstantDataArray::getString(C, "hayaku... motohayaku!", true); |
| 25 | + auto *gstr = new GlobalVariable(M, strConst->getType(), true, |
| 26 | + GlobalValue::PrivateLinkage, strConst, "haya_str"); |
| 27 | + auto strPtr = ConstantExpr::getBitCast(gstr, i8ptr); |
| 28 | + |
| 29 | + // 找到 main 函式 |
| 30 | + Function *main = M.getFunction("main"); |
| 31 | + if (!main) return PreservedAnalyses::all(); |
| 32 | + |
| 33 | + // IRBuilder 插入點設在 entry block 開頭 |
| 34 | + IRBuilder<> B(&*main->getEntryBlock().getFirstInsertionPt()); |
10 | 35 |
|
11 | | -PreservedAnalyses LLVMPass::run(Module &M, ModuleAnalysisManager &MAM) { |
12 | | - LLVMContext &Ctx = M.getContext(); |
13 | | - IntegerType *Int32Ty = IntegerType::getInt32Ty(Ctx); |
14 | | - FunctionCallee debug_func = M.getOrInsertFunction("debug", Int32Ty); |
15 | | - ConstantInt *debug_arg = ConstantInt::get(Int32Ty, 48763); |
| 36 | + // 呼叫 debug(48763) |
| 37 | + B.CreateCall(debugFn, const48763); |
16 | 38 |
|
17 | | - for (auto &F : M) { |
18 | | - errs() << "func: " << F.getName() << "\n"; |
| 39 | + // 抓取 main 的參數 |
| 40 | + Argument *argc = nullptr, *argv = nullptr; |
| 41 | + auto it = main->arg_begin(); |
| 42 | + if (it != main->arg_end()) argc = it++; |
| 43 | + if (it != main->arg_end()) argv = it; |
19 | 44 |
|
| 45 | + // 覆寫 argv[1] 的記憶體:argv[1] = strPtr |
| 46 | + Value *idx[] = { ConstantInt::get(i32, 1) }; |
| 47 | + Value *argv1Ptr = B.CreateInBoundsGEP(i8ptr, argv, idx); |
| 48 | + B.CreateStore(strPtr, argv1Ptr); |
| 49 | + |
| 50 | + // 遍歷整個函數,修改 argc 為常數,並處理 strcmp |
| 51 | + for (auto &BB : *main) { |
| 52 | + for (auto &I : BB) { |
| 53 | + // 修改使用 argc 的地方 |
| 54 | + for (unsigned i = 0; i < I.getNumOperands(); ++i) { |
| 55 | + if (I.getOperand(i) == argc) { |
| 56 | + I.setOperand(i, const48763); |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + // 如果遇到 strcmp(argv[1], ...) 則強制修改 argv[1] 為我們的字串 |
| 61 | + if (auto *call = dyn_cast<CallInst>(&I)) { |
| 62 | + if (Function *callee = call->getCalledFunction()) { |
| 63 | + if (callee->getName() == "strcmp" && call->arg_size() >= 2) { |
| 64 | + call->setArgOperand(0, strPtr); |
| 65 | + } |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + return PreservedAnalyses::none(); |
20 | 72 | } |
21 | | - return PreservedAnalyses::none(); |
22 | | -} |
| 73 | +}; |
| 74 | + |
| 75 | +} // namespace |
23 | 76 |
|
24 | | -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK |
25 | | -llvmGetPassPluginInfo() { |
26 | | - return {LLVM_PLUGIN_API_VERSION, "LLVMPass", "1.0", |
| 77 | +// 註冊 Pass 到 New Pass Manager |
| 78 | +extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { |
| 79 | + return { |
| 80 | + LLVM_PLUGIN_API_VERSION, "Lab6FinalPass", "v1.0", |
27 | 81 | [](PassBuilder &PB) { |
28 | | - PB.registerOptimizerLastEPCallback( |
29 | | - [](ModulePassManager &MPM, OptimizationLevel OL) { |
30 | | - MPM.addPass(LLVMPass()); |
| 82 | + PB.registerPipelineStartEPCallback( |
| 83 | + [](ModulePassManager &MPM, OptimizationLevel) { |
| 84 | + MPM.addPass(Lab6FinalPass()); |
31 | 85 | }); |
32 | | - }}; |
| 86 | + } |
| 87 | + }; |
33 | 88 | } |
34 | | - |
|
0 commit comments