Can _start be the thumb function?

Can _start be a thumb function (in a Linux user program)?

Yes it can. The steps are not as simple as you may believe.

Please use the .code 16 as described by others. Also look at ARM Script predicate; my answer shows how to detect a thumb binary. The entry symbol must have the traditional _start+1 value or Linux will decide to call your _start in ARM mode.

Also your code is trying to emulate,

 int main(void) { return 2; }

The _start symbol must not do this (as per auselen). To do _start to main() in ARM mode you need,

 #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);

 /* 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 good to clear the lr so that stack traces will terminate. You can avoid the argc and argv processing if you want. The start shows how to work with this. The estart is just a wrapper to convert the main() return code to an exit() call.

You need to convert the above assembler to Thumb equivalents. I would suggest using gcc inline assembler. You can convert to pure assembler source if you get inlines to work. However, doing this in ‘C’ source is probably more practical, unless you are trying to make a very minimal executable.

Helpful gcc arguements are,

 -nostartfiles -static -nostdlib -isystem <path to linux user headers>

Add -mthumb and you should have a harness for either mode.

Leave a Comment