x86上不对齐的指针 [英] Mis-aligned pointers on x86

查看:283
本文介绍了x86上不对齐的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人提供一个例子,是因为一个指针从一个类型到另一个类型,由于对齐错误而失败?



这个答案,双方都表示做类似

  char * foo = ...; 
int bar = *(int *)foo;如果启用了对齐检查,

可能会导致错误。



在GDB中通过 set $ ps | =(1 <<18)设置对齐检查标志后,我试图产生一个错误条件







>

我的系统上没有答案的代码段失败 - 我将尝试使用不同的编译器版本,以后在不同的PC上。



Btw,我自己的测试代码看起来像这样(现在也使用asm设置 AC 标志和未对齐的读写):

  #include< assert.h> 

int main(void)
{
#ifndef NOASM
__asm __(
pushf\\\

orl $ ;< 18),(%esp)\\\

popf \\\

);
#endif

volatile unsigned char foo [] = {1,2,3,4,5,6};
volatile unsigned int bar = 0;

bar = *(int *)(foo + 1);
assert(bar == 0x05040302);

bar = *(int *)(foo + 2);
assert(bar == 0x06050403);

*(int *)(foo + 1)= 0xf1f2f3f4;
assert(foo [1] == 0xf4& foo [2] == 0xf3& foo [3] == 0xf2&
foo [4] == 0xf1 );

return 0;
}

断言通过没有问题,即使生成的代码肯定包含未对齐的访问 mov -0x17(%ebp),%edx movl $ 0xf1f2f3f4,-0x17(%ebp) p>




因此将设置 AC 触发 SIGBUS 还是不行?我不能让它在我的英特尔双核笔记本电脑上工作在Windows XP下没有我测试的GCC版本(MinGW-3.4.5,MinGW-4.3.0,Cygwin-3.4.4),而codelogic和Jonathan Leffler上面提到的x86上的失败...

解决方案

EFLAGS.AC实际生效还有一个附加条件, CR0.AM必须设置为防止INT 17h在早于未处理此异常的处理程序的486之前的旧OS上跳闸。不幸的是,Windows不会默认设置它,你需要写一个内核模式驱动程序来设置它。


Can someone provide an example were casting a pointer from one type to another fails due to mis-alignment?

In the comments to this answer, bothie states that doing something like

char * foo = ...;
int bar = *(int *)foo;

might lead to errors even on x86 if alignment-checking is enabled.

I tried to produce an error condition after setting the alignment-check flag via set $ps |= (1<<18) in GDB, but nothing happened.

What does a working (ie non-working ;)) example look like?


None of the code snippets from the answers fail on my system - I'll try it with a different compiler version and on a different pc later.

Btw, my own test code looked like this (now also using asm to set AC flag and unaligned read and write):

#include <assert.h>

int main(void)
{
    #ifndef NOASM
    __asm__(
        "pushf\n"
        "orl $(1<<18),(%esp)\n"
        "popf\n"
    );
    #endif

    volatile unsigned char foo[] = { 1, 2, 3, 4, 5, 6 };
    volatile unsigned int bar = 0;

    bar = *(int *)(foo + 1);
    assert(bar == 0x05040302);

    bar = *(int *)(foo + 2);
    assert(bar == 0x06050403);

    *(int *)(foo + 1) = 0xf1f2f3f4;
    assert(foo[1] == 0xf4 && foo[2] == 0xf3 && foo[3] == 0xf2 &&
        foo[4] == 0xf1);

    return 0;
}

The assertion passes without problems, even though the generated code definitely contains the unaligned access mov -0x17(%ebp), %edx and movl $0xf1f2f3f4,-0x17(%ebp).


So will setting AC trigger a SIGBUS or not? I couldn't get it to work on my Intel dual core laptop under Windows XP with none of the GCC versions I tested (MinGW-3.4.5, MinGW-4.3.0, Cygwin-3.4.4), whereas codelogic and Jonathan Leffler mentioned failures on x86...

解决方案

There is an additional condition, not mentioned, for EFLAGS.AC to actually take effect. CR0.AM must be set to prevent INT 17h from tripping on older OSes predating the 486 that have no handler for this exception. Unfortunately, Windows do not set it by default, you need to write a kernel-mode driver to set it.

这篇关于x86上不对齐的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