일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- pthread
- uftrace
- custom packer
- on stack replacement
- 안티디버깅
- tracerpid
- linux debugging
- LLVM
- OSR
- Linux packer
- android inject
- Linux custom packer
- so inject
- v8 tracing
- pinpoint
- Obfuscator
- on-stack replacement
- tracing
- Injection
- LLVM 난독화
- thread local storage
- TLS
- v8 optimizing
- LLVM Obfuscator
- linux thread
- 난독화
- anti debugging
- Android
- initial-exec
- apm
- Today
- Total
Why should I know this?
DEX to IR 개발일지 - Class 변환 본문
Dex2IR 을 개발한지 좀 됐기 때문에 슬슬 구조적으로 생각해야 할 문제들이 보이기 시작해서
기억의 번복을 줄이기 위해 앞으로는 일지를 작성하려고 합니다.
이 글에서 고민하고 싶은건 Class.변환입니다.
바로 들어가죠.
이 고민의 발단이 된 instruction은 iget 입니다.
iget-object p3, p0, Lkotlinx/coroutines/android/a;->_immediate:Lkotlinx/coroutines/android/a;
iget instruction 을 적절히 처리하려면 이제는 class 구조의 도입이 불가피합니다.
iget instruction은 Instance 로부터 field의 값을 읽는 명령어기 때문이죠.
Class는 IR에서 어떻게 다뤄지는 확인해봅시다.
#include <iostream>
class test {
public:
static int si;
double b;
int a;
char c;
short d;
};
int main()
{
test t;
double b = t.b;
int a = t.a;
char c = t.c;
short d = t.d;
int si = t.si;
}
class의 필드에 접근하는 방식을 보기 위해 간단한 코드를 작성했습니다.
ldr x8, [sp, #32]
str x8, [sp, #24]
ldr w8, [sp, #40]
str w8, [sp, #20]
ldrb w8, [sp, #44]
strb w8, [sp, #19]
ldrh w8, [sp, #46]
strh w8, [sp, #16]
adrp x8, :got:_ZN4test2siE
ldr x8, [x8, :got_lo12:_ZN4test2siE]
ldr w8, [x8]
str w8, [sp, #12]
%1 = alloca %class.test, align 8
%2 = alloca double, align 8
%3 = alloca i32, align 4
%4 = alloca i8, align 1
%5 = alloca i16, align 2
%6 = alloca i32, align 4
%7 = getelementptr inbounds %class.test, ptr %1, i32 0, i32 0
%8 = load double, ptr %7, align 8
store double %8, ptr %2, align 8
%9 = getelementptr inbounds %class.test, ptr %1, i32 0, i32 1
%10 = load i32, ptr %9, align 8
store i32 %10, ptr %3, align 4
%11 = getelementptr inbounds %class.test, ptr %1, i32 0, i32 2
%12 = load i8, ptr %11, align 4
store i8 %12, ptr %4, align 1
%13 = getelementptr inbounds %class.test, ptr %1, i32 0, i32 3
%14 = load i16, ptr %13, align 2
store i16 %14, ptr %5, align 2
%15 = load i32, ptr @_ZN4test2siE, align 4
store i32 %15, ptr %6, align 4
class 의 멤버변수에 접근하는 방식은 위와 같습니다.
여기서 문제가 하나 발생하는데, c++에서 class는 형상도 없이 쪼개져서 class.test라는 시작주소를 기준으로 +offset을 하여 field에 접근하게 되죠. 상대주소참조라고 불리는데, 반면 Java 는 모든 field에 대한 접근 방식은 class 에 field를 indexing 하여 접근하는 차이가 있습니다.
iget 명령은 class instance에서 field idx 를 통해 반환하기 때문에 offset을 계산할 필요가 없습니다.
즉, IR로 변환하고자 하는 입장에서는 class를 메모리 chunk 단위로 변환해 field를 offset 으로 참조할 수 있게 만들어야 하는 것이죠.
그래서 향후 필요한 작업을 정리하자면 다음과 같을 것 같습니다.
1. Class를 파싱할때 Static/Instance Field 들이 포함된 Class 구조체를 생성 => IR의 %class.test 처럼
2. 각 field의 field idx 를 생성한 Class 구조체의 멤버변수와 매칭시킬 방안을 강구 (llvm instrict 를 추가?)
3. iget의 instance 내 field 참조를 위의 IR처럼 class 주소 기반 상대주소참조로 변환
'LLVM-STUDY > TODO' 카테고리의 다른 글
LLVM Optimization study - simplify with ChatGPT (0) | 2023.03.19 |
---|---|
LLVM instruction 추가 PR (0) | 2023.03.17 |
LLVM 공부/기록/공유 고민 (0) | 2023.02.27 |
LLVM Optimization study - DCE (0) | 2023.02.17 |
DEX to IR 개발일지 - 간단한 bytecode <> IR 변환, mangling 필요?? (3) | 2023.01.17 |