Hi,

No canadian crosses this time around, this should be easily reproducible on any old linux box.

Let's have the following code in zz.c

#ifdef LIB
void work (char *x) { *x = 'x'; }
void call (char *x, char* y, void (*cb) (char *)) {
  cb (y);
  *x = (*y)++;
}
#else
void work (char *x);
void call (char *x, char* y, void (*cb) (char *));
#endif

#ifndef LIB
int main () {
  char x[10] = {};
  char y[10] = {};
  call (x, y, work);
  puts (x);
  puts (y);
}
#endif

And the following config in zz.conf:
void work(+string);
void call(+string, string, addr);
int puts(string);

Compile it like so:
gcc -DLIB -shared -fpic ~/zz.c -o libzz.so
gcc -ULIB ~/zz.c ./libzz.so -o zz

And run under ltrace (output trimmed):
$ ./ltrace -F zz.conf ./zz
call( <unfinished ...>
work("x") = <void>
<... call resumed> "y", "y", 0x00400548) = <void>
puts("x") = 2
puts("y") = 2
+++ exited (status 2) +++

Notice how "call" is listed with two "y" params, where it should list "x" and "y" (as the following puts calls correctly show). The problem here is that the register set is preserved in struct Process, not in struct callstack_element, and so is overwritten when nested call appears which has right-hand parameters too.

PM

_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/ltrace-devel

Reply via email to