diff --git a/elfio/elfio.hpp b/elfio/elfio.hpp index 33dd5a0..7235cbf 100644 --- a/elfio/elfio.hpp +++ b/elfio/elfio.hpp @@ -81,6 +81,7 @@ class elfio sections_ = std::move( other.sections_ ); segments_ = std::move( other.segments_ ); convertor = std::move( other.convertor ); + addr_translator = std::move( other.addr_translator ); current_file_pos = std::move( other.current_file_pos ); other.header = nullptr; @@ -97,6 +98,7 @@ class elfio sections_ = std::move( other.sections_ ); segments_ = std::move( other.segments_ ); convertor = std::move( other.convertor ); + addr_translator = std::move( other.addr_translator ); current_file_pos = std::move( other.current_file_pos ); other.header = nullptr; @@ -391,6 +393,9 @@ class elfio delete it; } segments_.clear(); + + std::vector empty_address_translation; + addr_translator.set_address_translation( empty_address_translation ); } //------------------------------------------------------------------------------ diff --git a/elfio/elfio_utils.hpp b/elfio/elfio_utils.hpp index 8452538..2ae91f9 100644 --- a/elfio/elfio_utils.hpp +++ b/elfio/elfio_utils.hpp @@ -163,10 +163,10 @@ class endianess_convertor //------------------------------------------------------------------------------ struct address_translation { - address_translation( uint64_t start, uint64_t end, uint64_t map_to ) - : start( start ), end( end ), map_to( map_to ){}; + address_translation( uint64_t start, uint64_t size, uint64_t map_to ) + : start( start ), size( size ), map_to( map_to ){}; std::streampos start; - std::streampos end; + std::streampos size; std::streampos map_to; }; @@ -177,19 +177,24 @@ class address_translator //------------------------------------------------------------------------------ void set_address_translation( std::vector& addr_trans ) { - translation = addr_trans; + addr_translations = addr_trans; + + std::sort( + addr_translations.begin(), addr_translations.end(), + []( address_translation& a, address_translation& b ) -> bool { + return a.map_to < b.map_to; + } ); } //------------------------------------------------------------------------------ std::streampos operator[]( std::streampos value ) const { - if ( translation.empty() ) { + if ( addr_translations.empty() ) { return value; } - for ( auto& t : translation ) { - if ( t.map_to <= value && - ( ( value - t.map_to ) < ( t.end - t.start ) ) ) { + for ( auto& t : addr_translations ) { + if ( ( t.map_to <= value ) && ( ( value - t.map_to ) < t.size ) ) { return t.start - t.map_to + value; } } @@ -197,10 +202,10 @@ class address_translator return value; } - bool empty() const { return translation.empty(); } + bool empty() const { return addr_translations.empty(); } private: - std::vector translation; + std::vector addr_translations; }; //------------------------------------------------------------------------------ diff --git a/examples/proc_mem/proc_mem.cpp b/examples/proc_mem/proc_mem.cpp index 0b290a1..21ed765 100644 --- a/examples/proc_mem/proc_mem.cpp +++ b/examples/proc_mem/proc_mem.cpp @@ -30,6 +30,7 @@ THE SOFTWARE. using namespace ELFIO; +//------------------------------------------------------------------------------ void get_translation_ranges( std::ifstream& proc_maps, const std::string& file_name, std::vector& result ) @@ -46,24 +47,20 @@ void get_translation_ranges( std::ifstream& proc_maps, if ( std::regex_match( line, match, rexpr ) ) { if ( match.size() == 9 && match[8].str() == file_name ) { - result.emplace_back( address_translation( - std::stoul( match[1].str(), 0, 16 ), - std::stoul( match[2].str(), 0, 16 ), - std::stoul( match[4].str(), 0, 16 ) ) ); + unsigned long start = std::stoul( match[1].str(), 0, 16 ); + unsigned long end = std::stoul( match[2].str(), 0, 16 ); + unsigned long mapped = std::stoul( match[4].str(), 0, 16 ); + result.emplace_back( start, end - start, mapped ); } } } - - std::sort( result.begin(), result.end(), - []( address_translation& a, address_translation& b ) -> bool { - return a.map_to < b.map_to; - } ); } +//------------------------------------------------------------------------------ int main( int argc, char** argv ) { if ( argc != 3 ) { - std::cout << "Usage: proc_mem pid full_file_path" << std::endl; + std::cout << "Usage: proc_mem " << std::endl; return 1; } @@ -76,16 +73,15 @@ int main( int argc, char** argv ) return 2; } + // Retrieve memory address translation ranges std::vector ranges; get_translation_ranges( proc_maps, argv[2], ranges ); - // for ( auto& range : ranges ) { - // std::cout << std::hex << range.start << " " << range.end << " " - // << range.map_to << std::endl; - // } + // Set address translation ranges prior loading ELF file elfio elffile; elffile.set_address_translation( ranges ); + // The 'load' will use the provided address translation now if ( elffile.load( std::string( "/proc/" ) + argv[1] + "/mem" ) ) { dump::header( std::cout, elffile ); dump::segment_headers( std::cout, elffile ); diff --git a/tests/ELFIOTest2.cpp b/tests/ELFIOTest2.cpp index 792c397..9aad78d 100644 --- a/tests/ELFIOTest2.cpp +++ b/tests/ELFIOTest2.cpp @@ -433,9 +433,9 @@ BOOST_AUTO_TEST_CASE( address_translation_test ) { std::vector ranges; - ranges.emplace_back( 500, 600, 0 ); - ranges.emplace_back( 1000, 2000, 500 ); - ranges.emplace_back( 3000, 4000, 2000 ); + ranges.emplace_back( 500, 100, 0 ); + ranges.emplace_back( 1000, 1000, 500 ); + ranges.emplace_back( 3000, 1000, 2000 ); address_translator tr; tr.set_address_translation( ranges );