Remove the IR for know for simplicity

This commit is contained in:
2024-03-01 10:13:55 +01:00
parent f37700a02d
commit 3a6d89767b
36 changed files with 7547 additions and 1079 deletions

1347
include/elfio/elf_types.hpp Normal file

File diff suppressed because it is too large Load Diff

1096
include/elfio/elfio.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

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

1346
include/elfio/elfio_dump.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,274 @@
/*
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_DYNAMIC_HPP
#define ELFIO_DYNAMIC_HPP
#include <algorithm>
namespace ELFIO {
//------------------------------------------------------------------------------
template <class S> class dynamic_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit dynamic_section_accessor_template( const elfio& elf_file,
S* section )
: elf_file( elf_file ), dynamic_section( section ), entries_num( 0 )
{
}
//------------------------------------------------------------------------------
Elf_Xword get_entries_num() const
{
size_t needed_entry_size = -1;
if ( elf_file.get_class() == ELFCLASS32 ) {
needed_entry_size = sizeof( Elf32_Dyn );
}
else {
needed_entry_size = sizeof( Elf64_Dyn );
}
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 get_entry( Elf_Xword index,
Elf_Xword& tag,
Elf_Xword& value,
std::string& str ) const
{
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_get_entry_dyn<Elf32_Dyn>( index, tag, value );
}
else {
generic_get_entry_dyn<Elf64_Dyn>( index, tag, value );
}
// If the tag has a string table reference - prepare the string
if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH ||
tag == DT_RUNPATH ) {
string_section_accessor strsec(
elf_file.sections[get_string_table_index()] );
const char* result = strsec.get_string( (Elf_Word)value );
if ( nullptr == result ) {
str.clear();
return false;
}
str = result;
}
else {
str.clear();
}
return true;
}
//------------------------------------------------------------------------------
void add_entry( Elf_Xword tag, Elf_Xword value )
{
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry_dyn<Elf32_Dyn>( tag, value );
}
else {
generic_add_entry_dyn<Elf64_Dyn>( tag, value );
}
}
//------------------------------------------------------------------------------
void add_entry( Elf_Xword tag, const std::string& str )
{
string_section_accessor strsec(
elf_file.sections[get_string_table_index()] );
Elf_Xword value = strsec.add_string( str );
add_entry( tag, value );
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
Elf_Half get_string_table_index() const
{
return (Elf_Half)dynamic_section->get_link();
}
//------------------------------------------------------------------------------
template <class T>
void generic_get_entry_dyn( Elf_Xword index,
Elf_Xword& tag,
Elf_Xword& value ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
// Check unusual case when dynamic section has no data
if ( dynamic_section->get_data() == nullptr ||
( index + 1 ) * dynamic_section->get_entry_size() >
dynamic_section->get_size() ||
dynamic_section->get_entry_size() < sizeof( T ) ) {
tag = DT_NULL;
value = 0;
return;
}
const T* pEntry = reinterpret_cast<const T*>(
dynamic_section->get_data() +
index * dynamic_section->get_entry_size() );
tag = convertor( pEntry->d_tag );
switch ( tag ) {
case DT_NULL:
case DT_SYMBOLIC:
case DT_TEXTREL:
case DT_BIND_NOW:
value = 0;
break;
case DT_NEEDED:
case DT_PLTRELSZ:
case DT_RELASZ:
case DT_RELAENT:
case DT_STRSZ:
case DT_SYMENT:
case DT_SONAME:
case DT_RPATH:
case DT_RELSZ:
case DT_RELENT:
case DT_PLTREL:
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_RUNPATH:
case DT_FLAGS:
case DT_PREINIT_ARRAYSZ:
value = convertor( pEntry->d_un.d_val );
break;
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_DEBUG:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY:
default:
value = convertor( pEntry->d_un.d_ptr );
break;
}
}
//------------------------------------------------------------------------------
template <class T>
void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T entry;
switch ( tag ) {
case DT_NULL:
case DT_SYMBOLIC:
case DT_TEXTREL:
case DT_BIND_NOW:
entry.d_un.d_val = convertor( decltype( entry.d_un.d_val )( 0 ) );
break;
case DT_NEEDED:
case DT_PLTRELSZ:
case DT_RELASZ:
case DT_RELAENT:
case DT_STRSZ:
case DT_SYMENT:
case DT_SONAME:
case DT_RPATH:
case DT_RELSZ:
case DT_RELENT:
case DT_PLTREL:
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_RUNPATH:
case DT_FLAGS:
case DT_PREINIT_ARRAYSZ:
entry.d_un.d_val =
convertor( decltype( entry.d_un.d_val )( value ) );
break;
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_DEBUG:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY:
default:
entry.d_un.d_ptr =
convertor( decltype( entry.d_un.d_val )( value ) );
break;
}
entry.d_tag = convertor( decltype( entry.d_tag )( tag ) );
dynamic_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* dynamic_section;
mutable Elf_Xword entries_num;
};
using dynamic_section_accessor = dynamic_section_accessor_template<section>;
using const_dynamic_section_accessor =
dynamic_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_DYNAMIC_HPP

View File

@ -0,0 +1,153 @@
/*
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 ELF_HEADER_HPP
#define ELF_HEADER_HPP
#include <iostream>
namespace ELFIO {
class elf_header
{
public:
virtual ~elf_header() = default;
virtual bool load( std::istream& stream ) = 0;
virtual bool save( std::ostream& stream ) const = 0;
// ELF header functions
ELFIO_GET_ACCESS_DECL( unsigned char, class );
ELFIO_GET_ACCESS_DECL( unsigned char, elf_version );
ELFIO_GET_ACCESS_DECL( unsigned char, encoding );
ELFIO_GET_ACCESS_DECL( Elf_Half, header_size );
ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size );
ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version );
ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi );
ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index );
};
template <class T> struct elf_header_impl_types;
template <> struct elf_header_impl_types<Elf32_Ehdr>
{
using Phdr_type = Elf32_Phdr;
using Shdr_type = Elf32_Shdr;
static const unsigned char file_class = ELFCLASS32;
};
template <> struct elf_header_impl_types<Elf64_Ehdr>
{
using Phdr_type = Elf64_Phdr;
using Shdr_type = Elf64_Shdr;
static const unsigned char file_class = ELFCLASS64;
};
template <class T> class elf_header_impl : public elf_header
{
public:
//------------------------------------------------------------------------------
elf_header_impl( endianess_convertor* convertor,
unsigned char encoding,
const address_translator* translator )
: convertor( convertor ), translator( translator )
{
header.e_ident[EI_MAG0] = ELFMAG0;
header.e_ident[EI_MAG1] = ELFMAG1;
header.e_ident[EI_MAG2] = ELFMAG2;
header.e_ident[EI_MAG3] = ELFMAG3;
header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class;
header.e_ident[EI_DATA] = encoding;
header.e_ident[EI_VERSION] = EV_CURRENT;
header.e_version = ( *convertor )( (Elf_Word)EV_CURRENT );
header.e_ehsize = ( sizeof( header ) );
header.e_ehsize = ( *convertor )( header.e_ehsize );
header.e_shstrndx = ( *convertor )( (Elf_Half)1 );
header.e_phentsize =
sizeof( typename elf_header_impl_types<T>::Phdr_type );
header.e_shentsize =
sizeof( typename elf_header_impl_types<T>::Shdr_type );
header.e_phentsize = ( *convertor )( header.e_phentsize );
header.e_shentsize = ( *convertor )( header.e_shentsize );
}
//------------------------------------------------------------------------------
bool load( std::istream& stream ) override
{
stream.seekg( ( *translator )[0] );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
return ( stream.gcount() == sizeof( header ) );
}
//------------------------------------------------------------------------------
bool save( std::ostream& stream ) const override
{
stream.seekp( ( *translator )[0] );
stream.write( reinterpret_cast<const char*>( &header ),
sizeof( header ) );
return stream.good();
}
//------------------------------------------------------------------------------
// ELF header functions
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, encoding, header.e_ident[EI_DATA] );
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, segment_entry_size, header.e_phentsize );
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,
abi_version,
header.e_ident[EI_ABIVERSION] );
ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type );
ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine );
ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags );
ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx );
ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry );
ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum );
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:
T header = {};
endianess_convertor* convertor = nullptr;
const address_translator* translator = nullptr;
};
} // namespace ELFIO
#endif // ELF_HEADER_HPP

View File

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

View File

@ -0,0 +1,184 @@
/*
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_NOTE_HPP
#define ELFIO_NOTE_HPP
namespace ELFIO {
//------------------------------------------------------------------------------
// There are discrepancies in documentations. SCO documentation
// (http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section)
// requires 8 byte entries alignment for 64-bit ELF file,
// but Oracle's definition uses the same structure
// for 32-bit and 64-bit formats.
// (https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html)
//
// It looks like EM_X86_64 Linux implementation is similar to Oracle's
// definition. Therefore, the same alignment works for both formats
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
template <class S, Elf_Xword ( S::*F_get_size )() const>
class note_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit note_section_accessor_template( const elfio& elf_file, S* section )
: elf_file( elf_file ), notes( section )
{
process_section();
}
//------------------------------------------------------------------------------
Elf_Word get_notes_num() const
{
return (Elf_Word)note_start_positions.size();
}
//------------------------------------------------------------------------------
bool get_note( Elf_Word index,
Elf_Word& type,
std::string& name,
char*& desc,
Elf_Word& descSize ) const
{
if ( index >= ( notes->*F_get_size )() ) {
return false;
}
const char* pData = notes->get_data() + note_start_positions[index];
int align = sizeof( Elf_Word );
const endianess_convertor& convertor = elf_file.get_convertor();
type = convertor( *(const Elf_Word*)( pData + 2 * (size_t)align ) );
Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) );
descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) );
Elf_Xword 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;
}
name.assign( pData + 3 * (size_t)align, namesz - 1 );
if ( 0 == descSize ) {
desc = nullptr;
}
else {
desc = const_cast<char*>( pData + 3 * (size_t)align +
( ( namesz + align - 1 ) / align ) *
(size_t)align );
}
return true;
}
//------------------------------------------------------------------------------
void add_note( Elf_Word type,
const std::string& name,
const char* desc,
Elf_Word descSize )
{
const endianess_convertor& convertor = elf_file.get_convertor();
int align = sizeof( Elf_Word );
Elf_Word nameLen = (Elf_Word)name.size() + 1;
Elf_Word nameLenConv = convertor( nameLen );
std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align );
Elf_Word descSizeConv = convertor( descSize );
buffer.append( reinterpret_cast<char*>( &descSizeConv ), align );
type = convertor( type );
buffer.append( reinterpret_cast<char*>( &type ), align );
buffer.append( name );
buffer.append( 1, '\x00' );
const char pad[] = { '\0', '\0', '\0', '\0' };
if ( nameLen % align != 0 ) {
buffer.append( pad, (size_t)align - nameLen % align );
}
if ( desc != nullptr && descSize != 0 ) {
buffer.append( desc, descSize );
if ( descSize % align != 0 ) {
buffer.append( pad, (size_t)align - descSize % align );
}
}
note_start_positions.emplace_back( ( notes->*F_get_size )() );
notes->append_data( buffer );
}
private:
//------------------------------------------------------------------------------
void process_section()
{
const endianess_convertor& convertor = elf_file.get_convertor();
const char* data = notes->get_data();
Elf_Xword size = ( notes->*F_get_size )();
Elf_Xword current = 0;
note_start_positions.clear();
// Is it empty?
if ( nullptr == data || 0 == size ) {
return;
}
Elf_Word align = sizeof( Elf_Word );
while ( current + (Elf_Xword)3 * align <= size ) {
Elf_Word namesz = convertor( *(const Elf_Word*)( data + current ) );
Elf_Word descsz = convertor(
*(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 += advance;
}
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* notes;
std::vector<Elf_Xword> note_start_positions;
};
using note_section_accessor =
note_section_accessor_template<section, &section::get_size>;
using const_note_section_accessor =
note_section_accessor_template<const section, &section::get_size>;
using note_segment_accessor =
note_section_accessor_template<segment, &segment::get_file_size>;
using const_note_segment_accessor =
note_section_accessor_template<const segment, &segment::get_file_size>;
} // namespace ELFIO
#endif // ELFIO_NOTE_HPP

View File

@ -0,0 +1,460 @@
/*
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_RELOCATION_HPP
#define ELFIO_RELOCATION_HPP
namespace ELFIO {
template <typename T> struct get_sym_and_type;
template <> struct get_sym_and_type<Elf32_Rel>
{
static int get_r_sym( Elf_Xword info )
{
return ELF32_R_SYM( (Elf_Word)info );
}
static int get_r_type( Elf_Xword info )
{
return ELF32_R_TYPE( (Elf_Word)info );
}
};
template <> struct get_sym_and_type<Elf32_Rela>
{
static int get_r_sym( Elf_Xword info )
{
return ELF32_R_SYM( (Elf_Word)info );
}
static int get_r_type( Elf_Xword info )
{
return ELF32_R_TYPE( (Elf_Word)info );
}
};
template <> struct get_sym_and_type<Elf64_Rel>
{
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 ); }
};
template <> struct get_sym_and_type<Elf64_Rela>
{
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 ); }
};
//------------------------------------------------------------------------------
template <class S> class relocation_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit relocation_section_accessor_template( const elfio& elf_file,
S* section )
: elf_file( elf_file ), relocation_section( section )
{
}
//------------------------------------------------------------------------------
Elf_Xword get_entries_num() const
{
Elf_Xword nRet = 0;
if ( 0 != relocation_section->get_entry_size() ) {
nRet = relocation_section->get_size() /
relocation_section->get_entry_size();
}
return nRet;
}
//------------------------------------------------------------------------------
bool get_entry( Elf_Xword index,
Elf64_Addr& offset,
Elf_Word& symbol,
unsigned& type,
Elf_Sxword& addend ) const
{
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
if ( elf_file.get_class() == ELFCLASS32 ) {
if ( SHT_REL == relocation_section->get_type() ) {
generic_get_entry_rel<Elf32_Rel>( index, offset, symbol, type,
addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_get_entry_rela<Elf32_Rela>( index, offset, symbol, type,
addend );
}
}
else {
if ( SHT_REL == relocation_section->get_type() ) {
generic_get_entry_rel<Elf64_Rel>( index, offset, symbol, type,
addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_get_entry_rela<Elf64_Rela>( index, offset, symbol, type,
addend );
}
}
return true;
}
//------------------------------------------------------------------------------
bool get_entry( Elf_Xword index,
Elf64_Addr& offset,
Elf64_Addr& symbolValue,
std::string& symbolName,
unsigned& type,
Elf_Sxword& addend,
Elf_Sxword& calcValue ) const
{
// Do regular job
Elf_Word symbol = 0;
bool ret = get_entry( index, offset, symbol, type, addend );
// Find the symbol
Elf_Xword size;
unsigned char bind;
unsigned char symbolType;
Elf_Half section;
unsigned char other;
symbol_section_accessor symbols(
elf_file, elf_file.sections[get_symbol_table_index()] );
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;
}
//------------------------------------------------------------------------------
bool set_entry( Elf_Xword index,
Elf64_Addr offset,
Elf_Word symbol,
unsigned type,
Elf_Sxword addend )
{
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
if ( elf_file.get_class() == ELFCLASS32 ) {
if ( SHT_REL == relocation_section->get_type() ) {
generic_set_entry_rel<Elf32_Rel>( index, offset, symbol, type,
addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_set_entry_rela<Elf32_Rela>( index, offset, symbol, type,
addend );
}
}
else {
if ( SHT_REL == relocation_section->get_type() ) {
generic_set_entry_rel<Elf64_Rel>( index, offset, symbol, type,
addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_set_entry_rela<Elf64_Rela>( index, offset, symbol, type,
addend );
}
}
return true;
}
//------------------------------------------------------------------------------
void add_entry( Elf64_Addr offset, Elf_Xword info )
{
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry<Elf32_Rel>( offset, info );
}
else {
generic_add_entry<Elf64_Rel>( offset, info );
}
}
//------------------------------------------------------------------------------
void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type )
{
Elf_Xword info;
if ( elf_file.get_class() == ELFCLASS32 ) {
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
}
else {
info = ELF64_R_INFO( (Elf_Xword)symbol, type );
}
add_entry( offset, info );
}
//------------------------------------------------------------------------------
void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
{
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry<Elf32_Rela>( offset, info, addend );
}
else {
generic_add_entry<Elf64_Rela>( offset, info, addend );
}
}
//------------------------------------------------------------------------------
void add_entry( Elf64_Addr offset,
Elf_Word symbol,
unsigned type,
Elf_Sxword addend )
{
Elf_Xword info;
if ( elf_file.get_class() == ELFCLASS32 ) {
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
}
else {
info = ELF64_R_INFO( (Elf_Xword)symbol, type );
}
add_entry( offset, info, addend );
}
//------------------------------------------------------------------------------
void add_entry( string_section_accessor str_writer,
const char* str,
symbol_section_accessor sym_writer,
Elf64_Addr value,
Elf_Word size,
unsigned char sym_info,
unsigned char other,
Elf_Half shndx,
Elf64_Addr offset,
unsigned type )
{
Elf_Word str_index = str_writer.add_string( str );
Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size,
sym_info, other, shndx );
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:
//------------------------------------------------------------------------------
Elf_Half get_symbol_table_index() const
{
return (Elf_Half)relocation_section->get_link();
}
//------------------------------------------------------------------------------
template <class T>
void generic_get_entry_rel( Elf_Xword index,
Elf64_Addr& offset,
Elf_Word& symbol,
unsigned& type,
Elf_Sxword& addend ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
const T* pEntry = reinterpret_cast<const T*>(
relocation_section->get_data() +
index * relocation_section->get_entry_size() );
offset = convertor( pEntry->r_offset );
Elf_Xword tmp = convertor( pEntry->r_info );
symbol = get_sym_and_type<T>::get_r_sym( tmp );
type = get_sym_and_type<T>::get_r_type( tmp );
addend = 0;
}
//------------------------------------------------------------------------------
template <class T>
void generic_get_entry_rela( Elf_Xword index,
Elf64_Addr& offset,
Elf_Word& symbol,
unsigned& type,
Elf_Sxword& addend ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
const T* pEntry = reinterpret_cast<const T*>(
relocation_section->get_data() +
index * relocation_section->get_entry_size() );
offset = convertor( pEntry->r_offset );
Elf_Xword tmp = convertor( pEntry->r_info );
symbol = get_sym_and_type<T>::get_r_sym( tmp );
type = get_sym_and_type<T>::get_r_type( tmp );
addend = convertor( pEntry->r_addend );
}
//------------------------------------------------------------------------------
template <class T>
void generic_set_entry_rel( Elf_Xword index,
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();
T entry;
entry.r_offset = decltype( entry.r_offset )( offset );
entry.r_info = decltype( entry.r_info )( info );
entry.r_offset = convertor( entry.r_offset );
entry.r_info = convertor( entry.r_info );
relocation_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
}
//------------------------------------------------------------------------------
template <class T>
void
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T entry;
entry.r_offset = offset;
entry.r_info = info;
entry.r_addend = addend;
entry.r_offset = convertor( entry.r_offset );
entry.r_info = convertor( entry.r_info );
entry.r_addend = convertor( entry.r_addend );
relocation_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* relocation_section = nullptr;
};
using relocation_section_accessor =
relocation_section_accessor_template<section>;
using const_relocation_section_accessor =
relocation_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_RELOCATION_HPP

View File

@ -0,0 +1,367 @@
/*
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_SECTION_HPP
#define ELFIO_SECTION_HPP
#include <string>
#include <iostream>
#include <new>
#include <limits>
namespace ELFIO {
class section
{
friend class elfio;
public:
virtual ~section() = default;
ELFIO_GET_ACCESS_DECL( Elf_Half, index );
ELFIO_GET_SET_ACCESS_DECL( std::string, name );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
virtual const char* get_data() const = 0;
virtual void set_data( const char* raw_data, Elf_Word size ) = 0;
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 void
insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) = 0;
virtual void insert_data( Elf_Xword pos, const std::string& data ) = 0;
virtual size_t get_stream_size() const = 0;
virtual void set_stream_size( size_t value ) = 0;
protected:
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
virtual bool load( std::istream& stream,
std::streampos header_offset,
bool is_lazy ) = 0;
virtual void save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset ) = 0;
virtual bool is_address_initialized() const = 0;
};
template <class T> class section_impl : public section
{
public:
//------------------------------------------------------------------------------
section_impl( const endianess_convertor* convertor,
const address_translator* translator,
const std::shared_ptr<compression_interface>& compression )
: convertor( convertor ), translator( translator ),
compression( compression )
{
}
//------------------------------------------------------------------------------
// Section info functions
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, size, header.sh_size );
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_Xword, addr_align, header.sh_addralign );
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_ACCESS( Elf64_Addr, address, header.sh_addr );
//------------------------------------------------------------------------------
Elf_Half get_index() const override { return index; }
//------------------------------------------------------------------------------
std::string get_name() const override { return name; }
//------------------------------------------------------------------------------
void set_name( const std::string& name_prm ) override
{
this->name = name_prm;
}
//------------------------------------------------------------------------------
void set_address( const Elf64_Addr& value ) override
{
header.sh_addr = decltype( header.sh_addr )( value );
header.sh_addr = ( *convertor )( header.sh_addr );
is_address_set = true;
}
//------------------------------------------------------------------------------
bool is_address_initialized() const override { return is_address_set; }
//------------------------------------------------------------------------------
const char* get_data() const override
{
if ( is_lazy ) {
load_data();
}
return data.get();
}
//------------------------------------------------------------------------------
void set_data( const char* raw_data, Elf_Word size ) override
{
if ( get_type() != SHT_NOBITS ) {
data = std::unique_ptr<char[]>( new ( std::nothrow ) char[size] );
if ( nullptr != data.get() && nullptr != raw_data ) {
data_size = size;
std::copy( raw_data, raw_data + size, data.get() );
}
else {
data_size = 0;
}
}
set_size( data_size );
if ( translator->empty() ) {
set_stream_size( data_size );
}
}
//------------------------------------------------------------------------------
void set_data( const std::string& str_data ) override
{
return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
}
//------------------------------------------------------------------------------
void append_data( const char* raw_data, Elf_Word size ) override
{
insert_data( get_size(), raw_data, size );
}
//------------------------------------------------------------------------------
void append_data( const std::string& str_data ) override
{
return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
}
//------------------------------------------------------------------------------
void
insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) override
{
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 ) {
char* d = data.get();
std::copy( d, d + pos, new_data.get() );
std::copy( raw_data, raw_data + size,
new_data.get() + pos );
std::copy( d + pos, d + get_size(),
new_data.get() + pos + size );
data = std::move( new_data );
}
else {
size = 0;
}
}
set_size( get_size() + size );
if ( translator->empty() ) {
set_stream_size( get_stream_size() + size );
}
}
}
//------------------------------------------------------------------------------
void insert_data( Elf_Xword pos, const std::string& str_data ) override
{
return insert_data( pos, str_data.c_str(), (Elf_Word)str_data.size() );
}
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_;
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() ) {
header.sh_offset = decltype( header.sh_offset )( data_offset );
header.sh_offset = ( *convertor )( header.sh_offset );
}
save_header( stream, header_offset );
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
get_size() != 0 && data != nullptr ) {
save_data( stream, data_offset );
}
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
void save_header( std::ostream& stream, std::streampos header_offset ) const
{
adjust_stream_size( stream, header_offset );
stream.write( reinterpret_cast<const char*>( &header ),
sizeof( header ) );
}
//------------------------------------------------------------------------------
void save_data( std::ostream& stream, std::streampos data_offset )
{
adjust_stream_size( stream, data_offset );
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:
mutable std::istream* pstream = nullptr;
T header = {};
Elf_Half index = 0;
std::string name;
mutable std::unique_ptr<char[]> data;
mutable Elf_Word data_size = 0;
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
#endif // ELFIO_SECTION_HPP

View File

@ -0,0 +1,254 @@
/*
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_SEGMENT_HPP
#define ELFIO_SEGMENT_HPP
#include <iostream>
#include <vector>
#include <new>
#include <limits>
namespace ELFIO {
class segment
{
friend class elfio;
public:
virtual ~segment() = default;
ELFIO_GET_ACCESS_DECL( Elf_Half, index );
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( Elf_Xword, file_size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
virtual const char* get_data() const = 0;
virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0;
virtual Elf_Half add_section_index( Elf_Half index,
Elf_Xword addr_align ) = 0;
virtual Elf_Half get_sections_num() const = 0;
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
virtual bool is_offset_initialized() const = 0;
protected:
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
virtual const std::vector<Elf_Half>& get_sections() const = 0;
virtual bool load( std::istream& stream,
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> class segment_impl : public segment
{
public:
//------------------------------------------------------------------------------
segment_impl( const endianess_convertor* convertor,
const address_translator* translator )
: convertor( convertor ), translator( translator )
{
}
//------------------------------------------------------------------------------
// Section info functions
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_Xword, align, ph.p_align );
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( Elf_Xword, file_size, ph.p_filesz );
ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
//------------------------------------------------------------------------------
Elf_Half get_index() const override { return index; }
//------------------------------------------------------------------------------
const char* get_data() const override
{
if ( is_lazy ) {
load_data();
}
return data.get();
}
//------------------------------------------------------------------------------
Elf_Half add_section_index( Elf_Half sec_index,
Elf_Xword addr_align ) override
{
sections.emplace_back( sec_index );
if ( addr_align > get_align() ) {
set_align( addr_align );
}
return (Elf_Half)sections.size();
}
//------------------------------------------------------------------------------
Elf_Half add_section( section* psec, Elf_Xword addr_align ) override
{
return add_section_index( psec->get_index(), addr_align );
}
//------------------------------------------------------------------------------
Elf_Half get_sections_num() const override
{
return (Elf_Half)sections.size();
}
//------------------------------------------------------------------------------
Elf_Half get_section_index_at( Elf_Half num ) const override
{
if ( num < sections.size() ) {
return sections[num];
}
return Elf_Half( -1 );
}
//------------------------------------------------------------------------------
protected:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void set_offset( const Elf64_Off& value ) override
{
ph.p_offset = decltype( ph.p_offset )( value );
ph.p_offset = ( *convertor )( ph.p_offset );
is_offset_set = true;
}
//------------------------------------------------------------------------------
bool is_offset_initialized() const override { return is_offset_set; }
//------------------------------------------------------------------------------
const std::vector<Elf_Half>& get_sections() const override
{
return sections;
}
//------------------------------------------------------------------------------
void set_index( const Elf_Half& value ) override { index = value; }
//------------------------------------------------------------------------------
bool load( std::istream& stream,
std::streampos header_offset,
bool is_lazy_ ) override
{
pstream = &stream;
is_lazy = is_lazy_;
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*>( &ph ), sizeof( ph ) );
is_offset_set = true;
if ( !is_lazy ) {
return load_data();
}
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,
std::streampos header_offset,
std::streampos data_offset ) override
{
ph.p_offset = decltype( ph.p_offset )( data_offset );
ph.p_offset = ( *convertor )( ph.p_offset );
adjust_stream_size( stream, header_offset );
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:
mutable std::istream* pstream = nullptr;
T ph = {};
Elf_Half index = 0;
mutable std::unique_ptr<char[]> data;
std::vector<Elf_Half> sections;
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
#endif // ELFIO_SEGMENT_HPP

View File

@ -0,0 +1,97 @@
/*
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_STRINGS_HPP
#define ELFIO_STRINGS_HPP
#include <cstdlib>
#include <cstring>
#include <string>
namespace ELFIO {
//------------------------------------------------------------------------------
template <class S> class string_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit string_section_accessor_template( S* section )
: string_section( section )
{
}
//------------------------------------------------------------------------------
const char* get_string( Elf_Word index ) const
{
if ( string_section ) {
const char* data = string_section->get_data();
if ( index < string_section->get_size() && nullptr != data ) {
size_t string_length =
strnlen( data + index, string_section->get_size() - index );
if ( string_length < ( string_section->get_size() - index ) )
return data + index;
}
}
return nullptr;
}
//------------------------------------------------------------------------------
Elf_Word add_string( const char* str )
{
Elf_Word current_position = 0;
if ( string_section ) {
// Strings are addeded to the end of the current section data
current_position =
static_cast<Elf_Word>( string_section->get_size() );
if ( current_position == 0 ) {
char empty_string = '\0';
string_section->append_data( &empty_string, 1 );
current_position++;
}
string_section->append_data(
str, static_cast<Elf_Word>( std::strlen( str ) + 1 ) );
}
return current_position;
}
//------------------------------------------------------------------------------
Elf_Word add_string( const std::string& str )
{
return add_string( str.c_str() );
}
//------------------------------------------------------------------------------
private:
S* string_section;
};
using string_section_accessor = string_section_accessor_template<section>;
using const_string_section_accessor =
string_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_STRINGS_HPP

View File

@ -0,0 +1,562 @@
/*
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_SYMBOLS_HPP
#define ELFIO_SYMBOLS_HPP
namespace ELFIO {
//------------------------------------------------------------------------------
template <class S> class symbol_section_accessor_template
{
public:
//------------------------------------------------------------------------------
explicit symbol_section_accessor_template( const elfio& elf_file,
S* symbol_section )
: elf_file( elf_file ), symbol_section( symbol_section )
{
find_hash_section();
}
//------------------------------------------------------------------------------
Elf_Xword get_symbols_num() const
{
Elf_Xword nRet = 0;
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;
}
//------------------------------------------------------------------------------
bool 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;
if ( elf_file.get_class() == ELFCLASS32 ) {
ret = generic_get_symbol<Elf32_Sym>( index, name, value, size, bind,
type, section_index, other );
}
else {
ret = generic_get_symbol<Elf64_Sym>( index, name, value, size, bind,
type, section_index, other );
}
return ret;
}
//------------------------------------------------------------------------------
bool get_symbol( const 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;
if ( 0 != get_hash_table_index() ) {
if ( hash_section->get_type() == SHT_HASH ) {
ret = hash_lookup( name, value, size, bind, type, section_index,
other );
}
if ( hash_section->get_type() == SHT_GNU_HASH ||
hash_section->get_type() == DT_GNU_HASH ) {
if ( elf_file.get_class() == ELFCLASS32 ) {
ret = gnu_hash_lookup<uint32_t>(
name, value, size, bind, type, section_index, other );
}
else {
ret = gnu_hash_lookup<uint64_t>(
name, value, size, bind, type, section_index, other );
}
}
}
if ( !ret ) {
for ( Elf_Xword i = 0; !ret && i < get_symbols_num(); i++ ) {
std::string symbol_name;
if ( get_symbol( i, symbol_name, value, size, bind, type,
section_index, other ) ) {
if ( symbol_name == name ) {
ret = true;
}
}
}
}
return ret;
}
//------------------------------------------------------------------------------
bool get_symbol( const Elf64_Addr& value,
std::string& name,
Elf_Xword& size,
unsigned char& bind,
unsigned char& type,
Elf_Half& section_index,
unsigned char& other ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
Elf_Xword idx = 0;
bool match = false;
Elf64_Addr v = 0;
if ( elf_file.get_class() == ELFCLASS32 ) {
match = generic_search_symbols<Elf32_Sym>(
[&]( const Elf32_Sym* sym ) {
return convertor( sym->st_value ) == value;
},
idx );
}
else {
match = generic_search_symbols<Elf64_Sym>(
[&]( const Elf64_Sym* sym ) {
return convertor( sym->st_value ) == value;
},
idx );
}
if ( match ) {
return get_symbol( idx, name, v, size, bind, type, section_index,
other );
}
return false;
}
//------------------------------------------------------------------------------
Elf_Word add_symbol( Elf_Word name,
Elf64_Addr value,
Elf_Xword size,
unsigned char info,
unsigned char other,
Elf_Half shndx )
{
Elf_Word nRet;
if ( symbol_section->get_size() == 0 ) {
if ( elf_file.get_class() == ELFCLASS32 ) {
nRet = generic_add_symbol<Elf32_Sym>( 0, 0, 0, 0, 0, 0 );
}
else {
nRet = generic_add_symbol<Elf64_Sym>( 0, 0, 0, 0, 0, 0 );
}
}
if ( elf_file.get_class() == ELFCLASS32 ) {
nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info,
other, shndx );
}
else {
nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info,
other, shndx );
}
return nRet;
}
//------------------------------------------------------------------------------
Elf_Word add_symbol( Elf_Word name,
Elf64_Addr value,
Elf_Xword size,
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 );
}
//------------------------------------------------------------------------------
Elf_Word add_symbol( string_section_accessor& pStrWriter,
const char* str,
Elf64_Addr value,
Elf_Xword size,
unsigned char info,
unsigned char other,
Elf_Half shndx )
{
Elf_Word index = pStrWriter.add_string( str );
return add_symbol( index, value, size, info, other, shndx );
}
//------------------------------------------------------------------------------
Elf_Word add_symbol( string_section_accessor& pStrWriter,
const char* str,
Elf64_Addr value,
Elf_Xword size,
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 );
}
//------------------------------------------------------------------------------
Elf_Xword arrange_local_symbols(
std::function<void( Elf_Xword first, Elf_Xword second )> func =
nullptr )
{
Elf_Xword nRet = 0;
if ( elf_file.get_class() == ELFCLASS32 ) {
nRet = generic_arrange_local_symbols<Elf32_Sym>( func );
}
else {
nRet = generic_arrange_local_symbols<Elf64_Sym>( func );
}
return nRet;
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
void find_hash_section()
{
Elf_Half nSecNo = elf_file.sections.size();
for ( Elf_Half i = 0; i < nSecNo; ++i ) {
const section* sec = elf_file.sections[i];
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_index = i;
break;
}
}
}
//------------------------------------------------------------------------------
Elf_Half get_string_table_index() const
{
return (Elf_Half)symbol_section->get_link();
}
//------------------------------------------------------------------------------
Elf_Half get_hash_table_index() const { return hash_section_index; }
//------------------------------------------------------------------------------
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
{
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>
bool gnu_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
{
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;
if ( nullptr != 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() );
const endianess_convertor& convertor = elf_file.get_convertor();
section* string_section =
elf_file.sections[get_string_table_index()];
string_section_accessor str_reader( string_section );
const char* pStr =
str_reader.get_string( convertor( pSym->st_name ) );
if ( nullptr != pStr ) {
name = pStr;
}
value = convertor( pSym->st_value );
size = convertor( pSym->st_size );
bind = ELF_ST_BIND( pSym->st_info );
type = ELF_ST_TYPE( pSym->st_info );
section_index = convertor( pSym->st_shndx );
other = pSym->st_other;
ret = true;
}
return ret;
}
//------------------------------------------------------------------------------
template <class T>
Elf_Word generic_add_symbol( Elf_Word name,
Elf64_Addr value,
Elf_Xword size,
unsigned char info,
unsigned char other,
Elf_Half shndx )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T entry;
entry.st_name = convertor( name );
entry.st_value = decltype( entry.st_value )( value );
entry.st_value = convertor( entry.st_value );
entry.st_size = decltype( entry.st_size )( size );
entry.st_size = convertor( entry.st_size );
entry.st_info = convertor( info );
entry.st_other = convertor( other );
entry.st_shndx = convertor( shndx );
symbol_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
Elf_Word nRet =
Elf_Word( symbol_section->get_size() / sizeof( entry ) - 1 );
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:
const elfio& elf_file;
S* symbol_section;
Elf_Half hash_section_index{ 0 };
const section* hash_section{ nullptr };
};
using symbol_section_accessor = symbol_section_accessor_template<section>;
using const_symbol_section_accessor =
symbol_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_SYMBOLS_HPP

View File

@ -0,0 +1,302 @@
/*
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_UTILS_HPP
#define ELFIO_UTILS_HPP
#include <cstdint>
#include <ostream>
#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0
#define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \
virtual void set_##NAME( const TYPE& value ) = 0
#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \
virtual TYPE get_##NAME() const = 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 {
//------------------------------------------------------------------------------
class endianess_convertor
{
public:
//------------------------------------------------------------------------------
void setup( unsigned char elf_file_encoding )
{
need_conversion = ( elf_file_encoding != get_host_encoding() );
}
//------------------------------------------------------------------------------
uint64_t 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 ) {
return value;
}
value =
( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) |
( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 );
return value;
}
//------------------------------------------------------------------------------
int32_t operator()( int32_t value ) const
{
if ( !need_conversion ) {
return value;
}
return (int32_t)( *this )( (uint32_t)value );
}
//------------------------------------------------------------------------------
uint16_t operator()( uint16_t value ) const
{
if ( !need_conversion ) {
return value;
}
value =
(uint16_t)( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 );
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:
//------------------------------------------------------------------------------
unsigned char get_host_encoding() const
{
static const int tmp = 1;
if ( 1 == *reinterpret_cast<const char*>( &tmp ) ) {
return ELFDATA2LSB;
}
else {
return ELFDATA2MSB;
}
}
//------------------------------------------------------------------------------
bool need_conversion = false;
};
//------------------------------------------------------------------------------
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;
};
//------------------------------------------------------------------------------
class address_translator
{
public:
//------------------------------------------------------------------------------
void set_address_translation( std::vector<address_translation>& addr_trans )
{
addr_translations = addr_trans;
std::sort( addr_translations.begin(), addr_translations.end(),
[]( const address_translation& a,
const 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;
if ( g != 0 )
h ^= g >> 24;
h &= ~g;
}
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 ) {
if ( auto digit = value & 0xF; 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
#endif // ELFIO_UTILS_HPP

View File

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

View File

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