@@ -1260,8 +1260,7 @@ void SharedFile<E>::parse(Context<E> &ctx) {
12601260
12611261 this ->symbol_strtab = this ->get_string (ctx, symtab_sec->sh_link );
12621262 soname = get_soname (ctx);
1263- version_strings = read_verdef (ctx);
1264- append (version_strings, read_verneed (ctx));
1263+ version_strings = read_version_strings (ctx);
12651264
12661265 // Read a symbol table.
12671266 std::span<ElfSym<E>> esyms = this ->template get_data <ElfSym<E>>(ctx, *symtab_sec);
@@ -1271,20 +1270,21 @@ void SharedFile<E>::parse(Context<E> &ctx) {
12711270 vers = this ->template get_data <U16<E>>(ctx, *sec);
12721271
12731272 for (i64 i = symtab_sec->sh_info ; i < esyms.size (); i++) {
1274- u16 ver;
1275- if (vers.empty ())
1276- ver = VER_NDX_GLOBAL;
1277- else
1278- ver = vers[i] & ~VERSYM_HIDDEN;
1279-
1280- if (ver == VER_NDX_LOCAL)
1273+ u16 ver = vers.empty () ? VER_NDX_GLOBAL : (vers[i] & ~VERSYM_HIDDEN);
1274+
1275+ // A defined symbol with VER_NDX_LOCAL is bound locally and isn't
1276+ // really exposed for dynamic linking; skip it. We never skip
1277+ // undefined references — the dynamic loader doesn't distinguish
1278+ // local vs global on the undef side, and dropping them would hide
1279+ // the DSO's reference from us.
1280+ if (ver == VER_NDX_LOCAL && !esyms[i].is_undef ())
12811281 continue ;
12821282
12831283 this ->elf_syms2 .push_back (esyms[i]);
1284- // Defined symbols index into verdef; undefined symbols index into
1285- // verneed. We record VER_NDX_GLOBAL for undefined symbols here
1286- // because resolve_symbols only consults versyms[] for defined
1287- // symbols (see SharedFile::resolve_symbols) .
1284+
1285+ // resolve_symbols only consults versyms[] for defined symbols
1286+ // (see SharedFile:: resolve_symbols), so VER_NDX_GLOBAL is fine
1287+ // for undefined entries .
12881288 this ->versyms .push_back (esyms[i].is_undef () ? (u16 )VER_NDX_GLOBAL : ver);
12891289
12901290 std::string_view name = this ->symbol_strtab .data () + esyms[i].st_name ;
@@ -1384,67 +1384,61 @@ std::string_view SharedFile<E>::get_dt_audit(Context<E> &ctx) {
13841384// If an undefiend symbol `foo` is resolved to a symbol defined by the
13851385// shared object, it's marked so that it'll be resolved to (`foo`, the
13861386// default version of the library) at load-time.
1387+ //
1388+ // Reads .gnu.version_d and .gnu.version_r and returns a vector of
1389+ // version names indexed by versym value. The versym index space is
1390+ // shared between the two sections (vd_ndx for defined symbols and
1391+ // vna_other for undefined ones), so a single vector covers both.
13871392template <typename E>
1388- std::vector<std::string_view> SharedFile<E>::read_verdef(Context<E> &ctx) {
1389- ElfShdr<E> *verdef_sec = this ->find_section (SHT_GNU_VERDEF);
1390- if (!verdef_sec)
1391- return {};
1392-
1393- std::string_view verdef = this ->get_string (ctx, *verdef_sec);
1394- std::string_view strtab = this ->get_string (ctx, verdef_sec->sh_link );
1395-
1393+ std::vector<std::string_view>
1394+ SharedFile<E>::read_version_strings(Context<E> &ctx) {
13961395 std::vector<std::string_view> vec;
1397- u8 *ptr = (u8 *)verdef.data ();
13981396
1399- for (;; ) {
1400- ElfVerdef<E> *ver = (ElfVerdef<E> *)ptr ;
1401- if (ver-> vd_ndx == VER_NDX_UNSPECIFIED)
1402- Fatal (ctx) << * this << " : symbol version too large " ;
1397+ if (ElfShdr<E> *sec = this -> find_section (SHT_GNU_VERDEF) ) {
1398+ std::string_view verdef = this -> get_string (ctx, *sec) ;
1399+ std::string_view strtab = this -> get_string (ctx, sec-> sh_link );
1400+ u8 *ptr = ( u8 *)verdef. data () ;
14031401
1404- if (vec.size () <= ver->vd_ndx )
1405- vec.resize (ver->vd_ndx + 1 );
1402+ for (;;) {
1403+ ElfVerdef<E> *ver = (ElfVerdef<E> *)ptr;
1404+ if (ver->vd_ndx == VER_NDX_UNSPECIFIED)
1405+ Fatal (ctx) << *this << " : symbol version too large" ;
14061406
1407- ElfVerdaux<E> *aux = (ElfVerdaux<E> *)(ptr + ver->vd_aux );
1408- vec[ver->vd_ndx ] = strtab.data () + aux->vda_name ;
1409- if (!ver->vd_next )
1410- break ;
1411- ptr += ver->vd_next ;
1412- }
1413- return vec;
1414- }
1407+ if (vec.size () <= ver->vd_ndx )
1408+ vec.resize (ver->vd_ndx + 1 );
14151409
1416- // Reads .gnu.version_r and returns a vector of version names indexed
1417- // by vna_other. .gnu.version_r records the versions a shared object
1418- // needs from the libraries it depends on; the versym of an undefined
1419- // dynamic symbol indexes into these entries.
1420- template <typename E>
1421- std::vector<std::string_view> SharedFile<E>::read_verneed(Context<E> &ctx) {
1422- ElfShdr<E> *verneed_sec = this ->find_section (SHT_GNU_VERNEED);
1423- if (!verneed_sec)
1424- return {};
1410+ ElfVerdaux<E> *aux = (ElfVerdaux<E> *)(ptr + ver->vd_aux );
1411+ vec[ver->vd_ndx ] = strtab.data () + aux->vda_name ;
1412+ if (!ver->vd_next )
1413+ break ;
1414+ ptr += ver->vd_next ;
1415+ }
1416+ }
14251417
1426- std::vector<std::string_view> vec;
1427- std::string_view verneed = this ->get_string (ctx, *verneed_sec);
1428- std::string_view strtab = this ->get_string (ctx, verneed_sec->sh_link );
1429-
1430- u8 *ptr = (u8 *)verneed.data ();
1431- for (;;) {
1432- ElfVerneed<E> *vn = (ElfVerneed<E> *)ptr;
1433- u8 *aux_ptr = ptr + vn->vn_aux ;
1434- for (i64 i = 0 ; i < vn->vn_cnt ; i++) {
1435- ElfVernaux<E> *aux = (ElfVernaux<E> *)aux_ptr;
1436- u16 idx = aux->vna_other & ~VERSYM_HIDDEN;
1437- if (vec.size () <= idx)
1438- vec.resize (idx + 1 );
1439- vec[idx] = strtab.data () + aux->vna_name ;
1440- if (!aux->vna_next )
1418+ if (ElfShdr<E> *sec = this ->find_section (SHT_GNU_VERNEED)) {
1419+ std::string_view verneed = this ->get_string (ctx, *sec);
1420+ std::string_view strtab = this ->get_string (ctx, sec->sh_link );
1421+ u8 *ptr = (u8 *)verneed.data ();
1422+
1423+ for (;;) {
1424+ ElfVerneed<E> *vn = (ElfVerneed<E> *)ptr;
1425+ u8 *aux_ptr = ptr + vn->vn_aux ;
1426+ for (i64 i = 0 ; i < vn->vn_cnt ; i++) {
1427+ ElfVernaux<E> *aux = (ElfVernaux<E> *)aux_ptr;
1428+ u16 idx = aux->vna_other & ~VERSYM_HIDDEN;
1429+ if (vec.size () <= idx)
1430+ vec.resize (idx + 1 );
1431+ vec[idx] = strtab.data () + aux->vna_name ;
1432+ if (!aux->vna_next )
1433+ break ;
1434+ aux_ptr += aux->vna_next ;
1435+ }
1436+ if (!vn->vn_next )
14411437 break ;
1442- aux_ptr += aux-> vna_next ;
1438+ ptr += vn-> vn_next ;
14431439 }
1444- if (!vn->vn_next )
1445- break ;
1446- ptr += vn->vn_next ;
14471440 }
1441+
14481442 return vec;
14491443}
14501444
0 commit comments