diff --git a/src/core/kernel/KernelInteractions.cpp b/src/core/kernel/KernelInteractions.cpp index 9a838906..27406a31 100644 --- a/src/core/kernel/KernelInteractions.cpp +++ b/src/core/kernel/KernelInteractions.cpp @@ -31,6 +31,35 @@ namespace Qv2ray::core::kernel } coreFile.close(); + + // Get Core ABI. + auto [abi, err] = kernel::abi::deduceKernelABI(vCorePath); + if (err) + { + LOG(MODULE_VCORE, "Core ABI deduction failed: " + err.value()) + *message = err.value(); + return false; + } + LOG(MODULE_VCORE, "Core ABI: " + kernel::abi::abiToString(abi.value())) + + // Get Compiled ABI + auto compiledABI = kernel::abi::COMPILED_ABI_TYPE; + LOG(MODULE_VCORE, "Host ABI: " + kernel::abi::abiToString(compiledABI)) + + // Check ABI Compatibility. + switch (kernel::abi::checkCompatibility(compiledABI, abi.value())) + { + case kernel::abi::ABI_NOPE: + LOG(MODULE_VCORE, "Host is incompatible with core") + *message = tr("V2Ray core is incompatible with your platform." NEWLINE // + "Expected core ABI is %1, but got actual %2." NEWLINE // + "Maybe you have downloaded the wrong core?") + .arg(kernel::abi::abiToString(compiledABI), kernel::abi::abiToString(abi.value())); + return false; + case kernel::abi::ABI_MAYBE: LOG(MODULE_VCORE, "WARNING: Host maybe incompatible with core"); [[fallthrough]]; + case kernel::abi::ABI_PERFECT: LOG(MODULE_VCORE, "Host is compatible with core"); + } + // // Check file existance. // From: https://www.v2fly.org/chapter_02/env.html#asset-location diff --git a/src/core/kernel/KernelInteractions.hpp b/src/core/kernel/KernelInteractions.hpp index 1a98eb67..825c15f0 100644 --- a/src/core/kernel/KernelInteractions.hpp +++ b/src/core/kernel/KernelInteractions.hpp @@ -1,6 +1,7 @@ #pragma once #include "base/Qv2rayBase.hpp" #include "core/CoreSafeTypes.hpp" +#include "core/kernel/QvKernelABIChecker.hpp" #include diff --git a/src/core/kernel/QvKernelABIChecker.cpp b/src/core/kernel/QvKernelABIChecker.cpp index 962b95ce..d9c41418 100644 --- a/src/core/kernel/QvKernelABIChecker.cpp +++ b/src/core/kernel/QvKernelABIChecker.cpp @@ -4,7 +4,7 @@ namespace Qv2ray::core::kernel::abi { - [[nodiscard]] QvKernelABICompatibility inline checkCompatibility(QvKernelABIType hostType, QvKernelABIType targetType) + [[nodiscard]] QvKernelABICompatibility checkCompatibility(QvKernelABIType hostType, QvKernelABIType targetType) { switch (hostType) { @@ -36,9 +36,9 @@ namespace Qv2ray::core::kernel::abi if (quint32 elfMagicMaybe; QDataStream(arr) >> elfMagicMaybe, 0x7F454C46u == elfMagicMaybe) { quint16 elfInstruction; - if (QDataStream stream(arr); stream.skipRawData(0x12), stream >> elfInstruction, elfInstruction == 0x003Eu) + if (QDataStream stream(arr); stream.skipRawData(0x12), stream >> elfInstruction, elfInstruction == 0x3E00u) return { QvKernelABIType::ABI_ELF_X86_64, std::nullopt }; - else if (elfInstruction == 0x0003u) + else if (elfInstruction == 0x0300u) return { QvKernelABIType::ABI_ELF_X86, std::nullopt }; else return { QvKernelABIType::ABI_ELF_OTHER, std::nullopt }; @@ -51,4 +51,16 @@ namespace Qv2ray::core::kernel::abi return { std::nullopt, QObject::tr("cannot deduce the type of core executable file %1").arg(pathCoreExecutable) }; } + [[nodiscard]] QString abiToString(QvKernelABIType abi) + { + switch (abi) + { + case ABI_WIN32: return QObject::tr("Windows PE executable"); + case ABI_MACH_O: return QObject::tr("macOS Mach-O executable"); + case ABI_ELF_X86: return QObject::tr("ELF x86 executable"); + case ABI_ELF_X86_64: return QObject::tr("ELF amd64 executable"); + case ABI_ELF_OTHER: return QObject::tr("other ELF executable"); + default: return QObject::tr("unknown abi"); + } + } } // namespace Qv2ray::core::kernel::abi diff --git a/src/core/kernel/QvKernelABIChecker.hpp b/src/core/kernel/QvKernelABIChecker.hpp index 79b38aa2..d9dedb7c 100644 --- a/src/core/kernel/QvKernelABIChecker.hpp +++ b/src/core/kernel/QvKernelABIChecker.hpp @@ -38,6 +38,7 @@ namespace Qv2ray::core::kernel #endif [[nodiscard]] std::pair, std::optional> deduceKernelABI(const QString &pathCoreExecutable); - [[nodiscard]] QvKernelABICompatibility inline checkCompatibility(QvKernelABIType hostType, QvKernelABIType targetType); + [[nodiscard]] QvKernelABICompatibility checkCompatibility(QvKernelABIType hostType, QvKernelABIType targetType); + [[nodiscard]] QString abiToString(QvKernelABIType abi); } // namespace abi } // namespace Qv2ray::core::kernel