Add R_ARM_REL32 .

This commit is contained in:
Christian Speckner 2024-08-11 15:40:55 +02:00
parent 91044b3b4f
commit 8a3cf489ec
3 changed files with 114 additions and 2 deletions

View File

@ -96,6 +96,7 @@ class ElfFile {
static constexpr uInt32 STT_NOTYPE = 0x00; static constexpr uInt32 STT_NOTYPE = 0x00;
static constexpr uInt32 R_ARM_ABS32 = 0x02; static constexpr uInt32 R_ARM_ABS32 = 0x02;
static constexpr uInt32 R_ARM_REL32 = 0x03;
static constexpr uInt32 R_ARM_THM_CALL = 0x0a; static constexpr uInt32 R_ARM_THM_CALL = 0x0a;
static constexpr uInt32 R_ARM_THM_JUMP24 = 0x1e; static constexpr uInt32 R_ARM_THM_JUMP24 = 0x1e;
static constexpr uInt32 R_ARM_TARGET1 = 0x26; static constexpr uInt32 R_ARM_TARGET1 = 0x26;

View File

@ -438,7 +438,12 @@ void ElfLinker::applyRelocationToSection(const ElfFile::Relocation& relocation,
"unable to relocate " + symbol.name + " in " + targetSection.name + ": target out of range" "unable to relocate " + symbol.name + " in " + targetSection.name + ": target out of range"
); );
uInt8* target = const uInt32 targetAddress =
getSegmentBase(targetSectionRelocated.segment) +
targetSectionRelocated.offset +
relocation.offset;
uInt8* const target =
getSegmentDataRef(targetSectionRelocated.segment).get() + getSegmentDataRef(targetSectionRelocated.segment).get() +
targetSectionRelocated.offset + targetSectionRelocated.offset +
relocation.offset; relocation.offset;
@ -453,6 +458,16 @@ void ElfLinker::applyRelocationToSection(const ElfFile::Relocation& relocation,
break; break;
} }
case ElfFile::R_ARM_REL32:
{
uInt32 value = relocatedSymbol->value + relocation.addend.value_or(read32(target));
value |= (symbol.type == ElfFile::STT_FUNC ? 0x01 : 0);
write32(target, value - targetAddress);
break;
}
case ElfFile::R_ARM_THM_CALL: case ElfFile::R_ARM_THM_CALL:
case ElfFile::R_ARM_THM_JUMP24: case ElfFile::R_ARM_THM_JUMP24:
{ {

View File

@ -688,6 +688,102 @@ TEST(ElfLinker, RodataSectionsGoToRodata) {
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345679)); EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345679));
} }
TEST(ElfLinker, R_ARM_REL32_InsertsTheValueRelativeToTheTargetPosition_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_REL32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::text, 0x14), static_cast<uInt32>(0x12345678 - 0x00100014));
}
TEST(ElfLinker, R_ARM_REL32_InsertsTheValueRelativeToTheTargetPosition_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_REL32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::data, 0x14), static_cast<uInt32>(0x12345678 - 0x00200014));
}
TEST(ElfLinker, R_ARM_REL32_InsertsTheValueRelativeToTheTargetPosition_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_REL32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345678 - 0x00300014));
}
TEST(ElfLinker, R_ARM_REL32_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_REL32, -4);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345674 - 0x00300014));
}
TEST(ElfLinker, R_ARM_REL32_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_REL32)
.write32(0x14, -4);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345674 - 0x00300014));
}
TEST(ElfLinker, R_ARM_REL32_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_REL32);
linker.link({});
EXPECT_EQ(segmentRead32(linker, SegmentType::rodata, 0x14), static_cast<uInt32>(0x12345679 - 0x00300014));
}
TEST(ElfLinker, R_ARM_THM_CALL_PatchesOffset) { TEST(ElfLinker, R_ARM_THM_CALL_PatchesOffset) {
ElfFixture fixture(1000); ElfFixture fixture(1000);
ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture); ElfLinker linker(0x00100000, 0x00200000, 0x00300000, fixture);
@ -854,7 +950,7 @@ TEST(ElfLinker, RodataSectionsGoToRodata) {
} }
INSTANTIATE_TEST_SUITE_P(RelocationExceptionSuite, RelocationExceptionTest, testing::Values( INSTANTIATE_TEST_SUITE_P(RelocationExceptionSuite, RelocationExceptionTest, testing::Values(
ElfFile::R_ARM_ABS32, ElfFile::R_ARM_TARGET1, ElfFile::R_ARM_ABS32, ElfFile::R_ARM_TARGET1, ElfFile::R_ARM_REL32,
ElfFile::R_ARM_THM_CALL, ElfFile::R_ARM_THM_JUMP24 ElfFile::R_ARM_THM_CALL, ElfFile::R_ARM_THM_JUMP24
)); ));