ios - 这可能是 ios-armv7 的 llvm-gcc 的错误,我无法解释

标签 ios c gcc arm

    the following code works fine on linux-x86, darwin-x86, but not for ios-armv7.

    the right output should be: 
        m[0]: 0.500000, v: 0.500000
        m[1]: 0.500000, v: 0.500000
        m[2]: 0.500000, v: 0.500000
        m[3]: 0.500000, v: 0.500000
        m[4]: 0.500000, v: 0.500000

    but I found the wrong output:
        m[0]: 0.500000, v: 0.500000
        m[1]: 0.500000, v: 0.000000
        m[2]: 0.500000, v: 0.000000
        m[3]: 0.500000, v: 0.000000
        m[4]: 0.500000, v: 0.000000

    I also found the stange when it's built for ios-armv7:

    [a] remove function 'func', move the function body to 'main' function, it works fine
    [b] declare the array 'm[5]' as 'double m[5]', it works fine
    [c] set the variable 'v' as 'v = 0.5 or v = sqrt(2.0f/8)', it works fine
    [d] if the gcc optimize option is '-O0', it works fine, but when it's '-O1 or -O2', wrong output occurs


    My iPad1 was cracked, so I can cross-compile a executable on my MacBook Air, and 'scp' the executable to iPad1 and run it. The following is details:

    1. cross-compile a executable on Mac:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc -O1 -Wall -arch armv7 -mcpu=cortex-a8 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk -I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/usr/include -D__IPHONE_OS__ -miphoneos-version-min=4.0 foo.c

    2. 'scp' the executable to iPad
    scp a.out mobile@192.168.1.106:~

    3. 'ssh' to iPad
    ssh mobile@192.168.1.106 #the default password is 'alpine'

    4. run a.out on iPad
    ./a.out
#include <stdio.h>
#include <math.h>

int
func(int n) /* [a] */
{
    int i;
    float m[5]; /* [b] */
    double v;

    v = sqrt(2.0f/n); /* [c] */

    for(i=0;i<5;++i) {
        m[i]=v;
        printf("m[%d]: %f, v: %f\n", i, m[i], v);
    }

    return 0;
}


int
main(int argc, char **argv)
{
    return func(8);
}

您还可以在 https://gist.github.com/ashun/5992120 上找到完整代码

