mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
7b3a80155e
These are going to be used to select the correct root.
473 lines
10 KiB
C++
473 lines
10 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
|
|
#include "revng/Model/OperatingSystem.h"
|
|
|
|
#include "revng/Model/Generated/Early/Architecture.h"
|
|
|
|
namespace model::Architecture {
|
|
|
|
inline bool isLittleEndian(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86:
|
|
case model::Architecture::x86_64:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::mipsel:
|
|
return true;
|
|
case model::Architecture::mips:
|
|
case model::Architecture::systemz:
|
|
return false;
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline Values fromLLVMArchitecture(llvm::Triple::ArchType A) {
|
|
switch (A) {
|
|
case llvm::Triple::x86:
|
|
return model::Architecture::x86;
|
|
case llvm::Triple::x86_64:
|
|
return model::Architecture::x86_64;
|
|
case llvm::Triple::arm:
|
|
return model::Architecture::arm;
|
|
case llvm::Triple::aarch64:
|
|
return model::Architecture::aarch64;
|
|
case llvm::Triple::mips:
|
|
return model::Architecture::mips;
|
|
case llvm::Triple::mipsel:
|
|
return model::Architecture::mipsel;
|
|
case llvm::Triple::systemz:
|
|
return model::Architecture::systemz;
|
|
default:
|
|
return model::Architecture::Invalid;
|
|
}
|
|
}
|
|
|
|
inline llvm::Triple::ArchType toLLVMArchitecture(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86:
|
|
return llvm::Triple::x86;
|
|
case model::Architecture::x86_64:
|
|
return llvm::Triple::x86_64;
|
|
case model::Architecture::arm:
|
|
return llvm::Triple::arm;
|
|
case model::Architecture::aarch64:
|
|
return llvm::Triple::aarch64;
|
|
case model::Architecture::mips:
|
|
return llvm::Triple::mips;
|
|
case model::Architecture::mipsel:
|
|
return llvm::Triple::mipsel;
|
|
case model::Architecture::systemz:
|
|
return llvm::Triple::systemz;
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
/// Return the size of the pointer in bytes
|
|
constexpr inline uint64_t getPointerSize(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
return 4;
|
|
case model::Architecture::x86_64:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::systemz:
|
|
return 8;
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
constexpr inline uint64_t getCallPushSize(Values V) {
|
|
switch (V) {
|
|
case x86:
|
|
return 4;
|
|
|
|
case x86_64:
|
|
return 8;
|
|
|
|
case arm:
|
|
case mips:
|
|
case mipsel:
|
|
case aarch64:
|
|
case systemz:
|
|
return 0;
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
constexpr inline llvm::ArrayRef<char> getBasicBlockEndingPattern(Values V) {
|
|
switch (V) {
|
|
case x86:
|
|
case x86_64:
|
|
return "\xcc";
|
|
|
|
case arm:
|
|
// bx lr
|
|
return "\x1e\xff\x2f\xe1";
|
|
|
|
case mips:
|
|
// jr ra
|
|
return "\x08\x00\xe0\x03";
|
|
|
|
case mipsel:
|
|
// jr ra
|
|
return "\x03\xe0\x00\x08";
|
|
|
|
case aarch64:
|
|
// ret
|
|
return "\xc0\x03\x5f\xd6";
|
|
|
|
case systemz:
|
|
// TODO
|
|
return "";
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
// TODO: this is libtinycode-specific
|
|
constexpr inline llvm::StringRef getSyscallHelper(Values V) {
|
|
switch (V) {
|
|
case x86:
|
|
return "helper_raise_interrupt";
|
|
|
|
case x86_64:
|
|
return "helper_syscall";
|
|
|
|
case arm:
|
|
case aarch64:
|
|
return "helper_exception_with_syndrome";
|
|
|
|
case mips:
|
|
case mipsel:
|
|
return "helper_raise_exception";
|
|
|
|
case systemz:
|
|
return "helper_exception";
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
// TODO: this is libtinycode-specific
|
|
inline llvm::ArrayRef<uint64_t> getNoReturnSyscallNumbers(Values V) {
|
|
switch (V) {
|
|
case x86: {
|
|
static uint64_t NoReturnSyscalls[] = {
|
|
0xfc, // exit_group
|
|
0x01, // exit
|
|
0x0b // execve
|
|
};
|
|
return NoReturnSyscalls;
|
|
}
|
|
|
|
case x86_64: {
|
|
static uint64_t NoReturnSyscalls[] = {
|
|
0xe7, // exit_group
|
|
0x3c, // exit
|
|
0x3b // execve
|
|
};
|
|
return NoReturnSyscalls;
|
|
}
|
|
|
|
case arm: {
|
|
static uint64_t NoReturnSyscalls[] = {
|
|
0xf8, // exit_group
|
|
0x1, // exit
|
|
0xb // execve
|
|
};
|
|
return NoReturnSyscalls;
|
|
}
|
|
|
|
case aarch64: {
|
|
static uint64_t NoReturnSyscalls[] = {
|
|
0x5e, // exit_group
|
|
0x5d, // exit
|
|
0xdd // execve
|
|
};
|
|
return NoReturnSyscalls;
|
|
}
|
|
|
|
case mips:
|
|
case mipsel: {
|
|
static uint64_t NoReturnSyscalls[] = {
|
|
0x1096, // exit_group
|
|
0xfa1, // exit
|
|
0xfab // execve
|
|
};
|
|
return NoReturnSyscalls;
|
|
}
|
|
|
|
case systemz: {
|
|
static uint64_t NoReturnSyscalls[] = {
|
|
0xf8, // exit_group
|
|
0x1, // exit
|
|
0xb, // execve
|
|
};
|
|
return NoReturnSyscalls;
|
|
}
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline bool hasELFRelocationAddend(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86_64:
|
|
case model::Architecture::systemz:
|
|
case model::Architecture::aarch64:
|
|
return true;
|
|
|
|
case model::Architecture::x86:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
return false;
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline llvm::StringRef getReadRegisterAssembly(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86_64:
|
|
return "movq %REGISTER, $0";
|
|
|
|
case model::Architecture::systemz:
|
|
case model::Architecture::x86:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
return "";
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline llvm::StringRef getWriteRegisterAssembly(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86_64:
|
|
return "movq $0, %REGISTER";
|
|
|
|
case model::Architecture::systemz:
|
|
case model::Architecture::x86:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
return "";
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline llvm::StringRef getJumpAssembly(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86_64:
|
|
return "jmpq *$0";
|
|
|
|
case model::Architecture::systemz:
|
|
case model::Architecture::x86:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
return "";
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
llvm::StringRef getPCCSVName(Values V);
|
|
|
|
inline llvm::StringRef getQEMUName(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86_64:
|
|
return "x86_64";
|
|
case model::Architecture::systemz:
|
|
return "s390x";
|
|
case model::Architecture::x86:
|
|
return "i386";
|
|
case model::Architecture::arm:
|
|
return "arm";
|
|
case model::Architecture::aarch64:
|
|
return "aarch64";
|
|
case model::Architecture::mips:
|
|
return "mips";
|
|
case model::Architecture::mipsel:
|
|
return "mipsel";
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline Values fromQEMUName(llvm::StringRef Name) {
|
|
if (Name == "x86_64")
|
|
return model::Architecture::x86_64;
|
|
else if (Name == "s390x")
|
|
return model::Architecture::systemz;
|
|
else if (Name == "i386")
|
|
return model::Architecture::x86;
|
|
else if (Name == "arm")
|
|
return model::Architecture::arm;
|
|
else if (Name == "aarch64")
|
|
return model::Architecture::aarch64;
|
|
else if (Name == "mips")
|
|
return model::Architecture::mips;
|
|
else if (Name == "mipsel")
|
|
return model::Architecture::mipsel;
|
|
else
|
|
revng_abort();
|
|
}
|
|
|
|
inline unsigned getMinimalFinalStackOffset(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86_64:
|
|
return 8;
|
|
|
|
case model::Architecture::x86:
|
|
return 4;
|
|
|
|
case model::Architecture::systemz:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
return 0;
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline constexpr llvm::StringRef getAssemblyCommentIndicator(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86:
|
|
case model::Architecture::x86_64:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
case model::Architecture::systemz:
|
|
return "#";
|
|
case model::Architecture::arm:
|
|
return "@";
|
|
case model::Architecture::aarch64:
|
|
return "//";
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline constexpr llvm::StringRef getAssemblyLabelIndicator(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86:
|
|
case model::Architecture::x86_64:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
case model::Architecture::systemz:
|
|
return ":";
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline constexpr bool hasDelaySlot(Values V) {
|
|
switch (V) {
|
|
case model::Architecture::x86:
|
|
case model::Architecture::x86_64:
|
|
case model::Architecture::arm:
|
|
case model::Architecture::aarch64:
|
|
case model::Architecture::systemz:
|
|
return false;
|
|
case model::Architecture::mips:
|
|
case model::Architecture::mipsel:
|
|
return true;
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
inline bool isAvailableFor(Values V,
|
|
model::OperatingSystem::Values OperatingSystem) {
|
|
switch (OperatingSystem) {
|
|
case model::OperatingSystem::Linux:
|
|
switch (V) {
|
|
case Architecture::x86_64:
|
|
case Architecture::aarch64:
|
|
case Architecture::x86:
|
|
case Architecture::arm:
|
|
case Architecture::mips:
|
|
case Architecture::mipsel:
|
|
case Architecture::systemz:
|
|
return true;
|
|
case Architecture::Count:
|
|
case Architecture::Invalid:
|
|
revng_abort();
|
|
}
|
|
|
|
case model::OperatingSystem::Windows:
|
|
switch (V) {
|
|
case Architecture::x86_64:
|
|
case Architecture::aarch64:
|
|
case Architecture::x86:
|
|
case Architecture::arm:
|
|
return true;
|
|
case Architecture::mips:
|
|
case Architecture::mipsel:
|
|
case Architecture::systemz:
|
|
return false;
|
|
case Architecture::Count:
|
|
case Architecture::Invalid:
|
|
revng_abort();
|
|
}
|
|
|
|
case model::OperatingSystem::MacOS:
|
|
switch (V) {
|
|
case Architecture::x86_64:
|
|
case Architecture::aarch64:
|
|
return true;
|
|
case Architecture::x86:
|
|
case Architecture::arm:
|
|
case Architecture::mips:
|
|
case Architecture::mipsel:
|
|
case Architecture::systemz:
|
|
return false;
|
|
case Architecture::Count:
|
|
case Architecture::Invalid:
|
|
revng_abort();
|
|
}
|
|
|
|
case model::OperatingSystem::Invalid:
|
|
// If unspecified, any architecture goes
|
|
revng_assert(V != Architecture::Invalid);
|
|
return true;
|
|
|
|
default:
|
|
revng_abort();
|
|
}
|
|
}
|
|
|
|
} // namespace model::Architecture
|
|
|
|
#include "revng/Model/Generated/Late/Architecture.h"
|