简体   繁体   中英

ARMv8 Assembly, Run into bus error when calling a subroutine

Every time I try to run the program with odd command line argument, the program runs into a bus error.

./test 4 5
bus error (core dumped)

./test 7 13
bus error (core dumped)

But when I run it with even command line argument, it works just fine.

./test 12 12

Here is my code:

    .balign 4
    .global main

main:   
        
    stp x29,    x30,    [sp, -48]!  //save fp and link register to stack
    mov x29,    sp      //update fp register
    
    mov w28,    w0      //move argc to w28
    mov x27,    x1  //move argv to counter2
    
    //load argv[1]
    mov x19, 1          
    ldr x0, [x27, w19, sxtw 3]
    bl  atoi
    mov x21,    x0
    
    //load argv[2]
    mov x19, 2  
    ldr x0, [x27, w19, sxtw 3]
    bl  atoi
    mov x22,    x0
    
    //store argc, argv[1], argv[2] in memory
    str w28,    [x29, 16]
    str x21,    [x29, 20]
    str x22,    [x29, 28]
    
    //allocate memory for an array
    mul x24,    x21,    x22
    lsl x24,    x24,    #2
    sub x24,    xzr,    x24
    add sp, sp, x24
    
    //call function initializeRandom
    ldr x0, [x29, 20]
    ldr x1, [x29, 28]
    mov x2, sp
    bl initializeRandom
    
    //deallocate memory
    ldr x21,    [x29, 20]
    ldr x22,    [x29, 28]
    mul x24,    x21,    x22
    lsl x24,    x24,    #2
    add sp, sp, x24
    
mainEnd:    //End of main() function
    ldp x29,    x30,    [sp],   48  //restore fp and link registers
    ret



////////initializeRandom(int x, int y, int* table) function////////

    .balign 4
initializeRandom:
    stp x29,    x30,    [sp, -64]!
    mov x29,    sp
    
    //end of subroutine
    ldp x29,    x30,    [sp],   64
    ret     

The subroutine initializeRandom's purpose is to populate the array created in main function with random numbers. But the program doesn't even run when the subroutine is basically empty. Why does a bus error occur and how do I fix it?

The difference is behavior may be because, depending on the value that was computed in x24 in your code, the value of sp will or will not be aligned on a 16 bytes boundary after having executed add sp, sp, x24 at line #33. This is of course equivalent to say that sp shall always contain a value which is a multiple of 0x10 prior to using sp for referencing memory.

This will cause an exception at the first attempt to access memory using sp , that is at the line stp x29, x30, [sp, -64]! of initializeRandom() .

gdb --args ./program 7 13

Reading symbols from ./program...
(gdb) b 33
Breakpoint 1 at 0x7b4: file program.s, line 33.
(gdb) run
Starting program: /home/user/stackoverflow/65167437/program 7 13

Breakpoint 1, main () at program.s:33
33          add sp, sp, x24
(gdb) p/x $sp
$1 = 0xfffffffff300
(gdb) p/x $x24
$2 = 0xfffffffffffffe94
(gdb)


gdb --args ./program 22 22

Reading symbols from ./program...
(gdb) b 33
Breakpoint 1 at 0x7b4: file program.s, line 33.
(gdb) run
Starting program: /home/user/stackoverflow/65167437/program 22 22

Breakpoint 1, main () at program.s:33
33          add sp, sp, x24
(gdb) p/x $sp
$1 = 0xfffffffff300
(gdb) p/x$x24
$2 = 0xfffffffffffff870
(gdb)

Please refer to article Using the Stack in AArch32 and AArch64 :

Rules Specific to AArch64

For AArch64, sp must be 16-byte aligned whenever it is used to access memory. This is enforced by AArch64 hardware.

    This means that it is difficult to implement a generic push or pop operation for AArch64. There are no push or pop aliases like there are for ARM and Thumb.
    The hardware checks can be disabled by privileged code, but they're enabled in at least Linux and Android.

if you add code for rounding-up the value computed in x24 to the nearest multiple of 16/0x10 , your program should work with arbitrary argument values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM