Header dump shows correct values

This commit is contained in:
Serge Lamikhov-Center 2021-09-18 00:39:28 +03:00
parent 24d29a213a
commit 0a15ec0aea
8 changed files with 218 additions and 10 deletions

23
.vscode/launch.json vendored
View File

@ -48,6 +48,29 @@
], ],
"preLaunchTask": "ELF Dump Build", "preLaunchTask": "ELF Dump Build",
"miDebuggerPath": "/usr/bin/gdb" "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"
} }
] ]
} }

View File

@ -124,6 +124,11 @@ class elfio
create_mandatory_sections(); 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 ) bool load( const std::string& file_name )
{ {
@ -143,6 +148,7 @@ class elfio
unsigned char e_ident[EI_NIDENT]; unsigned char e_ident[EI_NIDENT];
// Read ELF file signature // Read ELF file signature
stream.seekg( addr_translator( 0 ) );
stream.read( reinterpret_cast<char*>( &e_ident ), sizeof( e_ident ) ); stream.read( reinterpret_cast<char*>( &e_ident ), sizeof( e_ident ) );
// Is it ELF file? // Is it ELF file?
@ -394,12 +400,12 @@ class elfio
elf_header* new_header = nullptr; elf_header* new_header = nullptr;
if ( file_class == ELFCLASS64 ) { if ( file_class == ELFCLASS64 ) {
new_header = new_header = new elf_header_impl<Elf64_Ehdr>( &convertor, encoding,
new elf_header_impl<Elf64_Ehdr>( &convertor, encoding ); &addr_translator );
} }
else if ( file_class == ELFCLASS32 ) { else if ( file_class == ELFCLASS32 ) {
new_header = new_header = new elf_header_impl<Elf32_Ehdr>( &convertor, encoding,
new elf_header_impl<Elf32_Ehdr>( &convertor, encoding ); &addr_translator );
} }
else { else {
return nullptr; return nullptr;
@ -1023,6 +1029,7 @@ class elfio
std::vector<section*> sections_; std::vector<section*> sections_;
std::vector<segment*> segments_; std::vector<segment*> segments_;
endianess_convertor convertor; endianess_convertor convertor;
address_translator addr_translator;
Elf_Xword current_file_pos; Elf_Xword current_file_pos;
}; };

View File

@ -75,9 +75,12 @@ template <class T> class elf_header_impl : public elf_header
{ {
public: 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 ), std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ),
'\0' ); '\0' );
@ -104,7 +107,7 @@ template <class T> class elf_header_impl : public elf_header
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool load( std::istream& stream ) override bool load( std::istream& stream ) override
{ {
stream.seekg( 0 ); stream.seekg( ( *translator )( 0 ) );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) ); stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
return ( stream.gcount() == 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 bool save( std::ostream& stream ) const override
{ {
stream.seekp( 0 ); stream.seekp( ( *translator )( 0 ) );
stream.write( reinterpret_cast<const char*>( &header ), stream.write( reinterpret_cast<const char*>( &header ),
sizeof( 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 ); ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
private: private:
T header; T header;
endianess_convertor* convertor; endianess_convertor* convertor;
const address_translator* translator;
}; };
} // namespace ELFIO } // namespace ELFIO

View File

@ -160,6 +160,48 @@ class endianess_convertor
bool need_conversion; 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 ) inline uint32_t elf_hash( const unsigned char* name )
{ {

View File

@ -1,6 +1,7 @@
add_subdirectory(add_section) add_subdirectory(add_section)
add_subdirectory(anonymizer) add_subdirectory(anonymizer)
add_subdirectory(elfdump) add_subdirectory(elfdump)
add_subdirectory(proc_mem)
add_subdirectory(tutorial) add_subdirectory(tutorial)
add_subdirectory(write_obj) add_subdirectory(write_obj)
add_subdirectory(writer) add_subdirectory(writer)

View File

@ -0,0 +1,3 @@
add_executable(proc_mem proc_mem.cpp)
target_link_libraries(proc_mem PRIVATE elfio::elfio)

View File

@ -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;
}

View File

@ -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.sections[".text"]->get_name(), sec_name );
BOOST_CHECK_EQUAL( r2.segments[1]->get_memory_size(), seg_size ); 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 );
}