Компиляция gcc с флагом nostdlib для платформы aarch64

Я пытаюсь скомпилировать двоичный файл с флагом nostdlib на платформе Aarch64.

Я успешно справился с этим на платформе x86-64 следующим образом:

    void _start() {

    /* main body of program: call main(), etc */

    /* exit system call */
    asm("movl $1,%eax;"
        "xorl %ebx,%ebx;"
        "int  $0x80"
    );
}

Есть ли аналог, делающий то же самое на платформе aarch64? (В частности, системный вызов выхода)

да. Скорее всего, это будет инструкция svc, но точные детали зависят от вашей ОС.

Jester 13.09.2018 19:26
0
1
248
1

Ответы 1

Приведенный ниже пример должен работать в системе aarch64-linux-gnu - он действительно работает при запуске qemu-aarch64 3.0 в моей системе x86_64 linux.

По моему скромному мнению, наиболее кратким / слабо связанным источником информации для учебных целей был бы исходный код musl-libc:

  • syscall_arch.h действительно содержит функции _syscall, которые будут использоваться в зависимости от количества аргументов, требуемых данным системным вызовом,
  • syscall.h.in действительно содержит определения для всех системных вызовов.

Затем мы должны использовать:

static inline long __syscall1(long n, long a)
{
    register long x8 __asm__("x8") = n;
    register long x0 __asm__("x0") = a;
    __asm_syscall("r"(x8), "0"(x0));
}

и __NR_exit:

#define __NR_exit 93
#define __NR_exit_group 94

Базовым примером на C будет syscall-exit.c:

#include "syscall_arch.h"
#include "syscall.h.in"

int main(void)
{
   // exiting with return code 1.
    __syscall1(__NR_exit, 1);

   // we should have exited.
   for (;;);
}

Компиляция / выполнение / проверка кода возврата:

/opt/linaro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -static -O0 -o exit-syscall exit-syscall.c
qemu-aarch64 exit-syscall
echo $?
1

Внимательно посмотрите на сгенерированный код для main () и __syscall1 (), используя:

/opt/linaro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objdump  -D exit-syscall > exit-syscall.lst

Выглядело бы так:

0000000000400554 <main>:
400554:   a9bf7bfd    stp x29, x30, [sp, #-16]!
400558:   910003fd    mov x29, sp
40055c:   d2800021    mov x1, #0x1                    // #1
400560:   d2800ba0    mov x0, #0x5d                   // #93
400564:   97fffff4    bl  400534 <__syscall1>


0000000000400534 <__syscall1>:
400534:   d10043ff    sub sp, sp, #0x10
400538:   f90007e0    str x0, [sp, #8]
40053c:   f90003e1    str x1, [sp]
400540:   f94007e8    ldr x8, [sp, #8]
400544:   f94003e0    ldr x0, [sp]
400548:   d4000001    svC#0x0
40054c:   910043ff    add sp, sp, #0x10
400550:   d65f03c0    ret

См. Документ «Стандарт вызова процедур для 64-битной архитектуры ARM (AArch64)» для получения дополнительной информации.

Следовательно, Aarch64-эквивалент вашего кода x86_64 будет exit-asm.c:

void main(void) {

    /* exit system call  - calling NR_exit with 1 as the return code*/
    asm("mov x0, #1;"
        "mov x8, #93;"
        "svC#0x0;"
    );

    for (;;);
}


/opt/linaro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -static -o example example.c 
qemu-aarch64 example
echo $?
1

Обратите внимание, что реализация exit () в glibc вызывает __NR_exit_group перед вызовом __NR_exit.

Другие вопросы по теме