blob: 8d3162b7c63c603cd56561b04e8b3ce14f4e0443 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "crazy_linker_relr_relocations.h"
#include "elf_traits.h"
#include <gtest/gtest.h>
namespace crazy {
TEST(RelrRelocations, DefaultConstruction) {
RelrRelocations relr;
relr.Apply(0);
}
TEST(RelrRelocations, ApplyWithSimpleAddressList) {
// Build a simple array of addresses initialized to pretty liberal values.
const size_t kDataSize = 128;
ELF::Addr data[kDataSize];
for (size_t n = 0; n < kDataSize; ++n)
data[n] = ELF::Addr(0) + n;
// Build an RELR table that lists every *even* item in data[] as a RELR
// relocation target. Offsets are relative to |data|, which thus must be
// the load bias when calling RelrRelocations::Apply() below.
const size_t kWordSize = sizeof(ELF::Addr);
const size_t kRelrSize = 8;
ELF::Relr relr_table[kRelrSize];
for (size_t n = 0; n < kRelrSize; ++n) {
relr_table[n] = kWordSize * n * 2;
}
RelrRelocations relr;
relr.SetAddress(reinterpret_cast<uintptr_t>(relr_table));
relr.SetSize(static_cast<ELF::Addr>(sizeof(relr_table)));
// Build the expected data table here, it's easier to understand the
// comparison.
auto load_bias = reinterpret_cast<uintptr_t>(data);
ELF::Addr expected[kDataSize];
for (size_t n = 0; n < kDataSize; ++n) {
if ((n < 2 * kRelrSize) && (n & 1) == 0) {
expected[n] = data[n] + load_bias;
} else {
expected[n] = data[n];
}
}
// Apply RELR relocations.
relr.Apply(load_bias);
// Compare results.
for (size_t n = 0; n < kDataSize; ++n) {
EXPECT_EQ(expected[n], data[n]) << "# " << n;
}
}
TEST(RelrRelocations, ApplyWithSimpleBitmaps) {
// Build a simple array of addresses initialized to pretty liberal values.
const size_t kDataSize = 128;
ELF::Addr data[kDataSize];
for (size_t n = 0; n < kDataSize; ++n)
data[n] = ELF::Addr(0) + n;
// Build an RELR table that lists every 3rd item in data[] as a RELR
// relocation target. Using only bitmaps. Base address is 0.
const size_t kWordSize = sizeof(ELF::Addr);
const size_t kBitsPerWord = (kWordSize * 8 - 1);
const size_t kRelrSize = (kDataSize + kBitsPerWord - 1) / kBitsPerWord;
ELF::Relr relr_table[kRelrSize] = {};
for (size_t n = 0; n < kDataSize; ++n) {
if ((n % 3) == 0)
relr_table[n / kBitsPerWord] |= (1 | (2 << (n % kBitsPerWord)));
}
RelrRelocations relr;
relr.SetAddress(reinterpret_cast<uintptr_t>(relr_table));
relr.SetSize(static_cast<ELF::Addr>(sizeof(relr_table)));
// Build the expected data table here, it's easier to understand the
// comparison.
auto load_bias = reinterpret_cast<uintptr_t>(data);
ELF::Addr expected[kDataSize];
for (size_t n = 0; n < kDataSize; ++n) {
if ((n % 3) == 0) {
expected[n] = data[n] + load_bias;
} else {
expected[n] = data[n];
}
}
// Apply RELR relocations.
relr.Apply(load_bias);
// Compare results.
for (size_t n = 0; n < kDataSize; ++n) {
EXPECT_EQ(expected[n], data[n]) << "# " << n;
}
}
} // namespace crazy