Showing posts with label c++. Show all posts
Showing posts with label c++. Show all posts

Friday, December 08, 2006

Backtracing from code in ARM

Recently I found a way to do backtrace from code in ARM processor. On a normal processor glibc itself provides a function called ‘backtrace’ using which we can do backtracing, resolving symbol names and etc. But my glibc (ver 2.95.3) doesn’t support this, so I thought of writing my own backtrace function and the result is this.

The following two pictures shows the structure of activation record in ARM and how it is maintained



So from the above pictures you could have found that the activation records are maintained like a linked list. All we need to find is the start of linked list and travel till there is no more record.

Glibc provides a built in macro ‘__builtin_frame_address’ using which we can find the current frame(activation record) address at any time. So the steps for backtracing are

  • Find current frame address (i.e. __builtin_frame_address)
  • The first four bytes(i.e. *fp) of frame points to program counter (PC), so skip it
  • The next four bytes(i.e. *(fp – 1)) since stack grow downwards) is link register or return address of current function
    • Using this we can find the parent/caller
  • The fourth four bytes(i.e. *(fp – 3)) points to the previous/caller activation record
    • This forms a linked list of activation records and end when *(fp – 3) is ‘0’
Code:

#include <stdio.h>
void backtrace(void* fp)
{
if (fp == 0)
return;

fprintf (stderr, "%p\n", *((int*)fp - 1));
backtrace ((void*)(*((int*)fp - 3)));
}

int bar()
{
printf ("bar\n");
printf ("*** backtrack ***\n");
backtrace (__builtin_frame_address (0));
printf ("\n");

return 0;
}

int foo()
{
printf ("foo\n");
printf ("*** backtrack ***\n");
backtrace (__builtin_frame_address (0));
printf ("\n");

return bar();
}

int main()
{
printf ("main at %p\n", main);
printf ("foo at %p\n", foo);
printf ("bar at %p\n\n", foo);

printf ("main\n");
printf ("*** backtrack ***\n");
backtrace (__builtin_frame_address (0));
printf ("\n");

return foo();
}

Output:
main at 0x919a1160
foo at 0x919a1114
bar at 0x919a1114

main
*** backtrack ***
0x919a13e0
0x919a1418
0x919a1064

foo
*** backtrack ***
0x919a11b8
0x919a13e0
0x919a1418
0x919a1064

bar
*** backtrack ***
0x919a1144
0x919a11b8
0x919a13e0
0x919a1418
0x919a1064

Wrapping malloc/free

Recently I have come across a situation in which I was supposed to detect memory leak in our application. Since we have written our own memory for our application memory requirements, it become easy for me to tell there is no memory leak inside our code. Since memory consumption was continuously increasing we had confirmed there was a memory leak but not in our code. So the only remaining place where the leak could happen is library. Since we don’t have the source of the library we couldn’t confirm the leak. I started googling for memory leak related stuff and finally end up with a solution.

The first solution is hooking malloc/free. This can be done by assigning callback functions to these variables __malloc_hook/__free_hook. But this feature is not available in older glibc (like mine 2.95.3). So I skipped to the second solution, that is wrapping the malloc/free functions with the help of linker, so that every call to malloc/free will notify us and we can do stuffs like profiling, auditing and etc. Seems simple? Yeah, it is simple if know how glibc memory allocator works.

First add the wrapper functions in your source code like below

void* __wrap_malloc(size_t size)
{

// You can call the real malloc by __real_malloc
// You can do also profiling, like how many allocations,
// size of allocations and etc.
}

void* __wrap_realloc(void* oldptr, size_t size)
{

}

void __wrap_free(void* ptr)
{

}


Then use the following LDFLAGS for compiling your program
-Wl,--wrap,malloc,--wrap,free,--wrap,realloc


NOTE: Some linkers (like mine) are very sensitive to the way the parameters are passed, so check

Now any call to malloc/free will come to __wrap_malloc/__wrap_free functions