tools: Add be_val.h

This commit is contained in:
James Benton 2018-05-23 11:10:23 +01:00
parent 7e788f47af
commit 09606f873e
6 changed files with 534 additions and 186 deletions

419
tools/common/be_val.h Normal file
View 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;
};

View File

@ -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);

View 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 { };

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <cstdint>
#include <cstring> #include <cstring>
#include <type_traits> #include <type_traits>

View File

@ -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 &section = *file.sections.back(); auto &section = *file.sections.back();
in.read(reinterpret_cast<char *>(&section.header), sizeof(elf::SectionHeader)); in.read(reinterpret_cast<char *>(&section.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 &section, 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 &section : 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 &section : file.sections) { for (const auto &section : 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;

View File

@ -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,