Update to latest ELFIO and undo any changes directly to ELFIO

This commit is contained in:
Maschell 2023-01-04 02:05:57 +01:00
parent ae06a5db31
commit c9ccf0f657
23 changed files with 4970 additions and 2796 deletions

View File

@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: clang-format - name: clang-format
run: | run: |
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio
build-binary: build-binary:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: clang-format needs: clang-format

View File

@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: clang-format - name: clang-format
run: | run: |
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio
check-build-with-logging: check-build-with-logging:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: clang-format needs: clang-format

View File

@ -62,7 +62,7 @@ docker run -it --rm -v ${PWD}:/project wiiupluginloaderbackend-builder make clea
## Format the code via docker ## Format the code via docker
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source -i` `docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio -i`
# Credits # Credits
- Maschell - Maschell

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/*
Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_ARRAY_HPP
#define ELFIO_ARRAY_HPP
#include <algorithm>
namespace ELFIO {
//------------------------------------------------------------------------------
template <class S, typename T> class array_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit array_section_accessor_template( const elfio& elf_file,
S* section )
: elf_file( elf_file ), array_section( section )
{
}
//------------------------------------------------------------------------------
Elf_Xword get_entries_num() const
{
Elf_Xword entry_size = sizeof( T );
return array_section->get_size() / entry_size;
}
//------------------------------------------------------------------------------
bool get_entry( Elf_Xword index, Elf64_Addr& address ) const
{
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
const endianess_convertor& convertor = elf_file.get_convertor();
const T temp = *reinterpret_cast<const T*>( array_section->get_data() +
index * sizeof( T ) );
address = convertor( temp );
return true;
}
//------------------------------------------------------------------------------
void add_entry( Elf64_Addr address )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T temp = convertor( (T)address );
array_section->append_data( reinterpret_cast<char*>( &temp ),
sizeof( temp ) );
}
private:
//------------------------------------------------------------------------------
const elfio& elf_file;
S* array_section;
};
template <typename T = Elf32_Word>
using array_section_accessor = array_section_accessor_template<section, T>;
template <typename T = Elf32_Word>
using const_array_section_accessor =
array_section_accessor_template<const section, T>;
} // namespace ELFIO
#endif // ELFIO_ARRAY_HPP

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -24,60 +23,76 @@ THE SOFTWARE.
#ifndef ELFIO_DYNAMIC_HPP #ifndef ELFIO_DYNAMIC_HPP
#define ELFIO_DYNAMIC_HPP #define ELFIO_DYNAMIC_HPP
#include <algorithm>
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class S > template <class S> class dynamic_section_accessor_template
class dynamic_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
dynamic_section_accessor_template( const elfio& elf_file_, S* section_ ) : explicit dynamic_section_accessor_template( const elfio& elf_file,
elf_file( elf_file_ ), S* section )
dynamic_section( section_ ) : elf_file( elf_file ), dynamic_section( section ), entries_num( 0 )
{ {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Xword Elf_Xword get_entries_num() const
get_entries_num() const
{ {
Elf_Xword nRet = 0; size_t needed_entry_size = -1;
if ( elf_file.get_class() == ELFCLASS32 ) {
if ( 0 != dynamic_section->get_entry_size() ) { needed_entry_size = sizeof( Elf32_Dyn );
nRet = dynamic_section->get_size() / dynamic_section->get_entry_size(); }
else {
needed_entry_size = sizeof( Elf64_Dyn );
} }
return nRet; if ( ( 0 == entries_num ) &&
( 0 != dynamic_section->get_entry_size() &&
dynamic_section->get_entry_size() >= needed_entry_size ) ) {
entries_num =
dynamic_section->get_size() / dynamic_section->get_entry_size();
Elf_Xword i;
Elf_Xword tag = DT_NULL;
Elf_Xword value = 0;
std::string str;
for ( i = 0; i < entries_num; i++ ) {
get_entry( i, tag, value, str );
if ( tag == DT_NULL )
break;
}
entries_num = std::min<Elf_Xword>( entries_num, i + 1 );
}
return entries_num;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool get_entry( Elf_Xword index,
get_entry( Elf_Xword index, Elf_Xword& tag,
Elf_Xword& tag, Elf_Xword& value,
Elf_Xword& value, std::string& str ) const
std::string& str ) const
{ {
if ( index >= get_entries_num() ) { // Is index valid if ( index >= get_entries_num() ) { // Is index valid
return false; return false;
} }
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
generic_get_entry_dyn< Elf32_Dyn >( index, tag, value ); generic_get_entry_dyn<Elf32_Dyn>( index, tag, value );
} }
else { else {
generic_get_entry_dyn< Elf64_Dyn >( index, tag, value ); generic_get_entry_dyn<Elf64_Dyn>( index, tag, value );
} }
// If the tag may have a string table reference, prepare the string // If the tag has a string table reference - prepare the string
if ( tag == DT_NEEDED || if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH ||
tag == DT_SONAME ||
tag == DT_RPATH ||
tag == DT_RUNPATH ) { tag == DT_RUNPATH ) {
string_section_accessor strsec = string_section_accessor strsec(
elf_file.sections[ get_string_table_index() ]; elf_file.sections[get_string_table_index()] );
const char* result = strsec.get_string( value ); const char* result = strsec.get_string( (Elf_Word)value );
if ( 0 == result ) { if ( nullptr == result ) {
str.clear(); str.clear();
return false; return false;
} }
@ -90,59 +105,55 @@ class dynamic_section_accessor_template
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void add_entry( Elf_Xword tag, Elf_Xword value )
add_entry( Elf_Xword tag,
Elf_Xword value )
{ {
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry< Elf32_Dyn >( tag, value ); generic_add_entry_dyn<Elf32_Dyn>( tag, value );
} }
else { else {
generic_add_entry< Elf64_Dyn >( tag, value ); generic_add_entry_dyn<Elf64_Dyn>( tag, value );
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void add_entry( Elf_Xword tag, const std::string& str )
add_entry( Elf_Xword tag,
const std::string& str )
{ {
string_section_accessor strsec = string_section_accessor strsec(
elf_file.sections[ get_string_table_index() ]; elf_file.sections[get_string_table_index()] );
Elf_Xword value = strsec.add_string( str ); Elf_Xword value = strsec.add_string( str );
add_entry( tag, value ); add_entry( tag, value );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half Elf_Half get_string_table_index() const
get_string_table_index() const
{ {
return (Elf_Half)dynamic_section->get_link(); return (Elf_Half)dynamic_section->get_link();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
void void generic_get_entry_dyn( Elf_Xword index,
generic_get_entry_dyn( Elf_Xword index, Elf_Xword& tag,
Elf_Xword& tag, Elf_Xword& value ) const
Elf_Xword& value ) const
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
// Check unusual case when dynamic section has no data // Check unusual case when dynamic section has no data
if( dynamic_section->get_data() == 0 || if ( dynamic_section->get_data() == nullptr ||
( index + 1 ) * dynamic_section->get_entry_size() > dynamic_section->get_size() ) { ( index + 1 ) * dynamic_section->get_entry_size() >
dynamic_section->get_size() ||
dynamic_section->get_entry_size() < sizeof( T ) ) {
tag = DT_NULL; tag = DT_NULL;
value = 0; value = 0;
return; return;
} }
const T* pEntry = reinterpret_cast<const T*>( const T* pEntry = reinterpret_cast<const T*>(
dynamic_section->get_data() + dynamic_section->get_data() +
index * dynamic_section->get_entry_size() ); index * dynamic_section->get_entry_size() );
tag = convertor( pEntry->d_tag ); tag = convertor( pEntry->d_tag );
switch ( tag ) { switch ( tag ) {
case DT_NULL: case DT_NULL:
@ -188,10 +199,9 @@ class dynamic_section_accessor_template
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
void void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value )
generic_add_entry( Elf_Xword tag, Elf_Xword value )
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
@ -202,7 +212,8 @@ class dynamic_section_accessor_template
case DT_SYMBOLIC: case DT_SYMBOLIC:
case DT_TEXTREL: case DT_TEXTREL:
case DT_BIND_NOW: case DT_BIND_NOW:
value = 0; entry.d_un.d_val = convertor( decltype( entry.d_un.d_val )( 0 ) );
break;
case DT_NEEDED: case DT_NEEDED:
case DT_PLTRELSZ: case DT_PLTRELSZ:
case DT_RELASZ: case DT_RELASZ:
@ -219,7 +230,8 @@ class dynamic_section_accessor_template
case DT_RUNPATH: case DT_RUNPATH:
case DT_FLAGS: case DT_FLAGS:
case DT_PREINIT_ARRAYSZ: case DT_PREINIT_ARRAYSZ:
entry.d_un.d_val = convertor( value ); entry.d_un.d_val =
convertor( decltype( entry.d_un.d_val )( value ) );
break; break;
case DT_PLTGOT: case DT_PLTGOT:
case DT_HASH: case DT_HASH:
@ -235,23 +247,27 @@ class dynamic_section_accessor_template
case DT_FINI_ARRAY: case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY: case DT_PREINIT_ARRAY:
default: default:
entry.d_un.d_ptr = convertor( value ); entry.d_un.d_ptr =
convertor( decltype( entry.d_un.d_val )( value ) );
break; break;
} }
entry.d_tag = convertor( tag ); entry.d_tag = convertor( decltype( entry.d_tag )( tag ) );
dynamic_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) ); dynamic_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file;
S* dynamic_section; S* dynamic_section;
mutable Elf_Xword entries_num;
}; };
using dynamic_section_accessor = dynamic_section_accessor_template<section>; using dynamic_section_accessor = dynamic_section_accessor_template<section>;
using const_dynamic_section_accessor = dynamic_section_accessor_template<const section>; using const_dynamic_section_accessor =
dynamic_section_accessor_template<const section>;
} // namespace ELFIO } // namespace ELFIO

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -31,55 +30,56 @@ namespace ELFIO {
class elf_header class elf_header
{ {
public: public:
virtual ~elf_header() {}; virtual ~elf_header() = default;
virtual bool load( std::istream& stream ) = 0; virtual bool load( std::istream& stream ) = 0;
virtual bool save( std::ostream& stream ) const = 0; virtual bool save( std::ostream& stream ) const = 0;
// ELF header functions // ELF header functions
ELFIO_GET_ACCESS_DECL( unsigned char, class ); ELFIO_GET_ACCESS_DECL( unsigned char, class );
ELFIO_GET_ACCESS_DECL( unsigned char, elf_version ); ELFIO_GET_ACCESS_DECL( unsigned char, elf_version );
ELFIO_GET_ACCESS_DECL( unsigned char, encoding ); ELFIO_GET_ACCESS_DECL( unsigned char, encoding );
ELFIO_GET_ACCESS_DECL( Elf_Half, header_size ); ELFIO_GET_ACCESS_DECL( Elf_Half, header_size );
ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size ); ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size );
ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size ); ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version );
ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi ); ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi );
ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version ); ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index );
}; };
template <class T> struct elf_header_impl_types;
template< class T > struct elf_header_impl_types; template <> struct elf_header_impl_types<Elf32_Ehdr>
template<> struct elf_header_impl_types<Elf32_Ehdr> { {
typedef Elf32_Phdr Phdr_type; using Phdr_type = Elf32_Phdr;
typedef Elf32_Shdr Shdr_type; using Shdr_type = Elf32_Shdr;
static const unsigned char file_class = ELFCLASS32; static const unsigned char file_class = ELFCLASS32;
}; };
template<> struct elf_header_impl_types<Elf64_Ehdr> { template <> struct elf_header_impl_types<Elf64_Ehdr>
typedef Elf64_Phdr Phdr_type; {
typedef Elf64_Shdr Shdr_type; using Phdr_type = Elf64_Phdr;
using Shdr_type = Elf64_Shdr;
static const unsigned char file_class = ELFCLASS64; static const unsigned char file_class = ELFCLASS64;
}; };
template< class T > class elf_header_impl : public elf_header template <class T> class elf_header_impl : public elf_header
{ {
public: public:
elf_header_impl( endianess_convertor* convertor_, //------------------------------------------------------------------------------
unsigned char encoding ) elf_header_impl( endianess_convertor* convertor,
unsigned char encoding,
const address_translator* translator )
: convertor( convertor ), translator( translator )
{ {
convertor = convertor_;
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
header.e_ident[EI_MAG0] = ELFMAG0; header.e_ident[EI_MAG0] = ELFMAG0;
header.e_ident[EI_MAG1] = ELFMAG1; header.e_ident[EI_MAG1] = ELFMAG1;
header.e_ident[EI_MAG2] = ELFMAG2; header.e_ident[EI_MAG2] = ELFMAG2;
@ -87,58 +87,65 @@ template< class T > class elf_header_impl : public elf_header
header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class; header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class;
header.e_ident[EI_DATA] = encoding; header.e_ident[EI_DATA] = encoding;
header.e_ident[EI_VERSION] = EV_CURRENT; header.e_ident[EI_VERSION] = EV_CURRENT;
header.e_version = (*convertor)( (Elf_Word)EV_CURRENT ); header.e_version = ( *convertor )( (Elf_Word)EV_CURRENT );
header.e_ehsize = ( sizeof( header ) ); header.e_ehsize = ( sizeof( header ) );
header.e_ehsize = (*convertor)( header.e_ehsize ); header.e_ehsize = ( *convertor )( header.e_ehsize );
header.e_shstrndx = (*convertor)( (Elf_Half)1 ); header.e_shstrndx = ( *convertor )( (Elf_Half)1 );
header.e_phentsize = sizeof( typename elf_header_impl_types<T>::Phdr_type ); header.e_phentsize =
header.e_shentsize = sizeof( typename elf_header_impl_types<T>::Shdr_type ); sizeof( typename elf_header_impl_types<T>::Phdr_type );
header.e_phentsize = (*convertor)( header.e_phentsize ); header.e_shentsize =
header.e_shentsize = (*convertor)( header.e_shentsize ); sizeof( typename elf_header_impl_types<T>::Shdr_type );
header.e_phentsize = ( *convertor )( header.e_phentsize );
header.e_shentsize = ( *convertor )( header.e_shentsize );
} }
bool //------------------------------------------------------------------------------
load( std::istream& stream ) bool load( std::istream& stream ) override
{ {
stream.seekg( 0 ); stream.seekg( ( *translator )[0] );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) ); stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
return (stream.gcount() == sizeof( header ) ); return ( stream.gcount() == sizeof( header ) );
} }
bool //------------------------------------------------------------------------------
save( std::ostream& stream ) const bool save( std::ostream& stream ) const override
{ {
stream.seekp( 0 ); stream.seekp( ( *translator )[0] );
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) ); stream.write( reinterpret_cast<const char*>( &header ),
sizeof( header ) );
return stream.good(); return stream.good();
} }
//------------------------------------------------------------------------------
// ELF header functions // ELF header functions
ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] ); ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] );
ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] ); ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] );
ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] ); ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] );
ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize ); ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize );
ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize ); ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize );
ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize ); ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize );
ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version); ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version );
ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] ); ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] );
ELFIO_GET_SET_ACCESS( unsigned char, abi_version, header.e_ident[EI_ABIVERSION] ); ELFIO_GET_SET_ACCESS( unsigned char,
ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type ); abi_version,
ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine ); header.e_ident[EI_ABIVERSION] );
ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags ); ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type );
ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx ); ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine );
ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry ); ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags );
ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum ); ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx );
ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff ); ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry );
ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum ); ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum );
ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff ); ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff );
ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum );
ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
private: private:
T header; T header = {};
endianess_convertor* convertor; endianess_convertor* convertor = nullptr;
const address_translator* translator = nullptr;
}; };
} // namespace ELFIO } // namespace ELFIO

View File

@ -0,0 +1,124 @@
/*
Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_MODINFO_HPP
#define ELFIO_MODINFO_HPP
#include <string>
#include <vector>
namespace ELFIO {
//------------------------------------------------------------------------------
template <class S> class modinfo_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit modinfo_section_accessor_template( S* section )
: modinfo_section( section )
{
process_section();
}
//------------------------------------------------------------------------------
Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); }
//------------------------------------------------------------------------------
bool
get_attribute( Elf_Word no, std::string& field, std::string& value ) const
{
if ( no < content.size() ) {
field = content[no].first;
value = content[no].second;
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool get_attribute( const std::string& field_name,
std::string& value ) const
{
for ( auto& i : content ) {
if ( field_name == i.first ) {
value = i.second;
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
Elf_Word add_attribute( const std::string& field, const std::string& value )
{
Elf_Word current_position = 0;
if ( modinfo_section ) {
// Strings are addeded to the end of the current section data
current_position = (Elf_Word)modinfo_section->get_size();
std::string attribute = field + "=" + value;
modinfo_section->append_data( attribute + '\0' );
content.emplace_back( field, value );
}
return current_position;
}
//------------------------------------------------------------------------------
private:
void process_section()
{
const char* pdata = modinfo_section->get_data();
if ( pdata ) {
ELFIO::Elf_Xword i = 0;
while ( i < modinfo_section->get_size() ) {
while ( i < modinfo_section->get_size() && !pdata[i] )
i++;
if ( i < modinfo_section->get_size() ) {
std::string info = pdata + i;
size_t loc = info.find( '=' );
content.emplace_back( info.substr( 0, loc ),
info.substr( loc + 1 ) );
i += info.length();
}
}
}
}
//------------------------------------------------------------------------------
private:
S* modinfo_section;
std::vector<std::pair<std::string, std::string>> content;
};
using modinfo_section_accessor = modinfo_section_accessor_template<section>;
using const_modinfo_section_accessor =
modinfo_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_MODINFO_HPP

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -39,73 +38,75 @@ namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class S > template <class S, Elf_Xword ( S::*F_get_size )() const>
class note_section_accessor_template class note_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
note_section_accessor_template( const elfio& elf_file_, S* section_ ) : explicit note_section_accessor_template( const elfio& elf_file, S* section )
elf_file( elf_file_ ), note_section( section_ ) : elf_file( elf_file ), notes( section )
{ {
process_section(); process_section();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word Elf_Word get_notes_num() const
get_notes_num() const
{ {
return (Elf_Word)note_start_positions.size(); return (Elf_Word)note_start_positions.size();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool get_note( Elf_Word index,
get_note( Elf_Word index, Elf_Word& type,
Elf_Word& type, std::string& name,
std::string& name, char*& desc,
void*& desc, Elf_Word& descSize ) const
Elf_Word& descSize ) const
{ {
if ( index >= note_section->get_size() ) { if ( index >= ( notes->*F_get_size )() ) {
return false; return false;
} }
const char* pData = note_section->get_data() + note_start_positions[index]; const char* pData = notes->get_data() + note_start_positions[index];
int align = sizeof( Elf_Word ); int align = sizeof( Elf_Word );
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
type = convertor( *(const Elf_Word*)( pData + 2*align ) ); type = convertor( *(const Elf_Word*)( pData + 2 * (size_t)align ) );
Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) ); Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) );
descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) ); descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) );
Elf_Xword max_name_size = note_section->get_size() - note_start_positions[index];
if ( namesz > max_name_size || Elf_Xword max_name_size =
namesz + descSize > max_name_size ) { ( notes->*F_get_size )() - note_start_positions[index];
if ( namesz < 1 || namesz > max_name_size ||
(Elf_Xword)namesz + descSize > max_name_size ) {
return false; return false;
} }
name.assign( pData + 3*align, namesz - 1); name.assign( pData + 3 * (size_t)align, namesz - 1 );
if ( 0 == descSize ) { if ( 0 == descSize ) {
desc = 0; desc = nullptr;
} }
else { else {
desc = const_cast<char*> ( pData + 3*align + desc = const_cast<char*>( pData + 3 * (size_t)align +
( ( namesz + align - 1 )/align )*align ); ( ( namesz + align - 1 ) / align ) *
(size_t)align );
} }
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void add_note( Elf_Word type, void add_note( Elf_Word type,
const std::string& name, const std::string& name,
const void* desc, const char* desc,
Elf_Word descSize ) Elf_Word descSize )
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
int align = sizeof( Elf_Word ); int align = sizeof( Elf_Word );
Elf_Word nameLen = (Elf_Word)name.size() + 1; Elf_Word nameLen = (Elf_Word)name.size() + 1;
Elf_Word nameLenConv = convertor( nameLen ); Elf_Word nameLenConv = convertor( nameLen );
std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align ); std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align );
Elf_Word descSizeConv = convertor( descSize ); Elf_Word descSizeConv = convertor( descSize );
buffer.append( reinterpret_cast<char*>( &descSizeConv ), align ); buffer.append( reinterpret_cast<char*>( &descSizeConv ), align );
type = convertor( type ); type = convertor( type );
buffer.append( reinterpret_cast<char*>( &type ), align ); buffer.append( reinterpret_cast<char*>( &type ), align );
@ -113,58 +114,70 @@ class note_section_accessor_template
buffer.append( 1, '\x00' ); buffer.append( 1, '\x00' );
const char pad[] = { '\0', '\0', '\0', '\0' }; const char pad[] = { '\0', '\0', '\0', '\0' };
if ( nameLen % align != 0 ) { if ( nameLen % align != 0 ) {
buffer.append( pad, align - nameLen % align ); buffer.append( pad, (size_t)align - nameLen % align );
} }
if ( desc != 0 && descSize != 0 ) { if ( desc != nullptr && descSize != 0 ) {
buffer.append( reinterpret_cast<const char*>( desc ), descSize ); buffer.append( desc, descSize );
if ( descSize % align != 0 ) { if ( descSize % align != 0 ) {
buffer.append( pad, align - descSize % align ); buffer.append( pad, (size_t)align - descSize % align );
} }
} }
note_start_positions.push_back( note_section->get_size() ); note_start_positions.emplace_back( ( notes->*F_get_size )() );
note_section->append_data( buffer ); notes->append_data( buffer );
} }
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void process_section() void process_section()
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
const char* data = note_section->get_data(); const char* data = notes->get_data();
Elf_Xword size = note_section->get_size(); Elf_Xword size = ( notes->*F_get_size )();
Elf_Xword current = 0; Elf_Xword current = 0;
note_start_positions.clear(); note_start_positions.clear();
// Is it empty? // Is it empty?
if ( 0 == data || 0 == size ) { if ( nullptr == data || 0 == size ) {
return; return;
} }
int align = sizeof( Elf_Word ); Elf_Word align = sizeof( Elf_Word );
while ( current + 3*align <= size ) { while ( current + (Elf_Xword)3 * align <= size ) {
note_start_positions.push_back( current ); Elf_Word namesz = convertor( *(const Elf_Word*)( data + current ) );
Elf_Word namesz = convertor(
*(const Elf_Word*)( data + current ) );
Elf_Word descsz = convertor( Elf_Word descsz = convertor(
*(const Elf_Word*)( data + current + sizeof( namesz ) ) ); *(const Elf_Word*)( data + current + sizeof( namesz ) ) );
Elf_Word advance =
(Elf_Xword)3 * sizeof( Elf_Word ) +
( ( namesz + align - 1 ) / align ) * (Elf_Xword)align +
( ( descsz + align - 1 ) / align ) * (Elf_Xword)align;
if ( namesz < size && descsz < size && current + advance <= size ) {
note_start_positions.emplace_back( current );
}
else {
break;
}
current += 3*sizeof( Elf_Word ) + current += advance;
( ( namesz + align - 1 ) / align ) * align +
( ( descsz + align - 1 ) / align ) * align;
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file;
S* note_section; S* notes;
std::vector<Elf_Xword> note_start_positions; std::vector<Elf_Xword> note_start_positions;
}; };
using note_section_accessor = note_section_accessor_template<section>; using note_section_accessor =
using const_note_section_accessor = note_section_accessor_template<const section>; note_section_accessor_template<section, &section::get_size>;
using const_note_section_accessor =
note_section_accessor_template<const section, &section::get_size>;
using note_segment_accessor =
note_section_accessor_template<segment, &segment::get_file_size>;
using const_note_segment_accessor =
note_section_accessor_template<const segment, &segment::get_file_size>;
} // namespace ELFIO } // namespace ELFIO

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -26,8 +25,8 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
template<typename T> struct get_sym_and_type; template <typename T> struct get_sym_and_type;
template<> struct get_sym_and_type< Elf32_Rel > template <> struct get_sym_and_type<Elf32_Rel>
{ {
static int get_r_sym( Elf_Xword info ) static int get_r_sym( Elf_Xword info )
{ {
@ -38,7 +37,7 @@ template<> struct get_sym_and_type< Elf32_Rel >
return ELF32_R_TYPE( (Elf_Word)info ); return ELF32_R_TYPE( (Elf_Word)info );
} }
}; };
template<> struct get_sym_and_type< Elf32_Rela > template <> struct get_sym_and_type<Elf32_Rela>
{ {
static int get_r_sym( Elf_Xword info ) static int get_r_sym( Elf_Xword info )
{ {
@ -49,161 +48,219 @@ template<> struct get_sym_and_type< Elf32_Rela >
return ELF32_R_TYPE( (Elf_Word)info ); return ELF32_R_TYPE( (Elf_Word)info );
} }
}; };
template<> struct get_sym_and_type< Elf64_Rel > template <> struct get_sym_and_type<Elf64_Rel>
{ {
static int get_r_sym( Elf_Xword info ) static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
{ static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
return ELF64_R_SYM( info );
}
static int get_r_type( Elf_Xword info )
{
return ELF64_R_TYPE( info );
}
}; };
template<> struct get_sym_and_type< Elf64_Rela > template <> struct get_sym_and_type<Elf64_Rela>
{ {
static int get_r_sym( Elf_Xword info ) static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
{ static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
return ELF64_R_SYM( info );
}
static int get_r_type( Elf_Xword info )
{
return ELF64_R_TYPE( info );
}
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class S > template <class S> class relocation_section_accessor_template
class relocation_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
relocation_section_accessor_template( const elfio& elf_file_, S* section_ ) : explicit relocation_section_accessor_template( const elfio& elf_file,
elf_file( elf_file_ ), S* section )
relocation_section( section_ ) : elf_file( elf_file ), relocation_section( section )
{ {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Xword Elf_Xword get_entries_num() const
get_entries_num() const
{ {
Elf_Xword nRet = 0; Elf_Xword nRet = 0;
if ( 0 != relocation_section->get_entry_size() ) { if ( 0 != relocation_section->get_entry_size() ) {
nRet = relocation_section->get_size() / relocation_section->get_entry_size(); nRet = relocation_section->get_size() /
relocation_section->get_entry_size();
} }
return nRet; return nRet;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool get_entry( Elf_Xword index,
get_entry( Elf_Xword index, Elf64_Addr& offset,
Elf64_Addr& offset, Elf_Word& symbol,
Elf_Word& symbol, unsigned& type,
Elf_Word& type, Elf_Sxword& addend ) const
Elf_Sxword& addend ) const
{ {
if ( index >= get_entries_num() ) { // Is index valid if ( index >= get_entries_num() ) { // Is index valid
return false; return false;
} }
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
if ( SHT_REL == relocation_section->get_type() ) { if ( SHT_REL == relocation_section->get_type() ) {
generic_get_entry_rel< Elf32_Rel >( index, offset, symbol, generic_get_entry_rel<Elf32_Rel>( index, offset, symbol, type,
type, addend ); addend );
} }
else if ( SHT_RELA == relocation_section->get_type() ) { else if ( SHT_RELA == relocation_section->get_type() ) {
generic_get_entry_rela< Elf32_Rela >( index, offset, symbol, generic_get_entry_rela<Elf32_Rela>( index, offset, symbol, type,
type, addend ); addend );
} }
} }
else { else {
if ( SHT_REL == relocation_section->get_type() ) { if ( SHT_REL == relocation_section->get_type() ) {
generic_get_entry_rel< Elf64_Rel >( index, offset, symbol, generic_get_entry_rel<Elf64_Rel>( index, offset, symbol, type,
type, addend ); addend );
} }
else if ( SHT_RELA == relocation_section->get_type() ) { else if ( SHT_RELA == relocation_section->get_type() ) {
generic_get_entry_rela< Elf64_Rela >( index, offset, symbol, generic_get_entry_rela<Elf64_Rela>( index, offset, symbol, type,
type, addend ); addend );
} }
} }
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool get_entry( Elf_Xword index,
get_entry( Elf_Xword index, Elf64_Addr& offset,
Elf64_Addr& offset, Elf64_Addr& symbolValue,
Elf64_Addr& symbolValue, std::string& symbolName,
std::string& symbolName, unsigned& type,
Elf_Word& type, Elf_Sxword& addend,
Elf_Sxword& addend, Elf_Sxword& calcValue ) const
Elf_Half& section) const
{ {
// Do regular job // Do regular job
Elf_Word symbol; Elf_Word symbol = 0;
bool ret = get_entry( index, offset, symbol, type, addend ); bool ret = get_entry( index, offset, symbol, type, addend );
// Find the symbol // Find the symbol
Elf_Xword size; Elf_Xword size;
unsigned char bind; unsigned char bind;
unsigned char symbolType; unsigned char symbolType;
Elf_Half section;
unsigned char other; unsigned char other;
symbol_section_accessor symbols( elf_file, elf_file.sections[get_symbol_table_index()] ); symbol_section_accessor symbols(
ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, elf_file, elf_file.sections[get_symbol_table_index()] );
size, bind, symbolType, section, other ); ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size,
bind, symbolType, section, other );
if ( ret ) { // Was it successful?
switch ( type ) {
case R_386_NONE: // none
calcValue = 0;
break;
case R_386_32: // S + A
calcValue = symbolValue + addend;
break;
case R_386_PC32: // S + A - P
calcValue = symbolValue + addend - offset;
break;
case R_386_GOT32: // G + A - P
calcValue = 0;
break;
case R_386_PLT32: // L + A - P
calcValue = 0;
break;
case R_386_COPY: // none
calcValue = 0;
break;
case R_386_GLOB_DAT: // S
case R_386_JMP_SLOT: // S
calcValue = symbolValue;
break;
case R_386_RELATIVE: // B + A
calcValue = addend;
break;
case R_386_GOTOFF: // S + A - GOT
calcValue = 0;
break;
case R_386_GOTPC: // GOT + A - P
calcValue = 0;
break;
default: // Not recognized symbol!
calcValue = 0;
break;
}
}
return ret; return ret;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void bool set_entry( Elf_Xword index,
add_entry( Elf64_Addr offset, Elf_Xword info ) Elf64_Addr offset,
Elf_Word symbol,
unsigned type,
Elf_Sxword addend )
{ {
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry< Elf32_Rel >( offset, info ); if ( SHT_REL == relocation_section->get_type() ) {
generic_set_entry_rel<Elf32_Rel>( index, offset, symbol, type,
addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_set_entry_rela<Elf32_Rela>( index, offset, symbol, type,
addend );
}
} }
else { else {
generic_add_entry< Elf64_Rel >( offset, info ); if ( SHT_REL == relocation_section->get_type() ) {
generic_set_entry_rel<Elf64_Rel>( index, offset, symbol, type,
addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_set_entry_rela<Elf64_Rela>( index, offset, symbol, type,
addend );
}
}
return true;
}
//------------------------------------------------------------------------------
void add_entry( Elf64_Addr offset, Elf_Xword info )
{
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry<Elf32_Rel>( offset, info );
}
else {
generic_add_entry<Elf64_Rel>( offset, info );
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type )
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type )
{ {
Elf_Xword info; Elf_Xword info;
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
info = ELF32_R_INFO( (Elf_Xword)symbol, type ); info = ELF32_R_INFO( (Elf_Xword)symbol, type );
} }
else { else {
info = ELF64_R_INFO((Elf_Xword)symbol, type ); info = ELF64_R_INFO( (Elf_Xword)symbol, type );
} }
add_entry( offset, info ); add_entry( offset, info );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
{ {
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry< Elf32_Rela >( offset, info, addend ); generic_add_entry<Elf32_Rela>( offset, info, addend );
} }
else { else {
generic_add_entry< Elf64_Rela >( offset, info, addend ); generic_add_entry<Elf64_Rela>( offset, info, addend );
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void add_entry( Elf64_Addr offset,
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type, Elf_Word symbol,
Elf_Sxword addend ) unsigned type,
Elf_Sxword addend )
{ {
Elf_Xword info; Elf_Xword info;
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
@ -216,48 +273,63 @@ class relocation_section_accessor_template
add_entry( offset, info, addend ); add_entry( offset, info, addend );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void add_entry( string_section_accessor str_writer,
add_entry( string_section_accessor str_writer, const char* str,
const char* str, symbol_section_accessor sym_writer,
symbol_section_accessor sym_writer, Elf64_Addr value,
Elf64_Addr value, Elf_Word size,
Elf_Word size, unsigned char sym_info,
unsigned char sym_info, unsigned char other,
unsigned char other, Elf_Half shndx,
Elf_Half shndx, Elf64_Addr offset,
Elf64_Addr offset, unsigned type )
unsigned char type )
{ {
Elf_Word str_index = str_writer.add_string( str ); Elf_Word str_index = str_writer.add_string( str );
Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size, Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size,
sym_info, other, shndx ); sym_info, other, shndx );
add_entry( offset, sym_index, type ); add_entry( offset, sym_index, type );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void swap_symbols( Elf_Xword first, Elf_Xword second )
{
Elf64_Addr offset = 0;
Elf_Word symbol = 0;
unsigned rtype = 0;
Elf_Sxword addend = 0;
for ( Elf_Word i = 0; i < get_entries_num(); i++ ) {
get_entry( i, offset, symbol, rtype, addend );
if ( symbol == first ) {
set_entry( i, offset, (Elf_Word)second, rtype, addend );
}
if ( symbol == second ) {
set_entry( i, offset, (Elf_Word)first, rtype, addend );
}
}
}
//------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half Elf_Half get_symbol_table_index() const
get_symbol_table_index() const
{ {
return (Elf_Half)relocation_section->get_link(); return (Elf_Half)relocation_section->get_link();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
void void generic_get_entry_rel( Elf_Xword index,
generic_get_entry_rel( Elf_Xword index, Elf64_Addr& offset,
Elf64_Addr& offset, Elf_Word& symbol,
Elf_Word& symbol, unsigned& type,
Elf_Word& type, Elf_Sxword& addend ) const
Elf_Sxword& addend ) const
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
const T* pEntry = reinterpret_cast<const T*>( const T* pEntry = reinterpret_cast<const T*>(
relocation_section->get_data() + relocation_section->get_data() +
index * relocation_section->get_entry_size() ); index * relocation_section->get_entry_size() );
offset = convertor( pEntry->r_offset ); offset = convertor( pEntry->r_offset );
Elf_Xword tmp = convertor( pEntry->r_info ); Elf_Xword tmp = convertor( pEntry->r_info );
symbol = get_sym_and_type<T>::get_r_sym( tmp ); symbol = get_sym_and_type<T>::get_r_sym( tmp );
@ -265,20 +337,19 @@ class relocation_section_accessor_template
addend = 0; addend = 0;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
void void generic_get_entry_rela( Elf_Xword index,
generic_get_entry_rela( Elf_Xword index, Elf64_Addr& offset,
Elf64_Addr& offset, Elf_Word& symbol,
Elf_Word& symbol, unsigned& type,
Elf_Word& type, Elf_Sxword& addend ) const
Elf_Sxword& addend ) const
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
const T* pEntry = reinterpret_cast<const T*>( const T* pEntry = reinterpret_cast<const T*>(
relocation_section->get_data() + relocation_section->get_data() +
index * relocation_section->get_entry_size() ); index * relocation_section->get_entry_size() );
offset = convertor( pEntry->r_offset ); offset = convertor( pEntry->r_offset );
Elf_Xword tmp = convertor( pEntry->r_info ); Elf_Xword tmp = convertor( pEntry->r_info );
symbol = get_sym_and_type<T>::get_r_sym( tmp ); symbol = get_sym_and_type<T>::get_r_sym( tmp );
@ -286,24 +357,76 @@ class relocation_section_accessor_template
addend = convertor( pEntry->r_addend ); addend = convertor( pEntry->r_addend );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
void void generic_set_entry_rel( Elf_Xword index,
generic_add_entry( Elf64_Addr offset, Elf_Xword info ) Elf64_Addr offset,
Elf_Word symbol,
unsigned type,
Elf_Sxword )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T* pEntry = const_cast<T*>( reinterpret_cast<const T*>(
relocation_section->get_data() +
index * relocation_section->get_entry_size() ) );
if ( elf_file.get_class() == ELFCLASS32 ) {
pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type );
}
else {
pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type );
}
pEntry->r_offset = decltype( pEntry->r_offset )( offset );
pEntry->r_offset = convertor( pEntry->r_offset );
pEntry->r_info = convertor( pEntry->r_info );
}
//------------------------------------------------------------------------------
template <class T>
void generic_set_entry_rela( Elf_Xword index,
Elf64_Addr offset,
Elf_Word symbol,
unsigned type,
Elf_Sxword addend )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T* pEntry = const_cast<T*>( reinterpret_cast<const T*>(
relocation_section->get_data() +
index * relocation_section->get_entry_size() ) );
if ( elf_file.get_class() == ELFCLASS32 ) {
pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type );
}
else {
pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type );
}
pEntry->r_offset = decltype( pEntry->r_offset )( offset );
pEntry->r_addend = decltype( pEntry->r_addend )( addend );
pEntry->r_offset = convertor( pEntry->r_offset );
pEntry->r_info = convertor( pEntry->r_info );
pEntry->r_addend = convertor( pEntry->r_addend );
}
//------------------------------------------------------------------------------
template <class T>
void generic_add_entry( Elf64_Addr offset, Elf_Xword info )
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
T entry; T entry;
entry.r_offset = offset; entry.r_offset = decltype( entry.r_offset )( offset );
entry.r_info = info; entry.r_info = decltype( entry.r_info )( info );
entry.r_offset = convertor( entry.r_offset ); entry.r_offset = convertor( entry.r_offset );
entry.r_info = convertor( entry.r_info ); entry.r_info = convertor( entry.r_info );
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) ); relocation_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
void void
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
{ {
@ -317,17 +440,20 @@ class relocation_section_accessor_template
entry.r_info = convertor( entry.r_info ); entry.r_info = convertor( entry.r_info );
entry.r_addend = convertor( entry.r_addend ); entry.r_addend = convertor( entry.r_addend );
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) ); relocation_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file;
S* relocation_section; S* relocation_section = nullptr;
}; };
using relocation_section_accessor = relocation_section_accessor_template<section>; using relocation_section_accessor =
using const_relocation_section_accessor = relocation_section_accessor_template<const section>; relocation_section_accessor_template<section>;
using const_relocation_section_accessor =
relocation_section_accessor_template<const section>;
} // namespace ELFIO } // namespace ELFIO

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -26,320 +25,342 @@ THE SOFTWARE.
#include <string> #include <string>
#include <iostream> #include <iostream>
#include "utils/logger.h" #include <new>
#include <zlib.h> #include <limits>
namespace ELFIO { namespace ELFIO {
class section class section
{ {
friend class elfio; friend class elfio;
public: public:
virtual ~section() {}; virtual ~section() = default;
ELFIO_GET_ACCESS_DECL ( Elf_Half, index ); ELFIO_GET_ACCESS_DECL( Elf_Half, index );
ELFIO_GET_SET_ACCESS_DECL( std::string, name ); ELFIO_GET_SET_ACCESS_DECL( std::string, name );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
ELFIO_GET_ACCESS_DECL ( Elf64_Off, offset ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
size_t stream_size;
size_t get_stream_size() const
{
return stream_size;
}
void set_stream_size(size_t value) virtual const char* get_data() const = 0;
{ virtual void set_data( const char* raw_data, Elf_Word size ) = 0;
stream_size = value; virtual void set_data( const std::string& data ) = 0;
} virtual void append_data( const char* raw_data, Elf_Word size ) = 0;
virtual void append_data( const std::string& data ) = 0;
virtual const char* get_data() const = 0; virtual void
virtual void set_data( const char* pData, Elf_Word size ) = 0; insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) = 0;
virtual void set_data( const std::string& data ) = 0; virtual void insert_data( Elf_Xword pos, const std::string& data ) = 0;
virtual void append_data( const char* pData, Elf_Word size ) = 0; virtual size_t get_stream_size() const = 0;
virtual void append_data( const std::string& data ) = 0; virtual void set_stream_size( size_t value ) = 0;
protected: protected:
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index ); ELFIO_SET_ACCESS_DECL( Elf_Half, index );
virtual void load( std::istream& stream, virtual bool load( std::istream& stream,
std::streampos header_offset ) = 0; std::streampos header_offset,
bool is_lazy ) = 0;
virtual void save( std::ostream& stream, virtual void save( std::ostream& stream,
std::streampos header_offset, std::streampos header_offset,
std::streampos data_offset ) = 0; std::streampos data_offset ) = 0;
virtual bool is_address_initialized() const = 0; virtual bool is_address_initialized() const = 0;
}; };
template <class T> class section_impl : public section
template< class T >
class section_impl : public section
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
section_impl( const endianess_convertor* convertor_ ) : convertor( convertor_ ) section_impl( const endianess_convertor* convertor,
const address_translator* translator,
const std::shared_ptr<compression_interface>& compression )
: convertor( convertor ), translator( translator ),
compression( compression )
{ {
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
is_address_set = false;
data = 0;
data_size = 0;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
~section_impl()
{
delete [] data;
}
//------------------------------------------------------------------------------
// Section info functions // Section info functions
ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type );
ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags );
ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size ); ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size );
ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link ); ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link );
ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info ); ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info );
ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign ); ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign );
ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize );
ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name );
ELFIO_GET_ACCESS ( Elf64_Addr, address, header.sh_addr ); ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr );
//------------------------------------------------------------------------------
Elf_Half get_index() const override { return index; }
//------------------------------------------------------------------------------
std::string get_name() const override { return name; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half void set_name( const std::string& name_prm ) override
get_index() const
{ {
return index; this->name = name_prm;
} }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ void set_address( const Elf64_Addr& value ) override
std::string
get_name() const
{ {
return name; header.sh_addr = decltype( header.sh_addr )( value );
} header.sh_addr = ( *convertor )( header.sh_addr );
//------------------------------------------------------------------------------
void
set_name( std::string name_ )
{
name = name_;
}
//------------------------------------------------------------------------------
void
set_address( Elf64_Addr value )
{
header.sh_addr = value;
header.sh_addr = (*convertor)( header.sh_addr );
is_address_set = true; is_address_set = true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool is_address_initialized() const override { return is_address_set; }
is_address_initialized() const
//------------------------------------------------------------------------------
const char* get_data() const override
{ {
return is_address_set; if ( is_lazy ) {
load_data();
}
return data.get();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
const char* void set_data( const char* raw_data, Elf_Word size ) override
get_data() const
{
return data;
}
//------------------------------------------------------------------------------
void
set_data( const char* raw_data, Elf_Word size )
{ {
if ( get_type() != SHT_NOBITS ) { if ( get_type() != SHT_NOBITS ) {
delete [] data; data = std::unique_ptr<char[]>( new ( std::nothrow ) char[size] );
data = new char[size]; if ( nullptr != data.get() && nullptr != raw_data ) {
if ( 0 != data && 0 != raw_data ) {
data_size = size; data_size = size;
std::copy( raw_data, raw_data + size, data ); std::copy( raw_data, raw_data + size, data.get() );
}
else {
data_size = 0;
} }
} }
set_size( size ); set_size( data_size );
if ( translator->empty() ) {
set_stream_size( data_size );
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void set_data( const std::string& str_data ) override
set_data( const std::string& str_data )
{ {
return set_data( str_data.c_str(), (Elf_Word)str_data.size() ); return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void append_data( const char* raw_data, Elf_Word size ) override
append_data( const char* raw_data, Elf_Word size )
{ {
if ( get_type() != SHT_NOBITS ) { insert_data( get_size(), raw_data, size );
if ( get_size() + size < data_size ) {
std::copy( raw_data, raw_data + size, data + get_size() );
}
else {
data_size = 2*( data_size + size);
char* new_data;
new_data = new char[data_size];
if ( 0 != new_data ) {
std::copy( data, data + get_size(), new_data );
std::copy( raw_data, raw_data + size, new_data + get_size() );
delete [] data;
data = new_data;
}
}
set_size( get_size() + size );
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void append_data( const std::string& str_data ) override
append_data( const std::string& str_data )
{ {
return append_data( str_data.c_str(), (Elf_Word)str_data.size() ); return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
protected:
//------------------------------------------------------------------------------
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
//------------------------------------------------------------------------------
void void
set_index( Elf_Half value ) insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) override
{ {
index = value; if ( get_type() != SHT_NOBITS ) {
} if ( get_size() + size < data_size ) {
char* d = data.get();
std::copy_backward( d + pos, d + get_size(),
d + get_size() + size );
std::copy( raw_data, raw_data + size, d + pos );
}
else {
data_size = 2 * ( data_size + size );
std::unique_ptr<char[]> new_data(
new ( std::nothrow ) char[data_size] );
//------------------------------------------------------------------------------ if ( nullptr != new_data ) {
void char* d = data.get();
load( std::istream& stream, std::copy( d, d + pos, new_data.get() );
std::streampos header_offset ) std::copy( raw_data, raw_data + size,
{ new_data.get() + pos );
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' ); std::copy( d + pos, d + get_size(),
new_data.get() + pos + size );
stream.seekg ( 0, stream.end ); data = std::move( new_data );
set_stream_size ( stream.tellg() );
stream.seekg( header_offset );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
Elf_Xword size = get_size();
if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size()) {
data = new char[size + 1];
if ( ( 0 != size ) && ( 0 != data ) ) {
stream.seekg( (*convertor)( header.sh_offset ) );
if (get_flags() & 0x08000000){
uint32_t uncompressed_size = size;
stream.read( (char *) &uncompressed_size, 4);
stream.read( data, size - 4);
char* uncompressedData = new char[uncompressed_size + 1];
int ret = 0;
z_stream s;
memset(&s, 0, sizeof(s));
s.zalloc = Z_NULL;
s.zfree = Z_NULL;
s.opaque = Z_NULL;
ret = inflateInit_(&s, ZLIB_VERSION, sizeof(s));
if (ret != Z_OK)
return;
s.avail_in = size - 4;
s.next_in = (Bytef *)data;
s.avail_out = uncompressed_size;
s.next_out = (Bytef *)&uncompressedData[0];
ret = inflate(&s, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END){
DEBUG_FUNCTION_LINE("NOOOO");
}
inflateEnd(&s);
delete [] data;
data = uncompressedData;
data_size = uncompressed_size;
set_size(uncompressed_size);
data[data_size] = 0; // Ensure data is ended with 0 to avoid oob read
}else{
stream.read( data, size );
data[size] = 0; // Ensure data is ended with 0 to avoid oob read
data_size = size;
} }
}else{ else {
set_size(0); size = 0;
DEBUG_FUNCTION_LINE("Failed to allocate memory."); }
}
set_size( get_size() + size );
if ( translator->empty() ) {
set_stream_size( get_stream_size() + size );
} }
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void insert_data( Elf_Xword pos, const std::string& str_data ) override
save( std::ostream& stream, {
std::streampos header_offset, return insert_data( pos, str_data.c_str(), (Elf_Word)str_data.size() );
std::streampos data_offset ) }
size_t get_stream_size() const override { return stream_size; }
//------------------------------------------------------------------------------
void set_stream_size( size_t value ) override { stream_size = value; }
//------------------------------------------------------------------------------
protected:
//------------------------------------------------------------------------------
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
//------------------------------------------------------------------------------
void set_index( const Elf_Half& value ) override { index = value; }
bool is_compressed() const
{
return ( ( get_flags() & SHF_RPX_DEFLATE ) ||
( get_flags() & SHF_COMPRESSED ) ) &&
compression != nullptr;
}
//------------------------------------------------------------------------------
bool load( std::istream& stream,
std::streampos header_offset,
bool is_lazy_ ) override
{
pstream = &stream;
is_lazy = is_lazy_;
header = { 0 };
if ( translator->empty() ) {
stream.seekg( 0, std::istream::end );
set_stream_size( size_t( stream.tellg() ) );
}
else {
set_stream_size( std::numeric_limits<size_t>::max() );
}
stream.seekg( ( *translator )[header_offset] );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
if ( !is_lazy || is_compressed() ) {
bool ret = load_data();
if ( is_compressed() ) {
Elf_Xword size = get_size();
Elf_Xword uncompressed_size = 0;
auto decompressed_data = compression->inflate(
data.get(), convertor, size, uncompressed_size );
if ( decompressed_data != nullptr ) {
set_size( uncompressed_size );
data = std::move( decompressed_data );
}
}
return ret;
}
return true;
}
bool load_data() const
{
is_lazy = false;
Elf_Xword size = get_size();
if ( nullptr == data && SHT_NULL != get_type() &&
SHT_NOBITS != get_type() && size < get_stream_size() ) {
data.reset( new ( std::nothrow ) char[size_t( size ) + 1] );
if ( ( 0 != size ) && ( nullptr != data ) ) {
pstream->seekg(
( *translator )[( *convertor )( header.sh_offset )] );
pstream->read( data.get(), size );
if ( static_cast<Elf_Xword>( pstream->gcount() ) != size ) {
data = nullptr;
return false;
}
// refresh size because it may have changed if we had to decompress data
size = get_size();
data.get()[size] =
0; // Ensure data is ended with 0 to avoid oob read
data_size = decltype( data_size )( size );
}
else {
data_size = 0;
}
}
return true;
}
//------------------------------------------------------------------------------
void save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset ) override
{ {
if ( 0 != get_index() ) { if ( 0 != get_index() ) {
header.sh_offset = data_offset; header.sh_offset = decltype( header.sh_offset )( data_offset );
header.sh_offset = (*convertor)( header.sh_offset ); header.sh_offset = ( *convertor )( header.sh_offset );
} }
save_header( stream, header_offset ); save_header( stream, header_offset );
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL && if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
get_size() != 0 && data != 0 ) { get_size() != 0 && data != nullptr ) {
save_data( stream, data_offset ); save_data( stream, data_offset );
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void save_header( std::ostream& stream, std::streampos header_offset ) const
save_header( std::ostream& stream,
std::streampos header_offset ) const
{ {
stream.seekp( header_offset ); adjust_stream_size( stream, header_offset );
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) ); stream.write( reinterpret_cast<const char*>( &header ),
sizeof( header ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void save_data( std::ostream& stream, std::streampos data_offset )
save_data( std::ostream& stream,
std::streampos data_offset ) const
{ {
stream.seekp( data_offset ); adjust_stream_size( stream, data_offset );
stream.write( get_data(), get_size() );
if ( ( ( get_flags() & SHF_COMPRESSED ) ||
( get_flags() & SHF_RPX_DEFLATE ) ) &&
compression != nullptr ) {
Elf_Xword decompressed_size = get_size();
Elf_Xword compressed_size = 0;
auto compressed_ptr = compression->deflate(
data.get(), convertor, decompressed_size, compressed_size );
stream.write( compressed_ptr.get(), compressed_size );
}
else {
stream.write( get_data(), get_size() );
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
T header; mutable std::istream* pstream = nullptr;
Elf_Half index; T header = {};
std::string name; Elf_Half index = 0;
char* data; std::string name;
Elf_Word data_size; mutable std::unique_ptr<char[]> data;
const endianess_convertor* convertor; mutable Elf_Word data_size = 0;
bool is_address_set; const endianess_convertor* convertor = nullptr;
const address_translator* translator = nullptr;
const std::shared_ptr<compression_interface> compression = nullptr;
bool is_address_set = false;
size_t stream_size = 0;
mutable bool is_lazy = false;
}; };
} // namespace ELFIO } // namespace ELFIO

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -26,107 +25,90 @@ THE SOFTWARE.
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <new>
#include <limits>
namespace ELFIO { namespace ELFIO {
class segment class segment
{ {
friend class elfio; friend class elfio;
public:
virtual ~segment() {};
ELFIO_GET_ACCESS_DECL ( Elf_Half, index ); public:
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); virtual ~segment() = default;
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); ELFIO_GET_ACCESS_DECL( Elf_Half, index );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
virtual const char* get_data() const = 0; virtual const char* get_data() const = 0;
virtual Elf_Half add_section_index( Elf_Half index, Elf_Xword addr_align ) = 0; virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0;
virtual Elf_Half get_sections_num() const = 0; virtual Elf_Half add_section_index( Elf_Half index,
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; Elf_Xword addr_align ) = 0;
virtual bool is_offset_initialized() const = 0; virtual Elf_Half get_sections_num() const = 0;
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
virtual bool is_offset_initialized() const = 0;
protected: protected:
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index ); ELFIO_SET_ACCESS_DECL( Elf_Half, index );
virtual const std::vector<Elf_Half>& get_sections() const = 0; virtual const std::vector<Elf_Half>& get_sections() const = 0;
virtual void load( std::istream& stream, std::streampos header_offset ) = 0;
virtual void save( std::ostream& stream, std::streampos header_offset, virtual bool load( std::istream& stream,
std::streampos data_offset ) = 0; std::streampos header_offset,
bool is_lazy ) = 0;
virtual void save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset ) = 0;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T> class segment_impl : public segment
class segment_impl : public segment
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
segment_impl( endianess_convertor* convertor_ ) : segment_impl( const endianess_convertor* convertor,
stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor_ ) const address_translator* translator )
: convertor( convertor ), translator( translator )
{ {
is_offset_set = false;
std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
virtual ~segment_impl()
{
delete [] data;
}
//------------------------------------------------------------------------------
// Section info functions // Section info functions
ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type );
ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags );
ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align );
ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr );
ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr );
ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz );
ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
size_t stream_size;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
size_t Elf_Half get_index() const override { return index; }
get_stream_size() const
//------------------------------------------------------------------------------
const char* get_data() const override
{ {
return stream_size; if ( is_lazy ) {
load_data();
}
return data.get();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Elf_Half add_section_index( Elf_Half sec_index,
set_stream_size(size_t value) Elf_Xword addr_align ) override
{ {
stream_size = value; sections.emplace_back( sec_index );
}
//------------------------------------------------------------------------------
Elf_Half
get_index() const
{
return index;
}
//------------------------------------------------------------------------------
const char*
get_data() const
{
return data;
}
//------------------------------------------------------------------------------
Elf_Half
add_section_index( Elf_Half sec_index, Elf_Xword addr_align )
{
sections.push_back( sec_index );
if ( addr_align > get_align() ) { if ( addr_align > get_align() ) {
set_align( addr_align ); set_align( addr_align );
} }
@ -134,108 +116,137 @@ class segment_impl : public segment
return (Elf_Half)sections.size(); return (Elf_Half)sections.size();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half Elf_Half add_section( section* psec, Elf_Xword addr_align ) override
get_sections_num() const {
return add_section_index( psec->get_index(), addr_align );
}
//------------------------------------------------------------------------------
Elf_Half get_sections_num() const override
{ {
return (Elf_Half)sections.size(); return (Elf_Half)sections.size();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half Elf_Half get_section_index_at( Elf_Half num ) const override
get_section_index_at( Elf_Half num ) const
{ {
if ( num < sections.size() ) { if ( num < sections.size() ) {
return sections[num]; return sections[num];
} }
return Elf_Half(-1); return Elf_Half( -1 );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
protected: protected:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void set_offset( const Elf64_Off& value ) override
set_offset( Elf64_Off value )
{ {
ph.p_offset = value; ph.p_offset = decltype( ph.p_offset )( value );
ph.p_offset = (*convertor)( ph.p_offset ); ph.p_offset = ( *convertor )( ph.p_offset );
is_offset_set = true; is_offset_set = true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool is_offset_initialized() const override { return is_offset_set; }
is_offset_initialized() const
{
return is_offset_set;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
const std::vector<Elf_Half>& const std::vector<Elf_Half>& get_sections() const override
get_sections() const
{ {
return sections; return sections;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void set_index( const Elf_Half& value ) override { index = value; }
set_index( Elf_Half value )
//------------------------------------------------------------------------------
bool load( std::istream& stream,
std::streampos header_offset,
bool is_lazy_ ) override
{ {
index = value; pstream = &stream;
} is_lazy = is_lazy_;
//------------------------------------------------------------------------------ if ( translator->empty() ) {
void stream.seekg( 0, std::istream::end );
load( std::istream& stream, set_stream_size( size_t( stream.tellg() ) );
std::streampos header_offset ) }
{ else {
set_stream_size( std::numeric_limits<size_t>::max() );
}
stream.seekg ( 0, stream.end ); stream.seekg( ( *translator )[header_offset] );
set_stream_size ( stream.tellg() );
stream.seekg( header_offset );
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) ); stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
is_offset_set = true; is_offset_set = true;
if ( PT_NULL != get_type() && 0 != get_file_size() ) { if ( !is_lazy ) {
stream.seekg( (*convertor)( ph.p_offset ) ); return load_data();
Elf_Xword size = get_file_size();
if ( size > get_stream_size() ) {
data = 0;
}
else {
data = new char[size + 1];
if ( 0 != data ) {
stream.read( data, size );
data[size] = 0;
}
}
} }
return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool load_data() const
{
is_lazy = false;
if ( PT_NULL == get_type() || 0 == get_file_size() ) {
return true;
}
pstream->seekg( ( *translator )[( *convertor )( ph.p_offset )] );
Elf_Xword size = get_file_size();
if ( size > get_stream_size() ) {
data = nullptr;
}
else {
data.reset( new ( std::nothrow ) char[(size_t)size + 1] );
if ( nullptr != data.get() && pstream->read( data.get(), size ) ) {
data.get()[size] = 0;
}
else {
data = nullptr;
return false;
}
}
return true;
}
//------------------------------------------------------------------------------
void save( std::ostream& stream, void save( std::ostream& stream,
std::streampos header_offset, std::streampos header_offset,
std::streampos data_offset ) std::streampos data_offset ) override
{ {
ph.p_offset = data_offset; ph.p_offset = decltype( ph.p_offset )( data_offset );
ph.p_offset = (*convertor)(ph.p_offset); ph.p_offset = ( *convertor )( ph.p_offset );
stream.seekp( header_offset ); adjust_stream_size( stream, header_offset );
stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) ); stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
size_t get_stream_size() const { return stream_size; }
//------------------------------------------------------------------------------
void set_stream_size( size_t value ) { stream_size = value; }
//------------------------------------------------------------------------------
private: private:
T ph; mutable std::istream* pstream = nullptr;
Elf_Half index; T ph = {};
char* data; Elf_Half index = 0;
std::vector<Elf_Half> sections; mutable std::unique_ptr<char[]> data;
endianess_convertor* convertor; std::vector<Elf_Half> sections;
bool is_offset_set; const endianess_convertor* convertor = nullptr;
const address_translator* translator = nullptr;
size_t stream_size = 0;
bool is_offset_set = false;
mutable bool is_lazy = false;
}; };
} // namespace ELFIO } // namespace ELFIO

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -31,70 +30,67 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class S > template <class S> class string_section_accessor_template
class string_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
string_section_accessor_template( S* section_ ) : explicit string_section_accessor_template( S* section )
string_section( section_ ) : string_section( section )
{ {
} }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ const char* get_string( Elf_Word index ) const
const char*
get_string( Elf_Word index ) const
{ {
if ( string_section ) { if ( string_section ) {
if ( index < string_section->get_size() ) { const char* data = string_section->get_data();
const char* data = string_section->get_data(); if ( index < string_section->get_size() && nullptr != data ) {
if ( 0 != data ) { size_t string_length =
strnlen( data + index, string_section->get_size() - index );
if ( string_length < ( string_section->get_size() - index ) )
return data + index; return data + index;
}
} }
} }
return 0; return nullptr;
} }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ Elf_Word add_string( const char* str )
Elf_Word
add_string( const char* str )
{ {
Elf_Word current_position = 0; Elf_Word current_position = 0;
if (string_section) { if ( string_section ) {
// Strings are addeded to the end of the current section data // Strings are addeded to the end of the current section data
current_position = (Elf_Word)string_section->get_size(); current_position =
static_cast<Elf_Word>( string_section->get_size() );
if ( current_position == 0 ) { if ( current_position == 0 ) {
char empty_string = '\0'; char empty_string = '\0';
string_section->append_data( &empty_string, 1 ); string_section->append_data( &empty_string, 1 );
current_position++; current_position++;
} }
string_section->append_data( str, (Elf_Word)std::strlen( str ) + 1 ); string_section->append_data(
str, static_cast<Elf_Word>( std::strlen( str ) + 1 ) );
} }
return current_position; return current_position;
} }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ Elf_Word add_string( const std::string& str )
Elf_Word
add_string( const std::string& str )
{ {
return add_string( str.c_str() ); return add_string( str.c_str() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
S* string_section; S* string_section;
}; };
using string_section_accessor = string_section_accessor_template<section>; using string_section_accessor = string_section_accessor_template<section>;
using const_string_section_accessor = string_section_accessor_template<const section>; using const_string_section_accessor =
string_section_accessor_template<const section>;
} // namespace ELFIO } // namespace ELFIO

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -27,40 +26,52 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class S > template <class S> class symbol_section_accessor_template
class symbol_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
symbol_section_accessor_template( const elfio& elf_file_, S* symbol_section_ ) : explicit symbol_section_accessor_template( const elfio& elf_file,
elf_file( elf_file_ ), S* symbol_section )
symbol_section( symbol_section_ ) : elf_file( elf_file ), symbol_section( symbol_section )
{ {
find_hash_section(); find_hash_section();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Xword Elf_Xword get_symbols_num() const
get_symbols_num() const
{ {
Elf_Xword nRet = 0; Elf_Xword nRet = 0;
if ( 0 != symbol_section->get_entry_size() ) {
nRet = symbol_section->get_size() / symbol_section->get_entry_size(); size_t minimum_symbol_size;
switch ( elf_file.get_class() ) {
case ELFCLASS32:
minimum_symbol_size = sizeof( Elf32_Sym );
break;
case ELFCLASS64:
minimum_symbol_size = sizeof( Elf64_Sym );
break;
default:
return nRet;
}
if ( symbol_section->get_entry_size() >= minimum_symbol_size &&
symbol_section->get_size() <= symbol_section->get_stream_size() ) {
nRet =
symbol_section->get_size() / symbol_section->get_entry_size();
} }
return nRet; return nRet;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool get_symbol( Elf_Xword index,
get_symbol( Elf_Xword index, std::string& name,
std::string& name, Elf64_Addr& value,
Elf64_Addr& value, Elf_Xword& size,
Elf_Xword& size, unsigned char& bind,
unsigned char& bind, unsigned char& type,
unsigned char& type, Elf_Half& section_index,
Elf_Half& section_index, unsigned char& other ) const
unsigned char& other ) const
{ {
bool ret = false; bool ret = false;
@ -76,46 +87,96 @@ class symbol_section_accessor_template
return ret; return ret;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool get_symbol( const std::string& name,
get_symbol( const std::string& name, Elf64_Addr& value,
Elf64_Addr& value, Elf_Xword& size,
Elf_Xword& size, unsigned char& bind,
unsigned char& bind, unsigned char& type,
unsigned char& type, Elf_Half& section_index,
Elf_Half& section_index, unsigned char& other ) const
unsigned char& other ) const
{ {
bool ret = false; bool ret = false;
if ( 0 != get_hash_table_index() ) { if ( 0 != get_hash_table_index() ) {
Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data(); if ( hash_section->get_type() == SHT_HASH ) {
Elf_Word nchain = *(const Elf_Word*)( hash_section->get_data() + ret = hash_lookup( name, value, size, bind, type, section_index,
sizeof( Elf_Word ) ); other );
Elf_Word val = elf_hash( (const unsigned char*)name.c_str() );
Elf_Word y = *(const Elf_Word*)( hash_section->get_data() +
( 2 + val % nbucket ) * sizeof( Elf_Word ) );
std::string str;
get_symbol( y, str, value, size, bind, type, section_index, other );
while ( str != name && STN_UNDEF != y && y < nchain ) {
y = *(const Elf_Word*)( hash_section->get_data() +
( 2 + nbucket + y ) * sizeof( Elf_Word ) );
get_symbol( y, str, value, size, bind, type, section_index, other );
} }
if ( str == name ) { if ( hash_section->get_type() == SHT_GNU_HASH ||
ret = true; hash_section->get_type() == DT_GNU_HASH ) {
if ( elf_file.get_class() == ELFCLASS32 ) {
ret = gnu_hash_lookup<uint32_t>(
name, value, size, bind, type, section_index, other );
}
else {
ret = gnu_hash_lookup<uint64_t>(
name, value, size, bind, type, section_index, other );
}
}
}
if ( !ret ) {
for ( Elf_Xword i = 0; !ret && i < get_symbols_num(); i++ ) {
std::string symbol_name;
if ( get_symbol( i, symbol_name, value, size, bind, type,
section_index, other ) ) {
if ( symbol_name == name ) {
ret = true;
}
}
} }
} }
return ret; return ret;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word bool get_symbol( const Elf64_Addr& value,
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, std::string& name,
unsigned char info, unsigned char other, Elf_Xword& size,
Elf_Half shndx ) unsigned char& bind,
unsigned char& type,
Elf_Half& section_index,
unsigned char& other ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
Elf_Xword idx = 0;
bool match = false;
Elf64_Addr v = 0;
if ( elf_file.get_class() == ELFCLASS32 ) {
match = generic_search_symbols<Elf32_Sym>(
[&]( const Elf32_Sym* sym ) {
return convertor( sym->st_value ) == value;
},
idx );
}
else {
match = generic_search_symbols<Elf64_Sym>(
[&]( const Elf64_Sym* sym ) {
return convertor( sym->st_value ) == value;
},
idx );
}
if ( match ) {
return get_symbol( idx, name, v, size, bind, type, section_index,
other );
}
return false;
}
//------------------------------------------------------------------------------
Elf_Word add_symbol( Elf_Word name,
Elf64_Addr value,
Elf_Xword size,
unsigned char info,
unsigned char other,
Elf_Half shndx )
{ {
Elf_Word nRet; Elf_Word nRet;
@ -129,110 +190,276 @@ class symbol_section_accessor_template
} }
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info, other, nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info,
shndx ); other, shndx );
} }
else { else {
nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info, other, nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info,
shndx ); other, shndx );
} }
return nRet; return nRet;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word Elf_Word add_symbol( Elf_Word name,
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, Elf64_Addr value,
unsigned char bind, unsigned char type, unsigned char other, Elf_Xword size,
Elf_Half shndx ) unsigned char bind,
unsigned char type,
unsigned char other,
Elf_Half shndx )
{ {
return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, shndx ); return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other,
shndx );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word Elf_Word add_symbol( string_section_accessor& pStrWriter,
add_symbol( string_section_accessor& pStrWriter, const char* str, const char* str,
Elf64_Addr value, Elf_Xword size, Elf64_Addr value,
unsigned char info, unsigned char other, Elf_Xword size,
Elf_Half shndx ) unsigned char info,
unsigned char other,
Elf_Half shndx )
{ {
Elf_Word index = pStrWriter.add_string( str ); Elf_Word index = pStrWriter.add_string( str );
return add_symbol( index, value, size, info, other, shndx ); return add_symbol( index, value, size, info, other, shndx );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word Elf_Word add_symbol( string_section_accessor& pStrWriter,
add_symbol( string_section_accessor& pStrWriter, const char* str, const char* str,
Elf64_Addr value, Elf_Xword size, Elf64_Addr value,
unsigned char bind, unsigned char type, unsigned char other, Elf_Xword size,
Elf_Half shndx ) unsigned char bind,
unsigned char type,
unsigned char other,
Elf_Half shndx )
{ {
return add_symbol( pStrWriter, str, value, size, ELF_ST_INFO( bind, type ), other, shndx ); return add_symbol( pStrWriter, str, value, size,
ELF_ST_INFO( bind, type ), other, shndx );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: Elf_Xword arrange_local_symbols(
//------------------------------------------------------------------------------ std::function<void( Elf_Xword first, Elf_Xword second )> func =
void nullptr )
find_hash_section() {
Elf_Xword nRet = 0;
if ( elf_file.get_class() == ELFCLASS32 ) {
nRet = generic_arrange_local_symbols<Elf32_Sym>( func );
}
else {
nRet = generic_arrange_local_symbols<Elf64_Sym>( func );
}
return nRet;
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
void find_hash_section()
{ {
hash_section = 0;
hash_section_index = 0;
Elf_Half nSecNo = elf_file.sections.size(); Elf_Half nSecNo = elf_file.sections.size();
for ( Elf_Half i = 0; i < nSecNo && 0 == hash_section_index; ++i ) { for ( Elf_Half i = 0; i < nSecNo; ++i ) {
const section* sec = elf_file.sections[i]; const section* sec = elf_file.sections[i];
if ( sec->get_link() == symbol_section->get_index() ) { if ( sec->get_link() == symbol_section->get_index() &&
( sec->get_type() == SHT_HASH ||
sec->get_type() == SHT_GNU_HASH ||
sec->get_type() == DT_GNU_HASH ) ) {
hash_section = sec; hash_section = sec;
hash_section_index = i; hash_section_index = i;
break;
} }
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half Elf_Half get_string_table_index() const
get_string_table_index() const
{ {
return (Elf_Half)symbol_section->get_link(); return (Elf_Half)symbol_section->get_link();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half Elf_Half get_hash_table_index() const { return hash_section_index; }
get_hash_table_index() const
//------------------------------------------------------------------------------
bool hash_lookup( const std::string& name,
Elf64_Addr& value,
Elf_Xword& size,
unsigned char& bind,
unsigned char& type,
Elf_Half& section_index,
unsigned char& other ) const
{ {
return hash_section_index; bool ret = false;
const endianess_convertor& convertor = elf_file.get_convertor();
Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data();
nbucket = convertor( nbucket );
Elf_Word nchain =
*(const Elf_Word*)( hash_section->get_data() + sizeof( Elf_Word ) );
nchain = convertor( nchain );
Elf_Word val = elf_hash( (const unsigned char*)name.c_str() );
Elf_Word y =
*(const Elf_Word*)( hash_section->get_data() +
( 2 + val % nbucket ) * sizeof( Elf_Word ) );
y = convertor( y );
std::string str;
get_symbol( y, str, value, size, bind, type, section_index, other );
while ( str != name && STN_UNDEF != y && y < nchain ) {
y = *(const Elf_Word*)( hash_section->get_data() +
( 2 + nbucket + y ) * sizeof( Elf_Word ) );
y = convertor( y );
get_symbol( y, str, value, size, bind, type, section_index, other );
}
if ( str == name ) {
ret = true;
}
return ret;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
bool bool gnu_hash_lookup( const std::string& name,
generic_get_symbol( Elf_Xword index, Elf64_Addr& value,
std::string& name, Elf64_Addr& value, Elf_Xword& size,
Elf_Xword& size, unsigned char& bind,
unsigned char& bind, unsigned char& type, unsigned char& type,
Elf_Half& section_index, Elf_Half& section_index,
unsigned char& other ) const unsigned char& other ) const
{
bool ret = false;
const endianess_convertor& convertor = elf_file.get_convertor();
uint32_t nbuckets = *( (uint32_t*)hash_section->get_data() + 0 );
uint32_t symoffset = *( (uint32_t*)hash_section->get_data() + 1 );
uint32_t bloom_size = *( (uint32_t*)hash_section->get_data() + 2 );
uint32_t bloom_shift = *( (uint32_t*)hash_section->get_data() + 3 );
nbuckets = convertor( nbuckets );
symoffset = convertor( symoffset );
bloom_size = convertor( bloom_size );
bloom_shift = convertor( bloom_shift );
T* bloom_filter =
(T*)( hash_section->get_data() + 4 * sizeof( uint32_t ) );
uint32_t hash = elf_gnu_hash( (const unsigned char*)name.c_str() );
uint32_t bloom_index = ( hash / ( 8 * sizeof( T ) ) ) % bloom_size;
T bloom_bits =
( (T)1 << ( hash % ( 8 * sizeof( T ) ) ) ) |
( (T)1 << ( ( hash >> bloom_shift ) % ( 8 * sizeof( T ) ) ) );
if ( ( convertor( bloom_filter[bloom_index] ) & bloom_bits ) !=
bloom_bits )
return ret;
uint32_t bucket = hash % nbuckets;
auto* buckets =
(uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) +
bloom_size * sizeof( T ) );
auto* chains =
(uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) +
bloom_size * sizeof( T ) +
nbuckets * sizeof( uint32_t ) );
if ( convertor( buckets[bucket] ) >= symoffset ) {
uint32_t chain_index = convertor( buckets[bucket] ) - symoffset;
uint32_t chain_hash = convertor( chains[chain_index] );
std::string symname;
while ( true ) {
if ( ( chain_hash >> 1 ) == ( hash >> 1 ) &&
get_symbol( chain_index + symoffset, symname, value, size,
bind, type, section_index, other ) &&
name == symname ) {
ret = true;
break;
}
if ( chain_hash & 1 )
break;
chain_hash = convertor( chains[++chain_index] );
}
}
return ret;
}
//------------------------------------------------------------------------------
template <class T> const T* generic_get_symbol_ptr( Elf_Xword index ) const
{
if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) {
const T* pSym = reinterpret_cast<const T*>(
symbol_section->get_data() +
index * symbol_section->get_entry_size() );
return pSym;
}
return nullptr;
}
//------------------------------------------------------------------------------
template <class T>
bool generic_search_symbols( std::function<bool( const T* )> match,
Elf_Xword& idx ) const
{
for ( Elf_Xword i = 0; i < get_symbols_num(); i++ ) {
const T* symPtr = generic_get_symbol_ptr<T>( i );
if ( symPtr == nullptr )
return false;
if ( match( symPtr ) ) {
idx = i;
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
template <class T>
bool generic_get_symbol( Elf_Xword index,
std::string& name,
Elf64_Addr& value,
Elf_Xword& size,
unsigned char& bind,
unsigned char& type,
Elf_Half& section_index,
unsigned char& other ) const
{ {
bool ret = false; bool ret = false;
if ( index < get_symbols_num() ) { if ( nullptr != symbol_section->get_data() &&
index < get_symbols_num() ) {
const T* pSym = reinterpret_cast<const T*>( const T* pSym = reinterpret_cast<const T*>(
symbol_section->get_data() + symbol_section->get_data() +
index * symbol_section->get_entry_size() ); index * symbol_section->get_entry_size() );
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
section* string_section = elf_file.sections[get_string_table_index()]; section* string_section =
elf_file.sections[get_string_table_index()];
string_section_accessor str_reader( string_section ); string_section_accessor str_reader( string_section );
const char* pStr = str_reader.get_string( convertor( pSym->st_name ) ); const char* pStr =
if ( 0 != pStr ) { str_reader.get_string( convertor( pSym->st_name ) );
if ( nullptr != pStr ) {
name = pStr; name = pStr;
} }
value = convertor( pSym->st_value ); value = convertor( pSym->st_value );
size = convertor( pSym->st_size ); size = convertor( pSym->st_size );
bind = ELF_ST_BIND( pSym->st_info ); bind = ELF_ST_BIND( pSym->st_info );
type = ELF_ST_TYPE( pSym->st_info ); type = ELF_ST_TYPE( pSym->st_info );
section_index = convertor( pSym->st_shndx ); section_index = convertor( pSym->st_shndx );
other = pSym->st_other; other = pSym->st_other;
ret = true; ret = true;
} }
@ -240,20 +467,22 @@ class symbol_section_accessor_template
return ret; return ret;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template< class T > template <class T>
Elf_Word Elf_Word generic_add_symbol( Elf_Word name,
generic_add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, Elf64_Addr value,
unsigned char info, unsigned char other, Elf_Xword size,
Elf_Half shndx ) unsigned char info,
unsigned char other,
Elf_Half shndx )
{ {
const endianess_convertor& convertor = elf_file.get_convertor(); const endianess_convertor& convertor = elf_file.get_convertor();
T entry; T entry;
entry.st_name = convertor( name ); entry.st_name = convertor( name );
entry.st_value = value; entry.st_value = decltype( entry.st_value )( value );
entry.st_value = convertor( entry.st_value ); entry.st_value = convertor( entry.st_value );
entry.st_size = size; entry.st_size = decltype( entry.st_size )( size );
entry.st_size = convertor( entry.st_size ); entry.st_size = convertor( entry.st_size );
entry.st_info = convertor( info ); entry.st_info = convertor( info );
entry.st_other = convertor( other ); entry.st_other = convertor( other );
@ -262,21 +491,71 @@ class symbol_section_accessor_template
symbol_section->append_data( reinterpret_cast<char*>( &entry ), symbol_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) ); sizeof( entry ) );
Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1; Elf_Word nRet =
Elf_Word( symbol_section->get_size() / sizeof( entry ) - 1 );
return nRet; return nRet;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T>
Elf_Xword generic_arrange_local_symbols(
std::function<void( Elf_Xword first, Elf_Xword second )> func )
{
const endianess_convertor& convertor = elf_file.get_convertor();
Elf_Word first_not_local =
1; // Skip the first entry. It is always NOTYPE
Elf_Xword current = 0;
Elf_Xword count = get_symbols_num();
while ( true ) {
T* p1 = nullptr;
T* p2 = nullptr;
while ( first_not_local < count ) {
p1 = const_cast<T*>(
generic_get_symbol_ptr<T>( first_not_local ) );
if ( ELF_ST_BIND( convertor( p1->st_info ) ) != STB_LOCAL )
break;
++first_not_local;
}
current = first_not_local + 1;
while ( current < count ) {
p2 = const_cast<T*>( generic_get_symbol_ptr<T>( current ) );
if ( ELF_ST_BIND( convertor( p2->st_info ) ) == STB_LOCAL )
break;
++current;
}
if ( first_not_local < count && current < count ) {
if ( func )
func( first_not_local, current );
std::swap( *p1, *p2 );
}
else {
// Update 'info' field of the section
symbol_section->set_info( first_not_local );
break;
}
}
return first_not_local;
}
//------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file;
S* symbol_section; S* symbol_section;
Elf_Half hash_section_index; Elf_Half hash_section_index{ 0 };
const section* hash_section; const section* hash_section{ nullptr };
}; };
using symbol_section_accessor = symbol_section_accessor_template<section>; using symbol_section_accessor = symbol_section_accessor_template<section>;
using const_symbol_section_accessor = symbol_section_accessor_template<const section>; using const_symbol_section_accessor =
symbol_section_accessor_template<const section>;
} // namespace ELFIO } // namespace ELFIO

View File

@ -1,6 +1,5 @@
// clang-format off
/* /*
Copyright (C) 2001-2015 by Serge Lamikhov-Center Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -24,158 +23,130 @@ THE SOFTWARE.
#ifndef ELFIO_UTILS_HPP #ifndef ELFIO_UTILS_HPP
#define ELFIO_UTILS_HPP #define ELFIO_UTILS_HPP
#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \ #include <cstdint>
TYPE get_##NAME() const \ #include <ostream>
{ \
return (*convertor)( FIELD ); \
}
#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \
void set_##NAME( TYPE value ) \
{ \
FIELD = value; \
FIELD = (*convertor)( FIELD ); \
}
#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \
TYPE get_##NAME() const \
{ \
return (*convertor)( FIELD ); \
} \
void set_##NAME( TYPE value ) \
{ \
FIELD = value; \
FIELD = (*convertor)( FIELD ); \
}
#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) \ #define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0
virtual TYPE get_##NAME() const = 0
#define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \ #define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \
virtual void set_##NAME( TYPE value ) = 0 virtual void set_##NAME( const TYPE& value ) = 0
#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \ #define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \
virtual TYPE get_##NAME() const = 0; \ virtual TYPE get_##NAME() const = 0; \
virtual void set_##NAME( TYPE value ) = 0 virtual void set_##NAME( const TYPE& value ) = 0
#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \
TYPE get_##NAME() const override { return ( *convertor )( FIELD ); }
#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \
void set_##NAME( const TYPE& value ) override \
{ \
FIELD = decltype( FIELD )( value ); \
FIELD = ( *convertor )( FIELD ); \
}
#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \
TYPE get_##NAME() const override { return ( *convertor )( FIELD ); } \
void set_##NAME( const TYPE& value ) override \
{ \
FIELD = decltype( FIELD )( value ); \
FIELD = ( *convertor )( FIELD ); \
}
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class endianess_convertor { class endianess_convertor
{
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
endianess_convertor() void setup( unsigned char elf_file_encoding )
{
need_conversion = false;
}
//------------------------------------------------------------------------------
void
setup( unsigned char elf_file_encoding )
{ {
need_conversion = ( elf_file_encoding != get_host_encoding() ); need_conversion = ( elf_file_encoding != get_host_encoding() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint64_t uint64_t operator()( uint64_t value ) const
operator()( uint64_t value ) const {
if ( !need_conversion ) {
return value;
}
value = ( ( value & 0x00000000000000FFuLL ) << 56 ) |
( ( value & 0x000000000000FF00uLL ) << 40 ) |
( ( value & 0x0000000000FF0000uLL ) << 24 ) |
( ( value & 0x00000000FF000000uLL ) << 8 ) |
( ( value & 0x000000FF00000000uLL ) >> 8 ) |
( ( value & 0x0000FF0000000000uLL ) >> 24 ) |
( ( value & 0x00FF000000000000uLL ) >> 40 ) |
( ( value & 0xFF00000000000000uLL ) >> 56 );
return value;
}
//------------------------------------------------------------------------------
int64_t operator()( int64_t value ) const
{
if ( !need_conversion ) {
return value;
}
return (int64_t)( *this )( (uint64_t)value );
}
//------------------------------------------------------------------------------
uint32_t operator()( uint32_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
} }
value = value =
( ( value & 0x00000000000000FFull ) << 56 ) | ( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) |
( ( value & 0x000000000000FF00ull ) << 40 ) | ( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 );
( ( value & 0x0000000000FF0000ull ) << 24 ) |
( ( value & 0x00000000FF000000ull ) << 8 ) |
( ( value & 0x000000FF00000000ull ) >> 8 ) |
( ( value & 0x0000FF0000000000ull ) >> 24 ) |
( ( value & 0x00FF000000000000ull ) >> 40 ) |
( ( value & 0xFF00000000000000ull ) >> 56 );
return value; return value;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int64_t int32_t operator()( int32_t value ) const
operator()( int64_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
} }
return (int64_t)(*this)( (uint64_t)value ); return (int32_t)( *this )( (uint32_t)value );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint32_t uint16_t operator()( uint16_t value ) const
operator()( uint32_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
} }
value = value =
( ( value & 0x000000FF ) << 24 ) | (uint16_t)( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 );
( ( value & 0x0000FF00 ) << 8 ) |
( ( value & 0x00FF0000 ) >> 8 ) |
( ( value & 0xFF000000 ) >> 24 );
return value; return value;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int32_t int16_t operator()( int16_t value ) const
operator()( int32_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
} }
return (int32_t)(*this)( (uint32_t)value ); return (int16_t)( *this )( (uint16_t)value );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint16_t int8_t operator()( int8_t value ) const { return value; }
operator()( uint16_t value ) const
{
if ( !need_conversion ) {
return value;
}
value =
( ( value & 0x00FF ) << 8 ) |
( ( value & 0xFF00 ) >> 8 );
return value; //------------------------------------------------------------------------------
} uint8_t operator()( uint8_t value ) const { return value; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int16_t
operator()( int16_t value ) const
{
if ( !need_conversion ) {
return value;
}
return (int16_t)(*this)( (uint16_t)value );
}
//------------------------------------------------------------------------------
int8_t
operator()( int8_t value ) const
{
return value;
}
//------------------------------------------------------------------------------
uint8_t
operator()( uint8_t value ) const
{
return value;
}
//------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
unsigned char unsigned char get_host_encoding() const
get_host_encoding() const
{ {
static const int tmp = 1; static const int tmp = 1;
if ( 1 == *(const char*)&tmp ) { if ( 1 == *reinterpret_cast<const char*>( &tmp ) ) {
return ELFDATA2LSB; return ELFDATA2LSB;
} }
else { else {
@ -183,20 +154,65 @@ class endianess_convertor {
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: bool need_conversion = false;
bool need_conversion;
}; };
//------------------------------------------------------------------------------
struct address_translation
{
address_translation( uint64_t start, uint64_t size, uint64_t mapped_to )
: start( start ), size( size ), mapped_to( mapped_to ){};
std::streampos start;
std::streampos size;
std::streampos mapped_to;
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline class address_translator
uint32_t
elf_hash( const unsigned char *name )
{ {
uint32_t h = 0, g; public:
while ( *name ) { //------------------------------------------------------------------------------
h = (h << 4) + *name++; void set_address_translation( std::vector<address_translation>& addr_trans )
{
addr_translations = addr_trans;
std::sort(
addr_translations.begin(), addr_translations.end(),
[]( address_translation& a, address_translation& b ) -> bool {
return a.start < b.start;
} );
}
//------------------------------------------------------------------------------
std::streampos operator[]( std::streampos value ) const
{
if ( addr_translations.empty() ) {
return value;
}
for ( auto& t : addr_translations ) {
if ( ( t.start <= value ) && ( ( value - t.start ) < t.size ) ) {
return value - t.start + t.mapped_to;
}
}
return value;
}
bool empty() const { return addr_translations.empty(); }
private:
std::vector<address_translation> addr_translations;
};
//------------------------------------------------------------------------------
inline uint32_t elf_hash( const unsigned char* name )
{
uint32_t h = 0;
uint32_t g = 0;
while ( *name != '\0' ) {
h = ( h << 4 ) + *name++;
g = h & 0xf0000000; g = h & 0xf0000000;
if ( g != 0 ) if ( g != 0 )
h ^= g >> 24; h ^= g >> 24;
@ -205,6 +221,83 @@ elf_hash( const unsigned char *name )
return h; return h;
} }
//------------------------------------------------------------------------------
inline uint32_t elf_gnu_hash( const unsigned char* s )
{
uint32_t h = 0x1505;
for ( unsigned char c = *s; c != '\0'; c = *++s )
h = ( h << 5 ) + h + c;
return h;
}
//------------------------------------------------------------------------------
inline std::string to_hex_string( uint64_t value )
{
std::string str;
while ( value ) {
auto digit = value & 0xF;
if ( digit < 0xA ) {
str = char( '0' + digit ) + str;
}
else {
str = char( 'A' + digit - 0xA ) + str;
}
value >>= 4;
}
return "0x" + str;
}
//------------------------------------------------------------------------------
inline void adjust_stream_size( std::ostream& stream, std::streamsize offset )
{
stream.seekp( 0, std::ios_base::end );
if ( stream.tellp() < offset ) {
std::streamsize size = offset - stream.tellp();
stream.write( std::string( size_t( size ), '\0' ).c_str(), size );
}
stream.seekp( offset );
}
/**
* Consumers should write an implementation of this class and pass an instance of it to the ELFIO::elfio constructor.
*/
class compression_interface
{
public:
virtual ~compression_interface() = default;
/**
* decompresses a compressed section
*
* @param data the buffer of compressed data
* @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness.
* @param compressed_size the size of the data buffer, in bytes
* @param decompressed_size a reference to a variable where the decompressed buffer size will be stored.
* @returns a smart pointer to the decompressed data.
*/
virtual std::unique_ptr<char[]>
inflate( const char* data,
const endianess_convertor* convertor,
Elf_Xword compressed_size,
Elf_Xword& uncompressed_size ) const = 0;
/**
* compresses a section
*
* @param data the buffer of uncompressed data
* @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness.
* @param decompressed_size the size of the data buffer, in bytes
* @param compressed_size a reference to a variable where the compressed buffer size will be stored.
* @returns a smart pointer to the compressed data.
*/
virtual std::unique_ptr<char[]>
deflate( const char* data,
const endianess_convertor* convertor,
Elf_Xword decompressed_size,
Elf_Xword& compressed_size ) const = 0;
};
} // namespace ELFIO } // namespace ELFIO
#endif // ELFIO_UTILS_HPP #endif // ELFIO_UTILS_HPP

View File

@ -0,0 +1 @@
#define ELFIO_VERSION "3.12"

View File

@ -0,0 +1,179 @@
/*
Copyright (C) 2001-present by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_VERSYM_HPP
#define ELFIO_VERSYM_HPP
namespace ELFIO {
//------------------------------------------------------------------------------
template <class S> class versym_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit versym_section_accessor_template( S* section )
: versym_section( section )
{
if ( section != nullptr ) {
entries_num = decltype( entries_num )( section->get_size() /
sizeof( Elf_Half ) );
}
}
//------------------------------------------------------------------------------
Elf_Word get_entries_num() const
{
if ( versym_section ) {
return entries_num;
}
return 0;
}
//------------------------------------------------------------------------------
bool get_entry( Elf_Word no, Elf_Half& value ) const
{
if ( versym_section && ( no < get_entries_num() ) ) {
value = ( (Elf_Half*)versym_section->get_data() )[no];
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool modify_entry( Elf_Word no, Elf_Half value )
{
if ( versym_section && ( no < get_entries_num() ) ) {
( (Elf_Half*)versym_section->get_data() )[no] = value;
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool add_entry( Elf_Half value )
{
if ( !versym_section ) {
return false;
}
versym_section->append_data( (const char*)&value, sizeof( Elf_Half ) );
++entries_num;
return true;
}
//------------------------------------------------------------------------------
private:
S* versym_section = nullptr;
Elf_Word entries_num = 0;
};
using versym_section_accessor = versym_section_accessor_template<section>;
using const_versym_section_accessor =
versym_section_accessor_template<const section>;
//------------------------------------------------------------------------------
template <class S> class versym_r_section_accessor_template
{
public:
//------------------------------------------------------------------------------
versym_r_section_accessor_template( const elfio& elf_file,
S* versym_r_section )
: elf_file( elf_file ), versym_r_section( versym_r_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_VERNEEDNUM ) {
entries_num = (Elf_Word)value;
break;
}
}
}
//------------------------------------------------------------------------------
Elf_Word get_entries_num() const { return entries_num; }
//------------------------------------------------------------------------------
bool get_entry( Elf_Word no,
Elf_Half& version,
std::string& file_name,
Elf_Word& hash,
Elf_Half& flags,
Elf_Half& other,
std::string& dep_name ) const
{
if ( versym_r_section == nullptr || ( no >= get_entries_num() ) ) {
return false;
}
const_string_section_accessor string_section_acc(
elf_file.sections[versym_r_section->get_link()] );
Elfxx_Verneed* verneed = (Elfxx_Verneed*)versym_r_section->get_data();
Elfxx_Vernaux* veraux =
(Elfxx_Vernaux*)( (char*)verneed + verneed->vn_aux );
for ( Elf_Word i = 0; i < no; ++i ) {
verneed = (Elfxx_Verneed*)( (char*)verneed + verneed->vn_next );
veraux = (Elfxx_Vernaux*)( (char*)verneed + verneed->vn_aux );
}
version = verneed->vn_version;
file_name = string_section_acc.get_string( verneed->vn_file );
hash = veraux->vna_hash;
flags = veraux->vna_flags;
other = veraux->vna_other;
dep_name = string_section_acc.get_string( veraux->vna_name );
return true;
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* versym_r_section = nullptr;
Elf_Word entries_num = 0;
};
using versym_r_section_accessor = versym_r_section_accessor_template<section>;
using const_versym_r_section_accessor =
versym_r_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_VERSYM_HPP

View File

@ -18,6 +18,8 @@
#include "PluginInformationFactory.h" #include "PluginInformationFactory.h"
#include "../utils/ElfUtils.h" #include "../utils/ElfUtils.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include "utils/membuf.hpp"
#include "utils/wiiu_zlib.hpp"
#include <coreinit/cache.h> #include <coreinit/cache.h>
#include <map> #include <map>
#include <memory> #include <memory>
@ -33,8 +35,11 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr"); DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr");
return {}; return {};
} }
elfio reader; elfio reader(new wiiu_zlib);
if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) { membuf sbuf((char *) pluginData->buffer.get(), (char *) pluginData->buffer.get() + pluginData->length);
std::istream in(&sbuf);
if (!reader.load(in)) {
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
return {}; return {};
} }
@ -302,17 +307,31 @@ bool PluginInformationFactory::addImportRelocationData(const std::unique_ptr<Plu
DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str()); DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str());
relocation_section_accessor rel(reader, psec); relocation_section_accessor rel(reader, psec);
for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) { for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) {
Elf_Word symbol = 0;
Elf64_Addr offset; Elf64_Addr offset;
Elf_Word type; Elf_Word type;
Elf_Sxword addend; Elf_Sxword addend;
std::string sym_name; std::string sym_name;
Elf64_Addr sym_value; Elf64_Addr sym_value;
Elf_Half sym_section_index;
if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) { if (!rel.get_entry(j, offset, symbol, type, addend)) {
DEBUG_FUNCTION_LINE_ERR("Failed to get relocation"); DEBUG_FUNCTION_LINE_ERR("Failed to get relocation");
return false; return false;
} }
symbol_section_accessor symbols(reader, reader.sections[(Elf_Half) psec->get_link()]);
// Find the symbol
Elf_Xword size;
unsigned char bind;
unsigned char symbolType;
Elf_Half sym_section_index;
unsigned char other;
if (!symbols.get_symbol(symbol, sym_name, sym_value, size,
bind, symbolType, sym_section_index, other)) {
DEBUG_FUNCTION_LINE_ERR("Failed to get symbol");
return false;
}
auto adjusted_sym_value = (uint32_t) sym_value; auto adjusted_sym_value = (uint32_t) sym_value;
if (adjusted_sym_value < 0xC0000000) { if (adjusted_sym_value < 0xC0000000) {
@ -354,16 +373,30 @@ bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section
DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str()); DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str());
relocation_section_accessor rel(reader, psec); relocation_section_accessor rel(reader, psec);
for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) { for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) {
Elf_Word symbol = 0;
Elf64_Addr offset; Elf64_Addr offset;
Elf_Word type; Elf_Word type;
Elf_Sxword addend; Elf_Sxword addend;
std::string sym_name; std::string sym_name;
Elf64_Addr sym_value; Elf64_Addr sym_value;
Elf_Half sym_section_index;
if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) { if (!rel.get_entry(j, offset, symbol, type, addend)) {
DEBUG_FUNCTION_LINE_ERR("Failed to get relocation"); DEBUG_FUNCTION_LINE_ERR("Failed to get relocation");
break; return false;
}
symbol_section_accessor symbols(reader, reader.sections[(Elf_Half) psec->get_link()]);
// Find the symbol
Elf_Xword size;
unsigned char bind;
unsigned char symbolType;
Elf_Half sym_section_index;
unsigned char other;
if (!symbols.get_symbol(symbol, sym_name, sym_value, size,
bind, symbolType, sym_section_index, other)) {
DEBUG_FUNCTION_LINE_ERR("Failed to get symbol");
return false;
} }
auto adjusted_sym_value = (uint32_t) sym_value; auto adjusted_sym_value = (uint32_t) sym_value;

View File

@ -18,6 +18,9 @@
#include "PluginMetaInformationFactory.h" #include "PluginMetaInformationFactory.h"
#include "elfio/elfio.hpp" #include "elfio/elfio.hpp"
#include "fs/FSUtils.h" #include "fs/FSUtils.h"
#include "utils/logger.h"
#include "utils/membuf.hpp"
#include "utils/wiiu_zlib.hpp"
#include <memory> #include <memory>
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr<PluginData> &pluginData) { std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr<PluginData> &pluginData) {
@ -25,8 +28,10 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
DEBUG_FUNCTION_LINE_ERR("Buffer is empty"); DEBUG_FUNCTION_LINE_ERR("Buffer is empty");
return {}; return {};
} }
ELFIO::elfio reader; ELFIO::elfio reader(new wiiu_zlib);
if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) { membuf sbuf((char *) pluginData->buffer.get(), (char *) pluginData->buffer.get() + pluginData->length);
std::istream in(&sbuf);
if (!reader.load(in)) {
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
return {}; return {};
} }
@ -34,7 +39,7 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
} }
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::string &filePath) { std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::string &filePath) {
ELFIO::elfio reader; ELFIO::elfio reader(new wiiu_zlib);
uint8_t *buffer = nullptr; uint8_t *buffer = nullptr;
uint32_t length = 0; uint32_t length = 0;
@ -43,7 +48,10 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
return {}; return {};
} }
if (!reader.load((char *) buffer, length)) { membuf sbuf((char *) buffer, (char *) buffer + length);
std::istream in(&sbuf);
if (!reader.load(in)) {
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
return {}; return {};
} }
@ -53,8 +61,12 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
} }
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size) { std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size) {
ELFIO::elfio reader; ELFIO::elfio reader(new wiiu_zlib);
if (!reader.load(buffer, size)) {
membuf sbuf((char *) buffer, (char *) buffer + size);
std::istream in(&sbuf);
if (!reader.load(in)) {
DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file"); DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file");
return std::nullopt; return std::nullopt;
} }
@ -73,7 +85,7 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
ELFIO::section *psec = reader.sections[i]; ELFIO::section *psec = reader.sections[i];
// Calculate total size: // Calculate total size:
if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) { if ((psec->get_type() == ELFIO::SHT_PROGBITS || psec->get_type() == ELFIO::SHT_NOBITS) && (psec->get_flags() & ELFIO::SHF_ALLOC)) {
uint32_t sectionSize = psec->get_size(); uint32_t sectionSize = psec->get_size();
auto address = (uint32_t) psec->get_address(); auto address = (uint32_t) psec->get_address();
if ((address >= 0x02000000) && address < 0x10000000) { if ((address >= 0x02000000) && address < 0x10000000) {

23
source/utils/membuf.hpp Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <iostream>
struct membuf : std::streambuf {
membuf(char *begin, char *end) {
this->setg(begin, begin, end);
}
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override {
if (dir == std::ios_base::cur)
gbump(off);
else if (dir == std::ios_base::end)
setg(eback(), egptr() + off, egptr());
else if (dir == std::ios_base::beg)
setg(eback(), eback() + off, egptr());
return gptr() - eback();
}
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
}
};

119
source/utils/wiiu_zlib.hpp Normal file
View File

@ -0,0 +1,119 @@
#pragma once
/****************************************************************************
* Copyright (C) 2018-2020 Nathan Strong
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <memory>
#include "elfio/elfio_utils.hpp"
#include "logger.h"
#include "utils.h"
#include <zlib.h>
class wiiu_zlib : public ELFIO::compression_interface {
public:
std::unique_ptr<char[]> inflate(const char *data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword compressed_size, ELFIO::Elf_Xword &uncompressed_size) const override {
read_uncompressed_size(data, convertor, uncompressed_size);
auto result = make_unique_nothrow<char[]>((uint32_t) (uncompressed_size + 1));
if (result == nullptr) {
return nullptr;
}
int z_ret;
z_stream s = {nullptr};
s.zalloc = Z_NULL;
s.zfree = Z_NULL;
s.opaque = Z_NULL;
if (inflateInit_(&s, ZLIB_VERSION, sizeof(s)) != Z_OK) {
return nullptr;
}
s.avail_in = compressed_size - 4;
s.next_in = (Bytef *) data;
s.avail_out = uncompressed_size;
s.next_out = (Bytef *) result.get();
z_ret = ::inflate(&s, Z_FINISH);
inflateEnd(&s);
if (z_ret != Z_OK && z_ret != Z_STREAM_END) {
return nullptr;
}
result[uncompressed_size] = '\0';
return result;
}
std::unique_ptr<char[]> deflate(const char *data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword decompressed_size, ELFIO::Elf_Xword &compressed_size) const override {
auto result = make_unique_nothrow<char[]>((uint32_t) (decompressed_size));
if (result == nullptr) {
return nullptr;
}
int z_ret = 0;
z_stream s = {nullptr};
s.zalloc = Z_NULL;
s.zfree = Z_NULL;
s.opaque = Z_NULL;
if ((z_ret = deflateInit(&s, Z_DEFAULT_COMPRESSION)) != Z_OK) {
return nullptr;
}
s.avail_in = decompressed_size;
s.next_in = (Bytef *) data;
s.avail_out = decompressed_size - 4;
s.next_out = (Bytef *) result.get() + 4;
z_ret = ::deflate(&s, Z_FINISH);
compressed_size = decompressed_size - s.avail_out;
deflateEnd(&s);
if (z_ret != Z_OK && z_ret != Z_STREAM_END) {
compressed_size = 0;
return nullptr;
}
write_compressed_size(result, convertor, compressed_size);
result[compressed_size] = '\0';
return result;
}
private:
static void read_uncompressed_size(const char *&data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword &uncompressed_size) {
union _int32buffer {
uint32_t word;
char bytes[4];
} int32buffer;
memcpy(int32buffer.bytes, data, 4);
data += 4;
uncompressed_size = (*convertor)(int32buffer.word);
}
static void write_compressed_size(std::unique_ptr<char[]> &result, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword compressed_size) {
union _int32buffer {
uint32_t word;
char bytes[4];
} int32buffer;
int32buffer.word = (*convertor)(compressed_size);
memcpy(result.get(), int32buffer.bytes, 4);
}
};