diff --git a/.vscode/launch.json b/.vscode/launch.json
index 942fb136f4bcde72df28aea83279a604f7226684..d870f5078aa1e573ecf6fb4feb751b0a9fa173c9 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -48,6 +48,29 @@
             ],
             "preLaunchTask": "ELF Dump Build",
             "miDebuggerPath": "/usr/bin/gdb"
+        },
+        {
+            "name": "Run proc_mem",
+            "type": "cppdbg",
+            "request": "launch",
+            "program": "${workspaceFolder}/build/examples/proc_mem/proc_mem",
+            "args": [
+                "2919",
+                "/usr/bin/bash"
+            ],
+            "stopAtEntry": false,
+            "cwd": "${workspaceFolder}",
+            "environment": [],
+            "externalConsole": false,
+            "MIMode": "gdb",
+            "setupCommands": [
+                {
+                    "description": "Enable pretty-printing for gdb",
+                    "text": "-enable-pretty-printing",
+                    "ignoreFailures": true
+                }
+            ],
+            "miDebuggerPath": "/usr/bin/gdb"
         }
     ]
 }
\ No newline at end of file
diff --git a/elfio/elfio.hpp b/elfio/elfio.hpp
index e84bd7f28c041074cae7da5d41d83d4762690f89..d983ea5d89af4295065e84959ce14e12cf83e1ca 100644
--- a/elfio/elfio.hpp
+++ b/elfio/elfio.hpp
@@ -124,6 +124,11 @@ class elfio
         create_mandatory_sections();
     }
 
+    void set_address_translation( std::vector<address_translation>& addr_trans )
+    {
+        addr_translator.set_address_translation( addr_trans );
+    }
+
     //------------------------------------------------------------------------------
     bool load( const std::string& file_name )
     {
@@ -143,6 +148,7 @@ class elfio
 
         unsigned char e_ident[EI_NIDENT];
         // Read ELF file signature
+        stream.seekg( addr_translator( 0 ) );
         stream.read( reinterpret_cast<char*>( &e_ident ), sizeof( e_ident ) );
 
         // Is it ELF file?
@@ -394,12 +400,12 @@ class elfio
         elf_header* new_header = nullptr;
 
         if ( file_class == ELFCLASS64 ) {
-            new_header =
-                new elf_header_impl<Elf64_Ehdr>( &convertor, encoding );
+            new_header = new elf_header_impl<Elf64_Ehdr>( &convertor, encoding,
+                                                          &addr_translator );
         }
         else if ( file_class == ELFCLASS32 ) {
-            new_header =
-                new elf_header_impl<Elf32_Ehdr>( &convertor, encoding );
+            new_header = new elf_header_impl<Elf32_Ehdr>( &convertor, encoding,
+                                                          &addr_translator );
         }
         else {
             return nullptr;
@@ -1023,6 +1029,7 @@ class elfio
     std::vector<section*> sections_;
     std::vector<segment*> segments_;
     endianess_convertor   convertor;
+    address_translator    addr_translator;
 
     Elf_Xword current_file_pos;
 };
diff --git a/elfio/elfio_header.hpp b/elfio/elfio_header.hpp
index 058b5ec5637fbb2106e43a211e9664ca63b166a7..fabca5a8cbfe00698760b965145ccd6fddd1c25c 100644
--- a/elfio/elfio_header.hpp
+++ b/elfio/elfio_header.hpp
@@ -75,9 +75,12 @@ template <class T> class elf_header_impl : public elf_header
 {
   public:
     //------------------------------------------------------------------------------
-    elf_header_impl( endianess_convertor* convertor, unsigned char encoding )
+    elf_header_impl( endianess_convertor*      convertor,
+                     unsigned char             encoding,
+                     const address_translator* translator )
     {
-        this->convertor = convertor;
+        this->convertor  = convertor;
+        this->translator = translator;
 
         std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ),
                      '\0' );
@@ -104,7 +107,7 @@ template <class T> class elf_header_impl : public elf_header
     //------------------------------------------------------------------------------
     bool load( std::istream& stream ) override
     {
-        stream.seekg( 0 );
+        stream.seekg( ( *translator )( 0 ) );
         stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
 
         return ( stream.gcount() == sizeof( header ) );
@@ -113,7 +116,7 @@ template <class T> class elf_header_impl : public elf_header
     //------------------------------------------------------------------------------
     bool save( std::ostream& stream ) const override
     {
-        stream.seekp( 0 );
+        stream.seekp( ( *translator )( 0 ) );
         stream.write( reinterpret_cast<const char*>( &header ),
                       sizeof( header ) );
 
@@ -145,8 +148,9 @@ template <class T> class elf_header_impl : public elf_header
     ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
 
   private:
-    T                    header;
-    endianess_convertor* convertor;
+    T                         header;
+    endianess_convertor*      convertor;
+    const address_translator* translator;
 };
 
 } // namespace ELFIO
diff --git a/elfio/elfio_utils.hpp b/elfio/elfio_utils.hpp
index 4b168546e31c01d6b88b2a804b1ddf342df9ae6e..bb7885873a1110050af66e7d4a6bca2d56686cb7 100644
--- a/elfio/elfio_utils.hpp
+++ b/elfio/elfio_utils.hpp
@@ -160,6 +160,48 @@ class endianess_convertor
     bool need_conversion;
 };
 
