Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

llvm12移植时问题 #1

Open
qwemnbvv opened this issue Mar 19, 2023 · 20 comments
Open

llvm12移植时问题 #1

qwemnbvv opened this issue Mar 19, 2023 · 20 comments

Comments

@qwemnbvv
Copy link

为了支持代码在较高版本的使用,将xVMP.cpp移植到了llvm12下编译完成,但是在编译后的使用存在一些问题
为了支持llvm12的使用,

Value *called_value = inst->getCalledValue();
更改为
Value *called_value = inst->getCalledOperand();

resultValue = IRBcallFunction.CreateCall(value, ArrayRef<Value *>(target_func_args));
更改
FunctionType *funcType = cast(cast(value->getType())->getElementType());
FunctionCallee funcCallee(funcType, value); resultValue = IRBcallFunction.CreateCall(funcCallee, ArrayRef<Value *>(target_func_args));

Value * arg = IRBcon.CreateLoad(ptr);
更改
Value * arg = IRBcon.CreateLoad(target_ptr_type,ptr);

Constant *tmp = Mod->getOrInsertFunction(fun->getName().str(), fun->getFunctionType());
Function *NewF = cast(tmp);
NewF->setLinkage(llvm::GlobalValue::LinkageTypes::InternalLinkage);
更改
FunctionCallee tmp = Mod->getOrInsertFunction(fun->getName().str(), fun->getFunctionType());
Function *NewF = cast(tmp.getCallee());
NewF->setLinkage(llvm::GlobalValue::LinkageTypes::InternalLinkage);
这样在llvm12中可以正常编译,但是在随后在执行pass经过的函数触发了Segmentation fault
我应该继续深入重构代码的实现 或者在代码的更新中出现了错误?

@BRYNHILDRINTHEDARKNESS
Copy link

BRYNHILDRINTHEDARKNESS commented Mar 27, 2023

@qwemnbvv 你好,请问你编译成功了吗?能否留个联系方式共同探讨

@TUGOhost
Copy link

TUGOhost commented Aug 23, 2023

过几天我更新一个llvm 12的版本,目前已经测试迁移到llvm 12成功了,效果也跟作者的类似
image

@TUGOhost
Copy link

不过,他这个虚拟化后的性能以及程序正确性有点问题不知道是不是我改的代码导致的我待会再对比下,看看能不能做点微薄的优化

@BRYNHILDRINTHEDARKNESS
Copy link

不过,他这个虚拟化后的性能以及程序正确性有点问题不知道是不是我改的代码导致的我待会再对比下,看看能不能做点微薄的优化

这个混淆是不是只能针对一些不复杂的代码,如果太复杂是不是也会有问题

@TUGOhost
Copy link

不过,他这个虚拟化后的性能以及程序正确性有点问题不知道是不是我改的代码导致的我待会再对比下,看看能不能做点微薄的优化

这个混淆是不是只能针对一些不复杂的代码,如果太复杂是不是也会有问题

目前测试是这样的,可能跟解释器的实现或者说ir 2 vmcode 有关?对于较为复杂的代码,性能确实堪忧,这块还需要优化的,不过可用的,这个确实是有vmp的效果的

@qwemnbvv
Copy link
Author

问题已经解决了,PassManagerBuilder添加了两次pass,修复后已经可以正常编译和处理,总体修改思路是没有问题的,不过即使在原始版本中测试似乎同样依旧存在一些bug?比较明显的两个是返回值获取和部分结构体处理存在一些问题

@qwemnbvv
Copy link
Author

问题已经解决了,PassManagerBuilder添加了两次pass,修复后已经可以正常编译和处理,总体修改思路是没有问题的,不过即使在原始版本中测试似乎同样依旧存在一些bug?比较明显的两个是返回值获取和部分结构体处理存在一些问题

