mirror of
https://github.com/serge1/ELFIO.git
synced 2024-12-26 18:15:40 +00:00
Added support for ".gnu.version_d"
This commit is contained in:
parent
41f4012d49
commit
647aba7a29
@ -1349,6 +1349,23 @@ struct Elf64_Dyn
|
|||||||
} d_un;
|
} d_un;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Elfxx_Verdef
|
||||||
|
{
|
||||||
|
Elf_Half vd_version;
|
||||||
|
Elf_Half vd_flags;
|
||||||
|
Elf_Half vd_ndx;
|
||||||
|
Elf_Half vd_cnt;
|
||||||
|
Elf_Word vd_hash;
|
||||||
|
Elf_Word vd_aux;
|
||||||
|
Elf_Word vd_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elfxx_Verdaux
|
||||||
|
{
|
||||||
|
Elf_Word vda_name;
|
||||||
|
Elf_Word vda_next;
|
||||||
|
};
|
||||||
|
|
||||||
struct Elfxx_Verneed
|
struct Elfxx_Verneed
|
||||||
{
|
{
|
||||||
Elf_Half vn_version;
|
Elf_Half vn_version;
|
||||||
|
@ -174,6 +174,88 @@ using versym_r_section_accessor = versym_r_section_accessor_template<section>;
|
|||||||
using const_versym_r_section_accessor =
|
using const_versym_r_section_accessor =
|
||||||
versym_r_section_accessor_template<const section>;
|
versym_r_section_accessor_template<const section>;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template <class S> class versym_d_section_accessor_template
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
versym_d_section_accessor_template( const elfio& elf_file,
|
||||||
|
S* versym_d_section )
|
||||||
|
: elf_file( elf_file ), versym_d_section( versym_d_section ),
|
||||||
|
entries_num( 0 )
|
||||||
|
{
|
||||||
|
// Find .dynamic section
|
||||||
|
const section* dynamic_section = elf_file.sections[".dynamic"];
|
||||||
|
|
||||||
|
if ( dynamic_section == nullptr ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_dynamic_section_accessor dynamic_section_acc( elf_file,
|
||||||
|
dynamic_section );
|
||||||
|
Elf_Xword dyn_sec_num = dynamic_section_acc.get_entries_num();
|
||||||
|
for ( Elf_Xword i = 0; i < dyn_sec_num; ++i ) {
|
||||||
|
Elf_Xword tag;
|
||||||
|
Elf_Xword value;
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
if ( dynamic_section_acc.get_entry( i, tag, value, str ) &&
|
||||||
|
tag == DT_VERDEFNUM ) {
|
||||||
|
entries_num = (Elf_Word)value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word get_entries_num() const { return entries_num; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool get_entry( Elf_Word no,
|
||||||
|
Elf_Half& flags,
|
||||||
|
Elf_Half& version_index,
|
||||||
|
Elf_Word& hash,
|
||||||
|
std::string& dep_name ) const
|
||||||
|
{
|
||||||
|
if ( versym_d_section == nullptr || ( no >= get_entries_num() ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_string_section_accessor string_section_acc(
|
||||||
|
elf_file.sections[versym_d_section->get_link()] );
|
||||||
|
|
||||||
|
Elfxx_Verdef* verdef = (Elfxx_Verdef*)versym_d_section->get_data();
|
||||||
|
Elfxx_Verdaux* verdaux =
|
||||||
|
(Elfxx_Verdaux*)( (char*)verdef + verdef->vd_aux );
|
||||||
|
for ( Elf_Word i = 0; i < no; ++i ) {
|
||||||
|
verdef = (Elfxx_Verdef*)( (char*)verdef + verdef->vd_next );
|
||||||
|
verdaux = (Elfxx_Verdaux*)( (char*)verdef + verdef->vd_aux );
|
||||||
|
}
|
||||||
|
|
||||||
|
// verdef->vd_version should always be 1
|
||||||
|
// see https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA.junk/symversion.html#VERDEFENTRIES
|
||||||
|
// verdef->vd_cnt should always be 1.
|
||||||
|
// see https://maskray.me/blog/2020-11-26-all-about-symbol-versioning
|
||||||
|
|
||||||
|
flags = verdef->vd_flags;
|
||||||
|
version_index = verdef->vd_ndx;
|
||||||
|
hash = verdef->vd_hash;
|
||||||
|
dep_name = string_section_acc.get_string( verdaux->vda_name );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
const elfio& elf_file;
|
||||||
|
S* versym_d_section = nullptr;
|
||||||
|
Elf_Word entries_num = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
using versym_d_section_accessor = versym_d_section_accessor_template<section>;
|
||||||
|
using const_versym_d_section_accessor =
|
||||||
|
versym_d_section_accessor_template<const section>;
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
|
||||||
#endif // ELFIO_VERSYM_HPP
|
#endif // ELFIO_VERSYM_HPP
|
||||||
|
@ -416,6 +416,78 @@ TEST( ELFIOTest, gnu_version_64_le )
|
|||||||
EXPECT_EQ( dep_name, "GLIBC_2.2.5" );
|
EXPECT_EQ( dep_name, "GLIBC_2.2.5" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
TEST( ELFIOTest, gnu_version_d_64_le )
|
||||||
|
{
|
||||||
|
elfio reader;
|
||||||
|
// Load ELF data
|
||||||
|
|
||||||
|
ASSERT_EQ( reader.load( "elf_examples/libversion_d.so" ), true );
|
||||||
|
|
||||||
|
section* dynsym = reader.sections[".dynsym"];
|
||||||
|
const_symbol_section_accessor dynsym_acc( reader, dynsym );
|
||||||
|
|
||||||
|
section* gnu_version = reader.sections[".gnu.version"];
|
||||||
|
const_versym_section_accessor gnu_version_arr( gnu_version );
|
||||||
|
|
||||||
|
const section* gnu_version_d = reader.sections[".gnu.version_d"];
|
||||||
|
const_versym_d_section_accessor gnu_version_d_arr( reader, gnu_version_d );
|
||||||
|
|
||||||
|
section* dynstr = reader.sections[".dynstr"];
|
||||||
|
|
||||||
|
EXPECT_EQ( gnu_version_d->get_link(), dynstr->get_index() );
|
||||||
|
|
||||||
|
EXPECT_EQ( dynsym_acc.get_symbols_num(),
|
||||||
|
gnu_version_arr.get_entries_num() );
|
||||||
|
|
||||||
|
EXPECT_EQ( dynsym_acc.get_symbols_num(), 10 );
|
||||||
|
|
||||||
|
EXPECT_EQ( gnu_version_d_arr.get_entries_num(), 3 );
|
||||||
|
|
||||||
|
auto v_check = [&]( const std::string& symbol,
|
||||||
|
const std::string& vername ) -> void {
|
||||||
|
std::string name;
|
||||||
|
Elf64_Addr value;
|
||||||
|
Elf_Xword size;
|
||||||
|
unsigned char bind;
|
||||||
|
unsigned char type;
|
||||||
|
Elf_Half section_index;
|
||||||
|
unsigned char other;
|
||||||
|
Elf64_Half verindex;
|
||||||
|
|
||||||
|
for ( Elf64_Word i = 0; i < dynsym_acc.get_symbols_num(); i++ ) {
|
||||||
|
ASSERT_EQ( dynsym_acc.get_symbol( i, name, value, size, bind, type,
|
||||||
|
section_index, other ),
|
||||||
|
true );
|
||||||
|
|
||||||
|
Elf64_Half vi;
|
||||||
|
ASSERT_EQ( gnu_version_arr.get_entry( i, vi ), true );
|
||||||
|
if ( name == symbol ) {
|
||||||
|
verindex = vi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT_NE( verindex, 0 );
|
||||||
|
|
||||||
|
for ( Elf64_Word i = 0; i < gnu_version_d_arr.get_entries_num(); i++ ) {
|
||||||
|
Elf_Half flags;
|
||||||
|
Elf_Half version_index;
|
||||||
|
Elf_Word hash;
|
||||||
|
std::string dep_name;
|
||||||
|
ASSERT_EQ( gnu_version_d_arr.get_entry( i, flags, version_index,
|
||||||
|
hash, dep_name ),
|
||||||
|
true );
|
||||||
|
if ( version_index == verindex ) {
|
||||||
|
EXPECT_EQ( flags, 0 );
|
||||||
|
EXPECT_EQ( dep_name, vername );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FAIL() << "version entry is not found";
|
||||||
|
};
|
||||||
|
v_check( "_Z20print_hello_world_v1v", "HELLO_1.0" );
|
||||||
|
v_check( "_Z20print_hello_world_v2v", "HELLO_2.0" );
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// TEST( ELFIOTest, gnu_version_64_le_modify )
|
// TEST( ELFIOTest, gnu_version_64_le_modify )
|
||||||
// {
|
// {
|
||||||
|
5
tests/elf_examples/version_d.cpp
Normal file
5
tests/elf_examples/version_d.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void print_hello_world_v1() { printf( "hello v1" ); }
|
||||||
|
|
||||||
|
void print_hello_world_v2() { printf( "hello v2" ); }
|
9
tests/elf_examples/version_d.map
Normal file
9
tests/elf_examples/version_d.map
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
HELLO_1.0 {
|
||||||
|
global:
|
||||||
|
_Z20print_hello_world_v1v;
|
||||||
|
};
|
||||||
|
|
||||||
|
HELLO_2.0 {
|
||||||
|
global:
|
||||||
|
_Z20print_hello_world_v2v;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user