Linux – Can _start be used as a thumbnail function?

Can _start be used as a thumbnail function?… here is a solution to the problem.

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.

Related Problems and Solutions