Squashed 'external/ELFIO/' content from commit 94f7706

git-subtree-dir: external/ELFIO
git-subtree-split: 94f7706b5325b2ad9872e4481278278592cf86c9
This commit is contained in:
2026-05-11 11:41:03 +02:00
commit a67f311330
261 changed files with 21266 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
add_subdirectory(add_section)
add_subdirectory(anonymizer)
add_subdirectory(elfdump)
add_subdirectory(elfio_ldd)
add_subdirectory(proc_mem)
add_subdirectory(tutorial)
add_subdirectory(write_obj)
add_subdirectory(writer)
#add_subdirectory(c_wrapper)
add_subdirectory(arion)
add_subdirectory(arioso)
+3
View File
@@ -0,0 +1,3 @@
add_executable(add_section add_section.cpp)
target_link_libraries(add_section PRIVATE elfio::elfio)
+53
View File
@@ -0,0 +1,53 @@
/*
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 <elfio/elfio.hpp>
using namespace ELFIO;
int main( int argc, char** argv )
{
if ( argc != 2 ) {
std::cout << "Usage: add_section <elf_file>" << std::endl;
return 1;
}
// Create an elfio reader
elfio reader;
// Load ELF data
if ( !reader.load( argv[1] ) ) {
std::cout << "Can't find or process ELF file " << argv[1] << std::endl;
return 2;
}
// Create additional section at the end of the file
section* note_sec = reader.sections.add( ".note.ELFIO" );
note_sec->set_type( SHT_NOTE );
note_section_accessor note_writer( reader, note_sec );
note_writer.add_note( 0x01, "Created by ELFIO", "My data", 8 );
reader.save( "./result.elf" );
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(anonymizer anonymizer.cpp)
target_link_libraries(anonymizer PRIVATE elfio::elfio)
+102
View File
@@ -0,0 +1,102 @@
/*
anonymizer.cpp - Overwrites string table for a function name.
Copyright (C) 2017 by Martin Bickel
Copyright (C) 2020 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.
*/
/*
To run the example, you may use the following script:
#!/usr/bin/bash
make
cp anonymizer temp.elf
readelf -a temp.elf > before.txt
./anonymizer temp.elf
readelf -a temp.elf > after.txt
diff before.txt after.txt
*/
#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#define ELFIO_NO_INTTYPES
#endif
#include <string>
#include <iostream>
#include <fstream>
#include <elfio/elfio.hpp>
using namespace ELFIO;
void overwrite_data( const std::string& filename,
Elf64_Off offset,
const std::string& str )
{
std::ofstream file( filename,
std::ios::in | std::ios::out | std::ios::binary );
if ( !file )
throw "Error opening file" + filename;
std::string data( str.length(), '-' );
file.seekp( (std::streampos)offset );
file.write( data.c_str(), data.length() + 1 );
}
void process_string_table( const section* s, const std::string& filename )
{
std::cout << "Info: processing string table section" << std::endl;
size_t index = 1;
while ( index < s->get_size() ) {
auto str = std::string( s->get_data() + index );
// For the example purpose, we rename main function name only
if ( str == "main" )
overwrite_data( filename, s->get_offset() + index, str );
index += str.length() + 1;
}
}
int main( int argc, char** argv )
{
if ( argc != 2 ) {
std::cout << "Usage: anonymizer <file_name>\n";
return 1;
}
std::string filename = argv[1];
elfio reader;
if ( !reader.load( filename ) ) {
std::cerr << "File " << filename
<< " is not found or it is not an ELF file\n";
return 1;
}
for ( const auto& section : reader.sections ) {
if ( section->get_type() == SHT_STRTAB &&
std::string( section->get_name() ) == std::string( ".strtab" ) ) {
process_string_table( section.get(), filename );
}
}
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(arion arion.cpp)
target_link_libraries(arion PRIVATE ario::ario)
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright (C) 2025-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.
*/
//------------------------------------------------------------------------------
// arion.cpp
//
// This example demonstrates how to use the ARIO library to inspect and list the
// contents of a UNIX archive (.ar) file. It provides a simple command-line tool
// that displays information about each member of the archive, including its name,
// size, file mode, and any associated symbols.
//
// Purpose:
// - Showcase ARIOs API for reading and iterating over archive members.
// - Provide a minimal example for archive inspection and symbol listing.
//
// Abilities:
// - Loads and parses a specified archive file.
// - Lists all members with their names, sizes, and file modes.
// - Displays symbols associated with each member, if available.
// - Command-line interface: Accepts the archive file name as an argument.
//
// This example serves as a reference for basic ARIO usage and as a foundation
// for building custom archive inspection tools.
//------------------------------------------------------------------------------
#include <iostream>
#include <ario/ario.hpp>
using namespace ARIO;
int main( int argc, char** argv )
{
if ( argc != 2 ) {
std::cout << "Usage: arion <file_name>" << std::endl;
return 1;
}
ario archive;
const auto result = archive.load( argv[1] );
if ( !result.ok() ) {
std::cerr << "Error loading archive: " << result.what() << std::endl;
return 1;
}
for ( const auto& member : archive.members ) {
std::cout << "Member: " << std::setw( 40 ) << std::left << member.name
<< " Size: " << std::setw( 8 ) << std::right << member.size
<< " Mode: " << std::setw( 3 ) << std::oct << member.mode
<< std::dec << std::endl;
std::vector<std::string> symbols;
if ( archive.get_symbols_for_member( member, symbols ).ok() ) {
auto first_time = true;
for ( const auto& symbol : symbols ) {
if ( first_time ) {
std::cout << " ";
first_time = false;
}
else {
std::cout << ", ";
}
std::cout << symbol;
}
if ( !first_time ) {
std::cout << std::endl;
}
}
}
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(arioso arioso.cpp)
target_link_libraries(arioso PRIVATE ario::ario elfio::elfio)
+346
View File
@@ -0,0 +1,346 @@
/*
Copyright (C) 2025-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.
*/
//------------------------------------------------------------------------------
// arioso.cpp
//
// This example demonstrates how to use the ARIO library (with optional ELFIO integration)
// to manage UNIX archive (.ar) files from the command line. It provides a practical tool
// for extracting, deleting, and adding files to an archive, similar to the standard 'ar' utility.
//
// Purpose:
// - Showcase ARIOs API for reading, modifying, and writing UNIX archive files.
// - Illustrate integration with ELFIO for symbol extraction from ELF object files.
//
// Abilities:
// - Extraction: Extracts specified files from the archive to the current directory.
// - Deletion: Removes specified files from the archive.
// - Addition: Adds new files to the archive, collecting and storing global symbols if the file is an ELF object.
// - Archive update: Safely writes changes to the archive using a temporary file for atomic updates.
// - Command-line interface: Accepts commands in the form:
// arioso <archive> [-e <files...>] [-d <files...>] [-a <files...>]
//
// This example serves as both a reference for ARIO/ELFIO usage and a foundation for building custom archive management tools.
//
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <filesystem>
#include <ario/ario.hpp>
#include <elfio/elfio.hpp>
using namespace ARIO;
using namespace ELFIO;
//------------------------------------------------------------------------------
// Simple command line parser for:
// arioso -e <files...> -d <files...> -a <files...>
struct CommandLineOptions
{
std::string archive_name; ///< Name of the archive file
std::vector<std::string> extract_files; ///< List of files to extract
std::vector<std::string> delete_files; ///< List of files to delete
std::vector<std::string> add_files; ///< List of files to add
};
//------------------------------------------------------------------------------
static CommandLineOptions parse_args( int argc, char** argv )
{
if ( argc < 2 ) {
std::cerr
<< "Usage: " << argv[0]
<< " <archive> [-e <files...>] [-d <files...>] [-a <files...>]"
<< std::endl;
return {};
}
CommandLineOptions opts;
opts.archive_name = argv[1];
std::vector<std::string>* current = nullptr;
for ( int i = 2; i < argc; ++i ) {
std::string arg = argv[i];
if ( arg == "-e" ) {
current = &opts.extract_files;
}
else if ( arg == "-d" ) {
current = &opts.delete_files;
}
else if ( arg == "-a" ) {
current = &opts.add_files;
}
else if ( current ) {
current->emplace_back( arg );
}
else {
std::cerr << "Unknown argument or missing option: " << arg
<< std::endl;
}
}
return opts;
}
//------------------------------------------------------------------------------
// This function would contain the logic to extract the member data to a file
static ario::Result extract_member( const ario::Member& member )
{
std::cout << "Extracting member: " << member << ", Size: " << member.size
<< " bytes" << std::endl;
std::filesystem::path output_path =
std::filesystem::current_path() / member.name;
std::ofstream output_file( output_path, std::ios::binary );
if ( !output_file ) {
return { " Failed to create output file : " + output_path.string() };
}
output_file.write( member.data().c_str(), member.size );
if ( output_file.fail() ) {
return { "Failed to write member data to file: " +
output_path.string() };
}
return {}; // Return success
}
//------------------------------------------------------------------------------
// Extract all members from the command line extraction list.
// The search should be done by member's name. Exact match is expected
static int extract_members( const CommandLineOptions& opts,
const ARIO::ario& archive )
{
for ( const auto& file_name : opts.extract_files ) {
const auto& pmember = std::find( archive.members.begin(),
archive.members.end(), file_name );
if ( pmember != archive.members.end() ) {
auto result = extract_member( *pmember );
if ( !result.ok() ) {
std::cerr << "Error extracting member '" << file_name
<< "': " << result.what() << std::endl;
}
}
else {
std::cerr << "Member '" << file_name << "' not found in the library"
<< std::endl;
return 1;
}
}
return 0;
}
//------------------------------------------------------------------------------
// Copy members from the source archive to the target archive
static int copy_members( const CommandLineOptions& opts,
const ARIO::ario& archive,
ARIO::ario& target_archive )
{
for ( const auto& member : archive.members ) {
if ( std::find( opts.delete_files.begin(), opts.delete_files.end(),
member.name ) != opts.delete_files.end() ) {
std::cout << "Removing member: " << member << std::endl;
continue; // Skip this member
}
auto result = target_archive.add_member( member, member.data() );
if ( !result.ok() ) {
std::cerr << "Error adding member '" << member.name
<< "': " << result.what() << std::endl;
return 3;
}
// Copy member symbols
std::vector<std::string> symbols;
archive.get_symbols_for_member( member, symbols );
target_archive.add_symbols_for_member( target_archive.members.back(),
symbols );
}
return 0;
}
//------------------------------------------------------------------------------
// Collect global symbols from an ELF file
static void
collect_elf_global_symbols( const ELFIO::elfio& elf,
std::vector<std::string>& gathered_symbols )
{
for ( const auto& sec : elf.sections ) {
// Look for the symbol table section
if ( sec->get_type() == SHT_SYMTAB ) {
// Access the symbols in the symbol table
symbol_section_accessor symbols( elf, sec.get() );
std::string name;
Elf64_Addr value;
Elf_Xword size;
unsigned char bind = 0, type = 0;
Elf_Half section_index;
unsigned char other;
// Iterate over all sections in the ELF file and gather all symbols
// that are functions or objects, and have global binding
for ( Elf_Xword i = 0; i < symbols.get_symbols_num(); ++i ) {
// Extract symbol properties
symbols.get_symbol( i, name, value, size, bind, type,
section_index, other );
// For each global function or object symbol, check that the archive symbol table can find it
if ( ( type == STT_FUNC || type == STT_OBJECT ||
type == STT_TLS || type == STT_COMMON ) &&
bind == STB_GLOBAL ) {
gathered_symbols.emplace_back( name );
}
}
}
}
}
//------------------------------------------------------------------------------
// Add a new member to the archive
static ario::Result add_new_member( ario& archive,
const std::string_view& file_name )
{
std::filesystem::path full_file_path = file_name;
if ( !std::filesystem::exists( full_file_path ) ) {
return { "File does not exist: " + full_file_path.string() };
}
ario::Member new_member;
new_member.name = full_file_path.filename().string();
new_member.uid = 0;
new_member.gid = 0;
new_member.mode = 0644;
std::ifstream input( full_file_path, std::ios::binary );
if ( !input ) {
return { "Failed to open file: " + full_file_path.string() };
}
const std::string data( ( std::istreambuf_iterator<char>( input ) ),
std::istreambuf_iterator<char>() );
const auto result = archive.add_member( new_member, data );
if ( !result.ok() ) {
return result;
}
elfio elf;
if ( elf.load( full_file_path.string() ) ) {
std::vector<std::string> gathered_symbols;
collect_elf_global_symbols( elf, gathered_symbols );
archive.add_symbols_for_member( archive.members.back(),
gathered_symbols );
}
return {}; // Return success
}
//------------------------------------------------------------------------------
// Add members from the command line addition list
static int add_new_members( const CommandLineOptions& opts,
ARIO::ario& target_archive )
{
for ( const auto& file_name : opts.add_files ) {
std::cout << "Adding member: " << file_name << std::endl;
auto result = add_new_member( target_archive, file_name );
if ( !result.ok() ) {
std::cerr << "Error adding member '" << file_name
<< "': " << result.what() << std::endl;
return 3;
}
}
return 0;
}
//------------------------------------------------------------------------------
// Save the new archive to a file
static int save_new_archive( ARIO::ario& target_archive,
const std::string& archive_name )
{
// Create a temporary filename for the archive
auto temp_dir = std::filesystem::temp_directory_path();
std::string temp_filename;
do {
// Generate a random filename
temp_filename = "ario_tmp_" + std::to_string( std::rand() ) + ".ar";
} while ( std::filesystem::exists( temp_dir / temp_filename ) );
std::filesystem::path temp_path = temp_dir / temp_filename;
target_archive.save( temp_path.string() );
// Move temporary file to the original one
std::error_code ec;
std::filesystem::rename( temp_path, archive_name, ec );
if ( ec ) {
std::cerr << "Error renaming temporary file: " << ec.message()
<< std::endl;
return 4;
}
return 0;
}
//------------------------------------------------------------------------------
int main( int argc, char** argv )
{
auto opts = parse_args( argc, argv );
// Open existing library or create a new one. In the last case, the library will be empty.
ario archive;
const auto result = archive.load( opts.archive_name );
if ( !result.ok() ) {
std::cerr << "Error loading archive: " << result.what() << std::endl;
return 1;
}
// Extract members from the archive
int retVal = extract_members( opts, archive );
if ( retVal != 0 )
return retVal;
// Check if there are no files to delete or add
if ( opts.delete_files.empty() && opts.add_files.empty() ) {
// No files to delete or add. Exiting
return 0;
}
// Create a new (empty) target archive
ario target_archive;
// Copy members not included to the command line deletion list
retVal = copy_members( opts, archive, target_archive );
if ( retVal != 0 )
return retVal;
// Add new members from the command line addition list
retVal = add_new_members( opts, target_archive );
if ( retVal != 0 )
return retVal;
// Save the new archive
retVal = save_new_archive( target_archive, opts.archive_name );
if ( retVal != 0 )
return retVal;
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(c_example c_example.c elfio_c_wrapper.cpp elfio_c_wrapper.h)
target_link_libraries(c_example PRIVATE elfio::elfio)
+198
View File
@@ -0,0 +1,198 @@
/*
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 <stdio.h>
#include <string.h>
#include <elfio/elf_types.hpp>
#include "elfio_c_wrapper.h"
int main( int argc, char* argv[] )
{
pelfio_t pelfio = elfio_new();
bool ret;
if ( argc == 1 )
ret = elfio_load( pelfio, argv[0] );
else
ret = elfio_load( pelfio, argv[1] );
if ( !ret ) {
printf( "Can't load ELF file\n" );
return 1;
}
char msg[128];
ret = elfio_validate( pelfio, msg, 128 );
if ( !ret ) {
printf( "Validation errors:\n" );
printf( "%s\n", msg );
return 2;
}
//-----------------------------------------------------------------------------
// elfio
//-----------------------------------------------------------------------------
printf( "Header size : %d\n", elfio_get_header_size( pelfio ) );
printf( "Version : %d\n", elfio_get_version( pelfio ) );
printf( "Section Entry : %d\n", elfio_get_section_entry_size( pelfio ) );
printf( "Segment Entry : %d\n", elfio_get_segment_entry_size( pelfio ) );
/* Uncomment a printf block of the interest */
//-----------------------------------------------------------------------------
// section
//-----------------------------------------------------------------------------
int secno = elfio_get_sections_num( pelfio );
printf( "Sections No : %d\n", secno );
for ( int i = 0; i < secno; i++ ) {
psection_t psection = elfio_get_section_by_index( pelfio, i );
char buff[128];
elfio_section_get_name( psection, buff, 100 );
// printf( " [%02d] %s\n", i, buff );
// printf( " %08lx : %08lx\n",
// elfio_section_get_address( psection ),
// elfio_section_get_size( psection ) );
}
//-----------------------------------------------------------------------------
// segment
//-----------------------------------------------------------------------------
int segno = elfio_get_segments_num( pelfio );
printf( "Segments No : %d\n", segno );
for ( int i = 0; i < segno; i++ ) {
psegment_t psegment = elfio_get_segment_by_index( pelfio, i );
elfio_segment_get_file_size( psegment );
// printf( " [%02d] %08lx : %08lx : %08lx\n", i,
// elfio_segment_get_virtual_address( psegment ),
// elfio_segment_get_memory_size( psegment ),
// elfio_segment_get_file_size( psegment ) );
}
//-----------------------------------------------------------------------------
// symbol
//-----------------------------------------------------------------------------
psection_t psection = elfio_get_section_by_name( pelfio, ".symtab" );
psymbol_t psymbols = elfio_symbol_section_accessor_new( pelfio, psection );
Elf_Xword symno = elfio_symbol_get_symbols_num( psymbols );
for ( int i = 0; i < symno; i++ ) {
char name[128];
Elf64_Addr value;
Elf_Xword size;
unsigned char bind;
unsigned char type;
Elf_Half section_index;
unsigned char other;
elfio_symbol_get_symbol( psymbols, i, name, 128, &value, &size, &bind,
&type, &section_index, &other );
// printf( "[%4d] %10lu, %4lu %s\n", i, value, size, name );
}
elfio_symbol_section_accessor_delete( psymbols );
//-----------------------------------------------------------------------------
// relocation
//-----------------------------------------------------------------------------
psection = elfio_get_section_by_name( pelfio, ".rela.dyn" );
prelocation_t preloc =
elfio_relocation_section_accessor_new( pelfio, psection );
Elf_Xword relno = elfio_relocation_get_entries_num( preloc );
for ( int i = 0; i < relno; i++ ) {
Elf64_Addr offset;
Elf_Word symbol;
Elf_Word type;
Elf_Sxword addend;
elfio_relocation_get_entry( preloc, i, &offset, &symbol, &type,
&addend );
// printf( "[%4d] %16lx, %08x %08x %16lx\n", i, offset, symbol, type, addend );
}
elfio_relocation_section_accessor_delete( preloc );
//-----------------------------------------------------------------------------
// string
//-----------------------------------------------------------------------------
psection = elfio_get_section_by_name( pelfio, ".strtab" );
pstring_t pstring = elfio_string_section_accessor_new( psection );
Elf_Word pos = 0;
const char* str = elfio_string_get_string( pstring, pos );
while ( str ) {
pos += (Elf_Word)strlen( str ) + 1;
str = elfio_string_get_string( pstring, pos );
// printf( "%s\n", str );
}
elfio_string_section_accessor_delete( pstring );
//-----------------------------------------------------------------------------
// note
//-----------------------------------------------------------------------------
psection = elfio_get_section_by_name( pelfio, ".note.gnu.build-id" );
pnote_t pnote = elfio_note_section_accessor_new( pelfio, psection );
int noteno = elfio_note_get_notes_num( pnote );
for ( int i = 0; i < noteno; i++ ) {
Elf_Word type;
char name[128];
int name_len = 128;
char* desc;
Elf_Word descSize = 128;
elfio_note_get_note( pnote, i, &type, name, name_len, (void**)&desc,
&descSize );
// printf( "[%4d] %s %08x\n", i, name, descSize );
}
elfio_note_section_accessor_delete( pnote );
//-----------------------------------------------------------------------------
// dynamic
//-----------------------------------------------------------------------------
psection = elfio_get_section_by_name( pelfio, ".dynamic" );
pdynamic_t pdynamic =
elfio_dynamic_section_accessor_new( pelfio, psection );
Elf_Xword dynno = elfio_dynamic_get_entries_num( pdynamic );
for ( int i = 0; i < dynno; i++ ) {
Elf_Xword tag;
Elf_Xword value;
char str[128];
elfio_dynamic_get_entry( pdynamic, i, &tag, &value, str, 128 );
// printf( "[%4d] %16lx %16lx %s\n", i, tag, value, str );
}
elfio_dynamic_section_accessor_delete( pdynamic );
//-----------------------------------------------------------------------------
// array
//-----------------------------------------------------------------------------
psection = elfio_get_section_by_name( pelfio, ".init_array" );
if ( psection != 0 ) {
parray_t parray = elfio_array_section_accessor_new( pelfio, psection );
Elf_Xword arrno = elfio_array_get_entries_num( parray );
for ( int i = 0; i < arrno; i++ ) {
Elf64_Addr addr;
elfio_array_get_entry( parray, i, &addr );
// printf( "[%4d] %16lx\n", i, addr );
}
elfio_array_section_accessor_delete( parray );
}
elfio_delete( pelfio );
return 0;
}
+500
View File
@@ -0,0 +1,500 @@
/*
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.
*/
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <elfio/elfio.hpp>
#include <cstring>
using namespace ELFIO;
#include "elfio_c_wrapper.h"
//-----------------------------------------------------------------------------
// elfio
//-----------------------------------------------------------------------------
pelfio_t elfio_new() { return new ( std::nothrow ) elfio; }
void elfio_delete( pelfio_t pelfio ) { delete (elfio*)pelfio; }
void elfio_create( pelfio_t pelfio,
unsigned char file_class,
unsigned char encoding )
{
pelfio->create( file_class, encoding );
}
bool elfio_load( pelfio_t pelfio, const char* file_name )
{
return pelfio->load( file_name );
}
bool elfio_save( pelfio_t pelfio, const char* file_name )
{
return pelfio->save( file_name );
}
ELFIO_C_HEADER_ACCESS_GET_IMPL( unsigned char, class );
ELFIO_C_HEADER_ACCESS_GET_IMPL( unsigned char, elf_version );
ELFIO_C_HEADER_ACCESS_GET_IMPL( unsigned char, encoding );
ELFIO_C_HEADER_ACCESS_GET_IMPL( Elf_Word, version );
ELFIO_C_HEADER_ACCESS_GET_IMPL( Elf_Half, header_size );
ELFIO_C_HEADER_ACCESS_GET_IMPL( Elf_Half, section_entry_size );
ELFIO_C_HEADER_ACCESS_GET_IMPL( Elf_Half, segment_entry_size );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( unsigned char, os_abi );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( unsigned char, abi_version );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( Elf_Half, type );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( Elf_Half, machine );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( Elf_Word, flags );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( Elf64_Addr, entry );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( Elf64_Off, sections_offset );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( Elf64_Off, segments_offset );
ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( Elf_Half, section_name_str_index );
Elf_Half elfio_get_sections_num( pelfio_t pelfio )
{
return pelfio->sections.size();
}
psection_t elfio_get_section_by_index( pelfio_t pelfio, int index )
{
return pelfio->sections[index];
}
psection_t elfio_get_section_by_name( pelfio_t pelfio, char* name )
{
return pelfio->sections[name];
}
psection_t elfio_add_section( pelfio_t pelfio, char* name )
{
return pelfio->sections.add( name );
}
Elf_Half elfio_get_segments_num( pelfio_t pelfio )
{
return pelfio->segments.size();
}
psegment_t elfio_get_segment_by_index( pelfio_t pelfio, int index )
{
return pelfio->segments[index];
}
psegment_t elfio_add_segment( pelfio_t pelfio )
{
return pelfio->segments.add();
}
bool elfio_validate( pelfio_t pelfio, char* msg, int msg_len )
{
std::string error = pelfio->validate();
if ( msg != nullptr && msg_len > 0 ) {
strncpy( msg, error.c_str(), (size_t)msg_len - 1 );
}
return error.empty();
}
//-----------------------------------------------------------------------------
// section
//-----------------------------------------------------------------------------
ELFIO_C_GET_ACCESS_IMPL( section, Elf_Half, index );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Word, type );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Xword, flags );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Word, info );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Word, link );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Xword, addr_align );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Xword, entry_size );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf64_Addr, address );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Xword, size );
ELFIO_C_GET_SET_ACCESS_IMPL( section, Elf_Word, name_string_offset );
ELFIO_C_GET_ACCESS_IMPL( section, Elf64_Off, offset );
void elfio_section_get_name( psection_t psection, char* buffer, int len )
{
strncpy( buffer, psection->get_name().c_str(), (size_t)len - 1 );
}
void elfio_section_set_name( psection_t psection, char* buffer )
{
psection->set_name( buffer );
}
char* elfio_section_get_data( psection_t psection )
{
return (char*)psection->get_data();
}
void elfio_section_set_data( psection_t psection,
const char* pData,
Elf_Word size )
{
psection->set_data( pData, size );
}
void elfio_section_append_data( psection_t psection,
const char* pData,
Elf_Word size )
{
psection->append_data( pData, size );
}
//-----------------------------------------------------------------------------
// segment
//-----------------------------------------------------------------------------
ELFIO_C_GET_ACCESS_IMPL( segment, Elf_Half, index );
ELFIO_C_GET_SET_ACCESS_IMPL( segment, Elf_Word, type );
ELFIO_C_GET_SET_ACCESS_IMPL( segment, Elf_Word, flags );
ELFIO_C_GET_SET_ACCESS_IMPL( segment, Elf_Xword, align );
ELFIO_C_GET_SET_ACCESS_IMPL( segment, Elf_Xword, memory_size );
ELFIO_C_GET_SET_ACCESS_IMPL( segment, Elf64_Addr, virtual_address );
ELFIO_C_GET_SET_ACCESS_IMPL( segment, Elf64_Addr, physical_address );
ELFIO_C_GET_SET_ACCESS_IMPL( segment, Elf_Xword, file_size );
ELFIO_C_GET_ACCESS_IMPL( segment, Elf64_Off, offset );
char* elfio_segment_get_data( psegment_t psegment )
{
return (char*)psegment->get_data();
}
Elf_Half elfio_segment_add_section_index( psegment_t psegment,
Elf_Half index,
Elf_Xword addr_align )
{
return psegment->add_section_index( index, addr_align );
}
Elf_Half elfio_segment_get_sections_num( psegment_t psegment )
{
return psegment->get_sections_num();
}
Elf_Half elfio_segment_get_section_index_at( psegment_t psegment, Elf_Half num )
{
return psegment->get_section_index_at( num );
}
bool elfio_segment_is_offset_initialized( psegment_t psegment )
{
return psegment->is_offset_initialized();
}
//-----------------------------------------------------------------------------
// symbol
//-----------------------------------------------------------------------------
psymbol_t elfio_symbol_section_accessor_new( pelfio_t pelfio,
psection_t psection )
{
return new ( std::nothrow ) symbol_section_accessor( *pelfio, psection );
}
void elfio_symbol_section_accessor_delete( psymbol_t psymbol )
{
delete psymbol;
}
Elf_Xword elfio_symbol_get_symbols_num( psymbol_t psymbol )
{
return psymbol->get_symbols_num();
}
bool elfio_symbol_get_symbol( psymbol_t psymbol,
Elf_Xword index,
char* name,
int name_len,
Elf64_Addr* value,
Elf_Xword* size,
unsigned char* bind,
unsigned char* type,
Elf_Half* section_index,
unsigned char* other )
{
std::string name_param;
bool ret = psymbol->get_symbol( index, name_param, *value, *size, *bind,
*type, *section_index, *other );
strncpy( name, name_param.c_str(), (size_t)name_len - 1 );
return ret;
}
Elf_Word elfio_symbol_add_symbol( psymbol_t psymbol,
Elf_Word name,
Elf64_Addr value,
Elf_Xword size,
unsigned char info,
unsigned char other,
Elf_Half shndx )
{
return psymbol->add_symbol( name, value, size, info, other, shndx );
}
Elf_Xword elfio_symbol_arrange_local_symbols(
psymbol_t psymbol, void ( *func )( Elf_Xword first, Elf_Xword second ) )
{
return psymbol->arrange_local_symbols( func );
}
//-----------------------------------------------------------------------------
// relocation
//-----------------------------------------------------------------------------
prelocation_t elfio_relocation_section_accessor_new( pelfio_t pelfio,
psection_t psection )
{
return new ( std::nothrow )
relocation_section_accessor( *pelfio, psection );
}
void elfio_relocation_section_accessor_delete( prelocation_t prelocation )
{
delete prelocation;
}
Elf_Xword elfio_relocation_get_entries_num( prelocation_t prelocation )
{
return prelocation->get_entries_num();
}
bool elfio_relocation_get_entry( prelocation_t prelocation,
Elf_Xword index,
Elf64_Addr* offset,
Elf_Word* symbol,
Elf_Word* type,
Elf_Sxword* addend )
{
return prelocation->get_entry( index, *offset, *symbol, *type, *addend );
}
bool elfio_relocation_set_entry( prelocation_t prelocation,
Elf_Xword index,
Elf64_Addr offset,
Elf_Word symbol,
Elf_Word type,
Elf_Sxword addend )
{
return prelocation->set_entry( index, offset, symbol, type, addend );
}
void elfio_relocation_add_entry( prelocation_t prelocation,
Elf64_Addr offset,
Elf_Word symbol,
unsigned char type,
Elf_Sxword addend )
{
return prelocation->add_entry( offset, symbol, type, addend );
}
void elfio_relocation_swap_symbols( prelocation_t prelocation,
Elf_Xword first,
Elf_Xword second )
{
prelocation->swap_symbols( first, second );
}
//-----------------------------------------------------------------------------
// string
//-----------------------------------------------------------------------------
pstring_t elfio_string_section_accessor_new( psection_t psection )
{
return new ( std::nothrow ) string_section_accessor( psection );
}
void elfio_string_section_accessor_delete( pstring_t pstring )
{
delete pstring;
}
const char* elfio_string_get_string( pstring_t pstring, Elf_Word index )
{
return pstring->get_string( index );
}
Elf_Word elfio_string_add_string( pstring_t pstring, char* str )
{
return pstring->add_string( str );
}
//-----------------------------------------------------------------------------
// note
//-----------------------------------------------------------------------------
pnote_t elfio_note_section_accessor_new( pelfio_t pelfio, psection_t psection )
{
return new ( std::nothrow ) note_section_accessor( *pelfio, psection );
}
void elfio_note_section_accessor_delete( pnote_t pnote ) { delete pnote; }
Elf_Word elfio_note_get_notes_num( pnote_t pnote )
{
return pnote->get_notes_num();
}
bool elfio_note_get_note( pnote_t pnote,
Elf_Word index,
Elf_Word* type,
char* name,
int name_len,
void** desc,
Elf_Word* descSize )
{
std::string name_str;
bool ret = pnote->get_note( index, *type, name_str, *desc, *descSize );
strncpy( name, name_str.c_str(), (size_t)name_len - 1 );
return ret;
}
void elfio_note_add_note( pnote_t pnote,
Elf_Word type,
const char* name,
const void* desc,
Elf_Word descSize )
{
pnote->add_note( type, name, desc, descSize );
}
//-----------------------------------------------------------------------------
// modinfo
//-----------------------------------------------------------------------------
pmodinfo_t elfio_modinfo_section_accessor_new( psection_t psection )
{
return new ( std::nothrow ) modinfo_section_accessor( psection );
}
void elfio_modinfo_section_accessor_delete( pmodinfo_t pmodinfo )
{
delete pmodinfo;
}
Elf_Word elfio_modinfo_get_attribute_num( pmodinfo_t pmodinfo )
{
return pmodinfo->get_attribute_num();
}
bool elfio_modinfo_get_attribute( pmodinfo_t pmodinfo,
Elf_Word no,
char* field,
int field_len,
char* value,
int value_len )
{
std::string field_str;
std::string value_str;
bool ret = pmodinfo->get_attribute( no, field_str, value_str );
strncpy( field, field_str.c_str(), (size_t)field_len - 1 );
strncpy( value, value_str.c_str(), (size_t)value_len - 1 );
return ret;
}
bool elfio_modinfo_get_attribute_by_name( pmodinfo_t pmodinfo,
char* field_name,
char* value,
int value_len )
{
std::string value_str;
bool ret = pmodinfo->get_attribute( value_str, value_str );
strncpy( value, value_str.c_str(), (size_t)value_len - 1 );
return ret;
}
Elf_Word
elfio_modinfo_add_attribute( pmodinfo_t pmodinfo, char* field, char* value )
{
return pmodinfo->add_attribute( field, value );
}
//-----------------------------------------------------------------------------
// dynamic
//-----------------------------------------------------------------------------
pdynamic_t elfio_dynamic_section_accessor_new( pelfio_t pelfio,
psection_t psection )
{
return new ( std::nothrow ) dynamic_section_accessor( *pelfio, psection );
}
void elfio_dynamic_section_accessor_delete( pdynamic_t pdynamic )
{
delete pdynamic;
}
Elf_Xword elfio_dynamic_get_entries_num( pdynamic_t pdynamic )
{
return pdynamic->get_entries_num();
}
bool elfio_dynamic_get_entry( pdynamic_t pdynamic,
Elf_Xword index,
Elf_Xword* tag,
Elf_Xword* value,
char* str,
int str_len )
{
std::string str_str;
bool ret = pdynamic->get_entry( index, *tag, *value, str_str );
strncpy( str, str_str.c_str(), (size_t)str_len - 1 );
return ret;
}
void elfio_dynamic_add_entry( pdynamic_t pdynamic,
Elf_Xword tag,
Elf_Xword value )
{
pdynamic->add_entry( tag, value );
}
//-----------------------------------------------------------------------------
// array
//-----------------------------------------------------------------------------
parray_t elfio_array_section_accessor_new( pelfio_t pelfio,
psection_t psection )
{
return new ( std::nothrow )
array_section_accessor<Elf64_Word>( *pelfio, psection );
}
void elfio_array_section_accessor_delete( parray_t parray ) { delete parray; }
Elf_Xword elfio_array_get_entries_num( parray_t parray )
{
return parray->get_entries_num();
}
bool elfio_array_get_entry( parray_t parray,
Elf_Xword index,
Elf64_Addr* paddress )
{
bool ret = parray->get_entry( index, *paddress );
return ret;
}
void elfio_array_add_entry( parray_t parray, Elf64_Addr address )
{
parray->add_entry( address );
}
+323
View File
@@ -0,0 +1,323 @@
/*
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.
*/
#ifndef ELFIO_C_WRAPPER_H
#define ELFIO_C_WRAPPER_H
#define ELFIO_C_HEADER_ACCESS_GET( TYPE, FNAME ) \
TYPE elfio_get_##FNAME( pelfio_t pelfio );
#define ELFIO_C_HEADER_ACCESS_GET_SET( TYPE, FNAME ) \
TYPE elfio_get_##FNAME( pelfio_t pelfio ); \
void elfio_set_##FNAME( pelfio_t pelfio, TYPE val );
#define ELFIO_C_HEADER_ACCESS_GET_IMPL( TYPE, FNAME ) \
TYPE elfio_get_##FNAME( pelfio_t pelfio ) { return pelfio->get_##FNAME(); }
#define ELFIO_C_HEADER_ACCESS_GET_SET_IMPL( TYPE, FNAME ) \
TYPE elfio_get_##FNAME( pelfio_t pelfio ) \
{ \
return pelfio->get_##FNAME(); \
} \
void elfio_set_##FNAME( pelfio_t pelfio, TYPE val ) \
{ \
pelfio->set_##FNAME( val ); \
}
#define ELFIO_C_GET_ACCESS_IMPL( CLASS, TYPE, NAME ) \
TYPE elfio_##CLASS##_get_##NAME( p##CLASS##_t p##CLASS ) \
{ \
return p##CLASS->get_##NAME(); \
}
#define ELFIO_C_SET_ACCESS_IMPL( CLASS, TYPE, NAME ) \
void elfio_##CLASS##_set_##NAME( p##CLASS##_t p##CLASS, TYPE value ) \
{ \
p##CLASS->set_##NAME( value ); \
}
#define ELFIO_C_GET_SET_ACCESS_IMPL( CLASS, TYPE, NAME ) \
TYPE elfio_##CLASS##_get_##NAME( p##CLASS##_t p##CLASS ) \
{ \
return p##CLASS->get_##NAME(); \
} \
void elfio_##CLASS##_set_##NAME( p##CLASS##_t p##CLASS, TYPE value ) \
{ \
p##CLASS->set_##NAME( value ); \
}
#define ELFIO_C_GET_ACCESS( CLASS, TYPE, NAME ) \
TYPE elfio_##CLASS##_get_##NAME( p##CLASS##_t p##CLASS );
#define ELFIO_C_SET_ACCESS( CLASS, TYPE, NAME ) \
void elfio_##CLASS##_set_##NAME( p##CLASS##_t p##CLASS, TYPE value );
#define ELFIO_C_GET_SET_ACCESS( CLASS, TYPE, NAME ) \
TYPE elfio_##CLASS##_get_##NAME( p##CLASS##_t p##CLASS ); \
void elfio_##CLASS##_set_##NAME( p##CLASS##_t p##CLASS, TYPE value )
#ifdef __cplusplus
typedef ELFIO::elfio* pelfio_t;
typedef ELFIO::section* psection_t;
typedef ELFIO::segment* psegment_t;
typedef ELFIO::symbol_section_accessor* psymbol_t;
typedef ELFIO::relocation_section_accessor* prelocation_t;
typedef ELFIO::string_section_accessor* pstring_t;
typedef ELFIO::note_section_accessor* pnote_t;
typedef ELFIO::modinfo_section_accessor* pmodinfo_t;
typedef ELFIO::dynamic_section_accessor* pdynamic_t;
typedef ELFIO::array_section_accessor<Elf64_Word>* parray_t;
extern "C"
{
#else
typedef void* pelfio_t;
typedef void* psection_t;
typedef void* psegment_t;
typedef void* psymbol_t;
typedef void* prelocation_t;
typedef void* pstring_t;
typedef void* pnote_t;
typedef void* pmodinfo_t;
typedef void* pdynamic_t;
typedef void* parray_t;
typedef int bool;
#endif
//-----------------------------------------------------------------------------
// elfio
//-----------------------------------------------------------------------------
pelfio_t elfio_new();
void elfio_delete( pelfio_t pelfio );
void elfio_create( pelfio_t pelfio,
unsigned char file_class,
unsigned char encoding );
bool elfio_load( pelfio_t pelfio, const char* file_name );
bool elfio_save( pelfio_t pelfio, const char* file_name );
ELFIO_C_HEADER_ACCESS_GET( unsigned char, class );
ELFIO_C_HEADER_ACCESS_GET( unsigned char, elf_version );
ELFIO_C_HEADER_ACCESS_GET( unsigned char, encoding );
ELFIO_C_HEADER_ACCESS_GET( Elf_Word, version );
ELFIO_C_HEADER_ACCESS_GET( Elf_Half, header_size );
ELFIO_C_HEADER_ACCESS_GET( Elf_Half, section_entry_size );
ELFIO_C_HEADER_ACCESS_GET( Elf_Half, segment_entry_size );
ELFIO_C_HEADER_ACCESS_GET_SET( unsigned char, os_abi );
ELFIO_C_HEADER_ACCESS_GET_SET( unsigned char, abi_version );
ELFIO_C_HEADER_ACCESS_GET_SET( Elf_Half, type );
ELFIO_C_HEADER_ACCESS_GET_SET( Elf_Half, machine );
ELFIO_C_HEADER_ACCESS_GET_SET( Elf_Word, flags );
ELFIO_C_HEADER_ACCESS_GET_SET( Elf64_Addr, entry );
ELFIO_C_HEADER_ACCESS_GET_SET( Elf64_Off, sections_offset );
ELFIO_C_HEADER_ACCESS_GET_SET( Elf64_Off, segments_offset );
ELFIO_C_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index );
Elf_Half elfio_get_sections_num( pelfio_t pelfio );
psection_t elfio_get_section_by_index( pelfio_t pelfio, int index );
psection_t elfio_get_section_by_name( pelfio_t pelfio, char* name );
psection_t elfio_add_section( pelfio_t pelfio, char* name );
Elf_Half elfio_get_segments_num( pelfio_t pelfio );
psegment_t elfio_get_segment_by_index( pelfio_t pelfio, int index );
psegment_t elfio_add_segment( pelfio_t pelfio );
bool elfio_validate( pelfio_t pelfio, char* msg, int msg_len );
//-----------------------------------------------------------------------------
// section
//-----------------------------------------------------------------------------
ELFIO_C_GET_ACCESS( section, Elf_Half, index );
ELFIO_C_GET_SET_ACCESS( section, Elf_Word, type );
ELFIO_C_GET_SET_ACCESS( section, Elf_Xword, flags );
ELFIO_C_GET_SET_ACCESS( section, Elf_Word, info );
ELFIO_C_GET_SET_ACCESS( section, Elf_Word, link );
ELFIO_C_GET_SET_ACCESS( section, Elf_Xword, addr_align );
ELFIO_C_GET_SET_ACCESS( section, Elf_Xword, entry_size );
ELFIO_C_GET_SET_ACCESS( section, Elf64_Addr, address );
ELFIO_C_GET_SET_ACCESS( section, Elf_Xword, size );
ELFIO_C_GET_SET_ACCESS( section, Elf_Word, name_string_offset );
ELFIO_C_GET_ACCESS( section, Elf64_Off, offset );
void elfio_section_get_name( psection_t psection, char* buffer, int len );
void elfio_section_set_name( psection_t psection, char* buffer );
char* elfio_section_get_data( psection_t psection );
void elfio_section_set_data( psection_t psection,
const char* pData,
Elf_Word size );
void elfio_section_append_data( psection_t psection,
const char* pData,
Elf_Word size );
//-----------------------------------------------------------------------------
// segment
//-----------------------------------------------------------------------------
ELFIO_C_GET_ACCESS( segment, Elf_Half, index );
ELFIO_C_GET_SET_ACCESS( segment, Elf_Word, type );
ELFIO_C_GET_SET_ACCESS( segment, Elf_Word, flags );
ELFIO_C_GET_SET_ACCESS( segment, Elf_Xword, align );
ELFIO_C_GET_SET_ACCESS( segment, Elf_Xword, memory_size );
ELFIO_C_GET_SET_ACCESS( segment, Elf64_Addr, virtual_address );
ELFIO_C_GET_SET_ACCESS( segment, Elf64_Addr, physical_address );
ELFIO_C_GET_SET_ACCESS( segment, Elf_Xword, file_size );
ELFIO_C_GET_ACCESS( segment, Elf64_Off, offset );
char* elfio_segment_get_data( psegment_t psegment );
Elf_Half elfio_segment_add_section_index( psegment_t psegment,
Elf_Half index,
Elf_Xword addr_align );
Elf_Half elfio_segment_get_sections_num( psegment_t psegment );
Elf_Half elfio_segment_get_section_index_at( psegment_t psegment,
Elf_Half num );
bool elfio_segment_is_offset_initialized( psegment_t psegment );
//-----------------------------------------------------------------------------
// symbol
//-----------------------------------------------------------------------------
psymbol_t elfio_symbol_section_accessor_new( pelfio_t pelfio,
psection_t psection );
void elfio_symbol_section_accessor_delete( psymbol_t psymbol );
Elf_Xword elfio_symbol_get_symbols_num( psymbol_t psymbol );
bool elfio_symbol_get_symbol( psymbol_t psymbol,
Elf_Xword index,
char* name,
int name_len,
Elf64_Addr* value,
Elf_Xword* size,
unsigned char* bind,
unsigned char* type,
Elf_Half* section_index,
unsigned char* other );
Elf_Word elfio_symbol_add_symbol( psymbol_t psymbol,
Elf_Word name,
Elf64_Addr value,
Elf_Xword size,
unsigned char info,
unsigned char other,
Elf_Half shndx );
Elf_Xword elfio_symbol_arrange_local_symbols(
psymbol_t psymbol,
void ( *func )( Elf_Xword first, Elf_Xword second ) );
//-----------------------------------------------------------------------------
// relocation
//-----------------------------------------------------------------------------
prelocation_t elfio_relocation_section_accessor_new( pelfio_t pelfio,
psection_t psection );
void elfio_relocation_section_accessor_delete( prelocation_t prelocation );
Elf_Xword elfio_relocation_get_entries_num( prelocation_t prelocation );
bool elfio_relocation_get_entry( prelocation_t prelocation,
Elf_Xword index,
Elf64_Addr* offset,
Elf_Word* symbol,
Elf_Word* type,
Elf_Sxword* addend );
bool elfio_relocation_set_entry( prelocation_t prelocation,
Elf_Xword index,
Elf64_Addr offset,
Elf_Word symbol,
Elf_Word type,
Elf_Sxword addend );
void elfio_relocation_add_entry( prelocation_t prelocation,
Elf64_Addr offset,
Elf_Word symbol,
unsigned char type,
Elf_Sxword addend );
void elfio_relocation_swap_symbols( prelocation_t prelocation,
Elf_Xword first,
Elf_Xword second );
//-----------------------------------------------------------------------------
// string
//-----------------------------------------------------------------------------
pstring_t elfio_string_section_accessor_new( psection_t psection );
void elfio_string_section_accessor_delete( pstring_t pstring );
const char* elfio_string_get_string( pstring_t pstring, Elf_Word index );
Elf_Word elfio_string_add_string( pstring_t pstring, char* str );
//-----------------------------------------------------------------------------
// note
//-----------------------------------------------------------------------------
pnote_t elfio_note_section_accessor_new( pelfio_t pelfio,
psection_t psection );
void elfio_note_section_accessor_delete( pnote_t pstring );
Elf_Word elfio_note_get_notes_num( pnote_t pnote );
bool elfio_note_get_note( pnote_t pnote,
Elf_Word index,
Elf_Word* type,
char* name,
int name_len,
void** desc,
Elf_Word* descSize );
void elfio_note_add_note( pnote_t pnote,
Elf_Word type,
const char* name,
const void* desc,
Elf_Word descSize );
//-----------------------------------------------------------------------------
// modinfo
//-----------------------------------------------------------------------------
pmodinfo_t elfio_modinfo_section_accessor_new( psection_t psection );
void elfio_modinfo_section_accessor_delete( pmodinfo_t pmodinfo );
Elf_Word elfio_modinfo_get_attribute_num( pmodinfo_t pmodinfo );
bool elfio_modinfo_get_attribute( pmodinfo_t pmodinfo,
Elf_Word no,
char* field,
int field_len,
char* value,
int value_len );
bool elfio_modinfo_get_attribute_by_name( pmodinfo_t pmodinfo,
char* field_name,
char* value,
int value_len );
Elf_Word elfio_modinfo_add_attribute( pmodinfo_t pmodinfo,
char* field,
char* value );
//-----------------------------------------------------------------------------
// dynamic
//-----------------------------------------------------------------------------
pdynamic_t elfio_dynamic_section_accessor_new( pelfio_t pelfio,
psection_t psection );
void elfio_dynamic_section_accessor_delete( pdynamic_t pdynamic );
Elf_Xword elfio_dynamic_get_entries_num( pdynamic_t pdynamic );
bool elfio_dynamic_get_entry( pdynamic_t pdynamic,
Elf_Xword index,
Elf_Xword* tag,
Elf_Xword* value,
char* str,
int str_len );
void elfio_dynamic_add_entry( pdynamic_t pdynamic,
Elf_Xword tag,
Elf_Xword value );
//-----------------------------------------------------------------------------
// array
//-----------------------------------------------------------------------------
parray_t elfio_array_section_accessor_new( pelfio_t pelfio,
psection_t psection );
void elfio_array_section_accessor_delete( parray_t parray );
Elf_Xword elfio_array_get_entries_num( parray_t parray );
bool elfio_array_get_entry( parray_t parray,
Elf_Xword index,
Elf64_Addr* paddress );
void elfio_array_add_entry( parray_t parray, Elf64_Addr address );
#ifdef __cplusplus
}
#endif
#endif // ELFIO_C_WRAPPER_H
+3
View File
@@ -0,0 +1,3 @@
add_executable(elfdump elfdump.cpp)
target_link_libraries(elfdump PRIVATE elfio::elfio)
+60
View File
@@ -0,0 +1,60 @@
/*
elfdump.cpp - Dump ELF file using ELFIO library.
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.
*/
#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#define ELFIO_NO_INTTYPES
#endif
#include <iostream>
#include <elfio/elfio_dump.hpp>
using namespace ELFIO;
int main( int argc, char** argv )
{
if ( argc != 2 ) {
printf( "Usage: elfdump <file_name>\n" );
return 1;
}
elfio reader;
if ( !reader.load( argv[1] ) ) {
printf( "File %s is not found or it is not an ELF file\n", argv[1] );
return 1;
}
dump::header( std::cout, reader );
dump::section_headers( std::cout, reader );
dump::segment_headers( std::cout, reader );
dump::symbol_tables( std::cout, reader );
dump::notes( std::cout, reader );
dump::modinfo( std::cout, reader );
dump::dynamic_tags( std::cout, reader );
dump::section_datas( std::cout, reader );
dump::segment_datas( std::cout, reader );
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(elfio-ldd elfio_ldd.cpp)
target_link_libraries(elfio-ldd PRIVATE elfio::elfio)
+56
View File
@@ -0,0 +1,56 @@
/*
elfio_ldd.cpp - Use ELFIO library to list dynamic libraries required by ELF file.
2025 Pasha-From-Russia
ELFIO 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.
*/
#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#define ELFIO_NO_INTTYPES
#endif
#include <iostream>
#include <elfio/elfio_dump.hpp>
using namespace ELFIO;
static const bool kPrintNamesOnly = true;
int main( int argc, char** argv )
{
if ( argc != 2 ) {
printf( "Usage: elfio_ldd <file_name>\n" );
return 1;
}
elfio reader;
if ( !reader.load( argv[1] ) ) {
printf( "File %s is not found or it is not an ELF file\n", argv[1] );
return 1;
}
dump::dynamic_tags( std::cout, reader, kPrintNamesOnly );
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(proc_mem proc_mem.cpp)
target_link_libraries(proc_mem PRIVATE elfio::elfio)
+96
View File
@@ -0,0 +1,96 @@
/*
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 ) {
unsigned long start = std::stoul( match[1].str(), 0, 16 );
unsigned long end = std::stoul( match[2].str(), 0, 16 );
unsigned long actual = std::stoul( match[4].str(), 0, 16 );
result.emplace_back( actual, end - start, start );
}
}
}
}
//------------------------------------------------------------------------------
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;
}
// Retrieve memory address translation ranges
std::vector<address_translation> ranges;
get_translation_ranges( proc_maps, argv[2], ranges );
// 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", true ) ) {
dump::header( std::cout, elffile );
dump::segment_headers( std::cout, elffile );
dump::segment_datas( std::cout, elffile );
}
else {
std::cout << "Can't open " << std::string( "/proc/" ) + argv[1] + "/mem"
<< " file" << std::endl;
}
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
# The file is used for VSCode debugging with sudo. Use it as following:
# "miDebuggerPath": "/home/user/ELFIO/examples/sudo_gdb.sh"
sudo /usr/bin/gdb "$@"
+3
View File
@@ -0,0 +1,3 @@
add_executable(tutorial tutorial.cpp)
target_link_libraries(tutorial PRIVATE elfio::elfio)
+104
View File
@@ -0,0 +1,104 @@
/*
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 <elfio/elfio.hpp>
using namespace ELFIO;
int main( int argc, char** argv )
{
if ( argc != 2 ) {
std::cout << "Usage: tutorial <elf_file>" << std::endl;
return 1;
}
// Create an elfio reader
elfio reader;
// Load ELF data
if ( !reader.load( argv[1] ) ) {
std::cout << "Can't find or process ELF file " << argv[1] << std::endl;
return 2;
}
// Print ELF file properties
std::cout << "ELF file class : ";
if ( reader.get_class() == ELFCLASS32 )
std::cout << "ELF32" << std::endl;
else
std::cout << "ELF64" << std::endl;
std::cout << "ELF file encoding : ";
if ( reader.get_encoding() == ELFDATA2LSB )
std::cout << "Little endian" << std::endl;
else
std::cout << "Big endian" << std::endl;
// Print ELF file sections info
Elf_Half sec_num = reader.sections.size();
std::cout << "Number of sections: " << sec_num << std::endl;
for ( int i = 0; i < sec_num; ++i ) {
section* psec = reader.sections[i];
std::cout << " [" << i << "] " << psec->get_name() << "\t"
<< psec->get_size() << std::endl;
// Access to section's data
// const char* p = reader.sections[i]->get_data()
}
// Print ELF file segments info
Elf_Half seg_num = reader.segments.size();
std::cout << "Number of segments: " << seg_num << std::endl;
for ( int i = 0; i < seg_num; ++i ) {
const segment* pseg = reader.segments[i];
std::cout << " [" << i << "] 0x" << std::hex << pseg->get_flags()
<< "\t0x" << pseg->get_virtual_address() << "\t0x"
<< pseg->get_file_size() << "\t0x" << pseg->get_memory_size()
<< std::endl;
// Access to segments's data
// const char* p = reader.segments[i]->get_data()
}
for ( int i = 0; i < sec_num; ++i ) {
section* psec = reader.sections[i];
// Check section type
if ( psec->get_type() == SHT_SYMTAB ) {
const symbol_section_accessor symbols( reader, psec );
for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j ) {
std::string name;
Elf64_Addr value;
Elf_Xword size;
unsigned char bind;
unsigned char type;
Elf_Half section_index;
unsigned char other;
// Read symbol properties
symbols.get_symbol( j, name, value, size, bind, type,
section_index, other );
std::cout << j << " " << name << " " << value << std::endl;
}
}
}
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(write_obj write_obj.cpp)
target_link_libraries(write_obj PRIVATE elfio::elfio)
+139
View File
@@ -0,0 +1,139 @@
/*
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.
*/
/*
* This example shows how to create ELF object file for Linux on x86
*
* Instructions:
* 1. Compile and link this file with ELFIO library
* g++ write_obj.cpp -o writer_obj
* 2. Execute result file write_obj
* ./write_obj
* 3. Link output file hello.o:
* ld -o hello hello.o
* 4. Run the result file:
* ./hello
*/
#include <elfio/elfio.hpp>
using namespace ELFIO;
int main( void )
{
elfio writer;
// You can't proceed before this function call!
writer.create( ELFCLASS64, ELFDATA2LSB );
writer.set_os_abi( ELFOSABI_LINUX );
writer.set_type( ET_REL );
writer.set_machine( EM_X86_64 );
// This is our code
char text[] = {
'\xB8', '\x04', '\x00', '\x00', '\x00', // mov eax, 4
'\xBB', '\x01', '\x00', '\x00', '\x00', // mov ebx, 1
'\xB9', '\x00', '\x00', '\x00', '\x00', // mov ecx, msg
'\xBA', '\x0E', '\x00', '\x00', '\x00', // mov edx, 14
'\xCD', '\x80', // int 0x80
'\xB8', '\x01', '\x00', '\x00', '\x00', // mov eax, 1
'\xCD', '\x80', // int 0x80
'\x48', '\x65', '\x6C', '\x6C', '\x6F', // msg: db 'Hello, World!', 10
'\x2C', '\x20', '\x57', '\x6F', '\x72',
'\x6C', '\x64', '\x21', '\x0A' };
Elf64_Addr place_to_adjust = 11;
// Create code section
section* text_sec = writer.sections.add( ".text" );
text_sec->set_type( SHT_PROGBITS );
text_sec->set_flags( SHF_ALLOC | SHF_EXECINSTR );
text_sec->set_addr_align( 0x10 );
text_sec->set_data( text, sizeof( text ) );
// Create string table section
section* str_sec = writer.sections.add( ".strtab" );
str_sec->set_type( SHT_STRTAB );
// Create string table writer
string_section_accessor stra( str_sec );
// Add label name
Elf32_Word str_index = stra.add_string( "msg" );
// Create symbol table section
section* sym_sec = writer.sections.add( ".symtab" );
sym_sec->set_type( SHT_SYMTAB );
sym_sec->set_info( 1 );
sym_sec->set_addr_align( 0x4 );
sym_sec->set_entry_size( writer.get_default_entry_size( SHT_SYMTAB ) );
sym_sec->set_link( str_sec->get_index() );
// Create symbol table writer
symbol_section_accessor syma( writer, sym_sec );
// Add symbol entry (msg has offset == 29)
Elf_Word sym_to_adjust = syma.add_symbol(
str_index, 29, 0, STB_GLOBAL, STT_OBJECT, 0, text_sec->get_index() );
// Another way to add symbol
syma.add_symbol( stra, "_start", 0x00000000, 0, STB_WEAK, STT_FUNC, 0,
text_sec->get_index() );
// Create relocation table section
section* rel_sec = writer.sections.add( ".rel.text" );
rel_sec->set_type( SHT_REL );
rel_sec->set_info( text_sec->get_index() );
rel_sec->set_addr_align( 0x4 );
rel_sec->set_entry_size( writer.get_default_entry_size( SHT_REL ) );
rel_sec->set_link( sym_sec->get_index() );
// Create relocation table writer
relocation_section_accessor rela( writer, rel_sec );
// Add relocation entry (adjust address at offset 11)
rela.add_entry( place_to_adjust, sym_to_adjust,
(unsigned char)R_X86_64_32 );
// Another method to add the same relocation entry at one step is:
// rela.add_entry( stra, "msg",
// syma, 29, 0,
// ELF_ST_INFO( STB_GLOBAL, STT_OBJECT ), 0,
// text_sec->get_index(),
// place_to_adjust, (unsigned char)R_386_RELATIVE );
// Create note section
section* note_sec = writer.sections.add( ".note" );
note_sec->set_type( SHT_NOTE );
note_section_accessor note_writer( writer, note_sec );
note_writer.add_note( 0x01, "Created by ELFIO", 0, 0 );
char descr[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
note_writer.add_note( 0x01, "Never easier!", descr, sizeof( descr ) );
// We don't use local symbols here. There is no need to rearrange them.
// But, for the completeness, we do this just prior 'save'
syma.arrange_local_symbols( [&]( Elf_Xword first, Elf_Xword second ) {
rela.swap_symbols( first, second );
} );
// Create ELF object file
writer.save( "hello.o" );
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
add_executable(writer writer.cpp)
target_link_libraries(writer PRIVATE elfio::elfio)
+132
View File
@@ -0,0 +1,132 @@
/*
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.
*/
/*
* This example shows how to create ELF executable file for Linux on x86-64
*
* Instructions:
* 1. Compile and link this file with ELFIO library
* g++ writer.cpp -o writer
* 2. Execute result file writer
* ./writer
* 3. Add executable flag for the output file
* chmod +x hello_x86_64
* 4. Run the result file:
* ./hello_x86_64
*/
#include <elfio/elfio.hpp>
using namespace ELFIO;
const Elf64_Addr CODE_ADDR = 0x00401000;
const Elf_Xword PAGE_SIZE = 0x1000;
const Elf64_Addr DATA_ADDR = CODE_ADDR + PAGE_SIZE;
int main( void )
{
elfio writer;
// You can't proceed without this function call!
writer.create( ELFCLASS64, ELFDATA2LSB );
writer.set_os_abi( ELFOSABI_LINUX );
writer.set_type( ET_EXEC );
writer.set_machine( EM_X86_64 );
// Create code section
section* text_sec = writer.sections.add( ".text" );
text_sec->set_type( SHT_PROGBITS );
text_sec->set_flags( SHF_ALLOC | SHF_EXECINSTR );
text_sec->set_addr_align( 0x10 );
// Add data into it
char text[] = {
'\xB8', '\x04', '\x00', '\x00', '\x00', // mov eax, 4
'\xBB', '\x01', '\x00', '\x00', '\x00', // mov ebx, 1
'\xB9', '\x00', '\x00', '\x00', '\x00', // mov ecx, msg
'\xBA', '\x0E', '\x00', '\x00', '\x00', // mov edx, 14
'\xCD', '\x80', // int 0x80
'\xB8', '\x01', '\x00', '\x00', '\x00', // mov eax, 1
'\xCD', '\x80' // int 0x80
};
// Adjust data address for 'msg'
*(std::uint32_t*)( text + 11 ) = DATA_ADDR;
text_sec->set_data( text, sizeof( text ) );
// Create a loadable segment
segment* text_seg = writer.segments.add();
text_seg->set_type( PT_LOAD );
text_seg->set_virtual_address( CODE_ADDR );
text_seg->set_physical_address( CODE_ADDR );
text_seg->set_flags( PF_X | PF_R );
text_seg->set_align( PAGE_SIZE );
// Add code section into program segment
text_seg->add_section( text_sec, text_sec->get_addr_align() );
// Create data section
section* data_sec = writer.sections.add( ".data" );
data_sec->set_type( SHT_PROGBITS );
data_sec->set_flags( SHF_ALLOC | SHF_WRITE );
data_sec->set_addr_align( 0x4 );
char data[] = {
'\x48', '\x65', '\x6C', '\x6C', '\x6F', // msg: db 'Hello, World!', 10
'\x2C', '\x20', '\x57', '\x6F', '\x72',
'\x6C', '\x64', '\x21', '\x0A' };
data_sec->set_data( data, sizeof( data ) );
// Create a read/write segment
segment* data_seg = writer.segments.add();
data_seg->set_type( PT_LOAD );
data_seg->set_virtual_address( DATA_ADDR );
data_seg->set_physical_address( DATA_ADDR );
data_seg->set_flags( PF_W | PF_R );
data_seg->set_align( PAGE_SIZE );
// Add code section into program segment
data_seg->add_section( data_sec, data_sec->get_addr_align() );
// Add optional signature for the file producer
section* note_sec = writer.sections.add( ".note" );
note_sec->set_type( SHT_NOTE );
note_sec->set_addr_align( 1 );
note_section_accessor note_writer( writer, note_sec );
note_writer.add_note( 0x01, "Created by ELFIO", 0, 0 );
char descr[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
note_writer.add_note( 0x01, "Never easier!", descr, sizeof( descr ) );
// Setup entry point. Usually, a linker sets this address on base of
// _start label.
// In this example, the code starts at the first address of the
// 'text_seg' segment. Therefore, the start address is set
// to be equal to the segment location
writer.set_entry( text_seg->get_virtual_address() );
// Create ELF file
writer.save( "hello_x86_64" );
return 0;
}