mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2024-11-18 02:39:20 +01:00
Update to latest ELFIO and undo any changes directly to ELFIO
This commit is contained in:
parent
ae06a5db31
commit
c9ccf0f657
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
run: |
|
run: |
|
||||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio
|
||||||
build-binary:
|
build-binary:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: clang-format
|
needs: clang-format
|
||||||
|
2
.github/workflows/pr.yml
vendored
2
.github/workflows/pr.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
run: |
|
run: |
|
||||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source
|
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio
|
||||||
check-build-with-logging:
|
check-build-with-logging:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: clang-format
|
needs: clang-format
|
||||||
|
@ -62,7 +62,7 @@ docker run -it --rm -v ${PWD}:/project wiiupluginloaderbackend-builder make clea
|
|||||||
|
|
||||||
## Format the code via docker
|
## Format the code via docker
|
||||||
|
|
||||||
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source -i`
|
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio -i`
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
- Maschell
|
- Maschell
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
88
source/elfio/elfio_array.hpp
Normal file
88
source/elfio/elfio_array.hpp
Normal 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
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,60 +23,76 @@ THE SOFTWARE.
|
|||||||
#ifndef ELFIO_DYNAMIC_HPP
|
#ifndef ELFIO_DYNAMIC_HPP
|
||||||
#define ELFIO_DYNAMIC_HPP
|
#define ELFIO_DYNAMIC_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace ELFIO {
|
namespace ELFIO {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class S >
|
template <class S> class dynamic_section_accessor_template
|
||||||
class dynamic_section_accessor_template
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
dynamic_section_accessor_template( const elfio& elf_file_, S* section_ ) :
|
explicit dynamic_section_accessor_template( const elfio& elf_file,
|
||||||
elf_file( elf_file_ ),
|
S* section )
|
||||||
dynamic_section( section_ )
|
: elf_file( elf_file ), dynamic_section( section ), entries_num( 0 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Xword
|
Elf_Xword get_entries_num() const
|
||||||
get_entries_num() const
|
|
||||||
{
|
{
|
||||||
Elf_Xword nRet = 0;
|
size_t needed_entry_size = -1;
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
if ( 0 != dynamic_section->get_entry_size() ) {
|
needed_entry_size = sizeof( Elf32_Dyn );
|
||||||
nRet = dynamic_section->get_size() / dynamic_section->get_entry_size();
|
}
|
||||||
|
else {
|
||||||
|
needed_entry_size = sizeof( Elf64_Dyn );
|
||||||
}
|
}
|
||||||
|
|
||||||
return nRet;
|
if ( ( 0 == entries_num ) &&
|
||||||
|
( 0 != dynamic_section->get_entry_size() &&
|
||||||
|
dynamic_section->get_entry_size() >= needed_entry_size ) ) {
|
||||||
|
entries_num =
|
||||||
|
dynamic_section->get_size() / dynamic_section->get_entry_size();
|
||||||
|
Elf_Xword i;
|
||||||
|
Elf_Xword tag = DT_NULL;
|
||||||
|
Elf_Xword value = 0;
|
||||||
|
std::string str;
|
||||||
|
for ( i = 0; i < entries_num; i++ ) {
|
||||||
|
get_entry( i, tag, value, str );
|
||||||
|
if ( tag == DT_NULL )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entries_num = std::min<Elf_Xword>( entries_num, i + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool get_entry( Elf_Xword index,
|
||||||
get_entry( Elf_Xword index,
|
Elf_Xword& tag,
|
||||||
Elf_Xword& tag,
|
Elf_Xword& value,
|
||||||
Elf_Xword& value,
|
std::string& str ) const
|
||||||
std::string& str ) const
|
|
||||||
{
|
{
|
||||||
if ( index >= get_entries_num() ) { // Is index valid
|
if ( index >= get_entries_num() ) { // Is index valid
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
generic_get_entry_dyn< Elf32_Dyn >( index, tag, value );
|
generic_get_entry_dyn<Elf32_Dyn>( index, tag, value );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generic_get_entry_dyn< Elf64_Dyn >( index, tag, value );
|
generic_get_entry_dyn<Elf64_Dyn>( index, tag, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the tag may have a string table reference, prepare the string
|
// If the tag has a string table reference - prepare the string
|
||||||
if ( tag == DT_NEEDED ||
|
if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH ||
|
||||||
tag == DT_SONAME ||
|
|
||||||
tag == DT_RPATH ||
|
|
||||||
tag == DT_RUNPATH ) {
|
tag == DT_RUNPATH ) {
|
||||||
string_section_accessor strsec =
|
string_section_accessor strsec(
|
||||||
elf_file.sections[ get_string_table_index() ];
|
elf_file.sections[get_string_table_index()] );
|
||||||
const char* result = strsec.get_string( value );
|
const char* result = strsec.get_string( (Elf_Word)value );
|
||||||
if ( 0 == result ) {
|
if ( nullptr == result ) {
|
||||||
str.clear();
|
str.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -90,59 +105,55 @@ class dynamic_section_accessor_template
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void add_entry( Elf_Xword tag, Elf_Xword value )
|
||||||
add_entry( Elf_Xword tag,
|
|
||||||
Elf_Xword value )
|
|
||||||
{
|
{
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
generic_add_entry< Elf32_Dyn >( tag, value );
|
generic_add_entry_dyn<Elf32_Dyn>( tag, value );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generic_add_entry< Elf64_Dyn >( tag, value );
|
generic_add_entry_dyn<Elf64_Dyn>( tag, value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void add_entry( Elf_Xword tag, const std::string& str )
|
||||||
add_entry( Elf_Xword tag,
|
|
||||||
const std::string& str )
|
|
||||||
{
|
{
|
||||||
string_section_accessor strsec =
|
string_section_accessor strsec(
|
||||||
elf_file.sections[ get_string_table_index() ];
|
elf_file.sections[get_string_table_index()] );
|
||||||
Elf_Xword value = strsec.add_string( str );
|
Elf_Xword value = strsec.add_string( str );
|
||||||
add_entry( tag, value );
|
add_entry( tag, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Half
|
Elf_Half get_string_table_index() const
|
||||||
get_string_table_index() const
|
|
||||||
{
|
{
|
||||||
return (Elf_Half)dynamic_section->get_link();
|
return (Elf_Half)dynamic_section->get_link();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
void
|
void generic_get_entry_dyn( Elf_Xword index,
|
||||||
generic_get_entry_dyn( Elf_Xword index,
|
Elf_Xword& tag,
|
||||||
Elf_Xword& tag,
|
Elf_Xword& value ) const
|
||||||
Elf_Xword& value ) const
|
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
// Check unusual case when dynamic section has no data
|
// Check unusual case when dynamic section has no data
|
||||||
if( dynamic_section->get_data() == 0 ||
|
if ( dynamic_section->get_data() == nullptr ||
|
||||||
( index + 1 ) * dynamic_section->get_entry_size() > dynamic_section->get_size() ) {
|
( index + 1 ) * dynamic_section->get_entry_size() >
|
||||||
|
dynamic_section->get_size() ||
|
||||||
|
dynamic_section->get_entry_size() < sizeof( T ) ) {
|
||||||
tag = DT_NULL;
|
tag = DT_NULL;
|
||||||
value = 0;
|
value = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* pEntry = reinterpret_cast<const T*>(
|
const T* pEntry = reinterpret_cast<const T*>(
|
||||||
dynamic_section->get_data() +
|
dynamic_section->get_data() +
|
||||||
index * dynamic_section->get_entry_size() );
|
index * dynamic_section->get_entry_size() );
|
||||||
tag = convertor( pEntry->d_tag );
|
tag = convertor( pEntry->d_tag );
|
||||||
switch ( tag ) {
|
switch ( tag ) {
|
||||||
case DT_NULL:
|
case DT_NULL:
|
||||||
@ -188,10 +199,9 @@ class dynamic_section_accessor_template
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
void
|
void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value )
|
||||||
generic_add_entry( Elf_Xword tag, Elf_Xword value )
|
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
@ -202,7 +212,8 @@ class dynamic_section_accessor_template
|
|||||||
case DT_SYMBOLIC:
|
case DT_SYMBOLIC:
|
||||||
case DT_TEXTREL:
|
case DT_TEXTREL:
|
||||||
case DT_BIND_NOW:
|
case DT_BIND_NOW:
|
||||||
value = 0;
|
entry.d_un.d_val = convertor( decltype( entry.d_un.d_val )( 0 ) );
|
||||||
|
break;
|
||||||
case DT_NEEDED:
|
case DT_NEEDED:
|
||||||
case DT_PLTRELSZ:
|
case DT_PLTRELSZ:
|
||||||
case DT_RELASZ:
|
case DT_RELASZ:
|
||||||
@ -219,7 +230,8 @@ class dynamic_section_accessor_template
|
|||||||
case DT_RUNPATH:
|
case DT_RUNPATH:
|
||||||
case DT_FLAGS:
|
case DT_FLAGS:
|
||||||
case DT_PREINIT_ARRAYSZ:
|
case DT_PREINIT_ARRAYSZ:
|
||||||
entry.d_un.d_val = convertor( value );
|
entry.d_un.d_val =
|
||||||
|
convertor( decltype( entry.d_un.d_val )( value ) );
|
||||||
break;
|
break;
|
||||||
case DT_PLTGOT:
|
case DT_PLTGOT:
|
||||||
case DT_HASH:
|
case DT_HASH:
|
||||||
@ -235,23 +247,27 @@ class dynamic_section_accessor_template
|
|||||||
case DT_FINI_ARRAY:
|
case DT_FINI_ARRAY:
|
||||||
case DT_PREINIT_ARRAY:
|
case DT_PREINIT_ARRAY:
|
||||||
default:
|
default:
|
||||||
entry.d_un.d_ptr = convertor( value );
|
entry.d_un.d_ptr =
|
||||||
|
convertor( decltype( entry.d_un.d_val )( value ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.d_tag = convertor( tag );
|
entry.d_tag = convertor( decltype( entry.d_tag )( tag ) );
|
||||||
|
|
||||||
dynamic_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
|
dynamic_section->append_data( reinterpret_cast<char*>( &entry ),
|
||||||
|
sizeof( entry ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
const elfio& elf_file;
|
const elfio& elf_file;
|
||||||
S* dynamic_section;
|
S* dynamic_section;
|
||||||
|
mutable Elf_Xword entries_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
using dynamic_section_accessor = dynamic_section_accessor_template<section>;
|
using dynamic_section_accessor = dynamic_section_accessor_template<section>;
|
||||||
using const_dynamic_section_accessor = dynamic_section_accessor_template<const section>;
|
using const_dynamic_section_accessor =
|
||||||
|
dynamic_section_accessor_template<const section>;
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -31,55 +30,56 @@ namespace ELFIO {
|
|||||||
class elf_header
|
class elf_header
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~elf_header() {};
|
virtual ~elf_header() = default;
|
||||||
|
|
||||||
virtual bool load( std::istream& stream ) = 0;
|
virtual bool load( std::istream& stream ) = 0;
|
||||||
virtual bool save( std::ostream& stream ) const = 0;
|
virtual bool save( std::ostream& stream ) const = 0;
|
||||||
|
|
||||||
// ELF header functions
|
// ELF header functions
|
||||||
ELFIO_GET_ACCESS_DECL( unsigned char, class );
|
ELFIO_GET_ACCESS_DECL( unsigned char, class );
|
||||||
ELFIO_GET_ACCESS_DECL( unsigned char, elf_version );
|
ELFIO_GET_ACCESS_DECL( unsigned char, elf_version );
|
||||||
ELFIO_GET_ACCESS_DECL( unsigned char, encoding );
|
ELFIO_GET_ACCESS_DECL( unsigned char, encoding );
|
||||||
ELFIO_GET_ACCESS_DECL( Elf_Half, header_size );
|
ELFIO_GET_ACCESS_DECL( Elf_Half, header_size );
|
||||||
ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size );
|
ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size );
|
||||||
ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size );
|
ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size );
|
||||||
|
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi );
|
ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version );
|
ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry );
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset );
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset );
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> struct elf_header_impl_types;
|
||||||
template< class T > struct elf_header_impl_types;
|
template <> struct elf_header_impl_types<Elf32_Ehdr>
|
||||||
template<> struct elf_header_impl_types<Elf32_Ehdr> {
|
{
|
||||||
typedef Elf32_Phdr Phdr_type;
|
using Phdr_type = Elf32_Phdr;
|
||||||
typedef Elf32_Shdr Shdr_type;
|
using Shdr_type = Elf32_Shdr;
|
||||||
static const unsigned char file_class = ELFCLASS32;
|
static const unsigned char file_class = ELFCLASS32;
|
||||||
};
|
};
|
||||||
template<> struct elf_header_impl_types<Elf64_Ehdr> {
|
template <> struct elf_header_impl_types<Elf64_Ehdr>
|
||||||
typedef Elf64_Phdr Phdr_type;
|
{
|
||||||
typedef Elf64_Shdr Shdr_type;
|
using Phdr_type = Elf64_Phdr;
|
||||||
|
using Shdr_type = Elf64_Shdr;
|
||||||
static const unsigned char file_class = ELFCLASS64;
|
static const unsigned char file_class = ELFCLASS64;
|
||||||
};
|
};
|
||||||
|
|
||||||
template< class T > class elf_header_impl : public elf_header
|
template <class T> class elf_header_impl : public elf_header
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
elf_header_impl( endianess_convertor* convertor_,
|
//------------------------------------------------------------------------------
|
||||||
unsigned char encoding )
|
elf_header_impl( endianess_convertor* convertor,
|
||||||
|
unsigned char encoding,
|
||||||
|
const address_translator* translator )
|
||||||
|
: convertor( convertor ), translator( translator )
|
||||||
{
|
{
|
||||||
convertor = convertor_;
|
|
||||||
|
|
||||||
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
|
|
||||||
|
|
||||||
header.e_ident[EI_MAG0] = ELFMAG0;
|
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||||
header.e_ident[EI_MAG1] = ELFMAG1;
|
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||||
header.e_ident[EI_MAG2] = ELFMAG2;
|
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||||
@ -87,58 +87,65 @@ template< class T > class elf_header_impl : public elf_header
|
|||||||
header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class;
|
header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class;
|
||||||
header.e_ident[EI_DATA] = encoding;
|
header.e_ident[EI_DATA] = encoding;
|
||||||
header.e_ident[EI_VERSION] = EV_CURRENT;
|
header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||||
header.e_version = (*convertor)( (Elf_Word)EV_CURRENT );
|
header.e_version = ( *convertor )( (Elf_Word)EV_CURRENT );
|
||||||
header.e_ehsize = ( sizeof( header ) );
|
header.e_ehsize = ( sizeof( header ) );
|
||||||
header.e_ehsize = (*convertor)( header.e_ehsize );
|
header.e_ehsize = ( *convertor )( header.e_ehsize );
|
||||||
header.e_shstrndx = (*convertor)( (Elf_Half)1 );
|
header.e_shstrndx = ( *convertor )( (Elf_Half)1 );
|
||||||
header.e_phentsize = sizeof( typename elf_header_impl_types<T>::Phdr_type );
|
header.e_phentsize =
|
||||||
header.e_shentsize = sizeof( typename elf_header_impl_types<T>::Shdr_type );
|
sizeof( typename elf_header_impl_types<T>::Phdr_type );
|
||||||
header.e_phentsize = (*convertor)( header.e_phentsize );
|
header.e_shentsize =
|
||||||
header.e_shentsize = (*convertor)( header.e_shentsize );
|
sizeof( typename elf_header_impl_types<T>::Shdr_type );
|
||||||
|
header.e_phentsize = ( *convertor )( header.e_phentsize );
|
||||||
|
header.e_shentsize = ( *convertor )( header.e_shentsize );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
//------------------------------------------------------------------------------
|
||||||
load( std::istream& stream )
|
bool load( std::istream& stream ) override
|
||||||
{
|
{
|
||||||
stream.seekg( 0 );
|
stream.seekg( ( *translator )[0] );
|
||||||
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
||||||
|
|
||||||
return (stream.gcount() == sizeof( header ) );
|
return ( stream.gcount() == sizeof( header ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
//------------------------------------------------------------------------------
|
||||||
save( std::ostream& stream ) const
|
bool save( std::ostream& stream ) const override
|
||||||
{
|
{
|
||||||
stream.seekp( 0 );
|
stream.seekp( ( *translator )[0] );
|
||||||
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
|
stream.write( reinterpret_cast<const char*>( &header ),
|
||||||
|
sizeof( header ) );
|
||||||
|
|
||||||
return stream.good();
|
return stream.good();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
// ELF header functions
|
// ELF header functions
|
||||||
ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] );
|
ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] );
|
||||||
ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] );
|
ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] );
|
||||||
ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] );
|
ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] );
|
||||||
ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize );
|
ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize );
|
||||||
ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize );
|
ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize );
|
||||||
ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize );
|
ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize );
|
||||||
|
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version);
|
ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version );
|
||||||
ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] );
|
ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] );
|
||||||
ELFIO_GET_SET_ACCESS( unsigned char, abi_version, header.e_ident[EI_ABIVERSION] );
|
ELFIO_GET_SET_ACCESS( unsigned char,
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type );
|
abi_version,
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine );
|
header.e_ident[EI_ABIVERSION] );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags );
|
ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx );
|
ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine );
|
||||||
ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry );
|
ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum );
|
ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx );
|
||||||
ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff );
|
ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum );
|
ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum );
|
||||||
ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
|
ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T header;
|
T header = {};
|
||||||
endianess_convertor* convertor;
|
endianess_convertor* convertor = nullptr;
|
||||||
|
const address_translator* translator = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
124
source/elfio/elfio_modinfo.hpp
Normal file
124
source/elfio/elfio_modinfo.hpp
Normal 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
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -39,73 +38,75 @@ namespace ELFIO {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class S >
|
template <class S, Elf_Xword ( S::*F_get_size )() const>
|
||||||
class note_section_accessor_template
|
class note_section_accessor_template
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
note_section_accessor_template( const elfio& elf_file_, S* section_ ) :
|
explicit note_section_accessor_template( const elfio& elf_file, S* section )
|
||||||
elf_file( elf_file_ ), note_section( section_ )
|
: elf_file( elf_file ), notes( section )
|
||||||
{
|
{
|
||||||
process_section();
|
process_section();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Word
|
Elf_Word get_notes_num() const
|
||||||
get_notes_num() const
|
|
||||||
{
|
{
|
||||||
return (Elf_Word)note_start_positions.size();
|
return (Elf_Word)note_start_positions.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool get_note( Elf_Word index,
|
||||||
get_note( Elf_Word index,
|
Elf_Word& type,
|
||||||
Elf_Word& type,
|
std::string& name,
|
||||||
std::string& name,
|
char*& desc,
|
||||||
void*& desc,
|
Elf_Word& descSize ) const
|
||||||
Elf_Word& descSize ) const
|
|
||||||
{
|
{
|
||||||
if ( index >= note_section->get_size() ) {
|
if ( index >= ( notes->*F_get_size )() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* pData = note_section->get_data() + note_start_positions[index];
|
const char* pData = notes->get_data() + note_start_positions[index];
|
||||||
int align = sizeof( Elf_Word );
|
int align = sizeof( Elf_Word );
|
||||||
|
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
type = convertor( *(const Elf_Word*)( pData + 2*align ) );
|
type = convertor( *(const Elf_Word*)( pData + 2 * (size_t)align ) );
|
||||||
Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) );
|
Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) );
|
||||||
descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) );
|
descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) );
|
||||||
Elf_Xword max_name_size = note_section->get_size() - note_start_positions[index];
|
|
||||||
if ( namesz > max_name_size ||
|
Elf_Xword max_name_size =
|
||||||
namesz + descSize > max_name_size ) {
|
( notes->*F_get_size )() - note_start_positions[index];
|
||||||
|
if ( namesz < 1 || namesz > max_name_size ||
|
||||||
|
(Elf_Xword)namesz + descSize > max_name_size ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
name.assign( pData + 3*align, namesz - 1);
|
name.assign( pData + 3 * (size_t)align, namesz - 1 );
|
||||||
if ( 0 == descSize ) {
|
if ( 0 == descSize ) {
|
||||||
desc = 0;
|
desc = nullptr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
desc = const_cast<char*> ( pData + 3*align +
|
desc = const_cast<char*>( pData + 3 * (size_t)align +
|
||||||
( ( namesz + align - 1 )/align )*align );
|
( ( namesz + align - 1 ) / align ) *
|
||||||
|
(size_t)align );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void add_note( Elf_Word type,
|
void add_note( Elf_Word type,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const void* desc,
|
const char* desc,
|
||||||
Elf_Word descSize )
|
Elf_Word descSize )
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
int align = sizeof( Elf_Word );
|
int align = sizeof( Elf_Word );
|
||||||
Elf_Word nameLen = (Elf_Word)name.size() + 1;
|
Elf_Word nameLen = (Elf_Word)name.size() + 1;
|
||||||
Elf_Word nameLenConv = convertor( nameLen );
|
Elf_Word nameLenConv = convertor( nameLen );
|
||||||
std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align );
|
std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align );
|
||||||
Elf_Word descSizeConv = convertor( descSize );
|
Elf_Word descSizeConv = convertor( descSize );
|
||||||
|
|
||||||
buffer.append( reinterpret_cast<char*>( &descSizeConv ), align );
|
buffer.append( reinterpret_cast<char*>( &descSizeConv ), align );
|
||||||
type = convertor( type );
|
type = convertor( type );
|
||||||
buffer.append( reinterpret_cast<char*>( &type ), align );
|
buffer.append( reinterpret_cast<char*>( &type ), align );
|
||||||
@ -113,58 +114,70 @@ class note_section_accessor_template
|
|||||||
buffer.append( 1, '\x00' );
|
buffer.append( 1, '\x00' );
|
||||||
const char pad[] = { '\0', '\0', '\0', '\0' };
|
const char pad[] = { '\0', '\0', '\0', '\0' };
|
||||||
if ( nameLen % align != 0 ) {
|
if ( nameLen % align != 0 ) {
|
||||||
buffer.append( pad, align - nameLen % align );
|
buffer.append( pad, (size_t)align - nameLen % align );
|
||||||
}
|
}
|
||||||
if ( desc != 0 && descSize != 0 ) {
|
if ( desc != nullptr && descSize != 0 ) {
|
||||||
buffer.append( reinterpret_cast<const char*>( desc ), descSize );
|
buffer.append( desc, descSize );
|
||||||
if ( descSize % align != 0 ) {
|
if ( descSize % align != 0 ) {
|
||||||
buffer.append( pad, align - descSize % align );
|
buffer.append( pad, (size_t)align - descSize % align );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
note_start_positions.push_back( note_section->get_size() );
|
note_start_positions.emplace_back( ( notes->*F_get_size )() );
|
||||||
note_section->append_data( buffer );
|
notes->append_data( buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void process_section()
|
void process_section()
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
const char* data = note_section->get_data();
|
const char* data = notes->get_data();
|
||||||
Elf_Xword size = note_section->get_size();
|
Elf_Xword size = ( notes->*F_get_size )();
|
||||||
Elf_Xword current = 0;
|
Elf_Xword current = 0;
|
||||||
|
|
||||||
note_start_positions.clear();
|
note_start_positions.clear();
|
||||||
|
|
||||||
// Is it empty?
|
// Is it empty?
|
||||||
if ( 0 == data || 0 == size ) {
|
if ( nullptr == data || 0 == size ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int align = sizeof( Elf_Word );
|
Elf_Word align = sizeof( Elf_Word );
|
||||||
while ( current + 3*align <= size ) {
|
while ( current + (Elf_Xword)3 * align <= size ) {
|
||||||
note_start_positions.push_back( current );
|
Elf_Word namesz = convertor( *(const Elf_Word*)( data + current ) );
|
||||||
Elf_Word namesz = convertor(
|
|
||||||
*(const Elf_Word*)( data + current ) );
|
|
||||||
Elf_Word descsz = convertor(
|
Elf_Word descsz = convertor(
|
||||||
*(const Elf_Word*)( data + current + sizeof( namesz ) ) );
|
*(const Elf_Word*)( data + current + sizeof( namesz ) ) );
|
||||||
|
Elf_Word advance =
|
||||||
|
(Elf_Xword)3 * sizeof( Elf_Word ) +
|
||||||
|
( ( namesz + align - 1 ) / align ) * (Elf_Xword)align +
|
||||||
|
( ( descsz + align - 1 ) / align ) * (Elf_Xword)align;
|
||||||
|
if ( namesz < size && descsz < size && current + advance <= size ) {
|
||||||
|
note_start_positions.emplace_back( current );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
current += 3*sizeof( Elf_Word ) +
|
current += advance;
|
||||||
( ( namesz + align - 1 ) / align ) * align +
|
|
||||||
( ( descsz + align - 1 ) / align ) * align;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
const elfio& elf_file;
|
const elfio& elf_file;
|
||||||
S* note_section;
|
S* notes;
|
||||||
std::vector<Elf_Xword> note_start_positions;
|
std::vector<Elf_Xword> note_start_positions;
|
||||||
};
|
};
|
||||||
|
|
||||||
using note_section_accessor = note_section_accessor_template<section>;
|
using note_section_accessor =
|
||||||
using const_note_section_accessor = note_section_accessor_template<const section>;
|
note_section_accessor_template<section, §ion::get_size>;
|
||||||
|
using const_note_section_accessor =
|
||||||
|
note_section_accessor_template<const section, §ion::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
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,8 +25,8 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
namespace ELFIO {
|
namespace ELFIO {
|
||||||
|
|
||||||
template<typename T> struct get_sym_and_type;
|
template <typename T> struct get_sym_and_type;
|
||||||
template<> struct get_sym_and_type< Elf32_Rel >
|
template <> struct get_sym_and_type<Elf32_Rel>
|
||||||
{
|
{
|
||||||
static int get_r_sym( Elf_Xword info )
|
static int get_r_sym( Elf_Xword info )
|
||||||
{
|
{
|
||||||
@ -38,7 +37,7 @@ template<> struct get_sym_and_type< Elf32_Rel >
|
|||||||
return ELF32_R_TYPE( (Elf_Word)info );
|
return ELF32_R_TYPE( (Elf_Word)info );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<> struct get_sym_and_type< Elf32_Rela >
|
template <> struct get_sym_and_type<Elf32_Rela>
|
||||||
{
|
{
|
||||||
static int get_r_sym( Elf_Xword info )
|
static int get_r_sym( Elf_Xword info )
|
||||||
{
|
{
|
||||||
@ -49,161 +48,219 @@ template<> struct get_sym_and_type< Elf32_Rela >
|
|||||||
return ELF32_R_TYPE( (Elf_Word)info );
|
return ELF32_R_TYPE( (Elf_Word)info );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<> struct get_sym_and_type< Elf64_Rel >
|
template <> struct get_sym_and_type<Elf64_Rel>
|
||||||
{
|
{
|
||||||
static int get_r_sym( Elf_Xword info )
|
static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
|
||||||
{
|
static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
|
||||||
return ELF64_R_SYM( info );
|
|
||||||
}
|
|
||||||
static int get_r_type( Elf_Xword info )
|
|
||||||
{
|
|
||||||
return ELF64_R_TYPE( info );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
template<> struct get_sym_and_type< Elf64_Rela >
|
template <> struct get_sym_and_type<Elf64_Rela>
|
||||||
{
|
{
|
||||||
static int get_r_sym( Elf_Xword info )
|
static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
|
||||||
{
|
static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
|
||||||
return ELF64_R_SYM( info );
|
|
||||||
}
|
|
||||||
static int get_r_type( Elf_Xword info )
|
|
||||||
{
|
|
||||||
return ELF64_R_TYPE( info );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class S >
|
template <class S> class relocation_section_accessor_template
|
||||||
class relocation_section_accessor_template
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
relocation_section_accessor_template( const elfio& elf_file_, S* section_ ) :
|
explicit relocation_section_accessor_template( const elfio& elf_file,
|
||||||
elf_file( elf_file_ ),
|
S* section )
|
||||||
relocation_section( section_ )
|
: elf_file( elf_file ), relocation_section( section )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Xword
|
Elf_Xword get_entries_num() const
|
||||||
get_entries_num() const
|
|
||||||
{
|
{
|
||||||
Elf_Xword nRet = 0;
|
Elf_Xword nRet = 0;
|
||||||
|
|
||||||
if ( 0 != relocation_section->get_entry_size() ) {
|
if ( 0 != relocation_section->get_entry_size() ) {
|
||||||
nRet = relocation_section->get_size() / relocation_section->get_entry_size();
|
nRet = relocation_section->get_size() /
|
||||||
|
relocation_section->get_entry_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nRet;
|
return nRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool get_entry( Elf_Xword index,
|
||||||
get_entry( Elf_Xword index,
|
Elf64_Addr& offset,
|
||||||
Elf64_Addr& offset,
|
Elf_Word& symbol,
|
||||||
Elf_Word& symbol,
|
unsigned& type,
|
||||||
Elf_Word& type,
|
Elf_Sxword& addend ) const
|
||||||
Elf_Sxword& addend ) const
|
|
||||||
{
|
{
|
||||||
if ( index >= get_entries_num() ) { // Is index valid
|
if ( index >= get_entries_num() ) { // Is index valid
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
if ( SHT_REL == relocation_section->get_type() ) {
|
if ( SHT_REL == relocation_section->get_type() ) {
|
||||||
generic_get_entry_rel< Elf32_Rel >( index, offset, symbol,
|
generic_get_entry_rel<Elf32_Rel>( index, offset, symbol, type,
|
||||||
type, addend );
|
addend );
|
||||||
}
|
}
|
||||||
else if ( SHT_RELA == relocation_section->get_type() ) {
|
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||||
generic_get_entry_rela< Elf32_Rela >( index, offset, symbol,
|
generic_get_entry_rela<Elf32_Rela>( index, offset, symbol, type,
|
||||||
type, addend );
|
addend );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( SHT_REL == relocation_section->get_type() ) {
|
if ( SHT_REL == relocation_section->get_type() ) {
|
||||||
generic_get_entry_rel< Elf64_Rel >( index, offset, symbol,
|
generic_get_entry_rel<Elf64_Rel>( index, offset, symbol, type,
|
||||||
type, addend );
|
addend );
|
||||||
}
|
}
|
||||||
else if ( SHT_RELA == relocation_section->get_type() ) {
|
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||||
generic_get_entry_rela< Elf64_Rela >( index, offset, symbol,
|
generic_get_entry_rela<Elf64_Rela>( index, offset, symbol, type,
|
||||||
type, addend );
|
addend );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool get_entry( Elf_Xword index,
|
||||||
get_entry( Elf_Xword index,
|
Elf64_Addr& offset,
|
||||||
Elf64_Addr& offset,
|
Elf64_Addr& symbolValue,
|
||||||
Elf64_Addr& symbolValue,
|
std::string& symbolName,
|
||||||
std::string& symbolName,
|
unsigned& type,
|
||||||
Elf_Word& type,
|
Elf_Sxword& addend,
|
||||||
Elf_Sxword& addend,
|
Elf_Sxword& calcValue ) const
|
||||||
Elf_Half& section) const
|
|
||||||
{
|
{
|
||||||
// Do regular job
|
// Do regular job
|
||||||
Elf_Word symbol;
|
Elf_Word symbol = 0;
|
||||||
bool ret = get_entry( index, offset, symbol, type, addend );
|
bool ret = get_entry( index, offset, symbol, type, addend );
|
||||||
|
|
||||||
// Find the symbol
|
// Find the symbol
|
||||||
Elf_Xword size;
|
Elf_Xword size;
|
||||||
unsigned char bind;
|
unsigned char bind;
|
||||||
unsigned char symbolType;
|
unsigned char symbolType;
|
||||||
|
Elf_Half section;
|
||||||
unsigned char other;
|
unsigned char other;
|
||||||
|
|
||||||
symbol_section_accessor symbols( elf_file, elf_file.sections[get_symbol_table_index()] );
|
symbol_section_accessor symbols(
|
||||||
ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue,
|
elf_file, elf_file.sections[get_symbol_table_index()] );
|
||||||
size, bind, symbolType, section, other );
|
ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size,
|
||||||
|
bind, symbolType, section, other );
|
||||||
|
|
||||||
|
if ( ret ) { // Was it successful?
|
||||||
|
switch ( type ) {
|
||||||
|
case R_386_NONE: // none
|
||||||
|
calcValue = 0;
|
||||||
|
break;
|
||||||
|
case R_386_32: // S + A
|
||||||
|
calcValue = symbolValue + addend;
|
||||||
|
break;
|
||||||
|
case R_386_PC32: // S + A - P
|
||||||
|
calcValue = symbolValue + addend - offset;
|
||||||
|
break;
|
||||||
|
case R_386_GOT32: // G + A - P
|
||||||
|
calcValue = 0;
|
||||||
|
break;
|
||||||
|
case R_386_PLT32: // L + A - P
|
||||||
|
calcValue = 0;
|
||||||
|
break;
|
||||||
|
case R_386_COPY: // none
|
||||||
|
calcValue = 0;
|
||||||
|
break;
|
||||||
|
case R_386_GLOB_DAT: // S
|
||||||
|
case R_386_JMP_SLOT: // S
|
||||||
|
calcValue = symbolValue;
|
||||||
|
break;
|
||||||
|
case R_386_RELATIVE: // B + A
|
||||||
|
calcValue = addend;
|
||||||
|
break;
|
||||||
|
case R_386_GOTOFF: // S + A - GOT
|
||||||
|
calcValue = 0;
|
||||||
|
break;
|
||||||
|
case R_386_GOTPC: // GOT + A - P
|
||||||
|
calcValue = 0;
|
||||||
|
break;
|
||||||
|
default: // Not recognized symbol!
|
||||||
|
calcValue = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
bool set_entry( Elf_Xword index,
|
||||||
add_entry( Elf64_Addr offset, Elf_Xword info )
|
Elf64_Addr offset,
|
||||||
|
Elf_Word symbol,
|
||||||
|
unsigned type,
|
||||||
|
Elf_Sxword addend )
|
||||||
{
|
{
|
||||||
|
if ( index >= get_entries_num() ) { // Is index valid
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
generic_add_entry< Elf32_Rel >( offset, info );
|
if ( SHT_REL == relocation_section->get_type() ) {
|
||||||
|
generic_set_entry_rel<Elf32_Rel>( index, offset, symbol, type,
|
||||||
|
addend );
|
||||||
|
}
|
||||||
|
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||||
|
generic_set_entry_rela<Elf32_Rela>( index, offset, symbol, type,
|
||||||
|
addend );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generic_add_entry< Elf64_Rel >( offset, info );
|
if ( SHT_REL == relocation_section->get_type() ) {
|
||||||
|
generic_set_entry_rel<Elf64_Rel>( index, offset, symbol, type,
|
||||||
|
addend );
|
||||||
|
}
|
||||||
|
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||||
|
generic_set_entry_rela<Elf64_Rela>( index, offset, symbol, type,
|
||||||
|
addend );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void add_entry( Elf64_Addr offset, Elf_Xword info )
|
||||||
|
{
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
generic_add_entry<Elf32_Rel>( offset, info );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
generic_add_entry<Elf64_Rel>( offset, info );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type )
|
||||||
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type )
|
|
||||||
{
|
{
|
||||||
Elf_Xword info;
|
Elf_Xword info;
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
|
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
info = ELF64_R_INFO((Elf_Xword)symbol, type );
|
info = ELF64_R_INFO( (Elf_Xword)symbol, type );
|
||||||
}
|
}
|
||||||
|
|
||||||
add_entry( offset, info );
|
add_entry( offset, info );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
|
||||||
add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
|
|
||||||
{
|
{
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
generic_add_entry< Elf32_Rela >( offset, info, addend );
|
generic_add_entry<Elf32_Rela>( offset, info, addend );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generic_add_entry< Elf64_Rela >( offset, info, addend );
|
generic_add_entry<Elf64_Rela>( offset, info, addend );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void add_entry( Elf64_Addr offset,
|
||||||
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type,
|
Elf_Word symbol,
|
||||||
Elf_Sxword addend )
|
unsigned type,
|
||||||
|
Elf_Sxword addend )
|
||||||
{
|
{
|
||||||
Elf_Xword info;
|
Elf_Xword info;
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
@ -216,48 +273,63 @@ class relocation_section_accessor_template
|
|||||||
add_entry( offset, info, addend );
|
add_entry( offset, info, addend );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void add_entry( string_section_accessor str_writer,
|
||||||
add_entry( string_section_accessor str_writer,
|
const char* str,
|
||||||
const char* str,
|
symbol_section_accessor sym_writer,
|
||||||
symbol_section_accessor sym_writer,
|
Elf64_Addr value,
|
||||||
Elf64_Addr value,
|
Elf_Word size,
|
||||||
Elf_Word size,
|
unsigned char sym_info,
|
||||||
unsigned char sym_info,
|
unsigned char other,
|
||||||
unsigned char other,
|
Elf_Half shndx,
|
||||||
Elf_Half shndx,
|
Elf64_Addr offset,
|
||||||
Elf64_Addr offset,
|
unsigned type )
|
||||||
unsigned char type )
|
|
||||||
{
|
{
|
||||||
Elf_Word str_index = str_writer.add_string( str );
|
Elf_Word str_index = str_writer.add_string( str );
|
||||||
Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size,
|
Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size,
|
||||||
sym_info, other, shndx );
|
sym_info, other, shndx );
|
||||||
add_entry( offset, sym_index, type );
|
add_entry( offset, sym_index, type );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
void swap_symbols( Elf_Xword first, Elf_Xword second )
|
||||||
|
{
|
||||||
|
Elf64_Addr offset = 0;
|
||||||
|
Elf_Word symbol = 0;
|
||||||
|
unsigned rtype = 0;
|
||||||
|
Elf_Sxword addend = 0;
|
||||||
|
for ( Elf_Word i = 0; i < get_entries_num(); i++ ) {
|
||||||
|
get_entry( i, offset, symbol, rtype, addend );
|
||||||
|
if ( symbol == first ) {
|
||||||
|
set_entry( i, offset, (Elf_Word)second, rtype, addend );
|
||||||
|
}
|
||||||
|
if ( symbol == second ) {
|
||||||
|
set_entry( i, offset, (Elf_Word)first, rtype, addend );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Half
|
Elf_Half get_symbol_table_index() const
|
||||||
get_symbol_table_index() const
|
|
||||||
{
|
{
|
||||||
return (Elf_Half)relocation_section->get_link();
|
return (Elf_Half)relocation_section->get_link();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
void
|
void generic_get_entry_rel( Elf_Xword index,
|
||||||
generic_get_entry_rel( Elf_Xword index,
|
Elf64_Addr& offset,
|
||||||
Elf64_Addr& offset,
|
Elf_Word& symbol,
|
||||||
Elf_Word& symbol,
|
unsigned& type,
|
||||||
Elf_Word& type,
|
Elf_Sxword& addend ) const
|
||||||
Elf_Sxword& addend ) const
|
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
const T* pEntry = reinterpret_cast<const T*>(
|
const T* pEntry = reinterpret_cast<const T*>(
|
||||||
relocation_section->get_data() +
|
relocation_section->get_data() +
|
||||||
index * relocation_section->get_entry_size() );
|
index * relocation_section->get_entry_size() );
|
||||||
offset = convertor( pEntry->r_offset );
|
offset = convertor( pEntry->r_offset );
|
||||||
Elf_Xword tmp = convertor( pEntry->r_info );
|
Elf_Xword tmp = convertor( pEntry->r_info );
|
||||||
symbol = get_sym_and_type<T>::get_r_sym( tmp );
|
symbol = get_sym_and_type<T>::get_r_sym( tmp );
|
||||||
@ -265,20 +337,19 @@ class relocation_section_accessor_template
|
|||||||
addend = 0;
|
addend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
void
|
void generic_get_entry_rela( Elf_Xword index,
|
||||||
generic_get_entry_rela( Elf_Xword index,
|
Elf64_Addr& offset,
|
||||||
Elf64_Addr& offset,
|
Elf_Word& symbol,
|
||||||
Elf_Word& symbol,
|
unsigned& type,
|
||||||
Elf_Word& type,
|
Elf_Sxword& addend ) const
|
||||||
Elf_Sxword& addend ) const
|
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
const T* pEntry = reinterpret_cast<const T*>(
|
const T* pEntry = reinterpret_cast<const T*>(
|
||||||
relocation_section->get_data() +
|
relocation_section->get_data() +
|
||||||
index * relocation_section->get_entry_size() );
|
index * relocation_section->get_entry_size() );
|
||||||
offset = convertor( pEntry->r_offset );
|
offset = convertor( pEntry->r_offset );
|
||||||
Elf_Xword tmp = convertor( pEntry->r_info );
|
Elf_Xword tmp = convertor( pEntry->r_info );
|
||||||
symbol = get_sym_and_type<T>::get_r_sym( tmp );
|
symbol = get_sym_and_type<T>::get_r_sym( tmp );
|
||||||
@ -286,24 +357,76 @@ class relocation_section_accessor_template
|
|||||||
addend = convertor( pEntry->r_addend );
|
addend = convertor( pEntry->r_addend );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
void
|
void generic_set_entry_rel( Elf_Xword index,
|
||||||
generic_add_entry( Elf64_Addr offset, Elf_Xword info )
|
Elf64_Addr offset,
|
||||||
|
Elf_Word symbol,
|
||||||
|
unsigned type,
|
||||||
|
Elf_Sxword )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
T* pEntry = const_cast<T*>( reinterpret_cast<const T*>(
|
||||||
|
relocation_section->get_data() +
|
||||||
|
index * relocation_section->get_entry_size() ) );
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
pEntry->r_offset = decltype( pEntry->r_offset )( offset );
|
||||||
|
pEntry->r_offset = convertor( pEntry->r_offset );
|
||||||
|
pEntry->r_info = convertor( pEntry->r_info );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template <class T>
|
||||||
|
void generic_set_entry_rela( Elf_Xword index,
|
||||||
|
Elf64_Addr offset,
|
||||||
|
Elf_Word symbol,
|
||||||
|
unsigned type,
|
||||||
|
Elf_Sxword addend )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
T* pEntry = const_cast<T*>( reinterpret_cast<const T*>(
|
||||||
|
relocation_section->get_data() +
|
||||||
|
index * relocation_section->get_entry_size() ) );
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
pEntry->r_offset = decltype( pEntry->r_offset )( offset );
|
||||||
|
pEntry->r_addend = decltype( pEntry->r_addend )( addend );
|
||||||
|
pEntry->r_offset = convertor( pEntry->r_offset );
|
||||||
|
pEntry->r_info = convertor( pEntry->r_info );
|
||||||
|
pEntry->r_addend = convertor( pEntry->r_addend );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template <class T>
|
||||||
|
void generic_add_entry( Elf64_Addr offset, Elf_Xword info )
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
T entry;
|
T entry;
|
||||||
entry.r_offset = offset;
|
entry.r_offset = decltype( entry.r_offset )( offset );
|
||||||
entry.r_info = info;
|
entry.r_info = decltype( entry.r_info )( info );
|
||||||
entry.r_offset = convertor( entry.r_offset );
|
entry.r_offset = convertor( entry.r_offset );
|
||||||
entry.r_info = convertor( entry.r_info );
|
entry.r_info = convertor( entry.r_info );
|
||||||
|
|
||||||
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
|
relocation_section->append_data( reinterpret_cast<char*>( &entry ),
|
||||||
|
sizeof( entry ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
void
|
void
|
||||||
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
|
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
|
||||||
{
|
{
|
||||||
@ -317,17 +440,20 @@ class relocation_section_accessor_template
|
|||||||
entry.r_info = convertor( entry.r_info );
|
entry.r_info = convertor( entry.r_info );
|
||||||
entry.r_addend = convertor( entry.r_addend );
|
entry.r_addend = convertor( entry.r_addend );
|
||||||
|
|
||||||
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
|
relocation_section->append_data( reinterpret_cast<char*>( &entry ),
|
||||||
|
sizeof( entry ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
const elfio& elf_file;
|
const elfio& elf_file;
|
||||||
S* relocation_section;
|
S* relocation_section = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
using relocation_section_accessor = relocation_section_accessor_template<section>;
|
using relocation_section_accessor =
|
||||||
using const_relocation_section_accessor = relocation_section_accessor_template<const section>;
|
relocation_section_accessor_template<section>;
|
||||||
|
using const_relocation_section_accessor =
|
||||||
|
relocation_section_accessor_template<const section>;
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,320 +25,342 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "utils/logger.h"
|
#include <new>
|
||||||
#include <zlib.h>
|
#include <limits>
|
||||||
|
|
||||||
namespace ELFIO {
|
namespace ELFIO {
|
||||||
|
|
||||||
class section
|
class section
|
||||||
{
|
{
|
||||||
friend class elfio;
|
friend class elfio;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~section() {};
|
virtual ~section() = default;
|
||||||
|
|
||||||
ELFIO_GET_ACCESS_DECL ( Elf_Half, index );
|
ELFIO_GET_ACCESS_DECL( Elf_Half, index );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( std::string, name );
|
ELFIO_GET_SET_ACCESS_DECL( std::string, name );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address );
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
|
||||||
ELFIO_GET_ACCESS_DECL ( Elf64_Off, offset );
|
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
size_t stream_size;
|
|
||||||
size_t get_stream_size() const
|
|
||||||
{
|
|
||||||
return stream_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_stream_size(size_t value)
|
virtual const char* get_data() const = 0;
|
||||||
{
|
virtual void set_data( const char* raw_data, Elf_Word size ) = 0;
|
||||||
stream_size = value;
|
virtual void set_data( const std::string& data ) = 0;
|
||||||
}
|
virtual void append_data( const char* raw_data, Elf_Word size ) = 0;
|
||||||
|
virtual void append_data( const std::string& data ) = 0;
|
||||||
virtual const char* get_data() const = 0;
|
virtual void
|
||||||
virtual void set_data( const char* pData, Elf_Word size ) = 0;
|
insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) = 0;
|
||||||
virtual void set_data( const std::string& data ) = 0;
|
virtual void insert_data( Elf_Xword pos, const std::string& data ) = 0;
|
||||||
virtual void append_data( const char* pData, Elf_Word size ) = 0;
|
virtual size_t get_stream_size() const = 0;
|
||||||
virtual void append_data( const std::string& data ) = 0;
|
virtual void set_stream_size( size_t value ) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
||||||
|
|
||||||
virtual void load( std::istream& stream,
|
virtual bool load( std::istream& stream,
|
||||||
std::streampos header_offset ) = 0;
|
std::streampos header_offset,
|
||||||
|
bool is_lazy ) = 0;
|
||||||
virtual void save( std::ostream& stream,
|
virtual void save( std::ostream& stream,
|
||||||
std::streampos header_offset,
|
std::streampos header_offset,
|
||||||
std::streampos data_offset ) = 0;
|
std::streampos data_offset ) = 0;
|
||||||
virtual bool is_address_initialized() const = 0;
|
virtual bool is_address_initialized() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> class section_impl : public section
|
||||||
template< class T >
|
|
||||||
class section_impl : public section
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
section_impl( const endianess_convertor* convertor_ ) : convertor( convertor_ )
|
section_impl( const endianess_convertor* convertor,
|
||||||
|
const address_translator* translator,
|
||||||
|
const std::shared_ptr<compression_interface>& compression )
|
||||||
|
: convertor( convertor ), translator( translator ),
|
||||||
|
compression( compression )
|
||||||
{
|
{
|
||||||
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
|
|
||||||
is_address_set = false;
|
|
||||||
data = 0;
|
|
||||||
data_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
~section_impl()
|
|
||||||
{
|
|
||||||
delete [] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Section info functions
|
// Section info functions
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type );
|
ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags );
|
ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size );
|
ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link );
|
ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info );
|
ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign );
|
ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize );
|
ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name );
|
ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name );
|
||||||
ELFIO_GET_ACCESS ( Elf64_Addr, address, header.sh_addr );
|
ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr );
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half get_index() const override { return index; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
std::string get_name() const override { return name; }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Half
|
void set_name( const std::string& name_prm ) override
|
||||||
get_index() const
|
|
||||||
{
|
{
|
||||||
return index;
|
this->name = name_prm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
void set_address( const Elf64_Addr& value ) override
|
||||||
std::string
|
|
||||||
get_name() const
|
|
||||||
{
|
{
|
||||||
return name;
|
header.sh_addr = decltype( header.sh_addr )( value );
|
||||||
}
|
header.sh_addr = ( *convertor )( header.sh_addr );
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
set_name( std::string name_ )
|
|
||||||
{
|
|
||||||
name = name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
set_address( Elf64_Addr value )
|
|
||||||
{
|
|
||||||
header.sh_addr = value;
|
|
||||||
header.sh_addr = (*convertor)( header.sh_addr );
|
|
||||||
is_address_set = true;
|
is_address_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool is_address_initialized() const override { return is_address_set; }
|
||||||
is_address_initialized() const
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const char* get_data() const override
|
||||||
{
|
{
|
||||||
return is_address_set;
|
if ( is_lazy ) {
|
||||||
|
load_data();
|
||||||
|
}
|
||||||
|
return data.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
const char*
|
void set_data( const char* raw_data, Elf_Word size ) override
|
||||||
get_data() const
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
set_data( const char* raw_data, Elf_Word size )
|
|
||||||
{
|
{
|
||||||
if ( get_type() != SHT_NOBITS ) {
|
if ( get_type() != SHT_NOBITS ) {
|
||||||
delete [] data;
|
data = std::unique_ptr<char[]>( new ( std::nothrow ) char[size] );
|
||||||
data = new char[size];
|
if ( nullptr != data.get() && nullptr != raw_data ) {
|
||||||
if ( 0 != data && 0 != raw_data ) {
|
|
||||||
data_size = size;
|
data_size = size;
|
||||||
std::copy( raw_data, raw_data + size, data );
|
std::copy( raw_data, raw_data + size, data.get() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data_size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_size( size );
|
set_size( data_size );
|
||||||
|
if ( translator->empty() ) {
|
||||||
|
set_stream_size( data_size );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void set_data( const std::string& str_data ) override
|
||||||
set_data( const std::string& str_data )
|
|
||||||
{
|
{
|
||||||
return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void append_data( const char* raw_data, Elf_Word size ) override
|
||||||
append_data( const char* raw_data, Elf_Word size )
|
|
||||||
{
|
{
|
||||||
if ( get_type() != SHT_NOBITS ) {
|
insert_data( get_size(), raw_data, size );
|
||||||
if ( get_size() + size < data_size ) {
|
|
||||||
std::copy( raw_data, raw_data + size, data + get_size() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data_size = 2*( data_size + size);
|
|
||||||
char* new_data;
|
|
||||||
new_data = new char[data_size];
|
|
||||||
|
|
||||||
if ( 0 != new_data ) {
|
|
||||||
std::copy( data, data + get_size(), new_data );
|
|
||||||
std::copy( raw_data, raw_data + size, new_data + get_size() );
|
|
||||||
delete [] data;
|
|
||||||
data = new_data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set_size( get_size() + size );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void append_data( const std::string& str_data ) override
|
||||||
append_data( const std::string& str_data )
|
|
||||||
{
|
{
|
||||||
return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
protected:
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void
|
void
|
||||||
set_index( Elf_Half value )
|
insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) override
|
||||||
{
|
{
|
||||||
index = value;
|
if ( get_type() != SHT_NOBITS ) {
|
||||||
}
|
if ( get_size() + size < data_size ) {
|
||||||
|
char* d = data.get();
|
||||||
|
std::copy_backward( d + pos, d + get_size(),
|
||||||
|
d + get_size() + size );
|
||||||
|
std::copy( raw_data, raw_data + size, d + pos );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data_size = 2 * ( data_size + size );
|
||||||
|
std::unique_ptr<char[]> new_data(
|
||||||
|
new ( std::nothrow ) char[data_size] );
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
if ( nullptr != new_data ) {
|
||||||
void
|
char* d = data.get();
|
||||||
load( std::istream& stream,
|
std::copy( d, d + pos, new_data.get() );
|
||||||
std::streampos header_offset )
|
std::copy( raw_data, raw_data + size,
|
||||||
{
|
new_data.get() + pos );
|
||||||
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
|
std::copy( d + pos, d + get_size(),
|
||||||
|
new_data.get() + pos + size );
|
||||||
stream.seekg ( 0, stream.end );
|
data = std::move( new_data );
|
||||||
set_stream_size ( stream.tellg() );
|
|
||||||
|
|
||||||
stream.seekg( header_offset );
|
|
||||||
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
|
||||||
|
|
||||||
|
|
||||||
Elf_Xword size = get_size();
|
|
||||||
if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size()) {
|
|
||||||
|
|
||||||
data = new char[size + 1];
|
|
||||||
|
|
||||||
if ( ( 0 != size ) && ( 0 != data ) ) {
|
|
||||||
stream.seekg( (*convertor)( header.sh_offset ) );
|
|
||||||
if (get_flags() & 0x08000000){
|
|
||||||
uint32_t uncompressed_size = size;
|
|
||||||
stream.read( (char *) &uncompressed_size, 4);
|
|
||||||
stream.read( data, size - 4);
|
|
||||||
|
|
||||||
char* uncompressedData = new char[uncompressed_size + 1];
|
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
z_stream s;
|
|
||||||
memset(&s, 0, sizeof(s));
|
|
||||||
|
|
||||||
s.zalloc = Z_NULL;
|
|
||||||
s.zfree = Z_NULL;
|
|
||||||
s.opaque = Z_NULL;
|
|
||||||
|
|
||||||
ret = inflateInit_(&s, ZLIB_VERSION, sizeof(s));
|
|
||||||
if (ret != Z_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
s.avail_in = size - 4;
|
|
||||||
s.next_in = (Bytef *)data;
|
|
||||||
|
|
||||||
s.avail_out = uncompressed_size;
|
|
||||||
s.next_out = (Bytef *)&uncompressedData[0];
|
|
||||||
|
|
||||||
ret = inflate(&s, Z_FINISH);
|
|
||||||
if (ret != Z_OK && ret != Z_STREAM_END){
|
|
||||||
DEBUG_FUNCTION_LINE("NOOOO");
|
|
||||||
}
|
|
||||||
|
|
||||||
inflateEnd(&s);
|
|
||||||
|
|
||||||
delete [] data;
|
|
||||||
data = uncompressedData;
|
|
||||||
data_size = uncompressed_size;
|
|
||||||
set_size(uncompressed_size);
|
|
||||||
data[data_size] = 0; // Ensure data is ended with 0 to avoid oob read
|
|
||||||
|
|
||||||
}else{
|
|
||||||
stream.read( data, size );
|
|
||||||
data[size] = 0; // Ensure data is ended with 0 to avoid oob read
|
|
||||||
data_size = size;
|
|
||||||
}
|
}
|
||||||
}else{
|
else {
|
||||||
set_size(0);
|
size = 0;
|
||||||
DEBUG_FUNCTION_LINE("Failed to allocate memory.");
|
}
|
||||||
|
}
|
||||||
|
set_size( get_size() + size );
|
||||||
|
if ( translator->empty() ) {
|
||||||
|
set_stream_size( get_stream_size() + size );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void insert_data( Elf_Xword pos, const std::string& str_data ) override
|
||||||
save( std::ostream& stream,
|
{
|
||||||
std::streampos header_offset,
|
return insert_data( pos, str_data.c_str(), (Elf_Word)str_data.size() );
|
||||||
std::streampos data_offset )
|
}
|
||||||
|
|
||||||
|
size_t get_stream_size() const override { return stream_size; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void set_stream_size( size_t value ) override { stream_size = value; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
protected:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void set_index( const Elf_Half& value ) override { index = value; }
|
||||||
|
|
||||||
|
bool is_compressed() const
|
||||||
|
{
|
||||||
|
return ( ( get_flags() & SHF_RPX_DEFLATE ) ||
|
||||||
|
( get_flags() & SHF_COMPRESSED ) ) &&
|
||||||
|
compression != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool load( std::istream& stream,
|
||||||
|
std::streampos header_offset,
|
||||||
|
bool is_lazy_ ) override
|
||||||
|
{
|
||||||
|
pstream = &stream;
|
||||||
|
is_lazy = is_lazy_;
|
||||||
|
header = { 0 };
|
||||||
|
|
||||||
|
if ( translator->empty() ) {
|
||||||
|
stream.seekg( 0, std::istream::end );
|
||||||
|
set_stream_size( size_t( stream.tellg() ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
set_stream_size( std::numeric_limits<size_t>::max() );
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.seekg( ( *translator )[header_offset] );
|
||||||
|
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
||||||
|
|
||||||
|
if ( !is_lazy || is_compressed() ) {
|
||||||
|
|
||||||
|
bool ret = load_data();
|
||||||
|
|
||||||
|
if ( is_compressed() ) {
|
||||||
|
Elf_Xword size = get_size();
|
||||||
|
Elf_Xword uncompressed_size = 0;
|
||||||
|
auto decompressed_data = compression->inflate(
|
||||||
|
data.get(), convertor, size, uncompressed_size );
|
||||||
|
if ( decompressed_data != nullptr ) {
|
||||||
|
set_size( uncompressed_size );
|
||||||
|
data = std::move( decompressed_data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_data() const
|
||||||
|
{
|
||||||
|
is_lazy = false;
|
||||||
|
Elf_Xword size = get_size();
|
||||||
|
if ( nullptr == data && SHT_NULL != get_type() &&
|
||||||
|
SHT_NOBITS != get_type() && size < get_stream_size() ) {
|
||||||
|
data.reset( new ( std::nothrow ) char[size_t( size ) + 1] );
|
||||||
|
|
||||||
|
if ( ( 0 != size ) && ( nullptr != data ) ) {
|
||||||
|
pstream->seekg(
|
||||||
|
( *translator )[( *convertor )( header.sh_offset )] );
|
||||||
|
pstream->read( data.get(), size );
|
||||||
|
if ( static_cast<Elf_Xword>( pstream->gcount() ) != size ) {
|
||||||
|
data = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// refresh size because it may have changed if we had to decompress data
|
||||||
|
size = get_size();
|
||||||
|
data.get()[size] =
|
||||||
|
0; // Ensure data is ended with 0 to avoid oob read
|
||||||
|
data_size = decltype( data_size )( size );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void save( std::ostream& stream,
|
||||||
|
std::streampos header_offset,
|
||||||
|
std::streampos data_offset ) override
|
||||||
{
|
{
|
||||||
if ( 0 != get_index() ) {
|
if ( 0 != get_index() ) {
|
||||||
header.sh_offset = data_offset;
|
header.sh_offset = decltype( header.sh_offset )( data_offset );
|
||||||
header.sh_offset = (*convertor)( header.sh_offset );
|
header.sh_offset = ( *convertor )( header.sh_offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
save_header( stream, header_offset );
|
save_header( stream, header_offset );
|
||||||
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
|
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
|
||||||
get_size() != 0 && data != 0 ) {
|
get_size() != 0 && data != nullptr ) {
|
||||||
save_data( stream, data_offset );
|
save_data( stream, data_offset );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void save_header( std::ostream& stream, std::streampos header_offset ) const
|
||||||
save_header( std::ostream& stream,
|
|
||||||
std::streampos header_offset ) const
|
|
||||||
{
|
{
|
||||||
stream.seekp( header_offset );
|
adjust_stream_size( stream, header_offset );
|
||||||
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
|
stream.write( reinterpret_cast<const char*>( &header ),
|
||||||
|
sizeof( header ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void save_data( std::ostream& stream, std::streampos data_offset )
|
||||||
save_data( std::ostream& stream,
|
|
||||||
std::streampos data_offset ) const
|
|
||||||
{
|
{
|
||||||
stream.seekp( data_offset );
|
adjust_stream_size( stream, data_offset );
|
||||||
stream.write( get_data(), get_size() );
|
|
||||||
|
if ( ( ( get_flags() & SHF_COMPRESSED ) ||
|
||||||
|
( get_flags() & SHF_RPX_DEFLATE ) ) &&
|
||||||
|
compression != nullptr ) {
|
||||||
|
Elf_Xword decompressed_size = get_size();
|
||||||
|
Elf_Xword compressed_size = 0;
|
||||||
|
auto compressed_ptr = compression->deflate(
|
||||||
|
data.get(), convertor, decompressed_size, compressed_size );
|
||||||
|
stream.write( compressed_ptr.get(), compressed_size );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream.write( get_data(), get_size() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
T header;
|
mutable std::istream* pstream = nullptr;
|
||||||
Elf_Half index;
|
T header = {};
|
||||||
std::string name;
|
Elf_Half index = 0;
|
||||||
char* data;
|
std::string name;
|
||||||
Elf_Word data_size;
|
mutable std::unique_ptr<char[]> data;
|
||||||
const endianess_convertor* convertor;
|
mutable Elf_Word data_size = 0;
|
||||||
bool is_address_set;
|
const endianess_convertor* convertor = nullptr;
|
||||||
|
const address_translator* translator = nullptr;
|
||||||
|
const std::shared_ptr<compression_interface> compression = nullptr;
|
||||||
|
bool is_address_set = false;
|
||||||
|
size_t stream_size = 0;
|
||||||
|
mutable bool is_lazy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,107 +25,90 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <new>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace ELFIO {
|
namespace ELFIO {
|
||||||
|
|
||||||
class segment
|
class segment
|
||||||
{
|
{
|
||||||
friend class elfio;
|
friend class elfio;
|
||||||
public:
|
|
||||||
virtual ~segment() {};
|
|
||||||
|
|
||||||
ELFIO_GET_ACCESS_DECL ( Elf_Half, index );
|
public:
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
|
virtual ~segment() = default;
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
|
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
|
ELFIO_GET_ACCESS_DECL( Elf_Half, index );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
|
||||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
|
||||||
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
|
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
|
|
||||||
virtual const char* get_data() const = 0;
|
virtual const char* get_data() const = 0;
|
||||||
|
|
||||||
virtual Elf_Half add_section_index( Elf_Half index, Elf_Xword addr_align ) = 0;
|
virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0;
|
||||||
virtual Elf_Half get_sections_num() const = 0;
|
virtual Elf_Half add_section_index( Elf_Half index,
|
||||||
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
|
Elf_Xword addr_align ) = 0;
|
||||||
virtual bool is_offset_initialized() const = 0;
|
virtual Elf_Half get_sections_num() const = 0;
|
||||||
|
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
|
||||||
|
virtual bool is_offset_initialized() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
||||||
|
|
||||||
virtual const std::vector<Elf_Half>& get_sections() const = 0;
|
virtual const std::vector<Elf_Half>& get_sections() const = 0;
|
||||||
virtual void load( std::istream& stream, std::streampos header_offset ) = 0;
|
|
||||||
virtual void save( std::ostream& stream, std::streampos header_offset,
|
virtual bool load( std::istream& stream,
|
||||||
std::streampos data_offset ) = 0;
|
std::streampos header_offset,
|
||||||
|
bool is_lazy ) = 0;
|
||||||
|
virtual void save( std::ostream& stream,
|
||||||
|
std::streampos header_offset,
|
||||||
|
std::streampos data_offset ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T> class segment_impl : public segment
|
||||||
class segment_impl : public segment
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
segment_impl( endianess_convertor* convertor_ ) :
|
segment_impl( const endianess_convertor* convertor,
|
||||||
stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor_ )
|
const address_translator* translator )
|
||||||
|
: convertor( convertor ), translator( translator )
|
||||||
{
|
{
|
||||||
is_offset_set = false;
|
|
||||||
std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
virtual ~segment_impl()
|
|
||||||
{
|
|
||||||
delete [] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Section info functions
|
// Section info functions
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type );
|
ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags );
|
ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align );
|
ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align );
|
||||||
ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr );
|
ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr );
|
||||||
ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr );
|
ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz );
|
ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz );
|
||||||
ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
|
ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
|
||||||
ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
|
ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
|
||||||
size_t stream_size;
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
size_t
|
Elf_Half get_index() const override { return index; }
|
||||||
get_stream_size() const
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const char* get_data() const override
|
||||||
{
|
{
|
||||||
return stream_size;
|
if ( is_lazy ) {
|
||||||
|
load_data();
|
||||||
|
}
|
||||||
|
return data.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
Elf_Half add_section_index( Elf_Half sec_index,
|
||||||
set_stream_size(size_t value)
|
Elf_Xword addr_align ) override
|
||||||
{
|
{
|
||||||
stream_size = value;
|
sections.emplace_back( sec_index );
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
Elf_Half
|
|
||||||
get_index() const
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
const char*
|
|
||||||
get_data() const
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
Elf_Half
|
|
||||||
add_section_index( Elf_Half sec_index, Elf_Xword addr_align )
|
|
||||||
{
|
|
||||||
sections.push_back( sec_index );
|
|
||||||
if ( addr_align > get_align() ) {
|
if ( addr_align > get_align() ) {
|
||||||
set_align( addr_align );
|
set_align( addr_align );
|
||||||
}
|
}
|
||||||
@ -134,108 +116,137 @@ class segment_impl : public segment
|
|||||||
return (Elf_Half)sections.size();
|
return (Elf_Half)sections.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Half
|
Elf_Half add_section( section* psec, Elf_Xword addr_align ) override
|
||||||
get_sections_num() const
|
{
|
||||||
|
return add_section_index( psec->get_index(), addr_align );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half get_sections_num() const override
|
||||||
{
|
{
|
||||||
return (Elf_Half)sections.size();
|
return (Elf_Half)sections.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Half
|
Elf_Half get_section_index_at( Elf_Half num ) const override
|
||||||
get_section_index_at( Elf_Half num ) const
|
|
||||||
{
|
{
|
||||||
if ( num < sections.size() ) {
|
if ( num < sections.size() ) {
|
||||||
return sections[num];
|
return sections[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
return Elf_Half(-1);
|
return Elf_Half( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
protected:
|
protected:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void set_offset( const Elf64_Off& value ) override
|
||||||
set_offset( Elf64_Off value )
|
|
||||||
{
|
{
|
||||||
ph.p_offset = value;
|
ph.p_offset = decltype( ph.p_offset )( value );
|
||||||
ph.p_offset = (*convertor)( ph.p_offset );
|
ph.p_offset = ( *convertor )( ph.p_offset );
|
||||||
is_offset_set = true;
|
is_offset_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool is_offset_initialized() const override { return is_offset_set; }
|
||||||
is_offset_initialized() const
|
|
||||||
{
|
|
||||||
return is_offset_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
const std::vector<Elf_Half>&
|
const std::vector<Elf_Half>& get_sections() const override
|
||||||
get_sections() const
|
|
||||||
{
|
{
|
||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void
|
void set_index( const Elf_Half& value ) override { index = value; }
|
||||||
set_index( Elf_Half value )
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool load( std::istream& stream,
|
||||||
|
std::streampos header_offset,
|
||||||
|
bool is_lazy_ ) override
|
||||||
{
|
{
|
||||||
index = value;
|
pstream = &stream;
|
||||||
}
|
is_lazy = is_lazy_;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
if ( translator->empty() ) {
|
||||||
void
|
stream.seekg( 0, std::istream::end );
|
||||||
load( std::istream& stream,
|
set_stream_size( size_t( stream.tellg() ) );
|
||||||
std::streampos header_offset )
|
}
|
||||||
{
|
else {
|
||||||
|
set_stream_size( std::numeric_limits<size_t>::max() );
|
||||||
|
}
|
||||||
|
|
||||||
stream.seekg ( 0, stream.end );
|
stream.seekg( ( *translator )[header_offset] );
|
||||||
set_stream_size ( stream.tellg() );
|
|
||||||
|
|
||||||
stream.seekg( header_offset );
|
|
||||||
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
|
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
|
||||||
is_offset_set = true;
|
is_offset_set = true;
|
||||||
|
|
||||||
if ( PT_NULL != get_type() && 0 != get_file_size() ) {
|
if ( !is_lazy ) {
|
||||||
stream.seekg( (*convertor)( ph.p_offset ) );
|
return load_data();
|
||||||
Elf_Xword size = get_file_size();
|
|
||||||
|
|
||||||
if ( size > get_stream_size() ) {
|
|
||||||
data = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data = new char[size + 1];
|
|
||||||
|
|
||||||
if ( 0 != data ) {
|
|
||||||
stream.read( data, size );
|
|
||||||
data[size] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
bool load_data() const
|
||||||
|
{
|
||||||
|
is_lazy = false;
|
||||||
|
if ( PT_NULL == get_type() || 0 == get_file_size() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pstream->seekg( ( *translator )[( *convertor )( ph.p_offset )] );
|
||||||
|
Elf_Xword size = get_file_size();
|
||||||
|
|
||||||
|
if ( size > get_stream_size() ) {
|
||||||
|
data = nullptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data.reset( new ( std::nothrow ) char[(size_t)size + 1] );
|
||||||
|
|
||||||
|
if ( nullptr != data.get() && pstream->read( data.get(), size ) ) {
|
||||||
|
data.get()[size] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
void save( std::ostream& stream,
|
void save( std::ostream& stream,
|
||||||
std::streampos header_offset,
|
std::streampos header_offset,
|
||||||
std::streampos data_offset )
|
std::streampos data_offset ) override
|
||||||
{
|
{
|
||||||
ph.p_offset = data_offset;
|
ph.p_offset = decltype( ph.p_offset )( data_offset );
|
||||||
ph.p_offset = (*convertor)(ph.p_offset);
|
ph.p_offset = ( *convertor )( ph.p_offset );
|
||||||
stream.seekp( header_offset );
|
adjust_stream_size( stream, header_offset );
|
||||||
stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
|
stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
size_t get_stream_size() const { return stream_size; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void set_stream_size( size_t value ) { stream_size = value; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
T ph;
|
mutable std::istream* pstream = nullptr;
|
||||||
Elf_Half index;
|
T ph = {};
|
||||||
char* data;
|
Elf_Half index = 0;
|
||||||
std::vector<Elf_Half> sections;
|
mutable std::unique_ptr<char[]> data;
|
||||||
endianess_convertor* convertor;
|
std::vector<Elf_Half> sections;
|
||||||
bool is_offset_set;
|
const endianess_convertor* convertor = nullptr;
|
||||||
|
const address_translator* translator = nullptr;
|
||||||
|
size_t stream_size = 0;
|
||||||
|
bool is_offset_set = false;
|
||||||
|
mutable bool is_lazy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -31,70 +30,67 @@ THE SOFTWARE.
|
|||||||
namespace ELFIO {
|
namespace ELFIO {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class S >
|
template <class S> class string_section_accessor_template
|
||||||
class string_section_accessor_template
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
string_section_accessor_template( S* section_ ) :
|
explicit string_section_accessor_template( S* section )
|
||||||
string_section( section_ )
|
: string_section( section )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
const char* get_string( Elf_Word index ) const
|
||||||
const char*
|
|
||||||
get_string( Elf_Word index ) const
|
|
||||||
{
|
{
|
||||||
if ( string_section ) {
|
if ( string_section ) {
|
||||||
if ( index < string_section->get_size() ) {
|
const char* data = string_section->get_data();
|
||||||
const char* data = string_section->get_data();
|
if ( index < string_section->get_size() && nullptr != data ) {
|
||||||
if ( 0 != data ) {
|
size_t string_length =
|
||||||
|
strnlen( data + index, string_section->get_size() - index );
|
||||||
|
if ( string_length < ( string_section->get_size() - index ) )
|
||||||
return data + index;
|
return data + index;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
Elf_Word add_string( const char* str )
|
||||||
Elf_Word
|
|
||||||
add_string( const char* str )
|
|
||||||
{
|
{
|
||||||
Elf_Word current_position = 0;
|
Elf_Word current_position = 0;
|
||||||
|
|
||||||
if (string_section) {
|
if ( string_section ) {
|
||||||
// Strings are addeded to the end of the current section data
|
// Strings are addeded to the end of the current section data
|
||||||
current_position = (Elf_Word)string_section->get_size();
|
current_position =
|
||||||
|
static_cast<Elf_Word>( string_section->get_size() );
|
||||||
|
|
||||||
if ( current_position == 0 ) {
|
if ( current_position == 0 ) {
|
||||||
char empty_string = '\0';
|
char empty_string = '\0';
|
||||||
string_section->append_data( &empty_string, 1 );
|
string_section->append_data( &empty_string, 1 );
|
||||||
current_position++;
|
current_position++;
|
||||||
}
|
}
|
||||||
string_section->append_data( str, (Elf_Word)std::strlen( str ) + 1 );
|
string_section->append_data(
|
||||||
|
str, static_cast<Elf_Word>( std::strlen( str ) + 1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_position;
|
return current_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
Elf_Word add_string( const std::string& str )
|
||||||
Elf_Word
|
|
||||||
add_string( const std::string& str )
|
|
||||||
{
|
{
|
||||||
return add_string( str.c_str() );
|
return add_string( str.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
S* string_section;
|
S* string_section;
|
||||||
};
|
};
|
||||||
|
|
||||||
using string_section_accessor = string_section_accessor_template<section>;
|
using string_section_accessor = string_section_accessor_template<section>;
|
||||||
using const_string_section_accessor = string_section_accessor_template<const section>;
|
using const_string_section_accessor =
|
||||||
|
string_section_accessor_template<const section>;
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -27,40 +26,52 @@ THE SOFTWARE.
|
|||||||
namespace ELFIO {
|
namespace ELFIO {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class S >
|
template <class S> class symbol_section_accessor_template
|
||||||
class symbol_section_accessor_template
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
symbol_section_accessor_template( const elfio& elf_file_, S* symbol_section_ ) :
|
explicit symbol_section_accessor_template( const elfio& elf_file,
|
||||||
elf_file( elf_file_ ),
|
S* symbol_section )
|
||||||
symbol_section( symbol_section_ )
|
: elf_file( elf_file ), symbol_section( symbol_section )
|
||||||
{
|
{
|
||||||
find_hash_section();
|
find_hash_section();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Xword
|
Elf_Xword get_symbols_num() const
|
||||||
get_symbols_num() const
|
|
||||||
{
|
{
|
||||||
Elf_Xword nRet = 0;
|
Elf_Xword nRet = 0;
|
||||||
if ( 0 != symbol_section->get_entry_size() ) {
|
|
||||||
nRet = symbol_section->get_size() / symbol_section->get_entry_size();
|
size_t minimum_symbol_size;
|
||||||
|
switch ( elf_file.get_class() ) {
|
||||||
|
case ELFCLASS32:
|
||||||
|
minimum_symbol_size = sizeof( Elf32_Sym );
|
||||||
|
break;
|
||||||
|
case ELFCLASS64:
|
||||||
|
minimum_symbol_size = sizeof( Elf64_Sym );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( symbol_section->get_entry_size() >= minimum_symbol_size &&
|
||||||
|
symbol_section->get_size() <= symbol_section->get_stream_size() ) {
|
||||||
|
nRet =
|
||||||
|
symbol_section->get_size() / symbol_section->get_entry_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nRet;
|
return nRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool get_symbol( Elf_Xword index,
|
||||||
get_symbol( Elf_Xword index,
|
std::string& name,
|
||||||
std::string& name,
|
Elf64_Addr& value,
|
||||||
Elf64_Addr& value,
|
Elf_Xword& size,
|
||||||
Elf_Xword& size,
|
unsigned char& bind,
|
||||||
unsigned char& bind,
|
unsigned char& type,
|
||||||
unsigned char& type,
|
Elf_Half& section_index,
|
||||||
Elf_Half& section_index,
|
unsigned char& other ) const
|
||||||
unsigned char& other ) const
|
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
@ -76,46 +87,96 @@ class symbol_section_accessor_template
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool
|
bool get_symbol( const std::string& name,
|
||||||
get_symbol( const std::string& name,
|
Elf64_Addr& value,
|
||||||
Elf64_Addr& value,
|
Elf_Xword& size,
|
||||||
Elf_Xword& size,
|
unsigned char& bind,
|
||||||
unsigned char& bind,
|
unsigned char& type,
|
||||||
unsigned char& type,
|
Elf_Half& section_index,
|
||||||
Elf_Half& section_index,
|
unsigned char& other ) const
|
||||||
unsigned char& other ) const
|
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
if ( 0 != get_hash_table_index() ) {
|
if ( 0 != get_hash_table_index() ) {
|
||||||
Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data();
|
if ( hash_section->get_type() == SHT_HASH ) {
|
||||||
Elf_Word nchain = *(const Elf_Word*)( hash_section->get_data() +
|
ret = hash_lookup( name, value, size, bind, type, section_index,
|
||||||
sizeof( Elf_Word ) );
|
other );
|
||||||
Elf_Word val = elf_hash( (const unsigned char*)name.c_str() );
|
|
||||||
|
|
||||||
Elf_Word y = *(const Elf_Word*)( hash_section->get_data() +
|
|
||||||
( 2 + val % nbucket ) * sizeof( Elf_Word ) );
|
|
||||||
std::string str;
|
|
||||||
get_symbol( y, str, value, size, bind, type, section_index, other );
|
|
||||||
while ( str != name && STN_UNDEF != y && y < nchain ) {
|
|
||||||
y = *(const Elf_Word*)( hash_section->get_data() +
|
|
||||||
( 2 + nbucket + y ) * sizeof( Elf_Word ) );
|
|
||||||
get_symbol( y, str, value, size, bind, type, section_index, other );
|
|
||||||
}
|
}
|
||||||
if ( str == name ) {
|
if ( hash_section->get_type() == SHT_GNU_HASH ||
|
||||||
ret = true;
|
hash_section->get_type() == DT_GNU_HASH ) {
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
ret = gnu_hash_lookup<uint32_t>(
|
||||||
|
name, value, size, bind, type, section_index, other );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = gnu_hash_lookup<uint64_t>(
|
||||||
|
name, value, size, bind, type, section_index, other );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !ret ) {
|
||||||
|
for ( Elf_Xword i = 0; !ret && i < get_symbols_num(); i++ ) {
|
||||||
|
std::string symbol_name;
|
||||||
|
if ( get_symbol( i, symbol_name, value, size, bind, type,
|
||||||
|
section_index, other ) ) {
|
||||||
|
if ( symbol_name == name ) {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Word
|
bool get_symbol( const Elf64_Addr& value,
|
||||||
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
|
std::string& name,
|
||||||
unsigned char info, unsigned char other,
|
Elf_Xword& size,
|
||||||
Elf_Half shndx )
|
unsigned char& bind,
|
||||||
|
unsigned char& type,
|
||||||
|
Elf_Half& section_index,
|
||||||
|
unsigned char& other ) const
|
||||||
|
{
|
||||||
|
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
Elf_Xword idx = 0;
|
||||||
|
bool match = false;
|
||||||
|
Elf64_Addr v = 0;
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
match = generic_search_symbols<Elf32_Sym>(
|
||||||
|
[&]( const Elf32_Sym* sym ) {
|
||||||
|
return convertor( sym->st_value ) == value;
|
||||||
|
},
|
||||||
|
idx );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
match = generic_search_symbols<Elf64_Sym>(
|
||||||
|
[&]( const Elf64_Sym* sym ) {
|
||||||
|
return convertor( sym->st_value ) == value;
|
||||||
|
},
|
||||||
|
idx );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( match ) {
|
||||||
|
return get_symbol( idx, name, v, size, bind, type, section_index,
|
||||||
|
other );
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word add_symbol( Elf_Word name,
|
||||||
|
Elf64_Addr value,
|
||||||
|
Elf_Xword size,
|
||||||
|
unsigned char info,
|
||||||
|
unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
{
|
{
|
||||||
Elf_Word nRet;
|
Elf_Word nRet;
|
||||||
|
|
||||||
@ -129,110 +190,276 @@ class symbol_section_accessor_template
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( elf_file.get_class() == ELFCLASS32 ) {
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info, other,
|
nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info,
|
||||||
shndx );
|
other, shndx );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info, other,
|
nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info,
|
||||||
shndx );
|
other, shndx );
|
||||||
}
|
}
|
||||||
|
|
||||||
return nRet;
|
return nRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Word
|
Elf_Word add_symbol( Elf_Word name,
|
||||||
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
|
Elf64_Addr value,
|
||||||
unsigned char bind, unsigned char type, unsigned char other,
|
Elf_Xword size,
|
||||||
Elf_Half shndx )
|
unsigned char bind,
|
||||||
|
unsigned char type,
|
||||||
|
unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
{
|
{
|
||||||
return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, shndx );
|
return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other,
|
||||||
|
shndx );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Word
|
Elf_Word add_symbol( string_section_accessor& pStrWriter,
|
||||||
add_symbol( string_section_accessor& pStrWriter, const char* str,
|
const char* str,
|
||||||
Elf64_Addr value, Elf_Xword size,
|
Elf64_Addr value,
|
||||||
unsigned char info, unsigned char other,
|
Elf_Xword size,
|
||||||
Elf_Half shndx )
|
unsigned char info,
|
||||||
|
unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
{
|
{
|
||||||
Elf_Word index = pStrWriter.add_string( str );
|
Elf_Word index = pStrWriter.add_string( str );
|
||||||
return add_symbol( index, value, size, info, other, shndx );
|
return add_symbol( index, value, size, info, other, shndx );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Word
|
Elf_Word add_symbol( string_section_accessor& pStrWriter,
|
||||||
add_symbol( string_section_accessor& pStrWriter, const char* str,
|
const char* str,
|
||||||
Elf64_Addr value, Elf_Xword size,
|
Elf64_Addr value,
|
||||||
unsigned char bind, unsigned char type, unsigned char other,
|
Elf_Xword size,
|
||||||
Elf_Half shndx )
|
unsigned char bind,
|
||||||
|
unsigned char type,
|
||||||
|
unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
{
|
{
|
||||||
return add_symbol( pStrWriter, str, value, size, ELF_ST_INFO( bind, type ), other, shndx );
|
return add_symbol( pStrWriter, str, value, size,
|
||||||
|
ELF_ST_INFO( bind, type ), other, shndx );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
Elf_Xword arrange_local_symbols(
|
||||||
//------------------------------------------------------------------------------
|
std::function<void( Elf_Xword first, Elf_Xword second )> func =
|
||||||
void
|
nullptr )
|
||||||
find_hash_section()
|
{
|
||||||
|
Elf_Xword nRet = 0;
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
nRet = generic_arrange_local_symbols<Elf32_Sym>( func );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nRet = generic_arrange_local_symbols<Elf64_Sym>( func );
|
||||||
|
}
|
||||||
|
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void find_hash_section()
|
||||||
{
|
{
|
||||||
hash_section = 0;
|
|
||||||
hash_section_index = 0;
|
|
||||||
Elf_Half nSecNo = elf_file.sections.size();
|
Elf_Half nSecNo = elf_file.sections.size();
|
||||||
for ( Elf_Half i = 0; i < nSecNo && 0 == hash_section_index; ++i ) {
|
for ( Elf_Half i = 0; i < nSecNo; ++i ) {
|
||||||
const section* sec = elf_file.sections[i];
|
const section* sec = elf_file.sections[i];
|
||||||
if ( sec->get_link() == symbol_section->get_index() ) {
|
if ( sec->get_link() == symbol_section->get_index() &&
|
||||||
|
( sec->get_type() == SHT_HASH ||
|
||||||
|
sec->get_type() == SHT_GNU_HASH ||
|
||||||
|
sec->get_type() == DT_GNU_HASH ) ) {
|
||||||
hash_section = sec;
|
hash_section = sec;
|
||||||
hash_section_index = i;
|
hash_section_index = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Half
|
Elf_Half get_string_table_index() const
|
||||||
get_string_table_index() const
|
|
||||||
{
|
{
|
||||||
return (Elf_Half)symbol_section->get_link();
|
return (Elf_Half)symbol_section->get_link();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Elf_Half
|
Elf_Half get_hash_table_index() const { return hash_section_index; }
|
||||||
get_hash_table_index() const
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool hash_lookup( const std::string& name,
|
||||||
|
Elf64_Addr& value,
|
||||||
|
Elf_Xword& size,
|
||||||
|
unsigned char& bind,
|
||||||
|
unsigned char& type,
|
||||||
|
Elf_Half& section_index,
|
||||||
|
unsigned char& other ) const
|
||||||
{
|
{
|
||||||
return hash_section_index;
|
bool ret = false;
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data();
|
||||||
|
nbucket = convertor( nbucket );
|
||||||
|
Elf_Word nchain =
|
||||||
|
*(const Elf_Word*)( hash_section->get_data() + sizeof( Elf_Word ) );
|
||||||
|
nchain = convertor( nchain );
|
||||||
|
Elf_Word val = elf_hash( (const unsigned char*)name.c_str() );
|
||||||
|
Elf_Word y =
|
||||||
|
*(const Elf_Word*)( hash_section->get_data() +
|
||||||
|
( 2 + val % nbucket ) * sizeof( Elf_Word ) );
|
||||||
|
y = convertor( y );
|
||||||
|
std::string str;
|
||||||
|
get_symbol( y, str, value, size, bind, type, section_index, other );
|
||||||
|
while ( str != name && STN_UNDEF != y && y < nchain ) {
|
||||||
|
y = *(const Elf_Word*)( hash_section->get_data() +
|
||||||
|
( 2 + nbucket + y ) * sizeof( Elf_Word ) );
|
||||||
|
y = convertor( y );
|
||||||
|
get_symbol( y, str, value, size, bind, type, section_index, other );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( str == name ) {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
bool
|
bool gnu_hash_lookup( const std::string& name,
|
||||||
generic_get_symbol( Elf_Xword index,
|
Elf64_Addr& value,
|
||||||
std::string& name, Elf64_Addr& value,
|
Elf_Xword& size,
|
||||||
Elf_Xword& size,
|
unsigned char& bind,
|
||||||
unsigned char& bind, unsigned char& type,
|
unsigned char& type,
|
||||||
Elf_Half& section_index,
|
Elf_Half& section_index,
|
||||||
unsigned char& other ) const
|
unsigned char& other ) const
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
uint32_t nbuckets = *( (uint32_t*)hash_section->get_data() + 0 );
|
||||||
|
uint32_t symoffset = *( (uint32_t*)hash_section->get_data() + 1 );
|
||||||
|
uint32_t bloom_size = *( (uint32_t*)hash_section->get_data() + 2 );
|
||||||
|
uint32_t bloom_shift = *( (uint32_t*)hash_section->get_data() + 3 );
|
||||||
|
nbuckets = convertor( nbuckets );
|
||||||
|
symoffset = convertor( symoffset );
|
||||||
|
bloom_size = convertor( bloom_size );
|
||||||
|
bloom_shift = convertor( bloom_shift );
|
||||||
|
|
||||||
|
T* bloom_filter =
|
||||||
|
(T*)( hash_section->get_data() + 4 * sizeof( uint32_t ) );
|
||||||
|
|
||||||
|
uint32_t hash = elf_gnu_hash( (const unsigned char*)name.c_str() );
|
||||||
|
uint32_t bloom_index = ( hash / ( 8 * sizeof( T ) ) ) % bloom_size;
|
||||||
|
T bloom_bits =
|
||||||
|
( (T)1 << ( hash % ( 8 * sizeof( T ) ) ) ) |
|
||||||
|
( (T)1 << ( ( hash >> bloom_shift ) % ( 8 * sizeof( T ) ) ) );
|
||||||
|
|
||||||
|
if ( ( convertor( bloom_filter[bloom_index] ) & bloom_bits ) !=
|
||||||
|
bloom_bits )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
uint32_t bucket = hash % nbuckets;
|
||||||
|
auto* buckets =
|
||||||
|
(uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) +
|
||||||
|
bloom_size * sizeof( T ) );
|
||||||
|
auto* chains =
|
||||||
|
(uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) +
|
||||||
|
bloom_size * sizeof( T ) +
|
||||||
|
nbuckets * sizeof( uint32_t ) );
|
||||||
|
|
||||||
|
if ( convertor( buckets[bucket] ) >= symoffset ) {
|
||||||
|
uint32_t chain_index = convertor( buckets[bucket] ) - symoffset;
|
||||||
|
uint32_t chain_hash = convertor( chains[chain_index] );
|
||||||
|
std::string symname;
|
||||||
|
|
||||||
|
while ( true ) {
|
||||||
|
if ( ( chain_hash >> 1 ) == ( hash >> 1 ) &&
|
||||||
|
get_symbol( chain_index + symoffset, symname, value, size,
|
||||||
|
bind, type, section_index, other ) &&
|
||||||
|
name == symname ) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( chain_hash & 1 )
|
||||||
|
break;
|
||||||
|
chain_hash = convertor( chains[++chain_index] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template <class T> const T* generic_get_symbol_ptr( Elf_Xword index ) const
|
||||||
|
{
|
||||||
|
if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) {
|
||||||
|
const T* pSym = reinterpret_cast<const T*>(
|
||||||
|
symbol_section->get_data() +
|
||||||
|
index * symbol_section->get_entry_size() );
|
||||||
|
|
||||||
|
return pSym;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template <class T>
|
||||||
|
bool generic_search_symbols( std::function<bool( const T* )> match,
|
||||||
|
Elf_Xword& idx ) const
|
||||||
|
{
|
||||||
|
for ( Elf_Xword i = 0; i < get_symbols_num(); i++ ) {
|
||||||
|
const T* symPtr = generic_get_symbol_ptr<T>( i );
|
||||||
|
|
||||||
|
if ( symPtr == nullptr )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( match( symPtr ) ) {
|
||||||
|
idx = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template <class T>
|
||||||
|
bool generic_get_symbol( Elf_Xword index,
|
||||||
|
std::string& name,
|
||||||
|
Elf64_Addr& value,
|
||||||
|
Elf_Xword& size,
|
||||||
|
unsigned char& bind,
|
||||||
|
unsigned char& type,
|
||||||
|
Elf_Half& section_index,
|
||||||
|
unsigned char& other ) const
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
if ( index < get_symbols_num() ) {
|
if ( nullptr != symbol_section->get_data() &&
|
||||||
|
index < get_symbols_num() ) {
|
||||||
const T* pSym = reinterpret_cast<const T*>(
|
const T* pSym = reinterpret_cast<const T*>(
|
||||||
symbol_section->get_data() +
|
symbol_section->get_data() +
|
||||||
index * symbol_section->get_entry_size() );
|
index * symbol_section->get_entry_size() );
|
||||||
|
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
section* string_section = elf_file.sections[get_string_table_index()];
|
section* string_section =
|
||||||
|
elf_file.sections[get_string_table_index()];
|
||||||
string_section_accessor str_reader( string_section );
|
string_section_accessor str_reader( string_section );
|
||||||
const char* pStr = str_reader.get_string( convertor( pSym->st_name ) );
|
const char* pStr =
|
||||||
if ( 0 != pStr ) {
|
str_reader.get_string( convertor( pSym->st_name ) );
|
||||||
|
if ( nullptr != pStr ) {
|
||||||
name = pStr;
|
name = pStr;
|
||||||
}
|
}
|
||||||
value = convertor( pSym->st_value );
|
value = convertor( pSym->st_value );
|
||||||
size = convertor( pSym->st_size );
|
size = convertor( pSym->st_size );
|
||||||
bind = ELF_ST_BIND( pSym->st_info );
|
bind = ELF_ST_BIND( pSym->st_info );
|
||||||
type = ELF_ST_TYPE( pSym->st_info );
|
type = ELF_ST_TYPE( pSym->st_info );
|
||||||
section_index = convertor( pSym->st_shndx );
|
section_index = convertor( pSym->st_shndx );
|
||||||
other = pSym->st_other;
|
other = pSym->st_other;
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
@ -240,20 +467,22 @@ class symbol_section_accessor_template
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
template< class T >
|
template <class T>
|
||||||
Elf_Word
|
Elf_Word generic_add_symbol( Elf_Word name,
|
||||||
generic_add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
|
Elf64_Addr value,
|
||||||
unsigned char info, unsigned char other,
|
Elf_Xword size,
|
||||||
Elf_Half shndx )
|
unsigned char info,
|
||||||
|
unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
{
|
{
|
||||||
const endianess_convertor& convertor = elf_file.get_convertor();
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
T entry;
|
T entry;
|
||||||
entry.st_name = convertor( name );
|
entry.st_name = convertor( name );
|
||||||
entry.st_value = value;
|
entry.st_value = decltype( entry.st_value )( value );
|
||||||
entry.st_value = convertor( entry.st_value );
|
entry.st_value = convertor( entry.st_value );
|
||||||
entry.st_size = size;
|
entry.st_size = decltype( entry.st_size )( size );
|
||||||
entry.st_size = convertor( entry.st_size );
|
entry.st_size = convertor( entry.st_size );
|
||||||
entry.st_info = convertor( info );
|
entry.st_info = convertor( info );
|
||||||
entry.st_other = convertor( other );
|
entry.st_other = convertor( other );
|
||||||
@ -262,21 +491,71 @@ class symbol_section_accessor_template
|
|||||||
symbol_section->append_data( reinterpret_cast<char*>( &entry ),
|
symbol_section->append_data( reinterpret_cast<char*>( &entry ),
|
||||||
sizeof( entry ) );
|
sizeof( entry ) );
|
||||||
|
|
||||||
Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1;
|
Elf_Word nRet =
|
||||||
|
Elf_Word( symbol_section->get_size() / sizeof( entry ) - 1 );
|
||||||
|
|
||||||
return nRet;
|
return nRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
template <class T>
|
||||||
|
Elf_Xword generic_arrange_local_symbols(
|
||||||
|
std::function<void( Elf_Xword first, Elf_Xword second )> func )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
Elf_Word first_not_local =
|
||||||
|
1; // Skip the first entry. It is always NOTYPE
|
||||||
|
Elf_Xword current = 0;
|
||||||
|
Elf_Xword count = get_symbols_num();
|
||||||
|
|
||||||
|
while ( true ) {
|
||||||
|
T* p1 = nullptr;
|
||||||
|
T* p2 = nullptr;
|
||||||
|
|
||||||
|
while ( first_not_local < count ) {
|
||||||
|
p1 = const_cast<T*>(
|
||||||
|
generic_get_symbol_ptr<T>( first_not_local ) );
|
||||||
|
if ( ELF_ST_BIND( convertor( p1->st_info ) ) != STB_LOCAL )
|
||||||
|
break;
|
||||||
|
++first_not_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = first_not_local + 1;
|
||||||
|
while ( current < count ) {
|
||||||
|
p2 = const_cast<T*>( generic_get_symbol_ptr<T>( current ) );
|
||||||
|
if ( ELF_ST_BIND( convertor( p2->st_info ) ) == STB_LOCAL )
|
||||||
|
break;
|
||||||
|
++current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( first_not_local < count && current < count ) {
|
||||||
|
if ( func )
|
||||||
|
func( first_not_local, current );
|
||||||
|
|
||||||
|
std::swap( *p1, *p2 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Update 'info' field of the section
|
||||||
|
symbol_section->set_info( first_not_local );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return first_not_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
const elfio& elf_file;
|
const elfio& elf_file;
|
||||||
S* symbol_section;
|
S* symbol_section;
|
||||||
Elf_Half hash_section_index;
|
Elf_Half hash_section_index{ 0 };
|
||||||
const section* hash_section;
|
const section* hash_section{ nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
using symbol_section_accessor = symbol_section_accessor_template<section>;
|
using symbol_section_accessor = symbol_section_accessor_template<section>;
|
||||||
using const_symbol_section_accessor = symbol_section_accessor_template<const section>;
|
using const_symbol_section_accessor =
|
||||||
|
symbol_section_accessor_template<const section>;
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
Copyright (C) 2001-present by Serge Lamikhov-Center
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,158 +23,130 @@ THE SOFTWARE.
|
|||||||
#ifndef ELFIO_UTILS_HPP
|
#ifndef ELFIO_UTILS_HPP
|
||||||
#define ELFIO_UTILS_HPP
|
#define ELFIO_UTILS_HPP
|
||||||
|
|
||||||
#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \
|
#include <cstdint>
|
||||||
TYPE get_##NAME() const \
|
#include <ostream>
|
||||||
{ \
|
|
||||||
return (*convertor)( FIELD ); \
|
|
||||||
}
|
|
||||||
#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \
|
|
||||||
void set_##NAME( TYPE value ) \
|
|
||||||
{ \
|
|
||||||
FIELD = value; \
|
|
||||||
FIELD = (*convertor)( FIELD ); \
|
|
||||||
}
|
|
||||||
#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \
|
|
||||||
TYPE get_##NAME() const \
|
|
||||||
{ \
|
|
||||||
return (*convertor)( FIELD ); \
|
|
||||||
} \
|
|
||||||
void set_##NAME( TYPE value ) \
|
|
||||||
{ \
|
|
||||||
FIELD = value; \
|
|
||||||
FIELD = (*convertor)( FIELD ); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) \
|
#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0
|
||||||
virtual TYPE get_##NAME() const = 0
|
|
||||||
|
|
||||||
#define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \
|
#define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \
|
||||||
virtual void set_##NAME( TYPE value ) = 0
|
virtual void set_##NAME( const TYPE& value ) = 0
|
||||||
|
|
||||||
#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \
|
#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \
|
||||||
virtual TYPE get_##NAME() const = 0; \
|
virtual TYPE get_##NAME() const = 0; \
|
||||||
virtual void set_##NAME( TYPE value ) = 0
|
virtual void set_##NAME( const TYPE& value ) = 0
|
||||||
|
|
||||||
|
#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \
|
||||||
|
TYPE get_##NAME() const override { return ( *convertor )( FIELD ); }
|
||||||
|
|
||||||
|
#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \
|
||||||
|
void set_##NAME( const TYPE& value ) override \
|
||||||
|
{ \
|
||||||
|
FIELD = decltype( FIELD )( value ); \
|
||||||
|
FIELD = ( *convertor )( FIELD ); \
|
||||||
|
}
|
||||||
|
#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \
|
||||||
|
TYPE get_##NAME() const override { return ( *convertor )( FIELD ); } \
|
||||||
|
void set_##NAME( const TYPE& value ) override \
|
||||||
|
{ \
|
||||||
|
FIELD = decltype( FIELD )( value ); \
|
||||||
|
FIELD = ( *convertor )( FIELD ); \
|
||||||
|
}
|
||||||
|
|
||||||
namespace ELFIO {
|
namespace ELFIO {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class endianess_convertor {
|
class endianess_convertor
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
endianess_convertor()
|
void setup( unsigned char elf_file_encoding )
|
||||||
{
|
|
||||||
need_conversion = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
setup( unsigned char elf_file_encoding )
|
|
||||||
{
|
{
|
||||||
need_conversion = ( elf_file_encoding != get_host_encoding() );
|
need_conversion = ( elf_file_encoding != get_host_encoding() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
uint64_t
|
uint64_t operator()( uint64_t value ) const
|
||||||
operator()( uint64_t value ) const
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
value = ( ( value & 0x00000000000000FFuLL ) << 56 ) |
|
||||||
|
( ( value & 0x000000000000FF00uLL ) << 40 ) |
|
||||||
|
( ( value & 0x0000000000FF0000uLL ) << 24 ) |
|
||||||
|
( ( value & 0x00000000FF000000uLL ) << 8 ) |
|
||||||
|
( ( value & 0x000000FF00000000uLL ) >> 8 ) |
|
||||||
|
( ( value & 0x0000FF0000000000uLL ) >> 24 ) |
|
||||||
|
( ( value & 0x00FF000000000000uLL ) >> 40 ) |
|
||||||
|
( ( value & 0xFF00000000000000uLL ) >> 56 );
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
int64_t operator()( int64_t value ) const
|
||||||
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return (int64_t)( *this )( (uint64_t)value );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
uint32_t operator()( uint32_t value ) const
|
||||||
{
|
{
|
||||||
if ( !need_conversion ) {
|
if ( !need_conversion ) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
value =
|
value =
|
||||||
( ( value & 0x00000000000000FFull ) << 56 ) |
|
( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) |
|
||||||
( ( value & 0x000000000000FF00ull ) << 40 ) |
|
( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 );
|
||||||
( ( value & 0x0000000000FF0000ull ) << 24 ) |
|
|
||||||
( ( value & 0x00000000FF000000ull ) << 8 ) |
|
|
||||||
( ( value & 0x000000FF00000000ull ) >> 8 ) |
|
|
||||||
( ( value & 0x0000FF0000000000ull ) >> 24 ) |
|
|
||||||
( ( value & 0x00FF000000000000ull ) >> 40 ) |
|
|
||||||
( ( value & 0xFF00000000000000ull ) >> 56 );
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
int64_t
|
int32_t operator()( int32_t value ) const
|
||||||
operator()( int64_t value ) const
|
|
||||||
{
|
{
|
||||||
if ( !need_conversion ) {
|
if ( !need_conversion ) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return (int64_t)(*this)( (uint64_t)value );
|
return (int32_t)( *this )( (uint32_t)value );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
uint32_t
|
uint16_t operator()( uint16_t value ) const
|
||||||
operator()( uint32_t value ) const
|
|
||||||
{
|
{
|
||||||
if ( !need_conversion ) {
|
if ( !need_conversion ) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
value =
|
value =
|
||||||
( ( value & 0x000000FF ) << 24 ) |
|
(uint16_t)( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 );
|
||||||
( ( value & 0x0000FF00 ) << 8 ) |
|
|
||||||
( ( value & 0x00FF0000 ) >> 8 ) |
|
|
||||||
( ( value & 0xFF000000 ) >> 24 );
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
int32_t
|
int16_t operator()( int16_t value ) const
|
||||||
operator()( int32_t value ) const
|
|
||||||
{
|
{
|
||||||
if ( !need_conversion ) {
|
if ( !need_conversion ) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return (int32_t)(*this)( (uint32_t)value );
|
return (int16_t)( *this )( (uint16_t)value );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
uint16_t
|
int8_t operator()( int8_t value ) const { return value; }
|
||||||
operator()( uint16_t value ) const
|
|
||||||
{
|
|
||||||
if ( !need_conversion ) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
value =
|
|
||||||
( ( value & 0x00FF ) << 8 ) |
|
|
||||||
( ( value & 0xFF00 ) >> 8 );
|
|
||||||
|
|
||||||
return value;
|
//------------------------------------------------------------------------------
|
||||||
}
|
uint8_t operator()( uint8_t value ) const { return value; }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
int16_t
|
|
||||||
operator()( int16_t value ) const
|
|
||||||
{
|
|
||||||
if ( !need_conversion ) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return (int16_t)(*this)( (uint16_t)value );
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
int8_t
|
|
||||||
operator()( int8_t value ) const
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
uint8_t
|
|
||||||
operator()( uint8_t value ) const
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
private:
|
private:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
unsigned char
|
unsigned char get_host_encoding() const
|
||||||
get_host_encoding() const
|
|
||||||
{
|
{
|
||||||
static const int tmp = 1;
|
static const int tmp = 1;
|
||||||
if ( 1 == *(const char*)&tmp ) {
|
if ( 1 == *reinterpret_cast<const char*>( &tmp ) ) {
|
||||||
return ELFDATA2LSB;
|
return ELFDATA2LSB;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -183,20 +154,65 @@ class endianess_convertor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
bool need_conversion = false;
|
||||||
bool need_conversion;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
struct address_translation
|
||||||
|
{
|
||||||
|
address_translation( uint64_t start, uint64_t size, uint64_t mapped_to )
|
||||||
|
: start( start ), size( size ), mapped_to( mapped_to ){};
|
||||||
|
std::streampos start;
|
||||||
|
std::streampos size;
|
||||||
|
std::streampos mapped_to;
|
||||||
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
inline
|
class address_translator
|
||||||
uint32_t
|
|
||||||
elf_hash( const unsigned char *name )
|
|
||||||
{
|
{
|
||||||
uint32_t h = 0, g;
|
public:
|
||||||
while ( *name ) {
|
//------------------------------------------------------------------------------
|
||||||
h = (h << 4) + *name++;
|
void set_address_translation( std::vector<address_translation>& addr_trans )
|
||||||
|
{
|
||||||
|
addr_translations = addr_trans;
|
||||||
|
|
||||||
|
std::sort(
|
||||||
|
addr_translations.begin(), addr_translations.end(),
|
||||||
|
[]( address_translation& a, address_translation& b ) -> bool {
|
||||||
|
return a.start < b.start;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
std::streampos operator[]( std::streampos value ) const
|
||||||
|
{
|
||||||
|
if ( addr_translations.empty() ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto& t : addr_translations ) {
|
||||||
|
if ( ( t.start <= value ) && ( ( value - t.start ) < t.size ) ) {
|
||||||
|
return value - t.start + t.mapped_to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const { return addr_translations.empty(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<address_translation> addr_translations;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
inline uint32_t elf_hash( const unsigned char* name )
|
||||||
|
{
|
||||||
|
uint32_t h = 0;
|
||||||
|
uint32_t g = 0;
|
||||||
|
while ( *name != '\0' ) {
|
||||||
|
h = ( h << 4 ) + *name++;
|
||||||
g = h & 0xf0000000;
|
g = h & 0xf0000000;
|
||||||
if ( g != 0 )
|
if ( g != 0 )
|
||||||
h ^= g >> 24;
|
h ^= g >> 24;
|
||||||
@ -205,6 +221,83 @@ elf_hash( const unsigned char *name )
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
inline uint32_t elf_gnu_hash( const unsigned char* s )
|
||||||
|
{
|
||||||
|
uint32_t h = 0x1505;
|
||||||
|
for ( unsigned char c = *s; c != '\0'; c = *++s )
|
||||||
|
h = ( h << 5 ) + h + c;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
inline std::string to_hex_string( uint64_t value )
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
while ( value ) {
|
||||||
|
auto digit = value & 0xF;
|
||||||
|
if ( digit < 0xA ) {
|
||||||
|
str = char( '0' + digit ) + str;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = char( 'A' + digit - 0xA ) + str;
|
||||||
|
}
|
||||||
|
value >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "0x" + str;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
inline void adjust_stream_size( std::ostream& stream, std::streamsize offset )
|
||||||
|
{
|
||||||
|
stream.seekp( 0, std::ios_base::end );
|
||||||
|
if ( stream.tellp() < offset ) {
|
||||||
|
std::streamsize size = offset - stream.tellp();
|
||||||
|
stream.write( std::string( size_t( size ), '\0' ).c_str(), size );
|
||||||
|
}
|
||||||
|
stream.seekp( offset );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumers should write an implementation of this class and pass an instance of it to the ELFIO::elfio constructor.
|
||||||
|
*/
|
||||||
|
class compression_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~compression_interface() = default;
|
||||||
|
/**
|
||||||
|
* decompresses a compressed section
|
||||||
|
*
|
||||||
|
* @param data the buffer of compressed data
|
||||||
|
* @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness.
|
||||||
|
* @param compressed_size the size of the data buffer, in bytes
|
||||||
|
* @param decompressed_size a reference to a variable where the decompressed buffer size will be stored.
|
||||||
|
* @returns a smart pointer to the decompressed data.
|
||||||
|
*/
|
||||||
|
virtual std::unique_ptr<char[]>
|
||||||
|
inflate( const char* data,
|
||||||
|
const endianess_convertor* convertor,
|
||||||
|
Elf_Xword compressed_size,
|
||||||
|
Elf_Xword& uncompressed_size ) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* compresses a section
|
||||||
|
*
|
||||||
|
* @param data the buffer of uncompressed data
|
||||||
|
* @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness.
|
||||||
|
* @param decompressed_size the size of the data buffer, in bytes
|
||||||
|
* @param compressed_size a reference to a variable where the compressed buffer size will be stored.
|
||||||
|
* @returns a smart pointer to the compressed data.
|
||||||
|
*/
|
||||||
|
virtual std::unique_ptr<char[]>
|
||||||
|
deflate( const char* data,
|
||||||
|
const endianess_convertor* convertor,
|
||||||
|
Elf_Xword decompressed_size,
|
||||||
|
Elf_Xword& compressed_size ) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
|
||||||
#endif // ELFIO_UTILS_HPP
|
#endif // ELFIO_UTILS_HPP
|
||||||
|
1
source/elfio/elfio_version.hpp
Normal file
1
source/elfio/elfio_version.hpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#define ELFIO_VERSION "3.12"
|
179
source/elfio/elfio_versym.hpp
Normal file
179
source/elfio/elfio_versym.hpp
Normal 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
|
@ -18,6 +18,8 @@
|
|||||||
#include "PluginInformationFactory.h"
|
#include "PluginInformationFactory.h"
|
||||||
#include "../utils/ElfUtils.h"
|
#include "../utils/ElfUtils.h"
|
||||||
#include "../utils/utils.h"
|
#include "../utils/utils.h"
|
||||||
|
#include "utils/membuf.hpp"
|
||||||
|
#include "utils/wiiu_zlib.hpp"
|
||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -33,8 +35,11 @@ PluginInformationFactory::load(const std::shared_ptr<PluginData> &pluginData, re
|
|||||||
DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr");
|
DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
elfio reader;
|
elfio reader(new wiiu_zlib);
|
||||||
if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) {
|
membuf sbuf((char *) pluginData->buffer.get(), (char *) pluginData->buffer.get() + pluginData->length);
|
||||||
|
std::istream in(&sbuf);
|
||||||
|
|
||||||
|
if (!reader.load(in)) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
|
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -302,17 +307,31 @@ bool PluginInformationFactory::addImportRelocationData(const std::unique_ptr<Plu
|
|||||||
DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str());
|
DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str());
|
||||||
relocation_section_accessor rel(reader, psec);
|
relocation_section_accessor rel(reader, psec);
|
||||||
for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) {
|
for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) {
|
||||||
|
Elf_Word symbol = 0;
|
||||||
Elf64_Addr offset;
|
Elf64_Addr offset;
|
||||||
Elf_Word type;
|
Elf_Word type;
|
||||||
Elf_Sxword addend;
|
Elf_Sxword addend;
|
||||||
std::string sym_name;
|
std::string sym_name;
|
||||||
Elf64_Addr sym_value;
|
Elf64_Addr sym_value;
|
||||||
Elf_Half sym_section_index;
|
|
||||||
|
|
||||||
if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) {
|
if (!rel.get_entry(j, offset, symbol, type, addend)) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get relocation");
|
DEBUG_FUNCTION_LINE_ERR("Failed to get relocation");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
symbol_section_accessor symbols(reader, reader.sections[(Elf_Half) psec->get_link()]);
|
||||||
|
|
||||||
|
// Find the symbol
|
||||||
|
Elf_Xword size;
|
||||||
|
unsigned char bind;
|
||||||
|
unsigned char symbolType;
|
||||||
|
Elf_Half sym_section_index;
|
||||||
|
unsigned char other;
|
||||||
|
|
||||||
|
if (!symbols.get_symbol(symbol, sym_name, sym_value, size,
|
||||||
|
bind, symbolType, sym_section_index, other)) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to get symbol");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto adjusted_sym_value = (uint32_t) sym_value;
|
auto adjusted_sym_value = (uint32_t) sym_value;
|
||||||
if (adjusted_sym_value < 0xC0000000) {
|
if (adjusted_sym_value < 0xC0000000) {
|
||||||
@ -354,16 +373,30 @@ bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section
|
|||||||
DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str());
|
DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str());
|
||||||
relocation_section_accessor rel(reader, psec);
|
relocation_section_accessor rel(reader, psec);
|
||||||
for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) {
|
for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) {
|
||||||
|
Elf_Word symbol = 0;
|
||||||
Elf64_Addr offset;
|
Elf64_Addr offset;
|
||||||
Elf_Word type;
|
Elf_Word type;
|
||||||
Elf_Sxword addend;
|
Elf_Sxword addend;
|
||||||
std::string sym_name;
|
std::string sym_name;
|
||||||
Elf64_Addr sym_value;
|
Elf64_Addr sym_value;
|
||||||
Elf_Half sym_section_index;
|
|
||||||
|
|
||||||
if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) {
|
if (!rel.get_entry(j, offset, symbol, type, addend)) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get relocation");
|
DEBUG_FUNCTION_LINE_ERR("Failed to get relocation");
|
||||||
break;
|
return false;
|
||||||
|
}
|
||||||
|
symbol_section_accessor symbols(reader, reader.sections[(Elf_Half) psec->get_link()]);
|
||||||
|
|
||||||
|
// Find the symbol
|
||||||
|
Elf_Xword size;
|
||||||
|
unsigned char bind;
|
||||||
|
unsigned char symbolType;
|
||||||
|
Elf_Half sym_section_index;
|
||||||
|
unsigned char other;
|
||||||
|
|
||||||
|
if (!symbols.get_symbol(symbol, sym_name, sym_value, size,
|
||||||
|
bind, symbolType, sym_section_index, other)) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to get symbol");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto adjusted_sym_value = (uint32_t) sym_value;
|
auto adjusted_sym_value = (uint32_t) sym_value;
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
#include "PluginMetaInformationFactory.h"
|
#include "PluginMetaInformationFactory.h"
|
||||||
#include "elfio/elfio.hpp"
|
#include "elfio/elfio.hpp"
|
||||||
#include "fs/FSUtils.h"
|
#include "fs/FSUtils.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include "utils/membuf.hpp"
|
||||||
|
#include "utils/wiiu_zlib.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr<PluginData> &pluginData) {
|
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr<PluginData> &pluginData) {
|
||||||
@ -25,8 +28,10 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
|
|||||||
DEBUG_FUNCTION_LINE_ERR("Buffer is empty");
|
DEBUG_FUNCTION_LINE_ERR("Buffer is empty");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
ELFIO::elfio reader;
|
ELFIO::elfio reader(new wiiu_zlib);
|
||||||
if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) {
|
membuf sbuf((char *) pluginData->buffer.get(), (char *) pluginData->buffer.get() + pluginData->length);
|
||||||
|
std::istream in(&sbuf);
|
||||||
|
if (!reader.load(in)) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
|
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -34,7 +39,7 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::string &filePath) {
|
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(const std::string &filePath) {
|
||||||
ELFIO::elfio reader;
|
ELFIO::elfio reader(new wiiu_zlib);
|
||||||
|
|
||||||
uint8_t *buffer = nullptr;
|
uint8_t *buffer = nullptr;
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
@ -43,7 +48,10 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reader.load((char *) buffer, length)) {
|
membuf sbuf((char *) buffer, (char *) buffer + length);
|
||||||
|
std::istream in(&sbuf);
|
||||||
|
|
||||||
|
if (!reader.load(in)) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
|
DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -53,8 +61,12 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size) {
|
std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size) {
|
||||||
ELFIO::elfio reader;
|
ELFIO::elfio reader(new wiiu_zlib);
|
||||||
if (!reader.load(buffer, size)) {
|
|
||||||
|
membuf sbuf((char *) buffer, (char *) buffer + size);
|
||||||
|
std::istream in(&sbuf);
|
||||||
|
|
||||||
|
if (!reader.load(in)) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file");
|
DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
@ -73,7 +85,7 @@ std::optional<std::unique_ptr<PluginMetaInformation>> PluginMetaInformationFacto
|
|||||||
ELFIO::section *psec = reader.sections[i];
|
ELFIO::section *psec = reader.sections[i];
|
||||||
|
|
||||||
// Calculate total size:
|
// Calculate total size:
|
||||||
if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) {
|
if ((psec->get_type() == ELFIO::SHT_PROGBITS || psec->get_type() == ELFIO::SHT_NOBITS) && (psec->get_flags() & ELFIO::SHF_ALLOC)) {
|
||||||
uint32_t sectionSize = psec->get_size();
|
uint32_t sectionSize = psec->get_size();
|
||||||
auto address = (uint32_t) psec->get_address();
|
auto address = (uint32_t) psec->get_address();
|
||||||
if ((address >= 0x02000000) && address < 0x10000000) {
|
if ((address >= 0x02000000) && address < 0x10000000) {
|
||||||
|
23
source/utils/membuf.hpp
Normal file
23
source/utils/membuf.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct membuf : std::streambuf {
|
||||||
|
membuf(char *begin, char *end) {
|
||||||
|
this->setg(begin, begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override {
|
||||||
|
if (dir == std::ios_base::cur)
|
||||||
|
gbump(off);
|
||||||
|
else if (dir == std::ios_base::end)
|
||||||
|
setg(eback(), egptr() + off, egptr());
|
||||||
|
else if (dir == std::ios_base::beg)
|
||||||
|
setg(eback(), eback() + off, egptr());
|
||||||
|
return gptr() - eback();
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
|
||||||
|
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
|
||||||
|
}
|
||||||
|
};
|
119
source/utils/wiiu_zlib.hpp
Normal file
119
source/utils/wiiu_zlib.hpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Copyright (C) 2018-2020 Nathan Strong
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "elfio/elfio_utils.hpp"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
class wiiu_zlib : public ELFIO::compression_interface {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<char[]> inflate(const char *data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword compressed_size, ELFIO::Elf_Xword &uncompressed_size) const override {
|
||||||
|
read_uncompressed_size(data, convertor, uncompressed_size);
|
||||||
|
auto result = make_unique_nothrow<char[]>((uint32_t) (uncompressed_size + 1));
|
||||||
|
if (result == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int z_ret;
|
||||||
|
z_stream s = {nullptr};
|
||||||
|
|
||||||
|
s.zalloc = Z_NULL;
|
||||||
|
s.zfree = Z_NULL;
|
||||||
|
s.opaque = Z_NULL;
|
||||||
|
|
||||||
|
if (inflateInit_(&s, ZLIB_VERSION, sizeof(s)) != Z_OK) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.avail_in = compressed_size - 4;
|
||||||
|
s.next_in = (Bytef *) data;
|
||||||
|
s.avail_out = uncompressed_size;
|
||||||
|
s.next_out = (Bytef *) result.get();
|
||||||
|
|
||||||
|
z_ret = ::inflate(&s, Z_FINISH);
|
||||||
|
inflateEnd(&s);
|
||||||
|
|
||||||
|
if (z_ret != Z_OK && z_ret != Z_STREAM_END) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[uncompressed_size] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<char[]> deflate(const char *data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword decompressed_size, ELFIO::Elf_Xword &compressed_size) const override {
|
||||||
|
auto result = make_unique_nothrow<char[]>((uint32_t) (decompressed_size));
|
||||||
|
if (result == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int z_ret = 0;
|
||||||
|
z_stream s = {nullptr};
|
||||||
|
|
||||||
|
s.zalloc = Z_NULL;
|
||||||
|
s.zfree = Z_NULL;
|
||||||
|
s.opaque = Z_NULL;
|
||||||
|
|
||||||
|
if ((z_ret = deflateInit(&s, Z_DEFAULT_COMPRESSION)) != Z_OK) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.avail_in = decompressed_size;
|
||||||
|
s.next_in = (Bytef *) data;
|
||||||
|
s.avail_out = decompressed_size - 4;
|
||||||
|
s.next_out = (Bytef *) result.get() + 4;
|
||||||
|
|
||||||
|
z_ret = ::deflate(&s, Z_FINISH);
|
||||||
|
compressed_size = decompressed_size - s.avail_out;
|
||||||
|
deflateEnd(&s);
|
||||||
|
|
||||||
|
if (z_ret != Z_OK && z_ret != Z_STREAM_END) {
|
||||||
|
compressed_size = 0;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_compressed_size(result, convertor, compressed_size);
|
||||||
|
result[compressed_size] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void read_uncompressed_size(const char *&data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword &uncompressed_size) {
|
||||||
|
union _int32buffer {
|
||||||
|
uint32_t word;
|
||||||
|
char bytes[4];
|
||||||
|
} int32buffer;
|
||||||
|
memcpy(int32buffer.bytes, data, 4);
|
||||||
|
data += 4;
|
||||||
|
uncompressed_size = (*convertor)(int32buffer.word);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_compressed_size(std::unique_ptr<char[]> &result, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword compressed_size) {
|
||||||
|
union _int32buffer {
|
||||||
|
uint32_t word;
|
||||||
|
char bytes[4];
|
||||||
|
} int32buffer;
|
||||||
|
|
||||||
|
int32buffer.word = (*convertor)(compressed_size);
|
||||||
|
memcpy(result.get(), int32buffer.bytes, 4);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user