cleanup: address API cleanup review comments

This commit is contained in:
Duncan Ogilvie
2026-05-12 13:52:40 +02:00
parent 08b7d32c68
commit 6dd2bdb9f0
3 changed files with 55 additions and 7 deletions
+2 -2
View File
@@ -632,7 +632,7 @@ Constant* dataArr = ConstantDataArray::get(ctx, arrayRef);
**Python:**
```python
arr = llvm.array_const(elem_ty, [elem1, elem2])
arr = elem_ty.array_const([elem1, elem2])
data_arr = elem_ty.array_const(string_data)
```
@@ -645,7 +645,7 @@ Constant* s = ConstantStruct::get(structTy, {field1, field2});
**Python:**
```python
s = llvm.named_struct_const(struct_ty, [field1, field2])
s = struct_ty.named_struct_const([field1, field2])
```
---
+37 -1
View File
@@ -3,7 +3,12 @@
from pathlib import Path
import llvm
from tools.obfuscation.ollvm_obf import PipelineOptions, apply_pipeline, main
from tools.obfuscation.ollvm_obf import (
PipelineOptions,
apply_pipeline,
main,
poison_internal_uses_before_erasing,
)
def test_ollvm_if_convert_eliminates_phi_and_introduces_select() -> None:
@@ -218,6 +223,37 @@ def test_ollvm_loop_to_recursion_smoke() -> None:
def test_loop_to_recursion_rejects_unresolved_escaping_values() -> None:
ir = r'''
define i32 @f(i32 %x) {
entry:
br label %body
body:
%v = add i32 %x, 1
br label %exit
exit:
%use = add i32 %v, 2
ret i32 %use
}
'''
with llvm.create_context() as ctx:
with ctx.parse_ir(ir) as mod:
fn = mod.get_function("f")
assert fn is not None
body = next(bb for bb in fn.basic_blocks if bb.name == "body")
inst = body.first_instruction
assert inst is not None
try:
poison_internal_uses_before_erasing(inst, {body})
except RuntimeError as exc:
assert "unresolved external use" in str(exc)
assert "poison" in str(exc)
else:
raise AssertionError("expected unresolved external use to be rejected")
assert "poison" not in mod.to_string()
def test_ollvm_loop_to_recursion_skips_multi_exit_loop() -> None:
ir = r'''
define i32 @f(i32 %n) {
+16 -4
View File
@@ -246,9 +246,21 @@ def replace_all_uses_with_if(
user.replace_uses_of_with(old_value, new_value)
def poison_uses_before_erasing(inst: llvm.Value) -> None:
if inst.type.kind != llvm.TypeKind.Void and inst.has_uses:
inst.replace_all_uses_with(inst.type.poison())
def poison_internal_uses_before_erasing(
inst: llvm.Value,
doomed_blocks: set[llvm.BasicBlock],
) -> None:
if inst.type.kind == llvm.TypeKind.Void or not inst.has_uses:
return
for user in inst.users:
if not user.is_instruction or user.block not in doomed_blocks:
raise RuntimeError(
"loop-to-recursion left an unresolved external use of "
f"{inst.name or '<unnamed>'}; refusing to rewrite it to poison"
)
inst.replace_all_uses_with(inst.type.poison())
def position_after_instruction(builder: llvm.Builder, inst: llvm.Value) -> None:
@@ -2512,7 +2524,7 @@ def loop_to_recursion_module(mod: llvm.Module, seed: int, cfg: FilterConfig) ->
for inst in bb.instructions
]
for inst in loop_instructions:
poison_uses_before_erasing(inst)
poison_internal_uses_before_erasing(inst, loop_block_set)
for bb in loop_blocks:
for inst in reversed(list(bb.instructions)):
inst.erase_from_parent()