Prohibit unaligned memory accesses on x86/x86_64

2019-03-12 21:43发布

问题:

I want to emulate the system with prohibited unaligned memory accesses on the x86/x86_64. Is there some debugging tool or special mode to do this?

I want to run many (CPU-intensive) tests on the several x86/x86_64 PCs when working with software (C/C++) designed for SPARC or some other similar CPU. But my access to Sparc is limited.

As I know, Sparc always checks alignment in memory reads and writes to be natural (reading a byte from any address, but reading a 4-byte word only allowed when address is divisible by 4).

May be Valgrind or PIN has such mode? Or special mode of compiler? I'm searching for Linux non-commercial tool, but windows tools allowed too.

or may be there is secret CPU flag in EFLAGS?

回答1:

It's tricky and I haven't done it personally, but I think you can do it in the following way:

x86_64 CPUs (specifically I've checked Intel Corei7 but I guess others as well) have a performance counter MISALIGN_MEM_REF which counter misaligned memory references.

So first of all, you can run your program and use "perf" tool under Linux to get a count of the number of misaligned access your code has done.

A more tricky and interesting hack would be to write a kernel module that programs the performance counter to generate an interrupt on overflow and get it to overflow the first unaligned load/store. Respond to this interrupt in your kernel module but sending a signal to your process.

This will, in effect, turn the x86_64 into a core that doesn't support unaligned access.

This wont be simple though - beside your code, the system libraries also use unaligned accesses, so it will be tricky to separate them from your own code.



回答2:

I've just read question Does unaligned memory access always cause bus errors? which linked to Wikipedia article Segmentation Fault.

In the article, there's a wonderful reminder of rather uncommon Intel processor flags AC aka Alignment Check.

And here's how to enable it (from Segmentation Fault):

#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__) 
     /* Enable Alignment Checking on x86_64 */
    __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

Once enable it's working a lot like ARM alignment settings in /proc/cpu/alignment, see answer How to trap unaligned memory access? for examples.

Additionally, if you're using GCC, I suggest you enable -Wcast-align warnings. When building for a target with strict alignment requirements (ARM for example), GCC will report locations that might lead to unaligned memory access.



回答3:

Perhaps you somehow could compile to SSE, with all aligned moves. Unaligned accesses with movaps are illegal and probably would behave as illegal unaligned accesses on other architechtures.