Exemplo de assinaturas - PUC-Rio

Propaganda
Enunciado T2
Entrega: 14/06 (até 23:59)
create_func: gera, em tempo de execução, uma nova
função a partir de outra função qualquer f (a original)
DynCall create_func(void* f, const char* signature)
Onde:
f = ponteiro para uma função já existente
signature = descrição da assinatura de f (tipo de
parâmetros e valor de retorno),
Create_func retorna um ponteiro para a função gerada
dinamicamente, de tipo DynCall
Typedef void (*DynCall) (Any* params)
A função gerada por create_func
• Recebe como parâmetro um vetor p (tipo Any)
com os argumentos a serem passados à f.
typedef union {
int i;
char c;
double d;
float f;
void* p;
} Any;
• Elemento p[0] fica reservado para o valor de
retorno de f (mesmo que f não retorne valor)
• Os argumentos da chamada a f: de p[1] em
diante
Exemplo de assinaturas
Função original
float f (int a, int b)
String
signature
“ii>f”
void g (int a, double b)
“id”
double h (int n, double* v)
“ip>d”
Cada tipo de parâmetro é indicado por um caracter:
(int, char, double, float, pointer)
Tipo do valor de retorno precedido do caracter ‘>’
Exemplo:
double pow(double x,double y) ≡ xy
• create_func (pow,”dd>d”) deve gerar
código de máquina que equivale ao
procedimento:
void df (Any* v) {
v[0].d = pow(v[1].d, v[2].d);
}
• Implemente também uma free_func
(DynCall f) com código para liberar o espaço
ocupado pela função criada dinamicamente
• O protótipo de create_func e free_func (&
definição de Any) estão em dyncall.h (seu
trabalho deverá ser o dyncall.c)
1
Exemplo:
double pow(double x,double y)
• Uso de create_func (pow,”dd>d”):
#include <math.h>
#include "dyncall.h"
int main (void) {
int i;
Any params[3];
DynCall f = create_func(pow,"dd>d");
params[2].d = 2.0; /* todos os numeros elevados ao quadrado */
for (i = 0; i <= 10; i++) {
params[1].d = i;
f(params);
printf("%.0f^%.0f =.0f\n",params[1].d,params[2].d,params[0].d);
}
free_func(f);
return 0;
}
Create_func
Deve gerar, em um uma área da memória, um trecho de
código em linguagem de máquina que implementa a
função criada dinamicamente
Para isso, create func deve percorrer o vetor signature da
função original e gerar código de máquina que:
• Leia cada parâmetro do vetor params (respeitando os
tipos)
• Use push para empilhar estes parâmetros para
chamada da função original (neste exemplo, pow)
• Chame a função através de “call”
• Use pop para desempilhar os argumentos da pilha
• Armazene em p[0] o valor de retorno da função original
(neste exemplo, pow)
Para descobrir qual é o código de máquina equivalente ao
assembly, leia o manual do Intel Pentium (vol 2), ou
faça engenharia reversa usando:
objdump –d objectfile
Creat_func
• Código de máquina deve ser escrito em vetor de bytes
(alocado previamente)
unsigned char[500] a;
• Para converter end. do vetor para endereço de função,
declare o tipo ponteiro para função (recebendo params e
retornando void), conforme abaixo:
typedef void (*funcp) (Any* params);
• A seguir, atribua o endereço do array a uma variável do
tipo acima:
funcp f = (funcp) a;
• Obs: Use gcc com a opção -Wa,--execstack
2
Download