[心得] ARM Procedure Call GCC/G++ 4.1.1

看板LinuxDev作者 (晚宴行動如期舉行)時間18年前 (2006/11/21 19:26), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/1
※ [本文轉錄自 gen2linux 信箱] 作者: gen2linux (晚宴行動如期舉行) 看板: LinuxDev 標題: [心得] ARM Procedure Call GCC/G++ 4.1.1 時間: Mon Nov 20 23:40:05 2006 ARM Procedure Call with g++(gcc) 4.1.1 這是一個一般情況下有關 g++(gcc)如何在 ARM平台上實作 procedure call的心得memo ,用的機會雖少,但應該還是可以參考,可運用的場合有二: 1. invoke a C/C++ function in assembly 2. ARM Exploit development 參考文件 Procedure Call Standard for the ARM Architecture http://www.arm.com/miscPDFs/8031.pdf Tool: gcc/g++ 4.1.1, gdb ARM926EJ-S Procedure call規則: 1. R0,R1,R2,R3為傳遞參數的暫存器 2. 若參數超過四個,則再利用stack來傳遞參數 a. Compiler在compile time就決定是否要用stack來傳遞參數 b. 若是,則會將其加入決定caller stack空間的考量(也就是決定caller 之 SP暫存器的位置之時) 3. R11用來作為存取區域變數、函式參數的基準(類似x86的EBP) 4. 32bit和64bit參數(如long long、double)傳遞方式原理相同,只差在一個64bit 參數需要用兩個register或兩個DWord的memory來傳遞,以下是規則 –SP mod 4 = 0(from APCS, Arm Procedure Call Stardard) –32bit參數位址 mod 4 = 0 –64bit參數位址 mod 8 = 0 5. 底下的討論都是在沒有加上最佳化(-O)的情況下, 討論參數為 32bit或 64bit時 的情況 === 參數全為 32bit === int object::func(char c, int i, float f){…} --= Caller方 =-- Caller呼叫某物件的funciton時 1.取得該function位址並存於Rn a、將物件的指標存在R0 b、由指標取得該物件之vtable指標(offset為 0) c、跟據vtable和該函式之索引以取得該函式位址,將該位址存放在空閒的Rn暫存器 2.設定參數,R1~R3為前三個參數 3.把第四個參數設定在[SP], 第五個設在[SP+4], 第六個設在[SP+8]… 4.將PC搬給LR 5.BX Rn,呼叫該函式 6.返回值位於R0 --= Callee方 =-- -Prolog段- 1. 將R11、IP、LR、PC暫存器壓入堆疊,形成所謂的Activation Record。 2. 將有用到的通用暫存器壓入堆疊(optional) 3. 設定R11為SP-4,R11在此函式其間不會再改變 4. 移動SP以空出區域變數、函式參數的空間 5. 將處在R0~R3的函式參數搬移至stack中,以空出R0~R3來利用。往後要存取函式參 數亦如同在存取區域變數,需以R11來參考。 -Code段- 1. 如要存取參數時,亦同存取區域變數的方式,例如第一個參數位於 [r11, #-n] (n由compiler視當時callee區域變數大小決定),則第二個參數位於[r11, #-n-4], 第三個參數位於[r11, #-n-8],第四個參數位於[r11, #-n-16]。 2. 第五個參數以後位在Caller的stack中,故第五個參數則位於[r11, #n+4], 第六個參數位於[r11, #n+8]… -Epilog段- 1. 將結果搬至 R0 2. 移動SP,以縮減掉區域變數/函式參數區,使得SP指向Activation Record。 3. 將Activation Record中的值覆蓋回暫存器,包括R11、SP、LR(無PC)。 4. BX LR,返回原來的的函式 === 參數全為 64bit === int object::func(long long l, double d){…} -- Caller方 -- 1. 流程不變,R0依然指向該物件 2. R1空出,挪為它用 <<< 注意!! 3. R2與R3共同裝填第一個參數,第二個參數填至 [SP]與[SP+4],第三個填至[SP+8]與 [SP+12]… -- Callee 規則不變,只差在每一個函式參數為兩個DWord。 === 參數為 32bit與64bit混合 === int object::func(long long l, int i, double d){…} -- Caller方 -- 需注意要符合規則:64bit參數位址 mod 8 = 0,意即所有64bit參數位址需對齊8, 因為64bit參數和32bit參數一同排列在記憶體中時,很有可能出現64bit參數之位址 不對齊 8,如下圖,0x104 mod 8 != 0, 0x0100 0x104 0x112 [ 1st arg:32bit ][ 2nd argu: 64bit ] 故需增加一無意義的DWord來使得64bit參數與8對齊 0x0100 0x104 x108 0x116 [ 1st arg:32bit ][ dummy:32bit ][ 2nd argu: 64bit ] -- Callee方 -- 存取參數時的規則亦同上面caller方 -- Red Shirt located. Do you have in sight? Red Shirt confirmed. -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.96.111.56 ※ 編輯: gen2linux 來自: 140.96.111.56 (11/21 19:29)
文章代碼(AID): #15Ok9cJu (LinuxDev)
文章代碼(AID): #15Ok9cJu (LinuxDev)