vgo*_*anz 5 c assembly arm entry-point
我正试图用这个工具链使用CMake在arm架构中建立一个hello world
我的主要
int main()
{
char *str = "Hello World";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
还有我的CMakeLists.txt
cmake_minimum_required(VERSION 3.4)
SET(PROJ_NAME arm-hello-world-nostdlib)
PROJECT(${PROJ_NAME})
# Include directories with headers
#---------------------------------------------------#
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include )
# Source
#---------------------------------------------------#
FILE(GLOB ${PROJ_NAME}_SRC
"src/*.c"
)
FILE(GLOB ${PROJ_NAME}_HEADERS
"include/*.h"
)
# Create Exe
#---------------------------------------------------#
ADD_EXECUTABLE(${PROJ_NAME} ${${PROJ_NAME}_SRC} ${${PROJ_NAME}_HEADERS})
# Specify libraries or flags to use when linking a given target.
#---------------------------------------------------#
TARGET_LINK_LIBRARIES(${PROJ_NAME} -nostdlib --specs=rdimon.specs -lm -lrdimon)
Run Code Online (Sandbox Code Playgroud)
此配置启动警告:
[100%] Linking C executable arm-hello-world-nostdlib
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000
Run Code Online (Sandbox Code Playgroud)
使用qemu执行二进制文件会导致执行崩溃:
qemu-arm arm-hello-world-nostdlib
qemu: uncaught target signal 4 (Illegal instruction) - core dumped
Illegal instruction (core dumped)
Run Code Online (Sandbox Code Playgroud)
没有标志--nostdlib完美地工作,并命令
arm-none-eabi-objdump -s arm-hello-world-nostdlib
Run Code Online (Sandbox Code Playgroud)
以二进制显示大量信息,仅使用标志显示进行编译:
samples/helloworld-nostdlib/arm-hello-world-nostdlib: file format elf32-littlearm
Contents of section .text:
8000 80b483b0 00af044b 7b600023 18460c37 .......K{`.#.F.7
8010 bd465df8 047b7047 1c800000 .F]..{pG....
Contents of section .rodata:
801c 48656c6c 6f20576f 726c6400 Hello World.
Contents of section .comment:
0000 4743433a 20284665 646f7261 20352e32 GCC: (Fedora 5.2
0010 2e302d33 2e666332 33292035 2e322e30 .0-3.fc23) 5.2.0
0020 00 .
Contents of section .ARM.attributes:
0000 41380000 00616561 62690001 2e000000 A8...aeabi......
0010 05436f72 7465782d 4d340006 0d074d09 .Cortex-M4....M.
0020 020a0612 04140115 01170318 0119011a ................
0030 011b011c 011e0622 01 .......".
Run Code Online (Sandbox Code Playgroud)
我不想在我的二进制文件中使用stl库,但我想我错过了汇编代码来找到入口点.如何手动添加?
更新: 根据GNU Linker doc for -nostdlib:
链接时请勿使用标准系统启动文件或库.没有启动文件,只有您指定的库将传递给链接器,并且将忽略指定系统库链接的选项,例如-static-libgcc或-shared-libgcc.
或者,如果有人不想使用标准库,则可以使用标志-nodefaultlibs.
链接时请勿使用标准系统库.只有您指定的库才会传递给链接器,并且会忽略指定系统库链接的选项,例如-static-libgcc或-shared-libgcc.除非使用-nostartfiles,否则标准启动文件将正常使用.
编译器可能会生成对memcmp,memset,memcpy和memmove的调用.这些条目通常由libc中的条目解析.指定此选项时,应通过其他机制提供这些入口点.
顺便说一句,我想要一种方法来创建和添加启动文件,这是本教程中可能的方法,但我添加赏金以获得我的问题的答案,并为每个人提供一般解决方案.我认为这对于想要定制和了解交叉编译,arm和启动文件的人来说非常有用.
更新2
使用start.S汇编代码:
.text
.align 4
.global _start
.global _exit
_start:
mov fp, #0 /* frame pointer */
ldr a1, [sp] /* 1st arg = argc */
add a2, sp, #4 /* 2nd arg = argv */
bl main
_exit:
mov r7, #1 /* __NR_exit */
swi 0
.type _start,function
.size _start,_exit-_start
.type _exit,function
.size _exit,.-_exit
Run Code Online (Sandbox Code Playgroud)
指示arsv提供的入口点,并使用命令进行编译:
arm-none-eabi-gcc -nostdlib -o main main.c start.S
Run Code Online (Sandbox Code Playgroud)
似乎工作性质.更新CMakeLists.txt:
#Directly works:
#arm-none-eabi-gcc -nostdlib -o main main.c start.S
cmake_minimum_required(VERSION 3.4)
SET(PROJ_NAME arm-hello-world-nostdlib)
# Assembler files (.S) in the source list are ignored completely by CMake unless we
# “enable” the assembler by telling CMake in the project definition that we’re using assembly
# files. When we enable assembler, CMake detects gcc as the assembler rather than as – this
# is good for us because we then only need one set of compilation flags.
PROJECT(${PROJ_NAME} C ASM)
# Include directories with headers
#---------------------------------------------------#
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include )
# Source
#---------------------------------------------------#
FILE(GLOB ${PROJ_NAME}_SRC
"src/start.S"
"src/*.c"
)
FILE(GLOB ${PROJ_NAME}_HEADERS
"include/*.h"
)
# Create Exe
#---------------------------------------------------#
ADD_EXECUTABLE(${PROJ_NAME} ${${PROJ_NAME}_SRC} ${${PROJ_NAME}_HEADERS} )
# Specify libraries or flags to use when linking a given target.
#---------------------------------------------------#
TARGET_LINK_LIBRARIES(${PROJ_NAME} -nostdlib --specs=rdimon.specs -lm -lrdimon)
Run Code Online (Sandbox Code Playgroud)
如果您遇到以下链接问题:
arm-none-eabi/bin/ld: error: CMakeFiles/arm-hello-world-nostdlib.dir/src/main.c.obj: Conflicting CPU architectures 1/13
Run Code Online (Sandbox Code Playgroud)
对于cortex-a9,它的工具链存在问题,可以使用:
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS}"
"-mcpu=cortex-a9 -march=armv7-a -mthumb"
"-mfloat-abi=softfp -mfpu=fpv4-sp-d16"
)
Run Code Online (Sandbox Code Playgroud)
这是我在我的一个小项目中使用的 _start.s 。
使用 qemu-arm 链接并运行 main() 应该足够了:
.text
.align 4
.global _start
.global _exit
_start:
mov fp, #0 /* frame pointer */
ldr a1, [sp] /* 1st arg = argc */
add a2, sp, #4 /* 2nd arg = argv */
bl main
_exit:
mov r7, #1 /* __NR_exit */
swi 0
.type _start,function
.size _start,_exit-_start
.type _exit,function
.size _exit,.-_exit
Run Code Online (Sandbox Code Playgroud)
请注意,这是 ARM 上常见 Linux 用户空间二进制文件的启动代码。这就是您可能想要的 qemu-arm (qemu linux 用户模式或系统调用代理)。对于其他情况,例如链接帖子中的裸铁二进制文件、非 Linux 用户空间或其他体系结构,启动代码将会有所不同。
在 Linux 中,新加载的二进制文件通过位于堆栈顶部的 argc、argv[]、envp[]、auxv[] 进行调用。启动代码必须根据 arch 调用约定将其转换为正确的 main(argc, argv) 调用。对于 ARM,这是寄存器 a1 中的第一个参数,a2 中的第二个参数。
上面的“被调用”意味着从ELF头跳转到e_entry地址,如果找到的话,由ld将其设置为指向_start符号。由于没有在任何地方定义 _start,ld 将 e_entry 设置为 0x8000,并且当进行跳转时发生在 0x8000 处的任何内容显然看起来都不像有效的 ARM 指令。这并不完全出乎意料。
从更小/更干净的 libc 实现(如 musl 或 Dietlibc)中读取代码对理解此类内容有很大帮助。顺便说一句,上面的代码源自 Dietlibc。
https://github.com/ensc/dietlibc/blob/master/arm/start.S
http://git.musl-libc.org/cgit/musl/tree/arch/arm/crt_arch.h
作为参考,使用简约的 CMakeLists.txt 来构建项目:(
假设文件名为 main.c 和 _start.s)
project(arm-hello-world-nostdlib)
cmake_minimum_required(VERSION 3.4)
enable_language(ASM)
set(CMAKE_C_COMPILER arm-none-gnueabi-gcc)
set(CMAKE_ASM_COMPILER arm-none-gnueabi-gcc)
set(CMAKE_ASM_FLAGS -c)
set(CMAKE_VERBOSE_MAKEFILE on)
add_executable(main _start.s main.c)
target_link_libraries(main -nostdlib)
Run Code Online (Sandbox Code Playgroud)
像这样运行生成的可执行文件:qemu-arm ./main