mirror of
https://github.com/serge1/ELFIO.git
synced 2024-12-26 09:14:29 +00:00
Header dump shows correct values
This commit is contained in:
parent
24d29a213a
commit
0a15ec0aea
23
.vscode/launch.json
vendored
23
.vscode/launch.json
vendored
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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)
|
||||
|
3
examples/proc_mem/CMakeLists.txt
Normal file
3
examples/proc_mem/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
add_executable(proc_mem proc_mem.cpp)
|
||||
target_link_libraries(proc_mem PRIVATE elfio::elfio)
|
101
examples/proc_mem/proc_mem.cpp
Normal file
101
examples/proc_mem/proc_mem.cpp
Normal 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;
|
||||
}
|
@ -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 );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user