Mis-aligned pointers on x86

后端 未结 8 666
一整个雨季
一整个雨季 2020-11-30 06:36

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 s

8条回答
  •  天涯浪人
    2020-11-30 07:31

    #include 
    
    int main(int argc, char **argv)
    {
      char c[] = "a";
    
      printf("%d\n", *(int*)(c));
    }
    

    This gives me a SIGBUS after setting set $ps |= (1<<18) in gdb, which apparently is thrown when address alignment is incorrect (amongst other reasons).

    EDIT: It's fairly easy to raise SIGBUS:

    int main(int argc, char **argv)
    {
        /* EDIT: enable AC check */
        asm("pushf; "
            "orl $(1<<18), (%esp); "
            "popf;");
    
        char c[] = "1234567";
        char d[] = "12345678";
        return 0;
    }
    

    Looking at main's disassembly in gdb:

    Dump of assembler code for function main:
    ....
    0x08048406 :   mov    0x8048510,%eax
    0x0804840b :   mov    0x8048514,%edx
    0x08048411 :   mov    %eax,-0x10(%ebp)
    0x08048414 :   mov    %edx,-0xc(%ebp)
    0x08048417 :   movl   $0x34333231,-0x19(%ebp)   <== BAM! SIGBUS
    0x0804841e :   movl   $0x38373635,-0x15(%ebp)
    0x08048425 :   movb   $0x0,-0x11(%ebp)
    

    Anyhow, Christoph your test program fails under Linux raising a SIGBUS as it should. It's probably a Windows thing?


    You can enable the Alignment Check bit in code using this snippet:

    /* enable AC check */
    asm("pushf; "
        "orl $(1<<18), (%esp); "
        "popf;");
    

    Also, ensure that the flag was indeed set:

    unsigned int flags;
    asm("pushf; "
        "movl (%%esp), %0; "
        "popf; " : "=r"(flags));
    fprintf(stderr, "%d\n", flags & (1<<18));
    

提交回复
热议问题