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
"
"mov r7, %1
"
"swi #7
"
: : "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
" /* Clear the link register. */
" ldr r0, [sp]
" /* Get argc... */
" add r1, sp, #4
" /* ... and argv ... */
" b estart
" /* 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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…