2013-08-25 26 views
5

Ho bisogno di chiamare una funzione in C solo conoscendo l'indirizzo, e nessuna informazione su di esso prototipo (non posso lanciarlo su un puntatore di funzione C).Chiamare l'indirizzo C come funzione senza prototipo

Le informazioni che ho su questa funzione sono l'indirizzo.

Conosco anche i parametri che desidero passare ad esso (grazie a un puntatore del vuoto) e la dimensione dell'array di argomenti (accessibile tramite il puntatore del vuoto).

Voglio anche rispettare la convenzione di chiamata C. Per la versione x86, ho più o meno sapere come farlo (allocare lo spazio sullo stack, copiare i parametri su quello spazio e infine chiamare la funzione).

Il problema è con la convenzione x64 (Linux per ora) dove i parametri sono passati attraverso i registri. Non ho idea della dimensione di ciascun parametro per riempire registri in modo appropriato, conosco solo la dimensione della serie di parametri.

Inoltre, non voglio dipendere da gcc, quindi non posso usare __builtin_apply che sembra essere lo standard e anche essere piuttosto scuro.

Voglio scrivere la mia parte di codice per supportare il multi-compilatore e anche per imparare cose interessanti.

Quindi, in pratica, la funzione Voglio scrivere come lo stesso prototipo di __builtin_apply quali è:

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

voglio anche il codice per scrivere in C (grazie a asm inline) o asm x64 puro .

Quindi esiste un modo per farlo correttamente e nel rispetto della convenzione chiamata ? O è impossibile con la convenzione x64 senza conoscere esattamente il prototipo della funzione?

+4

Dai un'occhiata a [libffi] (http://sourceware.org/libffi/). – tangrs

+0

Questa potrebbe essere un'ottima alternativa, ma il problema con libffi è che è necessario conoscere il tipo di ciascun parametro e il tipo di ritorno della funzione. Voglio evitare di raccogliere queste informazioni per evitare perdite di tempo se possibile. Quindi è possibile con l'architettura x64? – Zerkan

+1

@Zerkan no non lo è, hai bisogno dei tipi di parametri, non c'è magia che possa posizionare i parametri nei registri appropriati o impilare lo spazio quando si chiama una funzione senza conoscere gli argomenti – nos

risposta

0

penso, tutta la vostra decisione non sarà supportato multi-compilatore, perché il meccanismo di passaggio di argomenti alla funzione (registri, il loro ordine, pila, memoria) - E 'caratteristica dipendenza compilatore ...

+3

_ "è la funzione di dipendenza del compilatore" _. Fortunatamente non lo è. Almeno non se il compilatore aderisce alla [ABI] (http://en.wikipedia.org/wiki/Application_binary_interface) del SO di destinazione. – Michael

+0

Sì, certo, supporta alcune interfacce esterne di basso livello. Ma il supporto di ABI è anche la funzione di dipendenza dal compilatore =) Solo una cosa, che qualsiasi compilatore dovrebbe supportare esattamente - Language Standart –

2

Specialmente per la convenzione di chiamata x64 su Linux, questo non funzionerà affatto.

Il motivo è la convenzione di chiamata molto complicata.

Alcuni esempi:

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

In questi due casi il valore "X" viene passato alle funzioni diverso perché in virgola mobile e interi vengono passati alle funzioni in diversi registri.

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

In questi due casi gli argomenti "x" e "y" sono in ordine diverso. Tuttavia vengono passati alla funzione nello stesso modo (entrambe le funzioni usano lo stesso registro per "x" e lo stesso registro per "y").

Conclusione: per creare una funzione che esegue ciò che si desidera, è necessario passare una stringa contenente i tipi di argomento di ciascun argomento alla funzione assembler. Il numero/dimensione degli argomenti non è decisamente sufficiente.Tuttavia sarebbe sicuramente possibile, a condizione che funzioni solo su Linux.

Problemi correlati