mirror of
https://github.com/wiiu-env/wut.git
synced 2025-02-03 00:12:35 +01:00
tools: Add be_val.h
This commit is contained in:
parent
7e788f47af
commit
09606f873e
419
tools/common/be_val.h
Normal file
419
tools/common/be_val.h
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utils.h"
|
||||||
|
#include "type_traits.h"
|
||||||
|
#include <fmt/ostream.h>
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
class be_val
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static_assert(!std::is_array<Type>::value,
|
||||||
|
"be_val invalid type: array");
|
||||||
|
|
||||||
|
static_assert(!std::is_pointer<Type>::value,
|
||||||
|
"be_val invalid type: pointer");
|
||||||
|
|
||||||
|
static_assert(sizeof(Type) == 1 || sizeof(Type) == 2 || sizeof(Type) == 4 || sizeof(Type) == 8,
|
||||||
|
"be_val invalid type size");
|
||||||
|
|
||||||
|
using value_type = Type;
|
||||||
|
|
||||||
|
be_val() = default;
|
||||||
|
|
||||||
|
be_val(const value_type &value) :
|
||||||
|
mStorage(byte_swap(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type value() const
|
||||||
|
{
|
||||||
|
return byte_swap(mStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(value_type value)
|
||||||
|
{
|
||||||
|
mStorage = byte_swap(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator value_type() const
|
||||||
|
{
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T = Type,
|
||||||
|
typename = typename std::enable_if<std::is_convertible<T, bool>::value ||
|
||||||
|
std::is_constructible<bool, T>::value
|
||||||
|
>::type>
|
||||||
|
explicit operator bool() const
|
||||||
|
{
|
||||||
|
return static_cast<bool>(value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = typename std::enable_if<std::is_convertible<Type, OtherType>::value ||
|
||||||
|
std::is_constructible<OtherType, Type>::value ||
|
||||||
|
std::is_convertible<Type, typename safe_underlying_type<OtherType>::type>::value
|
||||||
|
>::type>
|
||||||
|
explicit operator OtherType() const
|
||||||
|
{
|
||||||
|
return static_cast<OtherType>(value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = typename std::enable_if<std::is_constructible<value_type, const OtherType &>::value ||
|
||||||
|
std::is_convertible<const OtherType &, value_type>::value>::type>
|
||||||
|
be_val & operator =(const OtherType &other)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
||||||
|
setValue(value_type { other });
|
||||||
|
} else {
|
||||||
|
setValue(static_cast<value_type>(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = typename std::enable_if<std::is_constructible<value_type, const OtherType &>::value ||
|
||||||
|
std::is_convertible<const OtherType &, value_type>::value>::type>
|
||||||
|
be_val & operator =(OtherType &&other)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
||||||
|
setValue(value_type { std::forward<OtherType>(other) });
|
||||||
|
} else {
|
||||||
|
setValue(static_cast<value_type>(std::forward<OtherType>(other)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = typename std::enable_if<std::is_convertible<const OtherType &, value_type>::value ||
|
||||||
|
std::is_constructible<value_type, const OtherType &>::value>::type>
|
||||||
|
be_val & operator =(const be_val<OtherType> &other)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
||||||
|
setValue(value_type { other.value() });
|
||||||
|
} else {
|
||||||
|
setValue(static_cast<value_type>(other.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = typename std::enable_if<std::is_convertible<const OtherType &, value_type>::value ||
|
||||||
|
std::is_constructible<value_type, const OtherType &>::value>::type>
|
||||||
|
be_val & operator =(be_val<OtherType> &&other)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
||||||
|
setValue(value_type { other.value() });
|
||||||
|
} else {
|
||||||
|
setValue(static_cast<value_type>(other.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator ==(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator ==(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator !=(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator !=(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() != other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator >=(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator >=(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() >= other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator <=(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator <=(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() <= other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator >(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator >(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() > other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator <(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator <(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() < other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto operator +()
|
||||||
|
-> decltype(std::declval<const K>(). operator+()) const
|
||||||
|
{
|
||||||
|
return +value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto operator -()
|
||||||
|
-> decltype(std::declval<const K>(). operator-()) const
|
||||||
|
{
|
||||||
|
return -value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator +(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator +(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() + other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator -(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator -(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() - other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator *(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator *(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() * other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator /(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator /(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() / other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator %(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator %(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() % other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator |(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator |(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() | other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator &(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator &(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() & other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator ^(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator ^(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() ^ other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator <<(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator <<(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() << other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType, typename K = value_type>
|
||||||
|
auto operator >>(const OtherType &other)
|
||||||
|
-> decltype(std::declval<const K>().operator >>(std::declval<const OtherType>())) const
|
||||||
|
{
|
||||||
|
return value() >> other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() + std::declval<const OtherType>())>
|
||||||
|
be_val &operator +=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = value() + other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() - std::declval<const OtherType>())>
|
||||||
|
be_val &operator -=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = value() - other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() * std::declval<const OtherType>())>
|
||||||
|
be_val &operator *=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = value() * other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() / std::declval<const OtherType>())>
|
||||||
|
be_val &operator /=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = value() / other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() % std::declval<const OtherType>())>
|
||||||
|
be_val &operator %=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = value() % other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() | std::declval<const OtherType>())>
|
||||||
|
be_val &operator |=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = static_cast<Type>(value() | other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() & std::declval<const OtherType>())>
|
||||||
|
be_val &operator &=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = static_cast<Type>(value() & other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() ^ std::declval<const OtherType>())>
|
||||||
|
be_val &operator ^=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = static_cast<Type>(value() ^ other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() << std::declval<const OtherType>())>
|
||||||
|
be_val &operator <<=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = value() << other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OtherType,
|
||||||
|
typename = decltype(std::declval<const value_type>() >> std::declval<const OtherType>())>
|
||||||
|
be_val &operator >>=(const OtherType &other)
|
||||||
|
{
|
||||||
|
*this = value() >> other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T = Type,
|
||||||
|
typename = decltype(std::declval<const T>() + 1)>
|
||||||
|
be_val &operator ++()
|
||||||
|
{
|
||||||
|
setValue(value() + 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T = Type,
|
||||||
|
typename = decltype(std::declval<const T>() + 1)>
|
||||||
|
be_val operator ++(int)
|
||||||
|
{
|
||||||
|
auto before = *this;
|
||||||
|
setValue(value() + 1);
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T = Type,
|
||||||
|
typename = decltype(std::declval<const T>() - 1)>
|
||||||
|
be_val &operator --()
|
||||||
|
{
|
||||||
|
setValue(value() - 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T = Type,
|
||||||
|
typename = decltype(std::declval<const T>() - 1)>
|
||||||
|
be_val operator --(int)
|
||||||
|
{
|
||||||
|
auto before = *this;
|
||||||
|
setValue(value() - 1);
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IndexType,
|
||||||
|
typename K = value_type>
|
||||||
|
auto operator [](const IndexType &index)
|
||||||
|
-> decltype(std::declval<K>().operator [](std::declval<IndexType>()))
|
||||||
|
{
|
||||||
|
return value().operator [](index);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto operator ->()
|
||||||
|
-> decltype(std::declval<K>().operator ->())
|
||||||
|
{
|
||||||
|
return value().operator ->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto operator ->() const
|
||||||
|
-> decltype(std::declval<const K>().operator ->())
|
||||||
|
{
|
||||||
|
return value().operator ->();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto operator *()
|
||||||
|
-> decltype(std::declval<K>().operator *())
|
||||||
|
{
|
||||||
|
return value().operator *();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto operator *() const
|
||||||
|
-> decltype(std::declval<const K>().operator *())
|
||||||
|
{
|
||||||
|
return value().operator ->();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to access FunctionPointer::getAddress
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto getAddress()
|
||||||
|
-> decltype(std::declval<const K>().getAddress()) const
|
||||||
|
{
|
||||||
|
return value().getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to access Pointer::getRawPointer
|
||||||
|
template<typename K = value_type>
|
||||||
|
auto getRawPointer()
|
||||||
|
-> decltype(std::declval<const K>().getRawPointer()) const
|
||||||
|
{
|
||||||
|
return value().getRawPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Please use virt_addrof or phys_addrof instead
|
||||||
|
auto operator &() = delete;
|
||||||
|
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const be_val &b) {
|
||||||
|
return os << b.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type mStorage;
|
||||||
|
};
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "be_val.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@ -202,67 +203,67 @@ static const unsigned HeaderMagic = 0x7f454c46;
|
|||||||
|
|
||||||
struct Header
|
struct Header
|
||||||
{
|
{
|
||||||
uint32_t magic; // File identification.
|
be_val<uint32_t> magic; // File identification.
|
||||||
uint8_t fileClass; // File class.
|
be_val<uint8_t> fileClass; // File class.
|
||||||
uint8_t encoding; // Data encoding.
|
be_val<uint8_t> encoding; // Data encoding.
|
||||||
uint8_t elfVersion; // File version.
|
be_val<uint8_t> elfVersion; // File version.
|
||||||
uint16_t abi; // OS/ABI identification. (EABI_*)
|
be_val<uint16_t> abi; // OS/ABI identification. (EABI_*)
|
||||||
uint8_t pad[7];
|
be_val<uint8_t> pad[7];
|
||||||
|
|
||||||
uint16_t type; // Type of file (ET_*)
|
be_val<uint16_t> type; // Type of file (ET_*)
|
||||||
uint16_t machine; // Required architecture for this file (EM_*)
|
be_val<uint16_t> machine; // Required architecture for this file (EM_*)
|
||||||
uint32_t version; // Must be equal to 1
|
be_val<uint32_t> version; // Must be equal to 1
|
||||||
uint32_t entry; // Address to jump to in order to start program
|
be_val<uint32_t> entry; // Address to jump to in order to start program
|
||||||
uint32_t phoff; // Program header table's file offset, in bytes
|
be_val<uint32_t> phoff; // Program header table's file offset, in bytes
|
||||||
uint32_t shoff; // Section header table's file offset, in bytes
|
be_val<uint32_t> shoff; // Section header table's file offset, in bytes
|
||||||
uint32_t flags; // Processor-specific flags
|
be_val<uint32_t> flags; // Processor-specific flags
|
||||||
uint16_t ehsize; // Size of ELF header, in bytes
|
be_val<uint16_t> ehsize; // Size of ELF header, in bytes
|
||||||
uint16_t phentsize; // Size of an entry in the program header table
|
be_val<uint16_t> phentsize; // Size of an entry in the program header table
|
||||||
uint16_t phnum; // Number of entries in the program header table
|
be_val<uint16_t> phnum; // Number of entries in the program header table
|
||||||
uint16_t shentsize; // Size of an entry in the section header table
|
be_val<uint16_t> shentsize; // Size of an entry in the section header table
|
||||||
uint16_t shnum; // Number of entries in the section header table
|
be_val<uint16_t> shnum; // Number of entries in the section header table
|
||||||
uint16_t shstrndx; // Sect hdr table index of sect name string table
|
be_val<uint16_t> shstrndx; // Sect hdr table index of sect name string table
|
||||||
};
|
};
|
||||||
CHECK_SIZE(Header, 0x34);
|
CHECK_SIZE(Header, 0x34);
|
||||||
|
|
||||||
struct SectionHeader
|
struct SectionHeader
|
||||||
{
|
{
|
||||||
uint32_t name; // Section name (index into string table)
|
be_val<uint32_t> name; // Section name (index into string table)
|
||||||
uint32_t type; // Section type (SHT_*)
|
be_val<uint32_t> type; // Section type (SHT_*)
|
||||||
uint32_t flags; // Section flags (SHF_*)
|
be_val<uint32_t> flags; // Section flags (SHF_*)
|
||||||
uint32_t addr; // Address where section is to be loaded
|
be_val<uint32_t> addr; // Address where section is to be loaded
|
||||||
uint32_t offset; // File offset of section data, in bytes
|
be_val<uint32_t> offset; // File offset of section data, in bytes
|
||||||
uint32_t size; // Size of section, in bytes
|
be_val<uint32_t> size; // Size of section, in bytes
|
||||||
uint32_t link; // Section type-specific header table index link
|
be_val<uint32_t> link; // Section type-specific header table index link
|
||||||
uint32_t info; // Section type-specific extra information
|
be_val<uint32_t> info; // Section type-specific extra information
|
||||||
uint32_t addralign; // Section address alignment
|
be_val<uint32_t> addralign; // Section address alignment
|
||||||
uint32_t entsize; // Size of records contained within the section
|
be_val<uint32_t> entsize; // Size of records contained within the section
|
||||||
};
|
};
|
||||||
CHECK_SIZE(SectionHeader, 0x28);
|
CHECK_SIZE(SectionHeader, 0x28);
|
||||||
|
|
||||||
struct Symbol
|
struct Symbol
|
||||||
{
|
{
|
||||||
uint32_t name; // Symbol name (index into string table)
|
be_val<uint32_t> name; // Symbol name (index into string table)
|
||||||
uint32_t value; // Value or address associated with the symbol
|
be_val<uint32_t> value; // Value or address associated with the symbol
|
||||||
uint32_t size; // Size of the symbol
|
be_val<uint32_t> size; // Size of the symbol
|
||||||
uint8_t info; // Symbol's type and binding attributes
|
be_val<uint8_t> info; // Symbol's type and binding attributes
|
||||||
uint8_t other; // Must be zero; reserved
|
be_val<uint8_t> other; // Must be zero; reserved
|
||||||
uint16_t shndx; // Which section (header table index) it's defined in (SHN_*)
|
be_val<uint16_t> shndx; // Which section (header table index) it's defined in (SHN_*)
|
||||||
};
|
};
|
||||||
CHECK_SIZE(Symbol, 0x10);
|
CHECK_SIZE(Symbol, 0x10);
|
||||||
|
|
||||||
struct Rela
|
struct Rela
|
||||||
{
|
{
|
||||||
uint32_t offset;
|
be_val<uint32_t> offset;
|
||||||
uint32_t info;
|
be_val<uint32_t> info;
|
||||||
int32_t addend;
|
be_val<int32_t> addend;
|
||||||
};
|
};
|
||||||
CHECK_SIZE(Rela, 0x0C);
|
CHECK_SIZE(Rela, 0x0C);
|
||||||
|
|
||||||
struct RplImport
|
struct RplImport
|
||||||
{
|
{
|
||||||
uint32_t count;
|
be_val<uint32_t> count;
|
||||||
uint32_t signature;
|
be_val<uint32_t> signature;
|
||||||
char name[1];
|
char name[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,48 +271,48 @@ struct RplExport
|
|||||||
{
|
{
|
||||||
struct Export
|
struct Export
|
||||||
{
|
{
|
||||||
uint32_t value;
|
be_val<uint32_t> value;
|
||||||
uint32_t name;
|
be_val<uint32_t> name;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t count;
|
be_val<uint32_t> count;
|
||||||
uint32_t signature;
|
be_val<uint32_t> signature;
|
||||||
Export exports[1];
|
Export exports[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RplCrc
|
struct RplCrc
|
||||||
{
|
{
|
||||||
uint32_t crc;
|
be_val<uint32_t> crc;
|
||||||
};
|
};
|
||||||
CHECK_SIZE(RplCrc, 0x04);
|
CHECK_SIZE(RplCrc, 0x04);
|
||||||
|
|
||||||
struct RplFileInfo
|
struct RplFileInfo
|
||||||
{
|
{
|
||||||
uint32_t version;
|
be_val<uint32_t> version;
|
||||||
uint32_t textSize;
|
be_val<uint32_t> textSize;
|
||||||
uint32_t textAlign;
|
be_val<uint32_t> textAlign;
|
||||||
uint32_t dataSize;
|
be_val<uint32_t> dataSize;
|
||||||
uint32_t dataAlign;
|
be_val<uint32_t> dataAlign;
|
||||||
uint32_t loadSize;
|
be_val<uint32_t> loadSize;
|
||||||
uint32_t loadAlign;
|
be_val<uint32_t> loadAlign;
|
||||||
uint32_t tempSize;
|
be_val<uint32_t> tempSize;
|
||||||
uint32_t trampAdjust;
|
be_val<uint32_t> trampAdjust;
|
||||||
uint32_t sdaBase;
|
be_val<uint32_t> sdaBase;
|
||||||
uint32_t sda2Base;
|
be_val<uint32_t> sda2Base;
|
||||||
uint32_t stackSize;
|
be_val<uint32_t> stackSize;
|
||||||
uint32_t filename;
|
be_val<uint32_t> filename;
|
||||||
uint32_t flags;
|
be_val<uint32_t> flags;
|
||||||
uint32_t heapSize;
|
be_val<uint32_t> heapSize;
|
||||||
uint32_t tagOffset;
|
be_val<uint32_t> tagOffset;
|
||||||
uint32_t minVersion;
|
be_val<uint32_t> minVersion;
|
||||||
int32_t compressionLevel;
|
be_val<int32_t> compressionLevel;
|
||||||
uint32_t trampAddition;
|
be_val<uint32_t> trampAddition;
|
||||||
uint32_t fileInfoPad;
|
be_val<uint32_t> fileInfoPad;
|
||||||
uint32_t cafeSdkVersion;
|
be_val<uint32_t> cafeSdkVersion;
|
||||||
uint32_t cafeSdkRevision;
|
be_val<uint32_t> cafeSdkRevision;
|
||||||
uint16_t tlsModuleIndex;
|
be_val<uint16_t> tlsModuleIndex;
|
||||||
uint16_t tlsAlignShift;
|
be_val<uint16_t> tlsAlignShift;
|
||||||
uint32_t runtimeFileInfoSize;
|
be_val<uint32_t> runtimeFileInfoSize;
|
||||||
};
|
};
|
||||||
CHECK_SIZE(RplFileInfo, 0x60);
|
CHECK_SIZE(RplFileInfo, 0x60);
|
||||||
|
|
||||||
|
22
tools/common/type_traits.h
Normal file
22
tools/common/type_traits.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
// Same as std::underlying_type but works for non-enum Types
|
||||||
|
template<class T, bool = std::is_enum<T>::value>
|
||||||
|
struct safe_underlying_type : std::underlying_type<T> { };
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct safe_underlying_type<T, false>
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Maps bool value to a std::bool_constant type
|
||||||
|
template<bool>
|
||||||
|
struct is_true;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct is_true<false> : std::false_type { };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct is_true<true> : std::true_type { };
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
@ -27,73 +27,6 @@ struct ElfFile
|
|||||||
std::vector<std::unique_ptr<Section>> sections;
|
std::vector<std::unique_ptr<Section>> sections;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
byte_swap(elf::Header &header)
|
|
||||||
{
|
|
||||||
header.magic = byte_swap(header.magic);
|
|
||||||
header.abi = byte_swap(header.abi);
|
|
||||||
header.type = byte_swap(header.type);
|
|
||||||
header.machine = byte_swap(header.machine);
|
|
||||||
header.version = byte_swap(header.version);
|
|
||||||
header.entry = byte_swap(header.entry);
|
|
||||||
header.phoff = byte_swap(header.phoff);
|
|
||||||
header.shoff = byte_swap(header.shoff);
|
|
||||||
header.flags = byte_swap(header.flags);
|
|
||||||
header.ehsize = byte_swap(header.ehsize);
|
|
||||||
header.phentsize = byte_swap(header.phentsize);
|
|
||||||
header.phnum = byte_swap(header.phnum);
|
|
||||||
header.shentsize = byte_swap(header.shentsize);
|
|
||||||
header.shnum = byte_swap(header.shnum);
|
|
||||||
header.shstrndx = byte_swap(header.shstrndx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
byte_swap(elf::SectionHeader &header)
|
|
||||||
{
|
|
||||||
header.name = byte_swap(header.name);
|
|
||||||
header.type = byte_swap(header.type);
|
|
||||||
header.flags = byte_swap(header.flags);
|
|
||||||
header.addr = byte_swap(header.addr);
|
|
||||||
header.offset = byte_swap(header.offset);
|
|
||||||
header.size = byte_swap(header.size);
|
|
||||||
header.link = byte_swap(header.link);
|
|
||||||
header.info = byte_swap(header.info);
|
|
||||||
header.addralign = byte_swap(header.addralign);
|
|
||||||
header.entsize = byte_swap(header.entsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
byte_swap(elf::RplFileInfo &info)
|
|
||||||
{
|
|
||||||
info.version = byte_swap(info.version);
|
|
||||||
info.textSize = byte_swap(info.textSize);
|
|
||||||
info.textAlign = byte_swap(info.textAlign);
|
|
||||||
info.dataSize = byte_swap(info.dataSize);
|
|
||||||
info.dataAlign = byte_swap(info.dataAlign);
|
|
||||||
info.loadSize = byte_swap(info.loadSize);
|
|
||||||
info.loadAlign = byte_swap(info.loadAlign);
|
|
||||||
info.tempSize = byte_swap(info.tempSize);
|
|
||||||
info.trampAdjust = byte_swap(info.trampAdjust);
|
|
||||||
info.sdaBase = byte_swap(info.sdaBase);
|
|
||||||
info.sda2Base = byte_swap(info.sda2Base);
|
|
||||||
info.stackSize = byte_swap(info.stackSize);
|
|
||||||
info.filename = byte_swap(info.filename);
|
|
||||||
info.flags = byte_swap(info.flags);
|
|
||||||
info.heapSize = byte_swap(info.heapSize);
|
|
||||||
info.tagOffset = byte_swap(info.tagOffset);
|
|
||||||
info.minVersion = byte_swap(info.minVersion);
|
|
||||||
info.compressionLevel = byte_swap(info.compressionLevel);
|
|
||||||
info.trampAddition = byte_swap(info.trampAddition);
|
|
||||||
info.fileInfoPad = byte_swap(info.fileInfoPad);
|
|
||||||
info.cafeSdkVersion = byte_swap(info.cafeSdkVersion);
|
|
||||||
info.cafeSdkRevision = byte_swap(info.cafeSdkRevision);
|
|
||||||
info.tlsModuleIndex = byte_swap(info.tlsModuleIndex);
|
|
||||||
info.tlsAlignShift = byte_swap(info.tlsAlignShift);
|
|
||||||
info.runtimeFileInfoSize = byte_swap(info.runtimeFileInfoSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
getSectionIndex(ElfFile &file, const char *name)
|
getSectionIndex(ElfFile &file, const char *name)
|
||||||
{
|
{
|
||||||
@ -158,7 +91,6 @@ readElf(ElfFile &file, const std::string &filename)
|
|||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
in.read(reinterpret_cast<char *>(&file.header), sizeof(elf::Header));
|
in.read(reinterpret_cast<char *>(&file.header), sizeof(elf::Header));
|
||||||
byte_swap(file.header);
|
|
||||||
|
|
||||||
if (file.header.magic != elf::HeaderMagic) {
|
if (file.header.magic != elf::HeaderMagic) {
|
||||||
fmt::print("Invalid ELF magic header {:08X}", elf::HeaderMagic);
|
fmt::print("Invalid ELF magic header {:08X}", elf::HeaderMagic);
|
||||||
@ -193,7 +125,6 @@ readElf(ElfFile &file, const std::string &filename)
|
|||||||
auto §ion = *file.sections.back();
|
auto §ion = *file.sections.back();
|
||||||
|
|
||||||
in.read(reinterpret_cast<char *>(§ion.header), sizeof(elf::SectionHeader));
|
in.read(reinterpret_cast<char *>(§ion.header), sizeof(elf::SectionHeader));
|
||||||
byte_swap(section.header);
|
|
||||||
|
|
||||||
if (!section.header.size || section.header.type == elf::SHT_NOBITS) {
|
if (!section.header.size || section.header.type == elf::SHT_NOBITS) {
|
||||||
continue;
|
continue;
|
||||||
@ -373,9 +304,9 @@ reorderSectionIndex(ElfFile &file)
|
|||||||
auto symbols = reinterpret_cast<elf::Symbol *>(section->data.data());
|
auto symbols = reinterpret_cast<elf::Symbol *>(section->data.data());
|
||||||
auto numSymbols = section->data.size() / sizeof(elf::Symbol);
|
auto numSymbols = section->data.size() / sizeof(elf::Symbol);
|
||||||
for (auto i = 0u; i < numSymbols; ++i) {
|
for (auto i = 0u; i < numSymbols; ++i) {
|
||||||
auto shndx = byte_swap(symbols[i].shndx);
|
auto shndx = symbols[i].shndx;
|
||||||
if (shndx < elf::SHN_LORESERVE) {
|
if (shndx < elf::SHN_LORESERVE) {
|
||||||
symbols[i].shndx = byte_swap<uint16_t>(mapOldToNew[shndx]);
|
symbols[i].shndx = mapOldToNew[shndx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -449,8 +380,6 @@ generateFileInfoSection(ElfFile &file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_swap(info);
|
|
||||||
|
|
||||||
auto section = std::make_unique<ElfFile::Section>();
|
auto section = std::make_unique<ElfFile::Section>();
|
||||||
section->header.name = 0;
|
section->header.name = 0;
|
||||||
section->header.type = elf::SHT_RPL_FILEINFO;
|
section->header.type = elf::SHT_RPL_FILEINFO;
|
||||||
@ -485,7 +414,7 @@ generateCrcSection(ElfFile &file)
|
|||||||
crc = crc32(crc, reinterpret_cast<Bytef *>(section->data.data()), section->data.size());
|
crc = crc32(crc, reinterpret_cast<Bytef *>(section->data.data()), section->data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
crcs.push_back(byte_swap(crc));
|
crcs.push_back(crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto section = std::make_unique<ElfFile::Section>();
|
auto section = std::make_unique<ElfFile::Section>();
|
||||||
@ -517,12 +446,7 @@ getSymbol(ElfFile::Section §ion, size_t index, elf::Symbol &symbol)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol.name = byte_swap(symbols[index].name);
|
symbol = symbols[index];
|
||||||
symbol.value = byte_swap(symbols[index].value);
|
|
||||||
symbol.size = byte_swap(symbols[index].size);
|
|
||||||
symbol.info = byte_swap(symbols[index].info);
|
|
||||||
symbol.other = byte_swap(symbols[index].other);
|
|
||||||
symbol.shndx = byte_swap(symbols[index].shndx);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,9 +478,9 @@ fixRelocations(ElfFile &file)
|
|||||||
auto rels = reinterpret_cast<elf::Rela *>(section->data.data());
|
auto rels = reinterpret_cast<elf::Rela *>(section->data.data());
|
||||||
auto numRels = section->data.size() / sizeof(elf::Rela);
|
auto numRels = section->data.size() / sizeof(elf::Rela);
|
||||||
for (auto i = 0u; i < numRels; ++i) {
|
for (auto i = 0u; i < numRels; ++i) {
|
||||||
auto info = byte_swap(rels[i].info);
|
auto info = rels[i].info;
|
||||||
auto addend = byte_swap(rels[i].addend);
|
auto addend = rels[i].addend;
|
||||||
auto offset = byte_swap(rels[i].offset);
|
auto offset = rels[i].offset;
|
||||||
auto index = info >> 8;
|
auto index = info >> 8;
|
||||||
auto type = info & 0xFF;
|
auto type = info & 0xFF;
|
||||||
|
|
||||||
@ -595,14 +519,14 @@ fixRelocations(ElfFile &file)
|
|||||||
auto &newRel = newRelocations.back();
|
auto &newRel = newRelocations.back();
|
||||||
|
|
||||||
// Modify current relocation to R_PPC_GHS_REL16_LO
|
// Modify current relocation to R_PPC_GHS_REL16_LO
|
||||||
rels[i].info = byte_swap<uint32_t>((index << 8) | elf::R_PPC_GHS_REL16_LO);
|
rels[i].info = (index << 8) | elf::R_PPC_GHS_REL16_LO;
|
||||||
rels[i].addend = byte_swap<int32_t>(addend);
|
rels[i].addend = addend;
|
||||||
rels[i].offset = byte_swap<uint32_t>(offset);
|
rels[i].offset = offset;
|
||||||
|
|
||||||
// Create a R_PPC_GHS_REL16_HI
|
// Create a R_PPC_GHS_REL16_HI
|
||||||
newRel.info = byte_swap<uint32_t>((index << 8) | elf::R_PPC_GHS_REL16_HI);
|
newRel.info = (index << 8) | elf::R_PPC_GHS_REL16_HI;
|
||||||
newRel.addend = byte_swap<int32_t>(addend + 2);
|
newRel.addend = addend + 2;
|
||||||
newRel.offset = byte_swap<uint32_t>(offset + 2);
|
newRel.offset = offset + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -692,8 +616,8 @@ relocateSection(ElfFile &file,
|
|||||||
auto symbols = reinterpret_cast<elf::Symbol *>(symSection->data.data());
|
auto symbols = reinterpret_cast<elf::Symbol *>(symSection->data.data());
|
||||||
auto numSymbols = symSection->data.size() / sizeof(elf::Symbol);
|
auto numSymbols = symSection->data.size() / sizeof(elf::Symbol);
|
||||||
for (auto i = 0u; i < numSymbols; ++i) {
|
for (auto i = 0u; i < numSymbols; ++i) {
|
||||||
auto type = byte_swap(symbols[i].info) & 0xf;
|
auto type = symbols[i].info & 0xf;
|
||||||
auto value = byte_swap(symbols[i].value);
|
auto value = symbols[i].value;
|
||||||
|
|
||||||
// Only relocate data, func, section symbols
|
// Only relocate data, func, section symbols
|
||||||
if (type != elf::STT_OBJECT &&
|
if (type != elf::STT_OBJECT &&
|
||||||
@ -703,7 +627,7 @@ relocateSection(ElfFile &file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (value >= oldSectionAddress && value <= oldSectionAddressEnd) {
|
if (value >= oldSectionAddress && value <= oldSectionAddressEnd) {
|
||||||
symbols[i].value = byte_swap<uint32_t>((value - oldSectionAddress) + newSectionAddress);
|
symbols[i].value = (value - oldSectionAddress) + newSectionAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -717,10 +641,10 @@ relocateSection(ElfFile &file,
|
|||||||
auto rela = reinterpret_cast<elf::Rela *>(relaSection->data.data());
|
auto rela = reinterpret_cast<elf::Rela *>(relaSection->data.data());
|
||||||
auto numRelas = relaSection->data.size() / sizeof(elf::Rela);
|
auto numRelas = relaSection->data.size() / sizeof(elf::Rela);
|
||||||
for (auto i = 0u; i < numRelas; ++i) {
|
for (auto i = 0u; i < numRelas; ++i) {
|
||||||
auto offset = byte_swap(rela[i].offset);
|
auto offset = rela[i].offset;
|
||||||
|
|
||||||
if (offset >= oldSectionAddress && offset <= oldSectionAddressEnd) {
|
if (offset >= oldSectionAddress && offset <= oldSectionAddressEnd) {
|
||||||
rela[i].offset = byte_swap<uint32_t>((offset - oldSectionAddress) + newSectionAddress);
|
rela[i].offset = (offset - oldSectionAddress) + newSectionAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -925,13 +849,6 @@ writeRpl(ElfFile &file, const std::string &filename)
|
|||||||
{
|
{
|
||||||
auto shoff = file.header.shoff;
|
auto shoff = file.header.shoff;
|
||||||
|
|
||||||
// Swap back file & section header to big endian before writing
|
|
||||||
byte_swap(file.header);
|
|
||||||
|
|
||||||
for (auto §ion : file.sections) {
|
|
||||||
byte_swap(section->header);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the file out
|
// Write the file out
|
||||||
std::ofstream out { filename, std::ofstream::binary };
|
std::ofstream out { filename, std::ofstream::binary };
|
||||||
|
|
||||||
@ -953,7 +870,7 @@ writeRpl(ElfFile &file, const std::string &filename)
|
|||||||
// Write sections
|
// Write sections
|
||||||
for (const auto §ion : file.sections) {
|
for (const auto §ion : file.sections) {
|
||||||
if (section->data.size()) {
|
if (section->data.size()) {
|
||||||
out.seekp(byte_swap(section->header.offset), std::ios::beg);
|
out.seekp(section->header.offset, std::ios::beg);
|
||||||
out.write(section->data.data(), section->data.size());
|
out.write(section->data.data(), section->data.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -979,11 +896,6 @@ int main(int argc, const char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* From here onwards file.header and section.header is in little endian,
|
|
||||||
* everything else remains in big endian!
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!fixBssNoBits(elf)) {
|
if (!fixBssNoBits(elf)) {
|
||||||
fmt::print("ERROR: fixBssNoBits failed");
|
fmt::print("ERROR: fixBssNoBits failed");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
@ -34,15 +36,6 @@ trim(std::string &s)
|
|||||||
rtrim(s);
|
rtrim(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
|
||||||
byte_swap(uint32_t v)
|
|
||||||
{
|
|
||||||
return ((v >> 24) & 0xff) |
|
|
||||||
((v << 8) & 0xff0000) |
|
|
||||||
((v >> 8) & 0xff00) |
|
|
||||||
((v << 24) & 0xff000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ReadMode
|
enum class ReadMode
|
||||||
{
|
{
|
||||||
INVALID,
|
INVALID,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user