mirror of
https://github.com/serge1/ELFIO.git
synced 2024-11-19 11:14:46 +00:00
Add support for reading Wii U RPX/RPL
== DETAILS The Wii U uses a slightly customized ELF format which uses zlib compression on certain section types. This commit adds the following: - add `SHT_` constants for the custom ELF sections - add `SHF_RPX_DEFLATE` flag used to denote a compressed section - add code in the section `load()` method to detect the `SHF_RPX_DEFLATE` flag and decompress the section
This commit is contained in:
parent
1df77b2495
commit
582d929d9d
@ -529,6 +529,11 @@ 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;
|
||||
|
||||
// Section attribute flags
|
||||
@ -545,6 +550,8 @@ 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;
|
||||
|
@ -28,6 +28,8 @@ THE SOFTWARE.
|
||||
#include <new>
|
||||
#include <limits>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
namespace ELFIO {
|
||||
|
||||
class section
|
||||
@ -214,13 +216,59 @@ template <class T> class section_impl : public section
|
||||
if ( ( 0 != size ) && ( nullptr != data ) ) {
|
||||
stream.seekg(
|
||||
( *translator )[( *convertor )( header.sh_offset )] );
|
||||
stream.read( data.get(), size );
|
||||
if ( static_cast<Elf_Xword>( stream.gcount() ) != size ) {
|
||||
data = nullptr;
|
||||
return false;
|
||||
if(get_flags() & SHF_RPX_DEFLATE) {
|
||||
Elf_Xword uncompressed_size = 0;
|
||||
fixup_size(stream, size, uncompressed_size);
|
||||
|
||||
// reallocate data to be the correct size
|
||||
data.reset( new (std::nothrow) char[size_t(uncompressed_size) + 1]);
|
||||
// create a buffer to hold the compressed bits
|
||||
auto compressed_data = std::unique_ptr<char>(new char[size_t(size)]);
|
||||
if( data == nullptr || compressed_data == nullptr) {
|
||||
std::cerr << "failed to allocate memory buffers for decompression" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
set_size(uncompressed_size);
|
||||
// read rest of data into data buffer
|
||||
stream.read( compressed_data.get(), size);
|
||||
|
||||
z_stream s = { 0 };
|
||||
int z_result = 0;
|
||||
|
||||
s.zalloc = Z_NULL;
|
||||
s.zfree = Z_NULL;
|
||||
s.opaque = Z_NULL;
|
||||
|
||||
if(Z_OK != (z_result = inflateInit_(&s, ZLIB_VERSION, sizeof(s)))) {
|
||||
std::cerr << "error initializing zlib: " << z_result << std::endl;
|
||||
data = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
s.avail_in = size;
|
||||
s.next_in = (Bytef *)compressed_data.get();
|
||||
|
||||
s.avail_out = uncompressed_size;
|
||||
s.next_out = (Bytef *)data.get();
|
||||
|
||||
z_result = inflate(&s, Z_FINISH);
|
||||
inflateEnd(&s);
|
||||
if (z_result != Z_OK && z_result != Z_STREAM_END) {
|
||||
std::cerr << "error decompressing section: " << z_result << std::endl;
|
||||
data = nullptr;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
stream.read( data.get(), size );
|
||||
if ( static_cast<Elf_Xword>( stream.gcount() ) != size ) {
|
||||
data = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
data.get()[size] =
|
||||
0; // Ensure data is ended with 0 to avoid oob read
|
||||
// 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_size = decltype( data_size )( size );
|
||||
}
|
||||
else {
|
||||
@ -250,6 +298,14 @@ template <class T> class section_impl : public section
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
void fixup_size(std::istream& stream, Elf_Xword& compressed_size, Elf_Xword& uncompressed_size) {
|
||||
uint32_t tmp = 0;
|
||||
stream.read((char *)&tmp, 4);
|
||||
tmp = (*convertor)(tmp);
|
||||
|
||||
uncompressed_size = static_cast<Elf_Xword>(tmp);
|
||||
compressed_size = get_size() - 4;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void save_header( std::ostream& stream, std::streampos header_offset ) const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user