diff --git a/tools/common/be_val.h b/tools/common/be_val.h
new file mode 100644
index 0000000..58262c0
--- /dev/null
+++ b/tools/common/be_val.h
@@ -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;
+};
diff --git a/tools/common/elf.h b/tools/common/elf.h
index e831413..0cbf7ca 100644
--- a/tools/common/elf.h
+++ b/tools/common/elf.h
@@ -1,5 +1,6 @@
 #pragma once
 #include <cstdint>
+#include "be_val.h"
 #include "utils.h"
 
 #pragma pack(push, 1)
@@ -202,67 +203,67 @@ static const unsigned HeaderMagic = 0x7f454c46;
 
 struct Header
 {
-   uint32_t magic;       // File identification.
-   uint8_t fileClass;    // File class.
-   uint8_t encoding;     // Data encoding.
-   uint8_t elfVersion;   // File version.
-   uint16_t abi;         // OS/ABI identification. (EABI_*)
-   uint8_t pad[7];
+   be_val<uint32_t> magic;       // File identification.
+   be_val<uint8_t> fileClass;    // File class.
+   be_val<uint8_t> encoding;     // Data encoding.
+   be_val<uint8_t> elfVersion;   // File version.
+   be_val<uint16_t> abi;         // OS/ABI identification. (EABI_*)
+   be_val<uint8_t> pad[7];
 
-   uint16_t type;        // Type of file (ET_*)
-   uint16_t machine;     // Required architecture for this file (EM_*)
-   uint32_t version;     // Must be equal to 1
-   uint32_t entry;       // Address to jump to in order to start program
-   uint32_t phoff;       // Program header table's file offset, in bytes
-   uint32_t shoff;       // Section header table's file offset, in bytes
-   uint32_t flags;       // Processor-specific flags
-   uint16_t ehsize;      // Size of ELF header, in bytes
-   uint16_t phentsize;   // Size of an entry in the program header table
-   uint16_t phnum;       // Number of entries in the program header table
-   uint16_t shentsize;   // Size of an entry in the section header table
-   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> type;        // Type of file (ET_*)
+   be_val<uint16_t> machine;     // Required architecture for this file (EM_*)
+   be_val<uint32_t> version;     // Must be equal to 1
+   be_val<uint32_t> entry;       // Address to jump to in order to start program
+   be_val<uint32_t> phoff;       // Program header table's file offset, in bytes
+   be_val<uint32_t> shoff;       // Section header table's file offset, in bytes
+   be_val<uint32_t> flags;       // Processor-specific flags
+   be_val<uint16_t> ehsize;      // Size of ELF header, in bytes
+   be_val<uint16_t> phentsize;   // Size of an entry in the program header table
+   be_val<uint16_t> phnum;       // Number of entries in the program header table
+   be_val<uint16_t> shentsize;   // Size of an entry in the section header table
+   be_val<uint16_t> shnum;       // Number of entries in the section header table
+   be_val<uint16_t> shstrndx;    // Sect hdr table index of sect name string table
 };
 CHECK_SIZE(Header, 0x34);
 
 struct SectionHeader
 {
-   uint32_t name;      // Section name (index into string table)
-   uint32_t type;      // Section type (SHT_*)
-   uint32_t flags;     // Section flags (SHF_*)
-   uint32_t addr;      // Address where section is to be loaded
-   uint32_t offset;    // File offset of section data, in bytes
-   uint32_t size;      // Size of section, in bytes
-   uint32_t link;      // Section type-specific header table index link
-   uint32_t info;      // Section type-specific extra information
-   uint32_t addralign; // Section address alignment
-   uint32_t entsize;   // Size of records contained within the section
+   be_val<uint32_t> name;      // Section name (index into string table)
+   be_val<uint32_t> type;      // Section type (SHT_*)
+   be_val<uint32_t> flags;     // Section flags (SHF_*)
+   be_val<uint32_t> addr;      // Address where section is to be loaded
+   be_val<uint32_t> offset;    // File offset of section data, in bytes
+   be_val<uint32_t> size;      // Size of section, in bytes
+   be_val<uint32_t> link;      // Section type-specific header table index link
+   be_val<uint32_t> info;      // Section type-specific extra information
+   be_val<uint32_t> addralign; // Section address alignment
+   be_val<uint32_t> entsize;   // Size of records contained within the section
 };
 CHECK_SIZE(SectionHeader, 0x28);
 
 struct Symbol
 {
-   uint32_t name;  // Symbol name (index into string table)
-   uint32_t value; // Value or address associated with the symbol
-   uint32_t size;  // Size of the symbol
-   uint8_t  info;  // Symbol's type and binding attributes
-   uint8_t  other; // Must be zero; reserved
-   uint16_t shndx; // Which section (header table index) it's defined in (SHN_*)
+   be_val<uint32_t> name;  // Symbol name (index into string table)
+   be_val<uint32_t> value; // Value or address associated with the symbol
+   be_val<uint32_t> size;  // Size of the symbol
+   be_val<uint8_t>  info;  // Symbol's type and binding attributes
+   be_val<uint8_t>  other; // Must be zero; reserved
+   be_val<uint16_t> shndx; // Which section (header table index) it's defined in (SHN_*)
 };
 CHECK_SIZE(Symbol, 0x10);
 
 struct Rela
 {
-   uint32_t offset;
-   uint32_t info;
-   int32_t addend;
+   be_val<uint32_t> offset;
+   be_val<uint32_t> info;
+   be_val<int32_t> addend;
 };
 CHECK_SIZE(Rela, 0x0C);
 
 struct RplImport
 {
-   uint32_t count;
-   uint32_t signature;
+   be_val<uint32_t> count;
+   be_val<uint32_t> signature;
    char name[1];
 };
 
