首页 > 解决方案 > 交叉组装臂组件时 _start 运行之前的 Segfault

问题描述

我正在尝试交叉组装我的手臂组件,因为我的目标系统(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

当使用并运行转移到 piscp时,我得到一个段错误。当我将它加载到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.

环顾四周,我找到了几种诊断方法,但没有任何帮助。

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显示我的程序集)。

标签: assemblyarmgnu

解决方案


我使用了错误的工具链‍♂️。

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

我从我的虚拟机中清除了它,然后运行

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 位版本。这次的行为是它可以很好地组装,但是运行时会说Illegal Instruction,并且加载时gdb会导致它无限期挂起(但不会导致任何错误)。

解决方法是改用:

sudo apt install gcc-aarch64-linux-gnu

推荐阅读