@@ -177,6 +177,9 @@ struct _bfd_riscv_elf_obj_tdata
177177
178178 /* tls_type for each local got entry. */
179179 char * local_got_tls_type ;
180+
181+ /* PLT type. */
182+ riscv_plt_type plt_type ;
180183};
181184
182185#define _bfd_riscv_elf_tdata (abfd ) \
@@ -233,6 +236,15 @@ struct riscv_elf_link_hash_table
233236
234237 /* Relocations for variant CC symbols may be present. */
235238 int variant_cc ;
239+
240+ /* The number of bytes in the PLT header and enties. */
241+ bfd_size_type plt_header_size ;
242+ bfd_size_type plt_entry_size ;
243+
244+ /* Functions to make PLT header and entries. */
245+ bool (* make_plt_header ) (bfd * output_bfd , struct riscv_elf_link_hash_table * htab );
246+ bool (* make_plt_entry ) (bfd * output_bfd , asection * got , bfd_vma got_offset ,
247+ asection * plt , bfd_vma plt_offset );
236248};
237249
238250/* Instruction access functions. */
@@ -255,6 +267,12 @@ struct riscv_elf_link_hash_table
255267 && elf_hash_table_id (elf_hash_table (p)) == RISCV_ELF_DATA) \
256268 ? (struct riscv_elf_link_hash_table *) (p)->hash : NULL)
257269
270+ /* Forward declaration PLT related functions. */
271+ static bool
272+ riscv_make_plt_header (bfd * , struct riscv_elf_link_hash_table * );
273+ static bool
274+ riscv_make_plt_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma );
275+
258276void
259277riscv_elfNN_set_options (struct bfd_link_info * link_info ,
260278 struct riscv_elf_params * params )
@@ -322,9 +340,14 @@ riscv_is_insn_reloc (const reloc_howto_type *howto)
322340/* Generate a PLT header. */
323341
324342static bool
325- riscv_make_plt_header (bfd * output_bfd , bfd_vma gotplt_addr , bfd_vma addr ,
326- uint32_t * entry )
343+ riscv_make_plt_header (bfd * output_bfd , struct riscv_elf_link_hash_table * htab )
327344{
345+ asection * splt = htab -> elf .splt ;
346+ bfd_vma addr = sec_addr (splt );
347+
348+ asection * sgotplt = htab -> elf .sgotplt ;
349+ bfd_vma gotplt_addr = sec_addr (sgotplt );
350+
328351 bfd_vma gotplt_offset_high = RISCV_PCREL_HIGH_PART (gotplt_addr , addr );
329352 bfd_vma gotplt_offset_low = RISCV_PCREL_LOW_PART (gotplt_addr , addr );
330353
@@ -345,6 +368,7 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
345368 l[w|d] t0, PTRSIZE(t0) # link map
346369 jr t3 */
347370
371+ uint32_t entry [PLT_HEADER_INSNS ];
348372 entry [0 ] = RISCV_UTYPE (AUIPC , X_T2 , gotplt_offset_high );
349373 entry [1 ] = RISCV_RTYPE (SUB , X_T1 , X_T1 , X_T3 );
350374 entry [2 ] = RISCV_ITYPE (LREG , X_T3 , X_T2 , gotplt_offset_low );
@@ -354,15 +378,20 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr,
354378 entry [6 ] = RISCV_ITYPE (LREG , X_T0 , X_T0 , RISCV_ELF_WORD_BYTES );
355379 entry [7 ] = RISCV_ITYPE (JALR , 0 , X_T3 , 0 );
356380
381+ for (int i = 0 ; i < PLT_HEADER_INSNS ; i ++ )
382+ bfd_putl32 (entry [i ], splt -> contents + 4 * i );
383+
357384 return true;
358385}
359386
360387/* Generate a PLT entry. */
361388
362389static bool
363- riscv_make_plt_entry (bfd * output_bfd , bfd_vma got , bfd_vma addr ,
364- uint32_t * entry )
390+ riscv_make_plt_entry (bfd * output_bfd , asection * gotsec , bfd_vma got_offset ,
391+ asection * pltsec , bfd_vma plt_offset )
365392{
393+ bfd_vma got = sec_addr (gotsec ) + got_offset ;
394+ bfd_vma addr = sec_addr (pltsec ) + plt_offset ;
366395 /* RVE has no t3 register, so this won't work, and is not supported. */
367396 if (elf_elfheader (output_bfd )-> e_flags & EF_RISCV_RVE )
368397 {
@@ -376,11 +405,16 @@ riscv_make_plt_entry (bfd *output_bfd, bfd_vma got, bfd_vma addr,
376405 jalr t1, t3
377406 nop */
378407
408+ uint32_t entry [PLT_ENTRY_INSNS ];
379409 entry [0 ] = RISCV_UTYPE (AUIPC , X_T3 , RISCV_PCREL_HIGH_PART (got , addr ));
380410 entry [1 ] = RISCV_ITYPE (LREG , X_T3 , X_T3 , RISCV_PCREL_LOW_PART (got , addr ));
381411 entry [2 ] = RISCV_ITYPE (JALR , X_T1 , X_T3 , 0 );
382412 entry [3 ] = RISCV_NOP ;
383413
414+ bfd_byte * loc = pltsec -> contents + plt_offset ;
415+ for (int i = 0 ; i < PLT_ENTRY_INSNS ; i ++ )
416+ bfd_putl32 (entry [i ], loc + 4 * i );
417+
384418 return true;
385419}
386420
@@ -494,6 +528,31 @@ riscv_elf_link_hash_table_free (bfd *obfd)
494528 _bfd_elf_link_hash_table_free (obfd );
495529}
496530
531+ /* Set up the PLT generation stubs in the hash table. */
532+
533+ static void
534+ setup_plt_values (struct bfd * output_bfd ,
535+ struct riscv_elf_link_hash_table * htab ,
536+ unsigned plt_type )
537+ {
538+ switch (plt_type )
539+ {
540+ case PLT_NORMAL :
541+ htab -> plt_header_size = PLT_HEADER_SIZE ;
542+ htab -> plt_entry_size = PLT_ENTRY_SIZE ;
543+ htab -> make_plt_header = riscv_make_plt_header ;
544+ htab -> make_plt_entry = riscv_make_plt_entry ;
545+ break ;
546+
547+ default :
548+ _bfd_error_handler (_ ("%pB: error: unsupported PLT type: %u" ),
549+ output_bfd ,
550+ plt_type );
551+ bfd_set_error (bfd_error_bad_value );
552+ break ;
553+ }
554+ }
555+
497556/* Create a RISC-V ELF linker hash table. */
498557
499558static struct bfd_link_hash_table *
@@ -516,6 +575,8 @@ riscv_elf_link_hash_table_create (bfd *abfd)
516575 ret -> max_alignment = (bfd_vma ) - 1 ;
517576 ret -> max_alignment_for_gp = (bfd_vma ) - 1 ;
518577
578+ setup_plt_values (abfd , ret , PLT_NORMAL );
579+
519580 /* Create hash table for local ifunc. */
520581 ret -> loc_hash_table = htab_try_create (1024 ,
521582 riscv_elf_local_htab_hash ,
@@ -1266,12 +1327,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
12661327 asection * s = htab -> elf .splt ;
12671328
12681329 if (s -> size == 0 )
1269- s -> size = PLT_HEADER_SIZE ;
1330+ s -> size = htab -> plt_header_size ;
12701331
12711332 h -> plt .offset = s -> size ;
12721333
12731334 /* Make room for this entry. */
1274- s -> size += PLT_ENTRY_SIZE ;
1335+ s -> size += htab -> plt_entry_size ;
12751336
12761337 /* We also need to make an entry in the .got.plt section. */
12771338 htab -> elf .sgotplt -> size += GOT_ENTRY_SIZE ;
@@ -1463,6 +1524,7 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
14631524 void * inf )
14641525{
14651526 struct bfd_link_info * info ;
1527+ struct riscv_elf_link_hash_table * htab ;
14661528
14671529 if (h -> root .type == bfd_link_hash_indirect )
14681530 return true;
@@ -1471,15 +1533,16 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
14711533 h = (struct elf_link_hash_entry * ) h -> root .u .i .link ;
14721534
14731535 info = (struct bfd_link_info * ) inf ;
1536+ htab = riscv_elf_hash_table (info );
14741537
14751538 /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
14761539 here if it is defined and referenced in a non-shared object. */
14771540 if (h -> type == STT_GNU_IFUNC
14781541 && h -> def_regular )
14791542 return _bfd_elf_allocate_ifunc_dyn_relocs (info , h ,
14801543 & h -> dyn_relocs ,
1481- PLT_ENTRY_SIZE ,
1482- PLT_HEADER_SIZE ,
1544+ htab -> plt_entry_size ,
1545+ htab -> plt_header_size ,
14831546 GOT_ENTRY_SIZE ,
14841547 true);
14851548 return true;
@@ -2487,14 +2550,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
24872550
24882551 if (htab -> elf .splt != NULL )
24892552 {
2490- plt_idx = (h -> plt .offset - PLT_HEADER_SIZE )
2491- / PLT_ENTRY_SIZE ;
2553+ plt_idx = (h -> plt .offset - htab -> plt_header_size )
2554+ / htab -> plt_entry_size ;
24922555 off = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE );
24932556 base_got = htab -> elf .sgotplt ;
24942557 }
24952558 else
24962559 {
2497- plt_idx = h -> plt .offset / PLT_ENTRY_SIZE ;
2560+ plt_idx = h -> plt .offset / htab -> plt_entry_size ;
24982561 off = plt_idx * GOT_ENTRY_SIZE ;
24992562 base_got = htab -> elf .igotplt ;
25002563 }
@@ -3266,8 +3329,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
32663329 {
32673330 /* We've decided to create a PLT entry for this symbol. */
32683331 bfd_byte * loc ;
3269- bfd_vma i , header_address , plt_idx , got_offset , got_address ;
3270- uint32_t plt_entry [PLT_ENTRY_INSNS ];
3332+ bfd_vma plt_idx , got_offset , got_address ;
32713333 Elf_Internal_Rela rela ;
32723334 asection * plt , * gotplt , * relplt ;
32733335
@@ -3297,36 +3359,29 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
32973359 || relplt == NULL )
32983360 abort ();
32993361
3300- /* Calculate the address of the PLT header. */
3301- header_address = sec_addr (plt );
3302-
33033362 /* Calculate the index of the entry and the offset of .got.plt entry.
33043363 For static executables, we don't reserve anything. */
33053364 if (plt == htab -> elf .splt )
33063365 {
3307- plt_idx = (h -> plt .offset - PLT_HEADER_SIZE ) / PLT_ENTRY_SIZE ;
3366+ plt_idx = (h -> plt .offset - htab -> plt_header_size )
3367+ / htab -> plt_entry_size ;
33083368 got_offset = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE );
33093369 }
33103370 else
33113371 {
3312- plt_idx = h -> plt .offset / PLT_ENTRY_SIZE ;
3372+ plt_idx = h -> plt .offset / htab -> plt_entry_size ;
33133373 got_offset = plt_idx * GOT_ENTRY_SIZE ;
33143374 }
33153375
33163376 /* Calculate the address of the .got.plt entry. */
33173377 got_address = sec_addr (gotplt ) + got_offset ;
33183378
3319- /* Find out where the .plt entry should go. */
3320- loc = plt -> contents + h -> plt .offset ;
33213379
33223380 /* Fill in the PLT entry itself. */
3323- if (! riscv_make_plt_entry (output_bfd , got_address ,
3324- header_address + h -> plt .offset ,
3325- plt_entry ))
3381+ if (! htab -> make_plt_entry (output_bfd , gotplt , got_offset ,
3382+ plt , h -> plt .offset ))
33263383 return false;
33273384
3328- for (i = 0 ; i < PLT_ENTRY_INSNS ; i ++ )
3329- bfd_putl32 (plt_entry [i ], loc + 4 * i );
33303385
33313386 /* Fill in the initial value of the .got.plt entry. */
33323387 loc = gotplt -> contents + (got_address - sec_addr (gotplt ));
@@ -3614,19 +3669,12 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
36143669 /* Fill in the head and tail entries in the procedure linkage table. */
36153670 if (splt -> size > 0 )
36163671 {
3617- int i ;
3618- uint32_t plt_header [PLT_HEADER_INSNS ];
3619- ret = riscv_make_plt_header (output_bfd ,
3620- sec_addr (htab -> elf .sgotplt ),
3621- sec_addr (splt ), plt_header );
3672+ ret = htab -> make_plt_header (output_bfd , htab );
36223673 if (!ret )
36233674 return ret ;
36243675
3625- for (i = 0 ; i < PLT_HEADER_INSNS ; i ++ )
3626- bfd_putl32 (plt_header [i ], splt -> contents + 4 * i );
3627-
36283676 elf_section_data (splt -> output_section )-> this_hdr .sh_entsize
3629- = PLT_ENTRY_SIZE ;
3677+ = htab -> plt_entry_size ;
36303678 }
36313679 }
36323680
@@ -3689,7 +3737,15 @@ static bfd_vma
36893737riscv_elf_plt_sym_val (bfd_vma i , const asection * plt ,
36903738 const arelent * rel ATTRIBUTE_UNUSED )
36913739{
3692- return plt -> vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE ;
3740+ unsigned plt_type = _bfd_riscv_elf_tdata (plt -> owner )-> plt_type ;
3741+ switch (plt_type )
3742+ {
3743+ case PLT_NORMAL :
3744+ return plt -> vma + (PLT_HEADER_SIZE ) + (i * PLT_ENTRY_SIZE );
3745+
3746+ default :
3747+ abort ();
3748+ }
36933749}
36943750
36953751/* Used to decide how to sort relocs in an optimal manner for the
0 commit comments