目前实际代码测试触发情况的一些例子:
1.当函数返回类型为int时如果不在代码中设置返回值编译时会直接报错,潜在问题似乎不止这一点,一些特殊的类型返回似乎同样存在一些问题
2.似乎是vm的通病,测试了很多开源的vm都存在对部分结构体处理时的一些问题,这是一个例子:
size_t preadv(long address, void *buffer, size_t size) { struct iovec iov_ReadBuffer, iov_ReadOffset; iov_ReadBuffer.iov_base = buffer; iov_ReadBuffer.iov_len = size; iov_ReadOffset.iov_base = (void *)address; iov_ReadOffset.iov_len = size;
return syscall(SYS_process_vm_readv, getpid(), &iov_ReadBuffer, 1, &iov_ReadOffset, 1, 0); }
读取其实并没有按照预期进行?
性能延迟是可以因为代码混淆强度是可以被接受的,但其实整个项目如果上方两个问题普遍存在在实用性上更趋向玩具?
普通的更新是没有意义的,作者应该也没有继续维护的打算

@TUGOhost
Copy link

问题已经解决了,PassManagerBuilder添加了两次pass,修复后已经可以正常编译和处理,总体修改思路是没有问题的,不过即使在原始版本中测试似乎同样依旧存在一些bug?比较明显的两个是返回值获取和部分结构体处理存在一些问题

目前实际代码测试触发情况的一些例子: 1.当函数返回类型为int时如果不在代码中设置返回值编译时会直接报错,潜在问题似乎不止这一点,一些特殊的类型返回似乎同样存在一些问题 2.似乎是vm的通病,测试了很多开源的vm都存在对部分结构体处理时的一些问题,这是一个例子: size_t preadv(long address, void *buffer, size_t size) { struct iovec iov_ReadBuffer, iov_ReadOffset; iov_ReadBuffer.iov_base = buffer; iov_ReadBuffer.iov_len = size; iov_ReadOffset.iov_base = (void *)address; iov_ReadOffset.iov_len = size; return syscall(SYS_process_vm_readv, getpid(), &iov_ReadBuffer, 1, &iov_ReadOffset, 1, 0); } 读取其实并没有按照预期进行? 性能延迟是可以因为代码混淆强度是可以被接受的,但其实整个项目如果上方两个问题普遍存在在实用性上更趋向玩具? 普通的更新是没有意义的,作者应该也没有继续维护的打算

大佬,我改后的xVMP pass存在点问题,作者提供的test下的代码稍微复杂的运行停不下来,其次简单点的也会返回0,不知道是不是因为pass改的问题,大佬这边有分享吗?上述的两个问题都可以优化来进行,可以试试

@TUGOhost
Copy link

xVMP.cpp改动点:

Value *called_value = inst->getCalledValue();

改成:

Value *called_value = inst->getCalledOperand();
resultValue = IRBcallFunction.CreateCall(value, ArrayRef<Value *>(target_func_args));

改成:

FunctionType *funcType = cast<FunctionType>(value->getType()->getPointerElementType());
resultValue = IRBcallFunction.CreateCall(funcType, value, ArrayRef<Value *>(target_func_args));
Constant *tmp = Mod->getOrInsertFunction(fun->getName().str(), fun->getFunctionType());
Function *NewF = cast<Function>(tmp);

改成:

FunctionCallee tmp = Mod->getOrInsertFunction(fun->getName(), fun->getFunctionType());
Function *NewF = cast<Function>(tmp.getCallee());

编译这个pass不会报错,用这个pass --xVMP也不会出错,但是运行实际的代码会有问题,要么无限执行不停下,要么返回的结果是错的

@GANGE666
Copy link
Owner

@TUGOhost 我之前在尝试迁移在更高版本LLVM的时候也遇到过类似的情况。Debug后发现vmcode与原始IR有出入,原因为xVMP中直接使用了LLVM定义的BinaryOperator的值,而在LLVM 9之后BinaryOperator发生了变化,导致虚拟化后的程序行为异常。

请修改 xVMPInterpreter.h 中的 BinaryOperator codes 进行测试。

感谢对本项目的关注,欢迎PR!

@BRYNHILDRINTHEDARKNESS
Copy link

@TUGOhost 我之前在尝试迁移在更高版本LLVM的时候也遇到过类似的情况。Debug后发现vmcode与原始IR有出入,原因为xVMP中直接使用了LLVM定义的BinaryOperator的值,而在LLVM 9之后BinaryOperator发生了变化,导致虚拟化后的程序行为异常。

请修改 xVMPInterpreter.h 中的 BinaryOperator codes 进行测试。

感谢对本项目的关注,欢迎PR!

大佬何时做一个llvm12的升级

@TUGOhost
Copy link