@@ -270,48 +271,48 @@ struct RplExport
 {
    struct Export
    {
-      uint32_t value;
-      uint32_t name;
+      be_val<uint32_t> value;
+      be_val<uint32_t> name;
    };
 
-   uint32_t count;
-   uint32_t signature;
+   be_val<uint32_t> count;
+   be_val<uint32_t> signature;
    Export exports[1];
 };
 
 struct RplCrc
 {
-   uint32_t crc;
+   be_val<uint32_t> crc;
 };
 CHECK_SIZE(RplCrc, 0x04);
 
 struct RplFileInfo
 {
-   uint32_t version;
-   uint32_t textSize;
-   uint32_t textAlign;
-   uint32_t dataSize;
-   uint32_t dataAlign;
-   uint32_t loadSize;
-   uint32_t loadAlign;
-   uint32_t tempSize;
-   uint32_t trampAdjust;
-   uint32_t sdaBase;
-   uint32_t sda2Base;
-   uint32_t stackSize;
-   uint32_t filename;
-   uint32_t flags;
-   uint32_t heapSize;
-   uint32_t tagOffset;
-   uint32_t minVersion;
-   int32_t compressionLevel;
-   uint32_t trampAddition;
-   uint32_t fileInfoPad;
-   uint32_t cafeSdkVersion;
-   uint32_t cafeSdkRevision;
-   uint16_t tlsModuleIndex;
-   uint16_t tlsAlignShift;
-   uint32_t runtimeFileInfoSize;
+   be_val<uint32_t> version;
+   be_val<uint32_t> textSize;
+   be_val<uint32_t> textAlign;
+   be_val<uint32_t> dataSize;
+   be_val<uint32_t> dataAlign;
+   be_val<uint32_t> loadSize;
+   be_val<uint32_t> loadAlign;
+   be_val<uint32_t> tempSize;
+   be_val<uint32_t> trampAdjust;
+   be_val<uint32_t> sdaBase;
+   be_val<uint32_t> sda2Base;
+   be_val<uint32_t> stackSize;
+   be_val<uint32_t> filename;
+   be_val<uint32_t> flags;
+   be_val<uint32_t> heapSize;
+   be_val<uint32_t> tagOffset;
+   be_val<uint32_t> minVersion;
+   be_val<int32_t> compressionLevel;
+   be_val<uint32_t> trampAddition;
+   be_val<uint32_t> fileInfoPad;
+   be_val<uint32_t> cafeSdkVersion;
+   be_val<uint32_t> cafeSdkRevision;
+   be_val<uint16_t> tlsModuleIndex;
+   be_val<uint16_t> tlsAlignShift;
+   be_val<uint32_t> runtimeFileInfoSize;
 };
 CHECK_SIZE(RplFileInfo, 0x60);
 
diff --git a/tools/common/type_traits.h b/tools/common/type_traits.h
new file mode 100644
index 0000000..34fa7ec
--- /dev/null
+++ b/tools/common/type_traits.h
@@ -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 { };
diff --git a/tools/common/utils.h b/tools/common/utils.h
index 817dff3..a20e0e6 100644
--- a/tools/common/utils.h
+++ b/tools/common/utils.h
@@ -1,4 +1,5 @@
 #pragma once
+#include <cstdint>
 #include <cstring>
 #include <type_traits>
 