下面是程序集。你可以在命令'vim -d'的帮助下找到不同之处

  1. 前面代码的汇编,将数组'm[5]'声明为'double m[5]'
        .section    __TEXT,__text,regular,pure_instructions
        .section    __TEXT,__textcoal_nt,coalesced,pure_instructions
        .section    __TEXT,__const_coal,coalesced
        .section    __TEXT,__picsymbolstub4,symbol_stubs,none,16
        .section    __TEXT,__StaticInit,regular,pure_instructions
        .syntax unified
        .section    __TEXT,__text,regular,pure_instructions
        .globl  _func
        .align  2
        .code   16
        .thumb_func _func
    _func:
        push    {r4, r5, r6, r7, lr}
        add r7, sp, #12
        str r8, [sp, #-4]!
        sub sp, #8
        vmov.f32    s0, #2.000000e+00
        movw    r8, :lower16:(L_.str-(LPC0_0+4))
        vmov    s2, r0
        movt    r8, :upper16:(L_.str-(LPC0_0+4))
        vcvt.f32.s32    d1, d1
    LPC0_0:
        add r8, pc
        movs    r4, #0
        vdiv.f32    s0, s0, s2
        vsqrt.f32   s0, s0
        vcvt.f64.f32    d16, s0
        vmov    r5, r6, d16
    LBB0_1:
        mov r1, r4
        mov r0, r8
        mov r2, r5
        mov r3, r6
        vstr.64 d16, [sp]
        adds    r4, #1
        blx _printf
        cmp r4, #5
        bne LBB0_1
        movs    r0, #0
        add sp, #8
        ldr r8, [sp], #4
        pop {r4, r5, r6, r7, pc}

        .globl  _main
        .align  2
        .code   16
        .thumb_func _main
    _main:
        push    {r7, lr}
        mov r7, sp
        movs    r0, #8
        bl  _func
        movs    r0, #0
        pop {r7, pc}

        .section    __TEXT,__cstring,cstring_literals
    L_.str:
        .asciz   "m[%d]: %f, v: %f\n"


    .subsections_via_symbols
  1. 前面代码的汇编,将数组'm[5]'声明为'double m[5]'
        .section    __TEXT,__text,regular,pure_instructions
        .section    __TEXT,__textcoal_nt,coalesced,pure_instructions
        .section    __TEXT,__const_coal,coalesced
        .section    __TEXT,__picsymbolstub4,symbol_stubs,none,16
        .section    __TEXT,__StaticInit,regular,pure_instructions
        .syntax unified
        .section    __TEXT,__text,regular,pure_instructions
        .globl  _func
        .align  2
        .code   16
        .thumb_func _func
    _func:
        push    {r4, r5, r6, r7, lr}
        add r7, sp, #12
        str r8, [sp, #-4]!
        **vpush {d8}**
        sub sp, #8
        vmov.f32    s0, #2.000000e+00
        movw    r8, :lower16:(L_.str-(LPC0_0+4))
        vmov    s2, r0
        movt    r8, :upper16:(L_.str-(LPC0_0+4))
        vcvt.f32.s32    d1, d1
    LPC0_0:
        add r8, pc
        movs    r4, #0
        vdiv.f32    s0, s0, s2
        vcvt.f64.f32    d16, s0
        vsqrt.f64   d8, d16
        vmov    r5, r6, d8
    LBB0_1:
        mov r1, r4
        mov r0, r8
        mov r2, r5
        mov r3, r6
        vstr.64 d8, [sp]
        adds    r4, #1
        blx _printf
        cmp r4, #5
        bne LBB0_1
        movs    r0, #0
        add sp, #8
        vpop    {d8}
        ldr r8, [sp], #4
        pop {r4, r5, r6, r7, pc}

        .globl  _main
        .align  2
        .code   16
        .thumb_func _main
    _main:
        push    {r7, lr}
        mov r7, sp
        movs    r0, #8
        bl  _func
        movs    r0, #0
        pop {r7, pc}

        .section    __TEXT,__cstring,cstring_literals
    L_.str:
        .asciz   "m[%d]: %f, v: %f\n"


    .subsections_via_symbols

最佳答案

不清楚哪个程序集出错了,因为两者都被标记为“将数组 m[5] 声明为 double m[5]”,但不幸的是我没有这样做没有硬件或交叉编译器来重现您的问题。

值得注意的是,两个汇编代码中的循环非常相似。唯一的区别是 v 在第一个中位于 d16 中,在第二个中位于 d8 中。传递给 printfv 位于两个循环中的 (r5,r6) 并正确复制到 (r2, r3) 在调用 printf 之前。对于可变函数,浮点寄存器不得用于传递参数,这与非可变函数相反。因此两个循环看起来都是正确的。

我能想到的唯一解释是用于编译代码的 ABI 与包含 printf 的库的 ABI 不匹配。特别是考虑到编译后的代码来自交叉编译器,我假设 printf 来自系统上的动态库。由于 printf 被称为符合 EABI for ARM,我认为错误在库的 printf 中。

如果您的交叉编译器允许静态链接,您可以尝试这样做,因为您将使用与编译器相对应的库。当然应用程序变大了,但它至少可以证实对 printf 实现的怀疑。您可能想检查该库是否是使用符合 EABI 的编译器编译的。如果您可以在 iPad 上的调试器上逐步执行 printf,那么您应该能够确定 printf 从何处获取其浮点参数。它应该从 (r2,r3) 中获取。

很遗憾,我无法给出结论性的答案,但我希望我的建议对进一步调查有所帮助。

关于ios - 这可能是 ios-armv7 的 llvm-gcc 的错误,我无法解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17637445/

相关文章:

ios - 检测后台应用程序中的锁屏

ios - Pushwoosh 的 p12 证书总是不正确

iOS 10.3 beta 3 不会保留 KeychainItem 的数据

c - 当前 GCC(特别是在 Ubuntu 上)的默认 C -std 标准版本是什么?

linux - 如何使 libusb 库对另一个程序可见?

ios - UIPageViewController pageIndex 没有正确减少

C:在结构元素上使用 Free() 时出现问题,行为奇怪

c++ - 声明中类型和对象的相同标识符

python - 错误 : command 'gcc' failed with exit status 1 installing Fatiando (Python Package)

c++ - 试图让我的 C++ 代码编译,g++ 无法识别?