More tests.

This commit is contained in:
Christian Speckner 2024-07-14 20:28:40 +02:00
parent 92d5478e02
commit 3f5c331024
2 changed files with 294 additions and 50 deletions

View File

@ -24,7 +24,7 @@
namespace {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::optional<ElfLinker::SegmentType> determineSegmentType(const ElfFile::Section& section)
optional<ElfLinker::SegmentType> determineSegmentType(const ElfFile::Section& section)
{
switch (section.type) {
case ElfFile::SHT_PROGBITS:
@ -162,13 +162,13 @@ ElfLinker::RelocatedSymbol ElfLinker::findRelocatedSymbol(string_view name) cons
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const vector<std::optional<ElfLinker::RelocatedSection>>& ElfLinker::getRelocatedSections() const
const vector<optional<ElfLinker::RelocatedSection>>& ElfLinker::getRelocatedSections() const
{
return myRelocatedSections;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const vector<std::optional<ElfLinker::RelocatedSymbol>>& ElfLinker::getRelocatedSymbols() const
const vector<optional<ElfLinker::RelocatedSymbol>>& ElfLinker::getRelocatedSymbols() const
{
return myRelocatedSymbols;
}

View File

@ -23,6 +23,18 @@
#include "ElfLinker.hxx"
namespace {
using SegmentType = ElfLinker::SegmentType;
uInt32 segmentRead32(const ElfLinker& linker, SegmentType segment, uInt32 offset) {
const uInt8* addr = linker.getSegmentData(segment) + offset;
uInt32 value = *(addr++);
value |= *(addr++) << 8;
value |= *(addr++) << 16;
value |= *(addr++) << 24;
return value;
}
class ElfFixture: public ElfFile {
public:
@ -84,12 +96,39 @@ namespace {
return *this;
}
ElfFixture& addRelocation(uInt32 section, uInt32 symbol, uInt32 offset,
uInt8 type, optional<uInt32> addend = std::nullopt)
{
if (!myRelocations.contains(section))
myRelocations[section] = vector<ElfFile::Relocation>();
myRelocations[section].push_back(ElfFile::Relocation{
.offset = offset,
.info = 0,
.addend = addend,
.symbol = symbol,
.type = type,
.symbolName = ""
});
return *this;
}
ElfFixture& write8(size_t address, uInt8 value) {
myData[address] = value;
return *this;
}
ElfFixture& write32(size_t address, uInt32 value) {
myData[address++] = value;
myData[address++] = value >> 8;
myData[address++] = value >> 16;
myData[address++] = value >> 24;
return *this;
}
public:
size_t mySize;
unique_ptr<uInt8[]> myData;
@ -105,9 +144,9 @@ namespace {
linker.link({});
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::data), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::rodata), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::data), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::rodata), static_cast<uInt32>(0));
}
TEST(ElfLinker, TextSectionsGoToText) {
@ -126,26 +165,26 @@ namespace {
linker.link({});
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::text), static_cast<uInt32>(78));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::data), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::rodata), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::text), static_cast<uInt32>(78));
EXPECT_EQ(linker.getSegmentSize(SegmentType::data), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::rodata), static_cast<uInt32>(0));
EXPECT_EQ(linker.getRelocatedSections()[1]->offset, static_cast<uInt32>(0));
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, ElfLinker::SegmentType::text);
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, SegmentType::text);
EXPECT_EQ(linker.getRelocatedSections()[2]->offset, static_cast<uInt32>(12));
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, ElfLinker::SegmentType::text);
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, SegmentType::text);
EXPECT_EQ(linker.getRelocatedSections()[3]->offset, static_cast<uInt32>(34));
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, ElfLinker::SegmentType::text);
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, SegmentType::text);
EXPECT_EQ(linker.getRelocatedSections()[4]->offset, static_cast<uInt32>(67));
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, ElfLinker::SegmentType::text);
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, SegmentType::text);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::text)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::text)[12], 0x02);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::text)[34], 0x03);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::text)[67], 0x04);
EXPECT_EQ(linker.getSegmentData(SegmentType::text)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(SegmentType::text)[12], 0x02);
EXPECT_EQ(linker.getSegmentData(SegmentType::text)[34], 0x03);
EXPECT_EQ(linker.getSegmentData(SegmentType::text)[67], 0x04);
}
TEST(ElfLinker, DataSectionsGoToData) {
@ -164,26 +203,26 @@ namespace {
linker.link({});
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::data), static_cast<uInt32>(78));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::rodata), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::data), static_cast<uInt32>(78));
EXPECT_EQ(linker.getSegmentSize(SegmentType::rodata), static_cast<uInt32>(0));
EXPECT_EQ(linker.getRelocatedSections()[1]->offset, static_cast<uInt32>(0));
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[2]->offset, static_cast<uInt32>(12));
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[3]->offset, static_cast<uInt32>(34));
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[4]->offset, static_cast<uInt32>(67));
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, SegmentType::data);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[12], 0x02);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[34], 0x03);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[67], 0x04);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[12], 0x02);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[34], 0x03);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[67], 0x04);
}
TEST(ElfLinker, RodataSectionsGoToRodata) {
@ -202,26 +241,26 @@ TEST(ElfLinker, RodataSectionsGoToRodata) {
linker.link({});
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::data), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::rodata), static_cast<uInt32>(78));
EXPECT_EQ(linker.getSegmentSize(SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::data), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::rodata), static_cast<uInt32>(78));
EXPECT_EQ(linker.getRelocatedSections()[1]->offset, static_cast<uInt32>(0));
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, ElfLinker::SegmentType::rodata);
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, SegmentType::rodata);
EXPECT_EQ(linker.getRelocatedSections()[2]->offset, static_cast<uInt32>(12));
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, ElfLinker::SegmentType::rodata);
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, SegmentType::rodata);
EXPECT_EQ(linker.getRelocatedSections()[3]->offset, static_cast<uInt32>(34));
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, ElfLinker::SegmentType::rodata);
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, SegmentType::rodata);
EXPECT_EQ(linker.getRelocatedSections()[4]->offset, static_cast<uInt32>(67));
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, ElfLinker::SegmentType::rodata);
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, SegmentType::rodata);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::rodata)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::rodata)[12], 0x02);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::rodata)[34], 0x03);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::rodata)[67], 0x04);
EXPECT_EQ(linker.getSegmentData(SegmentType::rodata)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(SegmentType::rodata)[12], 0x02);
EXPECT_EQ(linker.getSegmentData(SegmentType::rodata)[34], 0x03);
EXPECT_EQ(linker.getSegmentData(SegmentType::rodata)[67], 0x04);
}
TEST(ElfLinker, BssSectionsGoToTheEndOfData) {
@ -238,26 +277,26 @@ TEST(ElfLinker, RodataSectionsGoToRodata) {
linker.link({});
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::data), static_cast<uInt32>(76));
EXPECT_EQ(linker.getSegmentSize(ElfLinker::SegmentType::rodata), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::text), static_cast<uInt32>(0));
EXPECT_EQ(linker.getSegmentSize(SegmentType::data), static_cast<uInt32>(76));
EXPECT_EQ(linker.getSegmentSize(SegmentType::rodata), static_cast<uInt32>(0));
EXPECT_EQ(linker.getRelocatedSections()[1]->offset, static_cast<uInt32>(0));
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[1]->segment, SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[2]->offset, static_cast<uInt32>(44));
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[2]->segment, SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[3]->offset, static_cast<uInt32>(10));
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[3]->segment, SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[4]->offset, static_cast<uInt32>(65));
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, ElfLinker::SegmentType::data);
EXPECT_EQ(linker.getRelocatedSections()[4]->segment, SegmentType::data);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[10], 0x02);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[44], 0);
EXPECT_EQ(linker.getSegmentData(ElfLinker::SegmentType::data)[65], 0);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[0], 0x01);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[10], 0x02);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[44], 0);
EXPECT_EQ(linker.getSegmentData(SegmentType::data)[65], 0);
}
TEST(ElfLinker, SegmentsMayEndNextToEachOther) {
@ -443,4 +482,209 @@ TEST(ElfLinker, RodataSectionsGoToRodata) {
EXPECT_FALSE(linker.getRelocatedSymbols()[0]->undefined);
EXPECT_EQ(linker.getRelocatedSymbols()[0]->value, static_cast<uInt32>(0x00200052));
}
TEST(ElfLinker, SymbolsThatReferToSectionsThatAreNotLoadedAreIgnored) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".init_array", ElfFile::SHT_INIT_ARRAY, 0, 0x10)
.addSymbol("foo", 0, 1);
linker.link({});
EXPECT_EQ(linker.getRelocatedSymbols().size(), static_cast<size_t>(1));
EXPECT_FALSE(linker.getRelocatedSymbols()[0].has_value());
}
TEST(ElfLinker, R_ARM_ABS32_InsertsTheValueAtTheTargetPosition_text) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".text.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".text.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_ABS32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::text, 0x14), static_cast<uInt32>(0x12345678));
}
TEST(ElfLinker, R_ARM_ABS32_InsertsTheValueAtTheTargetPosition_data) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".data.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".data.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_ABS32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::data, 0x14), static_cast<uInt32>(0x12345678));
}
TEST(ElfLinker, R_ARM_ABS32_InsertsTheValueAtTheTargetPosition_rodata) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_ABS32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345678));
}
TEST(ElfLinker, R_ARM_ABS32_AddsAddendToTarget) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_ABS32, -4);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345674));
}
TEST(ElfLinker, R_ARM_ABS32_UsesExistingValueAsAddend) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_ABS32)
.write32(0x14, -4);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345674));
}
TEST(ElfLinker, R_ARM_ABS32_SetsBit0IfTargetIsFunction) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS, ElfFile::STT_FUNC)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_ABS32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345679));
}
TEST(ElfLinker, R_ARM_TARGET1_InsertsTheValueAtTheTargetPosition_text) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".text.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".text.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_TARGET1);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::text, 0x14), static_cast<uInt32>(0x12345678));
}
TEST(ElfLinker, R_ARM_TARGET1_InsertsTheValueAtTheTargetPosition_data) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".data.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".data.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_TARGET1);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::data, 0x14), static_cast<uInt32>(0x12345678));
}
TEST(ElfLinker, R_ARM_TARGET1_InsertsTheValueAtTheTargetPosition_rodata) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_TARGET1);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345678));
}
TEST(ElfLinker, R_ARM_TARGET1_AddsAddendToTarget) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_TARGET1, -4);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345674));
}
TEST(ElfLinker, R_ARM_TARGET1_UsesExistingValueAsAddend) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_TARGET1)
.write32(0x14, -4);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345674));
}
TEST(ElfLinker, R_ARM_TARGET1_SetsBit0IfTargetIsFunction) {
ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
fixture
.addSection(".rodata.1", ElfFile::SHT_PROGBITS, 0, 0x10)
.addSection(".rodata.2", ElfFile::SHT_PROGBITS, 0x10, 0x10)
.addSymbol("foo", 0x12345678, ElfFile::SHN_ABS, ElfFile::STT_FUNC)
.addRelocation(2, 0, 0x04, ElfFile::R_ARM_TARGET1);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345679));
}
}