【问题标题】:Assembly executable on Termux now produces Illegal instruction error [duplicate]Termux 上的汇编可执行文件现在会产生非法指令错误 [重复]
【发布时间】:2019-04-01 05:04:43
【问题描述】:

你能告诉我我做错了什么吗?
我是汇编编程的新手,不熟悉ld 中的各种选项。

我一开始一直在尝试使用yasm 编译器,但后来意识到这是在编写符合 GNU 的汇编代码时采用 ARM 架构的方法。

binutils 包运行as 祝你好运,即GNU 汇编程序。但汇编代码必须与 ARM 兼容。

以下是arm.s内的代码:

.text                             /* Start of the program code section */ 
    .global main                      /* declares the main identifier */ 
    .type main, %function
main:    /* Address of the main function */ 
     /* Program code would go here */ 
     BR LR 
     /* Return to the caller */
    .end                              /* End of the program */

上面抛出了一个非法指令错误。这可以修复 将ret 替换为BR LR。这是 ARM V8 的新功能。


ARM 是一种 RISC 架构,不受 YASM 支持。

我的构建文件如下:

#/usr/bin/env bash 
#display usage
[ $# -eq 0 ] && { echo "Usage: $0 <File Name without extension> ";exit 1; }
set +e
rm -f $1.exe $1 $1.o
as -o $1.o $1.s
[ -e $1.o ] && { file $1.o;}
gcc -s -o $1.exe $1.o -fpic
ld -s -o $1  -pie --dynamic-linker /system/bin/linker64 /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o  $1.o -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/crtend_android.o
[ -e $1.exe ] && { file $1.exe;nohup ./$1.exe; }  
[ -e $1 ] && { file $1;nohup ./$1;}
set -e

代码之前导致了分段错误或总线错误。

使用上面更新的构建文件,我能够运行一两个程序而没有任何分段或总线错误。我将构建文件设置为生成两个可执行文件,一个使用 gcc,另一个使用 ld,因为一些在线教程使用 ld 而不是 gcc 进行链接步骤。使用 gcc 的详细设置,您可以查看传递给链接器的选项,从而独立地为链接器模拟相同的选项。

我可能遗漏了一些多余的设置。

您可以访问源代码和构建文件的更新,网址为 Learn Assembly

在此处从 Keil 中查看此资源。 arm Keil product guides

更多资源:

https://thinkingeek.com/2016/10/08/exploring-aarch64-assembler-chapter1/

How to link a gas assembly program that uses the C standard library with ld without using gcc?

虽然目前看来上述问题已得到解决,但运行以下代码时出现错误:

.text
.global main
main:
mov w0, #2
mov w7, #1 // request to exit program
svc 0

当我尝试执行代码时出现非法指令错误。

其次,如果我将 main 更改为 _start(因为我不想一直使用 main),那么 buildrun 脚本会出现以下错误。

./buildrun myprogram

  /data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: myprogram.o: in function `_start':    (.text+0x0): multiple definition of `_start'; /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o:crtbegin.c:(.text+0x0): first defined here       /data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o: in function `_start_main':      crtbegin.c:(.text+0x38): undefined reference to `main 
/data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: crtbegin.c:(.text+0x3c): undefined reference to `main'                                  clang-8: error: linker command failed with exit co
de 1 (use -v to see invocation)
ld: myprogram.o: in function `_start':            (.text+0x0): multiple definition of `_start'; /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o:crtbegin.c:(.text+0x0): first defined here       ld: /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o: in function `_start_main':              crtbegin.c:(.text+0x38): undefined reference to `main'
ld: crtbegin.c:(.text+0x3c): undefined reference to `main'

如何创建具有除 main 之外的入口点的程序?

我希望能够:

  1. 创建一个有效的静态链接可执行文件。

  2. 创建一个可执行文件,其中包含一个名为 _start 而不是 main 的函数。

这个file 构建不使用 main 或调用任何库调用的静态可执行文件。

  1. 使用除 main 之外的入口点创建动​​态链接的可执行文件。 我的build file 处理这个,有点,入口点作为第二个参数。

  2. 创建一个可执行文件,使用主管调用svc 退出而不抛出非法指令错误,而不是使用ret

我可以通过在寄存器 X8 中设置系统调用号来调用svc,而不是在版本 7 ARM 中的 W7。此外,ARM 64 已根据以下头文件重新编号系统调用号。 https://github.com/torvalds/linux/blob/v4.17/include/uapi/asm-generic/unistd.h https://reverseengineering.stackexchange.com/q/16917

.data .balign 8 labs: .asciz "Azeria Labs\n" //.asciz adds a null-byte to the end of the string .balign 8 after_labs: .set size_of_labs, after_labs - labs .balign 8 addr_of_labs: .dword labs .balign 8 .text .global main

主要:
mov x0, #1 //STDOUT ldr x1,addr_of_labs //labs的内存地址 mov w2, #size_of_labs //labs的大小 mov x8,#64 svc #0x0 //调用系统调用 _exit: mov x8, #93 //exit系统调用 svc #0x0 //调用系统调用

上面的代码是从下面列出的示例代码中移植而来的。 https://azeria-labs.com/writing-arm-shellcode/ 将数据部分压缩为一个而不是像示例中那样从站点拆分它可以减轻链接时的重定位错误。

其他有用的参考资料:

https://thinkingeek.com/2013/01/09/arm-assembler-raspberry-pi-chapter-1/

*查看 ehrt74 对上述帖子的评论,了解进一步探索 svc 调用的动机。 *

【问题讨论】:

  • 引用的堆栈溢出示例也生成了一个静态可执行文件。谢谢。

标签: linux x86 assembly


【解决方案1】:

Yasm 是一个 x86 汇编程序。它不能为 ARM 处理器生成可执行文件。

您正在使用的教程描述的是 x86 程序集。它们旨在在 x86 系统上遵循。

【讨论】:

  • 我现在知道了。当我开始时,我不是。
  • 是的,我找不到 ARM V8 汇编语言的任何快速入门资源。如果你想看看我的程序有什么问题,你可以从 Git 中查看我的源代码。我是在任何架构上进行汇编编码的新手。我觉得我应该先在一个平台上进行组装,然后再冒险修复 Termux 上的问题。我需要先熟悉汇编编程。其次,为 ARM 列出的资源需要与 x86 格式的任何其他编程资源进行交叉引用,然后进行更改以在 ARM 上运行它们。这不是一个简单的练习。
  • Arm 有两种汇编语言变体。 UAL 和 GNU 汇编。按要求使用后者。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 2021-11-29
  • 1970-01-01
相关资源
最近更新 更多