일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- thread local storage
- apm
- linux debugging
- custom packer
- Injection
- so inject
- pthread
- android inject
- 안티디버깅
- pinpoint
- tracerpid
- LLVM
- on stack replacement
- Android
- LLVM 난독화
- anti debugging
- on-stack replacement
- v8 tracing
- OSR
- initial-exec
- Linux custom packer
- uftrace
- v8 optimizing
- Linux packer
- LLVM Obfuscator
- TLS
- tracing
- 난독화
- Obfuscator
- linux thread
- Today
- Total
Why should I know this?
computeKnownBits & KnownBits 관련 예제 본문
https://llvm.org/doxygen/ValueTracking_8cpp.html#a903bd19e9d31beff55b22fe86111639e
Determine which bits of V are known to be either zero or one and return them.
void | computeKnownBits (const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true) |
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOne bit sets. | |
KnownBits | computeKnownBits (const Value *V, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true) |
Returns the known bits rather than passing by reference. | |
KnownBits | computeKnownBits (const Value *V, const APInt &DemandedElts, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true) |
Returns the known bits rather than passing by reference. | |
KnownBits | computeKnownBits (const Value *V, const APInt &DemandedElts, unsigned Depth, const SimplifyQuery &Q) |
Determine which bits of V are known to be either zero or one and return them. | |
KnownBits | computeKnownBits (const Value *V, unsigned Depth, const SimplifyQuery &Q) |
Determine which bits of V are known to be either zero or one and return them. | |
void | computeKnownBits (const Value *V, KnownBits &Known, unsigned Depth, const SimplifyQuery &Q) |
예1)
define i1 @test_and1(i32 %x, i32 %n) {
; CHECK-LABEL: @test_and1(
; CHECK-NEXT: [[NN:%.*]] = and i32 [[N:%.*]], 2147483647
; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[NN]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[C]]
;
%nn = and i32 %n, 2147483647
%a = icmp sge i32 %x, 0
%b = icmp slt i32 %x, %nn
%c = and i1 %a, %b
ret i1 %c
}
(X s>= 0) & (X s< (Y & MAX_VALUE_SIGNED(Y)) --> (Y & MAX_VALUE_SIGNED(Y)) u< X
요렇게 최적화를 할 수 있으려면 조건이 (X s< (Y & MAX_VALUE_SIGNED(Y)) 에서 음수가 아니여야 한다.
이걸 체크하고자 한다면, %nn 의 KnownBit를 구해서, 음수 비트가 세팅되어 있는지 확인해야 한다.
// X s< 0 | X s>= (Y & SIGNED_MAX(Y)) -> (Y & SIGNED_MAX(Y)) u=< X
//
if (match(&I, m_CombineOr(m_c_Or(m_Value(X), m_Value(Y)),
m_c_And(m_Value(X), m_Value(Y))))) {
LLVM_DEBUG(dbgs() << "Match or/and\n");
Value *A, *B, *RangeEnd;
const APInt *RangeStart;
if (match(X, m_c_ICmp(Pred0, m_Value(A), m_APInt(RangeStart))) &&
match(Y, m_c_ICmp(Pred1, m_Specific(A), m_Value(RangeEnd)))) {
LLVM_DEBUG(dbgs() << "RangeStart : " << *RangeStart << "\n");
KnownBits Known =
computeKnownBits(RangeEnd, DL, /*Depth=*/0, &AC, &I, &DT);
LLVM_DEBUG(dbgs() << "RangeEnd bits :"; Known.print(errs()); dbgs() << Known.isNonNegative() << "\n");
}
}
단순화 한 예제 코드를 음수비트가 세팅됐는지 확인하는 코드이다.
[simplify-study]TestBody:1128 test_and1
[simplify-study]knownBitTest:1101 Match or/and
[simplify-study]knownBitTest:1107 RangeStart : 0
[simplify-study]knownBitTest:1110 RangeEnd bits :{Zero=-2147483648, One=0}1
[simplify-study]TestBody:1128 test_or1
[simplify-study]knownBitTest:1101 Match or/and
[simplify-study]knownBitTest:1107 RangeStart : 0
[simplify-study]knownBitTest:1110 RangeEnd bits :{Zero=-2147483648, One=0}1
[simplify-study]TestBody:1128 test_or2
[simplify-study]knownBitTest:1101 Match or/and
[simplify-study]knownBitTest:1107 RangeStart : -1
[simplify-study]knownBitTest:1110 RangeEnd bits :{Zero=-2147483648, One=0}1
KnownBits는 둘로 구성되어 있는데, Zero와 One이다. 각기 0인 비트와 One인 비트로 구성되어 있다.
여기서 Zero가 -2147483648로 된 이유는, 테스트에서 2147483647과 And 연산을 했기 때문이다.
결과로 오직 SIGN BIT 만이 0으로 세팅될 수 있어서 Zero의 Signbit를 검사하는 isNonNegative() 함수는 True 가 된다.
computeKnownBitsFromContext
이름 그대로 Context에서 computeKnownBits를 찾는 함수.
최상단에는 최근에 추가된 DomConditionCache 가 활용된다.
https://die4taoam.tistory.com/150
countMaxTrailingZeros | countMaxTrailingOnes | countMaxLeadingZeros | countMaxLeadingOnes | |
00001011 | 0 | 2 | 4 | 0 |
00010100 | 2 | 0 | 3 | 0 |
구현내용
TrailingsZeros = One.countr_zero -> One의 오른쪽에서 "0" 카운팅 -> One은 1로 세팅된 비트.
-> 0로 세팅된 비트를 오른쪽부터 카운팅
TrailingsOnes = Zero.countr_zero -> Zero의 오른쪽부터 "0" 카운팅 -> Zero는 0로 세팅 가능성 있는 비트.
-> 1로 세팅된 비트를 오른쪽부터 카운팅
Trailings == countr_zero
LeadingZeros = One.countl_zero -> One의 왼쪽에서 "0" 카운팅 -> One은 1로 세팅 가능성 있는 비트.
-> 0로 세팅된 비트를 왼쪽부터 카운팅
LeadingOnes = Zero.countl_zero -> Zero의 왼쪽부터 "0" 카운팅 -> Zero는 0로 세팅 가능성 있는 비트.
-> 1로 세팅된 비트를 왼쪽부터 카운팅
Leading == countl_zero
countMinTrailingZeros | countMinTrailingOnes | countMinLeadingZeros | countMinLeadingOnes | |
00001011 | 0 | 2 | 4 | 0 |
00010100 | 2 | 0 | 3 | 0 |
구현내용
<아직 작성중>
'LLVM-STUDY' 카테고리의 다른 글
[TODO] DomConditionCache (0) | 2023.12.11 |
---|---|
SubclassOptionalData (0) | 2023.12.11 |
byval (0) | 2023.11.07 |
LLVM Study 관련 팁 (0) | 2023.10.25 |
LLVM Pass 작성 - 2018년 이후 (0) | 2023.10.11 |