感谢大佬,修改 xVMPInterpreter.h 中的 BinaryOperator codes就可以了

@GANGE666
Copy link
Owner

@TUGOhost 我之前在尝试迁移在更高版本LLVM的时候也遇到过类似的情况。Debug后发现vmcode与原始IR有出入,原因为xVMP中直接使用了LLVM定义的BinaryOperator的值,而在LLVM 9之后BinaryOperator发生了变化,导致虚拟化后的程序行为异常。
请修改 xVMPInterpreter.h 中的 BinaryOperator codes 进行测试。
感谢对本项目的关注,欢迎PR!

大佬何时做一个llvm12的升级

我个人短期内事情比较多,估计没有这方面的安排。不过我看有同学在做对LLVM高版本进行适配,也欢迎大家多多讨论、提交代码~

@TUGOhost
Copy link

更新到fork的仓库里了,xVMP代码:https://github.com/TUGOhost/xVMP/tree/llvm-12.0.1/xVMP_plugin

@TUGOhost
Copy link

做了点测试,主要是跑了下作者的tests目录下的程序以及Tigress_protection 下的测试代码,发现如下点:
switch指令不支持,会导致原有逻辑出现错误

[ERROR] Unsupport Instruction:
switch i64 %73, label %sw.epilog [
i64 7, label %sw.bb
i64 6, label %sw.bb58
i64 5, label %sw.bb61
i64 4, label %sw.bb64
i64 3, label %sw.bb67
i64 2, label %sw.bb70
i64 1, label %sw.bb73
]

phi、extractvalue 指令不支持,会导致pass执行时崩溃

[ERROR] Unsupport Instruction:
%cond.i.i = phi i32 [ %call.i.i, %cond.true.i.i ], [ %call3.i.i, %cond.false.i.i ]

[ERROR] Unsupport Instruction:
%26 = extractvalue { i64, i64 } %call27, 0

我尝试写一些优化,目前测试的是c代码,cpp还未涉及

@TUGOhost
Copy link

这几天将写好的pass 用ndk编译,支持到android gradle的编译链路中,发现一些奇怪的现象,主要是ir的指令会根据编译参数的不同而产生不同,会出现phi这种指令,我自己在pass中不对这个处理,但是相应的BinaryOperator指令会用到这个phi指令,所以会出现编译报错的情况,不太懂这块要怎么翻译成功,感觉这种ir 2 vm code的思路需要对每条ir都做一个翻译过程,要不然会遇到各种编译不通过的情况

@wawls
Copy link

wawls commented Nov 5, 2023

@TUGOhost 大佬能否适配一下llvm14

@TUGOhost
Copy link

TUGOhost commented Nov 6, 2023

@TUGOhost 大佬能否适配一下llvm14

适配并不难,大佬主要是关心下相应的llvm变化,以及询问gpt来进行,其次就是解释器中的code了

@TUGOhost
Copy link

TUGOhost commented Nov 6, 2023

这几天将写好的pass 用ndk编译,支持到android gradle的编译链路中,发现一些奇怪的现象,主要是ir的指令会根据编译参数的不同而产生不同,会出现phi这种指令,我自己在pass中不对这个处理,但是相应的BinaryOperator指令会用到这个phi指令,所以会出现编译报错的情况,不太懂这块要怎么翻译成功,感觉这种ir 2 vm code的思路需要对每条ir都做一个翻译过程,要不然会遇到各种编译不通过的情况

这个问题,我后续-O0来解决,其次也解决了phi指令的问题,并不是很难,基本上修复完了,配合-O0来进行使用不会出现什么问题

@wawls
Copy link

wawls commented Dec 24, 2023

这几天将写好的pass 用ndk编译,支持到android gradle的编译链路中,发现一些奇怪的现象,主要是ir的指令会根据编译参数的不同而产生不同,会出现phi这种指令,我自己在pass中不对这个处理,但是相应的BinaryOperator指令会用到这个phi指令,所以会出现编译报错的情况,不太懂这块要怎么翻译成功,感觉这种ir 2 vm code的思路需要对每条ir都做一个翻译过程,要不然会遇到各种编译不通过的情况

这个问题,我后续-O0来解决,其次也解决了phi指令的问题,并不是很难,基本上修复完了,配合-O0来进行使用不会出现什么问题

大佬到时候能发一下源码吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants