_start 之前的段错误在交叉组装 arm 组件时运行

Segfault before _start runs when cross-assembling arm assembly

我正试图交叉 assemble 我的手臂组件,因为我的目标系统没有屏幕 (Raspberry Pi 4B)。作为一个你好世界,我有 mcve.s:

.global main

.section .text, "ax"
main:
    movs r3, #10

组装使用:

arm-none-eabi-gcc mcve.s --specs=nosys.specs -g -o mcve

当使用 scp 和 运行 传输到 pi 时,出现段错误。当我将它加载到 gdb (+ gef) 时,我立即得到一个段错误:

Reading symbols from mcve...
gef➤  start
[+] Breaking at '{<text variable, no debug info>} 0x821c <main>'
[+] Breaking at '{<text variable, no debug info>} 0x816c <_start>'
[+] Breaking at entry-point: 0x816c
[!] Command 'entry-break' failed to execute properly, reason: During startup program terminated with signal SIGSEGV, Segmentation fault.

环顾四周,我发现了一些诊断方法,但 none 有所帮助。

starti 仍然立即崩溃:

gef➤  starti
Starting program: /path/mcve 
During startup program terminated with signal SIGSEGV, Segmentation fault.

在入口点突破也是如此:

gef➤  info files
Symbols from "/path/mcve".
Local exec file:
    `/path/mcve', file type elf32-littlearm.
    Entry point: 0x816c
    0x00008000 - 0x00008018 is .init
    0x00008018 - 0x00008650 is .text
    0x00008650 - 0x00008668 is .fini
    0x00008668 - 0x000086b4 is .rodata
    0x000086b4 - 0x000086bc is .ARM.exidx
    0x000086bc - 0x000086c0 is .eh_frame
    0x000186c0 - 0x000186c8 is .init_array
    0x000186c8 - 0x000186cc is .fini_array
    0x000186d0 - 0x00018b04 is .data
    0x00018b04 - 0x00018b44 is .bss
gef➤  break *0x816c
Breakpoint 1 at 0x816c
gef➤  start
[+] Breaking at '{<text variable, no debug info>} 0x821c <main>'
[+] Breaking at '{<text variable, no debug info>} 0x816c <_start>'
[+] Breaking at entry-point: 0x816c
[!] Command 'entry-break' failed to execute properly, reason: During startup program terminated with signal SIGSEGV, Segmentation fault.

不过,我有能力获得_start的来源:

gef➤  disass _start
Dump of assembler code for function _start:
   0x0000816c <+0>: ldr r3, [pc, #148]  ; 0x8208 <_start+156>
   0x00008170 <+4>: cmp r3, #0
   0x00008174 <+8>: ldreq   r3, [pc, #128]  ; 0x81fc <_start+144>
   0x00008178 <+12>:    mov sp, r3
   0x0000817c <+16>:    bl  0x80e4 <_stack_init>
   0x00008180 <+20>:    movs    r1, #0
   0x00008184 <+24>:    mov r11, r1
   0x00008188 <+28>:    mov r7, r1
   0x0000818c <+32>:    ldr r0, [pc, #120]  ; 0x820c <_start+160>
   0x00008190 <+36>:    ldr r2, [pc, #120]  ; 0x8210 <_start+164>
   0x00008194 <+40>:    subs    r2, r2, r0
   0x00008198 <+44>:    bl  0x82a8 <memset>
   0x0000819c <+48>:    ldr r3, [pc, #92]   ; 0x8200 <_start+148>
   0x000081a0 <+52>:    cmp r3, #0
   0x000081a4 <+56>:    beq 0x81b0 <_start+68>
   0x000081a8 <+60>:    mov lr, pc
   0x000081ac <+64>:    mov pc, r3
   0x000081b0 <+68>:    ldr r3, [pc, #76]   ; 0x8204 <_start+152>
   0x000081b4 <+72>:    cmp r3, #0
   0x000081b8 <+76>:    beq 0x81c4 <_start+88>
   0x000081bc <+80>:    mov lr, pc
   0x000081c0 <+84>:    mov pc, r3
   0x000081c4 <+88>:    movs    r0, #0
   0x000081c8 <+92>:    movs    r1, #0
   0x000081cc <+96>:    movs    r4, r0
   0x000081d0 <+100>:   movs    r5, r1
   0x000081d4 <+104>:   ldr r0, [pc, #56]   ; 0x8214 <_start+168>
   0x000081d8 <+108>:   cmp r0, #0
   0x000081dc <+112>:   beq 0x81e8 <_start+124>
   0x000081e0 <+116>:   ldr r0, [pc, #48]   ; 0x8218 <_start+172>
   0x000081e4 <+120>:   bl  0x84fc <atexit>
   0x000081e8 <+124>:   bl  0x8220 <__libc_init_array>
   0x000081ec <+128>:   movs    r0, r4
   0x000081f0 <+132>:   movs    r1, r5
   0x000081f4 <+136>:   bl  0x821c <main>
   0x000081f8 <+140>:   bl  0x8018 <exit>
   0x000081fc <+144>:   andeq   r0, r8, r0
   0x00008200 <+148>:   andeq   r0, r0, r0
   0x00008204 <+152>:   andeq   r0, r0, r0
   0x00008208 <+156>:   andeq   r0, r0, r0
   0x0000820c <+160>:   andeq   r8, r1, r4, lsl #22
   0x00008210 <+164>:   andeq   r8, r1, r4, asr #22
   0x00008214 <+168>:           ; <UNDEFINED> instruction: 0x000084fc
   0x00008218 <+172>:   andeq   r8, r0, r12, lsl r5

为了尝试将 gcc 排除在等式之外,我在程序集中将入口点更改为 _start,并直接使用 ldas

arm-none-eabi-as -g mcve.s -o mcve.o
arm-none-eabi-ld mcve.o -o mcve

但我得到了与以前相同的行为(除了显示我的程序集的 diass)。

我用错了工具链‍♂️。

我已经手动下载并使用了gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2;虽然回想起来,我不太清楚为什么。

我从我的 VM 中清除了它,运行

sudo apt install gcc-arm-linux-gnueabihf

然后,我使用安装的二进制文件:

arm-linux-gnueabihf-as -g mcve.s -o mcve.o
arm-linux-gnueabihf-ld mcve.o -o mcve

现在可以正常使用了。


现在我又花了一个下午来摆弄错误的工具链。我核对了我现有的 Kali,并选择安装 64 位版本。这次的行为是 assemble 没问题,但是当 运行 会说 Illegal Instruction,当加载到 gdb 时会导致它无限期地挂起(但不会导致任何错误)。

解决方法是改为使用:

sudo apt install gcc-aarch64-linux-gnu