# Storage Allocation Hooks in C



## sverch (Feb 20, 2011)

Hi all, this is my first time posting on these forums.  I am hoping that I picked the right forum for this topic.  Please let me know if there is a better place for this.

I am currently porting a user space threads package called "capriccio" to FreeBSD for a research project.  

The original Linux version can be found here: http://capriccio.cs.berkeley.edu/

I have never ported anything to FreeBSD before, so I am really just jumping in right now.

My current problem is that memory allocation hooks that appear to be Linux specific are being used to trace memory usage.  

Here is the man page for those hooks: http://linux.die.net/man/3/malloc_hook

And here is part of the code that uses them:

```
typeof(__free_hook) orig_free_hook;
typeof(__malloc_hook) orig_malloc_hook;
typeof(__realloc_hook) orig_realloc_hook;


static void *capriccio_malloc_hook(size_t size, const void *callsite)
{
  void *ret;
  (void) callsite;
  
  // FIXME: race
  __malloc_hook = orig_malloc_hook;
  ret = malloc(size);
  __malloc_hook = (typeof(__malloc_hook))capriccio_malloc_hook;

  if( !ret ) return NULL;

  thread_stats_add_heap( malloc_usable_size(ret) );
  
  return ret;
}
```

The build terminates with:

[cmd=]resource_stats.c:58: error: '__free_hook' undeclared here (not in a function)
[/cmd]

Is there a way to get these hooks for FreeBSD?  Is there a FreeBSD equivalent that would provide the same functionality?  I found ways to override built in functions using #define, but I'm wondering if there is another way.  Note that these hooks also give you the information about the call site, but I looked through the code and it is not being used so that information is optional.

Thanks in advance for your help/explanation!


----------



## expl (Feb 21, 2011)

Does not look like a complicated interface. Easy to implement by overwriting the libc hook with your own and calling the linux format functions for user hooks.


----------



## sverch (Feb 21, 2011)

Thanks for the quick reply!  I think I understand the general idea, but I don't really know where to start.  How do I overwrite the libc hook?  How do I call the linux functions for user hooks?  Do I need to install something for linux compatibility?  If you could point me to any references/man pages that I should read through to get more familiar with this I would be grateful.  I looked a the malloc_hook man page on linux, and it talks about how to use the interface, not about how to implement it.


----------



## expl (Feb 22, 2011)

Sorry for not being so clear. When I say overwrite a hook I mean overwrite the function's definition that you want to hook into. As when you call a function most recent definition is used.


----------



## sverch (Feb 23, 2011)

So for this I would have a header file that contains something like:


```
#define malloc mymalloc
```

Am I correct in the observation that this doesn't end up getting me the call site information?  That is fine, but I just want to make sure that I'm understanding what you mean.


----------



## sverch (Mar 2, 2011)

Actually, it seems like my best option is to just use dlsym to access the dynamic linker directly and just define my own function.  Is this a good approach?  Would there be a way to get the call site information that way?  Is this what you had in mind?  Thanks!


----------



## expl (Mar 3, 2011)

Sorry, I forgot about your problem.

Here is a quick hook implementation by me:


```
#include <sys/types.h>

#include <stdio.h>
#include <dlfcn.h>

/*HOOKS IMPLEMENTATION*/
#define PARENT_FRAME 0x01

void *(*__malloc)(size_t size);
void *(*__malloc_hook)(size_t size, const void *caller);
void *(*__cur_malloc_hook)(size_t size, const void *caller);

void *malloc(size_t size){
	const void *caller = __builtin_return_address(PARENT_FRAME);
	__malloc = dlsym(RTLD_NEXT, "malloc");
	
	if(__malloc_hook)
		return __malloc_hook(size, caller);

	return __malloc(size);
}

/*IMPLEMENTATION ENDS AND USER APP CODE BEGINS*/

void *my_hook(size_t size, const void *caller){
	/*protecting our hook's printf from endless recursion*/
	__cur_malloc_hook = __malloc_hook;
	__malloc_hook = NULL;
	
	printf("size: %u\ncaller: 0x%x\n", size, caller);
	
	__malloc_hook = __cur_malloc_hook;
	
	return __malloc(size);
}

int main(int argc, char *argv[]){
	__malloc_hook = my_hook;
	
	printf("hmm\n");
	
	malloc(1);
	malloc(1);
    return 0;
}
```

Note that printf() will call malloc within its code and it will have another caller address printed than the two malloc() called from main() function.


----------



## sverch (Mar 3, 2011)

Thank you!  This was exactly what I needed!

The only thing I want to mention is that PARENT_FRAME should be 0x00, not 0x01.  0x00 gives the return address of the current function, while 0x01 gives the return address of the caller function (and 0x02 gives the return address of the caller's caller, etc.)

Thank you for all of your help!  I actually ran into another problem where this can be applied (wrappers for connect/accept/listen that used Linux specific syscalls where dlsym should have been used).

I would like to mark this thread as solved, but I haven't had 10 posts yet.  Is there any way to get this marked as solved?


----------



## expl (Mar 3, 2011)

Function that called the malloc is the parent and its address that we want to have in caller field, in that case one stack frame offset is the desired effect (0x01).


----------

