When working sometimes ago on an embedded system with a simple MMU, I used to program dynamically this MMU to detect memory corruptions.
For instance, at some moment at runtime, the foo variable was overwritten with some unexpected data (probably by a dangling pointer or whatever). So I added the additional debugging code :
- at init, the memory used by foo was indicated as a forbidden region to the MMU;
- each time foo was accessed on purpose, access to the region was allowed just before then forbidden just after;
- a MMU irq handler was added to dump the master and the address responsible of the violation.
This was actually some kind of watchpoint, but directly self-handled by the code itself.
Now, I would like to reuse the same trick, but on a x86 platform. The problem is that I am very far from understanding how is working the MMU on this platform, and how it is used by Linux, but I wonder if any library/tool/system call already exist to deal with this problem.
Note that I am aware that various tools exist like Valgrind or GDB to manage memory problems, but as far as I know, none of these tools car be dynamically reconfigured by the debugged code.
I am mainly interested for user space under Linux, but any info on kernel mode or under Windows is also welcome!
PHP Segmentation fault when started from crond
1:waiting for 2 different events in a single thread
- dmalloc is a library this replaces
free()with extensive debugging versions, capable of using page boundaries to detect memory overruns/underruns, filling allocated and freed memory, leak-checking, and more.
- valgrind is a memory debugger this allows very precise memory debugging (detecting accurately any out-of-bounds access) at the expense of program speed (programs run substantially slower under it). It must also did leak checking.
mprotect()system call is what you're after. This lets you change the protections on a memory region.. Memory protection on x86 under Linux is done at the level of a page - 4096 bytes. So you will have to arrange for your protected variable to live on its own page(s), not sharing with any another variables. One way to arrange for this is to use
posix_memalign()to allocate the memory for the variable, using 4096 as the alignment and rounding up the size to the next multiple of 4096 (Actually, you must use
sysconf(_SC_PAGESIZE)to determine the page size in a portable manner, rather than using a hardcoded value). Ananother way to is allocate the variable within a union this pads it out to a multiple of the page size, and use the gcc attrialthough e
__attrialthough e__ ((aligned (4096))to align the variable.. In place of your MMU IRQ handler, you simply install a signal handler for the
SIGSEGVsignal using the
sa_sigactionmember of the structure passed to the
sigaction()function. Your signal handler will be passed a
siginfo_tstructure as its second argument, which will contain a member
sa_addrthis has the address of the faulting instruction..