Virtual Method Table을 알아내는 방법은 세가지가 가능함.
1. 인라인 어셈블리 사용
asm {
mov ebx, Form1
mov ebx, [ebx]
mov d1, ebx
}
2. 포인터 이용
d2 = *PDWORD(Form1);
3. __classid 이용
d3 = DWORD(__classid(TForm1));
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
DWORD d1, d2, d3;
// 방법 1
asm {
mov ebx, Form1
mov ebx, [ebx]
mov d1, ebx
}
// 방법 2
d2 = *PDWORD(Form1);
// 방법 3
d3 = DWORD(__classid(TForm1));
Caption = String().sprintf(L"%Xh, %Xh, %Xh", d1, d2, d3);
}
//---------------------------------------------------------------------------
방법 1, 2는 따로 설명할 게 없고, __classid는 사실상 버추얼 메소드 테이블의 위치임.
컴파일러가 바이너리를 생성할 때, 클래스에 대한 정보도 같이 넣게 되는데
앞 부분은 Class Type 정보 혹은 RTTI 정보를 넣고, 뒷 부분은 버추얼 메소드 테이블을 넣음.
----------- Class Type 정보 혹은 RTTI 정보 -----#---------- 버추얼 메소드 테이블 ------
그리고 컴파일러가 __classid가 #의 위치를 가리키도록 코드를 생성하기 때문에
__classid 자체가 버추얼 메소드 테이블의 시작 위치가 되는 셈임.
델파이도 마찬가지임.
procedure TForm1.Button1Click(Sender: TObject);
var
d1, d2, d3 : DWORD;
begin
// 방법 1
asm
mov ebx, Form1
mov ebx, [ebx]
mov d1, ebx
end;
// 방법 2
d2 := PDWORD(Form1)^;
// 방법 3
d3 := DWORD(TComponentClass(TForm1));
Caption := String.Format('%Xh, %Xh, %Xh', [d1,d2,d3]);
end;
방법 1, 2, 3 전부 같은 값을 출력할 것임.
Class Type 정보 혹은 RTTI 구조와 IDE 내부에서 폼 디자이너가 어떤 식으로 구현되어있고 역할을 하게
되는지 강좌로 올려 볼까 했는데, 쓰기 권한이 없다고 해서 간단하게 줄임 ㅋ
델파이 님이 쓰신 글 :
: COM을 어셈블러로 코딩하신거 보고 완전 감동 먹었는데 지나다가님이라면 알고계실지도 모르지요
:
: 관심 가져주셔서 감사합니다 (__)
:
:
:
: 길손 님이 쓰신 글 :
: : 델파이 님이 쓰신 글 :
: : : procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
: : :
: : : 을 후킹해서 TForm으로 부터 상속 받은 유져 폼이 생성되기 전에 유저 폼의 가상함수를 가로채려고 합니다
: : :
: : : 빌더에서
: : : Application->CreateForm(__classid(TForm1), &Form1);
: : :
: : : 위와 같이 __classid(TForm1)이 CreateFrom에 인수로 넘어 오는데요
: : :
: : : 제가 알고자 하는 것은 __classid(TForm1) 값으로 객체 생성 전에 TForm1의 가상함수 테이블을 알아내야 하거든요.
: : :
: : : 방법이 없을까요.
: : :
: : :
: : :
: :
: :
: : __classid가 델파이에서 사용하는 class of 형식의 내부 데이타 구조라서
: : 델파이 컴파일러 만든 사람 아니면 알수 없을걸요? 지나다가님 같은 초고수 분도 이건 모르실듯 한데요
: :