Avoid streams in ELFIO to redcude the binary size

This commit is contained in:
Maschell 2023-01-04 17:44:14 +01:00
parent 241b5ba661
commit f4332bdadf
25 changed files with 4452 additions and 3037 deletions

View File

@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: clang-format - name: clang-format
run: | run: |
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source ./wumsloader/src docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source ./wumsloader/src --exclude ./wumsloader/src/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@v2 - uses: actions/checkout@v2
- name: clang-format - name: clang-format
run: | run: |
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source ./wumsloader/src docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source ./wumsloader/src --exclude ./wumsloader/src/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

@ -44,7 +44,7 @@ docker run -it --rm -v ${PWD}:/project wumsloader-builder make clean
## 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 ./wumsloader/src -i` `docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source ./wumsloader/src -i --exclude ./wumsloader/src/elfio -i`
## Credits ## Credits
- Maschell - Maschell

View File

@ -1,3 +1,5 @@
#include <stdint.h>
#include "../wumsloader/src/elfio/elf_types.hpp" #include "../wumsloader/src/elfio/elf_types.hpp"
#include "utils/logger.h" #include "utils/logger.h"
#include <coreinit/cache.h> #include <coreinit/cache.h>
@ -21,7 +23,7 @@ uint32_t load_loader_elf(unsigned char *baseAddress, char *elf_data, uint32_t fi
phdrs = (ELFIO::Elf32_Phdr *) (elf_data + ehdr->e_phoff); phdrs = (ELFIO::Elf32_Phdr *) (elf_data + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) { for (i = 0; i < ehdr->e_phnum; i++) {
if (phdrs[i].p_type != PT_LOAD) { if (phdrs[i].p_type != ELFIO::PT_LOAD) {
continue; continue;
} }
@ -39,7 +41,7 @@ uint32_t load_loader_elf(unsigned char *baseAddress, char *elf_data, uint32_t fi
memcpy((void *) p_paddr, image, phdrs[i].p_filesz); memcpy((void *) p_paddr, image, phdrs[i].p_filesz);
DCFlushRange((void *) p_paddr, phdrs[i].p_filesz); DCFlushRange((void *) p_paddr, phdrs[i].p_filesz);
if (phdrs[i].p_flags & PF_X) { if (phdrs[i].p_flags & ELFIO::PF_X) {
ICInvalidateRange((void *) p_paddr, phdrs[i].p_memsz); ICInvalidateRange((void *) p_paddr, phdrs[i].p_memsz);
} }
} }

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,36 +23,54 @@ 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
@ -69,15 +86,13 @@ class dynamic_section_accessor_template
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;
} }
@ -91,25 +106,21 @@ class dynamic_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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 );
} }
@ -117,24 +128,24 @@ class dynamic_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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;
@ -190,8 +201,7 @@ 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
@ -24,16 +23,16 @@ THE SOFTWARE.
#ifndef ELF_HEADER_HPP #ifndef ELF_HEADER_HPP
#define ELF_HEADER_HPP #define ELF_HEADER_HPP
#include <iostream> #include <cstring>
namespace ELFIO { 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 save( std::ostream& stream ) const = 0; virtual bool load( const char * pBuffer, size_t pBufferSize ) = 0;
// ELF header functions // ELF header functions
ELFIO_GET_ACCESS_DECL( unsigned char, class ); ELFIO_GET_ACCESS_DECL( unsigned char, class );
@ -57,29 +56,28 @@ class elf_header
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; {
typedef Elf32_Shdr Shdr_type; using Phdr_type = Elf32_Phdr;
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_, //------------------------------------------------------------------------------
elf_header_impl( endianess_convertor* convertor,
unsigned char encoding ) unsigned char encoding )
: convertor( convertor )
{ {
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;
@ -91,30 +89,26 @@ template< class T > class elf_header_impl : public elf_header
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_shentsize =
sizeof( typename elf_header_impl_types<T>::Shdr_type );
header.e_phentsize = ( *convertor )( header.e_phentsize ); header.e_phentsize = ( *convertor )( header.e_phentsize );
header.e_shentsize = ( *convertor )( header.e_shentsize ); header.e_shentsize = ( *convertor )( header.e_shentsize );
} }
bool //------------------------------------------------------------------------------
load( std::istream& stream ) bool load( const char * pBuffer, size_t pBufferSize ) override
{ {
stream.seekg( 0 ); if(sizeof( header ) > pBufferSize) {
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) ); return false;
}
memcpy( reinterpret_cast<char*>( &header ), pBuffer, sizeof( header ));
return (stream.gcount() == sizeof( header ) ); return true;
}
bool
save( std::ostream& stream ) const
{
stream.seekp( 0 );
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
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] );
@ -125,7 +119,9 @@ template< class T > class elf_header_impl : public elf_header
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,
abi_version,
header.e_ident[EI_ABIVERSION] );
ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type ); ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type );
ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine ); ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine );
ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags ); ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags );
@ -137,8 +133,8 @@ template< class T > class elf_header_impl : public elf_header
ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff ); ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
private: private:
T header; T header = {};
endianess_convertor* convertor; endianess_convertor* convertor = 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,55 +38,56 @@ 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,
void*& desc, char*& 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;
@ -96,7 +96,7 @@ class note_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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();
@ -106,6 +106,7 @@ class note_section_accessor_template
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,17 +114,17 @@ 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:
@ -131,40 +132,52 @@ class note_section_accessor_template
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
@ -51,59 +50,44 @@ template<> struct get_sym_and_type< Elf32_Rela >
}; };
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,
Elf_Word& type, unsigned& 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
@ -112,22 +96,22 @@ class relocation_section_accessor_template
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 );
} }
} }
@ -135,35 +119,109 @@ class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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,
Elf_Word& type, unsigned& type,
Elf_Sxword& addend, Elf_Sxword& addend,
Elf_Half& section) const Elf_Sxword& calcValue ) 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 ( 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 {
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 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry<Elf32_Rel>( offset, info ); generic_add_entry<Elf32_Rel>( offset, info );
@ -174,8 +232,7 @@ class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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 ) {
@ -189,8 +246,7 @@ class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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 );
@ -201,8 +257,9 @@ class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void add_entry( Elf64_Addr offset,
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type, Elf_Word symbol,
unsigned type,
Elf_Sxword addend ) Elf_Sxword addend )
{ {
Elf_Xword info; Elf_Xword info;
@ -217,8 +274,7 @@ class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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,
@ -227,7 +283,7 @@ class relocation_section_accessor_template
unsigned char other, unsigned char other,
Elf_Half shndx, Elf_Half shndx,
Elf64_Addr offset, Elf64_Addr offset,
unsigned char type ) unsigned 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,
@ -235,22 +291,38 @@ class relocation_section_accessor_template
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,
Elf_Word& type, unsigned& 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();
@ -267,11 +339,10 @@ class relocation_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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,
Elf_Word& type, unsigned& 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();
@ -288,18 +359,70 @@ class relocation_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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 ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -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
@ -25,17 +24,17 @@ THE SOFTWARE.
#define ELFIO_SECTION_HPP #define ELFIO_SECTION_HPP
#include <string> #include <string>
#include <iostream> #include <new>
#include "utils/logger.h" #include <limits>
#include <zlib.h>
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 );
@ -49,53 +48,33 @@ class section
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)
{
stream_size = value;
}
virtual const char* get_data() const = 0; virtual const char* get_data() const = 0;
virtual void set_data( const char* pData, Elf_Word size ) = 0; virtual void set_data( const char* raw_data, Elf_Word size ) = 0;
virtual void set_data( const std::string& data ) = 0; virtual void set_data( const std::string& data ) = 0;
virtual void append_data( const char* pData, Elf_Word size ) = 0; virtual void append_data( const char* raw_data, Elf_Word size ) = 0;
virtual void append_data( const std::string& data ) = 0; virtual void append_data( const std::string& data ) = 0;
virtual void
insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) = 0;
virtual void insert_data( Elf_Xword pos, const std::string& data ) = 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( const char * pBuffer, size_t pBufferSize,
std::streampos header_offset ) = 0; off_t header_offset) = 0;
virtual void save( std::ostream& stream,
std::streampos header_offset,
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 std::shared_ptr<compression_interface>& compression )
: convertor( convertor ), 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;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -109,94 +88,97 @@ class section_impl : public section
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; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half std::string get_name() const override { return name; }
get_index() const
{
return index;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
std::string void set_name( const std::string& name_prm ) override
get_name() const
{ {
return name; this->name = name_prm;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void set_address( const Elf64_Addr& value ) override
set_name( std::string name_ )
{ {
name = name_; header.sh_addr = decltype( header.sh_addr )( value );
}
//------------------------------------------------------------------------------
void
set_address( Elf64_Addr value )
{
header.sh_addr = value;
header.sh_addr = ( *convertor )( header.sh_addr ); 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; 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 );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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 append_data( const char* raw_data, Elf_Word size ) override
{
insert_data( get_size(), raw_data, size );
}
//------------------------------------------------------------------------------
void append_data( const std::string& str_data ) override
{
return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
append_data( const char* raw_data, Elf_Word size ) insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) override
{ {
if ( get_type() != SHT_NOBITS ) { if ( get_type() != SHT_NOBITS ) {
if ( get_size() + size < data_size ) { if ( get_size() + size < data_size ) {
std::copy( raw_data, raw_data + size, data + get_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 { else {
data_size = 2 * ( data_size + size ); data_size = 2 * ( data_size + size );
char* new_data; std::unique_ptr<char[]> new_data(
new_data = new char[data_size]; new ( std::nothrow ) char[data_size] );
if ( 0 != new_data ) { if ( nullptr != new_data ) {
std::copy( data, data + get_size(), new_data ); char* d = data.get();
std::copy( raw_data, raw_data + size, new_data + get_size() ); std::copy( d, d + pos, new_data.get() );
delete [] data; std::copy( raw_data, raw_data + size,
data = new_data; new_data.get() + pos );
std::copy( d + pos, d + get_size(),
new_data.get() + pos + size );
data = std::move( new_data );
}
else {
size = 0;
} }
} }
set_size( get_size() + size ); set_size( get_size() + size );
@ -204,10 +186,9 @@ class section_impl : public section
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void insert_data( Elf_Xword pos, 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 insert_data( pos, str_data.c_str(), (Elf_Word)str_data.size() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -216,134 +197,85 @@ class section_impl : public section
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void set_index( const Elf_Half& value ) override { index = value; }
set_index( Elf_Half value )
bool is_compressed() const
{ {
index = value; return ( ( get_flags() & SHF_RPX_DEFLATE ) ||
( get_flags() & SHF_COMPRESSED ) ) &&
compression != nullptr;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void bool load( const char * pBuffer, size_t pBufferSize,
load( std::istream& stream, off_t header_offset) override
std::streampos header_offset )
{ {
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' ); header = { };
stream.seekg ( 0, stream.end ); if( header_offset + sizeof( header ) > pBufferSize ) {
set_stream_size ( stream.tellg() ); return false;
}
stream.seekg( header_offset ); memcpy( reinterpret_cast<char*>( &header ), pBuffer + header_offset, sizeof( header ) );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
bool ret = load_data(pBuffer, pBufferSize);
if (ret && is_compressed() ) {
Elf_Xword size = get_size(); Elf_Xword size = get_size();
if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size()) { Elf_Xword uncompressed_size = 0;
auto decompressed_data = compression->inflate(
data = new char[size + 1]; data.get(), convertor, size, uncompressed_size );
if ( decompressed_data != nullptr ) {
if ( ( 0 != size ) && ( 0 != data ) ) { set_size( uncompressed_size );
stream.seekg( (*convertor)( header.sh_offset ) ); data = std::move( decompressed_data );
if (get_flags() & 0x08000000){
uint32_t decompressed_size = size;
stream.read( (char *) &decompressed_size, 4);
stream.read( data, size - 4);
char* decompressedData = new (std::nothrow) char[decompressed_size + 1];
if(!decompressedData) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocated memory for decompressing the section");
OSFatal("Failed to allocated memory for decompressing the section");
}
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 = decompressed_size;
s.next_out = (Bytef *)&decompressedData[0];
ret = inflate(&s, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END){
DEBUG_FUNCTION_LINE_ERR("inflate section failed.");
}
inflateEnd(&s);
delete [] data;
data = decompressedData;
data_size = decompressed_size;
set_size(decompressed_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{
set_size(0);
DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory.");
} }
} }
return ret;
} }
//------------------------------------------------------------------------------ bool load_data(const char * pBuffer, size_t pBufferSize) const
void
save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset )
{ {
if ( 0 != get_index() ) { Elf_Xword size = get_size();
header.sh_offset = data_offset; if ( nullptr == data && SHT_NULL != get_type() &&
header.sh_offset = (*convertor)( header.sh_offset ); SHT_NOBITS != get_type() && size < pBufferSize ) {
data.reset( new ( std::nothrow ) char[size_t( size ) + 1] );
if ( ( 0 != size ) && ( nullptr != data ) ) {
auto offset = ( *convertor )( header.sh_offset );
if(offset + size > pBufferSize) {
data = nullptr;
return false;
}
memcpy( data.get(), pBuffer + offset, size );
// 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;
}
} }
save_header( stream, header_offset ); return true;
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
get_size() != 0 && data != 0 ) {
save_data( stream, data_offset );
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ private:
void
save_header( std::ostream& stream,
std::streampos header_offset ) const
{
stream.seekp( header_offset );
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
}
//------------------------------------------------------------------------------
void
save_data( std::ostream& stream,
std::streampos data_offset ) const
{
stream.seekp( data_offset );
stream.write( get_data(), get_size() );
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
T header; T header = {};
Elf_Half index; Elf_Half index = 0;
std::string name; std::string name;
char* data; mutable std::unique_ptr<char[]> data;
Elf_Word data_size; mutable Elf_Word data_size = 0;
const endianess_convertor* convertor; const endianess_convertor* convertor = nullptr;
bool is_address_set; const std::shared_ptr<compression_interface> compression = nullptr;
bool is_address_set = 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
@ -24,16 +23,18 @@ THE SOFTWARE.
#ifndef ELFIO_SEGMENT_HPP #ifndef ELFIO_SEGMENT_HPP
#define ELFIO_SEGMENT_HPP #define ELFIO_SEGMENT_HPP
#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: public:
virtual ~segment() {}; virtual ~segment() = default;
ELFIO_GET_ACCESS_DECL( Elf_Half, index ); ELFIO_GET_ACCESS_DECL( Elf_Half, index );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
@ -47,7 +48,9 @@ class segment
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 add_section_index( Elf_Half index,
Elf_Xword addr_align ) = 0;
virtual Elf_Half get_sections_num() const = 0; virtual Elf_Half get_sections_num() const = 0;
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
virtual bool is_offset_initialized() const = 0; virtual bool is_offset_initialized() const = 0;
@ -57,29 +60,19 @@ class segment
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( const char * pBuffer, size_t pBufferSize,
std::streampos data_offset ) = 0; off_t header_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_ ) : convertor( convertor )
{ {
is_offset_set = false;
std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' );
}
//------------------------------------------------------------------------------
virtual ~segment_impl()
{
delete [] data;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -92,41 +85,21 @@ class segment_impl : public segment
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; 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 );
} }
@ -135,15 +108,19 @@ class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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];
@ -157,85 +134,73 @@ class segment_impl : public segment
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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 )
{
index = value;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void bool load( const char * pBuffer, size_t pBufferSize,
load( std::istream& stream, off_t header_offset) override
std::streampos header_offset )
{ {
if( header_offset + sizeof( ph ) > pBufferSize ) {
stream.seekg ( 0, stream.end ); return false;
set_stream_size ( stream.tellg() ); }
memcpy( reinterpret_cast<char*>( &ph ), pBuffer + header_offset, sizeof( ph ) );
stream.seekg( header_offset );
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() ) { return load_data(pBuffer, pBufferSize);
stream.seekg( (*convertor)( ph.p_offset ) );
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;
}
}
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void save( std::ostream& stream, bool load_data(const char * pBuffer, size_t pBufferSize) const
std::streampos header_offset,
std::streampos data_offset )
{ {
ph.p_offset = data_offset; if ( PT_NULL == get_type() || 0 == get_file_size() ) {
ph.p_offset = (*convertor)(ph.p_offset); return true;
stream.seekp( header_offset ); }
stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) ); auto offset = ( *convertor )( ph.p_offset );
Elf_Xword size = get_file_size();
if ( size > pBufferSize ) {
data = nullptr;
}
else {
data.reset( new ( std::nothrow ) char[(size_t)size + 1] );
if ( nullptr != data.get()) {
memcpy(data.get(), pBuffer + offset, size);
}
else {
data = nullptr;
return false;
}
}
return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
T ph; T ph = {};
Elf_Half index; Elf_Half index = 0;
char* data; mutable std::unique_ptr<char[]> data;
std::vector<Elf_Half> sections; std::vector<Elf_Half> sections;
endianess_convertor* convertor; const endianess_convertor* convertor = nullptr;
bool is_offset_set; bool is_offset_set = 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,59 +30,55 @@ 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* const char* get_string( Elf_Word index ) const
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 ( 0 != data ) { if ( index < string_section->get_size() && nullptr != 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 Elf_Word add_string( const char* str )
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 Elf_Word add_string( const std::string& str )
add_string( const std::string& str )
{ {
return add_string( str.c_str() ); return add_string( str.c_str() );
} }
@ -94,7 +89,8 @@ class string_section_accessor_template
}; };
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,33 +26,44 @@ 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 ) {
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,
@ -77,8 +87,7 @@ class symbol_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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,
@ -89,32 +98,83 @@ class symbol_section_accessor_template
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 ||
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; 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,
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_Half shndx )
{ {
Elf_Word nRet; Elf_Word nRet;
@ -129,31 +189,37 @@ 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,
unsigned char bind,
unsigned char type,
unsigned char other,
Elf_Half shndx ) 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,
unsigned char info,
unsigned char other,
Elf_Half shndx ) Elf_Half shndx )
{ {
Elf_Word index = pStrWriter.add_string( str ); Elf_Word index = pStrWriter.add_string( str );
@ -161,70 +227,230 @@ class symbol_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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,
unsigned char bind,
unsigned char type,
unsigned char other,
Elf_Half shndx ) 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 );
}
//------------------------------------------------------------------------------
Elf_Xword arrange_local_symbols(
std::function<void( Elf_Xword first, Elf_Xword second )> func =
nullptr )
{
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: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void find_hash_section()
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& type, unsigned char& bind,
unsigned char& type,
Elf_Half& section_index,
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, Elf_Half& section_index,
unsigned char& other ) const 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 );
@ -242,18 +468,20 @@ class symbol_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
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,
unsigned char info,
unsigned char other,
Elf_Half shndx ) 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 +490,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,79 +23,66 @@ 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 \
{ \
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 ) { if ( !need_conversion ) {
return value; return value;
} }
value = value = ( ( value & 0x00000000000000FFuLL ) << 56 ) |
( ( value & 0x00000000000000FFull ) << 56 ) | ( ( value & 0x000000000000FF00uLL ) << 40 ) |
( ( value & 0x000000000000FF00ull ) << 40 ) | ( ( value & 0x0000000000FF0000uLL ) << 24 ) |
( ( value & 0x0000000000FF0000ull ) << 24 ) | ( ( value & 0x00000000FF000000uLL ) << 8 ) |
( ( value & 0x00000000FF000000ull ) << 8 ) | ( ( value & 0x000000FF00000000uLL ) >> 8 ) |
( ( value & 0x000000FF00000000ull ) >> 8 ) | ( ( value & 0x0000FF0000000000uLL ) >> 24 ) |
( ( value & 0x0000FF0000000000ull ) >> 24 ) | ( ( value & 0x00FF000000000000uLL ) >> 40 ) |
( ( value & 0x00FF000000000000ull ) >> 40 ) | ( ( value & 0xFF00000000000000uLL ) >> 56 );
( ( value & 0xFF00000000000000ull ) >> 56 );
return value; return value;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int64_t int64_t operator()( int64_t value ) const
operator()( int64_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
@ -105,24 +91,20 @@ class endianess_convertor {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint32_t uint32_t operator()( uint32_t value ) const
operator()( uint32_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
} }
value = value =
( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) |
( ( value & 0x0000FF00 ) << 8 ) | ( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 );
( ( value & 0x00FF0000 ) >> 8 ) |
( ( value & 0xFF000000 ) >> 24 );
return value; return value;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int32_t int32_t operator()( int32_t value ) const
operator()( int32_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
@ -131,22 +113,19 @@ class endianess_convertor {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint16_t uint16_t operator()( uint16_t value ) const
operator()( uint16_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
} }
value = value =
( ( value & 0x00FF ) << 8 ) | (uint16_t)( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 );
( ( value & 0xFF00 ) >> 8 );
return value; return value;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int16_t int16_t operator()( int16_t value ) const
operator()( int16_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
return value; return value;
@ -155,27 +134,18 @@ class endianess_convertor {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int8_t int8_t operator()( int8_t value ) const { return value; }
operator()( int8_t value ) const
{
return value;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint8_t uint8_t operator()( uint8_t value ) const { return value; }
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 {
@ -184,18 +154,15 @@ class endianess_convertor {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: bool need_conversion = false;
bool need_conversion;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline inline uint32_t elf_hash( const unsigned char* name )
uint32_t
elf_hash( const unsigned char *name )
{ {
uint32_t h = 0, g; uint32_t h = 0;
while ( *name ) { uint32_t g = 0;
while ( *name != '\0' ) {
h = ( h << 4 ) + *name++; h = ( h << 4 ) + *name++;
g = h & 0xf0000000; g = h & 0xf0000000;
if ( g != 0 ) if ( g != 0 )
@ -205,6 +172,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,7 +18,7 @@ extern std::vector<void *> gAllocatedAddresses;
#define MEMORY_REGION_SIZE 0x00800000 #define MEMORY_REGION_SIZE 0x00800000
#define CUSTOM_RPX_LOADER_RETURN_CODE 0x00009000 // We have to skip the first 0x00009000 bytes because it's still used #define CUSTOM_RPX_LOADER_RETURN_CODE 0x00009000 // We have to skip the first 0x00009000 bytes because it's still used
#define RELOCATOR_SIZE 0x0E0000 // Maximum size of the wumsloader, needs to match the one defined in link.ld #define RELOCATOR_SIZE 0x52000 // Maximum size of the wumsloader, needs to match the one defined in link.ld
#define ENVIRONMENT_PATH_LENGTH 0x100 // Length of the EnvironmentPath. #define ENVIRONMENT_PATH_LENGTH 0x100 // Length of the EnvironmentPath.
#define MEMORY_REGION_ENVIRONMENT_STRING_ADRR (MEMORY_REGION_START + CUSTOM_RPX_LOADER_RETURN_CODE + RELOCATOR_SIZE) #define MEMORY_REGION_ENVIRONMENT_STRING_ADRR (MEMORY_REGION_START + CUSTOM_RPX_LOADER_RETURN_CODE + RELOCATOR_SIZE)

View File

@ -92,4 +92,4 @@ SECTIONS {
} }
} }
ASSERT((SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata) + SIZEOF(.eh_frame) + SIZEOF(.bss)) < 0x0E0000, "Memory overlapping with modules."); ASSERT((SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata) + SIZEOF(.eh_frame) + SIZEOF(.bss)) < 0x52000, "Memory overlapping with modules.");

View File

@ -21,6 +21,7 @@
#include "utils/OnLeavingScope.h" #include "utils/OnLeavingScope.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "utils/wiiu_zlib.hpp"
#include <coreinit/cache.h> #include <coreinit/cache.h>
#include <coreinit/memdefaultheap.h> #include <coreinit/memdefaultheap.h>
#include <map> #include <map>
@ -30,7 +31,7 @@
using namespace ELFIO; using namespace ELFIO;
std::optional<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::string &path) { std::optional<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::string &path) {
elfio reader; elfio reader(new wiiu_zlib);
auto moduleData = make_shared_nothrow<ModuleData>(); auto moduleData = make_shared_nothrow<ModuleData>();
if (!moduleData) { if (!moduleData) {
DEBUG_FUNCTION_LINE_ERR("Failed to alloc module data"); DEBUG_FUNCTION_LINE_ERR("Failed to alloc module data");
@ -349,17 +350,30 @@ bool ModuleDataFactory::getImportRelocationData(std::shared_ptr<ModuleData> &mod
if (psec->get_type() == SHT_RELA || psec->get_type() == SHT_REL) { if (psec->get_type() == SHT_RELA || psec->get_type() == SHT_REL) {
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");
OSFatal("Failed to get relocation"); return false;
break; }
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;
@ -402,17 +416,31 @@ bool ModuleDataFactory::linkSection(elfio &reader, uint32_t section_index, uint3
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 >= 0x02000000) && adjusted_sym_value < 0x10000000) { if ((adjusted_sym_value >= 0x02000000) && adjusted_sym_value < 0x10000000) {

View File

@ -4,7 +4,6 @@
#include "memory.h" #include "memory.h"
#include <algorithm> #include <algorithm>
#include <coreinit/cache.h> #include <coreinit/cache.h>
#include <iostream>
#include <iterator> #include <iterator>
#include <malloc.h> #include <malloc.h>
#include <vector> #include <vector>

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 = {};
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;
z_stream s = {};
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);
}
};