@@ -301,6 +301,13 @@ typedef struct
301301 const char * name ;
302302} riscv_jvt_htab_entry ;
303303
304+ /* Hash table entry for lpadinfo: maps symbol name to lpad value. */
305+ typedef struct
306+ {
307+ const char * name ;
308+ uint32_t lpad_value ;
309+ } riscv_lpadinfo_entry ;
310+
304311struct riscv_elf_link_hash_table
305312{
306313 struct elf_link_hash_table elf ;
@@ -336,6 +343,9 @@ struct riscv_elf_link_hash_table
336343
337344 riscv_jvt_htab_t * jvt_htab ;
338345
346+ /* Hash table for lpadinfo: symbol name -> lpad value. */
347+ htab_t lpadinfo_htab ;
348+
339349 /* Find compact relocations in check_relocs. */
340350 bool compact_relocs ;
341351
@@ -346,7 +356,9 @@ struct riscv_elf_link_hash_table
346356 /* Functions to make PLT header and entries. */
347357 bool (* make_plt_header ) (bfd * output_bfd , struct riscv_elf_link_hash_table * htab );
348358 bool (* make_plt_entry ) (bfd * output_bfd , asection * got , bfd_vma got_offset ,
349- asection * plt , bfd_vma plt_offset );
359+ asection * plt , bfd_vma plt_offset ,
360+ struct elf_link_hash_entry * h ,
361+ struct bfd_link_info * info );
350362};
351363
352364/* Instruction access functions. */
@@ -378,26 +390,32 @@ static bool
378390riscv_make_plt_header (bfd * , struct riscv_elf_link_hash_table * );
379391
380392static bool
381- riscv_make_plt_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma );
393+ riscv_make_plt_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma ,
394+ struct elf_link_hash_entry * , struct bfd_link_info * );
382395
383396static bool riscv_make_plt_compact_header (bfd * ,
384397 struct riscv_elf_link_hash_table * );
385398
386399static bool riscv_make_plt_compact_entry (bfd * , asection * , bfd_vma ,
387- asection * , bfd_vma );
400+ asection * , bfd_vma ,
401+ struct elf_link_hash_entry * ,
402+ struct bfd_link_info * );
388403
389404static bool
390405riscv_make_plt_zicfilp_header (bfd * , struct riscv_elf_link_hash_table * );
391406
392407static bool
393- riscv_make_plt_zicfilp_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma );
408+ riscv_make_plt_zicfilp_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma ,
409+ struct elf_link_hash_entry * , struct bfd_link_info * );
394410
395411static bool
396412riscv_make_plt_zicfilp_func_sig_header (bfd * , struct riscv_elf_link_hash_table * );
397413
398414static bool
399- riscv_make_plt_zicfilp_func_sig_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma );
415+ riscv_make_plt_zicfilp_func_sig_entry (bfd * , asection * , bfd_vma , asection * , bfd_vma ,
416+ struct elf_link_hash_entry * , struct bfd_link_info * );
400417
418+ static bool riscv_lpadinfo_lookup (htab_t , const char * , uint32_t * );
401419
402420static void
403421setup_plt_values (struct bfd_link_info * link_info ,
@@ -947,7 +965,9 @@ riscv_make_plt_zicfilp_func_sig_header (bfd *output_bfd,
947965
948966static bool
949967riscv_make_plt_entry (bfd * output_bfd , asection * got , bfd_vma got_offset ,
950- asection * plt , bfd_vma plt_offset )
968+ asection * plt , bfd_vma plt_offset ,
969+ struct elf_link_hash_entry * h ATTRIBUTE_UNUSED ,
970+ struct bfd_link_info * info ATTRIBUTE_UNUSED )
951971{
952972 bfd_vma got_entry_addr = sec_addr (got ) + got_offset ;
953973 /* RVE has no t3 register, so this won't work, and is not supported. */
@@ -995,7 +1015,9 @@ riscv_make_plt_entry (bfd *output_bfd, asection *got, bfd_vma got_offset,
9951015static bool
9961016riscv_make_plt_compact_entry (bfd * output_bfd , asection * got ATTRIBUTE_UNUSED ,
9971017 bfd_vma got_offset , asection * plt ,
998- bfd_vma plt_offset )
1018+ bfd_vma plt_offset ,
1019+ struct elf_link_hash_entry * h ATTRIBUTE_UNUSED ,
1020+ struct bfd_link_info * info ATTRIBUTE_UNUSED )
9991021{
10001022 bfd_vma plt_addr = sec_addr (plt );
10011023 /* RVE has no t3 register, so this won't work, and is not supported. */
@@ -1054,7 +1076,9 @@ riscv_make_plt_compact_entry (bfd *output_bfd, asection *got ATTRIBUTE_UNUSED,
10541076
10551077static bool
10561078riscv_make_plt_zicfilp_entry (bfd * output_bfd ATTRIBUTE_UNUSED , asection * got ,
1057- bfd_vma got_offset , asection * plt , bfd_vma plt_offset )
1079+ bfd_vma got_offset , asection * plt , bfd_vma plt_offset ,
1080+ struct elf_link_hash_entry * h ATTRIBUTE_UNUSED ,
1081+ struct bfd_link_info * info ATTRIBUTE_UNUSED )
10581082{
10591083 /* lpad 0
10601084 1: auipc t3, %pcrel_hi(function@.got.plt)
@@ -1080,11 +1104,25 @@ riscv_make_plt_zicfilp_entry (bfd *output_bfd ATTRIBUTE_UNUSED, asection *got,
10801104static bool
10811105riscv_make_plt_zicfilp_func_sig_entry (bfd * output_bfd ATTRIBUTE_UNUSED , asection * got ,
10821106 bfd_vma got_offset , asection * plt ,
1083- bfd_vma plt_offset )
1107+ bfd_vma plt_offset ,
1108+ struct elf_link_hash_entry * h ,
1109+ struct bfd_link_info * info )
10841110{
1085- /* FIXME: Use 1 for landing pad label now, need use from
1086- .riscv.lpadinfo section. */
1087- int64_t lpl = 1 << 12 ;
1111+ struct riscv_elf_link_hash_table * htab = riscv_elf_hash_table (info );
1112+ uint32_t lpad_value = 0 ;
1113+
1114+ /* Look up lpad_value from lpadinfo hash table. */
1115+ if (htab -> lpadinfo_htab != NULL && h != NULL )
1116+ {
1117+ const char * name = h -> root .root .string ;
1118+ if (!riscv_lpadinfo_lookup (htab -> lpadinfo_htab , name , & lpad_value ))
1119+ _bfd_error_handler
1120+ (_ ("warning: no lpadinfo for PLT symbol `%s', using default value 0" ),
1121+ name );
1122+ }
1123+
1124+ /* The lpad value is placed in bits [31:12] of the instruction. */
1125+ int64_t lpl = (int64_t ) lpad_value << 12 ;
10881126
10891127 /* lpad <value>
10901128 auipc t3, %hi(function@.got.plt)
@@ -1235,6 +1273,198 @@ riscv_free_jvt_htab (riscv_jvt_htab_t *htab)
12351273 htab_delete (htab -> jalt_htab );
12361274}
12371275
1276+ /* Hash function for lpadinfo entries (by symbol name). */
1277+
1278+ static hashval_t
1279+ riscv_lpadinfo_htab_hash (const void * entry )
1280+ {
1281+ const riscv_lpadinfo_entry * e = entry ;
1282+ return htab_hash_string (e -> name );
1283+ }
1284+
1285+ /* Equality function for lpadinfo entries. */
1286+
1287+ static int
1288+ riscv_lpadinfo_htab_eq (const void * entry1 , const void * entry2 )
1289+ {
1290+ const riscv_lpadinfo_entry * e1 = entry1 , * e2 = entry2 ;
1291+ return strcmp (e1 -> name , e2 -> name ) == 0 ;
1292+ }
1293+
1294+ /* Look up lpad_value for a symbol in the lpadinfo hash table.
1295+ Returns true if found, false otherwise. The lpad_value is stored
1296+ in *VALUE_OUT if found. */
1297+
1298+ static bool
1299+ riscv_lpadinfo_lookup (htab_t htab , const char * name , uint32_t * value_out )
1300+ {
1301+ if (htab == NULL || name == NULL )
1302+ return false;
1303+
1304+ riscv_lpadinfo_entry search = { .name = name , .lpad_value = 0 };
1305+ riscv_lpadinfo_entry * entry = htab_find (htab , & search );
1306+
1307+ if (entry != NULL )
1308+ {
1309+ * value_out = entry -> lpad_value ;
1310+ return true;
1311+ }
1312+ return false;
1313+ }
1314+
1315+ /* Read .riscv.lpadinfo section from an input BFD and populate the
1316+ lpadinfo hash table with symbol name -> lpad_value mappings. */
1317+
1318+ static bool
1319+ riscv_read_lpadinfo_section (bfd * abfd , struct bfd_link_info * info )
1320+ {
1321+ struct riscv_elf_link_hash_table * htab = riscv_elf_hash_table (info );
1322+ asection * sec ;
1323+ bfd_byte * contents = NULL ;
1324+ Elf_Internal_Shdr * symtab_hdr ;
1325+ Elf_Internal_Sym * isymbuf = NULL ;
1326+ char * strtab = NULL ;
1327+ size_t strtab_size = 0 ;
1328+ uint32_t num_entries ;
1329+ uint32_t entry_size = RISCV_LPADINFO_ENTRY_SIZE ; /* lpi_sym + lpi_value + lpi_sig */
1330+ bool ret = true;
1331+
1332+ if (htab == NULL )
1333+ return false;
1334+
1335+ /* Find the .riscv.lpadinfo section. */
1336+ sec = bfd_get_section_by_name (abfd , ".riscv.lpadinfo" );
1337+ if (sec == NULL || sec -> size == 0 )
1338+ return true; /* No lpadinfo section, not an error. */
1339+
1340+ /* Verify section type. */
1341+ if (elf_section_data (sec )-> this_hdr .sh_type != SHT_RISCV_LANDING_PAD_INFO )
1342+ return true;
1343+
1344+ /* Create the hash table if needed. */
1345+ if (htab -> lpadinfo_htab == NULL )
1346+ {
1347+ htab -> lpadinfo_htab = htab_try_create (64 , riscv_lpadinfo_htab_hash ,
1348+ riscv_lpadinfo_htab_eq , free );
1349+ if (htab -> lpadinfo_htab == NULL )
1350+ return false;
1351+ }
1352+
1353+ /* Read section contents. */
1354+ if (!bfd_malloc_and_get_section (abfd , sec , & contents ))
1355+ {
1356+ ret = false;
1357+ goto cleanup ;
1358+ }
1359+
1360+ /* Get number of entries from sh_info. */
1361+ num_entries = elf_section_data (sec )-> this_hdr .sh_info ;
1362+ if (num_entries == 0 || num_entries * entry_size > sec -> size )
1363+ goto cleanup ;
1364+
1365+ /* Read the symbol table. */
1366+ symtab_hdr = & elf_tdata (abfd )-> symtab_hdr ;
1367+ if (symtab_hdr -> sh_info != 0 )
1368+ {
1369+ isymbuf = (Elf_Internal_Sym * ) symtab_hdr -> contents ;
1370+ if (isymbuf == NULL )
1371+ isymbuf = bfd_elf_get_elf_syms (abfd , symtab_hdr ,
1372+ symtab_hdr -> sh_info , 0 ,
1373+ NULL , NULL , NULL );
1374+ }
1375+
1376+ /* Read the string table. */
1377+ if (symtab_hdr -> sh_link != 0 )
1378+ {
1379+ unsigned int strndx = symtab_hdr -> sh_link ;
1380+ Elf_Internal_Shdr * strtab_hdr = elf_elfsections (abfd )[strndx ];
1381+ strtab = (char * ) bfd_elf_get_str_section (abfd , strndx );
1382+ strtab_size = strtab_hdr -> sh_size ;
1383+ }
1384+
1385+ /* Process each entry. */
1386+ for (uint32_t i = 0 ; i < num_entries ; i ++ )
1387+ {
1388+ bfd_byte * ptr = contents + i * entry_size ;
1389+ uint32_t sym_index = bfd_get_32 (abfd , ptr );
1390+ uint32_t lpad_value = bfd_get_32 (abfd , ptr + 4 );
1391+ const char * sym_name = NULL ;
1392+
1393+ /* Get symbol name. */
1394+ if (sym_index < symtab_hdr -> sh_info && isymbuf != NULL )
1395+ {
1396+ /* Local symbol. */
1397+ Elf_Internal_Sym * isym = isymbuf + sym_index ;
1398+ if (isym -> st_name < strtab_size && strtab != NULL )
1399+ sym_name = strtab + isym -> st_name ;
1400+ }
1401+ else
1402+ {
1403+ /* Global symbol - look up in hash table. */
1404+ unsigned int sym_hash_idx = sym_index - symtab_hdr -> sh_info ;
1405+ struct elf_link_hash_entry * * sym_hashes = elf_sym_hashes (abfd );
1406+ unsigned int symcount = ((symtab_hdr -> sh_size / sizeof (ElfNN_External_Sym ))
1407+ - symtab_hdr -> sh_info );
1408+ if (sym_hashes != NULL && sym_hash_idx < symcount )
1409+ {
1410+ struct elf_link_hash_entry * h = sym_hashes [sym_hash_idx ];
1411+ if (h != NULL )
1412+ sym_name = h -> root .root .string ;
1413+ }
1414+ }
1415+
1416+ if (sym_name == NULL || sym_name [0 ] == '\0' )
1417+ continue ;
1418+
1419+ /* Check if entry already exists. */
1420+ riscv_lpadinfo_entry search = { .name = sym_name , .lpad_value = 0 };
1421+ riscv_lpadinfo_entry * existing = htab_find (htab -> lpadinfo_htab , & search );
1422+
1423+ if (existing != NULL )
1424+ {
1425+ /* Entry exists, check for conflict. */
1426+ if (existing -> lpad_value != lpad_value )
1427+ {
1428+ _bfd_error_handler
1429+ (_ ("%pB: conflicting lpadinfo values for `%s': "
1430+ "0x%x vs 0x%x" ),
1431+ abfd , sym_name , existing -> lpad_value , lpad_value );
1432+ }
1433+ continue ;
1434+ }
1435+
1436+ /* Insert new entry. */
1437+ riscv_lpadinfo_entry * * slot = (riscv_lpadinfo_entry * * )
1438+ htab_find_slot (htab -> lpadinfo_htab , & search , INSERT );
1439+
1440+ if (* slot == NULL )
1441+ {
1442+ * slot = (riscv_lpadinfo_entry * ) bfd_malloc (sizeof (riscv_lpadinfo_entry ));
1443+ if (* slot == NULL )
1444+ {
1445+ ret = false;
1446+ goto cleanup ;
1447+ }
1448+ (* slot )-> name = bfd_strdup (sym_name );
1449+ if ((* slot )-> name == NULL )
1450+ {
1451+ free (* slot );
1452+ * slot = NULL ;
1453+ ret = false;
1454+ goto cleanup ;
1455+ }
1456+ (* slot )-> lpad_value = lpad_value ;
1457+ }
1458+ }
1459+
1460+ cleanup :
1461+ free (contents );
1462+ if (isymbuf != NULL && isymbuf != (Elf_Internal_Sym * ) symtab_hdr -> contents )
1463+ free (isymbuf );
1464+
1465+ return ret ;
1466+ }
1467+
12381468/* Update table jump hash entry. */
12391469
12401470static bool
@@ -1354,6 +1584,9 @@ riscv_elf_link_hash_table_free (bfd *obfd)
13541584 free (ret -> jvt_htab );
13551585 }
13561586
1587+ if (ret -> lpadinfo_htab )
1588+ htab_delete (ret -> lpadinfo_htab );
1589+
13571590 _bfd_elf_link_hash_table_free (obfd );
13581591}
13591592
@@ -4445,7 +4678,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
44454678
44464679 /* Fill in the PLT entry itself. */
44474680 if (! htab -> make_plt_entry (output_bfd , gotplt , got_offset ,
4448- plt , h -> plt .offset ))
4681+ plt , h -> plt .offset , h , info ))
44494682 return false;
44504683
44514684
@@ -5397,7 +5630,8 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
53975630 {
53985631 elf_flags_init (obfd ) = true;
53995632 elf_elfheader (obfd )-> e_flags = new_flags ;
5400- return true;
5633+ /* Still need to read lpadinfo section. */
5634+ return riscv_read_lpadinfo_section (ibfd , info );
54015635 }
54025636
54035637 /* Disallow linking different float ABIs. */
@@ -5424,6 +5658,10 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
54245658 /* Allow linking TSO and non-TSO, and keep the TSO flag. */
54255659 elf_elfheader (obfd )-> e_flags |= new_flags & EF_RISCV_TSO ;
54265660
5661+ /* Read lpadinfo section for PLT generation. */
5662+ if (!riscv_read_lpadinfo_section (ibfd , info ))
5663+ goto fail ;
5664+
54275665 return true;
54285666
54295667 fail :
0 commit comments