+//------------------------------------------------------------------------------
+struct address_translation
+{
+    address_translation( uint64_t start, uint64_t end, uint64_t map_to )
+        : start( start ), end( end ), map_to( map_to ){};
+    std::streampos start;
+    std::streampos end;
+    std::streampos map_to;
+};
+
+//------------------------------------------------------------------------------
+class address_translator
+{
+  public:
+    //------------------------------------------------------------------------------
+    void set_address_translation( std::vector<address_translation>& addr_trans )
+    {
+        translation = addr_trans;
+    }
+
+    //------------------------------------------------------------------------------
+    std::streampos operator()( std::streampos value ) const
+    {
+        if ( translation.empty() ) {
+            return value;
+        }
+
+        for ( auto& t : translation ) {
+            if ( t.map_to <= value &&
+                 ( ( value - t.map_to ) < ( t.end - t.start ) ) ) {
+                std::cout << std::hex << t.start - t.map_to + value << std::endl;
+                return t.start - t.map_to + value;
+            }
+        }
+
+        return value;
+    }
+
+  private:
+    std::vector<address_translation> translation;
+};
+
 //------------------------------------------------------------------------------
 inline uint32_t elf_hash( const unsigned char* name )
 {
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index ea12382864cfa7a67a8f45b72f025f1717544831..7433be39234967c87094c2939072705b0e4897ef 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(add_section)
 add_subdirectory(anonymizer)
 add_subdirectory(elfdump)
+add_subdirectory(proc_mem)
 add_subdirectory(tutorial)
 add_subdirectory(write_obj)
 add_subdirectory(writer)
diff --git a/examples/proc_mem/CMakeLists.txt b/examples/proc_mem/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3f8c1432a4b89817ac768e83f4ca7fec5e048185
--- /dev/null
+++ b/examples/proc_mem/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+add_executable(proc_mem proc_mem.cpp)
+target_link_libraries(proc_mem PRIVATE elfio::elfio)
diff --git a/examples/proc_mem/proc_mem.cpp b/examples/proc_mem/proc_mem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f35122cdeddf4396e5caf75af9b1a85d7edffab
--- /dev/null
+++ b/examples/proc_mem/proc_mem.cpp
@@ -0,0 +1,101 @@
+/*
+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.
+*/
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <regex>
+
+#include <elfio/elfio.hpp>
+#include <elfio/elfio_dump.hpp>
+
+using namespace ELFIO;
+
+void get_translation_ranges( std::ifstream&                    proc_maps,
+                             const std::string&                file_name,
+                             std::vector<address_translation>& result )
+{
+    result.clear();
+
+    const std::regex rexpr(
+        "([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r]...) ([0-9A-Fa-f]+) (.....) "
+        "([0-9]+)([[:blank:]]*)([[:graph:]]*)" );
+    std::smatch match;
+    while ( proc_maps ) {
+        std::string line;
+        std::getline( proc_maps, line );
+
+        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 ) ) );
+            }
+        }
+    }
+
+    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;
+        return 1;
+    }
+
+    // Process file translation regions for the ELF file from /proc/pid/maps
+    std::ifstream proc_maps( std::string( "/proc/" ) + argv[1] + "/maps" );
+    if ( !proc_maps ) {
+        std::cout << "Can't open "
+                  << std::string( "/proc/" ) + argv[1] + "/maps"
+                  << " file" << std::endl;
+        return 2;
+    }
+
+    std::vector<address_translation> 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;
+    // }
+
+    elfio elffile;
+    elffile.set_address_translation( ranges );
+
+    if ( elffile.load( std::string( "/proc/" ) + argv[1] + "/mem" ) ) {
+        dump::header( std::cout, elffile );
+        dump::section_headers( std::cout, elffile );
+        dump::segment_headers( std::cout, elffile );
+        dump::symbol_tables( std::cout, elffile );
+    }
+    else {
+        std::cout << "Can't open " << std::string( "/proc/" ) + argv[1] + "/mem"
+                  << " file" << std::endl;
+    }
+
+    return 0;
+}
diff --git a/tests/ELFIOTest2.cpp b/tests/ELFIOTest2.cpp
index 72cf726fa0f7bfc45de3ebfd3504bdd735530f5e..bfbfaf4ad72b0f076aafad4f3f2fc29d458788be 100644
--- a/tests/ELFIOTest2.cpp
+++ b/tests/ELFIOTest2.cpp
@@ -428,3 +428,30 @@ BOOST_AUTO_TEST_CASE( move_constructor_and_assignment )
     BOOST_CHECK_EQUAL( r2.sections[".text"]->get_name(), sec_name );
     BOOST_CHECK_EQUAL( r2.segments[1]->get_memory_size(), seg_size );
 }
+
+BOOST_AUTO_TEST_CASE( address_translation_test )
+{
+    std::vector<address_translation> ranges;
+
+    ranges.emplace_back( 500, 600, 0 );
+    ranges.emplace_back( 1000, 2000, 500 );
+    ranges.emplace_back( 3000, 4000, 2000 );
+
+    address_translator tr;
+    tr.set_address_translation( ranges );
+
+    BOOST_CHECK_EQUAL( tr( 0 ), 500 );
+    BOOST_CHECK_EQUAL( tr( 510 ), 1010 );
+    BOOST_CHECK_EQUAL( tr( 1710 ), 1710 );
+    BOOST_CHECK_EQUAL( tr( 2710 ), 3710 );
+    BOOST_CHECK_EQUAL( tr( 3710 ), 3710 );
+
+    ranges.clear();
+    tr.set_address_translation( ranges );
+
+    BOOST_CHECK_EQUAL( tr( 0 ), 0 );
+    BOOST_CHECK_EQUAL( tr( 510 ), 510 );
+    BOOST_CHECK_EQUAL( tr( 1710 ), 1710 );
+    BOOST_CHECK_EQUAL( tr( 2710 ), 2710 );
+    BOOST_CHECK_EQUAL( tr( 3710 ), 3710 );
+}