@@ -320,6 +320,12 @@ riscv_is_insn_reloc (const reloc_howto_type *howto)
320320#define PLT_ENTRY_INSNS 4
321321#define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
322322#define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
323+
324+ #define PLT_ZICFILP_UNLABELED_HEADER_INSNS 12
325+ #define PLT_ZICFILP_UNLABELED_ENTRY_INSNS 4
326+ #define PLT_ZICFILP_UNLABELED_HEADER_SIZE (PLT_ZICFILP_UNLABELED_HEADER_INSNS * 4)
327+ #define PLT_ZICFILP_UNLABELED_ENTRY_SIZE (PLT_ZICFILP_UNLABELED_ENTRY_INSNS * 4)
328+
323329#define GOT_ENTRY_SIZE RISCV_ELF_WORD_BYTES
324330#define TLS_GD_GOT_ENTRY_SIZE (RISCV_ELF_WORD_BYTES * 2)
325331#define TLS_IE_GOT_ENTRY_SIZE RISCV_ELF_WORD_BYTES
@@ -339,6 +345,31 @@ riscv_is_insn_reloc (const reloc_howto_type *howto)
339345# define MATCH_LREG MATCH_LQ
340346#endif
341347
348+
349+ /* Check whether the compact PLT is used in this object. Tools need this
350+ to dump the correct PLT header contents. */
351+
352+ static long
353+ elfNN_riscv_get_synthetic_symtab (bfd * abfd ,
354+ long symcount ,
355+ asymbol * * syms ,
356+ long dynsymcount ,
357+ asymbol * * dynsyms ,
358+ asymbol * * ret )
359+ {
360+ /* Check Zicfilp PLT. */
361+ elf_property * prop ;
362+ prop = _bfd_elf_get_property (abfd , GNU_PROPERTY_RISCV_FEATURE_1_AND , 4 );
363+ if (prop )
364+ {
365+ if (prop -> u .number & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED )
366+ _bfd_riscv_elf_tdata (abfd )-> plt_type |= PLT_ZICFILP_UNLABELED ;
367+ }
368+
369+ return _bfd_elf_get_synthetic_symtab (abfd , symcount , syms ,
370+ dynsymcount , dynsyms , ret );
371+ }
372+
342373/* Generate a PLT header. */
343374
344375static bool
@@ -386,6 +417,64 @@ riscv_make_plt_header (bfd *output_bfd, struct riscv_elf_link_hash_table *htab)
386417 return true;
387418}
388419
420+ static bool
421+ riscv_make_plt_zicfilp_unlabeled_header (bfd * output_bfd ,
422+ struct riscv_elf_link_hash_table * htab )
423+ {
424+ /*
425+ lpad 0 # disable label checking
426+ auipc t2, %hi(.got.plt) # Rewrite this to using
427+ sub t1, t1, t3 # shifted .got.plt offset + hdr size + 16
428+ l[w|d] t3, %lo(1b)(t2) # _dl_runtime_resolve
429+ addi t1, t1, -(hdr size + 12) # shifted .got.plt offset
430+ addi t0, t2, %pcrel_lo(1b) # &.got.plt
431+ srli t1, t1, log2(16/PTRSIZE) # .got.plt offset
432+ l[w|d] t0, PTRSIZE(t0) # link map
433+ jr t3
434+ nop
435+ nop
436+ nop */
437+
438+ /* RVE has no t3 register, so this won't work, and is not supported. */
439+ if (elf_elfheader (output_bfd )-> e_flags & EF_RISCV_RVE )
440+ {
441+ _bfd_error_handler (_ ("%pB: warning: RVE PLT generation not supported" ),
442+ output_bfd );
443+ return false;
444+ }
445+
446+ asection * gotplt = htab -> elf .sgotplt ;
447+ bfd_vma gotplt_addr = sec_addr (gotplt );
448+
449+ asection * splt = htab -> elf .splt ;
450+ bfd_vma plt_header_addr = sec_addr (splt );
451+
452+ bfd_vma auipc_addr = plt_header_addr + 4 ;
453+ /* Add INSN_BYTES to skip the lpad instruction. */
454+ bfd_vma gotplt_offset_high = RISCV_PCREL_HIGH_PART (gotplt_addr , auipc_addr );
455+ bfd_vma gotplt_offset_low = RISCV_PCREL_LOW_PART (gotplt_addr , auipc_addr );
456+
457+ uint32_t header [PLT_ZICFILP_UNLABELED_HEADER_INSNS ];
458+ header [0 ] = RISCV_UTYPE (LPAD , X_ZERO , 0 );
459+ header [1 ] = RISCV_UTYPE (AUIPC , X_T2 , gotplt_offset_high );
460+ header [2 ] = RISCV_RTYPE (SUB , X_T1 , X_T1 , X_T3 );
461+ header [3 ] = RISCV_ITYPE (LREG , X_T3 , X_T2 , gotplt_offset_low );
462+ header [4 ] = RISCV_ITYPE (ADDI , X_T1 , X_T1 ,
463+ (uint32_t ) - (PLT_ZICFILP_UNLABELED_HEADER_SIZE + 16 ));
464+ header [5 ] = RISCV_ITYPE (ADDI , X_T0 , X_T2 , gotplt_offset_low );
465+ header [6 ] = RISCV_ITYPE (SRLI , X_T1 , X_T1 , 4 - RISCV_ELF_LOG_WORD_BYTES );
466+ header [7 ] = RISCV_ITYPE (LREG , X_T0 , X_T0 , RISCV_ELF_WORD_BYTES );
467+ header [8 ] = RISCV_ITYPE (JALR , 0 , X_T3 , 0 );
468+ header [9 ] = RISCV_NOP ;
469+ header [10 ] = RISCV_NOP ;
470+ header [11 ] = RISCV_NOP ;
471+
472+ for (int i = 0 ; i < PLT_ZICFILP_UNLABELED_HEADER_INSNS ; i ++ )
473+ bfd_putl32 (header [i ], splt -> contents + 4 * i );
474+
475+ return true;
476+ }
477+
389478/* Generate a PLT entry. */
390479
391480static bool
@@ -420,6 +509,40 @@ riscv_make_plt_entry (bfd *output_bfd, asection *gotsec, bfd_vma got_offset,
420509 return true;
421510}
422511
512+ static bool
513+ riscv_make_plt_zicfilp_unlabeled_entry (bfd * output_bfd , asection * got ,
514+ bfd_vma got_offset , asection * plt ,
515+ bfd_vma plt_offset )
516+ {
517+ /* lpad 0
518+ 1: auipc t3, %pcrel_hi([email protected] ) 519+ l[w|d] t3, %pcrel_lo(1b)(t3)
520+ jalr t1, t3 */
521+
522+ /* RVE has no t3 register, so this won't work, and is not supported. */
523+ if (elf_elfheader (output_bfd )-> e_flags & EF_RISCV_RVE )
524+ {
525+ _bfd_error_handler (_ ("%pB: warning: RVE PLT generation not supported" ),
526+ output_bfd );
527+ return false;
528+ }
529+
530+ bfd_vma got_entry_addr = sec_addr (got ) + got_offset ;
531+ bfd_vma plt_entry_addr = sec_addr (plt ) + plt_offset ;
532+ bfd_vma auipc_addr = plt_entry_addr + 4 ;
533+ uint32_t entry [PLT_ZICFILP_UNLABELED_ENTRY_INSNS ];
534+ entry [0 ] = RISCV_UTYPE (LPAD , X_ZERO , 0 );
535+ entry [1 ] = RISCV_UTYPE (AUIPC , X_T3 , RISCV_PCREL_HIGH_PART (got_entry_addr , auipc_addr ));
536+ entry [2 ] = RISCV_ITYPE (LREG , X_T3 , X_T3 , RISCV_PCREL_LOW_PART (got_entry_addr , auipc_addr ));
537+ entry [3 ] = RISCV_ITYPE (JALR , X_T1 , X_T3 , 0 );
538+
539+ bfd_byte * loc = plt -> contents + plt_offset ;
540+ for (int i = 0 ; i < PLT_ZICFILP_UNLABELED_ENTRY_INSNS ; i ++ )
541+ bfd_putl32 (entry [i ], loc + 4 * i );
542+
543+ return true;
544+ }
545+
423546/* Create an entry in an RISC-V ELF linker hash table. */
424547
425548static struct bfd_hash_entry *
@@ -546,6 +669,13 @@ setup_plt_values (struct bfd *output_bfd,
546669 htab -> make_plt_entry = riscv_make_plt_entry ;
547670 break ;
548671
672+ case PLT_ZICFILP_UNLABELED :
673+ htab -> plt_header_size = PLT_ZICFILP_UNLABELED_HEADER_SIZE ;
674+ htab -> plt_entry_size = PLT_ZICFILP_UNLABELED_ENTRY_SIZE ;
675+ htab -> make_plt_header = riscv_make_plt_zicfilp_unlabeled_header ;
676+ htab -> make_plt_entry = riscv_make_plt_zicfilp_unlabeled_entry ;
677+ break ;
678+
549679 default :
550680 _bfd_error_handler (_ ("%pB: error: unsupported PLT type: %u" ),
551681 output_bfd ,
@@ -3745,6 +3875,9 @@ riscv_elf_plt_sym_val (bfd_vma i, const asection *plt,
37453875 case PLT_NORMAL :
37463876 return plt -> vma + (PLT_HEADER_SIZE ) + (i * PLT_ENTRY_SIZE );
37473877
3878+ case PLT_ZICFILP_UNLABELED :
3879+ return plt -> vma + PLT_ZICFILP_UNLABELED_HEADER_SIZE + (i * PLT_ZICFILP_UNLABELED_ENTRY_SIZE );
3880+
37483881 default :
37493882 abort ();
37503883 }
@@ -5855,6 +5988,13 @@ elfNN_riscv_link_setup_gnu_properties (struct bfd_link_info *info)
58555988 bfd * pbfd = _bfd_riscv_elf_link_setup_gnu_properties (info , & and_prop );
58565989
58575990 _bfd_riscv_elf_tdata (info -> output_bfd )-> gnu_and_prop = and_prop ;
5991+
5992+ if (and_prop & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED )
5993+ _bfd_riscv_elf_tdata (info -> output_bfd )-> plt_type = PLT_ZICFILP_UNLABELED ;
5994+
5995+ setup_plt_values (info -> output_bfd , riscv_elf_hash_table (info ),
5996+ _bfd_riscv_elf_tdata (info -> output_bfd )-> plt_type );
5997+
58585998 return pbfd ;
58595999}
58606000
@@ -5905,6 +6045,7 @@ elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd,
59056045#define elf_info_to_howto riscv_info_to_howto_rela
59066046#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section
59076047#define bfd_elfNN_mkobject elfNN_riscv_mkobject
6048+ #define bfd_elfNN_get_synthetic_symtab elfNN_riscv_get_synthetic_symtab
59086049#define elf_backend_additional_program_headers \
59096050 riscv_elf_additional_program_headers
59106051#define elf_backend_modify_segment_map riscv_elf_modify_segment_map
0 commit comments