diff --git a/elfio/elf_types.hpp b/elfio/elf_types.hpp index cb2cb51..c4f6b47 100644 --- a/elfio/elf_types.hpp +++ b/elfio/elf_types.hpp @@ -491,50 +491,50 @@ constexpr Elf_Word SHN_XINDEX = 0xFFFF; constexpr Elf_Word SHN_HIRESERVE = 0xFFFF; // Section types -constexpr Elf_Word SHT_NULL = 0; -constexpr Elf_Word SHT_PROGBITS = 1; -constexpr Elf_Word SHT_SYMTAB = 2; -constexpr Elf_Word SHT_STRTAB = 3; -constexpr Elf_Word SHT_RELA = 4; -constexpr Elf_Word SHT_HASH = 5; -constexpr Elf_Word SHT_DYNAMIC = 6; -constexpr Elf_Word SHT_NOTE = 7; -constexpr Elf_Word SHT_NOBITS = 8; -constexpr Elf_Word SHT_REL = 9; -constexpr Elf_Word SHT_SHLIB = 10; -constexpr Elf_Word SHT_DYNSYM = 11; -constexpr Elf_Word SHT_INIT_ARRAY = 14; -constexpr Elf_Word SHT_FINI_ARRAY = 15; -constexpr Elf_Word SHT_PREINIT_ARRAY = 16; -constexpr Elf_Word SHT_GROUP = 17; -constexpr Elf_Word SHT_SYMTAB_SHNDX = 18; -constexpr Elf_Word SHT_GNU_ATTRIBUTES = 0x6ffffff5; -constexpr Elf_Word SHT_GNU_HASH = 0x6ffffff6; -constexpr Elf_Word SHT_GNU_LIBLIST = 0x6ffffff7; -constexpr Elf_Word SHT_CHECKSUM = 0x6ffffff8; -constexpr Elf_Word SHT_LOSUNW = 0x6ffffffa; -constexpr Elf_Word SHT_SUNW_move = 0x6ffffffa; -constexpr Elf_Word SHT_SUNW_COMDAT = 0x6ffffffb; -constexpr Elf_Word SHT_SUNW_syminfo = 0x6ffffffc; -constexpr Elf_Word SHT_GNU_verdef = 0x6ffffffd; -constexpr Elf_Word SHT_GNU_verneed = 0x6ffffffe; -constexpr Elf_Word SHT_GNU_versym = 0x6fffffff; -constexpr Elf_Word SHT_LOOS = 0x60000000; -constexpr Elf_Word SHT_HIOS = 0x6fffffff; -constexpr Elf_Word SHT_LOPROC = 0x70000000; -constexpr Elf_Word SHT_ARM_EXIDX = 0x70000001; -constexpr Elf_Word SHT_ARM_PREEMPTMAP = 0x70000002; -constexpr Elf_Word SHT_ARM_ATTRIBUTES = 0x70000003; -constexpr Elf_Word SHT_ARM_DEBUGOVERLAY = 0x70000004; -constexpr Elf_Word SHT_ARM_OVERLAYSECTION = 0x70000005; -constexpr Elf_Word SHT_HIPROC = 0x7FFFFFFF; -constexpr Elf_Word SHT_LOUSER = 0x80000000; +constexpr Elf_Word SHT_NULL = 0; +constexpr Elf_Word SHT_PROGBITS = 1; +constexpr Elf_Word SHT_SYMTAB = 2; +constexpr Elf_Word SHT_STRTAB = 3; +constexpr Elf_Word SHT_RELA = 4; +constexpr Elf_Word SHT_HASH = 5; +constexpr Elf_Word SHT_DYNAMIC = 6; +constexpr Elf_Word SHT_NOTE = 7; +constexpr Elf_Word SHT_NOBITS = 8; +constexpr Elf_Word SHT_REL = 9; +constexpr Elf_Word SHT_SHLIB = 10; +constexpr Elf_Word SHT_DYNSYM = 11; +constexpr Elf_Word SHT_INIT_ARRAY = 14; +constexpr Elf_Word SHT_FINI_ARRAY = 15; +constexpr Elf_Word SHT_PREINIT_ARRAY = 16; +constexpr Elf_Word SHT_GROUP = 17; +constexpr Elf_Word SHT_SYMTAB_SHNDX = 18; +constexpr Elf_Word SHT_GNU_ATTRIBUTES = 0x6ffffff5; +constexpr Elf_Word SHT_GNU_HASH = 0x6ffffff6; +constexpr Elf_Word SHT_GNU_LIBLIST = 0x6ffffff7; +constexpr Elf_Word SHT_CHECKSUM = 0x6ffffff8; +constexpr Elf_Word SHT_LOSUNW = 0x6ffffffa; +constexpr Elf_Word SHT_SUNW_move = 0x6ffffffa; +constexpr Elf_Word SHT_SUNW_COMDAT = 0x6ffffffb; +constexpr Elf_Word SHT_SUNW_syminfo = 0x6ffffffc; +constexpr Elf_Word SHT_GNU_verdef = 0x6ffffffd; +constexpr Elf_Word SHT_GNU_verneed = 0x6ffffffe; +constexpr Elf_Word SHT_GNU_versym = 0x6fffffff; +constexpr Elf_Word SHT_LOOS = 0x60000000; +constexpr Elf_Word SHT_HIOS = 0x6fffffff; +constexpr Elf_Word SHT_LOPROC = 0x70000000; +constexpr Elf_Word SHT_ARM_EXIDX = 0x70000001; +constexpr Elf_Word SHT_ARM_PREEMPTMAP = 0x70000002; +constexpr Elf_Word SHT_ARM_ATTRIBUTES = 0x70000003; +constexpr Elf_Word SHT_ARM_DEBUGOVERLAY = 0x70000004; +constexpr Elf_Word SHT_ARM_OVERLAYSECTION = 0x70000005; +constexpr Elf_Word SHT_HIPROC = 0x7FFFFFFF; +constexpr Elf_Word SHT_LOUSER = 0x80000000; // Used by Nintendo Wii U -constexpr Elf_Word SHT_RPL_EXPORTS = 0x80000001; -constexpr Elf_Word SHT_RPL_IMPORTS = 0x80000002; -constexpr Elf_Word SHT_RPL_CRCS = 0x80000003; -constexpr Elf_Word SHT_RPL_FILEINFO = 0x80000004; -constexpr Elf_Word SHT_HIUSER = 0xFFFFFFFF; +constexpr Elf_Word SHT_RPL_EXPORTS = 0x80000001; +constexpr Elf_Word SHT_RPL_IMPORTS = 0x80000002; +constexpr Elf_Word SHT_RPL_CRCS = 0x80000003; +constexpr Elf_Word SHT_RPL_FILEINFO = 0x80000004; +constexpr Elf_Word SHT_HIUSER = 0xFFFFFFFF; // Section attribute flags constexpr Elf_Xword SHF_WRITE = 0x1; @@ -550,13 +550,13 @@ constexpr Elf_Xword SHF_TLS = 0x400; constexpr Elf_Xword SHF_COMPRESSED = 0x800; constexpr Elf_Xword SHF_GNU_RETAIN = 0x200000; constexpr Elf_Xword SHF_GNU_MBIND = 0x01000000; -// flag used in Nintendo RPX/RPL to indicate section data is zlib-compressed -constexpr Elf_Xword SHF_RPX_DEFLATE = 0x08000000; -constexpr Elf_Xword SHF_MASKOS = 0x0FF00000; -constexpr Elf_Xword SHF_MIPS_GPREL = 0x10000000; -constexpr Elf_Xword SHF_ORDERED = 0x40000000; -constexpr Elf_Xword SHF_EXCLUDE = 0x80000000; -constexpr Elf_Xword SHF_MASKPROC = 0xF0000000; +// flag used in Nintendo RPX/RPL to indicate section data is compressed +constexpr Elf_Xword SHF_RPX_DEFLATE = 0x08000000; +constexpr Elf_Xword SHF_MASKOS = 0x0FF00000; +constexpr Elf_Xword SHF_MIPS_GPREL = 0x10000000; +constexpr Elf_Xword SHF_ORDERED = 0x40000000; +constexpr Elf_Xword SHF_EXCLUDE = 0x80000000; +constexpr Elf_Xword SHF_MASKPROC = 0xF0000000; // Section group flags constexpr Elf_Word GRP_COMDAT = 0x1; @@ -1323,6 +1323,23 @@ struct Elf64_auxv } a_un; }; +struct Elf32_Chdr +{ + Elf32_Word ch_type; // The compression algorithm used + Elf32_Word ch_size; //The size, in bytes, of the uncompressed section data + Elf32_Word + ch_addralign; // The address alignment of the uncompressed section data +}; + +struct Elf64_Chdr +{ + Elf64_Word ch_type; //The compression algorithm used + Elf64_Word ch_reserved; // Reserved + Elf_Xword ch_size; //The size, in bytes, of the uncompressed section data + Elf_Xword + ch_addralign; //The address alignment of the uncompressed section data +}; + #ifdef __cplusplus } // namespace ELFIO #endif diff --git a/elfio/elfio.hpp b/elfio/elfio.hpp index 6a25ad4..b92bb56 100644 --- a/elfio/elfio.hpp +++ b/elfio/elfio.hpp @@ -63,12 +63,15 @@ class elfio { public: //------------------------------------------------------------------------------ - elfio() noexcept : sections( this ), segments( this ), zlib( nullptr ) + elfio() noexcept + : sections( this ), segments( this ), compression( nullptr ) { create( ELFCLASS32, ELFDATA2LSB ); } - elfio( wiiu_zlib_interface *zlib ) noexcept : sections( this ), segments( this ), zlib( std::shared_ptr(zlib) ) + elfio( compression_interface* compression ) noexcept + : sections( this ), segments( this ), + compression( std::shared_ptr( compression ) ) { elfio(); } @@ -82,12 +85,12 @@ class elfio segments_ = std::move( other.segments_ ); convertor = std::move( other.convertor ); addr_translator = std::move( other.addr_translator ); - zlib = std::move( other.zlib ); + compression = std::move( other.compression ); other.header = nullptr; other.sections_.clear(); other.segments_.clear(); - other.zlib = nullptr; + other.compression = nullptr; } elfio& operator=( elfio&& other ) noexcept @@ -99,11 +102,11 @@ class elfio convertor = std::move( other.convertor ); addr_translator = std::move( other.addr_translator ); current_file_pos = other.current_file_pos; - zlib = std::move( other.zlib ); + compression = std::move( other.compression ); other.current_file_pos = 0; other.header = nullptr; - other.zlib = nullptr; + other.compression = nullptr; other.sections_.clear(); other.segments_.clear(); } @@ -413,12 +416,12 @@ class elfio unsigned char file_class = get_class(); if ( file_class == ELFCLASS64 ) { - sections_.emplace_back( - new section_impl( &convertor, &addr_translator, zlib ) ); + sections_.emplace_back( new section_impl( + &convertor, &addr_translator, compression ) ); } else if ( file_class == ELFCLASS32 ) { - sections_.emplace_back( - new section_impl( &convertor, &addr_translator, zlib ) ); + sections_.emplace_back( new section_impl( + &convertor, &addr_translator, compression ) ); } else { sections_.pop_back(); @@ -1058,12 +1061,12 @@ class elfio //------------------------------------------------------------------------------ private: - std::unique_ptr header = nullptr; - std::vector> sections_; - std::vector> segments_; - endianess_convertor convertor; - address_translator addr_translator; - std::shared_ptr zlib = nullptr; + std::unique_ptr header = nullptr; + std::vector> sections_; + std::vector> segments_; + endianess_convertor convertor; + address_translator addr_translator; + std::shared_ptr compression = nullptr; Elf_Xword current_file_pos = 0; }; diff --git a/elfio/elfio_dump.hpp b/elfio/elfio_dump.hpp index 2acaef7..3310511 100644 --- a/elfio/elfio_dump.hpp +++ b/elfio/elfio_dump.hpp @@ -741,8 +741,10 @@ class dump out << "Key to Flags: W (write), A (alloc), X (execute), " << std::endl; out << " M (merge), S (strings), I (info)," << std::endl; - out << " L (link order), O (extra OS processing required)," << std::endl; - out << " G (group), T (TLS), C (compressed), E (exclude)" << std::endl; + out << " L (link order), O (extra OS processing required)," + << std::endl; + out << " G (group), T (TLS), C (compressed), E (exclude)" + << std::endl; } //------------------------------------------------------------------------------ @@ -979,7 +981,7 @@ class dump Elf_Word no_notes = notes.get_notes_num(); if ( no_notes == 0 ) - continue; + continue; out << "Note segment (" << i << ")" << std::endl << " No Name Data size Description" diff --git a/elfio/elfio_section.hpp b/elfio/elfio_section.hpp index fa76674..e36944d 100644 --- a/elfio/elfio_section.hpp +++ b/elfio/elfio_section.hpp @@ -73,10 +73,11 @@ template class section_impl : public section { public: //------------------------------------------------------------------------------ - section_impl( const endianess_convertor* convertor, - const address_translator* translator, - const std::shared_ptr &zlib ) - : convertor( convertor ), translator( translator ), zlib(zlib) + section_impl( const endianess_convertor* convertor, + const address_translator* translator, + const std::shared_ptr& compression ) + : convertor( convertor ), translator( translator ), + compression( compression ) { } @@ -221,28 +222,35 @@ template class section_impl : public section return false; } - if(get_flags() & SHF_RPX_DEFLATE) { - if(zlib == nullptr) { - std::cerr << "WARN: compressed section found but no zlib implementation provided. Skipping." << std::endl; + if ( ( get_flags() & SHF_RPX_DEFLATE ) || + ( get_flags() & SHF_COMPRESSED ) ) { + if ( compression == nullptr ) { + std::cerr + << "WARN: compressed section found but no " + "compression implementation provided. Skipping." + << std::endl; data = nullptr; return false; } // at this point, data holds the whole compressed stream Elf_Xword uncompressed_size = 0; - auto decompressed_data = zlib->inflate(data.get(), convertor, size, uncompressed_size); - if(decompressed_data == nullptr) { - std::cerr << "Failed to decompress section data." << std::endl; + auto decompressed_data = compression->inflate( + data.get(), convertor, size, uncompressed_size ); + if ( decompressed_data == nullptr ) { + std::cerr << "Failed to decompress section data." + << std::endl; data = nullptr; return false; } - set_size(uncompressed_size); + set_size( uncompressed_size ); - data = std::move(decompressed_data); + data = std::move( decompressed_data ); } // refresh size because it may have changed if we had to decompress data size = get_size(); - data.get()[size] = 0; // Ensure data is ended with 0 to avoid oob read + data.get()[size] = + 0; // Ensure data is ended with 0 to avoid oob read data_size = decltype( data_size )( size ); } else { @@ -285,28 +293,32 @@ template class section_impl : public section { adjust_stream_size( stream, data_offset ); - if( (get_flags() & SHF_RPX_DEFLATE) && zlib != nullptr) { + if ( ( ( get_flags() & SHF_COMPRESSED ) || + ( get_flags() & SHF_RPX_DEFLATE ) ) && + compression != nullptr ) { Elf_Xword decompressed_size = get_size(); - Elf_Xword compressed_size = 0; - auto compressed_ptr = zlib->deflate(data.get(), convertor, decompressed_size, compressed_size); - stream.write( compressed_ptr.get(), compressed_size); - } else { + Elf_Xword compressed_size = 0; + auto compressed_ptr = compression->deflate( + data.get(), convertor, decompressed_size, compressed_size ); + stream.write( compressed_ptr.get(), compressed_size ); + } + else { stream.write( get_data(), get_size() ); } } //------------------------------------------------------------------------------ private: - T header = { 0 }; - Elf_Half index = 0; - std::string name; - std::unique_ptr data; - Elf_Word data_size = 0; - const endianess_convertor* convertor = nullptr; - const address_translator* translator = nullptr; - const std::shared_ptr zlib = nullptr; - bool is_address_set = false; - size_t stream_size = 0; + T header = { 0 }; + Elf_Half index = 0; + std::string name; + std::unique_ptr data; + Elf_Word data_size = 0; + const endianess_convertor* convertor = nullptr; + const address_translator* translator = nullptr; + const std::shared_ptr compression = nullptr; + bool is_address_set = false; + size_t stream_size = 0; }; } // namespace ELFIO diff --git a/elfio/elfio_utils.hpp b/elfio/elfio_utils.hpp index a4c473c..980f888 100644 --- a/elfio/elfio_utils.hpp +++ b/elfio/elfio_utils.hpp @@ -263,12 +263,12 @@ inline void adjust_stream_size( std::ostream& stream, std::streamsize offset ) /** * Consumers should write an implementation of this class and pass an instance of it to the ELFIO::elfio constructor. */ -class wiiu_zlib_interface +class compression_interface { - public: - virtual ~wiiu_zlib_interface() = default; + public: + virtual ~compression_interface() = default; /** - * decompresses a RPX/RPL zlib-compressed section. + * decompresses a compressed section * * @param data the buffer of compressed data * @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness. @@ -276,10 +276,14 @@ class wiiu_zlib_interface * @param decompressed_size a reference to a variable where the decompressed buffer size will be stored. * @returns a smart pointer to the decompressed data. */ - virtual std::unique_ptr inflate(const char *data, const endianess_convertor *convertor, Elf_Xword compressed_size, Elf_Xword &uncompressed_size) const = 0; + virtual std::unique_ptr + inflate( const char* data, + const endianess_convertor* convertor, + Elf_Xword compressed_size, + Elf_Xword& uncompressed_size ) const = 0; - /** - * compresses a RPX/RPL zlib-compressed section. + /** + * compresses a section * * @param data the buffer of uncompressed data * @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness. @@ -287,10 +291,13 @@ class wiiu_zlib_interface * @param compressed_size a reference to a variable where the compressed buffer size will be stored. * @returns a smart pointer to the compressed data. */ - virtual std::unique_ptr deflate(const char *data, const endianess_convertor *convertor, Elf_Xword decompressed_size, Elf_Xword &compressed_size) const = 0; + virtual std::unique_ptr + deflate( const char* data, + const endianess_convertor* convertor, + Elf_Xword decompressed_size, + Elf_Xword& compressed_size ) const = 0; }; - } // namespace ELFIO #endif // ELFIO_UTILS_HPP diff --git a/examples/anonymizer/anonymizer.cpp b/examples/anonymizer/anonymizer.cpp index 09f3635..cc9501c 100644 --- a/examples/anonymizer/anonymizer.cpp +++ b/examples/anonymizer/anonymizer.cpp @@ -94,8 +94,7 @@ int main( int argc, char** argv ) for ( const auto& section : reader.sections ) { if ( section->get_type() == SHT_STRTAB && - std::string( section->get_name() ) == - std::string( ".strtab" ) ) { + std::string( section->get_name() ) == std::string( ".strtab" ) ) { process_string_table( section.get(), filename ); } } diff --git a/tests/ELFIOTest.cpp b/tests/ELFIOTest.cpp index 00ddd0b..8107ca9 100644 --- a/tests/ELFIOTest.cpp +++ b/tests/ELFIOTest.cpp @@ -32,7 +32,7 @@ THE SOFTWARE. using namespace ELFIO; //////////////////////////////////////////////////////////////////////////////// -void checkHeader( elfio& reader, +void checkHeader( const elfio& reader, unsigned char nClass, unsigned char encoding, unsigned char elfVersion, @@ -971,40 +971,51 @@ TEST( ELFIOTest, test_dynamic_64_2 ) EXPECT_EQ( value, 0 ); } -class mock_wiiu_zlib : public wiiu_zlib_interface { - public: - std::unique_ptr inflate(const char *data, const endianess_convertor *convertor, Elf_Xword compressed_size, Elf_Xword &uncompressed_size) const { +class mock_wiiu_compression : public compression_interface +{ + public: + std::unique_ptr + inflate( const char* data, + const endianess_convertor* convertor, + Elf_Xword compressed_size, + Elf_Xword& uncompressed_size ) const override + { uncompressed_size = 2 * compressed_size; - return std::unique_ptr(new char[uncompressed_size+1]); + return std::unique_ptr( new char[uncompressed_size + 1] ); } - std::unique_ptr deflate(const char *data, const endianess_convertor *convertor, Elf_Xword decompressed_size, Elf_Xword &compressed_size) const { + std::unique_ptr deflate( const char* data, + const endianess_convertor* convertor, + Elf_Xword decompressed_size, + Elf_Xword& compressed_size ) const override + { compressed_size = decompressed_size / 2; - return std::unique_ptr(new char[compressed_size+1]); + return std::unique_ptr( new char[compressed_size + 1] ); } }; //////////////////////////////////////////////////////////////////////////////// // Given: a valid RPX file -// When: we load it with no zlib implementation +// When: we load it with no compression implementation // Then: the size returns the raw section size (compressed size) -// When: we load it with a mock zlib implementation -// Then: the size changes to reflect the mock zlib implementation is being called +// When: we load it with a mock compression implementation +// Then: the size changes to reflect the mock compression implementation is being called // // This test does not do any further validation because doing so would require providing -// a real zlib implementation +// a real compression implementation TEST( ELFIOTest, test_rpx ) { - elfio reader(new mock_wiiu_zlib()); - elfio reader_no_zlib; + elfio reader( new mock_wiiu_compression() ); + elfio reader_no_compression; - ASSERT_EQ( reader_no_zlib.load( "elf_examples/helloworld.rpx" ), true ); - section *text1 = reader_no_zlib.sections[1]; - EXPECT_EQ( text1->get_size(), 36744); + ASSERT_EQ( reader_no_compression.load( "elf_examples/helloworld.rpx" ), + true ); + const section* text1 = reader_no_compression.sections[1]; + EXPECT_EQ( text1->get_size(), 36744 ); ASSERT_EQ( reader.load( "elf_examples/helloworld.rpx" ), true ); - section *text2 = reader.sections[1]; - EXPECT_EQ(text2->get_size(), text1->get_size() * 2); + const section* text2 = reader.sections[1]; + EXPECT_EQ( text2->get_size(), text1->get_size() * 2 ); } //////////////////////////////////////////////////////////////////////////////// diff --git a/tests/elf_examples/test_ppc.cpp b/tests/elf_examples/test_ppc.cpp index d07f900..1fa76c0 100644 --- a/tests/elf_examples/test_ppc.cpp +++ b/tests/elf_examples/test_ppc.cpp @@ -2,7 +2,7 @@ int main() { - std::cout << "Hello" << std::endl; - - return 0; + std::cout << "Hello" << std::endl; + + return 0; }