[FLUG] Keep on workin'

  • From: "Simon" <f.simon@xxxxxxxx>
  • To: <fanolug@xxxxxxxxxxxxx>
  • Date: Sat, 20 Jul 2002 14:15:17 +0200

Quando si è degli Dei Dorati lo si è e basta.
Veniamo al punto: per il pluridecorato itrace avevo
bisogno di un dyn_caller che mi permettesse passando
attraverso una sola funzione di chiamarne altre.
Insomma chiamare una funzione e dirgli "tu brava
funzioncina fai il tuo dovere... ma poi chiama
quest'altra funzione 'fcn' con questi parametri".

una cosa del tipo:

int dyn_caller(char *str, void *fcn, int stack_size, ...)

Dove fcn è la funzione che poi dyn_caller avrebbe
dovuto chiamare e stack_size la dimensione dello stack
che viene passato (...).
Il parametro str l'ho messo li così non serve a nulla
ora è solo per far vedere che posso passare dei
parametri extra se voglio.

Bene ora come l'ho realizzata:
(i commenti li ho fatti in inglese perchè poi andrà a
finire in itrace quindi non mi va di scriverli 2 volte)

int dyn_caller(char *str, void *fcn, int stack_size, ...)
{
  int ret;
  va_list ap;

  va_start(ap, stack_size);
  __asm__(
    "subl %1,%%esp\n"  /* Create space for new stack */
    "push %1\n"   /* First argument of memmove: size to copy */
    "push %0\n"   /* Second argument of memmove: source */
    "leal 8(%%esp), %%eax\n" /* Load effective address of destination */
    "push %%eax\n"  /* Third argument of memmove: destination */
    "call _memmove\n"  /* Call to memmove */
    "addl $0xC, %%esp\n" /* Move to new crated stack */
    "call *%2\n"  /* Call to *fcn */
    "movl %%eax, %3\n"  /* We save the return of fcn in ret */
    "addl %1,%%esp\n"  /* Restore old position of %esp */
      : : "m" (ap), "m" (stack_size),  "m" (fcn), "m" (ret)
  );
  va_end(ap);

  printf("Log: %s, ret: %i\n", str, ret);
}

Come vedete mi è toccata farla praticamente tutta
in asm... ovvio il C non permette di fare queste
porcherie (altre ma non questa:)... usare parte dello
stack corrente come stack di un'altra funzione.

Questa è la situazione dello stack subito dopo il
prologo di dyn_caller:

4 bytes: va_list ap;  <-- ESP
4 bytes: int ret;
4 bytes: EBP
4 bytes: RET
4 bytes: char *str
4 bytes: void *fcn
4 bytes: int stack_size
x bytes: stack extra

In teoria x dovrebbe essere uguale a stack_size,
quindi prendiamo x = stack_size (ricordatevelo!!!).
A questo punto per creare il nuovo stack per la nuova
chiamata a fcn bisogna "crearlo" abbassando l'ESP
(lo stack si abbassa decrementando ESP, nel nostro
disegno però alzandolo:).
Lo abbassiamo ovviamente quanto basta per mettere tutto
lo stack... ossia della dimensione di stack_size (= x).

x bytes: spazio libero  <-- ESP
4 bytes: va_list ap;
4 bytes: int ret;
4 bytes: EBP
4 bytes: RET
4 bytes: char *str
4 bytes: void *fcn
4 bytes: int stack_size
x bytes: stack extra

Ora per copiare lo "stack extra" nello "spazio libero"
ho usato la memmove. Per usare la memmove bisogna pushare
nello stack i parametri e poi chiamarla, ecco lo stack
con i nuovi parametri della memmove:

4 bytes: par. memmove: dest. ( = spazio libero) <-- ESP
4 bytes: par. memmove: sorg. ( = stack extra)
4 bytes: par. memmove: dimensione da spostare
x bytes: spazio libero
4 bytes: va_list ap;
4 bytes: int ret;
4 bytes: EBP
4 bytes: RET
4 bytes: char *str
4 bytes: void *fcn
4 bytes: int stack_size
x bytes: stack extra

Ora chiamando la memmove copiamo lo "stack extra" in
"spazio libero".
Ora che abbiamo ricreato lo stack basta spostare ESP alla fine
dello "spazio libero" (che contiene lo stack) e chiamare fcn:

4 bytes: STACK SPORCATO PRIMA (par. memmove)
4 bytes: STACK SPORCATO PRIMA (par. memmove)
4 bytes: STACK SPORCATO PRIMA (par. memmove)
x bytes: spazio libero  <-- ESP
4 bytes: va_list ap;
4 bytes: int ret;
4 bytes: EBP
4 bytes: RET
4 bytes: char *str
4 bytes: void *fcn
4 bytes: int stack_size
x bytes: stack extra

Dopo aver chiamato fcn dobbiamo rimettere a posto ESP alla
posizione precedente:

4 bytes: STACK SPORCATO PRIMA (par. memmove)
4 bytes: STACK SPORCATO PRIMA (par. memmove)
4 bytes: STACK SPORCATO PRIMA (par. memmove)
x bytes: STACK SPORCATO PRIMA (spazio libero)
4 bytes: va_list ap; <-- ESP
4 bytes: int ret;
4 bytes: EBP
4 bytes: RET
4 bytes: char *str
4 bytes: void *fcn
4 bytes: int stack_size
x bytes: stack extra

Ecco come funziona tutto l'accrocco!:)

Vi allego un ciaffo funzionante basato su sta cosa.
Come al solito i pagamenti a gecco@xxxxxxxxxxxxx

Certo che sono 37337 da bestia.

PS. se avete occasione... potreste provarlo su un 64bit?
chissà se funge lo stesso...
--
/* Federico 's1m0n' Simoncelli <f.simon@xxxxxxxx>
   http://www.jkcal.org/simon
*/
int main(){unsigned int g,h=0;while(++h){for(g=(h>1)?2:1;g<
h/2+1&&h%g!=0;g++);if(g==h/2+1)printf("%i\n",h);}return 0;}





--
Prendi GRATIS l'email universale che... risparmia: http://www.email.it/f

Sponsor:
Sai cosa è una "lampada di sale"? scoprilo qui:
Clicca qui: http://adv2.email.it/cgi-bin/foclick.cgi?mid=373&d=20-7

Other related posts: