2013-08-25 39 views
5

我需要通過知道它的地址,並沒有信息 原型(我不能將它轉換爲C函數指針)在C中調用函數。調用C地址作爲函數沒有原型

我對這個功能的信息是它的地址。

我也知道我想傳遞給它的參數(感謝void指針)和參數數組的大小(通過void指針訪問)。

我也想要尊重C調用約定。對於x86版本,我幾乎知道怎麼做(分配堆棧空間,將參數複製到 那個空間並最終調用該函數)。

現在的問題是x64約定(現在是Linux),其中參數是 通過寄存器。我不知道每個參數的大小要填寫 適當的寄存器,我只知道參數數組的大小。

此外,我不想依賴gcc,所以我不能使用__builtin_apply,似乎 是不標準的,也是非常黑暗。

我想寫我自己的一段代碼,以支持多編譯器,也可以到 學習有趣的東西。

因此,基本上,該函數我想要寫爲相同的原型 __builtin_apply它是:

void *call_ptr(void (*fun)(), void *params, size_t size); 

我想也代碼將它寫在C(由於ASM內聯)或純的x64 ASM 。

那麼有沒有一種方法可以正確地做到這一點,並就 公約的慣例?或者,這是不可能的與x64公約不知道 確切的函數原型稱爲?

+4

看看[libffi](http://sourceware.org/libffi/)。 – tangrs

+0

這可能是一個很好的選擇,但libffi的問題是它需要知道每個參數的類型和函數的返回類型。如果可能,我想避免收集這些信息以避免時間浪費。那麼對於x64體系結構,這是可能的嗎? – Zerkan

+1

@Zerkan不,它需要參數的類型,當調用一個函數而不知道參數時,沒有魔法可以將參數放置在正確的寄存器或堆棧空間中。 – nos

回答

0

我認爲,所有你的決定將不支持多編譯器,因爲傳遞參數的機制功能(寄存器,它們的順序,堆棧,內存) - 這是編譯器的依賴性功能...

+3

_ 「這是編譯器依賴功能」_。幸運的是,事實並非如此。至少在編譯器不符合目標操作系統的[ABI](http://en.wikipedia.org/wiki/Application_binary_interface)。 – Michael

+0

是的,當然,它支持一些外部低級接口。但是,支持ABI也是編譯器依賴功能=)只有一件事,任何編譯器都應該支持 - Language Standart –

2

特別是對於Linux上的x64調用約定,這根本不起作用。

原因是非常複雜的調用約定。

一些例子:

void funcA(float64 x); 
void funcB(int64 x); 

在這兩種情況下,值「x」是通過以不同的方式,因爲浮點和整數傳遞給功能在不同的寄存器的功能。

void funcC(float64 x,int64 y); 
void funcD(int64 y,float64 x); 

在這兩種情況下的參數的「x」和「y」是在不同的順序。然而,它們以相同的方式傳遞給函數(兩個函數對「x」使用相同的寄存器,對「y」使用相同的寄存器)。

結論:要創建一個你想要的函數,你必須將包含每個參數的參數類型的字符串傳遞給彙編函數。參數的數量/大小絕對不夠。但是它肯定是可能的 - 只要它只能在Linux上工作。