From cd780517234d61be000ffb921def2e2ce07171d7 Mon Sep 17 00:00:00 2001 From: YingMuo Date: Wed, 30 Apr 2025 03:52:57 +0800 Subject: [PATCH 1/3] feat: lab6 --- .github/workflows/lab-autograding.yml | 3 ++ lab6/Makefile | 14 +++++++++ lab6/README.md | 29 ++++++++++++++++++ lab6/ans | 6 ++++ lab6/llvm-pass.so.cc | 34 +++++++++++++++++++++ lab6/target.c | 29 ++++++++++++++++++ lab6/validate.sh | 43 +++++++++++++++++++++++++++ 7 files changed, 158 insertions(+) create mode 100644 lab6/Makefile create mode 100644 lab6/README.md create mode 100644 lab6/ans create mode 100644 lab6/llvm-pass.so.cc create mode 100644 lab6/target.c create mode 100755 lab6/validate.sh diff --git a/.github/workflows/lab-autograding.yml b/.github/workflows/lab-autograding.yml index 25a89a3..4cd459c 100644 --- a/.github/workflows/lab-autograding.yml +++ b/.github/workflows/lab-autograding.yml @@ -53,4 +53,7 @@ jobs: - name: Grading run: | cd lab${{ steps.lab.outputs.result }} + if [ ${{ steps.lab.outputs.result }} -eq 6 ]; then + sudo apt install -y llvm-14 + fi ./validate.sh diff --git a/lab6/Makefile b/lab6/Makefile new file mode 100644 index 0000000..bd37e34 --- /dev/null +++ b/lab6/Makefile @@ -0,0 +1,14 @@ +all: target + +llvm-pass.so: llvm-pass.so.cc + clang-14 `llvm-config-14 --cxxflags` -shared -fPIC $< -o $@ + +target: target.c llvm-pass.so + clang-14 `llvm-config-14 --cflags` -fexperimental-new-pass-manager \ + -fpass-plugin=./llvm-pass.so $< -o $@ + +run: + ./target 1 + +clean: + rm -f llvm-pass.so target \ No newline at end of file diff --git a/lab6/README.md b/lab6/README.md new file mode 100644 index 0000000..e6c45af --- /dev/null +++ b/lab6/README.md @@ -0,0 +1,29 @@ +# Lab6 + +## Introduction + +In this lab, you will write a llvm pass to instrument some codes to `target.c` in `llvm-pass.so.cc`. + +## Preparation (Important!!!) + +1. Sync fork your branch (e.g., `SQLab:311XXXXXX`) +2. `git checkout -b lab6` (**NOT** your student ID !!!) + +## Requirement + +Write a llvm pass to instrument some codes to `target.c` in `llvm-pass.so.cc` and satisfy following requirements. +1. (40%) Invoke debug function with the first argument is 48763 in main function. +2. (30%) Overwrite argv[1] to "hayaku... motohayaku!" before checking. +3. (30%) Overwrite argc to 48763 before checking. +You can run `validate.sh` in your local to test if you satisfy the requirements. + +Please note that you must not alter files other than `llvm-pass.so.cc`. You will get 0 points if + +1. you modify other files to achieve requirements. +2. you can't pass all CI on your PR. + +## Submission + +You need to open a pull request to your branch (e.g. 311XXXXXX, your student number) and contain the code that satisfies the abovementioned requirements. + +Moreover, please submit the URL of your PR to E3. Your submission will only be accepted when you present at both places. diff --git a/lab6/ans b/lab6/ans new file mode 100644 index 0000000..0d0a0d8 --- /dev/null +++ b/lab6/ans @@ -0,0 +1,6 @@ +./target 1 +deubg mode +argc = 48763 +argv[1] = hayaku... motohayaku! +Your argc is so hayaku! +Suta... basuto... sutorimu! diff --git a/lab6/llvm-pass.so.cc b/lab6/llvm-pass.so.cc new file mode 100644 index 0000000..6c6e17e --- /dev/null +++ b/lab6/llvm-pass.so.cc @@ -0,0 +1,34 @@ +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/IR/IRBuilder.h" + +using namespace llvm; + +struct LLVMPass : public PassInfoMixin { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +}; + +PreservedAnalyses LLVMPass::run(Module &M, ModuleAnalysisManager &MAM) { + LLVMContext &Ctx = M.getContext(); + IntegerType *Int32Ty = IntegerType::getInt32Ty(Ctx); + FunctionCallee debug_func = M.getOrInsertFunction("debug", Int32Ty); + ConstantInt *debug_arg = ConstantInt::get(Int32Ty, 48763); + + for (auto &F : M) { + errs() << "func: " << F.getName() << "\n"; + + } + return PreservedAnalyses::none(); +} + +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "LLVMPass", "1.0", + [](PassBuilder &PB) { + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + MPM.addPass(LLVMPass()); + }); + }}; +} + diff --git a/lab6/target.c b/lab6/target.c new file mode 100644 index 0000000..c13f2b7 --- /dev/null +++ b/lab6/target.c @@ -0,0 +1,29 @@ +#include +#include +#include + +void debug(int id) +{ + if (id == 48763) + printf("deubg mode\n"); + else + printf("bad id!\n"); +} + +int main(int argc, char **argv) +{ + printf("argc = %d\n", argc); + if (argc >= 2) + printf("argv[1] = %s\n", argv[1]); + else + return 0; + if (argc == 48763) + printf("Your argc is so hayaku!\n"); + else + printf("Your argc need to be modohayaku!\n"); + if (strcmp(argv[1], "hayaku... motohayaku!") == 0) + printf("Suta... basuto... sutorimu!\n"); + else + printf("You dead\n"); + return 0; +} diff --git a/lab6/validate.sh b/lab6/validate.sh new file mode 100755 index 0000000..a6128bb --- /dev/null +++ b/lab6/validate.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Check for unwanted files +for file in *; do + if [[ $file != "llvm-pass.so.cc" && $file != "target.c" && $file != "Makefile" && $file != "README.md" && $file != "validate.sh" && $file != "ans" ]]; then + echo "[!] Unwanted file detected: $file." + exit 1 + fi +done + +test_path="${BASH_SOURCE[0]}" +solution_path="$(realpath .)" +tmp_dir=$(mktemp -d -t lab5-XXXXXXXXXX) +answer="" + +cd $tmp_dir + +rm -rf * +cp $solution_path/Makefile . +cp $solution_path/*.c . +cp $solution_path/*.cc . +cp $solution_path/ans . + +make +make run > out 2>&1 +result=$(diff --strip-trailing-cr ans out) +if [[ -n $result ]]; then + echo "[!] Expected: " + cat ans + echo "" + echo "[!] Actual: " + cat out + echo "" + exit 1 +else + echo "[V] Pass" +fi + +rm -rf $tmp_dir + +exit 0 + +# vim: set fenc=utf8 ff=unix et sw=2 ts=2 sts=2: From c6406a3c0ed0e9fa7af54cb655fc2820c1ec2624 Mon Sep 17 00:00:00 2001 From: YingMuo Date: Wed, 30 Apr 2025 03:59:04 +0800 Subject: [PATCH 2/3] fix: lab6 --- .github/workflows/lab-autograding.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lab-autograding.yml b/.github/workflows/lab-autograding.yml index 4cd459c..5be69d2 100644 --- a/.github/workflows/lab-autograding.yml +++ b/.github/workflows/lab-autograding.yml @@ -45,7 +45,7 @@ jobs: const files = await github.rest.pulls.listFiles({ owner, repo, pull_number: issue_number }); const changedFiles = files.data.map((file) => file.filename); const allowedFileRegex = /^lab\d+\/main_test.js$/; - const specialChangedFiles = ["lab0/lab0.js", "lab5/antiasan.c"]; + const specialChangedFiles = ["lab0/lab0.js", "lab5/antiasan.c", "lab6/llvm-pass.so.cc"]; if (!changedFiles.every((file) => (allowedFileRegex.test(file) || specialChangedFiles.includes(file)))) { core.setFailed('The PR contains changes to files other than the allowed files.'); } From 139f54ada2eae49142c611b4951fa1562c031b1a Mon Sep 17 00:00:00 2001 From: banana1715 <82526396+banana1715@users.noreply.github.com> Date: Wed, 7 May 2025 20:11:04 +0800 Subject: [PATCH 3/3] Update llvm-pass.so.cc --- lab6/llvm-pass.so.cc | 56 +++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/lab6/llvm-pass.so.cc b/lab6/llvm-pass.so.cc index 6c6e17e..11943a0 100644 --- a/lab6/llvm-pass.so.cc +++ b/lab6/llvm-pass.so.cc @@ -1,34 +1,62 @@ #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalVariable.h" using namespace llvm; -struct LLVMPass : public PassInfoMixin { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -}; +struct LLVMPass : PassInfoMixin { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) { + LLVMContext &Ctx = M.getContext(); + + // 1) Declare debug prototype: void debug(i32) + FunctionCallee debugFunc = M.getOrInsertFunction( + "debug", + FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, false) + ); + ConstantInt *const48763 = ConstantInt::get(Type::getInt32Ty(Ctx), 48763); + + // 2) Locate main + if (Function *F = M.getFunction("main")) { + BasicBlock &entryBB = F->getEntryBlock(); + // Insert right after any allocas/PHIs in entry + IRBuilder<> builder(&*entryBB.getFirstInsertionPt()); + + // --- (40%) Call debug(48763) --- + builder.CreateCall(debugFunc, {const48763}); -PreservedAnalyses LLVMPass::run(Module &M, ModuleAnalysisManager &MAM) { - LLVMContext &Ctx = M.getContext(); - IntegerType *Int32Ty = IntegerType::getInt32Ty(Ctx); - FunctionCallee debug_func = M.getOrInsertFunction("debug", Int32Ty); - ConstantInt *debug_arg = ConstantInt::get(Int32Ty, 48763); + // --- (30%) Overwrite argc → 48763 --- + // main signature is: i32 @main(i32 %argc, i8** %argv) + Argument *argcArg = &*F->arg_begin(); + argcArg->replaceAllUsesWith(const48763); - for (auto &F : M) { - errs() << "func: " << F.getName() << "\n"; + // --- (30%) Overwrite argv[1] → "hayaku... motohayaku!" --- + Argument *argvArg = &*(std::next(F->arg_begin())); + // Create a global constant string + Value *strPtr = builder.CreateGlobalStringPtr("hayaku... motohayaku!"); + // Compute pointer to argv[1]: getelementptr i8*, i8** %argv, i64 1 + Value *idx1 = ConstantInt::get(Type::getInt64Ty(Ctx), 1); + Value *ptrToArg1 = builder.CreateInBoundsGEP( + argvArg->getType()->getPointerElementType(), // element type = i8* + argvArg, // base pointer i8** + idx1 + ); + // Store the new string into argv[1] + builder.CreateStore(strPtr, ptrToArg1); + } + return PreservedAnalyses::none(); } - return PreservedAnalyses::none(); -} +}; extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { return {LLVM_PLUGIN_API_VERSION, "LLVMPass", "1.0", [](PassBuilder &PB) { PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { + [](ModulePassManager &MPM, OptimizationLevel) { MPM.addPass(LLVMPass()); }); }}; } -