165042b18Sopenharmony_ci/*
265042b18Sopenharmony_ciCopyright (C) 2001-present by Serge Lamikhov-Center
365042b18Sopenharmony_ci
465042b18Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining a copy
565042b18Sopenharmony_ciof this software and associated documentation files (the "Software"), to deal
665042b18Sopenharmony_ciin the Software without restriction, including without limitation the rights
765042b18Sopenharmony_cito use, copy, modify, merge, publish, distribute, sublicense, and/or sell
865042b18Sopenharmony_cicopies of the Software, and to permit persons to whom the Software is
965042b18Sopenharmony_cifurnished to do so, subject to the following conditions:
1065042b18Sopenharmony_ci
1165042b18Sopenharmony_ciThe above copyright notice and this permission notice shall be included in
1265042b18Sopenharmony_ciall copies or substantial portions of the Software.
1365042b18Sopenharmony_ci
1465042b18Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1565042b18Sopenharmony_ciIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1665042b18Sopenharmony_ciFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1765042b18Sopenharmony_ciAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1865042b18Sopenharmony_ciLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1965042b18Sopenharmony_ciOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2065042b18Sopenharmony_ciTHE SOFTWARE.
2165042b18Sopenharmony_ci*/
2265042b18Sopenharmony_ci
2365042b18Sopenharmony_ci#include <iostream>
2465042b18Sopenharmony_ci#include <fstream>
2565042b18Sopenharmony_ci#include <sstream>
2665042b18Sopenharmony_ci#include <regex>
2765042b18Sopenharmony_ci
2865042b18Sopenharmony_ci#include <elfio/elfio.hpp>
2965042b18Sopenharmony_ci#include <elfio/elfio_dump.hpp>
3065042b18Sopenharmony_ci
3165042b18Sopenharmony_ciusing namespace ELFIO;
3265042b18Sopenharmony_ci
3365042b18Sopenharmony_ci//------------------------------------------------------------------------------
3465042b18Sopenharmony_civoid get_translation_ranges( std::ifstream&                    proc_maps,
3565042b18Sopenharmony_ci                             const std::string&                file_name,
3665042b18Sopenharmony_ci                             std::vector<address_translation>& result )
3765042b18Sopenharmony_ci{
3865042b18Sopenharmony_ci    result.clear();
3965042b18Sopenharmony_ci
4065042b18Sopenharmony_ci    const std::regex rexpr(
4165042b18Sopenharmony_ci        "([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r]...) ([0-9A-Fa-f]+) (.....) "
4265042b18Sopenharmony_ci        "([0-9]+)([[:blank:]]*)([[:graph:]]*)" );
4365042b18Sopenharmony_ci    std::smatch match;
4465042b18Sopenharmony_ci    while ( proc_maps ) {
4565042b18Sopenharmony_ci        std::string line;
4665042b18Sopenharmony_ci        std::getline( proc_maps, line );
4765042b18Sopenharmony_ci
4865042b18Sopenharmony_ci        if ( std::regex_match( line, match, rexpr ) ) {
4965042b18Sopenharmony_ci            if ( match.size() == 9 && match[8].str() == file_name ) {
5065042b18Sopenharmony_ci                unsigned long start  = std::stoul( match[1].str(), 0, 16 );
5165042b18Sopenharmony_ci                unsigned long end    = std::stoul( match[2].str(), 0, 16 );
5265042b18Sopenharmony_ci                unsigned long actual = std::stoul( match[4].str(), 0, 16 );
5365042b18Sopenharmony_ci                result.emplace_back( actual, end - start, start );
5465042b18Sopenharmony_ci            }
5565042b18Sopenharmony_ci        }
5665042b18Sopenharmony_ci    }
5765042b18Sopenharmony_ci}
5865042b18Sopenharmony_ci
5965042b18Sopenharmony_ci//------------------------------------------------------------------------------
6065042b18Sopenharmony_ciint main( int argc, char** argv )
6165042b18Sopenharmony_ci{
6265042b18Sopenharmony_ci    if ( argc != 3 ) {
6365042b18Sopenharmony_ci        std::cout << "Usage: proc_mem <pid> <full_file_path>" << std::endl;
6465042b18Sopenharmony_ci        return 1;
6565042b18Sopenharmony_ci    }
6665042b18Sopenharmony_ci
6765042b18Sopenharmony_ci    // Process file translation regions for the ELF file from /proc/pid/maps
6865042b18Sopenharmony_ci    std::ifstream proc_maps( std::string( "/proc/" ) + argv[1] + "/maps" );
6965042b18Sopenharmony_ci    if ( !proc_maps ) {
7065042b18Sopenharmony_ci        std::cout << "Can't open "
7165042b18Sopenharmony_ci                  << std::string( "/proc/" ) + argv[1] + "/maps"
7265042b18Sopenharmony_ci                  << " file" << std::endl;
7365042b18Sopenharmony_ci        return 2;
7465042b18Sopenharmony_ci    }
7565042b18Sopenharmony_ci
7665042b18Sopenharmony_ci    // Retrieve memory address translation ranges
7765042b18Sopenharmony_ci    std::vector<address_translation> ranges;
7865042b18Sopenharmony_ci    get_translation_ranges( proc_maps, argv[2], ranges );
7965042b18Sopenharmony_ci
8065042b18Sopenharmony_ci    // Set address translation ranges prior loading ELF file
8165042b18Sopenharmony_ci    elfio elffile;
8265042b18Sopenharmony_ci    elffile.set_address_translation( ranges );
8365042b18Sopenharmony_ci
8465042b18Sopenharmony_ci    // The 'load' will use the provided address translation now
8565042b18Sopenharmony_ci    if ( elffile.load( std::string( "/proc/" ) + argv[1] + "/mem", true ) ) {
8665042b18Sopenharmony_ci        dump::header( std::cout, elffile );
8765042b18Sopenharmony_ci        dump::segment_headers( std::cout, elffile );
8865042b18Sopenharmony_ci        dump::segment_datas( std::cout, elffile );
8965042b18Sopenharmony_ci    }
9065042b18Sopenharmony_ci    else {
9165042b18Sopenharmony_ci        std::cout << "Can't open " << std::string( "/proc/" ) + argv[1] + "/mem"
9265042b18Sopenharmony_ci                  << " file" << std::endl;
9365042b18Sopenharmony_ci    }
9465042b18Sopenharmony_ci
9565042b18Sopenharmony_ci    return 0;
9665042b18Sopenharmony_ci}
97