Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find whether a given address is in heap or in stack

Tags:

c

linux

unix

gcc

I have a requirement to find whether a given address is in heap or in stack. Is there a reliable way to do this in Linux?

I have thought about the following approach assuming that the stack will grow downward and heap will grow up towards stack. How reliable is this solution? We don't use gcc split-stack.

is_stack (void *addr) {
   int a;
   if( &a < addr) return stack;
   else return heap
}

[edit - I saw a similar question but that's more of a theoretical nature]

like image 515
joe Avatar asked Nov 19 '15 08:11

joe


1 Answers

First, you may have several stacks in your process, in particular if it is multi-threaded (and some libraries could start threads without you asking for them). And your process' virtual address space might have more segments than just heap & stack.

You might parse the /proc/self/maps pseudo-file. See proc(5). Notice that since it is a pseudo-file which is generated by the kernel, there is no physical IO involved, and reading & parsing that /proc/self/maps file should be really quick.

The address map of your process can change by calling mmap(2), munmap, execve, mprotect and some other system calls (see syscalls(2) to get a list of them); use strace(1) to understand which syscalls are done. Any call to malloc (internally called by many functions, including fopen...) or to free (and to dlopen etc etc....) could (but won't always) use them, so caching the result of parsing /proc/self/maps is not a reliable option.

Try first the cat /proc/$$/maps command in a terminal (showing you a description of your shell's virtual address space).

As many commented, because of ASLR, you don't have any idea of the relative position of stack and heap, even if there is one single stack. A possible trick could be to start your main with something putting the address of some local variable (or even of main's argc first argument, or of argv[0]) in some global void*stackbottom;, and to later compare the address like you do, that is test if( &a < addr && &a > stackbottom). Notice that Boehm's garbage collector is doing similar things.

But the most reliable way is to read and parse /proc/self/maps and that should be fairly quick and is certainly a programmatic solution (the kernel is dynamically giving information about its state and the process state thru /proc/ and no physical IO is involved reading it).

And still, be on stack or be in heap is an ill-defined property of pointers (in other words, stack or heap is a much more complex notion than what you imagine). You need to be more precise about what you really want to do.

Alterrnatively, redefine your own malloc, free etc and have your malloc manage some memory map.

like image 79
Basile Starynkevitch Avatar answered Oct 21 '22 09:10

Basile Starynkevitch