refactor(io): add new byte primitives for windows pe
This commit is contained in:
parent
fce86b13b8
commit
4f892eeb15
|
|
@ -7,6 +7,8 @@ add_executable(relinker
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/elfpatcher/src/general/ProgramHeaderLayoutBuilder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elfpatcher/src/general/SectionHeaderTableBuilder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/src/ByteWriter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/src/ByteReader.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/src/BufferUtils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/src/FileReader.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/io/src/FileWriter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/Amd64OnlyConverter.cpp
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ constexpr std::uint32_t kRelTypeAbsolute = 0;
|
|||
constexpr std::uint32_t kRelocBlockHeaderSize = 8;
|
||||
constexpr std::uint32_t kRelocEntrySize = 2;
|
||||
|
||||
constexpr std::uint32_t kSecExec = 0x60000020;
|
||||
constexpr std::uint32_t kSecRW = 0xC0000040;
|
||||
constexpr std::uint32_t kSecRO = 0x40000040;
|
||||
constexpr std::uint32_t kSecDiscard = 0x02000000;
|
||||
|
||||
struct MzHeader {
|
||||
std::uint8_t data[0x40];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <elfpatcher/windows/WindowsElfPatcher.hpp>
|
||||
#include <elfpatcher/general/ElfConstants.hpp>
|
||||
#include <domain/Types.hpp>
|
||||
#include <io/BufferUtils.hpp>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
|
@ -8,7 +9,6 @@
|
|||
#include <map>
|
||||
#include <algorithm>
|
||||
#include "WindowsPeFormat.hpp"
|
||||
#include "io/ByteWriter.hpp"
|
||||
|
||||
namespace Elfpatcher::Windows {
|
||||
|
||||
|
|
@ -24,15 +24,15 @@ MzHeader buildMzStub(std::uint32_t peOffset) {
|
|||
|
||||
void writeSectionHeader(std::vector<std::uint8_t>& buf, std::size_t off, const PeSection& sec) {
|
||||
std::memcpy(buf.data() + off, sec.name, 8);
|
||||
WriteU32(buf, off + 8, sec.virtualSize);
|
||||
WriteU32(buf, off + 12, sec.virtualAddress);
|
||||
WriteU32(buf, off + 16, sec.rawSize);
|
||||
WriteU32(buf, off + 20, sec.rawOffset);
|
||||
WriteU32(buf, off + 24, 0);
|
||||
WriteU32(buf, off + 28, 0);
|
||||
WriteU16(buf, off + 32, 0);
|
||||
WriteU16(buf, off + 34, 0);
|
||||
WriteU32(buf, off + 36, sec.characteristics);
|
||||
Io::WriteU32(buf, off + 8, sec.virtualSize);
|
||||
Io::WriteU32(buf, off + 12, sec.virtualAddress);
|
||||
Io::WriteU32(buf, off + 16, sec.rawSize);
|
||||
Io::WriteU32(buf, off + 20, sec.rawOffset);
|
||||
Io::WriteU32(buf, off + 24, 0);
|
||||
Io::WriteU32(buf, off + 28, 0);
|
||||
Io::WriteU16(buf, off + 32, 0);
|
||||
Io::WriteU16(buf, off + 34, 0);
|
||||
Io::WriteU32(buf, off + 36, sec.characteristics);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> buildRelocSection(
|
||||
|
|
@ -83,11 +83,11 @@ std::vector<std::uint8_t> buildRelocSection(
|
|||
entryCount++;
|
||||
}
|
||||
const std::uint32_t blockSize = kRelocBlockHeaderSize + entryCount * kRelocEntrySize;
|
||||
appendU32(buf, page);
|
||||
appendU32(buf, blockSize);
|
||||
Io::AppendU32(buf, page);
|
||||
Io::AppendU32(buf, blockSize);
|
||||
for (const std::uint32_t off : offsets) {
|
||||
const auto entry = static_cast<std::uint16_t>((kRelTypeDir64 << 12) | (off & 0xFFF));
|
||||
appendU16(buf, entry);
|
||||
Io::AppendU16(buf, entry);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
|
|
@ -111,43 +111,43 @@ std::vector<std::uint8_t> buildImportSection(
|
|||
|
||||
for (const auto& dll : dlls) {
|
||||
const std::uint32_t dllNameRva = dataBase + static_cast<std::uint32_t>(dataBuf.size());
|
||||
appendStr(dataBuf, dll.dllName);
|
||||
alignBuf(dataBuf, 2);
|
||||
Io::AppendString(dataBuf, dll.dllName);
|
||||
Io::AlignBuffer(dataBuf, 2);
|
||||
|
||||
const std::uint32_t iltRva = dataBase + static_cast<std::uint32_t>(dataBuf.size());
|
||||
for (const auto& thunk : dll.thunks) {
|
||||
const std::uint32_t hintNameRva = dataBase + static_cast<std::uint32_t>(dataBuf.size())
|
||||
+ static_cast<std::uint32_t>((dll.thunks.size() + 1) * 8);
|
||||
appendU64(dataBuf, hintNameRva);
|
||||
Io::AppendU64(dataBuf, hintNameRva);
|
||||
}
|
||||
appendU64(dataBuf, 0);
|
||||
Io::AppendU64(dataBuf, 0);
|
||||
|
||||
for (const auto& thunk : dll.thunks) {
|
||||
appendU16(dataBuf, 0);
|
||||
appendStr(dataBuf, thunk.symbolName);
|
||||
alignBuf(dataBuf, 2);
|
||||
Io::AppendU16(dataBuf, 0);
|
||||
Io::AppendString(dataBuf, thunk.symbolName);
|
||||
Io::AlignBuffer(dataBuf, 2);
|
||||
}
|
||||
|
||||
const std::uint32_t iatRva = dataBase + static_cast<std::uint32_t>(dataBuf.size());
|
||||
for (std::size_t i = 0; i < dll.thunks.size(); ++i) {
|
||||
const std::uint32_t iatEntryRva = iatRva + static_cast<std::uint32_t>(i * 8);
|
||||
outGotPatches.emplace_back(dll.thunks[i].gotRva, iatEntryRva);
|
||||
appendU64(dataBuf, 0);
|
||||
Io::AppendU64(dataBuf, 0);
|
||||
}
|
||||
appendU64(dataBuf, 0);
|
||||
Io::AppendU64(dataBuf, 0);
|
||||
|
||||
appendU32(descriptorBuf, iltRva);
|
||||
appendU32(descriptorBuf, 0);
|
||||
appendU32(descriptorBuf, 0);
|
||||
appendU32(descriptorBuf, dllNameRva);
|
||||
appendU32(descriptorBuf, iatRva);
|
||||
Io::AppendU32(descriptorBuf, iltRva);
|
||||
Io::AppendU32(descriptorBuf, 0);
|
||||
Io::AppendU32(descriptorBuf, 0);
|
||||
Io::AppendU32(descriptorBuf, dllNameRva);
|
||||
Io::AppendU32(descriptorBuf, iatRva);
|
||||
}
|
||||
|
||||
appendU32(descriptorBuf, 0);
|
||||
appendU32(descriptorBuf, 0);
|
||||
appendU32(descriptorBuf, 0);
|
||||
appendU32(descriptorBuf, 0);
|
||||
appendU32(descriptorBuf, 0);
|
||||
Io::AppendU32(descriptorBuf, 0);
|
||||
Io::AppendU32(descriptorBuf, 0);
|
||||
Io::AppendU32(descriptorBuf, 0);
|
||||
Io::AppendU32(descriptorBuf, 0);
|
||||
Io::AppendU32(descriptorBuf, 0);
|
||||
|
||||
std::vector<std::uint8_t> result;
|
||||
result.insert(result.end(), descriptorBuf.begin(), descriptorBuf.end());
|
||||
|
|
@ -237,7 +237,7 @@ std::vector<std::uint8_t> WindowsPePatcher::Patch(
|
|||
seg.flags = ph.Flags;
|
||||
loadSegs.push_back(seg);
|
||||
if (seg.vaddr < imageBase) imageBase = seg.vaddr;
|
||||
const std::uint64_t top = alignUp64(seg.vaddr + seg.memSize, kSectionAlignment);
|
||||
const std::uint64_t top = Io::AlignUp64(seg.vaddr + seg.memSize, kSectionAlignment);
|
||||
if (top > imageTop) imageTop = top;
|
||||
}
|
||||
|
||||
|
|
@ -390,10 +390,10 @@ std::vector<std::uint8_t> WindowsPePatcher::Patch(
|
|||
}
|
||||
|
||||
const auto loadImageSize = static_cast<std::uint32_t>(imageBuf.size());
|
||||
const std::uint32_t importSectionRva = alignUp(loadImageRva + loadImageSize, kSectionAlignment);
|
||||
const std::uint32_t importSectionRva = Io::AlignUp(loadImageRva + loadImageSize, kSectionAlignment);
|
||||
|
||||
std::vector<std::uint8_t> importSectionData = buildImportSection(importDlls, importSectionRva, gotPatches);
|
||||
alignBuf(importSectionData, kFileAlignment);
|
||||
Io::AlignBuffer(importSectionData, kFileAlignment);
|
||||
|
||||
for (const auto& [gotRva_, iatRva] : gotPatches) {
|
||||
const auto destInImage = static_cast<std::uint64_t>(gotRva_);
|
||||
|
|
@ -403,14 +403,14 @@ std::vector<std::uint8_t> WindowsPePatcher::Patch(
|
|||
std::memcpy(imageBuf.data() + destInImage, &iatVa, 8);
|
||||
}
|
||||
|
||||
const std::uint32_t relocSectionRva = alignUp(importSectionRva + static_cast<std::uint32_t>(importSectionData.size()), kSectionAlignment);
|
||||
const std::uint32_t relocSectionRva = Io::AlignUp(importSectionRva + static_cast<std::uint32_t>(importSectionData.size()), kSectionAlignment);
|
||||
std::vector<std::uint8_t> relocSectionData = buildRelocSection(dynamicSection.RelaData, imageBase);
|
||||
alignBuf(relocSectionData, kFileAlignment);
|
||||
Io::AlignBuffer(relocSectionData, kFileAlignment);
|
||||
|
||||
const std::uint32_t stubSectionRva = alignUp(relocSectionRva + static_cast<std::uint32_t>(relocSectionData.size()), kSectionAlignment);
|
||||
const std::uint32_t stubSectionRva = Io::AlignUp(relocSectionRva + static_cast<std::uint32_t>(relocSectionData.size()), kSectionAlignment);
|
||||
const std::uint64_t stubVaddr = adjustedBase + stubSectionRva;
|
||||
std::vector<std::uint8_t> stubData = buildEntryStub(elfEntryVaddr, stubVaddr);
|
||||
alignBuf(stubData, kFileAlignment);
|
||||
Io::AlignBuffer(stubData, kFileAlignment);
|
||||
|
||||
const std::uint32_t entryPointRva = stubSectionRva;
|
||||
|
||||
|
|
@ -419,75 +419,75 @@ std::vector<std::uint8_t> WindowsPePatcher::Patch(
|
|||
if (!relocSectionData.empty()) numSections++;
|
||||
numSections++;
|
||||
|
||||
const std::uint32_t sizeOfHeaders = alignUp(
|
||||
const std::uint32_t sizeOfHeaders = Io::AlignUp(
|
||||
0x40 + 4 + 20 + 240 + static_cast<std::uint32_t>(numSections) * 40,
|
||||
kFileAlignment);
|
||||
|
||||
if (sizeOfHeaders > kSizeOfPeHeaders)
|
||||
throw Domain::RelinkerException("PE headers exceed reserved header block size");
|
||||
|
||||
const std::uint32_t sizeOfImage = alignUp(stubSectionRva + static_cast<std::uint32_t>(stubData.size()), kSectionAlignment);
|
||||
const std::uint32_t sizeOfImage = Io::AlignUp(stubSectionRva + static_cast<std::uint32_t>(stubData.size()), kSectionAlignment);
|
||||
|
||||
const std::uint32_t mzPeOffset = 0x40;
|
||||
std::vector<std::uint8_t> result(kSizeOfPeHeaders, 0);
|
||||
|
||||
WriteU16(result, 0, kMzMagic);
|
||||
WriteU32(result, 0x3c, mzPeOffset);
|
||||
Io::WriteU16(result, 0, kMzMagic);
|
||||
Io::WriteU32(result, 0x3c, mzPeOffset);
|
||||
|
||||
std::size_t off = mzPeOffset;
|
||||
WriteU32(result, off, kPeSignature); off += 4;
|
||||
Io::WriteU32(result, off, kPeSignature); off += 4;
|
||||
|
||||
WriteU16(result, off, kMachinAmd64); off += 2;
|
||||
WriteU16(result, off, numSections); off += 2;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU16(result, off, 240); off += 2;
|
||||
WriteU16(result, off, kCharsExe | kCharsLargeAddressAware); off += 2;
|
||||
Io::WriteU16(result, off, kMachinAmd64); off += 2;
|
||||
Io::WriteU16(result, off, numSections); off += 2;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU16(result, off, 240); off += 2;
|
||||
Io::WriteU16(result, off, kCharsExe | kCharsLargeAddressAware); off += 2;
|
||||
|
||||
WriteU16(result, off, kOptMagicPe32Plus); off += 2;
|
||||
writeU8(result, off, 0); off += 1;
|
||||
writeU8(result, off, 0); off += 1;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, entryPointRva); off += 4;
|
||||
WriteU32(result, off, loadImageRva); off += 4;
|
||||
Io::WriteU16(result, off, kOptMagicPe32Plus); off += 2;
|
||||
Io::WriteU8(result, off, 0); off += 1;
|
||||
Io::WriteU8(result, off, 0); off += 1;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, entryPointRva); off += 4;
|
||||
Io::WriteU32(result, off, loadImageRva); off += 4;
|
||||
|
||||
writeU64(result, off, adjustedBase); off += 8;
|
||||
WriteU32(result, off, kSectionAlignment); off += 4;
|
||||
WriteU32(result, off, kFileAlignment); off += 4;
|
||||
WriteU16(result, off, static_cast<std::uint16_t>(kOsVersion)); off += 2;
|
||||
WriteU16(result, off, static_cast<std::uint16_t>(kOsVersionMinor)); off += 2;
|
||||
WriteU16(result, off, 0); off += 2;
|
||||
WriteU16(result, off, 0); off += 2;
|
||||
WriteU16(result, off, static_cast<std::uint16_t>(kOsVersion)); off += 2;
|
||||
WriteU16(result, off, static_cast<std::uint16_t>(kOsVersionMinor)); off += 2;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, sizeOfImage); off += 4;
|
||||
WriteU32(result, off, kSizeOfPeHeaders); off += 4;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU16(result, off, static_cast<std::uint16_t>(kSubsystemConsole)); off += 2;
|
||||
WriteU16(result, off, 0); off += 2;
|
||||
writeU64(result, off, 0); off += 8;
|
||||
writeU64(result, off, 0); off += 8;
|
||||
writeU64(result, off, 0); off += 8;
|
||||
writeU64(result, off, 0); off += 8;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, kNumberOfRvaAndSizes); off += 4;
|
||||
Io::WriteU64(result, off, adjustedBase); off += 8;
|
||||
Io::WriteU32(result, off, kSectionAlignment); off += 4;
|
||||
Io::WriteU32(result, off, kFileAlignment); off += 4;
|
||||
Io::WriteU16(result, off, static_cast<std::uint16_t>(kOsVersion)); off += 2;
|
||||
Io::WriteU16(result, off, static_cast<std::uint16_t>(kOsVersionMinor)); off += 2;
|
||||
Io::WriteU16(result, off, 0); off += 2;
|
||||
Io::WriteU16(result, off, 0); off += 2;
|
||||
Io::WriteU16(result, off, static_cast<std::uint16_t>(kOsVersion)); off += 2;
|
||||
Io::WriteU16(result, off, static_cast<std::uint16_t>(kOsVersionMinor)); off += 2;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, sizeOfImage); off += 4;
|
||||
Io::WriteU32(result, off, kSizeOfPeHeaders); off += 4;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU16(result, off, static_cast<std::uint16_t>(kSubsystemConsole)); off += 2;
|
||||
Io::WriteU16(result, off, 0); off += 2;
|
||||
Io::WriteU64(result, off, 0); off += 8;
|
||||
Io::WriteU64(result, off, 0); off += 8;
|
||||
Io::WriteU64(result, off, 0); off += 8;
|
||||
Io::WriteU64(result, off, 0); off += 8;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, kNumberOfRvaAndSizes); off += 4;
|
||||
|
||||
for (std::uint32_t i = 0; i < kNumberOfRvaAndSizes; ++i) {
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
Io::WriteU32(result, off, 0); off += 4;
|
||||
}
|
||||
|
||||
if (!importSectionData.empty()) {
|
||||
WriteU32(result, mzPeOffset + 4 + 20 + 104, importSectionRva);
|
||||
WriteU32(result, mzPeOffset + 4 + 20 + 108, static_cast<std::uint32_t>(importDlls.size() * 20));
|
||||
Io::WriteU32(result, mzPeOffset + 4 + 20 + 104, importSectionRva);
|
||||
Io::WriteU32(result, mzPeOffset + 4 + 20 + 108, static_cast<std::uint32_t>(importDlls.size() * 20));
|
||||
}
|
||||
if (!relocSectionData.empty()) {
|
||||
WriteU32(result, mzPeOffset + 4 + 20 + 168, relocSectionRva);
|
||||
WriteU32(result, mzPeOffset + 4 + 20 + 172, static_cast<std::uint32_t>(relocSectionData.size()));
|
||||
Io::WriteU32(result, mzPeOffset + 4 + 20 + 168, relocSectionRva);
|
||||
Io::WriteU32(result, mzPeOffset + 4 + 20 + 172, static_cast<std::uint32_t>(relocSectionData.size()));
|
||||
}
|
||||
|
||||
std::size_t shdrsOff = mzPeOffset + 4 + 20 + 240;
|
||||
|
|
@ -496,24 +496,19 @@ std::vector<std::uint8_t> WindowsPePatcher::Patch(
|
|||
char n[8]{};
|
||||
std::memcpy(n, name, std::min(std::strlen(name), std::size_t(8)));
|
||||
std::memcpy(result.data() + shdrsOff, n, 8);
|
||||
WriteU32(result, shdrsOff + 8, virtualSize);
|
||||
WriteU32(result, shdrsOff + 12, rva);
|
||||
WriteU32(result, shdrsOff + 16, rawSize);
|
||||
WriteU32(result, shdrsOff + 20, rawOff);
|
||||
WriteU32(result, shdrsOff + 24, 0);
|
||||
WriteU32(result, shdrsOff + 28, 0);
|
||||
WriteU16(result, shdrsOff + 32, 0);
|
||||
WriteU16(result, shdrsOff + 34, 0);
|
||||
WriteU32(result, shdrsOff + 36, chars);
|
||||
Io::WriteU32(result, shdrsOff + 8, virtualSize);
|
||||
Io::WriteU32(result, shdrsOff + 12, rva);
|
||||
Io::WriteU32(result, shdrsOff + 16, rawSize);
|
||||
Io::WriteU32(result, shdrsOff + 20, rawOff);
|
||||
Io::WriteU32(result, shdrsOff + 24, 0);
|
||||
Io::WriteU32(result, shdrsOff + 28, 0);
|
||||
Io::WriteU16(result, shdrsOff + 32, 0);
|
||||
Io::WriteU16(result, shdrsOff + 34, 0);
|
||||
Io::WriteU32(result, shdrsOff + 36, chars);
|
||||
shdrsOff += 40;
|
||||
};
|
||||
|
||||
constexpr std::uint32_t kSecExec = 0x60000020;
|
||||
constexpr std::uint32_t kSecRW = 0xC0000040;
|
||||
constexpr std::uint32_t kSecRO = 0x40000040;
|
||||
constexpr std::uint32_t kSecDiscard = 0x02000000;
|
||||
|
||||
const std::uint32_t loadRawSize = alignUp(loadImageSize, kFileAlignment);
|
||||
const std::uint32_t loadRawSize = Io::AlignUp(loadImageSize, kFileAlignment);
|
||||
std::uint32_t curRawOff = kSizeOfPeHeaders;
|
||||
|
||||
writeSec(".load", loadImageSize, loadImageRva, loadRawSize, curRawOff, kSecExec | kSecRW);
|
||||
|
|
@ -539,7 +534,7 @@ std::vector<std::uint8_t> WindowsPePatcher::Patch(
|
|||
writeSec(".entry", static_cast<std::uint32_t>(stubData.size()), stubSectionRva,
|
||||
static_cast<std::uint32_t>(stubData.size()), stubRawOff, kSecExec);
|
||||
|
||||
alignBuf(result, kFileAlignment);
|
||||
Io::AlignBuffer(result, kFileAlignment);
|
||||
|
||||
{
|
||||
std::vector<std::uint8_t> loadRaw(imageBuf.begin(), imageBuf.end());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef IO_BUFFERUTILS_HPP
|
||||
#define IO_BUFFERUTILS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Io {
|
||||
|
||||
void WriteU8(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint8_t v);
|
||||
void WriteU16(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint16_t v);
|
||||
void WriteU32(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint32_t v);
|
||||
void WriteU64(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint64_t v);
|
||||
|
||||
void AppendU8(std::vector<std::uint8_t>& buf, std::uint8_t v);
|
||||
void AppendU16(std::vector<std::uint8_t>& buf, std::uint16_t v);
|
||||
void AppendU32(std::vector<std::uint8_t>& buf, std::uint32_t v);
|
||||
void AppendU64(std::vector<std::uint8_t>& buf, std::uint64_t v);
|
||||
void AppendI64(std::vector<std::uint8_t>& buf, std::int64_t v);
|
||||
|
||||
void AppendString(std::vector<std::uint8_t>& buf, const std::string& str);
|
||||
void AlignBuffer(std::vector<std::uint8_t>& buf, std::size_t alignment);
|
||||
|
||||
std::uint16_t ReadU16(const std::vector<std::uint8_t>& buf, std::size_t offset);
|
||||
std::uint32_t ReadU32(const std::vector<std::uint8_t>& buf, std::size_t offset);
|
||||
std::uint64_t ReadU64(const std::vector<std::uint8_t>& buf, std::size_t offset);
|
||||
|
||||
template<typename T>
|
||||
constexpr T AlignUp(T value, T alignment) {
|
||||
return (value + alignment - 1) / alignment * alignment;
|
||||
}
|
||||
|
||||
std::uint64_t AlignUp64(std::uint64_t value, std::uint64_t alignment);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef IO_BYTEREADER_HPP
|
||||
#define IO_BYTEREADER_HPP
|
||||
|
||||
#include <io/IByteReader.hpp>
|
||||
|
||||
namespace Io {
|
||||
|
||||
class ByteReader : public IByteReader {
|
||||
public:
|
||||
std::uint16_t ReadU16(const std::vector<std::uint8_t>& buf, std::size_t offset) const override;
|
||||
std::uint32_t ReadU32(const std::vector<std::uint8_t>& buf, std::size_t offset) const override;
|
||||
std::uint64_t ReadU64(const std::vector<std::uint8_t>& buf, std::size_t offset) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -7,9 +7,13 @@ namespace Io {
|
|||
|
||||
class ByteWriter : public IByteWriter {
|
||||
public:
|
||||
void WriteU8(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint8_t v) const override;
|
||||
void WriteU16(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint16_t v) const override;
|
||||
void WriteU32(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint32_t v) const override;
|
||||
void WriteU64(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint64_t v) const override;
|
||||
void AppendU8(std::vector<std::uint8_t>& buf, std::uint8_t v) const override;
|
||||
void AppendU16(std::vector<std::uint8_t>& buf, std::uint16_t v) const override;
|
||||
void AppendU32(std::vector<std::uint8_t>& buf, std::uint32_t v) const override;
|
||||
void AppendU64(std::vector<std::uint8_t>& buf, std::uint64_t v) const override;
|
||||
void AppendI64(std::vector<std::uint8_t>& buf, std::int64_t v) const override;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef IO_IBYTEREADER_HPP
|
||||
#define IO_IBYTEREADER_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace Io {
|
||||
|
||||
class IByteReader {
|
||||
public:
|
||||
virtual ~IByteReader() = default;
|
||||
|
||||
virtual std::uint16_t ReadU16(const std::vector<std::uint8_t>& buf, std::size_t offset) const = 0;
|
||||
virtual std::uint32_t ReadU32(const std::vector<std::uint8_t>& buf, std::size_t offset) const = 0;
|
||||
virtual std::uint64_t ReadU64(const std::vector<std::uint8_t>& buf, std::size_t offset) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -10,9 +10,13 @@ class IByteWriter {
|
|||
public:
|
||||
virtual ~IByteWriter() = default;
|
||||
|
||||
virtual void WriteU8(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint8_t v) const = 0;
|
||||
virtual void WriteU16(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint16_t v) const = 0;
|
||||
virtual void WriteU32(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint32_t v) const = 0;
|
||||
virtual void WriteU64(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint64_t v) const = 0;
|
||||
virtual void AppendU8(std::vector<std::uint8_t>& buf, std::uint8_t v) const = 0;
|
||||
virtual void AppendU16(std::vector<std::uint8_t>& buf, std::uint16_t v) const = 0;
|
||||
virtual void AppendU32(std::vector<std::uint8_t>& buf, std::uint32_t v) const = 0;
|
||||
virtual void AppendU64(std::vector<std::uint8_t>& buf, std::uint64_t v) const = 0;
|
||||
virtual void AppendI64(std::vector<std::uint8_t>& buf, std::int64_t v) const = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
#include <io/BufferUtils.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Io {
|
||||
|
||||
void WriteU8(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint8_t v) {
|
||||
if (offset >= buf.size())
|
||||
throw std::out_of_range("WriteU8 out of bounds");
|
||||
buf[offset] = v;
|
||||
}
|
||||
|
||||
void WriteU16(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint16_t v) {
|
||||
if (offset + 2 > buf.size())
|
||||
throw std::out_of_range("WriteU16 out of bounds");
|
||||
std::memcpy(buf.data() + offset, &v, 2);
|
||||
}
|
||||
|
||||
void WriteU32(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint32_t v) {
|
||||
if (offset + 4 > buf.size())
|
||||
throw std::out_of_range("WriteU32 out of bounds");
|
||||
std::memcpy(buf.data() + offset, &v, 4);
|
||||
}
|
||||
|
||||
void WriteU64(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint64_t v) {
|
||||
if (offset + 8 > buf.size())
|
||||
throw std::out_of_range("WriteU64 out of bounds");
|
||||
std::memcpy(buf.data() + offset, &v, 8);
|
||||
}
|
||||
|
||||
void AppendU8(std::vector<std::uint8_t>& buf, std::uint8_t v) {
|
||||
buf.push_back(v);
|
||||
}
|
||||
|
||||
void AppendU16(std::vector<std::uint8_t>& buf, std::uint16_t v) {
|
||||
const std::size_t pos = buf.size();
|
||||
buf.resize(pos + 2);
|
||||
std::memcpy(buf.data() + pos, &v, 2);
|
||||
}
|
||||
|
||||
void AppendU32(std::vector<std::uint8_t>& buf, std::uint32_t v) {
|
||||
const std::size_t pos = buf.size();
|
||||
buf.resize(pos + 4);
|
||||
std::memcpy(buf.data() + pos, &v, 4);
|
||||
}
|
||||
|
||||
void AppendU64(std::vector<std::uint8_t>& buf, std::uint64_t v) {
|
||||
const std::size_t pos = buf.size();
|
||||
buf.resize(pos + 8);
|
||||
std::memcpy(buf.data() + pos, &v, 8);
|
||||
}
|
||||
|
||||
void AppendI64(std::vector<std::uint8_t>& buf, std::int64_t v) {
|
||||
AppendU64(buf, static_cast<std::uint64_t>(v));
|
||||
}
|
||||
|
||||
void AppendString(std::vector<std::uint8_t>& buf, const std::string& str) {
|
||||
buf.insert(buf.end(), str.begin(), str.end());
|
||||
buf.push_back(0);
|
||||
}
|
||||
|
||||
void AlignBuffer(std::vector<std::uint8_t>& buf, std::size_t alignment) {
|
||||
const std::size_t remainder = buf.size() % alignment;
|
||||
if (remainder != 0) {
|
||||
const std::size_t padding = alignment - remainder;
|
||||
buf.resize(buf.size() + padding, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::uint64_t AlignUp64(std::uint64_t value, std::uint64_t alignment) {
|
||||
return AlignUp(value, alignment);
|
||||
}
|
||||
|
||||
std::uint16_t ReadU16(const std::vector<std::uint8_t>& buf, std::size_t offset) {
|
||||
if (offset + 2 > buf.size())
|
||||
throw std::out_of_range("ReadU16 out of bounds");
|
||||
std::uint16_t v;
|
||||
std::memcpy(&v, buf.data() + offset, 2);
|
||||
return v;
|
||||
}
|
||||
|
||||
std::uint32_t ReadU32(const std::vector<std::uint8_t>& buf, std::size_t offset) {
|
||||
if (offset + 4 > buf.size())
|
||||
throw std::out_of_range("ReadU32 out of bounds");
|
||||
std::uint32_t v;
|
||||
std::memcpy(&v, buf.data() + offset, 4);
|
||||
return v;
|
||||
}
|
||||
|
||||
std::uint64_t ReadU64(const std::vector<std::uint8_t>& buf, std::size_t offset) {
|
||||
if (offset + 8 > buf.size())
|
||||
throw std::out_of_range("ReadU64 out of bounds");
|
||||
std::uint64_t v;
|
||||
std::memcpy(&v, buf.data() + offset, 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <io/ByteReader.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Io {
|
||||
|
||||
std::uint16_t ByteReader::ReadU16(const std::vector<std::uint8_t>& buf, std::size_t offset) const {
|
||||
if (offset + 2 > buf.size())
|
||||
throw std::out_of_range("ByteReader::ReadU16 out of bounds");
|
||||
std::uint16_t v;
|
||||
std::memcpy(&v, buf.data() + offset, 2);
|
||||
return v;
|
||||
}
|
||||
|
||||
std::uint32_t ByteReader::ReadU32(const std::vector<std::uint8_t>& buf, std::size_t offset) const {
|
||||
if (offset + 4 > buf.size())
|
||||
throw std::out_of_range("ByteReader::ReadU32 out of bounds");
|
||||
std::uint32_t v;
|
||||
std::memcpy(&v, buf.data() + offset, 4);
|
||||
return v;
|
||||
}
|
||||
|
||||
std::uint64_t ByteReader::ReadU64(const std::vector<std::uint8_t>& buf, std::size_t offset) const {
|
||||
if (offset + 8 > buf.size())
|
||||
throw std::out_of_range("ByteReader::ReadU64 out of bounds");
|
||||
std::uint64_t v;
|
||||
std::memcpy(&v, buf.data() + offset, 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
namespace Io {
|
||||
|
||||
void ByteWriter::WriteU8(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint8_t v) const {
|
||||
buf[offset] = v;
|
||||
}
|
||||
|
||||
void ByteWriter::WriteU16(std::vector<std::uint8_t>& buf, std::size_t offset, std::uint16_t v) const {
|
||||
std::memcpy(buf.data() + offset, &v, 2);
|
||||
}
|
||||
|
|
@ -15,6 +19,22 @@ void ByteWriter::WriteU64(std::vector<std::uint8_t>& buf, std::size_t offset, st
|
|||
std::memcpy(buf.data() + offset, &v, 8);
|
||||
}
|
||||
|
||||
void ByteWriter::AppendU8(std::vector<std::uint8_t>& buf, std::uint8_t v) const {
|
||||
buf.push_back(v);
|
||||
}
|
||||
|
||||
void ByteWriter::AppendU16(std::vector<std::uint8_t>& buf, std::uint16_t v) const {
|
||||
const std::size_t pos = buf.size();
|
||||
buf.resize(pos + 2);
|
||||
std::memcpy(buf.data() + pos, &v, 2);
|
||||
}
|
||||
|
||||
void ByteWriter::AppendU32(std::vector<std::uint8_t>& buf, std::uint32_t v) const {
|
||||
const std::size_t pos = buf.size();
|
||||
buf.resize(pos + 4);
|
||||
std::memcpy(buf.data() + pos, &v, 4);
|
||||
}
|
||||
|
||||
void ByteWriter::AppendU64(std::vector<std::uint8_t>& buf, std::uint64_t v) const {
|
||||
const std::size_t pos = buf.size();
|
||||
buf.resize(pos + 8);
|
||||
|
|
|
|||
Loading…
Reference in New Issue