mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
d10178483d
Unlike the previous iteration of `MetaAddress`, which tried to stuff all the parts of `MetaAddress` within the existing `PC` CSV, this implementation adds a set of new CSVs (or marks some existing ones as) to represent the four portions of the current PC's `MetaAddress`. * Introduce `ProgramCounterHandler`: a class responsible to maintain the PC-related CSVs. This class is also used to manipulate the new dispatcher. * `AdvancedValueInfo`: update for new MetaAddress. * External jump handler: do not clobber registers. When introducing support for dynamic binaries, we didn't realize that in x86-64 we were clobbering `r11`. To avoid this, we have to jump to an address stored in memory. However, due to the new `MetaAddress`, obtaining a *jumpable* address from the PC-related CSVs might require some computations (and it does in ARM). Therefore, we introduce a new global variable, `jumpablepc`, whose only role is to contain the jumpable version of the program counter and then be the target of the memory-indirect jump instruction. * Labels care only about absolute addresses. * CSAA: mark call site, even if no accesses.
184 lines
5.8 KiB
C++
184 lines
5.8 KiB
C++
/// \file MetaAddress.cpp
|
|
/// \brief Tests for MetaAddress
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
// Standard includes
|
|
#include <map>
|
|
|
|
// Boost includes
|
|
#define BOOST_TEST_MODULE MetaAddress
|
|
bool init_unit_test();
|
|
#include <boost/test/execution_monitor.hpp>
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
// Local libraries includes
|
|
#include "revng/Support/MetaAddress.h"
|
|
#include "revng/UnitTestHelpers/UnitTestHelpers.h"
|
|
|
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(MetaAddress)
|
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(MetaAddressType::Values)
|
|
|
|
using namespace llvm;
|
|
|
|
static MetaAddress generic32(uint64_t Address) {
|
|
return MetaAddress::fromGeneric(Triple::x86, Address);
|
|
}
|
|
|
|
static MetaAddress generic64(uint64_t Address) {
|
|
return MetaAddress::fromGeneric(Triple::x86_64, Address);
|
|
}
|
|
|
|
static MetaAddress pc(uint64_t Address) {
|
|
return MetaAddress::fromPC(Triple::x86, Address);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Constructor) {
|
|
using namespace MetaAddressType;
|
|
|
|
BOOST_TEST(MetaAddress().isInvalid());
|
|
BOOST_TEST(MetaAddress(0x1000, Generic32).isValid());
|
|
BOOST_TEST(MetaAddress(0x1000, Generic32).type() == Generic32);
|
|
BOOST_TEST(MetaAddress(0x1000, Generic32).address() == uint64_t(0x1000));
|
|
|
|
BOOST_TEST(MetaAddress(0x1000, Code_arm).isValid());
|
|
BOOST_TEST(MetaAddress(0x1001, Code_arm).isInvalid());
|
|
BOOST_TEST(MetaAddress(0x1000, Code_arm_thumb).isValid());
|
|
BOOST_TEST(MetaAddress(0x1001, Code_arm_thumb).isInvalid());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Factory) {
|
|
// Invalid
|
|
BOOST_TEST(MetaAddress::invalid().isInvalid());
|
|
|
|
// Code
|
|
BOOST_TEST(pc(0x1000).isCode());
|
|
BOOST_TEST(pc(0x1000).isCode(Triple::x86));
|
|
|
|
// Regular ARM and Thumb are both ARM
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::arm, 0x1000).isCode(Triple::arm));
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::arm, 0x1001).isCode(Triple::arm));
|
|
|
|
// Generic
|
|
BOOST_TEST(generic64(0x1000).isGeneric());
|
|
|
|
// Convert to generic
|
|
BOOST_TEST(pc(0x1000).toGeneric().isGeneric());
|
|
|
|
// bitSize
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::arm, 0).bitSize() == uint64_t(32));
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::aarch64, 0).bitSize() == uint64_t(64));
|
|
|
|
// Epoch
|
|
BOOST_TEST(generic64(0).epoch() == uint64_t(0));
|
|
BOOST_TEST(generic64(0).isDefaultEpoch());
|
|
|
|
// Address space
|
|
BOOST_TEST(generic64(0).addressSpace() == uint64_t(0));
|
|
BOOST_TEST(generic64(0).isDefaultAddressSpace());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Accessors) {
|
|
BOOST_TEST(MetaAddress::invalid().asPCOrZero() == uint64_t(0));
|
|
BOOST_TEST(pc(0x1000).asPC() == uint64_t(0x1000));
|
|
using MA = MetaAddress;
|
|
BOOST_TEST(MA::fromPC(Triple::arm, 0x1001).asPC() == uint64_t(0x1001));
|
|
BOOST_TEST(generic64(0x1000).address() == uint64_t(0x1000));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Arithmetic) {
|
|
BOOST_TEST(generic64(0x1000) + 1 == generic64(0x1001));
|
|
BOOST_TEST(generic64(0x1001) - 1 == generic64(0x1000));
|
|
BOOST_TEST(generic64(0x1000) + 0x1000 == generic64(0x2000));
|
|
BOOST_TEST((generic64(0x1010) - generic64(0x1000)) == uint64_t(0x10));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Overflow) {
|
|
BOOST_TEST(generic32(0xFFFFFFFF) + 1 == generic32(0));
|
|
BOOST_TEST(generic64(0xFFFFFFFF) + 1 == generic64(0x100000000));
|
|
BOOST_TEST(generic64(0xFFFFFFFFFFFFFFFF) + 1 == generic64(0));
|
|
BOOST_TEST(generic64(0) - 1 == generic64(0xFFFFFFFFFFFFFFFF));
|
|
BOOST_TEST(generic32(0) - 1 == generic32(0xFFFFFFFF));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Thumb) {
|
|
auto NonThumb = MetaAddress::fromPC(Triple::arm, 0x1000);
|
|
BOOST_TEST(NonThumb.type() == MetaAddressType::Code_arm);
|
|
BOOST_TEST(NonThumb.address() == uint64_t(0x1000));
|
|
BOOST_TEST(NonThumb.asPC() == uint64_t(0x1000));
|
|
|
|
auto Thumb = MetaAddress::fromPC(Triple::arm, 0x1001);
|
|
BOOST_TEST(Thumb.type() == MetaAddressType::Code_arm_thumb);
|
|
BOOST_TEST(Thumb.address() == uint64_t(0x1000));
|
|
BOOST_TEST(Thumb.asPC() == uint64_t(0x1001));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Alignment) {
|
|
// Regular ARM
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::arm, 0x1000).isValid());
|
|
|
|
// Thumb aligned at 4-bytes
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::arm, 0x1001).isValid());
|
|
|
|
// Thumb aligned at 2-bytes
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::arm, 0x1003).isValid());
|
|
|
|
// Misaligned regular ARM
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::arm, 0x1002).isInvalid());
|
|
|
|
// MIPS
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::mips, 0x1000).isValid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::mips, 0x1001).isInvalid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::mips, 0x1002).isInvalid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::mips, 0x1003).isInvalid());
|
|
|
|
// x86
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::x86, 0x1000).isValid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::x86, 0x1001).isValid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::x86, 0x1002).isValid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::x86, 0x1003).isValid());
|
|
|
|
// SystemZ
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::systemz, 0x1000).isValid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::systemz, 0x1001).isInvalid());
|
|
BOOST_TEST(MetaAddress::fromPC(Triple::systemz, 0x1002).isValid());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Comparison) {
|
|
auto A = MetaAddress::fromGeneric(Triple::x86, 0x1000);
|
|
auto B = MetaAddress::fromGeneric(Triple::x86, 0x1001);
|
|
|
|
BOOST_TEST(A.addressLowerThan(B));
|
|
BOOST_TEST(A != B);
|
|
BOOST_TEST(!(A.addressGreaterThan(B)));
|
|
|
|
A += 1;
|
|
BOOST_TEST(!(A.addressLowerThan(B)));
|
|
BOOST_TEST(A == B);
|
|
BOOST_TEST(!(A.addressGreaterThan(B)));
|
|
|
|
A += 1;
|
|
BOOST_TEST(!(A.addressLowerThan(B)));
|
|
BOOST_TEST(A != B);
|
|
BOOST_TEST(A.addressGreaterThan(B));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Page) {
|
|
BOOST_TEST(generic64(0x1234).pageStart() == generic64(0x1000));
|
|
BOOST_TEST(generic64(0x1234).nextPageStart() == generic64(0x2000));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Map) {
|
|
std::map<MetaAddress, int> Map;
|
|
|
|
Map[generic64(0)] = 1;
|
|
Map[MetaAddress::invalid()] = 1;
|
|
Map[pc(0)] = 1;
|
|
Map[MetaAddress::fromPC(Triple::arm, 0)] = 1;
|
|
Map[MetaAddress::fromPC(Triple::arm, 1)] = 1;
|
|
|
|
BOOST_TEST(Map.size() == size_t(5));
|
|
}
|