Skip to content

Commit fc28ca9

Browse files
committed
Refine generated instructions for staticly linked programs of Arm32
Previously, for the Arm architecture, the compiler generated the following sequence at the program entry point for staticly linked executables: - a 'bl' instruction to call a global initialization function, and then execute the main function. - a 'b' instruction. - a sequence of instructions to invoke the '_exit' system all. After further investigation, since the main function inherently invokes '_exit' upon completion, the entry sequence can be simplified. We now use a single 'b' instruction to perform an unconditional jump to the global initialization and the main routines. Additionally, the implementation of the '__syscall' function has been corrected. Previously, it modified registers r4-r7 without preserving their original values for the caller. This commit ensures that these callee-saved registers are properly saved and restored. Finally, This refinement improves the efficiency and correctness of the generated instructions for statically linked programs.
1 parent b75bfee commit fc28ca9

1 file changed

Lines changed: 44 additions & 22 deletions

File tree

src/arm-codegen.c

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,8 @@ void cfg_flatten(void)
165165
100; /* offset of __libc_start_main + main_wrapper in codegen */
166166
else {
167167
func = find_func("__syscall");
168-
func->bbs->elf_offset = 60; /* offset of start + exit in codegen */
169-
elf_offset =
170-
112; /* offset of start + branch + exit + syscall in codegen */
168+
func->bbs->elf_offset = 32; /* offset of start + branch in codegen */
169+
elf_offset = 92; /* offset of start + branch + syscall in codegen */
171170
}
172171

173172
GLOBAL_FUNC->bbs->elf_offset = elf_offset;
@@ -670,30 +669,52 @@ void code_generate(void)
670669
emit(__sw(__AL, __r12, __r8, 0));
671670

672671
if (!dynlink) {
673-
emit(__bl(__AL, GLOBAL_FUNC->bbs->elf_offset - elf_code->size));
674-
/* After global init, jump to main preparation */
675-
emit(__b(__AL,
676-
56)); /* PC+8: skip exit (24) + syscall (36) + ret (4) - 8 */
677-
678-
/* exit - only for static linking */
679-
emit(__movw(__AL, __r8, ofs));
680-
emit(__movt(__AL, __r8, ofs));
681-
emit(__add_r(__AL, __sp, __sp, __r8));
682-
emit(__mov_r(__AL, __r0, __r0));
683-
emit(__mov_i(__AL, __r7, 1));
684-
emit(__svc());
672+
/* Jump directly to the main preparation and then execute the
673+
* main function.
674+
*
675+
* In static linking mode, when the main function completes its
676+
* execution, it will invoke the '_exit' syscall to terminate
677+
* the program.
678+
*
679+
* That is, the execution flow is:
680+
*
681+
* +------------------+
682+
* | movw r8 <ofs> |
683+
* 'start' | ... |
684+
* | b <global init> | (1) jump to global init --+
685+
* +------------------+ |
686+
* | push {r4 ... r7} | |
687+
* '__syscall' | ... | |
688+
* | bx lr | |
689+
* +------------------+ |
690+
* | ... | (2) global init <------+
691+
* | (global init) |
692+
* | ... |
693+
* global init | movw r8 <ofs> |
694+
* + | movt r8 <ofs> |
695+
* call main() | ... |
696+
* | bl <main func> | (3) call main()
697+
* | mov r7 #1 |
698+
* | svc 0x00000000 | (4) call '_exit' after main()
699+
* +------------------+ returns
700+
*/
701+
emit(__b(__AL, GLOBAL_FUNC->bbs->elf_offset - elf_code->size));
685702

686703
/* __syscall - only for static linking
687704
*
688705
* If the number of arguments is greater than 4, the additional
689-
* arguments need to be retrieved from the stack. Since __syscall
690-
* doesn't require a local stack, it can directly use sp to obtain
691-
* the extra arguments.
706+
* arguments need to be retrieved from the stack. However, this
707+
* process must modify the contents of registers r4-r7.
708+
*
709+
* Therefore, __syscall needs to preserve the contents of these
710+
* registers before invoking a syscall, and restore them after
711+
* the syscall has completed.
692712
*/
693-
emit(__lw(__AL, __r4, __sp, 0));
694-
emit(__lw(__AL, __r5, __sp, 4));
695-
emit(__lw(__AL, __r6, __sp, 8));
696-
emit(__lw(__AL, __r7, __sp, 12));
713+
emit(__stmdb(__AL, 1, __sp, 0x00F0));
714+
emit(__lw(__AL, __r4, __sp, 16));
715+
emit(__lw(__AL, __r5, __sp, 20));
716+
emit(__lw(__AL, __r6, __sp, 24));
717+
emit(__lw(__AL, __r7, __sp, 28));
697718
emit(__mov_r(__AL, __r7, __r0));
698719
emit(__mov_r(__AL, __r0, __r1));
699720
emit(__mov_r(__AL, __r1, __r2));
@@ -702,6 +723,7 @@ void code_generate(void)
702723
emit(__mov_r(__AL, __r4, __r5));
703724
emit(__mov_r(__AL, __r5, __r6));
704725
emit(__svc());
726+
emit(__ldm(__AL, 1, __sp, 0x00F0));
705727
emit(__bx(__AL, __lr));
706728
}
707729

0 commit comments

Comments
 (0)