@@ -139,10 +139,18 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
139139
140140void cfg_flatten (void )
141141{
142- func_t * func = find_func ("__syscall" );
143- func -> bbs -> elf_offset = 48 ; /* offset of start + branch + exit in codegen */
142+ func_t * func ;
143+
144+ if (dynlink )
145+ elf_offset =
146+ 88 ; /* offset of __libc_start_main + main_wrapper in codegen */
147+ else {
148+ func = find_func ("__syscall" );
149+ func -> bbs -> elf_offset = 48 ; /* offset of start + exit in codegen */
150+ elf_offset =
151+ 84 ; /* offset of start + branch + exit + syscall in codegen */
152+ }
144153
145- elf_offset = 84 ; /* offset of start + branch + exit + syscall in codegen */
146154 GLOBAL_FUNC -> bbs -> elf_offset = elf_offset ;
147155
148156 for (ph2_ir_t * ph2_ir = GLOBAL_FUNC -> bbs -> ph2_ir_list .head ; ph2_ir ;
@@ -151,7 +159,10 @@ void cfg_flatten(void)
151159 }
152160
153161 /* prepare 'argc' and 'argv', then proceed to 'main' function */
154- elf_offset += 32 ; /* 6 insns for main call + 2 for exit */
162+ if (dynlink )
163+ elf_offset += 28 ;
164+ else
165+ elf_offset += 32 ; /* 6 insns for main call + 2 for exit */
155166
156167 for (func = FUNC_LIST .head ; func ; func = func -> next ) {
157168 /* Skip function declarations without bodies */
@@ -294,7 +305,16 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
294305 return ;
295306 case OP_call :
296307 func = find_func (ph2_ir -> func_name );
297- emit (__bl (__AL , func -> bbs -> elf_offset - elf_code -> size ));
308+ if (func -> bbs )
309+ ofs = func -> bbs -> elf_offset - elf_code -> size ;
310+ else if (dynlink )
311+ ofs = (dynamic_sections .elf_plt_start + func -> plt_offset ) -
312+ (elf_code_start + elf_code -> size );
313+ else {
314+ printf ("The '%s' function is not implemented\n" , ph2_ir -> func_name );
315+ abort ();
316+ }
317+ emit (__bl (__AL , ofs ));
298318 return ;
299319 case OP_load_data_address :
300320 emit (__movw (__AL , rd , ph2_ir -> src0 + elf_data_start ));
@@ -306,7 +326,14 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
306326 return ;
307327 case OP_address_of_func :
308328 func = find_func (ph2_ir -> func_name );
309- ofs = elf_code_start + func -> bbs -> elf_offset ;
329+ if (func -> bbs )
330+ ofs = elf_code_start + func -> bbs -> elf_offset ;
331+ else if (dynlink )
332+ ofs = dynamic_sections .elf_plt_start + func -> plt_offset ;
333+ else {
334+ printf ("The '%s' function is not implemented\n" , ph2_ir -> func_name );
335+ abort ();
336+ }
310337 emit (__movw (__AL , __r8 , ofs ));
311338 emit (__movt (__AL , __r8 , ofs ));
312339 emit (__sw (__AL , __r8 , rn , 0 ));
@@ -470,39 +497,76 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
470497 }
471498}
472499
500+ void plt_generate (void );
473501void code_generate (void )
474502{
475- elf_data_start = elf_code_start + elf_offset ;
476- elf_rodata_start = elf_data_start + elf_data -> size ;
477- elf_bss_start = elf_rodata_start + elf_rodata -> size ;
503+ if (dynlink ) {
504+ plt_generate ();
505+ /* Call __libc_start_main() */
506+ emit (__mov_i (__AL , __r11 , 0 ));
507+ emit (__mov_i (__AL , __lr , 0 ));
508+ emit (__pop_word (__AL , __r1 ));
509+ emit (__mov_r (__AL , __r2 , __sp ));
510+ emit (__push_reg (__AL , __r2 ));
511+ emit (__push_reg (__AL , __r0 ));
512+ emit (__mov_i (__AL , __r12 , 0 ));
513+ emit (__push_reg (__AL , __r12 ));
514+
515+ int main_wrapper_offset = elf_code -> size + 28 ;
516+ emit (__movw (__AL , __r0 , elf_code_start + main_wrapper_offset ));
517+ emit (__movt (__AL , __r0 , elf_code_start + main_wrapper_offset ));
518+ emit (__mov_i (__AL , __r3 , 0 ));
519+ emit (__bl (__AL , (dynamic_sections .elf_plt_start + PLT_FIXUP_SIZE ) -
520+ (elf_code_start + elf_code -> size )));
521+ /* Call '_exit' (syscall) to terminate the program if __libc_start_main
522+ * returns. */
523+ emit (__mov_i (__AL , __r0 , 127 ));
524+ emit (__mov_i (__AL , __r7 , 1 ));
525+ emit (__svc ());
478526
479- /* start */
527+ /* If the compiled program is dynamic linking, the starting
528+ * point of 'main_wrapper' is located here.
529+ *
530+ * Push the contents of r4-r11 and lr onto stack.
531+ * Preserve 'argc' and 'argv' for the 'main' function.
532+ */
533+ emit (__stmdb (__AL , 1 , __sp , 0x4FF0 ));
534+ emit (__mov_r (__AL , __r9 , __r0 ));
535+ emit (__mov_r (__AL , __r10 , __r1 ));
536+ }
537+ /* For both static and dynamic linking, we need to set up the stack
538+ * and call the main function.
539+ */
480540 emit (__movw (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
481541 emit (__movt (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
482542 emit (__sub_r (__AL , __sp , __sp , __r8 ));
483543 emit (__mov_r (__AL , __r12 , __sp ));
484- emit (__bl (__AL , GLOBAL_FUNC -> bbs -> elf_offset - elf_code -> size ));
485- /* After global init, jump to main preparation */
486- emit (__b (__AL , 56 )); /* PC+8: skip exit (24) + syscall (36) + ret (4) - 8 */
487544
488- /* exit */
489- emit (__movw (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
490- emit (__movt (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
491- emit (__add_r (__AL , __sp , __sp , __r8 ));
492- emit (__mov_r (__AL , __r0 , __r0 ));
493- emit (__mov_i (__AL , __r7 , 1 ));
494- emit (__svc ());
495-
496- /* syscall */
497- emit (__mov_r (__AL , __r7 , __r0 ));
498- emit (__mov_r (__AL , __r0 , __r1 ));
499- emit (__mov_r (__AL , __r1 , __r2 ));
500- emit (__mov_r (__AL , __r2 , __r3 ));
501- emit (__mov_r (__AL , __r3 , __r4 ));
502- emit (__mov_r (__AL , __r4 , __r5 ));
503- emit (__mov_r (__AL , __r5 , __r6 ));
504- emit (__svc ());
505- emit (__bx (__AL , __lr ));
545+ if (!dynlink ) {
546+ emit (__bl (__AL , GLOBAL_FUNC -> bbs -> elf_offset - elf_code -> size ));
547+ /* After global init, jump to main preparation */
548+ emit (__b (__AL ,
549+ 56 )); /* PC+8: skip exit (24) + syscall (36) + ret (4) - 8 */
550+
551+ /* exit - only for static linking */
552+ emit (__movw (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
553+ emit (__movt (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
554+ emit (__add_r (__AL , __sp , __sp , __r8 ));
555+ emit (__mov_r (__AL , __r0 , __r0 ));
556+ emit (__mov_i (__AL , __r7 , 1 ));
557+ emit (__svc ());
558+
559+ /* syscall */
560+ emit (__mov_r (__AL , __r7 , __r0 ));
561+ emit (__mov_r (__AL , __r0 , __r1 ));
562+ emit (__mov_r (__AL , __r1 , __r2 ));
563+ emit (__mov_r (__AL , __r2 , __r3 ));
564+ emit (__mov_r (__AL , __r3 , __r4 ));
565+ emit (__mov_r (__AL , __r4 , __r5 ));
566+ emit (__mov_r (__AL , __r5 , __r6 ));
567+ emit (__svc ());
568+ emit (__bx (__AL , __lr ));
569+ }
506570
507571 ph2_ir_t * ph2_ir ;
508572 for (ph2_ir = GLOBAL_FUNC -> bbs -> ph2_ir_list .head ; ph2_ir ;
@@ -511,20 +575,60 @@ void code_generate(void)
511575
512576 /* prepare 'argc' and 'argv', then proceed to 'main' function */
513577 if (MAIN_BB ) {
514- emit (__movw (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
515- emit (__movt (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
516- emit (__add_r (__AL , __r8 , __r12 , __r8 ));
517- emit (__lw (__AL , __r0 , __r8 , 0 ));
518- emit (__add_i (__AL , __r1 , __r8 , 4 ));
519- emit (__bl (__AL , MAIN_BB -> elf_offset - elf_code -> size ));
578+ if (dynlink ) {
579+ emit (__mov_r (__AL , __r0 , __r9 ));
580+ emit (__mov_r (__AL , __r1 , __r10 ));
581+ /* Call the main function.
582+ *
583+ * After the main function returns, the following
584+ * instructions restore the registers r4-r11 and
585+ * return control to __libc_start_main via the
586+ * preserved lr.
587+ */
588+ emit (__bl (__AL , MAIN_BB -> elf_offset - elf_code -> size ));
589+ emit (__movw (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
590+ emit (__movt (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
591+ emit (__add_r (__AL , __sp , __sp , __r8 ));
592+ emit (__ldm (__AL , 1 , __sp , 0x8FF0 ));
593+ } else {
594+ emit (__movw (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
595+ emit (__movt (__AL , __r8 , GLOBAL_FUNC -> stack_size ));
596+ emit (__add_r (__AL , __r8 , __r12 , __r8 ));
597+ emit (__lw (__AL , __r0 , __r8 , 0 ));
598+ emit (__add_i (__AL , __r1 , __r8 , 4 ));
520599
521- /* exit with main's return value - r0 already has the return value */
522- emit (__mov_i (__AL , __r7 , 1 ));
523- emit (__svc ());
600+ /* Call main function, and call '_exit' syscall to
601+ * terminate the program. */
602+ emit (__bl (__AL , MAIN_BB -> elf_offset - elf_code -> size ));
603+
604+ /* exit with main's return value - r0 already has the
605+ * return value */
606+ emit (__mov_i (__AL , __r7 , 1 ));
607+ emit (__svc ());
608+ }
524609 }
525610
526611 for (int i = 0 ; i < ph2_ir_idx ; i ++ ) {
527612 ph2_ir = PH2_IR_FLATTEN [i ];
528613 emit_ph2_ir (ph2_ir );
529614 }
530615}
616+
617+ void plt_generate (void )
618+ {
619+ int addr_of_got = dynamic_sections .elf_got_start + PTR_SIZE * 2 ;
620+ int end = dynamic_sections .plt_size - PLT_FIXUP_SIZE ;
621+ elf_write_int (dynamic_sections .elf_plt , __push_reg (__AL , __lr ));
622+ elf_write_int (dynamic_sections .elf_plt , __movw (__AL , __r10 , addr_of_got ));
623+ elf_write_int (dynamic_sections .elf_plt , __movt (__AL , __r10 , addr_of_got ));
624+ elf_write_int (dynamic_sections .elf_plt , __mov_r (__AL , __lr , __r10 ));
625+ elf_write_int (dynamic_sections .elf_plt , __lw (__AL , __pc , __lr , 0 ));
626+ for (int i = 0 ; i * PLT_ENT_SIZE < end ; i ++ ) {
627+ addr_of_got = dynamic_sections .elf_got_start + PTR_SIZE * (i + 3 );
628+ elf_write_int (dynamic_sections .elf_plt ,
629+ __movw (__AL , __r12 , addr_of_got ));
630+ elf_write_int (dynamic_sections .elf_plt ,
631+ __movt (__AL , __r12 , addr_of_got ));
632+ elf_write_int (dynamic_sections .elf_plt , __lw (__AL , __pc , __r12 , 0 ));
633+ }
634+ }
0 commit comments