4.1 The Skeleton of Program Function
要分析及轉換一個程式前,我們必須先了解一個程式的結構,以下面一個C語言所 寫的範例為例:
void main() {
printf(“ 5 + 5 = ", add(5,5));
}
int add(x,y) {
return sum(5,5);
}
程式由小到大的分別由三個步驟完成,如Table 13紅色箭頭所示:
Step 1:單一識別子( Single Identifier)組成一行函數原型(Function Prototype)。
Step 2:每個單行的函數原型再組成一個函數區塊(Function Block)。
Step 3:所有函數區塊的集合就形成了最後的程式區段(Program Section)。
Element Example
Single Identifier void、main、int、printf、sum 、return
Function Prototype
printf(“ 5 + 5 = ", add(5,5)); 、 sum(5,5);
Function Block
int add(x,y) {
return sum(5,5);
}
Program Section
void main() {
printf(“ 5 + 5 = ", add(5,5));
}
int add(x,y) {
return sum(5,5);
}
Table 13: Construct a Program Function
把要比對的識別子(Identifier)分成五種型態,存在資料庫並給予一個代號(flag)來區 別,如Table 14所示,藍色字體為Windows Identifier、紅色字體為Linux Identifier,分別 介紹如下:
No Flag Type Example
1 F Function ExFreePoolÆkfree
KeSetPriorityThreadÆset_user_nice 2 S Status STATUS_UNSUCCESSFULÆ-EFAULT
STATUS_DEVICE_BUSYÆ-EBUSY 3 P Function Parameter PagedPoolÆGFP_KERNEL
NonPagedPoolÆGFP_ATOMIC 4 T Data Type PUINTÆunsigned int *
KSPIN_LOCK Æspinlock_t LIST_ENTRYÆlist_head 5 D Driver Only DriverEntryÆfile_operations
DEVICE_EXTENSIONÆprivate_data
Table 14: The Category of Single Identifier
z 第一種F為函數,釋放記憶體的函數原型在Windows和Linux分別為:
VOID ExFreePool(IN PVOID P);
void kfree (void *ptr);
以及調整執行緒優先權的函數原型在Windows和Linux分別為:
KPRIORITY KeSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority);
void set_user_nice ( task_t *p , long nice);
以及插入項目到串列尾部的函數原型在Windows和Linux分別為:
VOID InsertTailList(IN PLIST_ENTRY ListHead,IN PLIST_ENTRY Entry);
void list_add_tail(struct list_head *new, struct list_head *head);
z 第二種S為回傳的狀態值,失敗的回傳值在Windows和Linux分別為:
STATUS_UNSUCCESSFUL -EFAULT
以及裝置忙碌的回傳值在Windows和Linux分別為:
STATUS_DEVICE_BUSY -EBUSY
z 第三種P為函數的參數值,可移出分頁的參數在Windows和Linux分別為:
PagedPool GFP_KERNEL
以及不可移出分頁的參數在Windows和Linux分別為:
NonPagedPool GFP_ATOMIC
z 第四種T為資料型態,指向無正負符號的整數型態變數,在Windows和Linux 分別為:
PUINT unsigned int *
以及自旋鎖的資料型別在Windows和Linux分別為:
KSPIN_LOCK spinlock_t
以及雙向鏈結串列型態在Windows和Linux分別為:
LIST_ENTRY list_head
z 第五種D為驅動程式特有的識別子,驅動程式指定Entry Function在Windows和 Linux分別為:
DriverEntry file_operations
以及驅動程式內部資料在Windows和Linux分別為:
DEVICE_EXTENSION private_data
4.2 Classify the Map with Driver Function
收集常用的Function比對後,可以完全對應(Full Map)的Identifier有77個,部分對應 (Partial Map)的有33個,只有Windows才有的Function有73個,只有Linux才有的Function 有28個,如Table 15。
Symbol Map Count
0 Full Map 77
1 Partial Map 33
2 Only for Windows, will mark it 73 3 Only for Linux, no influence or added 28
Total 211 Table 15: The Statistic of Function Map
兩邊的程式都是使用C語言來撰寫,所以平時用到的函數,如sizeof()、sum()函數
Windows Linux
Function Prototype
VOID RtlCopyMemory(
IN VOID UNALIGNED *Destination, IN CONST VOID UNALIGNED *Source, IN SIZE_T Length
);
Unsigned long copy_from_user(
void *to,
Table 16: Full Map with Data Copy Function
z Partial Map:函數功能完全相同但參數部分相同,以I/O位址對映到記憶體的函 數為例,如Table 17,在Windows的函數名為MmMapIoSpace,在Linux函數名 為ioremap,均有指定記憶體位置及大小的參數,但Windows平台多了一個指 定CacheType的參數。
Windows Linux
Function Prototype PVOID MmMapIoSpace(IN
PHYSICAL_ADDRESS PhysicalAddress, IN ULONG NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType );
void *ioremap(
unsigned long phys_addr, unsigned long size );
Token with parameter
MmMapIoSpace ioremap
Table 17: Partial Map with I/O Map Function
另一個類似的例子是將某塊記憶體清空為零的函數,如Table 18,在Windows的函 數名為RtlZeroMemory對應到Linux的函數名為memset,均有指定記憶體位置及長度的參 數,但Linux平台的函數較有彈性,在第二個參數可設定將記憶體清成偏好的值。此部
分要轉換必須將各個Identifier轉成Lex/Yacc可辨識的Token,再重新排放。
Windows Linux
Function Prototype VOID RtlZeroMemory(
IN VOID UNALIGNED *Destination, IN SIZE_T Length
);
void *memset(
void *s,
int c, // can set to prefer value size_t n
);
Table 18: Partial Map with Memory Set Function
z 特殊情況一:Windows沒有但Linux才有的函數,像module_init及module_exit 這兩個函數是Linux Driver特有的函數,如Table 19。此部分轉換後由Driver Generator另行加入程式碼即可。
Map Type Include Windows Linux
2 F linux/init.h Windows not Exist but Linux Exist module_init(XXX_init);
2 F linux/init.h Windows not Exist but Linux Exist module_exit(XXX_exit);
Table 19: Linux Only Function
z 特殊情況二:Windows有但Linux沒有的函數,像IoCreateSymbolicLink及 IoDeleteSymbolicLink這兩個函數是Windows Driver特有的函數,如Table 20。
此部分轉換到Linux後必須將Windows程式註解掉。
Map Type Include Windows Linux
3 F IoCreateSymbolicLink Windows Exist but Linux not Exist 3 F IoDeleteSymbolicLink Windows Exist but Linux not Exist
Table 20: Windows Only Function
有了上面的分類基礎及處理方式才能著手建立轉換模式,在後面的章節我們會使用 Lex/Yacc[19][20]來做轉換,並將這些函數的對應建立在資料庫裏以便做前置處理。