Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
506 views
in Technique[技术] by (71.8m points)

linux - Can _start be the thumb function?

Help me please with gnu assembler for arm926ejs cpu.

I try to build a simple program(test.S):

.global _start 
_start:
    mov r0, #2
    bx lr

and success build it:

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 the thumb func? or It is always arm func?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...