@@ -176,6 +176,9 @@ struct _bfd_riscv_elf_obj_tdata
176176
177177 /* tls_type for each local got entry. */
178178 char * local_got_tls_type ;
179+
180+ /* PLT type. */
181+ riscv_plt_type plt_type ;
179182};
180183
181184#define _bfd_riscv_elf_tdata (abfd ) \
@@ -232,6 +235,15 @@ struct riscv_elf_link_hash_table
232235
233236 /* Relocations for variant CC symbols may be present. */
234237 int variant_cc ;
238+
239+ /* The number of bytes in the PLT header and enties. */
240+ bfd_size_type plt_header_size ;
241+ bfd_size_type plt_entry_size ;
242+
243+ /* Functions to make PLT header and entries. */
244+ bool (* make_plt_header ) (bfd * output_bfd , struct riscv_elf_link_hash_table * htab );
245+ bool (* make_plt_entry ) (bfd * output_bfd , asection * got , bfd_vma got_offset ,
246+ asection * plt , bfd_vma plt_offset );
235247};
236248
237249/* Instruction access functions. */
@@ -252,6 +264,12 @@ struct riscv_elf_link_hash_table
252264 && elf_hash_table_id (elf_hash_table (p)) == RISCV_ELF_DATA) \
253265 ? (struct riscv_elf_link_hash_table *) (p)->hash : NULL)
254266
267+ /* Forward declaration PLT related functions. */
268+ static bool
269+ riscv_make_plt_header (bfd * , struct riscv_elf_link_hash_table * );
270+ static bool
271+ riscv_make_plt_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma );
272+
255273void
256274riscv_elfNN_set_options (struct bfd_link_info * link_info ,
257275 struct riscv_elf_params * params )
@@ -317,9 +335,14 @@ riscv_is_insn_reloc (const reloc_howto_type *howto)
317335/* Generate a PLT header. */
318336
319337static bool
320- riscv_make_plt_header (bfd * output_bfd , bfd_vma gotplt_addr , bfd_vma addr ,
321- uint32_t * entry )
338+ riscv_make_plt_header (bfd * output_bfd , struct riscv_elf_link_hash_table * htab )
322339{
340+ asection * splt = htab -> elf .splt ;
341+ bfd_vma addr = sec_addr (splt );
342+
343+ asection * sgotplt = htab -> elf .sgotplt ;
344+ bfd_vma gotplt_addr = sec_addr (sgotplt );
345+
323346 bfd_vma gotplt_offset_high = RISCV_PCREL_HIGH_PART (gotplt_addr , addr );
324347 bfd_vma gotplt_offset_low = RISCV_PCREL_LOW_PART (gotplt_addr , addr );
325348
@@ -340,6 +363,7 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
340363 l[w|d] t0, PTRSIZE(t0) # link map
341364 jr t3 */
342365
366+ uint32_t entry [PLT_HEADER_INSNS ];
343367 entry [0 ] = RISCV_UTYPE (AUIPC , X_T2 , gotplt_offset_high );
344368 entry [1 ] = RISCV_RTYPE (SUB , X_T1 , X_T1 , X_T3 );
345369 entry [2 ] = RISCV_ITYPE (LREG , X_T3 , X_T2 , gotplt_offset_low );
@@ -349,15 +373,20 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
349373 entry [6 ] = RISCV_ITYPE (LREG , X_T0 , X_T0 , RISCV_ELF_WORD_BYTES );
350374 entry [7 ] = RISCV_ITYPE (JALR , 0 , X_T3 , 0 );
351375
376+ for (int i = 0 ; i < PLT_HEADER_INSNS ; i ++ )
377+ bfd_putl32 (entry [i ], splt -> contents + 4 * i );
378+
352379 return true;
353380}
354381
355382/* Generate a PLT entry. */
356383
357384static bool
358- riscv_make_plt_entry (bfd * output_bfd , bfd_vma got , bfd_vma addr ,
359- uint32_t * entry )
385+ riscv_make_plt_entry (bfd * output_bfd , asection * gotsec , bfd_vma got_offset ,
386+ asection * pltsec , bfd_vma plt_offset )
360387{
388+ bfd_vma got = sec_addr (gotsec ) + got_offset ;
389+ bfd_vma addr = sec_addr (pltsec ) + plt_offset ;
361390 /* RVE has no t3 register, so this won't work, and is not supported. */
362391 if (elf_elfheader (output_bfd )-> e_flags & EF_RISCV_RVE )
363392 {
@@ -371,11 +400,16 @@ riscv_make_plt_entry (bfd *output_bfd, bfd_vma got, bfd_vma addr,
371400 jalr t1, t3
372401 nop */
373402
403+ uint32_t entry [PLT_ENTRY_INSNS ];
374404 entry [0 ] = RISCV_UTYPE (AUIPC , X_T3 , RISCV_PCREL_HIGH_PART (got , addr ));
375405 entry [1 ] = RISCV_ITYPE (LREG , X_T3 , X_T3 , RISCV_PCREL_LOW_PART (got , addr ));
376406 entry [2 ] = RISCV_ITYPE (JALR , X_T1 , X_T3 , 0 );
377407 entry [3 ] = RISCV_NOP ;
378408
409+ bfd_byte * loc = pltsec -> contents + plt_offset ;
410+ for (int i = 0 ; i < PLT_ENTRY_INSNS ; i ++ )
411+ bfd_putl32 (entry [i ], loc + 4 * i );
412+
379413 return true;
380414}
381415
@@ -489,6 +523,31 @@ riscv_elf_link_hash_table_free (bfd *obfd)
489523 _bfd_elf_link_hash_table_free (obfd );
490524}
491525
526+ /* Set up the PLT generation stubs in the hash table. */
527+
528+ static void
529+ setup_plt_values (struct bfd * output_bfd ,
530+ struct riscv_elf_link_hash_table * htab ,
531+ unsigned plt_type )
532+ {
533+ switch (plt_type )
534+ {
535+ case PLT_NORMAL :
536+ htab -> plt_header_size = PLT_HEADER_SIZE ;
537+ htab -> plt_entry_size = PLT_ENTRY_SIZE ;
538+ htab -> make_plt_header = riscv_make_plt_header ;
539+ htab -> make_plt_entry = riscv_make_plt_entry ;
540+ break ;
541+
542+ default :
543+ _bfd_error_handler (_ ("%pB: error: unsupported PLT type: %u" ),
544+ output_bfd ,
545+ plt_type );
546+ bfd_set_error (bfd_error_bad_value );
547+ break ;
548+ }
549+ }
550+
492551/* Create a RISC-V ELF linker hash table. */
493552
494553static struct bfd_link_hash_table *
@@ -511,6 +570,8 @@ riscv_elf_link_hash_table_create (bfd *abfd)
511570 ret -> max_alignment = (bfd_vma ) - 1 ;
512571 ret -> max_alignment_for_gp = (bfd_vma ) - 1 ;
513572
573+ setup_plt_values (abfd , ret , PLT_NORMAL );
574+
514575 /* Create hash table for local ifunc. */
515576 ret -> loc_hash_table = htab_try_create (1024 ,
516577 riscv_elf_local_htab_hash ,
@@ -1259,12 +1320,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
12591320 asection * s = htab -> elf .splt ;
12601321
12611322 if (s -> size == 0 )
1262- s -> size = PLT_HEADER_SIZE ;
1323+ s -> size = htab -> plt_header_size ;
12631324
12641325 h -> plt .offset = s -> size ;
12651326
12661327 /* Make room for this entry. */
1267- s -> size += PLT_ENTRY_SIZE ;
1328+ s -> size += htab -> plt_entry_size ;
12681329
12691330 /* We also need to make an entry in the .got.plt section. */
12701331 htab -> elf .sgotplt -> size += GOT_ENTRY_SIZE ;
@@ -1456,6 +1517,7 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
14561517 void * inf )
14571518{
14581519 struct bfd_link_info * info ;
1520+ struct riscv_elf_link_hash_table * htab ;
14591521
14601522 if (h -> root .type == bfd_link_hash_indirect )
14611523 return true;
@@ -1464,15 +1526,16 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
14641526 h = (struct elf_link_hash_entry * ) h -> root .u .i .link ;
14651527
14661528 info = (struct bfd_link_info * ) inf ;
1529+ htab = riscv_elf_hash_table (info );
14671530
14681531 /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
14691532 here if it is defined and referenced in a non-shared object. */
14701533 if (h -> type == STT_GNU_IFUNC
14711534 && h -> def_regular )
14721535 return _bfd_elf_allocate_ifunc_dyn_relocs (info , h ,
14731536 & h -> dyn_relocs ,
1474- PLT_ENTRY_SIZE ,
1475- PLT_HEADER_SIZE ,
1537+ htab -> plt_entry_size ,
1538+ htab -> plt_header_size ,
14761539 GOT_ENTRY_SIZE ,
14771540 true);
14781541 return true;
@@ -2472,14 +2535,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
24722535
24732536 if (htab -> elf .splt != NULL )
24742537 {
2475- plt_idx = (h -> plt .offset - PLT_HEADER_SIZE )
2476- / PLT_ENTRY_SIZE ;
2538+ plt_idx = (h -> plt .offset - htab -> plt_header_size )
2539+ / htab -> plt_entry_size ;
24772540 off = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE );
24782541 base_got = htab -> elf .sgotplt ;
24792542 }
24802543 else
24812544 {
2482- plt_idx = h -> plt .offset / PLT_ENTRY_SIZE ;
2545+ plt_idx = h -> plt .offset / htab -> plt_entry_size ;
24832546 off = plt_idx * GOT_ENTRY_SIZE ;
24842547 base_got = htab -> elf .igotplt ;
24852548 }
@@ -3247,8 +3310,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
32473310 {
32483311 /* We've decided to create a PLT entry for this symbol. */
32493312 bfd_byte * loc ;
3250- bfd_vma i , header_address , plt_idx , got_offset , got_address ;
3251- uint32_t plt_entry [PLT_ENTRY_INSNS ];
3313+ bfd_vma plt_idx , got_offset , got_address ;
32523314 Elf_Internal_Rela rela ;
32533315 asection * plt , * gotplt , * relplt ;
32543316
@@ -3278,36 +3340,29 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
32783340 || relplt == NULL )
32793341 abort ();
32803342
3281- /* Calculate the address of the PLT header. */
3282- header_address = sec_addr (plt );
3283-
32843343 /* Calculate the index of the entry and the offset of .got.plt entry.
32853344 For static executables, we don't reserve anything. */
32863345 if (plt == htab -> elf .splt )
32873346 {
3288- plt_idx = (h -> plt .offset - PLT_HEADER_SIZE ) / PLT_ENTRY_SIZE ;
3347+ plt_idx = (h -> plt .offset - htab -> plt_header_size )
3348+ / htab -> plt_entry_size ;
32893349 got_offset = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE );
32903350 }
32913351 else
32923352 {
3293- plt_idx = h -> plt .offset / PLT_ENTRY_SIZE ;
3353+ plt_idx = h -> plt .offset / htab -> plt_entry_size ;
32943354 got_offset = plt_idx * GOT_ENTRY_SIZE ;
32953355 }
32963356
32973357 /* Calculate the address of the .got.plt entry. */
32983358 got_address = sec_addr (gotplt ) + got_offset ;
32993359
3300- /* Find out where the .plt entry should go. */
3301- loc = plt -> contents + h -> plt .offset ;
33023360
33033361 /* Fill in the PLT entry itself. */
3304- if (! riscv_make_plt_entry (output_bfd , got_address ,
3305- header_address + h -> plt .offset ,
3306- plt_entry ))
3362+ if (! htab -> make_plt_entry (output_bfd , gotplt , got_offset ,
3363+ plt , h -> plt .offset ))
33073364 return false;
33083365
3309- for (i = 0 ; i < PLT_ENTRY_INSNS ; i ++ )
3310- bfd_putl32 (plt_entry [i ], loc + 4 * i );
33113366
33123367 /* Fill in the initial value of the .got.plt entry. */
33133368 loc = gotplt -> contents + (got_address - sec_addr (gotplt ));
@@ -3595,19 +3650,12 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
35953650 /* Fill in the head and tail entries in the procedure linkage table. */
35963651 if (splt -> size > 0 )
35973652 {
3598- int i ;
3599- uint32_t plt_header [PLT_HEADER_INSNS ];
3600- ret = riscv_make_plt_header (output_bfd ,
3601- sec_addr (htab -> elf .sgotplt ),
3602- sec_addr (splt ), plt_header );
3653+ ret = htab -> make_plt_header (output_bfd , htab );
36033654 if (!ret )
36043655 return ret ;
36053656
3606- for (i = 0 ; i < PLT_HEADER_INSNS ; i ++ )
3607- bfd_putl32 (plt_header [i ], splt -> contents + 4 * i );
3608-
36093657 elf_section_data (splt -> output_section )-> this_hdr .sh_entsize
3610- = PLT_ENTRY_SIZE ;
3658+ = htab -> plt_entry_size ;
36113659 }
36123660 }
36133661
@@ -3661,7 +3709,15 @@ static bfd_vma
36613709riscv_elf_plt_sym_val (bfd_vma i , const asection * plt ,
36623710 const arelent * rel ATTRIBUTE_UNUSED )
36633711{
3664- return plt -> vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE ;
3712+ unsigned plt_type = _bfd_riscv_elf_tdata (plt -> owner )-> plt_type ;
3713+ switch (plt_type )
3714+ {
3715+ case PLT_NORMAL :
3716+ return plt -> vma + (PLT_HEADER_SIZE ) + (i * PLT_ENTRY_SIZE );
3717+
3718+ default :
3719+ abort ();
3720+ }
36653721}
36663722
36673723/* Used to decide how to sort relocs in an optimal manner for the
0 commit comments