分支链接到putchar导致ARM中的分段错误 [英] Branch Link to putchar causes segmentation fault in 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
我希望有帮助.
更新
Update
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页/a>,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屋!