[Mlir-commits] [mlir] Added String and Symbol Obfuscation (PR #169365)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Nov 24 09:01:44 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Shubhang Sinha (Zrahay)
<details>
<summary>Changes</summary>
Added support for String and Symbol Obfuscation for MLIR .
---
Full diff: https://github.com/llvm/llvm-project/pull/169365.diff
6 Files Affected:
- (added) mlir/mlir-obfuscator/CMakeLists.txt (+21)
- (added) mlir/mlir-obfuscator/include/Obfuscator/Passes.h (+13)
- (added) mlir/mlir-obfuscator/lib/CMakeLists.txt ()
- (added) mlir/mlir-obfuscator/lib/Passes.cpp (+68)
- (added) mlir/mlir-obfuscator/lib/SymbolPass.cpp (+87)
- (added) mlir/mlir-obfuscator/test/input.mlir (+10)
``````````diff
diff --git a/mlir/mlir-obfuscator/CMakeLists.txt b/mlir/mlir-obfuscator/CMakeLists.txt
new file mode 100644
index 0000000000000..e565a158d00cb
--- /dev/null
+++ b/mlir/mlir-obfuscator/CMakeLists.txt
@@ -0,0 +1,21 @@
+cmake_minimum_required(VERSION 3.13)
+project(MLIROBF LANGUAGES CXX C)
+
+# Use C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+
+find_package(MLIR REQUIRED CONFIG) # What this does is that it tells the code that I want to use MLIR. Go find it and link to it.
+
+
+message(STATUS "Found MLIR: ${MLIR_PACKAGE_PREFIX}")
+
+
+include_directories(${PROJECT_SOURCE_DIR}/include) # THis helps it find include/Obfuscator/Passes.h
+
+
+add_subdirectory(lib) # This tells the CMake to build the code in mlir-obfuscator/lib/
+
+
+mlir_print_global_pass_registry() # Optional: Thjis is just to print MLIR passes for debugging
diff --git a/mlir/mlir-obfuscator/include/Obfuscator/Passes.h b/mlir/mlir-obfuscator/include/Obfuscator/Passes.h
new file mode 100644
index 0000000000000..f116f56c467ba
--- /dev/null
+++ b/mlir/mlir-obfuscator/include/Obfuscator/Passes.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "mlir/Pass/Pass.h"
+
+namespace mlir {
+
+// Creates the String Encryption Pass
+std::unique_ptr<Pass> createStringEncryptPass(llvm::StringRef key = "");
+
+// Creates the Symbol Obfuscation / Renaming Pass
+std::unique_ptr<Pass> createSymbolObfuscatePass(llvm::StringRef key = "");
+
+} // namespace mlir
diff --git a/mlir/mlir-obfuscator/lib/CMakeLists.txt b/mlir/mlir-obfuscator/lib/CMakeLists.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/mlir/mlir-obfuscator/lib/Passes.cpp b/mlir/mlir-obfuscator/lib/Passes.cpp
new file mode 100644
index 0000000000000..31bf01a044c27
--- /dev/null
+++ b/mlir/mlir-obfuscator/lib/Passes.cpp
@@ -0,0 +1,68 @@
+#include "Obfuscator/Passes.h"
+
+#include "mlir/IR/Attributes.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/IR/MLIRContext.h"
+
+#include <string>
+
+using namespace mlir;
+
+namespace {
+
+/// Simple XOR encryption for demonstration
+static std::string xorEncrypt(const std::string &input, const std::string &key) {
+ std::string out = input;
+ for (size_t i = 0; i < input.size(); i++) {
+ out[i] = input[i] ^ key[i % key.size()];
+ }
+ return out;
+}
+
+/// String Encryption Pass
+struct StringEncryptPass
+ : public PassWrapper<StringEncryptPass, OperationPass<ModuleOp>> { // This lines makes a skeleton for the pass
+
+ StringEncryptPass() = default;
+ StringEncryptPass(const std::string &k) : key(k) {}
+
+ void runOnOperation() override {
+ ModuleOp module = getOperation();
+ MLIRContext *ctx = module.getContext();
+
+ module.walk([&](Operation *op) { // Walk visits every operation in the IR, including the nested ones
+ bool changed = false;
+ SmallVector<NamedAttribute> newAttrs;
+
+ for (auto &attr : op->getAttrs()) {
+ // Only encrypt string attributes
+ if (auto strAttr = attr.getValue().dyn_cast<StringAttr>()) {
+ std::string original = strAttr.getValue().str();
+ std::string encrypted = xorEncrypt(original, key);
+
+ auto newValue = StringAttr::get(ctx, encrypted);
+ newAttrs.emplace_back(attr.getName(), newValue);
+ changed = true;
+ } else {
+ newAttrs.push_back(attr);
+ }
+ }
+
+ // Replace attribute dictionary if something changed
+ if (changed) {
+ op->setAttrDictionary(DictionaryAttr::get(ctx, newAttrs));
+ }
+ });
+ }
+
+ std::string key = "default_key";
+};
+
+} // namespace
+
+/// Factory function exposed to the outside world
+std::unique_ptr<Pass> mlir::createStringEncryptPass(llvm::StringRef key) {
+ return std::make_unique<StringEncryptPass>(key.str());
+}
diff --git a/mlir/mlir-obfuscator/lib/SymbolPass.cpp b/mlir/mlir-obfuscator/lib/SymbolPass.cpp
new file mode 100644
index 0000000000000..6473169cdb3a6
--- /dev/null
+++ b/mlir/mlir-obfuscator/lib/SymbolPass.cpp
@@ -0,0 +1,87 @@
+#include "Obfuscator/Passes.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/SymbolTable.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+
+#include <random>
+
+using namespace mlir;
+
+namespace {
+
+/// Utility: generate random obfuscated names (hex-based)
+static std::string generateObfuscatedName(std::mt19937 &rng) {
+ std::uniform_int_distribution<uint32_t> dist(0, 0xFFFFFFFF);
+ uint32_t num = dist(rng);
+
+ // format as hex string: f_a1b2c3d4
+ char buffer[16];
+ snprintf(buffer, sizeof(buffer), "f_%08x", num);
+ return std::string(buffer);
+}
+
+/// Symbol Obfuscation Pass
+struct SymbolObfuscatePass
+ : public PassWrapper<SymbolObfuscatePass, OperationPass<ModuleOp>> {
+
+ SymbolObfuscatePass() = default;
+ SymbolObfuscatePass(const std::string &k) : key(k) {}
+
+ void runOnOperation() override {
+ ModuleOp module = getOperation();
+ MLIRContext *ctx = module.getContext();
+ SymbolTable symbolTable(module);
+
+ // initialize RNG with deterministic seed (from key)
+ std::seed_seq seq(key.begin(), key.end());
+ std::mt19937 rng(seq);
+
+ // Mapping: oldName -> newName
+ llvm::StringMap<std::string> renameMap;
+
+ // Step 1: Rename symbol definitions (functions)
+ module.walk([&](func::FuncOp func) {
+ StringRef oldName = func.getName();
+ std::string newName = generateObfuscatedName(rng);
+
+ renameMap[oldName] = newName;
+ symbolTable.setSymbolName(func, newName);
+ });
+
+ // Step 2: Update symbol references everywhere
+ module.walk([&](Operation *op) {
+ SmallVector<NamedAttribute> updatedAttrs;
+ bool changed = false;
+
+ for (auto &attr : op->getAttrs()) {
+ if (auto symAttr = attr.getValue().dyn_cast<SymbolRefAttr>()) {
+ StringRef old = symAttr.getRootReference();
+ if (renameMap.count(old)) {
+ auto newRef = SymbolRefAttr::get(ctx, renameMap[old]);
+ updatedAttrs.emplace_back(attr.getName(), newRef);
+ changed = true;
+ continue;
+ }
+ }
+ // no change -> keep original
+ updatedAttrs.push_back(attr);
+ }
+
+ if (changed) {
+ op->setAttrDictionary(DictionaryAttr::get(ctx, updatedAttrs));
+ }
+ });
+ }
+
+ std::string key = "seed";
+};
+
+} // namespace
+
+/// Public factory
+std::unique_ptr<Pass> mlir::createSymbolObfuscatePass(llvm::StringRef key) {
+ return std::make_unique<SymbolObfuscatePass>(key.str());
+}
diff --git a/mlir/mlir-obfuscator/test/input.mlir b/mlir/mlir-obfuscator/test/input.mlir
new file mode 100644
index 0000000000000..76e45f2fe48cb
--- /dev/null
+++ b/mlir/mlir-obfuscator/test/input.mlir
@@ -0,0 +1,10 @@
+// String test
+func.func @hello() attributes { msg = "HELLO WORLD" } {
+ return
+}
+
+// Symbol test
+func.func @main() {
+ %0 = func.call @hello() : () -> ()
+ return
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/169365
More information about the Mlir-commits
mailing list