分支链接到 putchar 导致 ARM 中的分段错误 [英] Branch Link to putchar causes segmentation fault in ARM

查看:25
本文介绍了分支链接到 putchar 导致 ARM 中的分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无论我多么努力,我都无法将链接分支到 putchar 的事实.

I've isolated the fact that I cannot branch link to putchar no matter how hard I try.

连两行都喜欢

mov r0,$48
bl putchar

当我期望它打印 ASCII 0 时总是会出现段错误

Will always segfault when I'm expecting it to print ASCII 0

我可以分支到 putchar,它可以工作,但我不能分支链接.含义

I can branch to putchar, and it will work, but I cannot branch link. Meaning

mov r0,$48
b putchar

会起作用

我觉得我错过了一些非常基本的东西,但我不知道为什么.我只能假设它与 putchar 的返回有关,但我不知道是什么.

I feel like I'm missing something incredibly basic, but I cannot figure out why. I can only assume it has something to do with the return from putchar, but I have no idea what.

抱歉,这似乎是一个愚蠢的问题,但老实说,我找不到这方面的资源.

Sorry if this seems like a dumb question, but I honestly could not find a resource on this.

虽然上述陈述对我来说即使是一个独立的程序也是正确的,但我最终是在一个子程序中实现它,我认为这可能很重要

Although the above statements are true for even a standalone program for me, I am ultimately implementing this in a subroutine, which I figured might be important

推荐答案

这很难说,因为你没有提供足够的代码,但你可能缺少符合规范所需的代码ARM 调用约定.
完整的代码应该是把fp,lr保存在栈上,而不是调用putchar,然后恢复fp,lr并返回或恢复fp,pc,基本相同.

This is difficult to say because you did not provide enough code, but you may be missing the code required for being compliant with the ARM calling conventions.
The complete code should save fp, lr on the stack, than call putchar, then restore fp, lr and return or restore fp, pc, which is basically the same.

创建一个名为 example.s 的文件,内容如下:

Create a file named example.s with the following content:

        .arch armv7-a
        .align  2
        .globl main
        .arch armv7-a
        .syntax unified
        .arm
main:
         push    {fp, lr}
         mov     r0, #48
         bl      putchar
         pop     {fp, pc}

编译并链接 - 我编译了一个静态版本,因为我用 qemu-arm 测试过:

Compile and link it - I compiled a static version because I tested with qemu-arm:

/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -static -O0 -o example  example.s

执行它 - 在我的情况下使用 qemu-arm

Execute it - using qemu-arm in my case

/opt/qemu-3.1.0-static/bin/qemu-arm example
0

请注意:

pop     {fp, pc}

相当于:

pop     {fp, lr}
ret

我希望这会有所帮助.

更新

putchar() 确实返回传递的字符或 r0 中的 EOF.由于 r0 在 main 中没有被修改,它包含的值将返回给被调用者,即 bash,并且可以使用 echo $? 命令查看:

putchar() does return either the character that was passed or EOF in r0. Since r0 is not being modified in main, the value it does contain will be returned to the callee, i.e. bash, and can been see using the echo $? command:

opt/qemu-3.1.0/bin/qemu-arm example
0
echo $?
48

根据 ARM 调用约定的第 15 页、r4-r8 会在子程序调用之间保留,但 r0-r3 可能不会.

According to page 15 of ARM calling conventions, r4-r8 are being preserved across subroutine calls, but r0-r3 may not be.

使用objdump反汇编示例程序:

Using objdump for disassembling the example program:

/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-objdump -D example > example.lst

在example.lst中,可以看到putchar()是:
1) 根据 ARM 调用约定,保留 r4、r5、r6、r7、r8、lr,
2)利用您提到的已被修改的寄存器:

In example.lst, you can see that putchar() is:
1) preserving r4, r5, r6, r7, r8, lr according the the ARM Calling Convention,
2) making use of the registers you are mentioning as having been modified:

