@@ -469,25 +469,9 @@ void RangeExtensionThunk<E>::copy_buf(Context<E> &ctx) {
469
469
#define ASSERT_RANGE (val, start, size ) \
470
470
assert ((start) <= (val) && (val) < ((start) + (size)))
471
471
472
- static void relax_adrp_ldr_got_ldr (Context<E> &ctx, ObjectFile<E> *file,
473
- std::string_view &hints) {
474
- i64 addr1 = read_uleb (hints);
475
- i64 addr2 = read_uleb (hints);
476
- i64 addr3 = read_uleb (hints);
477
-
478
- Subsection<E> *subsec = file->find_subsection (ctx, addr1);
479
- if (!subsec || !subsec->is_alive )
480
- return ;
481
-
482
- ASSERT_RANGE (addr1, subsec->input_addr , subsec->input_size );
483
- ASSERT_RANGE (addr2, subsec->input_addr , subsec->input_size );
484
- ASSERT_RANGE (addr3, subsec->input_addr , subsec->input_size );
485
-
486
- i64 offset1 = addr1 - subsec->input_addr ;
487
- i64 offset2 = addr2 - subsec->input_addr ;
488
- i64 offset3 = addr3 - subsec->input_addr ;
489
-
490
- u8 *loc = ctx.buf + subsec->isec .osec .hdr .offset + subsec->output_offset ;
472
+ static void relax_adrp_ldr_got_ldr (Context<E> &ctx, Subsection<E> &subsec,
473
+ i64 offset1, i64 offset2, i64 offset3) {
474
+ u8 *loc = ctx.buf + subsec.isec .osec .hdr .offset + subsec.output_offset ;
491
475
ul32 *loc1 = (ul32 *)(loc + offset1);
492
476
ul32 *loc2 = (ul32 *)(loc + offset2);
493
477
ul32 *loc3 = (ul32 *)(loc + offset3);
@@ -501,9 +485,9 @@ static void relax_adrp_ldr_got_ldr(Context<E> &ctx, ObjectFile<E> *file,
501
485
(*loc2 & 0xffc0'0000 ) != 0xf940'0000 )
502
486
return ;
503
487
504
- u64 got_addr = page (subsec-> get_addr (ctx) + offset1) +
505
- (bits (*loc1, 23 , 5 ) << 14 ) + (bits (*loc1, 30 , 29 ) << 12 ) +
506
- (bits (*loc2, 21 , 10 ) << 3 );
488
+ u64 got_addr = page (subsec. get_addr (ctx) + offset1) +
489
+ (bits (*loc1, 23 , 5 ) << 14 ) + (bits (*loc1, 30 , 29 ) << 12 ) +
490
+ (bits (*loc2, 21 , 10 ) << 3 );
507
491
508
492
ASSERT_RANGE (got_addr, ctx.got .hdr .addr , ctx.got .hdr .size );
509
493
@@ -516,7 +500,7 @@ static void relax_adrp_ldr_got_ldr(Context<E> &ctx, ObjectFile<E> *file,
516
500
switch (*loc3 & 0xffc0'0000 ) {
517
501
case 0xf940'0000 : { // ldr Xc, [Xb, #imm]
518
502
u64 imm = bits (*loc3, 21 , 10 ) * 8 ;
519
- i64 disp = got_value + imm - subsec-> get_addr (ctx) - offset3;
503
+ i64 disp = got_value + imm - subsec. get_addr (ctx) - offset3;
520
504
if (disp == sign_extend (disp, 20 ) && (disp & 0b11 ) == 0 ) {
521
505
*loc1 = 0xd503'201f ; // nop
522
506
*loc2 = 0xd503'201f ; // nop
@@ -527,7 +511,7 @@ static void relax_adrp_ldr_got_ldr(Context<E> &ctx, ObjectFile<E> *file,
527
511
}
528
512
case 0xb940'0000 : { // ldr Wc, [Xb, #imm]
529
513
u64 imm = bits (*loc3, 21 , 10 ) * 4 ;
530
- i64 disp = got_value + imm - subsec-> get_addr (ctx) - offset3;
514
+ i64 disp = got_value + imm - subsec. get_addr (ctx) - offset3;
531
515
if (disp == sign_extend (disp, 20 ) && (disp & 0b11 ) == 0 ) {
532
516
*loc1 = 0xd503'201f ; // nop
533
517
*loc2 = 0xd503'201f ; // nop
@@ -540,30 +524,17 @@ static void relax_adrp_ldr_got_ldr(Context<E> &ctx, ObjectFile<E> *file,
540
524
}
541
525
542
526
// If the GOT slot is close enough to PC, we can eliminate ADRP.
543
- if (i64 disp = got_addr - subsec-> get_addr (ctx) - offset2;
527
+ if (i64 disp = got_addr - subsec. get_addr (ctx) - offset2;
544
528
disp == sign_extend (disp, 20 ) && (disp & 0b11 ) == 0 ) {
545
529
*loc1 = 0xd503'201f ; // nop
546
530
*loc2 = 0x5800'0000 | (bits (disp, 20 , 2 ) << 5 ) |
547
531
bits (*loc2, 4 , 0 ); // ldr Xb, _foo@GOT
548
532
}
549
533
}
550
534
551
- static void relax_adrp_add (Context<E> &ctx, ObjectFile<E> *file,
552
- std::string_view &hints) {
553
- i64 addr1 = read_uleb (hints);
554
- i64 addr2 = read_uleb (hints);
555
-
556
- Subsection<E> *subsec = file->find_subsection (ctx, addr1);
557
- if (!subsec || !subsec->is_alive )
558
- return ;
559
-
560
- ASSERT_RANGE (addr1, subsec->input_addr , subsec->input_size );
561
- ASSERT_RANGE (addr2, subsec->input_addr , subsec->input_size );
562
-
563
- i64 offset1 = addr1 - subsec->input_addr ;
564
- i64 offset2 = addr2 - subsec->input_addr ;
565
-
566
- u8 *loc = ctx.buf + subsec->isec .osec .hdr .offset + subsec->output_offset ;
535
+ static void relax_adrp_add (Context<E> &ctx, Subsection<E> &subsec,
536
+ i64 offset1, i64 offset2) {
537
+ u8 *loc = ctx.buf + subsec.isec .osec .hdr .offset + subsec.output_offset ;
567
538
ul32 *loc1 = (ul32 *)(loc + offset1);
568
539
ul32 *loc2 = (ul32 *)(loc + offset2);
569
540
@@ -575,10 +546,10 @@ static void relax_adrp_add(Context<E> &ctx, ObjectFile<E> *file,
575
546
(*loc2 & 0xffc0'0000 ) != 0x9100'0000 )
576
547
return ;
577
548
578
- u64 addr = page (subsec-> get_addr (ctx) + offset1) +
579
- (bits (*loc1, 23 , 5 ) << 14 ) + (bits (*loc1, 30 , 29 ) << 12 ) +
580
- bits (*loc2, 21 , 10 );
581
- i64 disp = addr - subsec-> get_addr (ctx) - offset2;
549
+ u64 addr = page (subsec. get_addr (ctx) + offset1) +
550
+ (bits (*loc1, 23 , 5 ) << 14 ) + (bits (*loc1, 30 , 29 ) << 12 ) +
551
+ bits (*loc2, 21 , 10 );
552
+ i64 disp = addr - subsec. get_addr (ctx) - offset2;
582
553
583
554
if (disp == sign_extend (disp, 20 )) {
584
555
*loc1 = 0xd503'201f ; // nop
@@ -618,12 +589,45 @@ void apply_linker_optimization_hints(Context<E> &ctx) {
618
589
i64 nargs = read_uleb (hints);
619
590
620
591
switch (type) {
621
- case LOH_ARM64_ADRP_LDR_GOT_LDR:
622
- relax_adrp_ldr_got_ldr (ctx, file, hints);
592
+ case LOH_ARM64_ADRP_LDR_GOT_LDR: {
593
+ assert (nargs == 3 );
594
+ i64 addr1 = read_uleb (hints);
595
+ i64 addr2 = read_uleb (hints);
596
+ i64 addr3 = read_uleb (hints);
597
+
598
+ Subsection<E> *subsec = file->find_subsection (ctx, addr1);
599
+ if (!subsec || !subsec->is_alive )
600
+ return ;
601
+
602
+ ASSERT_RANGE (addr1, subsec->input_addr , subsec->input_size );
603
+ ASSERT_RANGE (addr2, subsec->input_addr , subsec->input_size );
604
+ ASSERT_RANGE (addr3, subsec->input_addr , subsec->input_size );
605
+
606
+ i64 offset1 = addr1 - subsec->input_addr ;
607
+ i64 offset2 = addr2 - subsec->input_addr ;
608
+ i64 offset3 = addr3 - subsec->input_addr ;
609
+
610
+ relax_adrp_ldr_got_ldr (ctx, *subsec, offset1, offset2, offset3);
623
611
break ;
624
- case LOH_ARM64_ADRP_ADD:
625
- relax_adrp_add (ctx, file, hints);
612
+ }
613
+ case LOH_ARM64_ADRP_ADD: {
614
+ assert (nargs == 2 );
615
+ i64 addr1 = read_uleb (hints);
616
+ i64 addr2 = read_uleb (hints);
617
+
618
+ Subsection<E> *subsec = file->find_subsection (ctx, addr1);
619
+ if (!subsec || !subsec->is_alive )
620
+ return ;
621
+
622
+ ASSERT_RANGE (addr1, subsec->input_addr , subsec->input_size );
623
+ ASSERT_RANGE (addr2, subsec->input_addr , subsec->input_size );
624
+
625
+ i64 offset1 = addr1 - subsec->input_addr ;
626
+ i64 offset2 = addr2 - subsec->input_addr ;
627
+
628
+ relax_adrp_add (ctx, *subsec, offset1, offset2);
626
629
break ;
630
+ }
627
631
default :
628
632
// Skip unsupported optimizations hints.
629
633
for (i64 i = 0 ; i < nargs; i++)
0 commit comments