Add ELF support, handle condcodes, test ZRSH
All checks were successful
Test / build (push) Successful in 14s
All checks were successful
Test / build (push) Successful in 14s
This commit is contained in:
parent
e647b9e146
commit
d271bdc959
54
.clang-format
Normal file
54
.clang-format
Normal file
@ -0,0 +1,54 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: true
|
||||
BeforeWhile: true
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBraces: Custom
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
ColumnLimit: 120
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ContinuationIndentWidth: 2
|
||||
IncludeCategories:
|
||||
- Regex: '^<.*'
|
||||
Priority: 1
|
||||
- Regex: '^".*'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IndentCaseBlocks: true
|
||||
InsertNewlineAtEOF: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
PointerAlignment: Left
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
TabWidth: 4
|
||||
...
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.cache/
|
||||
.idea/
|
||||
build/
|
||||
emulator/customasm/*.bin
|
||||
|
||||
2
DOCS.txt
2
DOCS.txt
@ -25,7 +25,7 @@
|
||||
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
|
||||
║ BXOR ║ Bitwise exclusive or ║ D = A ^ B ║ CCCR ║ 0100 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 101 ║ A > B ║
|
||||
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
|
||||
║ RESERVED ║ ║ ║ ║ 0101 ║ ║ ║ ║ ║ ║ ║ ║ 110 ║ A != B ║
|
||||
║ ZRSH ║ Pad zero right shift ║ D = A >> B ║ CCCR ║ 0101 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 110 ║ A != B ║
|
||||
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣
|
||||
║ SRSH ║ Signed right shift ║ D = A >> B ║ CCCR ║ 0110 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 111 ║ Reserved ║
|
||||
╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╩═════════════════════════╣
|
||||
|
||||
21
emulator/include/elfio/LICENSE.txt
Normal file
21
emulator/include/elfio/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
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.
|
||||
1564
emulator/include/elfio/elf_types.hpp
Normal file
1564
emulator/include/elfio/elf_types.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1260
emulator/include/elfio/elfio.hpp
Normal file
1260
emulator/include/elfio/elfio.hpp
Normal file
File diff suppressed because it is too large
Load Diff
119
emulator/include/elfio/elfio_array.hpp
Normal file
119
emulator/include/elfio/elfio_array.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
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 for accessing array sections
|
||||
template <class S, typename T> class array_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
explicit array_section_accessor_template( const elfio& elf_file,
|
||||
S* section );
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Returns the number of entries in the array section
|
||||
Elf_Xword get_entries_num() const;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Retrieves an entry from the array section
|
||||
bool get_entry( Elf_Xword index, Elf64_Addr& address ) const;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Adds an entry to the array section
|
||||
void add_entry( Elf64_Addr address );
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------------------
|
||||
// Reference to the ELF file
|
||||
const elfio& elf_file;
|
||||
//------------------------------------------------------------------------------
|
||||
// Pointer to the array section
|
||||
S* array_section;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
template <class S, typename T>
|
||||
array_section_accessor_template<S, T>::array_section_accessor_template(
|
||||
const elfio& elf_file, S* section )
|
||||
: elf_file( elf_file ), array_section( section )
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Returns the number of entries in the array section
|
||||
template <class S, typename T>
|
||||
Elf_Xword array_section_accessor_template<S, T>::get_entries_num() const
|
||||
{
|
||||
Elf_Xword entry_size = sizeof( T );
|
||||
return array_section->get_size() / entry_size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Retrieves an entry from the array section
|
||||
template <class S, typename T>
|
||||
bool array_section_accessor_template<S, T>::get_entry(
|
||||
Elf_Xword index, Elf64_Addr& address ) const
|
||||
{
|
||||
if ( index >= get_entries_num() ) { // Is index valid
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& convertor = elf_file.get_convertor();
|
||||
|
||||
const T temp = *reinterpret_cast<const T*>( array_section->get_data() +
|
||||
index * sizeof( T ) );
|
||||
address = ( *convertor )( temp );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Adds an entry to the array section
|
||||
template <class S, typename T>
|
||||
void array_section_accessor_template<S, T>::add_entry( Elf64_Addr address )
|
||||
{
|
||||
const auto& convertor = elf_file.get_convertor();
|
||||
|
||||
T temp = ( *convertor )( (T)address );
|
||||
array_section->append_data( reinterpret_cast<char*>( &temp ),
|
||||
sizeof( temp ) );
|
||||
}
|
||||
|
||||
// Type aliases for array section accessors
|
||||
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
|
||||
1388
emulator/include/elfio/elfio_dump.hpp
Normal file
1388
emulator/include/elfio/elfio_dump.hpp
Normal file
File diff suppressed because it is too large
Load Diff
300
emulator/include/elfio/elfio_dynamic.hpp
Normal file
300
emulator/include/elfio/elfio_dynamic.hpp
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
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 for accessing dynamic sections
|
||||
template <class S> class dynamic_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
explicit dynamic_section_accessor_template( const elfio& elf_file,
|
||||
S* section )
|
||||
: elf_file( elf_file ), dynamic_section( section ), entries_num( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Returns the number of entries in the dynamic section
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Retrieves an entry from the dynamic section
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Adds an entry to the dynamic section
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Adds an entry with a string value to the dynamic section
|
||||
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:
|
||||
//------------------------------------------------------------------------------
|
||||
// Returns the index of the string table
|
||||
Elf_Half get_string_table_index() const
|
||||
{
|
||||
return (Elf_Half)dynamic_section->get_link();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Retrieves a generic entry from the dynamic section
|
||||
template <class T>
|
||||
void generic_get_entry_dyn( Elf_Xword index,
|
||||
Elf_Xword& tag,
|
||||
Elf_Xword& value ) const
|
||||
{
|
||||
const auto& convertor = elf_file.get_convertor();
|
||||
|
||||
// Check unusual case when dynamic section has no data
|
||||
if ( dynamic_section->get_data() == nullptr ||
|
||||
dynamic_section->get_entry_size() < sizeof( T ) ) {
|
||||
tag = DT_NULL;
|
||||
value = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for integer overflow in size calculation
|
||||
if ( index > ( dynamic_section->get_size() /
|
||||
dynamic_section->get_entry_size() ) -
|
||||
1 ) {
|
||||
tag = DT_NULL;
|
||||
value = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for integer overflow in pointer arithmetic
|
||||
Elf_Xword offset = index * dynamic_section->get_entry_size();
|
||||
if ( offset > dynamic_section->get_size() - sizeof( T ) ) {
|
||||
tag = DT_NULL;
|
||||
value = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const T* pEntry =
|
||||
reinterpret_cast<const T*>( dynamic_section->get_data() + offset );
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Adds a generic entry to the dynamic section
|
||||
template <class T>
|
||||
void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value )
|
||||
{
|
||||
const auto& 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:
|
||||
// Reference to the ELF file
|
||||
const elfio& elf_file;
|
||||
// Pointer to the dynamic section
|
||||
S* dynamic_section;
|
||||
// Number of entries in the dynamic section
|
||||
mutable Elf_Xword entries_num;
|
||||
};
|
||||
|
||||
// Type aliases for dynamic section accessors
|
||||
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
|
||||
192
emulator/include/elfio/elfio_header.hpp
Normal file
192
emulator/include/elfio/elfio_header.hpp
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
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
|
||||
* @brief Abstract base class for ELF header.
|
||||
*/
|
||||
class elf_header
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Virtual destructor.
|
||||
*/
|
||||
virtual ~elf_header() = default;
|
||||
|
||||
/**
|
||||
* @brief Load ELF header from stream.
|
||||
* @param stream Input stream.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
virtual bool load( std::istream& stream ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Save ELF header to stream.
|
||||
* @param stream Output stream.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
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 );
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct elf_header_impl_types
|
||||
* @brief Template specialization for ELF header implementation types.
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class elf_header_impl
|
||||
* @brief Template class for ELF header implementation.
|
||||
*/
|
||||
template <class T> class elf_header_impl : public elf_header
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param convertor Endianness convertor.
|
||||
* @param encoding Encoding type.
|
||||
* @param translator Address translator.
|
||||
*/
|
||||
elf_header_impl( std::shared_ptr<endianness_convertor> convertor,
|
||||
unsigned char encoding,
|
||||
std::shared_ptr<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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load ELF header from stream.
|
||||
* @param stream Input stream.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
bool load( std::istream& stream ) override
|
||||
{
|
||||
stream.seekg( ( *translator )[0] );
|
||||
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
||||
|
||||
return ( stream.gcount() == sizeof( header ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Save ELF header to stream.
|
||||
* @param stream Output stream.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
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 = {};
|
||||
std::shared_ptr<endianness_convertor> convertor = nullptr;
|
||||
std::shared_ptr<address_translator> translator = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ELFIO
|
||||
|
||||
#endif // ELF_HEADER_HPP
|
||||
168
emulator/include/elfio/elfio_modinfo.hpp
Normal file
168
emulator/include/elfio/elfio_modinfo.hpp
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
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 {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class modinfo_section_accessor_template
|
||||
* @brief A template class to access modinfo section.
|
||||
*
|
||||
* @tparam S The section type.
|
||||
*/
|
||||
template <class S> class modinfo_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Construct a new modinfo section accessor template object.
|
||||
*
|
||||
* @param section The section to be accessed.
|
||||
*/
|
||||
explicit modinfo_section_accessor_template( S* section )
|
||||
: modinfo_section( section )
|
||||
{
|
||||
process_section();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Get the number of attributes.
|
||||
*
|
||||
* @return Elf_Word The number of attributes.
|
||||
*/
|
||||
Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Get the attribute by index.
|
||||
*
|
||||
* @param no The index of the attribute.
|
||||
* @param field The field name of the attribute.
|
||||
* @param value The value of the attribute.
|
||||
* @return true If the attribute is found.
|
||||
* @return false If the attribute is not found.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Get the attribute by field name.
|
||||
*
|
||||
* @param field_name The field name of the attribute.
|
||||
* @param value The value of the attribute.
|
||||
* @return true If the attribute is found.
|
||||
* @return false If the attribute is not found.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Add a new attribute.
|
||||
*
|
||||
* @param field The field name of the attribute.
|
||||
* @param value The value of the attribute.
|
||||
* @return Elf_Word The position of the new attribute.
|
||||
*/
|
||||
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:
|
||||
/**
|
||||
* @brief Process the section to extract attributes.
|
||||
*/
|
||||
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; ///< The section to be accessed.
|
||||
std::vector<std::pair<std::string, std::string>>
|
||||
content; ///< The list of attributes.
|
||||
};
|
||||
|
||||
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
|
||||
208
emulator/include/elfio/elfio_note.hpp
Normal file
208
emulator/include/elfio/elfio_note.hpp
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
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
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class note_section_accessor_template
|
||||
//! \brief Class for accessing note section data
|
||||
template <class S, Elf_Xword ( S::*F_get_size )() const>
|
||||
class note_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param elf_file Reference to the ELF file
|
||||
//! \param section Pointer to the section
|
||||
explicit note_section_accessor_template( const elfio& elf_file, S* section )
|
||||
: elf_file( elf_file ), notes( section )
|
||||
{
|
||||
process_section();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the number of notes
|
||||
//! \return Number of notes
|
||||
Elf_Word get_notes_num() const
|
||||
{
|
||||
return (Elf_Word)note_start_positions.size();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get a note
|
||||
//! \param index Index of the note
|
||||
//! \param type Type of the note
|
||||
//! \param name Name of the note
|
||||
//! \param desc Pointer to the descriptor
|
||||
//! \param descSize Size of the descriptor
|
||||
//! \return True if successful, false otherwise
|
||||
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 auto& 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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a note
|
||||
//! \param type Type of the note
|
||||
//! \param name Name of the note
|
||||
//! \param desc Pointer to the descriptor
|
||||
//! \param descSize Size of the descriptor
|
||||
void add_note( Elf_Word type,
|
||||
const std::string& name,
|
||||
const char* desc,
|
||||
Elf_Word descSize )
|
||||
{
|
||||
const auto& 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:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Process the section to extract note start positions
|
||||
void process_section()
|
||||
{
|
||||
const auto& 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; //!< Reference to the ELF file
|
||||
S* notes; //!< Pointer to the section or segment
|
||||
std::vector<Elf_Xword>
|
||||
note_start_positions; //!< Vector of note start positions
|
||||
};
|
||||
|
||||
using note_section_accessor =
|
||||
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
|
||||
|
||||
#endif // ELFIO_NOTE_HPP
|
||||
596
emulator/include/elfio/elfio_relocation.hpp
Normal file
596
emulator/include/elfio/elfio_relocation.hpp
Normal file
@ -0,0 +1,596 @@
|
||||
/*
|
||||
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>
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the symbol from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Symbol
|
||||
static int get_r_sym( Elf_Xword info )
|
||||
{
|
||||
return ELF32_R_SYM( (Elf_Word)info );
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the type from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Type
|
||||
static int get_r_type( Elf_Xword info )
|
||||
{
|
||||
return ELF32_R_TYPE( (Elf_Word)info );
|
||||
}
|
||||
};
|
||||
template <> struct get_sym_and_type<Elf32_Rela>
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the symbol from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Symbol
|
||||
static int get_r_sym( Elf_Xword info )
|
||||
{
|
||||
return ELF32_R_SYM( (Elf_Word)info );
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the type from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Type
|
||||
static int get_r_type( Elf_Xword info )
|
||||
{
|
||||
return ELF32_R_TYPE( (Elf_Word)info );
|
||||
}
|
||||
};
|
||||
template <> struct get_sym_and_type<Elf64_Rel>
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the symbol from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Symbol
|
||||
static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the type from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Type
|
||||
static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
|
||||
};
|
||||
template <> struct get_sym_and_type<Elf64_Rela>
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the symbol from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Symbol
|
||||
static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the type from the relocation info
|
||||
//! \param info Relocation info
|
||||
//! \return Type
|
||||
static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class relocation_section_accessor_template
|
||||
//! \brief Class for accessing relocation section data
|
||||
template <class S> class relocation_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param elf_file Reference to the ELF file
|
||||
//! \param section Pointer to the section
|
||||
explicit relocation_section_accessor_template( const elfio& elf_file,
|
||||
S* section )
|
||||
: elf_file( elf_file ), relocation_section( section )
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the number of entries
|
||||
//! \return Number of entries
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get an entry
|
||||
//! \param index Index of the entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
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() ) {
|
||||
return generic_get_entry_rel<Elf32_Rel>( index, offset, symbol,
|
||||
type, addend );
|
||||
}
|
||||
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||
return generic_get_entry_rela<Elf32_Rela>(
|
||||
index, offset, symbol, type, addend );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( SHT_REL == relocation_section->get_type() ) {
|
||||
return generic_get_entry_rel<Elf64_Rel>( index, offset, symbol,
|
||||
type, addend );
|
||||
}
|
||||
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||
return generic_get_entry_rela<Elf64_Rela>(
|
||||
index, offset, symbol, type, addend );
|
||||
}
|
||||
}
|
||||
// Unknown relocation section type.
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get an entry with additional information
|
||||
//! \param index Index of the entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbolValue Value of the symbol
|
||||
//! \param symbolName Name of the symbol
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
//! \param calcValue Calculated value
|
||||
//! \return True if successful, false otherwise
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set an entry
|
||||
//! \param index Index of the entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add an entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param info Information of the entry
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add an entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add an entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param info Information of the entry
|
||||
//! \param addend Addend of the entry
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add an entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add an entry with additional information
|
||||
//! \param str_writer String section accessor
|
||||
//! \param str String
|
||||
//! \param sym_writer Symbol section accessor
|
||||
//! \param value Value of the symbol
|
||||
//! \param size Size of the symbol
|
||||
//! \param sym_info Symbol information
|
||||
//! \param other Other information
|
||||
//! \param shndx Section index
|
||||
//! \param offset Offset of the entry
|
||||
//! \param type Type of the entry
|
||||
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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Swap symbols
|
||||
//! \param first First symbol
|
||||
//! \param second Second symbol
|
||||
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:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the symbol table index
|
||||
//! \return Symbol table index
|
||||
Elf_Half get_symbol_table_index() const
|
||||
{
|
||||
return (Elf_Half)relocation_section->get_link();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get a generic entry for REL type
|
||||
//! \param index Index of the entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
template <class T>
|
||||
bool generic_get_entry_rel( Elf_Xword index,
|
||||
Elf64_Addr& offset,
|
||||
Elf_Word& symbol,
|
||||
unsigned& type,
|
||||
Elf_Sxword& addend ) const
|
||||
{
|
||||
const auto& convertor = elf_file.get_convertor();
|
||||
|
||||
if ( relocation_section->get_entry_size() < sizeof( T ) ) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get a generic entry for RELA type
|
||||
//! \param index Index of the entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
template <class T>
|
||||
bool generic_get_entry_rela( Elf_Xword index,
|
||||
Elf64_Addr& offset,
|
||||
Elf_Word& symbol,
|
||||
unsigned& type,
|
||||
Elf_Sxword& addend ) const
|
||||
{
|
||||
const auto& convertor = elf_file.get_convertor();
|
||||
|
||||
if ( relocation_section->get_entry_size() < sizeof( T ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 );
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set a generic entry for REL type
|
||||
//! \param index Index of the entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
template <class T>
|
||||
void generic_set_entry_rel( Elf_Xword index,
|
||||
Elf64_Addr offset,
|
||||
Elf_Word symbol,
|
||||
unsigned type,
|
||||
Elf_Sxword )
|
||||
{
|
||||
const auto& 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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set a generic entry for RELA type
|
||||
//! \param index Index of the entry
|
||||
//! \param offset Offset of the entry
|
||||
//! \param symbol Symbol of the entry
|
||||
//! \param type Type of the entry
|
||||
//! \param addend Addend of the entry
|
||||
template <class T>
|
||||
void generic_set_entry_rela( Elf_Xword index,
|
||||
Elf64_Addr offset,
|
||||
Elf_Word symbol,
|
||||
unsigned type,
|
||||
Elf_Sxword addend )
|
||||
{
|
||||
const auto& 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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a generic entry for REL type
|
||||
//! \param offset Offset of the entry
|
||||
//! \param info Information of the entry
|
||||
template <class T>
|
||||
void generic_add_entry( Elf64_Addr offset, Elf_Xword info )
|
||||
{
|
||||
const auto& 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 ) );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a generic entry for RELA type
|
||||
//! \param offset Offset of the entry
|
||||
//! \param info Information of the entry
|
||||
//! \param addend Addend of the entry
|
||||
template <class T>
|
||||
void
|
||||
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
|
||||
{
|
||||
const auto& 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
|
||||
611
emulator/include/elfio/elfio_section.hpp
Normal file
611
emulator/include/elfio/elfio_section.hpp
Normal file
@ -0,0 +1,611 @@
|
||||
/*
|
||||
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
|
||||
* @brief Represents a section in an ELF file.
|
||||
*/
|
||||
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 );
|
||||
|
||||
/**
|
||||
* @brief Get the data of the section.
|
||||
* @return Pointer to the data.
|
||||
*/
|
||||
virtual const char* get_data() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Free the data of the section.
|
||||
*/
|
||||
virtual void free_data() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Set the data of the section.
|
||||
* @param raw_data Pointer to the raw data.
|
||||
* @param size Size of the data.
|
||||
*/
|
||||
virtual void set_data( const char* raw_data, Elf_Xword size ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set the data of the section.
|
||||
* @param data String containing the data.
|
||||
*/
|
||||
virtual void set_data( const std::string& data ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Append data to the section.
|
||||
* @param raw_data Pointer to the raw data.
|
||||
* @param size Size of the data.
|
||||
*/
|
||||
virtual void append_data( const char* raw_data, Elf_Xword size ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Append data to the section.
|
||||
* @param data String containing the data.
|
||||
*/
|
||||
virtual void append_data( const std::string& data ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Insert data into the section at a specific position.
|
||||
* @param pos Position to insert the data.
|
||||
* @param raw_data Pointer to the raw data.
|
||||
* @param size Size of the data.
|
||||
*/
|
||||
virtual void
|
||||
insert_data( Elf_Xword pos, const char* raw_data, Elf_Xword size ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Insert data into the section at a specific position.
|
||||
* @param pos Position to insert the data.
|
||||
* @param data String containing the data.
|
||||
*/
|
||||
virtual void insert_data( Elf_Xword pos, const std::string& data ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the size of the stream.
|
||||
* @return Size of the stream.
|
||||
*/
|
||||
virtual size_t get_stream_size() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Set the size of the stream.
|
||||
* @param value Size of the stream.
|
||||
*/
|
||||
virtual void set_stream_size( size_t value ) = 0;
|
||||
|
||||
protected:
|
||||
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
||||
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
||||
|
||||
/**
|
||||
* @brief Load the section from a stream.
|
||||
* @param stream Input stream.
|
||||
* @param header_offset Offset of the header.
|
||||
* @param is_lazy Whether to load lazily.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
virtual bool load( std::istream& stream,
|
||||
std::streampos header_offset,
|
||||
bool is_lazy ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Save the section to a stream.
|
||||
* @param stream Output stream.
|
||||
* @param header_offset Offset of the header.
|
||||
* @param data_offset Offset of the data.
|
||||
*/
|
||||
virtual void save( std::ostream& stream,
|
||||
std::streampos header_offset,
|
||||
std::streampos data_offset ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Check if the address is initialized.
|
||||
* @return True if initialized, false otherwise.
|
||||
*/
|
||||
virtual bool is_address_initialized() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class section_impl
|
||||
* @brief Implementation of the section class.
|
||||
* @tparam T Type of the section header.
|
||||
*/
|
||||
template <class T> class section_impl : public section
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param convertor Pointer to the endianness convertor.
|
||||
* @param translator Pointer to the address translator.
|
||||
* @param compression Shared pointer to the compression interface.
|
||||
*/
|
||||
section_impl( std::shared_ptr<endianness_convertor> convertor,
|
||||
std::shared_ptr<address_translator> translator,
|
||||
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 );
|
||||
|
||||
/**
|
||||
* @brief Get the index of the section.
|
||||
* @return Index of the section.
|
||||
*/
|
||||
Elf_Half get_index() const override { return index; }
|
||||
|
||||
/**
|
||||
* @brief Get the name of the section.
|
||||
* @return Name of the section.
|
||||
*/
|
||||
std::string get_name() const override { return name; }
|
||||
|
||||
/**
|
||||
* @brief Set the name of the section.
|
||||
* @param name_prm Name of the section.
|
||||
*/
|
||||
void set_name( const std::string& name_prm ) override
|
||||
{
|
||||
this->name = name_prm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the address of the section.
|
||||
* @param value Address of the section.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the address is initialized.
|
||||
* @return True if initialized, false otherwise.
|
||||
*/
|
||||
bool is_address_initialized() const override { return is_address_set; }
|
||||
|
||||
/**
|
||||
* @brief Get the data of the section.
|
||||
* @return Pointer to the data.
|
||||
*/
|
||||
const char* get_data() const override
|
||||
{
|
||||
// If data load failed, the stream is corrupt
|
||||
// When lazy loading, attempts to call get_data() on it after initial load are useless
|
||||
// When loading non-lazily, that load_data() will attempt to read data from
|
||||
// the stream specified on load() call, which might be freed by this point
|
||||
if ( !is_loaded && can_be_loaded ) {
|
||||
bool res = load_data();
|
||||
|
||||
if ( !res ) {
|
||||
can_be_loaded = false;
|
||||
}
|
||||
}
|
||||
return data.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the data of the section.
|
||||
*/
|
||||
void free_data() const override
|
||||
{
|
||||
if ( is_lazy ) {
|
||||
data.reset( nullptr );
|
||||
is_loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the data of the section.
|
||||
* @param raw_data Pointer to the raw data.
|
||||
* @param size Size of the data.
|
||||
*/
|
||||
void set_data( const char* raw_data, Elf_Xword size ) override
|
||||
{
|
||||
if ( get_type() != SHT_NOBITS ) {
|
||||
data = std::unique_ptr<char[]>(
|
||||
new ( std::nothrow ) char[(size_t)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( (size_t)data_size );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the data of the section.
|
||||
* @param str_data String containing the data.
|
||||
*/
|
||||
void set_data( const std::string& str_data ) override
|
||||
{
|
||||
return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append data to the section.
|
||||
* @param raw_data Pointer to the raw data.
|
||||
* @param size Size of the data.
|
||||
*/
|
||||
void append_data( const char* raw_data, Elf_Xword size ) override
|
||||
{
|
||||
insert_data( get_size(), raw_data, size );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append data to the section.
|
||||
* @param str_data String containing the data.
|
||||
*/
|
||||
void append_data( const std::string& str_data ) override
|
||||
{
|
||||
return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert data into the section at a specific position.
|
||||
* @param pos Position to insert the data.
|
||||
* @param raw_data Pointer to the raw data.
|
||||
* @param size Size of the data.
|
||||
*/
|
||||
void
|
||||
insert_data( Elf_Xword pos, const char* raw_data, Elf_Xword size ) override
|
||||
{
|
||||
if ( get_type() != SHT_NOBITS ) {
|
||||
// Check for valid position
|
||||
if ( pos > get_size() ) {
|
||||
return; // Invalid position
|
||||
}
|
||||
|
||||
// Check for integer overflow in size calculation
|
||||
Elf_Xword new_size = get_size();
|
||||
if ( size > std::numeric_limits<Elf_Xword>::max() - new_size ) {
|
||||
return; // Size would overflow
|
||||
}
|
||||
new_size += size;
|
||||
|
||||
if ( new_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 {
|
||||
// Calculate new size with overflow check
|
||||
Elf_Xword new_data_size = data_size;
|
||||
if ( new_data_size >
|
||||
std::numeric_limits<Elf_Xword>::max() / 2 ) {
|
||||
return; // Multiplication would overflow
|
||||
}
|
||||
new_data_size *= 2;
|
||||
if ( size >
|
||||
std::numeric_limits<Elf_Xword>::max() - new_data_size ) {
|
||||
return; // Addition would overflow
|
||||
}
|
||||
new_data_size += size;
|
||||
|
||||
// Check if the size would overflow size_t
|
||||
if ( new_data_size > std::numeric_limits<size_t>::max() ) {
|
||||
return; // Size would overflow size_t
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> new_data(
|
||||
new ( std::nothrow ) char[(size_t)new_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 );
|
||||
data_size = new_data_size;
|
||||
}
|
||||
else {
|
||||
return; // Allocation failed
|
||||
}
|
||||
}
|
||||
set_size( new_size );
|
||||
if ( translator->empty() ) {
|
||||
set_stream_size( get_stream_size() + (size_t)size );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert data into the section at a specific position.
|
||||
* @param pos Position to insert the data.
|
||||
* @param str_data String containing the data.
|
||||
*/
|
||||
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() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the size of the stream.
|
||||
* @return Size of the stream.
|
||||
*/
|
||||
size_t get_stream_size() const override { return stream_size; }
|
||||
|
||||
/**
|
||||
* @brief Set the size of the stream.
|
||||
* @param value Size of the stream.
|
||||
*/
|
||||
void set_stream_size( size_t value ) override { stream_size = value; }
|
||||
|
||||
protected:
|
||||
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
|
||||
|
||||
/**
|
||||
* @brief Set the index of the section.
|
||||
* @param value Index of the section.
|
||||
*/
|
||||
void set_index( const Elf_Half& value ) override { index = value; }
|
||||
|
||||
/**
|
||||
* @brief Check if the section is compressed.
|
||||
* @return True if compressed, false otherwise.
|
||||
*/
|
||||
bool is_compressed() const
|
||||
{
|
||||
return ( ( get_flags() & SHF_RPX_DEFLATE ) ||
|
||||
( get_flags() & SHF_COMPRESSED ) ) &&
|
||||
compression != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load the section from a stream.
|
||||
* @param stream Input stream.
|
||||
* @param header_offset Offset of the header.
|
||||
* @param is_lazy_ Whether to load lazily.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
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_loaded ) ) {
|
||||
bool ret = get_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load the data of the section.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
bool load_data() const
|
||||
{
|
||||
Elf_Xword sh_offset =
|
||||
( *translator )[( *convertor )( header.sh_offset )];
|
||||
Elf_Xword size = get_size();
|
||||
|
||||
// Check for integer overflow in offset calculation
|
||||
if ( sh_offset > get_stream_size() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for integer overflow in size calculation
|
||||
if ( size > get_stream_size() ||
|
||||
size > ( get_stream_size() - sh_offset ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we need to load data
|
||||
if ( nullptr == data && SHT_NULL != get_type() &&
|
||||
SHT_NOBITS != get_type() ) {
|
||||
// Check if size can be safely converted to size_t
|
||||
if ( size > std::numeric_limits<size_t>::max() - 1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data.reset( new ( std::nothrow ) char[size_t( size ) + 1] );
|
||||
|
||||
if ( ( 0 != size ) && ( nullptr != data ) ) {
|
||||
pstream->seekg( sh_offset );
|
||||
pstream->read( data.get(), size );
|
||||
if ( static_cast<Elf_Xword>( pstream->gcount() ) != size ) {
|
||||
data.reset( nullptr );
|
||||
data_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
data_size = size;
|
||||
data.get()[size] = 0; // Safe now as we allocated size + 1
|
||||
}
|
||||
else {
|
||||
data_size = 0;
|
||||
if ( size != 0 ) {
|
||||
return false; // Failed to allocate required memory
|
||||
}
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Data already loaded or doesn't need loading
|
||||
is_loaded = ( nullptr != data ) || ( SHT_NULL == get_type() ) ||
|
||||
( SHT_NOBITS == get_type() );
|
||||
return is_loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Save the section to a stream.
|
||||
* @param stream Output stream.
|
||||
* @param header_offset Offset of the header.
|
||||
* @param data_offset Offset of the data.
|
||||
*/
|
||||
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:
|
||||
/**
|
||||
* @brief Save the header of the section to a stream.
|
||||
* @param stream Output stream.
|
||||
* @param header_offset Offset of the header.
|
||||
*/
|
||||
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 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Save the data of the section to a stream.
|
||||
* @param stream Output stream.
|
||||
* @param data_offset Offset of the data.
|
||||
*/
|
||||
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; /**< Pointer to the input stream. */
|
||||
T header = {}; /**< Section header. */
|
||||
Elf_Half index = 0; /**< Index of the section. */
|
||||
std::string name; /**< Name of the section. */
|
||||
mutable std::unique_ptr<char[]> data; /**< Pointer to the data. */
|
||||
mutable Elf_Xword data_size = 0; /**< Size of the data. */
|
||||
std::shared_ptr<endianness_convertor> convertor =
|
||||
nullptr; /**< Pointer to the endianness convertor. */
|
||||
std::shared_ptr<address_translator> translator =
|
||||
nullptr; /**< Pointer to the address translator. */
|
||||
std::shared_ptr<compression_interface> compression =
|
||||
nullptr; /**< Shared pointer to the compression interface. */
|
||||
bool is_address_set = false; /**< Flag indicating if the address is set. */
|
||||
size_t stream_size = 0; /**< Size of the stream. */
|
||||
mutable bool is_lazy =
|
||||
false; /**< Flag indicating if lazy loading is enabled. */
|
||||
mutable bool is_loaded =
|
||||
false; /**< Flag indicating if the data is loaded. */
|
||||
mutable bool can_be_loaded =
|
||||
true; /**< Flag indicating if the data can loaded. This is not the case if the section is corrupted. */
|
||||
};
|
||||
|
||||
} // namespace ELFIO
|
||||
|
||||
#endif // ELFIO_SECTION_HPP
|
||||
405
emulator/include/elfio/elfio_segment.hpp
Normal file
405
emulator/include/elfio/elfio_segment.hpp
Normal file
@ -0,0 +1,405 @@
|
||||
/*
|
||||
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
|
||||
//! \brief Class for accessing segment data
|
||||
class segment
|
||||
{
|
||||
friend class elfio;
|
||||
|
||||
public:
|
||||
virtual ~segment() = default;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the index of the segment
|
||||
//! \return Index of the segment
|
||||
ELFIO_GET_ACCESS_DECL( Elf_Half, index );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the type of the segment
|
||||
//! \return Type of the segment
|
||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the flags of the segment
|
||||
//! \return Flags of the segment
|
||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the alignment of the segment
|
||||
//! \return Alignment of the segment
|
||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the virtual address of the segment
|
||||
//! \return Virtual address of the segment
|
||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the physical address of the segment
|
||||
//! \return Physical address of the segment
|
||||
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the file size of the segment
|
||||
//! \return File size of the segment
|
||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the memory size of the segment
|
||||
//! \return Memory size of the segment
|
||||
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the offset of the segment
|
||||
//! \return Offset of the segment
|
||||
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the data of the segment
|
||||
//! \return Pointer to the data
|
||||
virtual const char* get_data() const = 0;
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Free the data of the segment
|
||||
virtual void free_data() const = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a section to the segment
|
||||
//! \param psec Pointer to the section
|
||||
//! \param addr_align Alignment of the section
|
||||
//! \return Index of the added section
|
||||
virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0;
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a section index to the segment
|
||||
//! \param index Index of the section
|
||||
//! \param addr_align Alignment of the section
|
||||
//! \return Index of the added section
|
||||
virtual Elf_Half add_section_index( Elf_Half index,
|
||||
Elf_Xword addr_align ) = 0;
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the number of sections in the segment
|
||||
//! \return Number of sections in the segment
|
||||
virtual Elf_Half get_sections_num() const = 0;
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the index of a section at a given position
|
||||
//! \param num Position of the section
|
||||
//! \return Index of the section
|
||||
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Check if the offset is initialized
|
||||
//! \return True if the offset is initialized, false otherwise
|
||||
virtual bool is_offset_initialized() const = 0;
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set the offset of the segment
|
||||
//! \param offset Offset of the segment
|
||||
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set the index of the segment
|
||||
//! \param index Index of the segment
|
||||
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the sections of the segment
|
||||
//! \return Vector of section indices
|
||||
virtual const std::vector<Elf_Half>& get_sections() const = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Load the segment from a stream
|
||||
//! \param stream Input stream
|
||||
//! \param header_offset Offset of the segment header
|
||||
//! \param is_lazy Whether to load the segment lazily
|
||||
//! \return True if successful, false otherwise
|
||||
virtual bool load( std::istream& stream,
|
||||
std::streampos header_offset,
|
||||
bool is_lazy ) = 0;
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Save the segment to a stream
|
||||
//! \param stream Output stream
|
||||
//! \param header_offset Offset of the segment header
|
||||
//! \param data_offset Offset of the segment data
|
||||
virtual void save( std::ostream& stream,
|
||||
std::streampos header_offset,
|
||||
std::streampos data_offset ) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class segment_impl
|
||||
//! \brief Implementation of the segment class
|
||||
template <class T> class segment_impl : public segment
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param convertor Pointer to the endianness convertor
|
||||
//! \param translator Pointer to the address translator
|
||||
segment_impl( std::shared_ptr<endianness_convertor> convertor,
|
||||
std::shared_ptr<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 );
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the index of the segment
|
||||
//! \return Index of the segment
|
||||
Elf_Half get_index() const override { return index; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the data of the segment
|
||||
//! \return Pointer to the data
|
||||
const char* get_data() const override
|
||||
{
|
||||
if ( !is_loaded ) {
|
||||
load_data();
|
||||
}
|
||||
return data.get();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Free the data of the segment
|
||||
void free_data() const override
|
||||
{
|
||||
if ( is_lazy ) {
|
||||
data.reset( nullptr );
|
||||
is_loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a section index to the segment
|
||||
//! \param sec_index Index of the section
|
||||
//! \param addr_align Alignment of the section
|
||||
//! \return Index of the added section
|
||||
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();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a section to the segment
|
||||
//! \param psec Pointer to the section
|
||||
//! \param addr_align Alignment of the section
|
||||
//! \return Index of the added section
|
||||
Elf_Half add_section( section* psec, Elf_Xword addr_align ) override
|
||||
{
|
||||
return add_section_index( psec->get_index(), addr_align );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the number of sections in the segment
|
||||
//! \return Number of sections in the segment
|
||||
Elf_Half get_sections_num() const override
|
||||
{
|
||||
return (Elf_Half)sections.size();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the index of a section at a given position
|
||||
//! \param num Position of the section
|
||||
//! \return Index of the section
|
||||
Elf_Half get_section_index_at( Elf_Half num ) const override
|
||||
{
|
||||
if ( num < sections.size() ) {
|
||||
return sections[num];
|
||||
}
|
||||
|
||||
return Elf_Half( -1 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
protected:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set the offset of the segment
|
||||
//! \param value Offset of the segment
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Check if the offset is initialized
|
||||
//! \return True if the offset is initialized, false otherwise
|
||||
bool is_offset_initialized() const override { return is_offset_set; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the sections of the segment
|
||||
//! \return Vector of section indices
|
||||
const std::vector<Elf_Half>& get_sections() const override
|
||||
{
|
||||
return sections;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set the index of the segment
|
||||
//! \param value Index of the segment
|
||||
void set_index( const Elf_Half& value ) override { index = value; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Load the segment from a stream
|
||||
//! \param stream Input stream
|
||||
//! \param header_offset Offset of the segment header
|
||||
//! \param is_lazy_ Whether to load the segment lazily
|
||||
//! \return True if successful, false otherwise
|
||||
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 || is_loaded ) ) {
|
||||
return load_data();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Load the data of the segment
|
||||
//! \return True if successful, false otherwise
|
||||
bool load_data() const
|
||||
{
|
||||
if ( PT_NULL == get_type() || 0 == get_file_size() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Elf_Xword p_offset = ( *translator )[( *convertor )( ph.p_offset )];
|
||||
Elf_Xword size = get_file_size();
|
||||
|
||||
// Check for integer overflow in offset calculation
|
||||
if ( p_offset > get_stream_size() ) {
|
||||
data = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for integer overflow in size calculation
|
||||
if ( size > get_stream_size() ||
|
||||
size > ( get_stream_size() - p_offset ) ) {
|
||||
data = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if size can be safely converted to size_t
|
||||
if ( size > std::numeric_limits<size_t>::max() - 1 ) {
|
||||
data = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
data.reset( new ( std::nothrow ) char[(size_t)size + 1] );
|
||||
|
||||
pstream->seekg( p_offset );
|
||||
if ( nullptr != data.get() && pstream->read( data.get(), size ) ) {
|
||||
data.get()[size] = 0;
|
||||
}
|
||||
else {
|
||||
data = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Save the segment to a stream
|
||||
//! \param stream Output stream
|
||||
//! \param header_offset Offset of the segment header
|
||||
//! \param data_offset Offset of the segment data
|
||||
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 ) );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the stream size
|
||||
//! \return Stream size
|
||||
size_t get_stream_size() const { return stream_size; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set the stream size
|
||||
//! \param value Stream size
|
||||
void set_stream_size( size_t value ) { stream_size = value; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
mutable std::istream* pstream = nullptr; //!< Pointer to the input stream
|
||||
T ph = {}; //!< Segment header
|
||||
Elf_Half index = 0; //!< Index of the segment
|
||||
mutable std::unique_ptr<char[]> data; //!< Pointer to the segment data
|
||||
std::vector<Elf_Half> sections; //!< Vector of section indices
|
||||
std::shared_ptr<endianness_convertor> convertor =
|
||||
nullptr; //!< Pointer to the endianness convertor
|
||||
std::shared_ptr<address_translator> translator =
|
||||
nullptr; //!< Pointer to the address translator
|
||||
size_t stream_size = 0; //!< Stream size
|
||||
bool is_offset_set = false; //!< Flag indicating if the offset is set
|
||||
mutable bool is_lazy =
|
||||
false; //!< Flag indicating if the segment is loaded lazily
|
||||
mutable bool is_loaded =
|
||||
false; //!< Flag indicating if the segment is loaded
|
||||
};
|
||||
|
||||
} // namespace ELFIO
|
||||
|
||||
#endif // ELFIO_SEGMENT_HPP
|
||||
143
emulator/include/elfio/elfio_strings.hpp
Normal file
143
emulator/include/elfio/elfio_strings.hpp
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
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>
|
||||
#include <limits>
|
||||
|
||||
namespace ELFIO {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class string_section_accessor_template
|
||||
//! \brief Class for accessing string section data
|
||||
template <class S> class string_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param section Pointer to the section
|
||||
explicit string_section_accessor_template( S* section )
|
||||
: string_section( section )
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get a string from the section
|
||||
//! \param index Index of the string
|
||||
//! \return Pointer to the string, or nullptr if not found
|
||||
const char* get_string( Elf_Word index ) const
|
||||
{
|
||||
if ( string_section ) {
|
||||
const char* data = string_section->get_data();
|
||||
size_t section_size =
|
||||
static_cast<size_t>( string_section->get_size() );
|
||||
|
||||
// Check if index is within bounds
|
||||
if ( index >= section_size || nullptr == data ) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check for integer overflow in size calculation
|
||||
size_t remaining_size = section_size - index;
|
||||
if ( remaining_size > section_size ) { // Check for underflow
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Use standard C++ functions to find string length
|
||||
const char* str = data + index;
|
||||
const char* end =
|
||||
(const char*)std::memchr( str, '\0', remaining_size );
|
||||
if ( end != nullptr && end < str + remaining_size ) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a string to the section
|
||||
//! \param str Pointer to the string
|
||||
//! \return Index of the added string
|
||||
Elf_Word add_string( const char* str )
|
||||
{
|
||||
if ( !str ) {
|
||||
return 0; // Return index of empty string for null input
|
||||
}
|
||||
|
||||
Elf_Word current_position = 0;
|
||||
|
||||
if ( string_section ) {
|
||||
// Strings are added 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++;
|
||||
}
|
||||
|
||||
// Calculate string length and check for overflow
|
||||
size_t str_len = std::strlen( str );
|
||||
if ( str_len > std::numeric_limits<Elf_Word>::max() - 1 ) {
|
||||
return 0; // String too long
|
||||
}
|
||||
|
||||
// Check if appending would overflow section size
|
||||
Elf_Word append_size = static_cast<Elf_Word>( str_len + 1 );
|
||||
if ( append_size >
|
||||
std::numeric_limits<Elf_Word>::max() - current_position ) {
|
||||
return 0; // Would overflow section size
|
||||
}
|
||||
|
||||
string_section->append_data( str, append_size );
|
||||
}
|
||||
|
||||
return current_position;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add a string to the section
|
||||
//! \param str The string to add
|
||||
//! \return Index of the added string
|
||||
Elf_Word add_string( const std::string& str )
|
||||
{
|
||||
return add_string( str.c_str() );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
S* string_section; //!< Pointer to the 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
|
||||
716
emulator/include/elfio/elfio_symbols.hpp
Normal file
716
emulator/include/elfio/elfio_symbols.hpp
Normal file
@ -0,0 +1,716 @@
|
||||
/*
|
||||
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 {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @class symbol_section_accessor_template
|
||||
// @brief A template class for accessing symbol sections in an ELF file.
|
||||
//------------------------------------------------------------------------------
|
||||
template <class S> class symbol_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Constructor
|
||||
// @param elf_file Reference to the ELF file
|
||||
// @param symbol_section Pointer to the symbol section
|
||||
//------------------------------------------------------------------------------
|
||||
explicit symbol_section_accessor_template( const elfio& elf_file,
|
||||
S* symbol_section )
|
||||
: elf_file( elf_file ), symbol_section( symbol_section )
|
||||
{
|
||||
find_hash_section();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the number of symbols in the section
|
||||
// @return Number of symbols
|
||||
//------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the symbol at the specified index
|
||||
// @param index Index of the symbol
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param section_index Section index of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @return True if the symbol is found, false otherwise
|
||||
//------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the symbol with the specified name
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param section_index Section index of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @return True if the symbol is found, false otherwise
|
||||
//------------------------------------------------------------------------------
|
||||
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<std::uint32_t>(
|
||||
name, value, size, bind, type, section_index, other );
|
||||
}
|
||||
else {
|
||||
ret = gnu_hash_lookup<std::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 ) &&
|
||||
( symbol_name == name ) ) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the symbol with the specified value
|
||||
// @param value Value of the symbol
|
||||
// @param name Name of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param section_index Section index of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @return True if the symbol is found, false otherwise
|
||||
//------------------------------------------------------------------------------
|
||||
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 auto& 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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Add a symbol to the section
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param info Info of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @param shndx Section index of the symbol
|
||||
// @return Index of the added symbol
|
||||
//------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Add a symbol to the section
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @param shndx Section index of the symbol
|
||||
// @return Index of the added symbol
|
||||
//------------------------------------------------------------------------------
|
||||
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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Add a symbol to the section
|
||||
// @param pStrWriter String section accessor
|
||||
// @param str Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param info Info of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @param shndx Section index of the symbol
|
||||
// @return Index of the added symbol
|
||||
//------------------------------------------------------------------------------
|
||||
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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Add a symbol to the section
|
||||
// @param pStrWriter String section accessor
|
||||
// @param str Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @param shndx Section index of the symbol
|
||||
// @return Index of the added symbol
|
||||
//------------------------------------------------------------------------------
|
||||
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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Arrange local symbols in the section
|
||||
// @param func Function to be called for each pair of symbols
|
||||
// @return Number of local symbols
|
||||
//------------------------------------------------------------------------------
|
||||
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:
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Find the hash section
|
||||
//------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the index of the string table
|
||||
// @return Index of the string table
|
||||
//------------------------------------------------------------------------------
|
||||
Elf_Half get_string_table_index() const
|
||||
{
|
||||
return (Elf_Half)symbol_section->get_link();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the index of the hash table
|
||||
// @return Index of the hash table
|
||||
//------------------------------------------------------------------------------
|
||||
Elf_Half get_hash_table_index() const { return hash_section_index; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Lookup a symbol in the hash table
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param section_index Section index of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @return True if the symbol is found, false otherwise
|
||||
//------------------------------------------------------------------------------
|
||||
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 auto& 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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Lookup a symbol in the GNU hash table
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param section_index Section index of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @return True if the symbol is found, false otherwise
|
||||
//------------------------------------------------------------------------------
|
||||
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 auto& convertor = elf_file.get_convertor();
|
||||
|
||||
std::uint32_t nbuckets =
|
||||
*( (std::uint32_t*)hash_section->get_data() + 0 );
|
||||
std::uint32_t symoffset =
|
||||
*( (std::uint32_t*)hash_section->get_data() + 1 );
|
||||
std::uint32_t bloom_size =
|
||||
*( (std::uint32_t*)hash_section->get_data() + 2 );
|
||||
std::uint32_t bloom_shift =
|
||||
*( (std::uint32_t*)hash_section->get_data() + 3 );
|
||||
nbuckets = ( *convertor )( nbuckets );
|
||||
symoffset = ( *convertor )( symoffset );
|
||||
bloom_size = ( *convertor )( bloom_size );
|
||||
bloom_shift = ( *convertor )( bloom_shift );
|
||||
|
||||
auto* bloom_filter =
|
||||
(T*)( hash_section->get_data() + 4 * sizeof( std::uint32_t ) );
|
||||
|
||||
std::uint32_t hash = elf_gnu_hash( (const unsigned char*)name.c_str() );
|
||||
std::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;
|
||||
|
||||
std::uint32_t bucket = hash % nbuckets;
|
||||
auto* buckets = (std::uint32_t*)( hash_section->get_data() +
|
||||
4 * sizeof( std::uint32_t ) +
|
||||
bloom_size * sizeof( T ) );
|
||||
auto* chains = (std::uint32_t*)( hash_section->get_data() +
|
||||
4 * sizeof( std::uint32_t ) +
|
||||
bloom_size * sizeof( T ) +
|
||||
nbuckets * sizeof( std::uint32_t ) );
|
||||
|
||||
if ( ( *convertor )( buckets[bucket] ) >= symoffset ) {
|
||||
std::uint32_t chain_index =
|
||||
( *convertor )( buckets[bucket] ) - symoffset;
|
||||
std::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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the symbol at the specified index
|
||||
// @param index Index of the symbol
|
||||
// @return Pointer to the symbol
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> const T* generic_get_symbol_ptr( Elf_Xword index ) const
|
||||
{
|
||||
if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) {
|
||||
if ( symbol_section->get_entry_size() < sizeof( T ) ) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto* pSym = reinterpret_cast<const T*>(
|
||||
symbol_section->get_data() +
|
||||
index * symbol_section->get_entry_size() );
|
||||
|
||||
return pSym;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Search for a symbol in the section
|
||||
// @param match Function to be called for each symbol
|
||||
// @param idx Index of the found symbol
|
||||
// @return True if the symbol is found, false otherwise
|
||||
//------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Get the symbol at the specified index
|
||||
// @param index Index of the symbol
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param bind Binding of the symbol
|
||||
// @param type Type of the symbol
|
||||
// @param section_index Section index of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @return True if the symbol is found, false otherwise
|
||||
//------------------------------------------------------------------------------
|
||||
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 auto* pSym = reinterpret_cast<const T*>(
|
||||
symbol_section->get_data() +
|
||||
index * symbol_section->get_entry_size() );
|
||||
|
||||
const auto& 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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Add a symbol to the section
|
||||
// @param name Name of the symbol
|
||||
// @param value Value of the symbol
|
||||
// @param size Size of the symbol
|
||||
// @param info Info of the symbol
|
||||
// @param other Other attributes of the symbol
|
||||
// @param shndx Section index of the symbol
|
||||
// @return Index of the added symbol
|
||||
//------------------------------------------------------------------------------
|
||||
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 auto& 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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// @brief Arrange local symbols in the section
|
||||
// @param func Function to be called for each pair of symbols
|
||||
// @return Number of local symbols
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
Elf_Xword generic_arrange_local_symbols(
|
||||
std::function<void( Elf_Xword first, Elf_Xword second )> func )
|
||||
{
|
||||
const auto& 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; ///< Reference to the ELF file
|
||||
S* symbol_section; ///< Pointer to the symbol section
|
||||
Elf_Half hash_section_index{ 0 }; ///< Index of the hash section
|
||||
const section* hash_section{ nullptr }; ///< Pointer to the hash section
|
||||
};
|
||||
|
||||
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
|
||||
373
emulator/include/elfio/elfio_utils.hpp
Normal file
373
emulator/include/elfio/elfio_utils.hpp
Normal file
@ -0,0 +1,373 @@
|
||||
/*
|
||||
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>
|
||||
#include <cstring>
|
||||
|
||||
#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 endianness_convertor
|
||||
//! \brief Class for converting endianness of data
|
||||
class endianness_convertor
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Setup the endianness convertor
|
||||
//! \param elf_file_encoding The encoding of the ELF file
|
||||
void setup( unsigned char elf_file_encoding )
|
||||
{
|
||||
need_conversion = ( elf_file_encoding != get_host_encoding() );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert a 64-bit unsigned integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::uint64_t operator()( std::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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert a 64-bit signed integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::int64_t operator()( std::int64_t value ) const
|
||||
{
|
||||
if ( !need_conversion ) {
|
||||
return value;
|
||||
}
|
||||
return ( std::int64_t )( *this )( (std::uint64_t)value );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert a 32-bit unsigned integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::uint32_t operator()( std::uint32_t value ) const
|
||||
{
|
||||
if ( !need_conversion ) {
|
||||
return value;
|
||||
}
|
||||
value =
|
||||
( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) |
|
||||
( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert a 32-bit signed integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::int32_t operator()( std::int32_t value ) const
|
||||
{
|
||||
if ( !need_conversion ) {
|
||||
return value;
|
||||
}
|
||||
return ( std::int32_t )( *this )( (std::uint32_t)value );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert a 16-bit unsigned integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::uint16_t operator()( std::uint16_t value ) const
|
||||
{
|
||||
if ( !need_conversion ) {
|
||||
return value;
|
||||
}
|
||||
value = ( std::uint16_t )( ( value & 0x00FF ) << 8 ) |
|
||||
( ( value & 0xFF00 ) >> 8 );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert a 16-bit signed integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::int16_t operator()( std::int16_t value ) const
|
||||
{
|
||||
if ( !need_conversion ) {
|
||||
return value;
|
||||
}
|
||||
return ( std::int16_t )( *this )( (std::uint16_t)value );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert an 8-bit signed integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::int8_t operator()( std::int8_t value ) const { return value; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert an 8-bit unsigned integer
|
||||
//! \param value The value to convert
|
||||
//! \return The converted value
|
||||
std::uint8_t operator()( std::uint8_t value ) const { return value; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the host encoding
|
||||
//! \return The host encoding
|
||||
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; //!< Flag indicating if conversion is needed
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \struct address_translation
|
||||
//! \brief Structure for address translation
|
||||
struct address_translation
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param start The start address
|
||||
//! \param size The size of the address range
|
||||
//! \param mapped_to The mapped address
|
||||
address_translation( std::uint64_t start,
|
||||
std::uint64_t size,
|
||||
std::uint64_t mapped_to )
|
||||
: start( start ), size( size ), mapped_to( mapped_to ){};
|
||||
std::streampos start; //!< Start address
|
||||
std::streampos size; //!< Size of the address range
|
||||
std::streampos mapped_to; //!< Mapped address
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class address_translator
|
||||
//! \brief Class for translating addresses
|
||||
class address_translator
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Set address translation
|
||||
//! \param addr_trans Vector of address translations
|
||||
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;
|
||||
} );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Translate an address
|
||||
//! \param value The address to translate
|
||||
//! \return The translated address
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Check if the address translator is empty
|
||||
//! \return True if empty, false otherwise
|
||||
bool empty() const { return addr_translations.empty(); }
|
||||
|
||||
private:
|
||||
std::vector<address_translation>
|
||||
addr_translations; //!< Vector of address translations
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Calculate the ELF hash of a name
|
||||
//! \param name The name to hash
|
||||
//! \return The ELF hash
|
||||
inline std::uint32_t elf_hash( const unsigned char* name )
|
||||
{
|
||||
std::uint32_t h = 0;
|
||||
std::uint32_t g = 0;
|
||||
while ( *name != '\0' ) {
|
||||
h = ( h << 4 ) + *name++;
|
||||
g = h & 0xf0000000;
|
||||
if ( g != 0 )
|
||||
h ^= g >> 24;
|
||||
h &= ~g;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Calculate the GNU hash of a name
|
||||
//! \param s The name to hash
|
||||
//! \return The GNU hash
|
||||
inline std::uint32_t elf_gnu_hash( const unsigned char* s )
|
||||
{
|
||||
std::uint32_t h = 0x1505;
|
||||
for ( unsigned char c = *s; c != '\0'; c = *++s )
|
||||
h = ( h << 5 ) + h + c;
|
||||
return h;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Convert a value to a hexadecimal string
|
||||
//! \param value The value to convert
|
||||
//! \return The hexadecimal string
|
||||
inline std::string to_hex_string( std::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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Adjust the size of a stream
|
||||
//! \param stream The stream to adjust
|
||||
//! \param offset The offset to adjust to
|
||||
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 );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the length of a string with a maximum length
|
||||
//! \param s The string
|
||||
//! \param n The maximum length
|
||||
//! \return The length of the string
|
||||
inline static size_t strnlength( const char* s, size_t n )
|
||||
{
|
||||
auto found = (const char*)std::memchr( s, '\0', n );
|
||||
return found ? (size_t)( found - s ) : n;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class compression_interface
|
||||
//! \brief Interface for compression and decompression
|
||||
class compression_interface
|
||||
{
|
||||
public:
|
||||
virtual ~compression_interface() = default;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Decompress a compressed section
|
||||
//! \param data The buffer of compressed data
|
||||
//! \param convertor Pointer to an endianness convertor instance
|
||||
//! \param compressed_size The size of the compressed data buffer
|
||||
//! \param uncompressed_size Reference to a variable to store the decompressed buffer size
|
||||
//! \return A smart pointer to the decompressed data
|
||||
virtual std::unique_ptr<char[]>
|
||||
inflate( const char* data,
|
||||
std::shared_ptr<const endianness_convertor> convertor,
|
||||
Elf_Xword compressed_size,
|
||||
Elf_Xword& uncompressed_size ) const = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Compress a section
|
||||
//! \param data The buffer of uncompressed data
|
||||
//! \param convertor Pointer to an endianness convertor instance
|
||||
//! \param decompressed_size The size of the uncompressed data buffer
|
||||
//! \param compressed_size Reference to a variable to store the compressed buffer size
|
||||
//! \return A smart pointer to the compressed data
|
||||
virtual std::unique_ptr<char[]>
|
||||
deflate( const char* data,
|
||||
std::shared_ptr<const endianness_convertor> convertor,
|
||||
Elf_Xword decompressed_size,
|
||||
Elf_Xword& compressed_size ) const = 0;
|
||||
};
|
||||
|
||||
} // namespace ELFIO
|
||||
|
||||
#endif // ELFIO_UTILS_HPP
|
||||
4
emulator/include/elfio/elfio_version.hpp
Normal file
4
emulator/include/elfio/elfio_version.hpp
Normal file
@ -0,0 +1,4 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//! \def ELFIO_VERSION
|
||||
//! \brief Defines the version of the ELFIO library
|
||||
#define ELFIO_VERSION "3.14"
|
||||
310
emulator/include/elfio/elfio_versym.hpp
Normal file
310
emulator/include/elfio/elfio_versym.hpp
Normal file
@ -0,0 +1,310 @@
|
||||
/*
|
||||
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 {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class versym_section_accessor_template
|
||||
//! \brief Class for accessing version symbol section data
|
||||
template <class S> class versym_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param section Pointer to the section
|
||||
explicit versym_section_accessor_template( S* section )
|
||||
: versym_section( section )
|
||||
{
|
||||
if ( section != nullptr ) {
|
||||
entries_num = decltype( entries_num )( section->get_size() /
|
||||
sizeof( Elf_Half ) );
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the number of entries
|
||||
//! \return Number of entries
|
||||
Elf_Word get_entries_num() const
|
||||
{
|
||||
if ( versym_section ) {
|
||||
return entries_num;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get an entry
|
||||
//! \param no Index of the entry
|
||||
//! \param value Value of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Modify an entry
|
||||
//! \param no Index of the entry
|
||||
//! \param value New value of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Add an entry
|
||||
//! \param value Value of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
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; //!< Pointer to the section
|
||||
Elf_Word entries_num = 0; //!< Number of entries
|
||||
};
|
||||
|
||||
using versym_section_accessor = versym_section_accessor_template<section>;
|
||||
using const_versym_section_accessor =
|
||||
versym_section_accessor_template<const section>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class versym_r_section_accessor_template
|
||||
//! \brief Class for accessing version requirement section data
|
||||
template <class S> class versym_r_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param elf_file Reference to the ELF file
|
||||
//! \param versym_r_section Pointer to the version requirement section
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the number of entries
|
||||
//! \return Number of entries
|
||||
Elf_Word get_entries_num() const { return entries_num; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get an entry
|
||||
//! \param no Index of the entry
|
||||
//! \param version Version of the entry
|
||||
//! \param file_name File name of the entry
|
||||
//! \param hash Hash of the entry
|
||||
//! \param flags Flags of the entry
|
||||
//! \param other Other information of the entry
|
||||
//! \param dep_name Dependency name of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
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; //!< Pointer to the version requirement section
|
||||
Elf_Word entries_num = 0; //!< Number of entries
|
||||
};
|
||||
|
||||
using versym_r_section_accessor = versym_r_section_accessor_template<section>;
|
||||
using const_versym_r_section_accessor =
|
||||
versym_r_section_accessor_template<const section>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \class versym_d_section_accessor_template
|
||||
//! \brief Class for accessing version definition section data
|
||||
template <class S> class versym_d_section_accessor_template
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Constructor
|
||||
//! \param elf_file Reference to the ELF file
|
||||
//! \param versym_d_section Pointer to the version definition section
|
||||
versym_d_section_accessor_template( const elfio& elf_file,
|
||||
S* versym_d_section )
|
||||
: elf_file( elf_file ), versym_d_section( versym_d_section ),
|
||||
entries_num( 0 )
|
||||
{
|
||||
// Find .dynamic section
|
||||
const section* dynamic_section = elf_file.sections[".dynamic"];
|
||||
|
||||
if ( dynamic_section == nullptr ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const_dynamic_section_accessor dynamic_section_acc( elf_file,
|
||||
dynamic_section );
|
||||
Elf_Xword dyn_sec_num = dynamic_section_acc.get_entries_num();
|
||||
for ( Elf_Xword i = 0; i < dyn_sec_num; ++i ) {
|
||||
Elf_Xword tag;
|
||||
Elf_Xword value;
|
||||
std::string str;
|
||||
|
||||
if ( dynamic_section_acc.get_entry( i, tag, value, str ) &&
|
||||
tag == DT_VERDEFNUM ) {
|
||||
entries_num = (Elf_Word)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get the number of entries
|
||||
//! \return Number of entries
|
||||
Elf_Word get_entries_num() const { return entries_num; }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Get an entry
|
||||
//! \param no Index of the entry
|
||||
//! \param flags Flags of the entry
|
||||
//! \param version_index Version index of the entry
|
||||
//! \param hash Hash of the entry
|
||||
//! \param dep_name Dependency name of the entry
|
||||
//! \return True if successful, false otherwise
|
||||
bool get_entry( Elf_Word no,
|
||||
Elf_Half& flags,
|
||||
Elf_Half& version_index,
|
||||
Elf_Word& hash,
|
||||
std::string& dep_name ) const
|
||||
{
|
||||
if ( versym_d_section == nullptr || ( no >= get_entries_num() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const_string_section_accessor string_section_acc(
|
||||
elf_file.sections[versym_d_section->get_link()] );
|
||||
|
||||
Elfxx_Verdef* verdef = (Elfxx_Verdef*)versym_d_section->get_data();
|
||||
Elfxx_Verdaux* verdaux =
|
||||
(Elfxx_Verdaux*)( (char*)verdef + verdef->vd_aux );
|
||||
for ( Elf_Word i = 0; i < no; ++i ) {
|
||||
verdef = (Elfxx_Verdef*)( (char*)verdef + verdef->vd_next );
|
||||
verdaux = (Elfxx_Verdaux*)( (char*)verdef + verdef->vd_aux );
|
||||
}
|
||||
|
||||
// verdef->vd_version should always be 1
|
||||
// see https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA.junk/symversion.html#VERDEFENTRIES
|
||||
// verdef->vd_cnt should always be 1.
|
||||
// see https://maskray.me/blog/2020-11-26-all-about-symbol-versioning
|
||||
|
||||
flags = verdef->vd_flags;
|
||||
version_index = verdef->vd_ndx;
|
||||
hash = verdef->vd_hash;
|
||||
dep_name = string_section_acc.get_string( verdaux->vda_name );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
const elfio& elf_file;
|
||||
S* versym_d_section =
|
||||
nullptr; //!< Pointer to the version definition section
|
||||
Elf_Word entries_num = 0; //!< Number of entries
|
||||
};
|
||||
|
||||
using versym_d_section_accessor = versym_d_section_accessor_template<section>;
|
||||
using const_versym_d_section_accessor =
|
||||
versym_d_section_accessor_template<const section>;
|
||||
|
||||
} // namespace ELFIO
|
||||
|
||||
#endif // ELFIO_VERSYM_HPP
|
||||
@ -47,20 +47,24 @@ class Emulator
|
||||
public:
|
||||
static constexpr uint8_t PC = 31;
|
||||
static constexpr uint8_t LC = 30;
|
||||
static constexpr uint8_t RA = 29;
|
||||
static constexpr uint8_t SP = 28;
|
||||
|
||||
Emulator();
|
||||
|
||||
void run(const std::vector<uint32_t>& program);
|
||||
void run(std::istream& program);
|
||||
|
||||
void map_device(std::unique_ptr<Device>&& device);
|
||||
|
||||
uint32_t& memory_at(uint16_t address);
|
||||
uint32_t& memory_at(uint32_t address);
|
||||
uint32_t& decode_operand(Operand operand);
|
||||
uint32_t& register_at(uint8_t index);
|
||||
|
||||
void run_instruction();
|
||||
|
||||
private:
|
||||
std::array<uint32_t, 1 << 16> memory;
|
||||
std::array<uint32_t, 1 << 17> memory;
|
||||
std::array<uint32_t, 1 << 5> registers;
|
||||
enum class Status
|
||||
{
|
||||
@ -72,9 +76,10 @@ private:
|
||||
uint32_t configuration;
|
||||
uint32_t dummy_value;
|
||||
std::vector<std::unique_ptr<Device>> devices;
|
||||
uint16_t mapped_base;
|
||||
uint32_t mapped_base;
|
||||
bool keep_running;
|
||||
|
||||
void run_internal();
|
||||
void read_instruction();
|
||||
|
||||
void CNST();
|
||||
@ -86,6 +91,7 @@ private:
|
||||
void BWOR();
|
||||
void BAND();
|
||||
void BXOR();
|
||||
void ZRSH();
|
||||
void SRSH();
|
||||
void ZLSH();
|
||||
void CLSH();
|
||||
@ -95,6 +101,7 @@ private:
|
||||
void DIVI();
|
||||
void MODU();
|
||||
|
||||
bool should_run() const;
|
||||
bool repeats() const;
|
||||
uint8_t simd_elements() const;
|
||||
uint8_t shift() const;
|
||||
@ -104,6 +111,7 @@ private:
|
||||
|
||||
uint32_t op_arithmetic_negate(uint32_t a) const;
|
||||
uint32_t op_logical_negate(uint32_t a) const;
|
||||
uint32_t op_pad_zero_right_shift(uint32_t a, uint32_t b) const;
|
||||
uint32_t op_signed_right_shift(uint32_t a, uint32_t b) const;
|
||||
uint32_t op_pad_zero_left_shift(uint32_t a, uint32_t b) const;
|
||||
uint32_t op_circular_left_shift(uint32_t a, uint32_t b) const;
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <elfio/elfio.hpp>
|
||||
|
||||
namespace foot
|
||||
{
|
||||
|
||||
@ -28,36 +30,52 @@ Emulator::Emulator() :
|
||||
memory{},
|
||||
registers{},
|
||||
configuration(0),
|
||||
mapped_base(0)
|
||||
{}
|
||||
mapped_base(0x00010000)
|
||||
{
|
||||
registers[SP] = 0xFFFF; // stack pointer
|
||||
}
|
||||
|
||||
void Emulator::run(const std::vector<uint32_t>& program)
|
||||
{
|
||||
std::copy(program.begin(), program.end(), memory.begin());
|
||||
|
||||
keep_running = true;
|
||||
while (keep_running)
|
||||
run_internal();
|
||||
}
|
||||
|
||||
void Emulator::run(std::istream& program)
|
||||
{
|
||||
ELFIO::elfio reader;
|
||||
reader.load(program);
|
||||
|
||||
for (const auto& seg : reader.segments)
|
||||
{
|
||||
run_instruction();
|
||||
for (auto& device : devices)
|
||||
|
||||
uint64_t dest = seg->get_virtual_address();
|
||||
uint64_t msize = seg->get_memory_size();
|
||||
uint64_t fsize = seg->get_file_size();
|
||||
const char* data = seg->get_data();
|
||||
|
||||
if (seg->get_type() != ELFIO::PT_LOAD)
|
||||
{
|
||||
if (device->update())
|
||||
{
|
||||
keep_running = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(reinterpret_cast<char*>(memory.data()) + dest, data, fsize);
|
||||
}
|
||||
|
||||
registers[PC] = reader.get_entry() / 4;
|
||||
|
||||
run_internal();
|
||||
}
|
||||
|
||||
void Emulator::map_device(std::unique_ptr<Device>&& device)
|
||||
{
|
||||
mapped_base -= device->mapped_memory_size();
|
||||
device->assigned_memory_base = &memory[mapped_base];
|
||||
|
||||
mapped_base += device->mapped_memory_size();
|
||||
devices.push_back(std::move(device));
|
||||
}
|
||||
|
||||
uint32_t& Emulator::memory_at(uint16_t address)
|
||||
uint32_t& Emulator::memory_at(uint32_t address)
|
||||
{
|
||||
return memory[address];
|
||||
}
|
||||
@ -77,7 +95,7 @@ uint32_t& Emulator::decode_operand(Operand operand)
|
||||
return memory[registers[operand.register_index]++];
|
||||
|
||||
case Operand::AddressingMode::Indirect:
|
||||
return memory[registers[operand.register_index]];
|
||||
return memory[registers[operand.register_index]];
|
||||
|
||||
default:
|
||||
return dummy_value;
|
||||
@ -93,6 +111,11 @@ void Emulator::run_instruction()
|
||||
{
|
||||
read_instruction();
|
||||
|
||||
if (!should_run())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool rep = repeats();
|
||||
const uint32_t loop_count = rep ? registers[LC] : 1;
|
||||
|
||||
@ -143,6 +166,10 @@ void Emulator::run_instruction()
|
||||
BXOR();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ZRSH();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
SRSH();
|
||||
break;
|
||||
@ -183,6 +210,22 @@ void Emulator::run_instruction()
|
||||
if (rep) { registers[LC] = loop_count; }
|
||||
}
|
||||
|
||||
void Emulator::run_internal()
|
||||
{
|
||||
keep_running = true;
|
||||
while (keep_running)
|
||||
{
|
||||
run_instruction();
|
||||
for (const auto& device : devices)
|
||||
{
|
||||
if (device->update())
|
||||
{
|
||||
keep_running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Emulator::read_instruction()
|
||||
{
|
||||
instruction = memory[registers[PC]++];
|
||||
@ -272,6 +315,15 @@ void Emulator::BXOR()
|
||||
d = a ^ b;
|
||||
}
|
||||
|
||||
void Emulator::ZRSH()
|
||||
{
|
||||
uint32_t a = decode_operand(instruction & 0x000000FF);
|
||||
uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8);
|
||||
uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16);
|
||||
|
||||
d = apply_many_binary(a, b, &Emulator::op_pad_zero_right_shift);
|
||||
}
|
||||
|
||||
void Emulator::SRSH()
|
||||
{
|
||||
uint32_t a = decode_operand(instruction & 0x000000FF);
|
||||
@ -344,6 +396,36 @@ void Emulator::MODU()
|
||||
d = apply_many_binary(a, b, &Emulator::op_mod);
|
||||
}
|
||||
|
||||
bool Emulator::should_run() const
|
||||
{
|
||||
switch ((instruction & 0xE0000000) >> 29)
|
||||
{
|
||||
case 0:
|
||||
return true;
|
||||
|
||||
case 1:
|
||||
return status_register == Status::Less;
|
||||
|
||||
case 2:
|
||||
return status_register == Status::Less || status_register == Status::Equal;
|
||||
|
||||
case 3:
|
||||
return status_register == Status::Equal;
|
||||
|
||||
case 4:
|
||||
return status_register == Status::Greater || status_register == Status::Equal;
|
||||
|
||||
case 5:
|
||||
return status_register == Status::Greater;
|
||||
|
||||
case 6:
|
||||
return status_register == Status::Less || status_register == Status::Greater;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Emulator::repeats() const
|
||||
{
|
||||
return instruction & 0x10000000;
|
||||
@ -404,6 +486,11 @@ uint32_t Emulator::op_logical_negate(uint32_t a) const
|
||||
return !a;
|
||||
}
|
||||
|
||||
uint32_t Emulator::op_pad_zero_right_shift(uint32_t a, uint32_t b) const
|
||||
{
|
||||
return a >> b;
|
||||
}
|
||||
|
||||
uint32_t Emulator::op_signed_right_shift(uint32_t a, uint32_t b) const
|
||||
{
|
||||
return int32_t(a) >> b;
|
||||
|
||||
@ -8,26 +8,6 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
std::vector<uint32_t> read_file(std::istream& stream)
|
||||
{
|
||||
std::vector<uint32_t> buf;
|
||||
|
||||
std::streampos pos = stream.tellg();
|
||||
stream.seekg(0, std::ios::end);
|
||||
pos = stream.tellg() - pos;
|
||||
buf.resize(pos / 4);
|
||||
stream.seekg(0, std::ios::beg);
|
||||
|
||||
for (int i = 0; i < buf.size(); i++)
|
||||
{
|
||||
unsigned char value[4] = {};
|
||||
stream.read((char*)value, 4);
|
||||
buf[i] = uint32_t(value[0]) | (uint32_t(value[1]) << 8) | (uint32_t(value[2]) << 16) | (uint32_t(value[3]) << 24);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
class PrintDevice : public foot::Device
|
||||
{
|
||||
public:
|
||||
@ -41,7 +21,7 @@ public:
|
||||
uint32_t& value = memory(0);
|
||||
if (value != 0)
|
||||
{
|
||||
std::cout << char(value);
|
||||
SDL_Log("%1s", (char*)&value);
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@ -134,7 +114,7 @@ int main(int argc, char** argv)
|
||||
emu.map_device(std::make_unique<PrintDevice>());
|
||||
emu.map_device(std::make_unique<MemoryViewDevice>(render, WIDTH, HEIGHT));
|
||||
|
||||
emu.run(read_file(file));
|
||||
emu.run(file);
|
||||
|
||||
SDL_DestroyRenderer(render);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
@ -15,6 +15,7 @@ test(long-instruction)
|
||||
test(bwor-instruction)
|
||||
test(band-instruction)
|
||||
test(bxor-instruction)
|
||||
test(zrsh-instruction)
|
||||
test(srsh-instruction)
|
||||
test(zlsh-instruction)
|
||||
test(clsh-instruction)
|
||||
@ -22,4 +23,4 @@ test(addi-instruction)
|
||||
test(subt-instruction)
|
||||
test(mult-instruction)
|
||||
test(divi-instruction)
|
||||
test(modu-instruction)
|
||||
test(modu-instruction)
|
||||
36
emulator/tests/zrsh-instruction.cpp
Normal file
36
emulator/tests/zrsh-instruction.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "test-common.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// CNST
|
||||
// dst - 0, Direct
|
||||
// imm - 0x4567
|
||||
//
|
||||
// ZRSH
|
||||
// dst - 0, Direct
|
||||
// a - 0, Direct
|
||||
// b - 2, Immediate
|
||||
{
|
||||
foot::Emulator emu = run_instructions({ 0x00204567, 0x05200220 });
|
||||
if (!check(0x1159, emu.register_at(0))) { return 1; }
|
||||
}
|
||||
|
||||
// CNST
|
||||
// dst - 0, Direct
|
||||
// imm - 0x4343
|
||||
//
|
||||
// CNST
|
||||
// dst - 1, Direct
|
||||
// imm - 0x1122
|
||||
//
|
||||
// ZRSH - 4-bit SIMD
|
||||
// dst - 0, Direct
|
||||
// a - 0, Direct
|
||||
// b - 1, Direct
|
||||
{
|
||||
foot::Emulator emu = run_instructions({ 0x00204343, 0x00211122, 0x05A021A0 });
|
||||
if (!check(0x2110, emu.register_at(0))) { return 1; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user