00016f50 <putchar>:
   16f50:   e92d41f0    push    {r4, r5, r6, r7, r8, lr}
   16f54:   e30354a8    movw    r5, #13480  ; 0x34a8
   16f58:   e3405008    movt    r5, #8
   16f5c:   e1a06000    mov r6, r0
   16f60:   e5954000    ldr r4, [r5]
   16f64:   e5943000    ldr r3, [r4]
   16f68:   e3130902    tst r3, #32768  ; 0x8000
   16f6c:   1a000015    bne 16fc8 <putchar+0x78>
   16f70:   e5943048    ldr r3, [r4, #72]   ; 0x48
   16f74:   ee1d7f70    mrc 15, 0, r7, cr13, cr0, {3}
   16f78:   e2477d13    sub r7, r7, #1216   ; 0x4c0
   16f7c:   e5932008    ldr r2, [r3, #8]
   16f80:   e1520007    cmp r2, r7
   16f84:   0a000030    beq 1704c <putchar+0xfc>
   16f88:   e3a02001    mov r2, #1
   16f8c:   e1931f9f    ldrex   r1, [r3]
   16f90:   e3510000    cmp r1, #0
   16f94:   1a000003    bne 16fa8 <putchar+0x58>
   16f98:   e1830f92    strex   r0, r2, [r3]
   16f9c:   e3500000    cmp r0, #0
   16fa0:   1afffff9    bne 16f8c <putchar+0x3c>
   16fa4:   f57ff05b    dmb ish
   16fa8:   1a00002d    bne 17064 <putchar+0x114>
   16fac:   e5943048    ldr r3, [r4, #72]   ; 0x48
   16fb0:   e5950000    ldr r0, [r5]
   16fb4:   e5837008    str r7, [r3, #8]
   16fb8:   e5932004    ldr r2, [r3, #4]
   16fbc:   e2822001    add r2, r2, #1
   16fc0:   e5832004    str r2, [r3, #4]
   16fc4:   ea000000    b   16fcc <putchar+0x7c>
   16fc8:   e1a00004    mov r0, r4
   16fcc:   e5903014    ldr r3, [r0, #20]
   16fd0:   e6efc076    uxtb    ip, r6
   16fd4:   e5902018    ldr r2, [r0, #24]
   16fd8:   e1530002    cmp r3, r2
   16fdc:   32832001    addcc   r2, r3, #1
   16fe0:   35802014    strcc   r2, [r0, #20]
   16fe4:   35c36000    strbcc  r6, [r3]
   16fe8:   2a000019    bcs 17054 <putchar+0x104>
   16fec:   e5943000    ldr r3, [r4]
   16ff0:   e3130902    tst r3, #32768  ; 0x8000
   16ff4:   1a000005    bne 17010 <putchar+0xc0>
   16ff8:   e5940048    ldr r0, [r4, #72]   ; 0x48
   16ffc:   e5903004    ldr r3, [r0, #4]
   17000:   e2433001    sub r3, r3, #1
   17004:   e5803004    str r3, [r0, #4]
   17008:   e3530000    cmp r3, #0
   1700c:   0a000001    beq 17018 <putchar+0xc8>
   17010:   e1a0000c    mov r0, ip
   17014:   e8bd81f0    pop {r4, r5, r6, r7, r8, pc}
   17018:   e5803008    str r3, [r0, #8]
   1701c:   f57ff05b    dmb ish
   17020:   e1902f9f    ldrex   r2, [r0]
   17024:   e1801f93    strex   r1, r3, [r0]
   17028:   e3510000    cmp r1, #0
   1702c:   1afffffb    bne 17020 <putchar+0xd0>
   17030:   e3520001    cmp r2, #1
   17034:   dafffff5    ble 17010 <putchar+0xc0>
   17038:   e3a01081    mov r1, #129    ; 0x81
   1703c:   e3a02001    mov r2, #1
   17040:   e3a070f0    mov r7, #240    ; 0xf0
   17044:   ef000000    svc 0x00000000
   17048:   eafffff0    b   17010 <putchar+0xc0>
   1704c:   e1a00004    mov r0, r4
   17050:   eaffffd8    b   16fb8 <putchar+0x68>
   ...

这篇关于分支链接到 putchar 导致 ARM 中的分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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