1

I am using Pin for some execution monitoring tasks towards x64 ELF binary code.

During the monitoring, for any memory write/read operation of the original code, I would like to record it as long as it refers the heap. However, given a memory address, I have no idea whether it refers the heap memory region or not.

One possible solution I can come up with is that, before every memory operation, I acquire the runtime memory region information of the target process, and check whether the current memory address is within the heap region. This can be done by following the steps below inside the Pintool.

  1. acquire the process ID of monitored process (This step can use Pin API Pin_GetPid)
  2. read the process memory region information in /proc/XXX/maps
  3. find the heap memory region
  4. check whether the current address is within the heap region

However, this is tedious and my test shows that this is extremely slow, as the size of memory heap can change during the runtime which means I need to go through the above steps everytime before memory operation.

So I am wondering, does Pin has APIs to provide the heap memory region information? Or is there any solution more efficient that the above one?

===================== update ===============================

enter image description here

1
  • I want to know how to solve this problem .Could you give me some advice?
    – user26860
    Dec 27, 2018 at 8:20

1 Answer 1

2

As you're saying you're using ELF code, i assume you're running under Linux, or another unix-y system. And proc/self/maps (you don't have to getpid() and use /proc/XXX/maps, really) hints at Linux as well.

One problem i see is the definition of heap - what about memory mapped regions, do they count as "heap" or not? Linux malloc uses mmap in some cases instead of expanding the heap, which is typically done by brk (which may itself be just a wrapper around mmap/mremap depending on your libc).

If you want to trace everything that's in malloced memory, i'd just compare the address to the end of the code segment (but beware of dynamic libraries; or omit that comparison completely as code typically isn't read and can't be written anyway) and the current value of the stack pointer. If the address is below the stack pointer, assume heap.

If you want to trace what's in the original, brk-managed heap only, read your memory map just once at the start, getting the heap start address, and monitor brk calls, adjusting the end address after each brk.

On x64, "below the stack pointer" must be taken with a grain of salt. On 16- and 32-bit x86 processors, anything below the stack pointer can be clobbered by hardware interrupts at any time, so sp/esp are a barrier to what software can use. On 64 bit processors, however, the ABI guarantees that 128 bytes below the stack pointer aren't changed by interrupts, so the compiler is free to use them (and will do so in leaf functions). Which means, you really need to compare your address to esp-0x80 if you're dealing with x64 code.

10
  • Very smart idea! I will check whether the address is within code section and stack pointer rsp. Thank you for saving my ass ;) Apr 25, 2016 at 13:26
  • Hi Guntram, recall rsp does not always refer to the top of the stack.. For example, at the beginning of one function, it can be something like this: mov esp, ebp; mov eax, [ebp-16]... Apr 25, 2016 at 14:52
  • Are you certain about this? Every function i've encountered makes sure to not access any memory below [er]sp, and function prologues typically push the old [er]bp, move sp into bp (the other way round than you describe), and subtract something from sp. Whatever is a few bytes below sp is subject to change without visible reason, because a hardware interrupt will cause the processor to push flags, cs and ip on the stack, and software can't predict when they arrive. Apr 25, 2016 at 16:21
  • Hi Guntram, I uploaded a screen shot Apr 25, 2016 at 16:42
  • 1
    Found something: eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 - going to include the essentials of that in my answer. Seems like on x64 only 128 bytes below the stack are "reserved", i.e. won't be clobbered by interrupts. Apr 25, 2016 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.