diff --git a/tools/elf2rpl/main.cpp b/tools/elf2rpl/main.cpp
index efb9ffb..2c22d45 100644
--- a/tools/elf2rpl/main.cpp
+++ b/tools/elf2rpl/main.cpp
@@ -27,73 +27,6 @@ struct ElfFile
    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
 getSectionIndex(ElfFile &file, const char *name)
 {
@@ -158,7 +91,6 @@ readElf(ElfFile &file, const std::string &filename)
 
    // Read header
    in.read(reinterpret_cast<char *>(&file.header), sizeof(elf::Header));
-   byte_swap(file.header);
 
    if (file.header.magic != elf::HeaderMagic) {
       fmt::print("Invalid ELF magic header {:08X}", elf::HeaderMagic);
@@ -193,7 +125,6 @@ readElf(ElfFile &file, const std::string &filename)
       auto &section = *file.sections.back();
 
       in.read(reinterpret_cast<char *>(&section.header), sizeof(elf::SectionHeader));
-      byte_swap(section.header);
 
       if (!section.header.size || section.header.type == elf::SHT_NOBITS) {
          continue;
@@ -373,9 +304,9 @@ reorderSectionIndex(ElfFile &file)
       auto symbols = reinterpret_cast<elf::Symbol *>(section->data.data());
       auto numSymbols = section->data.size() / sizeof(elf::Symbol);
       for (auto i = 0u; i < numSymbols; ++i) {
-         auto shndx = byte_swap(symbols[i].shndx);
+         auto shndx = symbols[i].shndx;
          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>();
    section->header.name = 0;
    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());
       }
 
-      crcs.push_back(byte_swap(crc));
+      crcs.push_back(crc);
    }
 
    auto section = std::make_unique<ElfFile::Section>();
@@ -517,12 +446,7 @@ getSymbol(ElfFile::Section &section, size_t index, elf::Symbol &symbol)
       return false;
    }
 
-   symbol.name = byte_swap(symbols[index].name);
-   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);
+   symbol = symbols[index];
    return true;
 }
 
@@ -554,9 +478,9 @@ fixRelocations(ElfFile &file)
       auto rels = reinterpret_cast<elf::Rela *>(section->data.data());
       auto numRels = section->data.size() / sizeof(elf::Rela);
       for (auto i = 0u; i < numRels; ++i) {
-         auto info = byte_swap(rels[i].info);
-         auto addend = byte_swap(rels[i].addend);
-         auto offset = byte_swap(rels[i].offset);
+         auto info = rels[i].info;
+         auto addend = rels[i].addend;
+         auto offset = rels[i].offset;
          auto index = info >> 8;
          auto type = info & 0xFF;
 
@@ -595,14 +519,14 @@ fixRelocations(ElfFile &file)
                auto &newRel = newRelocations.back();
 
                // 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].addend = byte_swap<int32_t>(addend);
-               rels[i].offset = byte_swap<uint32_t>(offset);
+               rels[i].info = (index << 8) | elf::R_PPC_GHS_REL16_LO;
+               rels[i].addend = addend;
+               rels[i].offset = offset;
 
                // Create a R_PPC_GHS_REL16_HI
-               newRel.info = byte_swap<uint32_t>((index << 8) | elf::R_PPC_GHS_REL16_HI);
-               newRel.addend = byte_swap<int32_t>(addend + 2);
-               newRel.offset = byte_swap<uint32_t>(offset + 2);
+               newRel.info = (index << 8) | elf::R_PPC_GHS_REL16_HI;
+               newRel.addend = addend + 2;
+               newRel.offset = offset + 2;
             }
 
             break;
@@ -692,8 +616,8 @@ relocateSection(ElfFile &file,
       auto symbols = reinterpret_cast<elf::Symbol *>(symSection->data.data());
       auto numSymbols = symSection->data.size() / sizeof(elf::Symbol);
       for (auto i = 0u; i < numSymbols; ++i) {
-         auto type = byte_swap(symbols[i].info) & 0xf;
-         auto value = byte_swap(symbols[i].value);
+         auto type = symbols[i].info & 0xf;
+         auto value = symbols[i].value;
 
          // Only relocate data, func, section symbols
          if (type != elf::STT_OBJECT &&
@@ -703,7 +627,7 @@ relocateSection(ElfFile &file,
          }
 
          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 numRelas = relaSection->data.size() / sizeof(elf::Rela);
       for (auto i = 0u; i < numRelas; ++i) {
-         auto offset = byte_swap(rela[i].offset);
+         auto offset = rela[i].offset;
 
          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;
 
-   // Swap back file & section header to big endian before writing
-   byte_swap(file.header);
-
-   for (auto &section : file.sections) {
-      byte_swap(section->header);
-   }
-
    // Write the file out
    std::ofstream out { filename, std::ofstream::binary };
 
@@ -953,7 +870,7 @@ writeRpl(ElfFile &file, const std::string &filename)
    // Write sections
    for (const auto &section : file.sections) {
       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());
       }
    }
@@ -979,11 +896,6 @@ int main(int argc, const char **argv)
       return -1;
    }
 
-   /*
-    * From here onwards file.header and section.header is in little endian,
-    * everything else remains in big endian!
-    */
-
    if (!fixBssNoBits(elf)) {
       fmt::print("ERROR: fixBssNoBits failed");
       return -1;
diff --git a/tools/rplgen/rplgen.cpp b/tools/rplgen/rplgen.cpp
index 138fc7c..8431b21 100644
--- a/tools/rplgen/rplgen.cpp
+++ b/tools/rplgen/rplgen.cpp
@@ -1,3 +1,5 @@
+#include "utils.h"
+
 #include <array>
 #include <algorithm>
 #include <cctype>
@@ -34,15 +36,6 @@ trim(std::string &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
 {
    INVALID,