2013-08-25 19 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をしたいです。

これを適切に行うには、呼び出し元の の規約について、または、これはx35のコンベンションでは不可能です という関数のプロトタイプを正確に知らないのですか?

+4

[libffi](http://sourceware.org/libffi/)をご覧ください。 – tangrs

+0

これは素晴らしい選択肢ですが、libffiの問題は、各パラメータの型と関数の戻り値の型を知る必要があることです。可能であれば、これらの情報を収集しないようにして、時間の損失を避けたいと考えています。それでは、x64アーキテクチャで可能ですか? – Zerkan

+1

@Zerkanいいえ、パラメータの型が必要です。引数を知らなくても関数を呼び出すときには、適切なレジスタやスタック空間にパラメータを置くことはできません。 – nos

答えて

0

私はあなたの決定のすべてが関数に引数を渡す仕組み(レジスタ、そのため、スタック、メモリ)ので、マルチコンパイラはサポートされません、と思う - それはコンパイラ依存の機能です...

+3

_ "それはコンパイラの依存機能" _です。幸い、そうではありません。少なくともコンパイラがターゲットOSの[ABI](http://en.wikipedia.org/wiki/Application_binary_interface)を遵守していない場合は、 – Michael

+0

はい、もちろん、それはいくつかの外部低レベルインタフェースをサポートしています。しかし、ABIのサポートはコンパイラ依存の機能でもあります=)コンパイラが正確にサポートしなければならないことは1つだけです - 言語Standart –

2

特に、 Linuxのx64呼び出し規約の場合、これはまったく機能しません。

理由は非常に複雑な呼び出し規約です。

いくつかの例:浮動小数点と整数を異なるレジスタ内の関数に渡されるので、これらの2つの場合において

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

は、値「X」は、異なる関数に渡されます。これらの2つの場合において

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

引数「X」と「Y」は、異なる順序です。しかし、それらは同じ方法で関数に渡されます(両方の関数が "x"に同じレジスタを使用し、 "y"に同じレジスタを使用します)。

結論:必要な機能を作成するには、各引数の引数型を含む文字列をアセンブラ関数に渡す必要があります。引数の数/サイズは間違いなく十分です。しかし、Linux上でのみ動作しなければならない限り、間違いなく可能です。

関連する問題