diff --git a/.gitignore b/.gitignore index 8c650fc..e1d396a 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,7 @@ tests/elf_examples/zavl_gen.ko examples/writer/hello_x86_64 examples/write_obj/hello +examples/c_interop/c_example # various unwanted files (backups, objects, cmake artifacts) *~ diff --git a/CMakeLists.txt b/CMakeLists.txt index 67513e8..4182a83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(examples/elfdump) add_subdirectory(examples/tutorial) add_subdirectory(examples/write_obj) add_subdirectory(examples/writer) +add_subdirectory(examples/c_interop) diff --git a/elfio/elf_types.hpp b/elfio/elf_types.hpp index 5c32bfe..e53f616 100644 --- a/elfio/elf_types.hpp +++ b/elfio/elf_types.hpp @@ -45,7 +45,9 @@ typedef signed long long int64_t; #endif // ELFIO_NO_CSTDINT #endif // ELFIO_NO_OWN_TYPES +#ifdef __cplusplus namespace ELFIO { +#endif // Attention! Platform depended definitions. typedef uint16_t Elf_Half; @@ -864,6 +866,8 @@ struct Elf64_Dyn } d_un; }; +#ifdef __cplusplus } // namespace ELFIO +#endif #endif // ELFTYPES_H diff --git a/elfio/elfio_utils.hpp b/elfio/elfio_utils.hpp index 1a0f65c..1efdbfc 100644 --- a/elfio/elfio_utils.hpp +++ b/elfio/elfio_utils.hpp @@ -25,6 +25,7 @@ THE SOFTWARE. #define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \ TYPE get_##NAME() const { return ( *convertor )( FIELD ); } + #define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \ void set_##NAME( TYPE value ) \ { \ diff --git a/examples/c_interop/CMakeLists.txt b/examples/c_interop/CMakeLists.txt new file mode 100644 index 0000000..0629019 --- /dev/null +++ b/examples/c_interop/CMakeLists.txt @@ -0,0 +1,3 @@ + +add_executable(c_example c_example.c elfio_c_interop.cpp elfio_c_interop.h) +include_directories(SYSTEM ${CMAKE_SOURCE_DIR}) diff --git a/examples/c_interop/c_example.c b/examples/c_interop/c_example.c new file mode 100644 index 0000000..df410f4 --- /dev/null +++ b/examples/c_interop/c_example.c @@ -0,0 +1,47 @@ +#include + +#include +#include "elfio_c_interop.h" + +int main( int argc, char* argv[] ) +{ + pelfio_t pelfio = elfio_new(); + bool ret = elfio_load( pelfio, argv[0] ); + + if ( !ret ) { + printf( "Can't load ELF file\n" ); + } + + 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 ) ); + + int secno = elfio_get_sections_num( pelfio ); + printf( "\nSections 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 ) ); + } + + int segno = elfio_get_segments_num( pelfio ); + printf( "\nSegments No : %d\n", segno ); + + for ( int i = 0; i < segno; i++ ) { + psegment_t psegment = elfio_get_segment_by_index( pelfio, i ); + 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 ) ); + } + + elfio_delete( pelfio ); + + return 0; +} diff --git a/examples/c_interop/elfio_c_interop.cpp b/examples/c_interop/elfio_c_interop.cpp new file mode 100644 index 0000000..f22d582 --- /dev/null +++ b/examples/c_interop/elfio_c_interop.cpp @@ -0,0 +1,190 @@ +/* +Copyright (C) 2001-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. +*/ + +#include +#include + +using namespace ELFIO; + +#include "elfio_c_interop.h" + +//----------------------------------------------------------------------------- +// elfio +//----------------------------------------------------------------------------- +pelfio_t elfio_new() { return new 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(); +} + +//----------------------------------------------------------------------------- +// 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(), 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(); +} diff --git a/examples/c_interop/elfio_c_interop.h b/examples/c_interop/elfio_c_interop.h new file mode 100644 index 0000000..647569a --- /dev/null +++ b/examples/c_interop/elfio_c_interop.h @@ -0,0 +1,174 @@ +/* +Copyright (C) 2001-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. +*/ + +#ifndef ELFIO_C_INTEROP_H +#define ELFIO_C_INTEROP_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; + +extern "C" +{ +#else +typedef void* pelfio_t; +typedef void* psection_t; +typedef void* psegment_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 ); + + //----------------------------------------------------------------------------- + // 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 ); + +#ifdef __cplusplus +} +#endif + +#endif // ELFIO_C_INTEROP_H