Can _start be used as a thumbnail function?
Please help me use the gnu assembler for arm926ejs cpu.
I tried to build a simple program (test. S):
.global _start
_start:
mov r0, #2
bx lr
And build it successfully:
arm-none-linux-gnueabi-as -mthumb -o test.o test. S
arm-none-linux-gnueabi-ld -o test test.o
But when I run the program in the Arm Target Linux environment, I get an error:
./test
Segmentation fault
What am I doing wrong?
Can _start function be a thumbnail function?
or
Always arm func?
Solution
Can _start be a thumb function (in a Linux user program)?
Yes, you can. The steps are not as simple as you think.
Please follow someone else’s description to use .code 16.
See also ARM Script predicate ; My answer shows how to detect thumb binaries. The entry symbol must have a traditional _start+1
value, otherwise Linux will decide to call your _start
in ARM mode.
Your code is also trying to mock
int main(void) { return 2; }
_start
symbol cannot do this (according to auselen ). To execute _start
to main()
in ARM mode
#include <linux/unistd.h>
static inline void exit(int status)
{
asm volatile ("mov r0, %0\n\t"
"mov r7, %1\n\t"
"swi #7\n\t"
: : "r" (status),
"Ir" (__NR_exit)
: "r0", "r7");
}
/* Wrapper for main return code. */
void __attribute__ ((unused)) estart (int argc, char*argv[])
{
int rval = main(argc,argv);
exit(rval);
}
/* Setup arguments for estart [like main()]. */
void __attribute__ ((naked)) _start (void)
{
asm(" sub lr, lr, lr\n" /* Clear the link register. */
" ldr r0, [sp]\n" /* Get argc... */
" add r1, sp, #4\n" /* ... and argv ... */
" b estart\n" /* Let's go! */
);
}
It is best to clear the lr
for the stack trace to terminate. You can avoid argc
and argv
processing if needed. Start
shows how to use it. estart
is simply a wrapper that converts the main
() return code into an exit()
call.
You need to convert the above assembler to the Thumb equivalent. I recommend using the gcc inline assembler. If inline works, it can be converted to pure assembler source code. However, it may be more practical to do this in the “C” source code, unless you are trying to make a very small executable.
A useful GCC argument is,
-nostartfiles -static -nostdlib -isystem <path to linux user headers>
Add -mthumb
and you should have a harness for either mode.