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

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
#include <cstdint>
#include <cstring>
#include <type_traits>

View File

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

View File

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