The pintool is broken.
The pintool is broken. I shouldn't have merged it.
This isn't easy to get right because pintools isn't the right tool for the job. ltrace or LD_PRELOAD should be used to debug dynamic calls. If someone wants to fix this OK. Here are the issues:
- There is no guarantee a called function will return using pintools because said function can jump into another one that isn't instrumented. For the pintool to be considered "working" it should handle this case and not be implementation dependent. This is a major issue. For example, on linux, calloc jumps into malloc at some point.
- The pintool doesn't detect abnormal termination of the program. Abort or Segfault, etc. In general it should tell villoc that a function didn't return. Villoc will know what to do and mark corresponding blocks as failures. This is important.
- The output isn't the same as ltrace's, (there is a missing space after the ',' in argument lists). This could also be fixed on villoc's side by changing the regex. Minor issue.
As an example, the following program produces wrong output:
#include <stdlib.h>
int main(int argc, char **argv)
{
(void) argc, (void) argv;
void *a;
int i;
for (i = 0; i < 10; ++i)
{
a = malloc(i * 1000);
if (i % 2)
free(a);
}
return 0;
}
Produces this trace on my setup:
realloc(0x0, 1425) = 0x7fcdd4237758
realloc(0x0, 1169) = 0x7fcdd4237bf0
realloc(0x0, 16) = 0x7fcdd4237bf8
realloc(0x0, 32) = 0x7fcdc0f8f4a0
realloc(0x0, 1178) = 0x7fcdc0f8f950
realloc(0x0, 40) = 0x7fcdc0f8f988
realloc(0x0, 40) = 0x7fcdc0f8f998
realloc(0x0, 56) = 0x7fcdc0f8f9a8
malloc(0) = 0x2527010
malloc(1000) = 0x2527030
free(0x2527030) = <void>
malloc(2000) = 0x2527030
malloc(3000) = 0x2527810
free(0x2527810) = <void>
malloc(4000) = 0x2527810
malloc(5000) = 0x25287c0
free(0x25287c0) = <void>
malloc(6000) = 0x25287c0
malloc(7000) = 0x2529f40
free(0x2529f40) = <void>
malloc(8000) = 0x2529f40
malloc(9000) = 0x252be90
free(0x252be90) = <void>
Villoc shows the final state as being:

Which is obviously wrong as the program is perfectly valid and shouldn't produce overlapping blocks.
@sam-b maybe you could look at this?
Just made a pull request to address some of this - the overlapping blocks seem to be from the loader which does some funky memory allocation that wouldn't normally be valid, the version in the pull request avoids this by only instrumenting after main is called. I also fixed the minor formatting issue.
It should definitely be possible to detect abnormal program termination as people are pin for fuzzing instrumentation, would need to have a look into this though.
I'm not entirely sure if over coming the first issue is easily do-able.
Obviously if you don't think pin is appropriate for this use case you can feel free to remove it from the repository.
Thanks for the work and the investigation! I'll look into this soon.
I don't have anything against pin :) I think it's something lots of people would want to try and it's a good thing an example is available in the repository. What I'm saying is that for simply monitoring calls to malloc & friends hooking the shared library using ltrace or LD_PRELOAD is probably easier and more exact when this is possible. Obviously having the pin tool is very useful when analyzing statically linked stuff or other anti-debugging tricks!
I confirm seeing this issue on my Gentoo into my own pin tool. Maybe one solution is to filter the IMGs we instrument and skeep instrumentation of "ld-linux-x86-64.so.2" :
if (strncmp(IMG_Name(img).c_str(),"ld-linux",8) != 0)
{
instrImageMalloc(img,v);
instrImageNew(img,v);
instrImageRealloc(img,v);
instrImageCalloc(img,v);
}