diff --git a/bindings/c/include/libhat/c/libhat.h b/bindings/c/include/libhat/c/libhat.h index 9ccb663..b6313d6 100644 --- a/bindings/c/include/libhat/c/libhat.h +++ b/bindings/c/include/libhat/c/libhat.h @@ -30,9 +30,7 @@ extern "C" { typedef enum libhat_status { libhat_success, // The operation was successful libhat_err_unknown, - libhat_err_sig_missing_masked_byte, libhat_err_sig_element_parse_error, - libhat_err_sig_empty_signature, libhat_err_sig_expected_wildcard, libhat_err_sig_invalid_token_length, libhat_err_invalid_argument_value, diff --git a/bindings/c/src/libhat.cpp b/bindings/c/src/libhat.cpp index f38d853..fe02cd7 100644 --- a/bindings/c/src/libhat.cpp +++ b/bindings/c/src/libhat.cpp @@ -95,9 +95,7 @@ LIBHAT_API const char* libhat_status_to_string(const libhat_status status) { switch (status) { STATUS_CASE(libhat_success); STATUS_CASE(libhat_err_unknown); - STATUS_CASE(libhat_err_sig_missing_masked_byte); STATUS_CASE(libhat_err_sig_element_parse_error); - STATUS_CASE(libhat_err_sig_empty_signature); STATUS_CASE(libhat_err_sig_expected_wildcard); STATUS_CASE(libhat_err_sig_invalid_token_length); STATUS_CASE(libhat_err_invalid_argument_value); @@ -113,9 +111,7 @@ LIBHAT_API libhat_status libhat_parse_signature(const char* signatureStr, const *signatureOut = nullptr; switch (result.error()) { using enum hat::signature_error; - case missing_masked_byte: return libhat_err_sig_missing_masked_byte; case element_parse_error: return libhat_err_sig_element_parse_error; - case empty_signature: return libhat_err_sig_empty_signature; case expected_wildcard: return libhat_err_sig_expected_wildcard; case invalid_token_length: return libhat_err_sig_invalid_token_length; } @@ -137,21 +133,14 @@ LIBHAT_API libhat_status libhat_create_signature( if (size && (!bytes || !mask)) { return libhat_err_invalid_argument_value; } - if (!size) { - return libhat_err_sig_empty_signature; - } hat::signature signature{}; - bool containsByte = false; - signature.reserve(size); + signature.resize(size); for (size_t i{}; i < size; i++) { - containsByte |= signature.emplace_back( + signature[i] = { static_cast(bytes[i]), static_cast(mask[i]) - ).all(); - } - if (!containsByte) { - return libhat_err_sig_missing_masked_byte; + }; } *signatureOut = new libhat_signature{std::move(signature)}; return libhat_success; diff --git a/include/libhat/defines.hpp b/include/libhat/defines.hpp index 9e3fc6f..05ea738 100644 --- a/include/libhat/defines.hpp +++ b/include/libhat/defines.hpp @@ -82,6 +82,14 @@ #define LIBHAT_TARGET(arch) #endif +#if defined(__GNUC__) || defined(__clang__) + #define LIBHAT_PURE __attribute__((pure)) + #define LIBHAT_CONST __attribute__((const)) +#else + #define LIBHAT_PURE + #define LIBHAT_CONST +#endif + #if __has_cpp_attribute(no_unique_address) #define LIBHAT_NO_UNIQUE_ADDRESS [[no_unique_address]] #elif __has_cpp_attribute(msvc::no_unique_address) diff --git a/include/libhat/scanner.hpp b/include/libhat/scanner.hpp index 39a8e44..fbc61e5 100644 --- a/include/libhat/scanner.hpp +++ b/include/libhat/scanner.hpp @@ -141,12 +141,9 @@ namespace hat::detail { using scan_function_t = const_scan_result(*)(const std::byte* begin, const std::byte* end, const scan_context& context); - struct scanner_context { - std::size_t vectorSize{}; - }; - enum class scan_mode { Auto, // Picks a mode at runtime + Search, // std::search Single, // std::find + std::equal SSE, // x86/x64 SSE 4.1 AVX2, // x86/x64 AVX2 @@ -154,29 +151,62 @@ namespace hat::detail { Neon, // ARMv7+ Neon }; + bool is_supported(scan_mode mode); + class scan_context { + static constexpr size_t impl_buffer_size = 48; + static constexpr size_t impl_buffer_align = alignof(std::max_align_t); public: - signature_view signature{}; - scan_function_t scanner{}; - scan_alignment alignment{}; - scan_hint hints{}; - std::size_t cmpIndex{}; - std::optional pairIndex{}; + scan_context(const scan_context&) = delete; + scan_context(scan_context&&) = delete; + scan_context& operator=(const scan_context&) = delete; + scan_context& operator=(scan_context&&) = delete; + + constexpr ~scan_context() { + if (impl_deleter_) { + impl_deleter_(impl_buffer_.data()); + impl_deleter_ = nullptr; + } + } + + [[nodiscard]] constexpr signature_view signature() const { + return signature_; + } + + template + void emplace(Args&&... args); + + template + [[nodiscard]] const T& get() const; [[nodiscard]] constexpr const_scan_result scan(const std::byte* begin, const std::byte* end) const { - if (signature.size() > static_cast(std::distance(begin, end))) LIBHAT_UNLIKELY { + if (signature_.empty()) LIBHAT_UNLIKELY { + return begin; + } + if (signature_.size() > static_cast(std::distance(begin, end))) LIBHAT_UNLIKELY { return {}; } - return this->scanner(begin, end, *this); + return scanner_(begin, end, *this); } - void apply_hints(const scanner_context&); - template static constexpr scan_context create(signature_view signature, scan_alignment alignment, scan_hint hints); + template + scan_context(const signature_view signature, const scan_function_t scanner, std::type_identity, Args&&... args) + : signature_(signature), scanner_(scanner) + { + emplace(std::forward(args)...); + } + + constexpr scan_context(const signature_view signature, const scan_function_t scanner) + : signature_(signature), scanner_(scanner) {} + private: - scan_context() = default; + signature_view signature_{}; + scan_function_t scanner_{}; + void(*impl_deleter_)(const void*){}; + alignas(impl_buffer_align) std::array impl_buffer_; }; LIBHAT_FORCEINLINE constexpr auto to_stride(const scan_alignment alignment) { @@ -202,77 +232,48 @@ namespace hat::detail { return std::assume_aligned(ptr); } + struct scan_parameters { + signature_view signature{}; + scan_alignment alignment{}; + scan_hint hints{}; + }; + template - scan_function_t resolve_scanner(scan_context&); + scan_context create_context(const scan_parameters&); template<> - scan_function_t resolve_scanner(scan_context&); + scan_context create_context(const scan_parameters&); template - const_scan_result find_pattern_single(const std::byte* begin, const std::byte* end, const scan_context& context) { + const_scan_result find_pattern_search(const std::byte* begin, const std::byte* end, const scan_context& context) { static constexpr auto stride = alignment_stride; - const auto signature = context.signature; - const auto cmpByte = *signature[context.cmpIndex]; - const auto scanBegin = align_up(begin) + context.cmpIndex; - const auto scanEnd = align_up(end - signature.size() + 1) + context.cmpIndex; - - if (scanBegin >= scanEnd) { - return nullptr; - } + const auto sig = context.signature(); + const auto scanBegin = align_up(begin); + const auto scanEnd = align_up(end - sig.size() + 1); + // intentionally kept simple/inefficient since this will only be used for small buffers for (auto i = scanBegin; i != scanEnd; i += stride) { - if (*i == cmpByte) { - const auto start = i - context.cmpIndex; - const auto match = std::equal(signature.begin(), signature.end(), start); - if (match) LIBHAT_UNLIKELY { - return start; - } + if (std::equal(sig.begin(), sig.end(), i)) { + return i; } } - return nullptr; } template<> - constexpr const_scan_result find_pattern_single(const std::byte* begin, const std::byte* end, const scan_context& context) { - const auto signature = context.signature; - const auto firstByte = *signature[context.cmpIndex]; - const auto scanEnd = end - signature.size() + 1 + context.cmpIndex; - - for (auto i = begin + context.cmpIndex; i != scanEnd; i++) { - // Use std::find to efficiently find the first byte - if LIBHAT_IF_CONSTEVAL { - i = std::find(i, scanEnd, firstByte); - if (i == scanEnd) LIBHAT_UNLIKELY break; - } else { - #ifndef _MSC_VER - i = static_cast( - std::memchr(i, static_cast(firstByte), static_cast(scanEnd - i))); - if (!i) LIBHAT_UNLIKELY break; - #elif __cpp_lib_execution >= 201902L - i = std::find(std::execution::unseq, i, scanEnd, firstByte); - if (i == scanEnd) LIBHAT_UNLIKELY break; - #else - i = std::find(i, scanEnd, firstByte); - if (i == scanEnd) LIBHAT_UNLIKELY break; - #endif - } - const auto start = i - context.cmpIndex; - const auto match = std::equal(signature.begin(), signature.end(), start); - if (match) LIBHAT_UNLIKELY { - return start; - } - } - return nullptr; + constexpr const_scan_result find_pattern_search(const std::byte* begin, const std::byte* end, const scan_context& context) { + const auto sig = context.signature(); + const auto it = std::search(begin, end, sig.begin(), sig.end()); + return it != end ? it : nullptr; } template<> - constexpr scan_function_t resolve_scanner(scan_context& context) { - switch (context.alignment) { - case scan_alignment::X1: return &find_pattern_single; - case scan_alignment::X4: return &find_pattern_single; - case scan_alignment::X16: return &find_pattern_single; + inline scan_context create_context(const scan_parameters& params) { + switch (params.alignment) { + case scan_alignment::X1: return {params.signature, &find_pattern_search}; + case scan_alignment::X4: return {params.signature, &find_pattern_search}; + case scan_alignment::X16: return {params.signature, &find_pattern_search}; } LIBHAT_UNREACHABLE(); } @@ -283,25 +284,19 @@ namespace hat::detail { template constexpr scan_context scan_context::create(const signature_view signature, const scan_alignment alignment, const scan_hint hints) { - std::size_t cmpIndex{}; - for (const auto& elem : signature) { - if (elem.all()) { - break; - } - cmpIndex++; - } - - scan_context ctx{}; - ctx.signature = signature; - ctx.alignment = alignment; - ctx.hints = hints; - ctx.cmpIndex = cmpIndex; + const scan_parameters params{ + .signature = signature, + .alignment = alignment, + .hints = hints, + }; if LIBHAT_IF_CONSTEVAL { - ctx.scanner = resolve_scanner(ctx); + if (alignment != scan_alignment::X1) { + std::abort(); + } + return {signature, &find_pattern_search}; } else { - ctx.scanner = resolve_scanner(ctx); + return create_context(params); } - return ctx; } } diff --git a/include/libhat/signature.hpp b/include/libhat/signature.hpp index 4479f1f..f78e45a 100644 --- a/include/libhat/signature.hpp +++ b/include/libhat/signature.hpp @@ -89,9 +89,7 @@ LIBHAT_EXPORT namespace hat { using fixed_signature = std::array; enum class signature_error { - missing_masked_byte, element_parse_error, - empty_signature, expected_wildcard, invalid_token_length, }; @@ -105,11 +103,8 @@ LIBHAT_EXPORT namespace hat { } /// Convert raw byte storage into a signature - [[nodiscard]] LIBHAT_CONSTEXPR_RESULT result bytes_to_signature(std::span bytes) { - if (bytes.empty()) { - return result_error{signature_error::empty_signature}; - } - return signature{bytes.begin(), bytes.end()}; + [[nodiscard]] constexpr signature bytes_to_signature(std::span bytes) { + return {bytes.begin(), bytes.end()}; } template @@ -124,11 +119,7 @@ LIBHAT_EXPORT namespace hat { } template - [[nodiscard]] LIBHAT_CONSTEXPR_RESULT result string_to_signature(std::basic_string_view str) { - if (str.empty()) { - return result_error{signature_error::empty_signature}; - } - + [[nodiscard]] constexpr signature string_to_signature(std::basic_string_view str) { signature result; result.resize(str.size() * sizeof(Char)); @@ -143,7 +134,7 @@ LIBHAT_EXPORT namespace hat { } template - [[nodiscard]] LIBHAT_CONSTEXPR_RESULT result string_to_signature(std::basic_string str) { + [[nodiscard]] constexpr signature string_to_signature(std::basic_string str) { return string_to_signature(std::basic_string_view{str}); } @@ -171,7 +162,6 @@ LIBHAT_EXPORT namespace hat { [[nodiscard]] LIBHAT_CONSTEXPR_RESULT result parse_signature_to(std::output_iterator auto out, const std::string_view str) { std::size_t written = 0; - bool containsByte = false; for (auto&& sub : str | std::views::split(' ')) { const std::string_view word{sub.begin(), sub.end()}; @@ -194,7 +184,6 @@ LIBHAT_EXPORT namespace hat { if (element) { *out++ = *element; written++; - containsByte |= element->all(); } else { return result_error{signature_error::element_parse_error}; } @@ -205,12 +194,6 @@ LIBHAT_EXPORT namespace hat { } } } - if (written == 0) { - return result_error{signature_error::empty_signature}; - } - if (!containsByte) { - return result_error{signature_error::missing_masked_byte}; - } return written; } diff --git a/include/libhat/system.hpp b/include/libhat/system.hpp index b8e64b9..2d6664e 100644 --- a/include/libhat/system.hpp +++ b/include/libhat/system.hpp @@ -142,5 +142,5 @@ LIBHAT_EXPORT namespace hat { LIBHAT_EXPORT namespace hat { - const system_info_impl& get_system(); + LIBHAT_PURE const system_info_impl& get_system(); } diff --git a/src/Scanner.cpp b/src/Scanner.cpp deleted file mode 100644 index ea3f472..0000000 --- a/src/Scanner.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include - -#include -#include - -#ifdef LIBHAT_HINT_X86_64 -#include "arch/x86/Frequency.hpp" -#endif - -#ifdef LIBHAT_HINT_AARCH64 -#include "arch/arm/Frequency.hpp" -#endif - -namespace hat::detail { - - static constexpr std::uint16_t NUM_PAIRS = 512; - - using pair_hint_t = std::tuple< - const std::array, NUM_PAIRS>&, - const std::array& - >; - - static constexpr auto get_pair_hint(const scan_hint hints) -> std::optional { -#ifdef LIBHAT_HINT_X86_64 - if (static_cast(hints & scan_hint::x86_64)) { - return std::tie(hat::detail::x86_64::pairs_x1, hat::detail::x86_64::scores_x1); - } -#endif -#ifdef LIBHAT_HINT_AARCH64 - if (static_cast(hints & scan_hint::aarch64)) { - return std::tie(hat::detail::aarch64::pairs_x1, hat::detail::aarch64::scores_x1); - } -#endif - return std::nullopt; - } - - void scan_context::apply_hints(const scanner_context& scanner) { - const bool pair0 = static_cast(this->hints & scan_hint::pair0); - - const auto pair_hint = get_pair_hint(this->hints); - if (pair_hint && !pair0 && scanner.vectorSize) { - const auto getScore = [&](const std::byte a, const std::byte b) -> std::uint16_t { - const auto& [pairs, scores] = *pair_hint; - const std::pair pair{a, b}; - const auto it = std::ranges::lower_bound(pairs, pair); - const auto index = static_cast(it - pairs.begin()); - return it != pairs.end() && *it == pair ? scores[index] : NUM_PAIRS; - }; - - std::optional> bestPair{}; - for (auto it = this->signature.begin(); it != std::prev(this->signature.end()); it++) { - const auto i = static_cast(it - this->signature.begin()); - auto& a = *it; - auto& b = *std::next(it); - - if (a.all() && b.all()) { - const auto score = getScore(a.value(), b.value()); - if (!bestPair || score > bestPair->second) { - bestPair.emplace(i, score); - } - } - } - - if (bestPair) { - this->pairIndex = bestPair->first; - } - } - - // If no "optimal" pair was found, find the first byte pair in the signature - if (!this->pairIndex.has_value()) { - for (auto it = this->signature.begin(); it != std::prev(this->signature.end()); it++) { - const auto i = static_cast(it - this->signature.begin()); - auto& a = *it; - auto& b = *std::next(it); - - if (a.all() && b.all()) { - this->pairIndex = i; - break; - } - if (i == 0 && pair0) { - break; - } - } - } - } - - template<> - scan_function_t resolve_scanner(scan_context& context) { - const auto& ext = get_system().extensions; -#if defined(LIBHAT_X86) || defined(LIBHAT_X86_64) - if (compiled_extensions.bmi || ext.bmi) { -#if defined(LIBHAT_X86_64) && defined(LIBHAT_FEATURE_AVX512) - if ((compiled_extensions.avx512f || ext.avx512f) - && (compiled_extensions.avx512bw || ext.avx512bw)) { - return resolve_scanner(context); - } -#endif - if (compiled_extensions.avx2 || ext.avx2) { - return resolve_scanner(context); - } - } -#if defined(LIBHAT_FEATURE_SSE) - if (compiled_extensions.sse41 || ext.sse41) { - return resolve_scanner(context); - } -#endif -#endif -#if defined(LIBHAT_ARM) || defined(LIBHAT_AARCH64) - if (compiled_extensions.neon || ext.neon) { - return resolve_scanner(context); - } -#endif - // If none of the vectorized implementations are available/supported, then fallback to scanning per-byte - return resolve_scanner(context); - } -} - -// Validate return value const-ness for the root find_pattern impl -namespace hat { - static_assert(std::is_same_v(), - std::declval(), - std::declval()))>); - - static_assert(std::is_same_v(), - std::declval(), - std::declval()))>); - - consteval auto count_matches() { - constexpr std::array a{std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, std::byte{1}}; - constexpr hat::fixed_signature<1> s{std::byte{1}}; - - std::vector results{}; - hat::find_all_pattern(a.cbegin(), a.cend(), std::back_inserter(results), s); - return results.size(); - } - static_assert(count_matches() == 2); - - static_assert([] { - constexpr std::array a{std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, std::byte{1}}; - constexpr hat::fixed_signature<1> s{std::byte{1}}; - - std::vector results{}; - hat::find_all_pattern(a.cbegin(), a.cend(), std::back_inserter(results), s); - - return results == hat::find_all_pattern(a.cbegin(), a.cend(), s); - }()); - - static_assert([] { - constexpr std::array a{std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, std::byte{1}}; - constexpr hat::fixed_signature<1> s{std::byte{1}}; - - std::array results{}; - const auto [scan_end, results_end] = hat::find_all_pattern(a.cbegin(), a.cend(), results.begin(), results.end(), s); - return scan_end == a.cend() && results_end == std::next(results.begin(), 2); - }()); -} diff --git a/src/arch/arm/Frequency.hpp b/src/arch/arm/Frequency.hpp deleted file mode 100644 index 5e7f4f9..0000000 --- a/src/arch/arm/Frequency.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace hat::detail::aarch64 { - - static constexpr auto p(std::uint8_t a, std::uint8_t b) { - return std::pair{std::byte{a}, std::byte{b}}; - } - - // Top 512 byte pair occurrences on 1 byte alignment, sorted. Sourced from all PE (.exe and .dll) files included in - // the "clang+llvm-22.1.8-aarch64-pc-windows-msvc" archive. This list accounts for ~50.9% of all byte pairs. - static constexpr inline auto pairs_x1 = std::to_array>({ - p(0x00, 0x00), p(0x00, 0x01), p(0x00, 0x08), p(0x00, 0x11), p(0x00, 0x12), p(0x00, 0x14), p(0x00, 0x20), p(0x00, 0x2A), - p(0x00, 0x34), p(0x00, 0x35), p(0x00, 0x36), p(0x00, 0x37), p(0x00, 0x39), p(0x00, 0x40), p(0x00, 0x51), p(0x00, 0x54), - p(0x00, 0x71), p(0x00, 0x79), p(0x00, 0x80), p(0x00, 0x90), p(0x00, 0x91), p(0x00, 0x94), p(0x00, 0xA9), p(0x00, 0xAA), - p(0x00, 0xB0), p(0x00, 0xB4), p(0x00, 0xB5), p(0x00, 0xB9), p(0x00, 0xD0), p(0x00, 0xD1), p(0x00, 0xF0), p(0x00, 0xF1), - p(0x00, 0xF9), p(0x00, 0xFD), p(0x01, 0x00), p(0x01, 0x01), p(0x01, 0x05), p(0x01, 0x08), p(0x01, 0x09), p(0x01, 0x0A), - p(0x01, 0x0B), p(0x01, 0x0C), p(0x01, 0x15), p(0x01, 0x3F), p(0x01, 0x40), p(0x01, 0x54), p(0x01, 0x71), p(0x01, 0x80), - p(0x01, 0x90), p(0x01, 0x91), p(0x01, 0xA9), p(0x01, 0xAA), p(0x01, 0xB0), p(0x01, 0xB9), p(0x01, 0xD0), p(0x01, 0xD1), - p(0x01, 0xF0), p(0x01, 0xF9), p(0x02, 0x00), p(0x02, 0x01), p(0x02, 0x05), p(0x02, 0x08), p(0x02, 0x40), p(0x02, 0x80), - p(0x02, 0x91), p(0x02, 0xA9), p(0x02, 0xAA), p(0x02, 0xF9), p(0x03, 0x00), p(0x03, 0x01), p(0x03, 0x02), p(0x03, 0x03), - p(0x03, 0x04), p(0x03, 0x05), p(0x03, 0x08), p(0x03, 0x09), p(0x03, 0x13), p(0x03, 0x14), p(0x03, 0x15), p(0x03, 0x16), - p(0x03, 0x17), p(0x03, 0x18), p(0x03, 0x19), p(0x03, 0x1A), p(0x03, 0x1B), p(0x03, 0x1C), p(0x03, 0x1F), p(0x03, 0x40), - p(0x03, 0x5F), p(0x03, 0x80), p(0x03, 0x91), p(0x03, 0xA9), p(0x03, 0xAA), p(0x04, 0x00), p(0x04, 0x40), p(0x04, 0x80), - p(0x04, 0x91), p(0x04, 0xA9), p(0x05, 0x00), p(0x05, 0x01), p(0x05, 0x40), p(0x05, 0x91), p(0x06, 0x00), p(0x06, 0x40), - p(0x06, 0x80), p(0x06, 0x91), p(0x07, 0x00), p(0x07, 0x40), p(0x07, 0x80), p(0x07, 0x91), p(0x08, 0x00), p(0x08, 0x01), - p(0x08, 0x05), p(0x08, 0x09), p(0x08, 0x10), p(0x08, 0x11), p(0x08, 0x21), p(0x08, 0x40), p(0x08, 0x41), p(0x08, 0x61), - p(0x08, 0x81), p(0x08, 0x8B), p(0x08, 0x91), p(0x08, 0xA1), p(0x08, 0xAA), p(0x08, 0xC1), p(0x08, 0xCB), p(0x08, 0xEB), - p(0x09, 0x00), p(0x09, 0x01), p(0x09, 0x05), p(0x09, 0x40), p(0x09, 0x6B), p(0x09, 0x8B), p(0x09, 0x91), p(0x09, 0xEB), - p(0x0A, 0x00), p(0x0A, 0x01), p(0x0A, 0x40), p(0x0A, 0xEB), p(0x0B, 0x00), p(0x0B, 0x40), p(0x0C, 0x00), p(0x0D, 0x00), - p(0x0D, 0x40), p(0x0E, 0x00), p(0x0E, 0x40), p(0x0F, 0x00), p(0x0F, 0x40), p(0x10, 0x00), p(0x10, 0x40), p(0x11, 0x00), - p(0x11, 0x40), p(0x12, 0x00), p(0x12, 0x40), p(0x13, 0x00), p(0x13, 0x40), p(0x13, 0xAA), p(0x14, 0x00), p(0x14, 0xAA), - p(0x14, 0xE0), p(0x14, 0xE8), p(0x14, 0xEB), p(0x15, 0x00), p(0x15, 0xAA), p(0x15, 0xEB), p(0x16, 0x40), p(0x16, 0xAA), - p(0x17, 0x00), p(0x17, 0x08), p(0x17, 0x40), p(0x17, 0x9F), p(0x17, 0xAA), p(0x17, 0xE0), p(0x17, 0xE8), p(0x18, 0xAA), - p(0x19, 0x00), p(0x19, 0xAA), p(0x1A, 0x00), p(0x1A, 0x40), p(0x1A, 0xAA), p(0x1B, 0x00), p(0x1B, 0x40), p(0x1B, 0xAA), - p(0x1C, 0xAA), p(0x1D, 0x00), p(0x1F, 0x00), p(0x1F, 0x01), p(0x1F, 0x05), p(0x1F, 0x09), p(0x1F, 0x20), p(0x1F, 0x2A), - p(0x1F, 0x40), p(0x1F, 0x41), p(0x1F, 0x7C), p(0x1F, 0xAA), p(0x20, 0x00), p(0x20, 0x01), p(0x20, 0x80), p(0x20, 0xD4), - p(0x21, 0x00), p(0x21, 0x40), p(0x22, 0x00), p(0x22, 0x40), p(0x23, 0x00), p(0x23, 0x01), p(0x23, 0x40), p(0x27, 0x00), - p(0x27, 0x40), p(0x28, 0x00), p(0x28, 0x01), p(0x29, 0x00), p(0x29, 0x01), p(0x29, 0x05), p(0x2A, 0x00), p(0x2A, 0xE0), - p(0x2B, 0x00), p(0x2B, 0x40), p(0x2F, 0x00), p(0x2F, 0x40), p(0x33, 0x00), p(0x33, 0x40), p(0x39, 0x08), p(0x39, 0x1F), - p(0x39, 0xE8), p(0x3D, 0x00), p(0x3D, 0xE0), p(0x3F, 0x00), p(0x3F, 0x01), p(0x3F, 0x05), p(0x3F, 0xD6), p(0x40, 0x00), - p(0x40, 0x01), p(0x40, 0x39), p(0x40, 0x79), p(0x40, 0x91), p(0x40, 0x92), p(0x40, 0xA9), p(0x40, 0xB1), p(0x40, 0xB9), - p(0x40, 0xF2), p(0x40, 0xF8), p(0x40, 0xF9), p(0x40, 0xFD), p(0x41, 0x00), p(0x41, 0x39), p(0x41, 0xA9), p(0x41, 0xB9), - p(0x41, 0xF8), p(0x41, 0xF9), p(0x42, 0x00), p(0x42, 0xA9), p(0x42, 0xB9), p(0x42, 0xF9), p(0x43, 0x00), p(0x43, 0x01), - p(0x43, 0x40), p(0x43, 0xA9), p(0x43, 0xF9), p(0x44, 0xA9), p(0x44, 0xF9), p(0x45, 0xF9), p(0x4A, 0x01), p(0x51, 0x1F), - p(0x52, 0x08), p(0x52, 0x09), p(0x52, 0x1F), p(0x52, 0xE0), p(0x52, 0xE3), p(0x52, 0xE8), p(0x53, 0xC2), p(0x54, 0x08), - p(0x54, 0x09), p(0x54, 0x1F), p(0x54, 0x28), p(0x54, 0x29), p(0x54, 0x3F), p(0x54, 0x68), p(0x54, 0x88), p(0x54, 0xE0), - p(0x54, 0xE8), p(0x54, 0xE9), p(0x54, 0xFE), p(0x5B, 0x01), p(0x5B, 0x41), p(0x5F, 0x01), p(0x5F, 0xD6), p(0x5F, 0xF8), - p(0x60, 0x00), p(0x60, 0x02), p(0x61, 0x00), p(0x62, 0x00), p(0x63, 0x00), p(0x68, 0x00), p(0x68, 0x02), p(0x68, 0x0A), - p(0x69, 0x02), p(0x6B, 0x01), p(0x71, 0x61), p(0x7C, 0x92), p(0x7C, 0xD3), p(0x7D, 0x92), p(0x7D, 0xD3), p(0x7F, 0x01), - p(0x7F, 0x02), p(0x80, 0x00), p(0x80, 0x3D), p(0x80, 0x52), p(0x81, 0x00), p(0x82, 0x00), p(0x83, 0x00), p(0x83, 0x01), - p(0x83, 0x02), p(0x88, 0x00), p(0x88, 0x02), p(0x88, 0x9A), p(0x89, 0x9A), p(0x90, 0x08), p(0x91, 0x00), p(0x91, 0x01), - p(0x91, 0x02), p(0x91, 0x03), p(0x91, 0x08), p(0x91, 0x1F), p(0x91, 0x22), p(0x91, 0xC0), p(0x91, 0xE0), p(0x91, 0xE1), - p(0x91, 0xE2), p(0x91, 0xE3), p(0x91, 0xE4), p(0x91, 0xE8), p(0x91, 0xE9), p(0x91, 0xFF), p(0x94, 0x20), p(0x94, 0x68), - p(0x94, 0xE0), p(0x94, 0xE1), p(0x94, 0xE8), p(0x97, 0x20), p(0x97, 0x68), p(0x97, 0xE0), p(0x97, 0xE1), p(0x97, 0xE8), - p(0x9F, 0x02), p(0x9F, 0x1A), p(0xA0, 0x00), p(0xA1, 0x00), p(0xA3, 0x00), p(0xA8, 0x02), p(0xA8, 0xC0), p(0xA9, 0x08), - p(0xA9, 0x1F), p(0xA9, 0xE0), p(0xA9, 0xE8), p(0xA9, 0xF3), p(0xA9, 0xF5), p(0xA9, 0xF7), p(0xA9, 0xF9), p(0xA9, 0xFE), - p(0xA9, 0xFF), p(0xAA, 0x00), p(0xAA, 0x01), p(0xAA, 0x02), p(0xAA, 0x03), p(0xAA, 0x08), p(0xAA, 0x1F), p(0xAA, 0xE0), - p(0xAA, 0xE1), p(0xAA, 0xE2), p(0xAA, 0xE3), p(0xAA, 0xE4), p(0xAA, 0xE5), p(0xAA, 0xE8), p(0xAA, 0xF3), p(0xAA, 0xF4), - p(0xAA, 0xF5), p(0xAA, 0xF6), p(0xAA, 0xF7), p(0xAA, 0xFE), p(0xAA, 0xFF), p(0xB0, 0x08), p(0xB4, 0x08), p(0xB4, 0xE0), - p(0xB9, 0x08), p(0xB9, 0x09), p(0xB9, 0x1F), p(0xB9, 0x29), p(0xB9, 0x3F), p(0xB9, 0x68), p(0xB9, 0xE0), p(0xB9, 0xE1), - p(0xB9, 0xE8), p(0xB9, 0xE9), p(0xB9, 0xFF), p(0xBF, 0x02), p(0xC0, 0x03), p(0xC0, 0x3D), p(0xC1, 0x00), p(0xC2, 0xA8), - p(0xC3, 0x00), p(0xC3, 0x01), p(0xC8, 0x02), p(0xD0, 0x08), p(0xD1, 0xF3), p(0xD4, 0xFF), p(0xD6, 0xE0), p(0xDF, 0x02), - p(0xE0, 0x03), p(0xE0, 0x07), p(0xE0, 0x0F), p(0xE0, 0x23), p(0xE0, 0x43), p(0xE0, 0x63), p(0xE0, 0x83), p(0xE0, 0xC3), - p(0xE1, 0x03), p(0xE1, 0x23), p(0xE1, 0x43), p(0xE1, 0x63), p(0xE1, 0x83), p(0xE1, 0xC3), p(0xE2, 0x03), p(0xE3, 0x00), - p(0xE3, 0x03), p(0xE4, 0x00), p(0xE4, 0x03), p(0xE5, 0x03), p(0xE6, 0x03), p(0xE7, 0x03), p(0xE8, 0x03), p(0xE8, 0x07), - p(0xE8, 0x0B), p(0xE8, 0x0F), p(0xE8, 0x13), p(0xE8, 0x17), p(0xE8, 0x23), p(0xE8, 0x27), p(0xE8, 0x43), p(0xE9, 0x03), - p(0xEA, 0x03), p(0xEB, 0x01), p(0xEB, 0x40), p(0xEB, 0x61), p(0xEB, 0xA1), p(0xEB, 0xC1), p(0xEB, 0xE1), p(0xED, 0x7C), - p(0xF0, 0x08), p(0xF1, 0x7D), p(0xF3, 0x03), p(0xF3, 0x53), p(0xF4, 0x03), p(0xF5, 0x03), p(0xF5, 0x5B), p(0xF5, 0x7B), - p(0xF6, 0x03), p(0xF7, 0x03), p(0xF7, 0x63), p(0xF8, 0x03), p(0xF9, 0x00), p(0xF9, 0x01), p(0xF9, 0x02), p(0xF9, 0x03), - p(0xF9, 0x08), p(0xF9, 0x09), p(0xF9, 0x0A), p(0xF9, 0x1F), p(0xF9, 0x20), p(0xF9, 0x21), p(0xF9, 0x28), p(0xF9, 0x29), - p(0xF9, 0x2A), p(0xF9, 0x3F), p(0xF9, 0x40), p(0xF9, 0x48), p(0xF9, 0x68), p(0xF9, 0x69), p(0xF9, 0x6B), p(0xF9, 0x7F), - p(0xF9, 0x88), p(0xF9, 0xA8), p(0xF9, 0xC8), p(0xF9, 0xE0), p(0xF9, 0xE1), p(0xF9, 0xE2), p(0xF9, 0xE8), p(0xF9, 0xE9), - p(0xF9, 0xEA), p(0xF9, 0xF3), p(0xF9, 0xF4), p(0xF9, 0xF5), p(0xF9, 0xF7), p(0xF9, 0xFB), p(0xF9, 0xFF), p(0xFA, 0x03), - p(0xFA, 0xFF), p(0xFB, 0x73), p(0xFB, 0xFF), p(0xFC, 0xFF), p(0xFD, 0xFF), p(0xFE, 0x0B), p(0xFE, 0xFF), p(0xFF, 0x03), - p(0xFF, 0x17), p(0xFF, 0x43), p(0xFF, 0x54), p(0xFF, 0x83), p(0xFF, 0x97), p(0xFF, 0xB4), p(0xFF, 0xC3), p(0xFF, 0xFF), - }); - - static constexpr inline auto scores_x1 = std::to_array({ - 0x002, 0x040, 0x0D9, 0x04F, 0x0A3, 0x00E, 0x06F, 0x12A, 0x048, 0x0F0, 0x07E, 0x0AE, 0x06E, 0x032, 0x05F, 0x001, - 0x011, 0x0F4, 0x00D, 0x087, 0x006, 0x043, 0x092, 0x018, 0x086, 0x024, 0x0B8, 0x019, 0x08F, 0x0B5, 0x074, 0x01B, - 0x004, 0x0ED, 0x00A, 0x078, 0x14C, 0x073, 0x021, 0x071, 0x0C9, 0x18B, 0x1C0, 0x08C, 0x01C, 0x1A0, 0x05E, 0x046, - 0x10B, 0x027, 0x0A2, 0x05D, 0x114, 0x156, 0x112, 0x145, 0x110, 0x0A6, 0x016, 0x0EE, 0x12C, 0x137, 0x01E, 0x0CA, - 0x04E, 0x0DF, 0x0C6, 0x1A6, 0x009, 0x028, 0x05C, 0x0CF, 0x149, 0x1E7, 0x057, 0x16E, 0x013, 0x01A, 0x02A, 0x033, - 0x054, 0x076, 0x0A1, 0x0D3, 0x106, 0x171, 0x010, 0x072, 0x036, 0x0DB, 0x081, 0x126, 0x195, 0x050, 0x14E, 0x15D, - 0x0B7, 0x184, 0x00C, 0x155, 0x03E, 0x0E2, 0x04C, 0x066, 0x1D5, 0x101, 0x04A, 0x056, 0x1FE, 0x152, 0x02E, 0x026, - 0x058, 0x15A, 0x17B, 0x16D, 0x0D1, 0x0E6, 0x119, 0x1D7, 0x12D, 0x0CC, 0x13D, 0x150, 0x098, 0x136, 0x10E, 0x089, - 0x038, 0x096, 0x191, 0x08B, 0x0EC, 0x138, 0x1FD, 0x03B, 0x077, 0x1FF, 0x06A, 0x190, 0x068, 0x09E, 0x12B, 0x0D2, - 0x1A2, 0x133, 0x0E3, 0x0C5, 0x097, 0x117, 0x153, 0x0B2, 0x0F6, 0x0FB, 0x0E4, 0x0A9, 0x0D5, 0x014, 0x179, 0x01F, - 0x120, 0x1EB, 0x11D, 0x130, 0x02C, 0x180, 0x1E3, 0x03D, 0x0D4, 0x1E2, 0x0DC, 0x1CF, 0x064, 0x05A, 0x16A, 0x093, - 0x129, 0x0BF, 0x199, 0x13A, 0x0F9, 0x100, 0x108, 0x15F, 0x1CB, 0x11A, 0x03F, 0x015, 0x053, 0x1B9, 0x1EC, 0x02D, - 0x0E1, 0x167, 0x1CA, 0x025, 0x045, 0x10F, 0x146, 0x080, 0x052, 0x11B, 0x065, 0x13C, 0x04D, 0x1CD, 0x0DD, 0x169, - 0x139, 0x0AB, 0x10C, 0x0E0, 0x095, 0x0FA, 0x18F, 0x1DF, 0x148, 0x16B, 0x1F1, 0x19E, 0x18D, 0x1C3, 0x1F9, 0x0A4, - 0x1E1, 0x14F, 0x1E4, 0x161, 0x061, 0x160, 0x085, 0x0A7, 0x1F5, 0x029, 0x0D0, 0x1DD, 0x143, 0x0B3, 0x1A1, 0x007, - 0x1CE, 0x144, 0x000, 0x1B3, 0x079, 0x1FB, 0x07B, 0x0C7, 0x15B, 0x039, 0x0BA, 0x0C0, 0x1AC, 0x0AD, 0x088, 0x111, - 0x1ED, 0x103, 0x1A8, 0x165, 0x1BD, 0x1AD, 0x16C, 0x1AF, 0x0D6, 0x1BE, 0x19D, 0x173, 0x1DC, 0x13B, 0x1C7, 0x09D, - 0x0FF, 0x0B0, 0x172, 0x1A4, 0x187, 0x124, 0x17A, 0x044, 0x082, 0x125, 0x170, 0x1FA, 0x1C1, 0x0D7, 0x037, 0x185, - 0x11F, 0x142, 0x0A5, 0x14A, 0x0AA, 0x192, 0x0AF, 0x183, 0x1DE, 0x198, 0x197, 0x19C, 0x182, 0x132, 0x109, 0x188, - 0x1DA, 0x164, 0x069, 0x003, 0x0F1, 0x11C, 0x06B, 0x131, 0x1CC, 0x1B6, 0x0FD, 0x17D, 0x196, 0x1D3, 0x17E, 0x1EA, - 0x116, 0x1F7, 0x0C1, 0x0CB, 0x1A7, 0x099, 0x020, 0x02F, 0x07F, 0x0EB, 0x1F8, 0x094, 0x1D1, 0x1BA, 0x1AA, 0x151, - 0x060, 0x123, 0x063, 0x09A, 0x1B5, 0x09B, 0x186, 0x075, 0x1A3, 0x0B4, 0x1C6, 0x11E, 0x113, 0x166, 0x14D, 0x1D2, - 0x0AC, 0x1DB, 0x1F0, 0x06D, 0x03A, 0x083, 0x0D8, 0x0B6, 0x070, 0x12E, 0x134, 0x1BB, 0x1B0, 0x059, 0x1BC, 0x07C, - 0x030, 0x049, 0x0C4, 0x121, 0x1B1, 0x09C, 0x14B, 0x12F, 0x13F, 0x1E8, 0x1F3, 0x1E6, 0x15C, 0x1E0, 0x122, 0x105, - 0x062, 0x154, 0x07D, 0x1B8, 0x1C9, 0x1C4, 0x0E8, 0x1F6, 0x0DE, 0x128, 0x174, 0x19B, 0x035, 0x08A, 0x15E, 0x1B7, - 0x0BC, 0x19F, 0x1C5, 0x1D9, 0x0B1, 0x127, 0x0E5, 0x1D8, 0x005, 0x0F2, 0x194, 0x0C8, 0x0F7, 0x1D0, 0x0CD, 0x135, - 0x00F, 0x118, 0x0F8, 0x193, 0x104, 0x163, 0x01D, 0x177, 0x042, 0x1C8, 0x09F, 0x0DA, 0x13E, 0x1E5, 0x034, 0x0FC, - 0x1BF, 0x181, 0x176, 0x1C2, 0x168, 0x10A, 0x189, 0x0C3, 0x18C, 0x1AE, 0x102, 0x1D4, 0x18E, 0x1AB, 0x1FC, 0x140, - 0x1EE, 0x0BB, 0x03C, 0x023, 0x04B, 0x067, 0x041, 0x162, 0x091, 0x0BE, 0x084, 0x0E9, 0x051, 0x0C2, 0x1F4, 0x107, - 0x012, 0x06C, 0x157, 0x022, 0x18A, 0x1EF, 0x0A0, 0x0BD, 0x1E9, 0x10D, 0x1A9, 0x158, 0x0A8, 0x1F2, 0x0B9, 0x17C, - 0x0FE, 0x16F, 0x1B2, 0x02B, 0x047, 0x115, 0x031, 0x090, 0x1B4, 0x08D, 0x175, 0x0EF, 0x17F, 0x19A, 0x07A, 0x1A5, - 0x1D6, 0x147, 0x178, 0x0F3, 0x08E, 0x159, 0x055, 0x0CE, 0x008, 0x0F5, 0x017, 0x0E7, 0x05B, 0x141, 0x0EA, 0x00B, - }); -} diff --git a/src/arch/x86/Frequency.hpp b/src/arch/x86/Frequency.hpp deleted file mode 100644 index 7bfadcd..0000000 --- a/src/arch/x86/Frequency.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace hat::detail::x86_64 { - - static constexpr auto p(std::uint8_t a, std::uint8_t b) { - return std::pair{std::byte{a}, std::byte{b}}; - } - - // Top 512 byte pair occurrences on 1 byte alignment, sorted. Sourced from multiple executables compiled for - // Windows using MSVC, ranging from versions 19.16 to 19.42. This list accounts for ~60.4% of all byte pairs. - static constexpr inline auto pairs_x1 = std::to_array>({ - p(0x00, 0x00), p(0x00, 0x01), p(0x00, 0x0F), p(0x00, 0x10), p(0x00, 0x33), p(0x00, 0x41), p(0x00, 0x44), p(0x00, 0x45), - p(0x00, 0x48), p(0x00, 0x49), p(0x00, 0x4C), p(0x00, 0x4D), p(0x00, 0x66), p(0x00, 0x72), p(0x00, 0x74), p(0x00, 0x75), - p(0x00, 0x80), p(0x00, 0x89), p(0x00, 0x8B), p(0x00, 0x90), p(0x00, 0xC6), p(0x00, 0xC7), p(0x00, 0xE8), p(0x00, 0xE9), - p(0x00, 0xEB), p(0x00, 0xF3), p(0x00, 0xFF), p(0x01, 0x00), p(0x01, 0x0F), p(0x01, 0x48), p(0x01, 0x4C), p(0x01, 0x74), - p(0x01, 0x75), p(0x01, 0xBA), p(0x02, 0x00), p(0x02, 0x48), p(0x03, 0x00), p(0x03, 0x48), p(0x03, 0x4C), p(0x04, 0x00), - p(0x04, 0x48), p(0x05, 0x00), p(0x05, 0x48), p(0x05, 0xE8), p(0x06, 0x00), p(0x06, 0x48), p(0x07, 0x00), p(0x07, 0x48), - p(0x07, 0xFF), p(0x08, 0x00), p(0x08, 0x01), p(0x08, 0x0F), p(0x08, 0x48), p(0x08, 0x49), p(0x08, 0x4C), p(0x08, 0x83), - p(0x08, 0xE8), p(0x08, 0xFF), p(0x09, 0x00), p(0x09, 0x48), p(0x0A, 0x00), p(0x0B, 0x48), p(0x0C, 0x00), p(0x0C, 0x48), - p(0x0C, 0x83), p(0x0F, 0x00), p(0x0F, 0x10), p(0x0F, 0x11), p(0x0F, 0x1F), p(0x0F, 0x28), p(0x0F, 0x29), p(0x0F, 0x48), - p(0x0F, 0x57), p(0x0F, 0x58), p(0x0F, 0x59), p(0x0F, 0x6F), p(0x0F, 0x76), p(0x0F, 0x7F), p(0x0F, 0x84), p(0x0F, 0x85), - p(0x0F, 0x87), p(0x0F, 0x95), p(0x0F, 0xAF), p(0x0F, 0xB6), p(0x0F, 0xB7), p(0x0F, 0xC1), p(0x10, 0x00), p(0x10, 0x01), - p(0x10, 0x05), p(0x10, 0x0F), p(0x10, 0x44), p(0x10, 0x48), p(0x10, 0x49), p(0x10, 0x4C), p(0x10, 0x72), p(0x10, 0xE8), - p(0x11, 0x00), p(0x11, 0x44), p(0x11, 0x45), p(0x11, 0x48), p(0x13, 0x48), p(0x18, 0x0F), p(0x18, 0x48), p(0x18, 0x49), - p(0x19, 0x48), p(0x1C, 0x48), p(0x1F, 0x76), p(0x20, 0x00), p(0x20, 0x01), p(0x20, 0x0F), p(0x20, 0x41), p(0x20, 0x48), - p(0x20, 0x49), p(0x20, 0x4C), p(0x20, 0x5B), p(0x20, 0x5F), p(0x20, 0xE8), p(0x20, 0xFF), p(0x24, 0x08), p(0x24, 0x10), - p(0x24, 0x18), p(0x24, 0x20), p(0x24, 0x28), p(0x24, 0x30), p(0x24, 0x38), p(0x24, 0x40), p(0x24, 0x48), p(0x24, 0x50), - p(0x24, 0x58), p(0x24, 0x60), p(0x24, 0x68), p(0x24, 0x70), p(0x24, 0x78), p(0x24, 0x80), p(0x27, 0x48), p(0x28, 0x00), - p(0x28, 0x48), p(0x28, 0x49), p(0x28, 0x4C), p(0x28, 0xE8), p(0x2B, 0x48), p(0x2B, 0xC1), p(0x2B, 0xC8), p(0x30, 0x0F), - p(0x30, 0x48), p(0x30, 0x49), p(0x30, 0x4C), p(0x30, 0xE8), p(0x33, 0xC0), p(0x33, 0xC4), p(0x33, 0xC9), p(0x33, 0xCC), - p(0x33, 0xD2), p(0x33, 0xF6), p(0x38, 0x00), p(0x38, 0x48), p(0x3B, 0xCA), p(0x40, 0x00), p(0x40, 0x08), p(0x40, 0x0F), - p(0x40, 0x10), p(0x40, 0x20), p(0x40, 0x48), p(0x40, 0x53), p(0x40, 0x88), p(0x40, 0xE8), p(0x41, 0x08), p(0x41, 0x0F), - p(0x41, 0x10), p(0x41, 0x54), p(0x41, 0x55), p(0x41, 0x56), p(0x41, 0x57), p(0x41, 0x5C), p(0x41, 0x5D), p(0x41, 0x5E), - p(0x41, 0x5F), p(0x41, 0x8B), p(0x41, 0xB8), p(0x41, 0xF8), p(0x42, 0x08), p(0x43, 0x08), p(0x43, 0x0C), p(0x43, 0x10), - p(0x43, 0x18), p(0x44, 0x0F), p(0x44, 0x24), p(0x44, 0x88), p(0x44, 0x89), p(0x44, 0x8B), p(0x44, 0x8D), p(0x45, 0x0F), - p(0x45, 0x33), p(0x46, 0x08), p(0x47, 0x08), p(0x47, 0x10), p(0x48, 0x03), p(0x48, 0x0F), p(0x48, 0x2B), p(0x48, 0x33), - p(0x48, 0x3B), p(0x48, 0x48), p(0x48, 0x81), p(0x48, 0x83), p(0x48, 0x85), p(0x48, 0x89), p(0x48, 0x8B), p(0x48, 0x8D), - p(0x48, 0xB8), p(0x48, 0xC1), p(0x48, 0xC7), p(0x48, 0xFF), p(0x49, 0x0F), p(0x49, 0x2B), p(0x49, 0x3B), p(0x49, 0x83), - p(0x49, 0x89), p(0x49, 0x8B), p(0x49, 0x8D), p(0x49, 0xF8), p(0x4B, 0x08), p(0x4C, 0x24), p(0x4C, 0x3B), p(0x4C, 0x89), - p(0x4C, 0x8B), p(0x4C, 0x8D), p(0x4D, 0x85), p(0x4D, 0x89), p(0x4D, 0x8B), p(0x50, 0x08), p(0x50, 0x48), p(0x53, 0x48), - p(0x54, 0x24), p(0x54, 0x41), p(0x55, 0x41), p(0x55, 0x48), p(0x55, 0x56), p(0x56, 0x41), p(0x56, 0x48), p(0x56, 0x57), - p(0x57, 0x41), p(0x57, 0x48), p(0x57, 0xC0), p(0x57, 0xC9), p(0x58, 0x00), p(0x58, 0x48), p(0x5B, 0xC3), p(0x5C, 0x24), - p(0x5C, 0x5F), p(0x5D, 0x41), p(0x5D, 0xC3), p(0x5E, 0x41), p(0x5E, 0x5D), p(0x5E, 0x5F), p(0x5F, 0x41), p(0x5F, 0x5E), - p(0x5F, 0xC3), p(0x60, 0x48), p(0x64, 0x24), p(0x66, 0x0F), p(0x66, 0x89), p(0x68, 0x48), p(0x6C, 0x24), p(0x70, 0x48), - p(0x72, 0x1C), p(0x74, 0x05), p(0x74, 0x24), p(0x75, 0x10), p(0x76, 0x07), p(0x78, 0x48), p(0x7C, 0x24), p(0x7F, 0x44), - p(0x7F, 0x45), p(0x80, 0x00), p(0x80, 0x48), p(0x81, 0xC4), p(0x81, 0xEC), p(0x81, 0xFA), p(0x83, 0xC0), p(0x83, 0xC1), - p(0x83, 0xC2), p(0x83, 0xC4), p(0x83, 0xEC), p(0x83, 0xF8), p(0x83, 0xFA), p(0x83, 0xFF), p(0x84, 0x00), p(0x84, 0x24), - p(0x84, 0xC0), p(0x85, 0xC0), p(0x85, 0xC9), p(0x85, 0xD2), p(0x85, 0xDB), p(0x85, 0xF6), p(0x85, 0xFF), p(0x88, 0x00), - p(0x89, 0x01), p(0x89, 0x02), p(0x89, 0x03), p(0x89, 0x05), p(0x89, 0x41), p(0x89, 0x42), p(0x89, 0x43), p(0x89, 0x44), - p(0x89, 0x45), p(0x89, 0x46), p(0x89, 0x47), p(0x89, 0x4C), p(0x89, 0x4D), p(0x89, 0x54), p(0x89, 0x5C), p(0x89, 0x5D), - p(0x89, 0x6B), p(0x89, 0x6C), p(0x89, 0x73), p(0x89, 0x74), p(0x89, 0x75), p(0x89, 0x7C), p(0x89, 0x7D), p(0x89, 0x84), - p(0x89, 0x85), p(0x8B, 0x00), p(0x8B, 0x01), p(0x8B, 0x03), p(0x8B, 0x04), p(0x8B, 0x05), p(0x8B, 0x06), p(0x8B, 0x07), - p(0x8B, 0x08), p(0x8B, 0x0D), p(0x8B, 0x40), p(0x8B, 0x41), p(0x8B, 0x42), p(0x8B, 0x43), p(0x8B, 0x44), p(0x8B, 0x45), - p(0x8B, 0x46), p(0x8B, 0x47), p(0x8B, 0x48), p(0x8B, 0x49), p(0x8B, 0x4B), p(0x8B, 0x4C), p(0x8B, 0x4D), p(0x8B, 0x4E), - p(0x8B, 0x4F), p(0x8B, 0x54), p(0x8B, 0x55), p(0x8B, 0x5B), p(0x8B, 0x5C), p(0x8B, 0x5D), p(0x8B, 0x73), p(0x8B, 0x74), - p(0x8B, 0x7C), p(0x8B, 0x80), p(0x8B, 0x85), p(0x8B, 0x8C), p(0x8B, 0x8D), p(0x8B, 0x9C), p(0x8B, 0xC0), p(0x8B, 0xC1), - p(0x8B, 0xC2), p(0x8B, 0xC3), p(0x8B, 0xC6), p(0x8B, 0xC7), p(0x8B, 0xC8), p(0x8B, 0xCB), p(0x8B, 0xCD), p(0x8B, 0xCE), - p(0x8B, 0xCF), p(0x8B, 0xD0), p(0x8B, 0xD3), p(0x8B, 0xD6), p(0x8B, 0xD7), p(0x8B, 0xD8), p(0x8B, 0xD9), p(0x8B, 0xDA), - p(0x8B, 0xE3), p(0x8B, 0xEA), p(0x8B, 0xF0), p(0x8B, 0xF1), p(0x8B, 0xF2), p(0x8B, 0xF8), p(0x8B, 0xF9), p(0x8B, 0xFA), - p(0x8C, 0x24), p(0x8D, 0x05), p(0x8D, 0x0D), p(0x8D, 0x15), p(0x8D, 0x41), p(0x8D, 0x44), p(0x8D, 0x45), p(0x8D, 0x4B), - p(0x8D, 0x4C), p(0x8D, 0x4D), p(0x8D, 0x4F), p(0x8D, 0x54), p(0x8D, 0x55), p(0x8D, 0x85), p(0x8D, 0x8A), p(0x8D, 0x8D), - p(0x8D, 0x95), p(0x8D, 0x9C), p(0x90, 0x00), p(0x90, 0x48), p(0x90, 0x4C), p(0x95, 0xC2), p(0x98, 0x00), p(0x9C, 0x24), - p(0xA0, 0x00), p(0xA8, 0x00), p(0xAA, 0xAA), p(0xB0, 0x00), p(0xB0, 0x01), p(0xB8, 0x00), p(0xC0, 0x00), p(0xC0, 0x0F), - p(0xC0, 0x48), p(0xC0, 0x74), p(0xC0, 0x75), p(0xC0, 0xF3), p(0xC0, 0xF8), p(0xC1, 0x43), p(0xC1, 0x48), p(0xC1, 0xE8), - p(0xC1, 0xF8), p(0xC2, 0x27), p(0xC2, 0x48), p(0xC3, 0x48), p(0xC3, 0xCC), p(0xC3, 0xE8), p(0xC4, 0x20), p(0xC4, 0x28), - p(0xC4, 0x30), p(0xC4, 0x48), p(0xC6, 0x44), p(0xC6, 0x45), p(0xC6, 0x48), p(0xC6, 0xF0), p(0xC7, 0x43), p(0xC7, 0x44), - p(0xC7, 0x45), p(0xC7, 0x48), p(0xC7, 0x85), p(0xC7, 0xF0), p(0xC8, 0x00), p(0xC8, 0x48), p(0xC8, 0xE8), p(0xC9, 0x0F), - p(0xC9, 0x48), p(0xC9, 0x74), p(0xC9, 0xF3), p(0xCB, 0x48), p(0xCB, 0xE8), p(0xCB, 0xFF), p(0xCC, 0x40), p(0xCC, 0x48), - p(0xCC, 0xCC), p(0xCC, 0xE8), p(0xCE, 0x48), p(0xCE, 0xE8), p(0xCF, 0x48), p(0xCF, 0xE8), p(0xD0, 0x00), p(0xD0, 0x48), - p(0xD2, 0x48), p(0xD3, 0x48), p(0xD6, 0x48), p(0xD7, 0x48), p(0xD8, 0x00), p(0xD8, 0x48), p(0xD9, 0x48), p(0xDA, 0x48), - p(0xDB, 0x74), p(0xE0, 0x00), p(0xE0, 0x48), p(0xE8, 0x00), p(0xE8, 0x48), p(0xEB, 0x03), p(0xEC, 0x20), p(0xF0, 0x00), - p(0xF0, 0x0F), p(0xF0, 0x48), p(0xF0, 0xFF), p(0xF2, 0x0F), p(0xF2, 0x48), p(0xF3, 0x0F), p(0xF8, 0x01), p(0xF8, 0x1F), - p(0xF8, 0x48), p(0xF9, 0x48), p(0xFA, 0x00), p(0xFA, 0x0F), p(0xFA, 0x10), p(0xFA, 0x48), p(0xFB, 0x48), p(0xFC, 0x48), - p(0xFD, 0x48), p(0xFD, 0x90), p(0xFD, 0xFF), p(0xFE, 0x48), p(0xFE, 0x90), p(0xFE, 0xFF), p(0xFF, 0x0F), p(0xFF, 0x15), - p(0xFF, 0x48), p(0xFF, 0x4C), p(0xFF, 0x50), p(0xFF, 0x74), p(0xFF, 0x90), p(0xFF, 0xC2), p(0xFF, 0xCC), p(0xFF, 0xFF), - }); - - static constexpr inline auto scores_x1 = std::to_array({ - 0x000, 0x0C0, 0x028, 0x084, 0x1C5, 0x083, 0x11B, 0x1E3, 0x005, 0x042, 0x02F, 0x18B, 0x146, 0x08B, 0x0F6, 0x137, - 0x15B, 0x1DC, 0x10B, 0x0BD, 0x0D6, 0x129, 0x01D, 0x0C1, 0x111, 0x182, 0x065, 0x008, 0x11E, 0x016, 0x1CB, 0x17E, - 0x051, 0x1F9, 0x021, 0x034, 0x03E, 0x014, 0x1DB, 0x07C, 0x05B, 0x0C4, 0x0B7, 0x159, 0x0FA, 0x0A2, 0x102, 0x06D, - 0x0E9, 0x0DE, 0x1A1, 0x197, 0x012, 0x132, 0x141, 0x0E1, 0x1C0, 0x0A3, 0x1C6, 0x19C, 0x1AD, 0x18F, 0x1C3, 0x1D3, - 0x0CA, 0x087, 0x024, 0x00D, 0x0D1, 0x08E, 0x126, 0x134, 0x033, 0x1D0, 0x1A7, 0x181, 0x106, 0x056, 0x038, 0x0DD, - 0x1DD, 0x19F, 0x13D, 0x046, 0x10F, 0x05A, 0x053, 0x1DE, 0x1D1, 0x135, 0x1E4, 0x015, 0x144, 0x123, 0x101, 0x1E6, - 0x1EF, 0x0D4, 0x0B8, 0x160, 0x1CE, 0x15D, 0x044, 0x1FD, 0x1FF, 0x0CE, 0x0FD, 0x125, 0x194, 0x18A, 0x1CF, 0x01F, - 0x13F, 0x0C8, 0x18D, 0x127, 0x0F3, 0x1B3, 0x0BB, 0x0A4, 0x0A5, 0x011, 0x039, 0x01B, 0x045, 0x031, 0x052, 0x04B, - 0x079, 0x067, 0x0B2, 0x080, 0x0EF, 0x192, 0x08C, 0x1BA, 0x04F, 0x1EE, 0x1BF, 0x173, 0x1D4, 0x0B1, 0x1B9, 0x1F0, - 0x027, 0x1A0, 0x17C, 0x16B, 0x06C, 0x0D9, 0x171, 0x0D7, 0x131, 0x1A3, 0x1D5, 0x049, 0x190, 0x17F, 0x064, 0x1B0, - 0x195, 0x1A5, 0x047, 0x12B, 0x19E, 0x1F3, 0x0DC, 0x05D, 0x172, 0x175, 0x1E0, 0x0C5, 0x115, 0x170, 0x1D7, 0x0BE, - 0x10E, 0x0AA, 0x0C6, 0x183, 0x12E, 0x0B3, 0x1A2, 0x138, 0x1C9, 0x0E5, 0x007, 0x1BC, 0x0DB, 0x0F4, 0x1A6, 0x1D2, - 0x081, 0x19A, 0x136, 0x1AF, 0x14C, 0x076, 0x060, 0x050, 0x030, 0x07E, 0x020, 0x006, 0x00B, 0x003, 0x001, 0x004, - 0x1E7, 0x075, 0x02B, 0x072, 0x1EC, 0x13A, 0x0D8, 0x15A, 0x091, 0x009, 0x0E4, 0x0EB, 0x1F7, 0x00F, 0x199, 0x010, - 0x00C, 0x018, 0x14E, 0x1BD, 0x073, 0x1BE, 0x068, 0x152, 0x026, 0x177, 0x1A4, 0x1BB, 0x153, 0x113, 0x1FA, 0x0E8, - 0x0F0, 0x054, 0x04C, 0x179, 0x1FE, 0x0AE, 0x0E3, 0x013, 0x1AC, 0x1F5, 0x0C2, 0x178, 0x140, 0x1D8, 0x114, 0x0E0, - 0x07B, 0x09C, 0x1EB, 0x04D, 0x154, 0x0D5, 0x082, 0x0BF, 0x0F2, 0x16E, 0x02E, 0x158, 0x0FF, 0x12F, 0x05E, 0x16C, - 0x163, 0x07F, 0x1C1, 0x11A, 0x0B9, 0x09A, 0x08D, 0x128, 0x08A, 0x02C, 0x03B, 0x023, 0x0BC, 0x1EA, 0x1B5, 0x098, - 0x097, 0x02A, 0x032, 0x16A, 0x092, 0x1D6, 0x13C, 0x104, 0x1B6, 0x1B1, 0x17B, 0x1C8, 0x10D, 0x148, 0x0B4, 0x01A, - 0x03F, 0x1ED, 0x0EC, 0x0A9, 0x168, 0x119, 0x035, 0x180, 0x1AA, 0x105, 0x1FC, 0x061, 0x0ED, 0x0AD, 0x0FC, 0x11C, - 0x0E7, 0x071, 0x04E, 0x077, 0x116, 0x07A, 0x143, 0x0FB, 0x11F, 0x1DA, 0x03C, 0x0A1, 0x12A, 0x120, 0x0D0, 0x0AC, - 0x15E, 0x145, 0x112, 0x09F, 0x155, 0x089, 0x06E, 0x1E2, 0x19D, 0x164, 0x0F9, 0x13B, 0x063, 0x196, 0x1B8, 0x0E6, - 0x1CC, 0x198, 0x1F6, 0x166, 0x122, 0x107, 0x13E, 0x095, 0x10C, 0x06F, 0x088, 0x05F, 0x057, 0x025, 0x1CA, 0x06A, - 0x040, 0x0B5, 0x0F5, 0x0F8, 0x109, 0x0A6, 0x0CF, 0x147, 0x185, 0x1E8, 0x110, 0x12C, 0x169, 0x103, 0x0D3, 0x167, - 0x0DA, 0x01E, 0x043, 0x066, 0x189, 0x093, 0x099, 0x130, 0x048, 0x037, 0x191, 0x059, 0x07D, 0x19B, 0x16F, 0x062, - 0x139, 0x1E5, 0x0C7, 0x01C, 0x1B2, 0x1E9, 0x142, 0x09D, 0x0E2, 0x162, 0x1CD, 0x0F7, 0x1B7, 0x12D, 0x0F1, 0x036, - 0x03A, 0x04A, 0x0EA, 0x184, 0x0CB, 0x0FE, 0x03D, 0x1A9, 0x187, 0x0A0, 0x070, 0x055, 0x02D, 0x1FB, 0x078, 0x1F4, - 0x188, 0x0B0, 0x118, 0x150, 0x10A, 0x1AE, 0x1AB, 0x069, 0x0AF, 0x0A7, 0x1C2, 0x121, 0x17A, 0x09B, 0x0CD, 0x16D, - 0x1F1, 0x041, 0x1DF, 0x094, 0x074, 0x1F8, 0x0CC, 0x019, 0x002, 0x05C, 0x1A8, 0x0C9, 0x100, 0x086, 0x14F, 0x090, - 0x1F2, 0x149, 0x165, 0x117, 0x1E1, 0x0A8, 0x133, 0x18E, 0x0B6, 0x15C, 0x157, 0x1C7, 0x15F, 0x193, 0x0AB, 0x17D, - 0x058, 0x0EE, 0x124, 0x0C3, 0x186, 0x022, 0x06B, 0x09E, 0x029, 0x14D, 0x096, 0x161, 0x1D9, 0x156, 0x176, 0x108, - 0x0BA, 0x1B4, 0x1C4, 0x08F, 0x14B, 0x0DF, 0x11D, 0x00E, 0x017, 0x151, 0x174, 0x14A, 0x085, 0x0D2, 0x18C, 0x00A, - }); -} diff --git a/src/os/linux/MemoryProtector.cpp b/src/memory_protector/linux.cpp similarity index 97% rename from src/os/linux/MemoryProtector.cpp rename to src/memory_protector/linux.cpp index 0624d8e..f313b42 100644 --- a/src/os/linux/MemoryProtector.cpp +++ b/src/memory_protector/linux.cpp @@ -3,9 +3,9 @@ #include #include -#include "../../Utils.hpp" -#include "Common.hpp" +#include "../utils.hpp" +#include "../utils_linux.hpp" #include diff --git a/src/os/mac/MemoryProtector.cpp b/src/memory_protector/mac.cpp similarity index 100% rename from src/os/mac/MemoryProtector.cpp rename to src/memory_protector/mac.cpp diff --git a/src/os/win32/MemoryProtector.cpp b/src/memory_protector/win32.cpp similarity index 100% rename from src/os/win32/MemoryProtector.cpp rename to src/memory_protector/win32.cpp diff --git a/src/os/linux/Process.cpp b/src/process/linux.cpp similarity index 98% rename from src/os/linux/Process.cpp rename to src/process/linux.cpp index 3d66472..131bc19 100644 --- a/src/os/linux/Process.cpp +++ b/src/process/linux.cpp @@ -6,15 +6,18 @@ #include #include -#include +#include // strnlen +#include #include #include #include #include +#include +#include -#include "Common.hpp" -#include "../../Utils.hpp" +#include "../utils.hpp" +#include "../utils_linux.hpp" namespace { diff --git a/src/os/mac/Process.cpp b/src/process/mac.cpp similarity index 100% rename from src/os/mac/Process.cpp rename to src/process/mac.cpp diff --git a/src/os/win32/Process.cpp b/src/process/win32.cpp similarity index 100% rename from src/os/win32/Process.cpp rename to src/process/win32.cpp diff --git a/src/arch/x86/AVX2.cpp b/src/scanner/avx2.cpp similarity index 84% rename from src/arch/x86/AVX2.cpp rename to src/scanner/avx2.cpp index 22c352f..a7b4e56 100644 --- a/src/arch/x86/AVX2.cpp +++ b/src/scanner/avx2.cpp @@ -1,10 +1,9 @@ #include +#include #if defined(LIBHAT_X86) || defined(LIBHAT_X86_64) -#include - -#include "../../Utils.hpp" +#include "simd.hpp" #include @@ -25,8 +24,8 @@ namespace hat::detail { template LIBHAT_TARGET("avx,avx2,bmi") static const_scan_result find_pattern_avx2(const std::byte* begin, const std::byte* end, const scan_context& context) { - const auto signature = context.signature; - const auto cmpIndex = cmpeq2 ? *context.pairIndex : context.cmpIndex; + const auto signature = context.signature(); + const auto cmpIndex = context.get().cmpIndex; // 256 bit vector containing first signature byte repeated const auto firstByte = _mm256_set1_epi8(static_cast(*signature[cmpIndex])); @@ -44,7 +43,7 @@ namespace hat::detail { auto [pre, vec, post] = segment_scan<__m256i, 32, veccmp>(begin, end, signature.size(), cmpIndex); if (!pre.empty()) { - const auto result = find_pattern_single(pre.data(), pre.data() + pre.size(), context); + const auto result = find_pattern_search(pre.data(), pre.data() + pre.size(), context); if (result.has_result()) { return result; } @@ -90,23 +89,24 @@ namespace hat::detail { } if (!post.empty()) { - return find_pattern_single(post.data(), post.data() + post.size(), context); + return find_pattern_search(post.data(), post.data() + post.size(), context); } return {}; } template<> - scan_function_t resolve_scanner(scan_context& context) { - context.apply_hints({.vectorSize = 32}); - - const auto alignment = context.alignment; - const auto signature = context.signature; - const bool cmpeq2 = context.pairIndex.has_value(); - const bool veccmp = signature.size() <= 32; - - return find_specialization_switch<[]() consteval { + scan_context create_context(const scan_parameters& params) { + return create_simd_scanner<[]() consteval { return &find_pattern_avx2; - }>(alignment, cmpeq2, veccmp); + }>(params, 32); + } +} +#else +namespace hat::detail { + + template<> + scan_context create_context(const scan_parameters&) { + LIBHAT_UNREACHABLE(); } } #endif diff --git a/src/arch/x86/AVX512.cpp b/src/scanner/avx512.cpp similarity index 82% rename from src/arch/x86/AVX512.cpp rename to src/scanner/avx512.cpp index 0f7fb67..c9fa2f9 100644 --- a/src/arch/x86/AVX512.cpp +++ b/src/scanner/avx512.cpp @@ -1,10 +1,9 @@ #include +#include #if defined(LIBHAT_X86_64) && defined(LIBHAT_FEATURE_AVX512) -#include - -#include "../../Utils.hpp" +#include "simd.hpp" #include @@ -25,8 +24,8 @@ namespace hat::detail { template LIBHAT_TARGET("avx512f,avx512bw,bmi") static const_scan_result find_pattern_avx512(const std::byte* begin, const std::byte* end, const scan_context& context) { - const auto signature = context.signature; - const auto cmpIndex = cmpeq2 ? *context.pairIndex : context.cmpIndex; + const auto signature = context.signature(); + const auto cmpIndex = context.get().cmpIndex; // 512 bit vector containing first signature byte repeated const auto firstByte = _mm512_set1_epi8(static_cast(*signature[cmpIndex])); @@ -45,7 +44,7 @@ namespace hat::detail { auto [pre, vec, post] = segment_scan<__m512i, 64, veccmp>(begin, end, signature.size(), cmpIndex); if (!pre.empty()) { - const auto result = find_pattern_single(pre.data(), pre.data() + pre.size(), context); + const auto result = find_pattern_search(pre.data(), pre.data() + pre.size(), context); if (result.has_result()) { return result; } @@ -87,23 +86,24 @@ namespace hat::detail { } if (!post.empty()) { - return find_pattern_single(post.data(), post.data() + post.size(), context); + return find_pattern_search(post.data(), post.data() + post.size(), context); } return {}; } template<> - scan_function_t resolve_scanner(scan_context& context) { - context.apply_hints({.vectorSize = 64}); - - const auto alignment = context.alignment; - const auto signature = context.signature; - const bool cmpeq2 = context.pairIndex.has_value(); - const bool veccmp = signature.size() <= 64; - - return find_specialization_switch<[]() consteval { + scan_context create_context(const scan_parameters& params) { + return create_simd_scanner<[]() consteval { return &find_pattern_avx512; - }>(alignment, cmpeq2, veccmp); + }>(params, 64); + } +} +#else +namespace hat::detail { + + template<> + scan_context create_context(const scan_parameters&) { + LIBHAT_UNREACHABLE(); } } #endif diff --git a/src/os/win32/Scanner.cpp b/src/scanner/experimental/win32.cpp similarity index 98% rename from src/os/win32/Scanner.cpp rename to src/scanner/experimental/win32.cpp index 980208a..6d564a3 100644 --- a/src/os/win32/Scanner.cpp +++ b/src/scanner/experimental/win32.cpp @@ -9,7 +9,7 @@ namespace hat::experimental { scan_result find_vtable(const std::string& className, const hat::process::module& mod) { // Tracing cross-references // Type Descriptor => Object Locator => VTable - auto sig = string_to_signature(".?AV" + className + "@@").value(); + auto sig = string_to_signature(".?AV" + className + "@@"); // TODO: Have a better solution for this // 3rd character may be 'V' for classes and 'U' for structs @@ -53,7 +53,7 @@ namespace hat::experimental { scan_result find_vtable(const std::string& className, const hat::process::module& mod) { // Tracing cross-references // Type Descriptor Name => Type Info => VTable - const auto sig = string_to_signature(std::to_string(className.size()) + className + "\0").value(); + const auto sig = string_to_signature(std::to_string(className.size()) + className + "\0"); const auto typeName = *find_pattern(sig, ".rdata", mod); if (!typeName) { return nullptr; diff --git a/src/scanner/frequency/aarch64.inl b/src/scanner/frequency/aarch64.inl new file mode 100644 index 0000000..e289aee --- /dev/null +++ b/src/scanner/frequency/aarch64.inl @@ -0,0 +1,103 @@ +// Top 512 byte pair occurrences on 1 byte alignment, sorted. Sourced from all PE (.exe and .dll) files included in +// the "clang+llvm-22.1.8-aarch64-pc-windows-msvc" archive. This list accounts for ~50.9% of all byte pairs. +static constexpr auto pairs_x1 = std::to_array>({ + p(0x00, 0x00), p(0x00, 0x01), p(0x00, 0x08), p(0x00, 0x11), p(0x00, 0x12), p(0x00, 0x14), p(0x00, 0x20), p(0x00, 0x2A), + p(0x00, 0x34), p(0x00, 0x35), p(0x00, 0x36), p(0x00, 0x37), p(0x00, 0x39), p(0x00, 0x40), p(0x00, 0x51), p(0x00, 0x54), + p(0x00, 0x71), p(0x00, 0x79), p(0x00, 0x80), p(0x00, 0x90), p(0x00, 0x91), p(0x00, 0x94), p(0x00, 0xA9), p(0x00, 0xAA), + p(0x00, 0xB0), p(0x00, 0xB4), p(0x00, 0xB5), p(0x00, 0xB9), p(0x00, 0xD0), p(0x00, 0xD1), p(0x00, 0xF0), p(0x00, 0xF1), + p(0x00, 0xF9), p(0x00, 0xFD), p(0x01, 0x00), p(0x01, 0x01), p(0x01, 0x05), p(0x01, 0x08), p(0x01, 0x09), p(0x01, 0x0A), + p(0x01, 0x0B), p(0x01, 0x0C), p(0x01, 0x15), p(0x01, 0x3F), p(0x01, 0x40), p(0x01, 0x54), p(0x01, 0x71), p(0x01, 0x80), + p(0x01, 0x90), p(0x01, 0x91), p(0x01, 0xA9), p(0x01, 0xAA), p(0x01, 0xB0), p(0x01, 0xB9), p(0x01, 0xD0), p(0x01, 0xD1), + p(0x01, 0xF0), p(0x01, 0xF9), p(0x02, 0x00), p(0x02, 0x01), p(0x02, 0x05), p(0x02, 0x08), p(0x02, 0x40), p(0x02, 0x80), + p(0x02, 0x91), p(0x02, 0xA9), p(0x02, 0xAA), p(0x02, 0xF9), p(0x03, 0x00), p(0x03, 0x01), p(0x03, 0x02), p(0x03, 0x03), + p(0x03, 0x04), p(0x03, 0x05), p(0x03, 0x08), p(0x03, 0x09), p(0x03, 0x13), p(0x03, 0x14), p(0x03, 0x15), p(0x03, 0x16), + p(0x03, 0x17), p(0x03, 0x18), p(0x03, 0x19), p(0x03, 0x1A), p(0x03, 0x1B), p(0x03, 0x1C), p(0x03, 0x1F), p(0x03, 0x40), + p(0x03, 0x5F), p(0x03, 0x80), p(0x03, 0x91), p(0x03, 0xA9), p(0x03, 0xAA), p(0x04, 0x00), p(0x04, 0x40), p(0x04, 0x80), + p(0x04, 0x91), p(0x04, 0xA9), p(0x05, 0x00), p(0x05, 0x01), p(0x05, 0x40), p(0x05, 0x91), p(0x06, 0x00), p(0x06, 0x40), + p(0x06, 0x80), p(0x06, 0x91), p(0x07, 0x00), p(0x07, 0x40), p(0x07, 0x80), p(0x07, 0x91), p(0x08, 0x00), p(0x08, 0x01), + p(0x08, 0x05), p(0x08, 0x09), p(0x08, 0x10), p(0x08, 0x11), p(0x08, 0x21), p(0x08, 0x40), p(0x08, 0x41), p(0x08, 0x61), + p(0x08, 0x81), p(0x08, 0x8B), p(0x08, 0x91), p(0x08, 0xA1), p(0x08, 0xAA), p(0x08, 0xC1), p(0x08, 0xCB), p(0x08, 0xEB), + p(0x09, 0x00), p(0x09, 0x01), p(0x09, 0x05), p(0x09, 0x40), p(0x09, 0x6B), p(0x09, 0x8B), p(0x09, 0x91), p(0x09, 0xEB), + p(0x0A, 0x00), p(0x0A, 0x01), p(0x0A, 0x40), p(0x0A, 0xEB), p(0x0B, 0x00), p(0x0B, 0x40), p(0x0C, 0x00), p(0x0D, 0x00), + p(0x0D, 0x40), p(0x0E, 0x00), p(0x0E, 0x40), p(0x0F, 0x00), p(0x0F, 0x40), p(0x10, 0x00), p(0x10, 0x40), p(0x11, 0x00), + p(0x11, 0x40), p(0x12, 0x00), p(0x12, 0x40), p(0x13, 0x00), p(0x13, 0x40), p(0x13, 0xAA), p(0x14, 0x00), p(0x14, 0xAA), + p(0x14, 0xE0), p(0x14, 0xE8), p(0x14, 0xEB), p(0x15, 0x00), p(0x15, 0xAA), p(0x15, 0xEB), p(0x16, 0x40), p(0x16, 0xAA), + p(0x17, 0x00), p(0x17, 0x08), p(0x17, 0x40), p(0x17, 0x9F), p(0x17, 0xAA), p(0x17, 0xE0), p(0x17, 0xE8), p(0x18, 0xAA), + p(0x19, 0x00), p(0x19, 0xAA), p(0x1A, 0x00), p(0x1A, 0x40), p(0x1A, 0xAA), p(0x1B, 0x00), p(0x1B, 0x40), p(0x1B, 0xAA), + p(0x1C, 0xAA), p(0x1D, 0x00), p(0x1F, 0x00), p(0x1F, 0x01), p(0x1F, 0x05), p(0x1F, 0x09), p(0x1F, 0x20), p(0x1F, 0x2A), + p(0x1F, 0x40), p(0x1F, 0x41), p(0x1F, 0x7C), p(0x1F, 0xAA), p(0x20, 0x00), p(0x20, 0x01), p(0x20, 0x80), p(0x20, 0xD4), + p(0x21, 0x00), p(0x21, 0x40), p(0x22, 0x00), p(0x22, 0x40), p(0x23, 0x00), p(0x23, 0x01), p(0x23, 0x40), p(0x27, 0x00), + p(0x27, 0x40), p(0x28, 0x00), p(0x28, 0x01), p(0x29, 0x00), p(0x29, 0x01), p(0x29, 0x05), p(0x2A, 0x00), p(0x2A, 0xE0), + p(0x2B, 0x00), p(0x2B, 0x40), p(0x2F, 0x00), p(0x2F, 0x40), p(0x33, 0x00), p(0x33, 0x40), p(0x39, 0x08), p(0x39, 0x1F), + p(0x39, 0xE8), p(0x3D, 0x00), p(0x3D, 0xE0), p(0x3F, 0x00), p(0x3F, 0x01), p(0x3F, 0x05), p(0x3F, 0xD6), p(0x40, 0x00), + p(0x40, 0x01), p(0x40, 0x39), p(0x40, 0x79), p(0x40, 0x91), p(0x40, 0x92), p(0x40, 0xA9), p(0x40, 0xB1), p(0x40, 0xB9), + p(0x40, 0xF2), p(0x40, 0xF8), p(0x40, 0xF9), p(0x40, 0xFD), p(0x41, 0x00), p(0x41, 0x39), p(0x41, 0xA9), p(0x41, 0xB9), + p(0x41, 0xF8), p(0x41, 0xF9), p(0x42, 0x00), p(0x42, 0xA9), p(0x42, 0xB9), p(0x42, 0xF9), p(0x43, 0x00), p(0x43, 0x01), + p(0x43, 0x40), p(0x43, 0xA9), p(0x43, 0xF9), p(0x44, 0xA9), p(0x44, 0xF9), p(0x45, 0xF9), p(0x4A, 0x01), p(0x51, 0x1F), + p(0x52, 0x08), p(0x52, 0x09), p(0x52, 0x1F), p(0x52, 0xE0), p(0x52, 0xE3), p(0x52, 0xE8), p(0x53, 0xC2), p(0x54, 0x08), + p(0x54, 0x09), p(0x54, 0x1F), p(0x54, 0x28), p(0x54, 0x29), p(0x54, 0x3F), p(0x54, 0x68), p(0x54, 0x88), p(0x54, 0xE0), + p(0x54, 0xE8), p(0x54, 0xE9), p(0x54, 0xFE), p(0x5B, 0x01), p(0x5B, 0x41), p(0x5F, 0x01), p(0x5F, 0xD6), p(0x5F, 0xF8), + p(0x60, 0x00), p(0x60, 0x02), p(0x61, 0x00), p(0x62, 0x00), p(0x63, 0x00), p(0x68, 0x00), p(0x68, 0x02), p(0x68, 0x0A), + p(0x69, 0x02), p(0x6B, 0x01), p(0x71, 0x61), p(0x7C, 0x92), p(0x7C, 0xD3), p(0x7D, 0x92), p(0x7D, 0xD3), p(0x7F, 0x01), + p(0x7F, 0x02), p(0x80, 0x00), p(0x80, 0x3D), p(0x80, 0x52), p(0x81, 0x00), p(0x82, 0x00), p(0x83, 0x00), p(0x83, 0x01), + p(0x83, 0x02), p(0x88, 0x00), p(0x88, 0x02), p(0x88, 0x9A), p(0x89, 0x9A), p(0x90, 0x08), p(0x91, 0x00), p(0x91, 0x01), + p(0x91, 0x02), p(0x91, 0x03), p(0x91, 0x08), p(0x91, 0x1F), p(0x91, 0x22), p(0x91, 0xC0), p(0x91, 0xE0), p(0x91, 0xE1), + p(0x91, 0xE2), p(0x91, 0xE3), p(0x91, 0xE4), p(0x91, 0xE8), p(0x91, 0xE9), p(0x91, 0xFF), p(0x94, 0x20), p(0x94, 0x68), + p(0x94, 0xE0), p(0x94, 0xE1), p(0x94, 0xE8), p(0x97, 0x20), p(0x97, 0x68), p(0x97, 0xE0), p(0x97, 0xE1), p(0x97, 0xE8), + p(0x9F, 0x02), p(0x9F, 0x1A), p(0xA0, 0x00), p(0xA1, 0x00), p(0xA3, 0x00), p(0xA8, 0x02), p(0xA8, 0xC0), p(0xA9, 0x08), + p(0xA9, 0x1F), p(0xA9, 0xE0), p(0xA9, 0xE8), p(0xA9, 0xF3), p(0xA9, 0xF5), p(0xA9, 0xF7), p(0xA9, 0xF9), p(0xA9, 0xFE), + p(0xA9, 0xFF), p(0xAA, 0x00), p(0xAA, 0x01), p(0xAA, 0x02), p(0xAA, 0x03), p(0xAA, 0x08), p(0xAA, 0x1F), p(0xAA, 0xE0), + p(0xAA, 0xE1), p(0xAA, 0xE2), p(0xAA, 0xE3), p(0xAA, 0xE4), p(0xAA, 0xE5), p(0xAA, 0xE8), p(0xAA, 0xF3), p(0xAA, 0xF4), + p(0xAA, 0xF5), p(0xAA, 0xF6), p(0xAA, 0xF7), p(0xAA, 0xFE), p(0xAA, 0xFF), p(0xB0, 0x08), p(0xB4, 0x08), p(0xB4, 0xE0), + p(0xB9, 0x08), p(0xB9, 0x09), p(0xB9, 0x1F), p(0xB9, 0x29), p(0xB9, 0x3F), p(0xB9, 0x68), p(0xB9, 0xE0), p(0xB9, 0xE1), + p(0xB9, 0xE8), p(0xB9, 0xE9), p(0xB9, 0xFF), p(0xBF, 0x02), p(0xC0, 0x03), p(0xC0, 0x3D), p(0xC1, 0x00), p(0xC2, 0xA8), + p(0xC3, 0x00), p(0xC3, 0x01), p(0xC8, 0x02), p(0xD0, 0x08), p(0xD1, 0xF3), p(0xD4, 0xFF), p(0xD6, 0xE0), p(0xDF, 0x02), + p(0xE0, 0x03), p(0xE0, 0x07), p(0xE0, 0x0F), p(0xE0, 0x23), p(0xE0, 0x43), p(0xE0, 0x63), p(0xE0, 0x83), p(0xE0, 0xC3), + p(0xE1, 0x03), p(0xE1, 0x23), p(0xE1, 0x43), p(0xE1, 0x63), p(0xE1, 0x83), p(0xE1, 0xC3), p(0xE2, 0x03), p(0xE3, 0x00), + p(0xE3, 0x03), p(0xE4, 0x00), p(0xE4, 0x03), p(0xE5, 0x03), p(0xE6, 0x03), p(0xE7, 0x03), p(0xE8, 0x03), p(0xE8, 0x07), + p(0xE8, 0x0B), p(0xE8, 0x0F), p(0xE8, 0x13), p(0xE8, 0x17), p(0xE8, 0x23), p(0xE8, 0x27), p(0xE8, 0x43), p(0xE9, 0x03), + p(0xEA, 0x03), p(0xEB, 0x01), p(0xEB, 0x40), p(0xEB, 0x61), p(0xEB, 0xA1), p(0xEB, 0xC1), p(0xEB, 0xE1), p(0xED, 0x7C), + p(0xF0, 0x08), p(0xF1, 0x7D), p(0xF3, 0x03), p(0xF3, 0x53), p(0xF4, 0x03), p(0xF5, 0x03), p(0xF5, 0x5B), p(0xF5, 0x7B), + p(0xF6, 0x03), p(0xF7, 0x03), p(0xF7, 0x63), p(0xF8, 0x03), p(0xF9, 0x00), p(0xF9, 0x01), p(0xF9, 0x02), p(0xF9, 0x03), + p(0xF9, 0x08), p(0xF9, 0x09), p(0xF9, 0x0A), p(0xF9, 0x1F), p(0xF9, 0x20), p(0xF9, 0x21), p(0xF9, 0x28), p(0xF9, 0x29), + p(0xF9, 0x2A), p(0xF9, 0x3F), p(0xF9, 0x40), p(0xF9, 0x48), p(0xF9, 0x68), p(0xF9, 0x69), p(0xF9, 0x6B), p(0xF9, 0x7F), + p(0xF9, 0x88), p(0xF9, 0xA8), p(0xF9, 0xC8), p(0xF9, 0xE0), p(0xF9, 0xE1), p(0xF9, 0xE2), p(0xF9, 0xE8), p(0xF9, 0xE9), + p(0xF9, 0xEA), p(0xF9, 0xF3), p(0xF9, 0xF4), p(0xF9, 0xF5), p(0xF9, 0xF7), p(0xF9, 0xFB), p(0xF9, 0xFF), p(0xFA, 0x03), + p(0xFA, 0xFF), p(0xFB, 0x73), p(0xFB, 0xFF), p(0xFC, 0xFF), p(0xFD, 0xFF), p(0xFE, 0x0B), p(0xFE, 0xFF), p(0xFF, 0x03), + p(0xFF, 0x17), p(0xFF, 0x43), p(0xFF, 0x54), p(0xFF, 0x83), p(0xFF, 0x97), p(0xFF, 0xB4), p(0xFF, 0xC3), p(0xFF, 0xFF), +}); + +static constexpr auto scores_x1 = std::to_array({ + 0x002, 0x040, 0x0D9, 0x04F, 0x0A3, 0x00E, 0x06F, 0x12A, 0x048, 0x0F0, 0x07E, 0x0AE, 0x06E, 0x032, 0x05F, 0x001, + 0x011, 0x0F4, 0x00D, 0x087, 0x006, 0x043, 0x092, 0x018, 0x086, 0x024, 0x0B8, 0x019, 0x08F, 0x0B5, 0x074, 0x01B, + 0x004, 0x0ED, 0x00A, 0x078, 0x14C, 0x073, 0x021, 0x071, 0x0C9, 0x18B, 0x1C0, 0x08C, 0x01C, 0x1A0, 0x05E, 0x046, + 0x10B, 0x027, 0x0A2, 0x05D, 0x114, 0x156, 0x112, 0x145, 0x110, 0x0A6, 0x016, 0x0EE, 0x12C, 0x137, 0x01E, 0x0CA, + 0x04E, 0x0DF, 0x0C6, 0x1A6, 0x009, 0x028, 0x05C, 0x0CF, 0x149, 0x1E7, 0x057, 0x16E, 0x013, 0x01A, 0x02A, 0x033, + 0x054, 0x076, 0x0A1, 0x0D3, 0x106, 0x171, 0x010, 0x072, 0x036, 0x0DB, 0x081, 0x126, 0x195, 0x050, 0x14E, 0x15D, + 0x0B7, 0x184, 0x00C, 0x155, 0x03E, 0x0E2, 0x04C, 0x066, 0x1D5, 0x101, 0x04A, 0x056, 0x1FE, 0x152, 0x02E, 0x026, + 0x058, 0x15A, 0x17B, 0x16D, 0x0D1, 0x0E6, 0x119, 0x1D7, 0x12D, 0x0CC, 0x13D, 0x150, 0x098, 0x136, 0x10E, 0x089, + 0x038, 0x096, 0x191, 0x08B, 0x0EC, 0x138, 0x1FD, 0x03B, 0x077, 0x1FF, 0x06A, 0x190, 0x068, 0x09E, 0x12B, 0x0D2, + 0x1A2, 0x133, 0x0E3, 0x0C5, 0x097, 0x117, 0x153, 0x0B2, 0x0F6, 0x0FB, 0x0E4, 0x0A9, 0x0D5, 0x014, 0x179, 0x01F, + 0x120, 0x1EB, 0x11D, 0x130, 0x02C, 0x180, 0x1E3, 0x03D, 0x0D4, 0x1E2, 0x0DC, 0x1CF, 0x064, 0x05A, 0x16A, 0x093, + 0x129, 0x0BF, 0x199, 0x13A, 0x0F9, 0x100, 0x108, 0x15F, 0x1CB, 0x11A, 0x03F, 0x015, 0x053, 0x1B9, 0x1EC, 0x02D, + 0x0E1, 0x167, 0x1CA, 0x025, 0x045, 0x10F, 0x146, 0x080, 0x052, 0x11B, 0x065, 0x13C, 0x04D, 0x1CD, 0x0DD, 0x169, + 0x139, 0x0AB, 0x10C, 0x0E0, 0x095, 0x0FA, 0x18F, 0x1DF, 0x148, 0x16B, 0x1F1, 0x19E, 0x18D, 0x1C3, 0x1F9, 0x0A4, + 0x1E1, 0x14F, 0x1E4, 0x161, 0x061, 0x160, 0x085, 0x0A7, 0x1F5, 0x029, 0x0D0, 0x1DD, 0x143, 0x0B3, 0x1A1, 0x007, + 0x1CE, 0x144, 0x000, 0x1B3, 0x079, 0x1FB, 0x07B, 0x0C7, 0x15B, 0x039, 0x0BA, 0x0C0, 0x1AC, 0x0AD, 0x088, 0x111, + 0x1ED, 0x103, 0x1A8, 0x165, 0x1BD, 0x1AD, 0x16C, 0x1AF, 0x0D6, 0x1BE, 0x19D, 0x173, 0x1DC, 0x13B, 0x1C7, 0x09D, + 0x0FF, 0x0B0, 0x172, 0x1A4, 0x187, 0x124, 0x17A, 0x044, 0x082, 0x125, 0x170, 0x1FA, 0x1C1, 0x0D7, 0x037, 0x185, + 0x11F, 0x142, 0x0A5, 0x14A, 0x0AA, 0x192, 0x0AF, 0x183, 0x1DE, 0x198, 0x197, 0x19C, 0x182, 0x132, 0x109, 0x188, + 0x1DA, 0x164, 0x069, 0x003, 0x0F1, 0x11C, 0x06B, 0x131, 0x1CC, 0x1B6, 0x0FD, 0x17D, 0x196, 0x1D3, 0x17E, 0x1EA, + 0x116, 0x1F7, 0x0C1, 0x0CB, 0x1A7, 0x099, 0x020, 0x02F, 0x07F, 0x0EB, 0x1F8, 0x094, 0x1D1, 0x1BA, 0x1AA, 0x151, + 0x060, 0x123, 0x063, 0x09A, 0x1B5, 0x09B, 0x186, 0x075, 0x1A3, 0x0B4, 0x1C6, 0x11E, 0x113, 0x166, 0x14D, 0x1D2, + 0x0AC, 0x1DB, 0x1F0, 0x06D, 0x03A, 0x083, 0x0D8, 0x0B6, 0x070, 0x12E, 0x134, 0x1BB, 0x1B0, 0x059, 0x1BC, 0x07C, + 0x030, 0x049, 0x0C4, 0x121, 0x1B1, 0x09C, 0x14B, 0x12F, 0x13F, 0x1E8, 0x1F3, 0x1E6, 0x15C, 0x1E0, 0x122, 0x105, + 0x062, 0x154, 0x07D, 0x1B8, 0x1C9, 0x1C4, 0x0E8, 0x1F6, 0x0DE, 0x128, 0x174, 0x19B, 0x035, 0x08A, 0x15E, 0x1B7, + 0x0BC, 0x19F, 0x1C5, 0x1D9, 0x0B1, 0x127, 0x0E5, 0x1D8, 0x005, 0x0F2, 0x194, 0x0C8, 0x0F7, 0x1D0, 0x0CD, 0x135, + 0x00F, 0x118, 0x0F8, 0x193, 0x104, 0x163, 0x01D, 0x177, 0x042, 0x1C8, 0x09F, 0x0DA, 0x13E, 0x1E5, 0x034, 0x0FC, + 0x1BF, 0x181, 0x176, 0x1C2, 0x168, 0x10A, 0x189, 0x0C3, 0x18C, 0x1AE, 0x102, 0x1D4, 0x18E, 0x1AB, 0x1FC, 0x140, + 0x1EE, 0x0BB, 0x03C, 0x023, 0x04B, 0x067, 0x041, 0x162, 0x091, 0x0BE, 0x084, 0x0E9, 0x051, 0x0C2, 0x1F4, 0x107, + 0x012, 0x06C, 0x157, 0x022, 0x18A, 0x1EF, 0x0A0, 0x0BD, 0x1E9, 0x10D, 0x1A9, 0x158, 0x0A8, 0x1F2, 0x0B9, 0x17C, + 0x0FE, 0x16F, 0x1B2, 0x02B, 0x047, 0x115, 0x031, 0x090, 0x1B4, 0x08D, 0x175, 0x0EF, 0x17F, 0x19A, 0x07A, 0x1A5, + 0x1D6, 0x147, 0x178, 0x0F3, 0x08E, 0x159, 0x055, 0x0CE, 0x008, 0x0F5, 0x017, 0x0E7, 0x05B, 0x141, 0x0EA, 0x00B, +}); diff --git a/src/scanner/frequency/x86_64.inl b/src/scanner/frequency/x86_64.inl new file mode 100644 index 0000000..e84e487 --- /dev/null +++ b/src/scanner/frequency/x86_64.inl @@ -0,0 +1,103 @@ +// Top 512 byte pair occurrences on 1 byte alignment, sorted. Sourced from multiple executables compiled for +// Windows using MSVC, ranging from versions 19.16 to 19.42. This list accounts for ~60.4% of all byte pairs. +static constexpr auto pairs_x1 = std::to_array>({ + p(0x00, 0x00), p(0x00, 0x01), p(0x00, 0x0F), p(0x00, 0x10), p(0x00, 0x33), p(0x00, 0x41), p(0x00, 0x44), p(0x00, 0x45), + p(0x00, 0x48), p(0x00, 0x49), p(0x00, 0x4C), p(0x00, 0x4D), p(0x00, 0x66), p(0x00, 0x72), p(0x00, 0x74), p(0x00, 0x75), + p(0x00, 0x80), p(0x00, 0x89), p(0x00, 0x8B), p(0x00, 0x90), p(0x00, 0xC6), p(0x00, 0xC7), p(0x00, 0xE8), p(0x00, 0xE9), + p(0x00, 0xEB), p(0x00, 0xF3), p(0x00, 0xFF), p(0x01, 0x00), p(0x01, 0x0F), p(0x01, 0x48), p(0x01, 0x4C), p(0x01, 0x74), + p(0x01, 0x75), p(0x01, 0xBA), p(0x02, 0x00), p(0x02, 0x48), p(0x03, 0x00), p(0x03, 0x48), p(0x03, 0x4C), p(0x04, 0x00), + p(0x04, 0x48), p(0x05, 0x00), p(0x05, 0x48), p(0x05, 0xE8), p(0x06, 0x00), p(0x06, 0x48), p(0x07, 0x00), p(0x07, 0x48), + p(0x07, 0xFF), p(0x08, 0x00), p(0x08, 0x01), p(0x08, 0x0F), p(0x08, 0x48), p(0x08, 0x49), p(0x08, 0x4C), p(0x08, 0x83), + p(0x08, 0xE8), p(0x08, 0xFF), p(0x09, 0x00), p(0x09, 0x48), p(0x0A, 0x00), p(0x0B, 0x48), p(0x0C, 0x00), p(0x0C, 0x48), + p(0x0C, 0x83), p(0x0F, 0x00), p(0x0F, 0x10), p(0x0F, 0x11), p(0x0F, 0x1F), p(0x0F, 0x28), p(0x0F, 0x29), p(0x0F, 0x48), + p(0x0F, 0x57), p(0x0F, 0x58), p(0x0F, 0x59), p(0x0F, 0x6F), p(0x0F, 0x76), p(0x0F, 0x7F), p(0x0F, 0x84), p(0x0F, 0x85), + p(0x0F, 0x87), p(0x0F, 0x95), p(0x0F, 0xAF), p(0x0F, 0xB6), p(0x0F, 0xB7), p(0x0F, 0xC1), p(0x10, 0x00), p(0x10, 0x01), + p(0x10, 0x05), p(0x10, 0x0F), p(0x10, 0x44), p(0x10, 0x48), p(0x10, 0x49), p(0x10, 0x4C), p(0x10, 0x72), p(0x10, 0xE8), + p(0x11, 0x00), p(0x11, 0x44), p(0x11, 0x45), p(0x11, 0x48), p(0x13, 0x48), p(0x18, 0x0F), p(0x18, 0x48), p(0x18, 0x49), + p(0x19, 0x48), p(0x1C, 0x48), p(0x1F, 0x76), p(0x20, 0x00), p(0x20, 0x01), p(0x20, 0x0F), p(0x20, 0x41), p(0x20, 0x48), + p(0x20, 0x49), p(0x20, 0x4C), p(0x20, 0x5B), p(0x20, 0x5F), p(0x20, 0xE8), p(0x20, 0xFF), p(0x24, 0x08), p(0x24, 0x10), + p(0x24, 0x18), p(0x24, 0x20), p(0x24, 0x28), p(0x24, 0x30), p(0x24, 0x38), p(0x24, 0x40), p(0x24, 0x48), p(0x24, 0x50), + p(0x24, 0x58), p(0x24, 0x60), p(0x24, 0x68), p(0x24, 0x70), p(0x24, 0x78), p(0x24, 0x80), p(0x27, 0x48), p(0x28, 0x00), + p(0x28, 0x48), p(0x28, 0x49), p(0x28, 0x4C), p(0x28, 0xE8), p(0x2B, 0x48), p(0x2B, 0xC1), p(0x2B, 0xC8), p(0x30, 0x0F), + p(0x30, 0x48), p(0x30, 0x49), p(0x30, 0x4C), p(0x30, 0xE8), p(0x33, 0xC0), p(0x33, 0xC4), p(0x33, 0xC9), p(0x33, 0xCC), + p(0x33, 0xD2), p(0x33, 0xF6), p(0x38, 0x00), p(0x38, 0x48), p(0x3B, 0xCA), p(0x40, 0x00), p(0x40, 0x08), p(0x40, 0x0F), + p(0x40, 0x10), p(0x40, 0x20), p(0x40, 0x48), p(0x40, 0x53), p(0x40, 0x88), p(0x40, 0xE8), p(0x41, 0x08), p(0x41, 0x0F), + p(0x41, 0x10), p(0x41, 0x54), p(0x41, 0x55), p(0x41, 0x56), p(0x41, 0x57), p(0x41, 0x5C), p(0x41, 0x5D), p(0x41, 0x5E), + p(0x41, 0x5F), p(0x41, 0x8B), p(0x41, 0xB8), p(0x41, 0xF8), p(0x42, 0x08), p(0x43, 0x08), p(0x43, 0x0C), p(0x43, 0x10), + p(0x43, 0x18), p(0x44, 0x0F), p(0x44, 0x24), p(0x44, 0x88), p(0x44, 0x89), p(0x44, 0x8B), p(0x44, 0x8D), p(0x45, 0x0F), + p(0x45, 0x33), p(0x46, 0x08), p(0x47, 0x08), p(0x47, 0x10), p(0x48, 0x03), p(0x48, 0x0F), p(0x48, 0x2B), p(0x48, 0x33), + p(0x48, 0x3B), p(0x48, 0x48), p(0x48, 0x81), p(0x48, 0x83), p(0x48, 0x85), p(0x48, 0x89), p(0x48, 0x8B), p(0x48, 0x8D), + p(0x48, 0xB8), p(0x48, 0xC1), p(0x48, 0xC7), p(0x48, 0xFF), p(0x49, 0x0F), p(0x49, 0x2B), p(0x49, 0x3B), p(0x49, 0x83), + p(0x49, 0x89), p(0x49, 0x8B), p(0x49, 0x8D), p(0x49, 0xF8), p(0x4B, 0x08), p(0x4C, 0x24), p(0x4C, 0x3B), p(0x4C, 0x89), + p(0x4C, 0x8B), p(0x4C, 0x8D), p(0x4D, 0x85), p(0x4D, 0x89), p(0x4D, 0x8B), p(0x50, 0x08), p(0x50, 0x48), p(0x53, 0x48), + p(0x54, 0x24), p(0x54, 0x41), p(0x55, 0x41), p(0x55, 0x48), p(0x55, 0x56), p(0x56, 0x41), p(0x56, 0x48), p(0x56, 0x57), + p(0x57, 0x41), p(0x57, 0x48), p(0x57, 0xC0), p(0x57, 0xC9), p(0x58, 0x00), p(0x58, 0x48), p(0x5B, 0xC3), p(0x5C, 0x24), + p(0x5C, 0x5F), p(0x5D, 0x41), p(0x5D, 0xC3), p(0x5E, 0x41), p(0x5E, 0x5D), p(0x5E, 0x5F), p(0x5F, 0x41), p(0x5F, 0x5E), + p(0x5F, 0xC3), p(0x60, 0x48), p(0x64, 0x24), p(0x66, 0x0F), p(0x66, 0x89), p(0x68, 0x48), p(0x6C, 0x24), p(0x70, 0x48), + p(0x72, 0x1C), p(0x74, 0x05), p(0x74, 0x24), p(0x75, 0x10), p(0x76, 0x07), p(0x78, 0x48), p(0x7C, 0x24), p(0x7F, 0x44), + p(0x7F, 0x45), p(0x80, 0x00), p(0x80, 0x48), p(0x81, 0xC4), p(0x81, 0xEC), p(0x81, 0xFA), p(0x83, 0xC0), p(0x83, 0xC1), + p(0x83, 0xC2), p(0x83, 0xC4), p(0x83, 0xEC), p(0x83, 0xF8), p(0x83, 0xFA), p(0x83, 0xFF), p(0x84, 0x00), p(0x84, 0x24), + p(0x84, 0xC0), p(0x85, 0xC0), p(0x85, 0xC9), p(0x85, 0xD2), p(0x85, 0xDB), p(0x85, 0xF6), p(0x85, 0xFF), p(0x88, 0x00), + p(0x89, 0x01), p(0x89, 0x02), p(0x89, 0x03), p(0x89, 0x05), p(0x89, 0x41), p(0x89, 0x42), p(0x89, 0x43), p(0x89, 0x44), + p(0x89, 0x45), p(0x89, 0x46), p(0x89, 0x47), p(0x89, 0x4C), p(0x89, 0x4D), p(0x89, 0x54), p(0x89, 0x5C), p(0x89, 0x5D), + p(0x89, 0x6B), p(0x89, 0x6C), p(0x89, 0x73), p(0x89, 0x74), p(0x89, 0x75), p(0x89, 0x7C), p(0x89, 0x7D), p(0x89, 0x84), + p(0x89, 0x85), p(0x8B, 0x00), p(0x8B, 0x01), p(0x8B, 0x03), p(0x8B, 0x04), p(0x8B, 0x05), p(0x8B, 0x06), p(0x8B, 0x07), + p(0x8B, 0x08), p(0x8B, 0x0D), p(0x8B, 0x40), p(0x8B, 0x41), p(0x8B, 0x42), p(0x8B, 0x43), p(0x8B, 0x44), p(0x8B, 0x45), + p(0x8B, 0x46), p(0x8B, 0x47), p(0x8B, 0x48), p(0x8B, 0x49), p(0x8B, 0x4B), p(0x8B, 0x4C), p(0x8B, 0x4D), p(0x8B, 0x4E), + p(0x8B, 0x4F), p(0x8B, 0x54), p(0x8B, 0x55), p(0x8B, 0x5B), p(0x8B, 0x5C), p(0x8B, 0x5D), p(0x8B, 0x73), p(0x8B, 0x74), + p(0x8B, 0x7C), p(0x8B, 0x80), p(0x8B, 0x85), p(0x8B, 0x8C), p(0x8B, 0x8D), p(0x8B, 0x9C), p(0x8B, 0xC0), p(0x8B, 0xC1), + p(0x8B, 0xC2), p(0x8B, 0xC3), p(0x8B, 0xC6), p(0x8B, 0xC7), p(0x8B, 0xC8), p(0x8B, 0xCB), p(0x8B, 0xCD), p(0x8B, 0xCE), + p(0x8B, 0xCF), p(0x8B, 0xD0), p(0x8B, 0xD3), p(0x8B, 0xD6), p(0x8B, 0xD7), p(0x8B, 0xD8), p(0x8B, 0xD9), p(0x8B, 0xDA), + p(0x8B, 0xE3), p(0x8B, 0xEA), p(0x8B, 0xF0), p(0x8B, 0xF1), p(0x8B, 0xF2), p(0x8B, 0xF8), p(0x8B, 0xF9), p(0x8B, 0xFA), + p(0x8C, 0x24), p(0x8D, 0x05), p(0x8D, 0x0D), p(0x8D, 0x15), p(0x8D, 0x41), p(0x8D, 0x44), p(0x8D, 0x45), p(0x8D, 0x4B), + p(0x8D, 0x4C), p(0x8D, 0x4D), p(0x8D, 0x4F), p(0x8D, 0x54), p(0x8D, 0x55), p(0x8D, 0x85), p(0x8D, 0x8A), p(0x8D, 0x8D), + p(0x8D, 0x95), p(0x8D, 0x9C), p(0x90, 0x00), p(0x90, 0x48), p(0x90, 0x4C), p(0x95, 0xC2), p(0x98, 0x00), p(0x9C, 0x24), + p(0xA0, 0x00), p(0xA8, 0x00), p(0xAA, 0xAA), p(0xB0, 0x00), p(0xB0, 0x01), p(0xB8, 0x00), p(0xC0, 0x00), p(0xC0, 0x0F), + p(0xC0, 0x48), p(0xC0, 0x74), p(0xC0, 0x75), p(0xC0, 0xF3), p(0xC0, 0xF8), p(0xC1, 0x43), p(0xC1, 0x48), p(0xC1, 0xE8), + p(0xC1, 0xF8), p(0xC2, 0x27), p(0xC2, 0x48), p(0xC3, 0x48), p(0xC3, 0xCC), p(0xC3, 0xE8), p(0xC4, 0x20), p(0xC4, 0x28), + p(0xC4, 0x30), p(0xC4, 0x48), p(0xC6, 0x44), p(0xC6, 0x45), p(0xC6, 0x48), p(0xC6, 0xF0), p(0xC7, 0x43), p(0xC7, 0x44), + p(0xC7, 0x45), p(0xC7, 0x48), p(0xC7, 0x85), p(0xC7, 0xF0), p(0xC8, 0x00), p(0xC8, 0x48), p(0xC8, 0xE8), p(0xC9, 0x0F), + p(0xC9, 0x48), p(0xC9, 0x74), p(0xC9, 0xF3), p(0xCB, 0x48), p(0xCB, 0xE8), p(0xCB, 0xFF), p(0xCC, 0x40), p(0xCC, 0x48), + p(0xCC, 0xCC), p(0xCC, 0xE8), p(0xCE, 0x48), p(0xCE, 0xE8), p(0xCF, 0x48), p(0xCF, 0xE8), p(0xD0, 0x00), p(0xD0, 0x48), + p(0xD2, 0x48), p(0xD3, 0x48), p(0xD6, 0x48), p(0xD7, 0x48), p(0xD8, 0x00), p(0xD8, 0x48), p(0xD9, 0x48), p(0xDA, 0x48), + p(0xDB, 0x74), p(0xE0, 0x00), p(0xE0, 0x48), p(0xE8, 0x00), p(0xE8, 0x48), p(0xEB, 0x03), p(0xEC, 0x20), p(0xF0, 0x00), + p(0xF0, 0x0F), p(0xF0, 0x48), p(0xF0, 0xFF), p(0xF2, 0x0F), p(0xF2, 0x48), p(0xF3, 0x0F), p(0xF8, 0x01), p(0xF8, 0x1F), + p(0xF8, 0x48), p(0xF9, 0x48), p(0xFA, 0x00), p(0xFA, 0x0F), p(0xFA, 0x10), p(0xFA, 0x48), p(0xFB, 0x48), p(0xFC, 0x48), + p(0xFD, 0x48), p(0xFD, 0x90), p(0xFD, 0xFF), p(0xFE, 0x48), p(0xFE, 0x90), p(0xFE, 0xFF), p(0xFF, 0x0F), p(0xFF, 0x15), + p(0xFF, 0x48), p(0xFF, 0x4C), p(0xFF, 0x50), p(0xFF, 0x74), p(0xFF, 0x90), p(0xFF, 0xC2), p(0xFF, 0xCC), p(0xFF, 0xFF), +}); + +static constexpr auto scores_x1 = std::to_array({ + 0x000, 0x0C0, 0x028, 0x084, 0x1C5, 0x083, 0x11B, 0x1E3, 0x005, 0x042, 0x02F, 0x18B, 0x146, 0x08B, 0x0F6, 0x137, + 0x15B, 0x1DC, 0x10B, 0x0BD, 0x0D6, 0x129, 0x01D, 0x0C1, 0x111, 0x182, 0x065, 0x008, 0x11E, 0x016, 0x1CB, 0x17E, + 0x051, 0x1F9, 0x021, 0x034, 0x03E, 0x014, 0x1DB, 0x07C, 0x05B, 0x0C4, 0x0B7, 0x159, 0x0FA, 0x0A2, 0x102, 0x06D, + 0x0E9, 0x0DE, 0x1A1, 0x197, 0x012, 0x132, 0x141, 0x0E1, 0x1C0, 0x0A3, 0x1C6, 0x19C, 0x1AD, 0x18F, 0x1C3, 0x1D3, + 0x0CA, 0x087, 0x024, 0x00D, 0x0D1, 0x08E, 0x126, 0x134, 0x033, 0x1D0, 0x1A7, 0x181, 0x106, 0x056, 0x038, 0x0DD, + 0x1DD, 0x19F, 0x13D, 0x046, 0x10F, 0x05A, 0x053, 0x1DE, 0x1D1, 0x135, 0x1E4, 0x015, 0x144, 0x123, 0x101, 0x1E6, + 0x1EF, 0x0D4, 0x0B8, 0x160, 0x1CE, 0x15D, 0x044, 0x1FD, 0x1FF, 0x0CE, 0x0FD, 0x125, 0x194, 0x18A, 0x1CF, 0x01F, + 0x13F, 0x0C8, 0x18D, 0x127, 0x0F3, 0x1B3, 0x0BB, 0x0A4, 0x0A5, 0x011, 0x039, 0x01B, 0x045, 0x031, 0x052, 0x04B, + 0x079, 0x067, 0x0B2, 0x080, 0x0EF, 0x192, 0x08C, 0x1BA, 0x04F, 0x1EE, 0x1BF, 0x173, 0x1D4, 0x0B1, 0x1B9, 0x1F0, + 0x027, 0x1A0, 0x17C, 0x16B, 0x06C, 0x0D9, 0x171, 0x0D7, 0x131, 0x1A3, 0x1D5, 0x049, 0x190, 0x17F, 0x064, 0x1B0, + 0x195, 0x1A5, 0x047, 0x12B, 0x19E, 0x1F3, 0x0DC, 0x05D, 0x172, 0x175, 0x1E0, 0x0C5, 0x115, 0x170, 0x1D7, 0x0BE, + 0x10E, 0x0AA, 0x0C6, 0x183, 0x12E, 0x0B3, 0x1A2, 0x138, 0x1C9, 0x0E5, 0x007, 0x1BC, 0x0DB, 0x0F4, 0x1A6, 0x1D2, + 0x081, 0x19A, 0x136, 0x1AF, 0x14C, 0x076, 0x060, 0x050, 0x030, 0x07E, 0x020, 0x006, 0x00B, 0x003, 0x001, 0x004, + 0x1E7, 0x075, 0x02B, 0x072, 0x1EC, 0x13A, 0x0D8, 0x15A, 0x091, 0x009, 0x0E4, 0x0EB, 0x1F7, 0x00F, 0x199, 0x010, + 0x00C, 0x018, 0x14E, 0x1BD, 0x073, 0x1BE, 0x068, 0x152, 0x026, 0x177, 0x1A4, 0x1BB, 0x153, 0x113, 0x1FA, 0x0E8, + 0x0F0, 0x054, 0x04C, 0x179, 0x1FE, 0x0AE, 0x0E3, 0x013, 0x1AC, 0x1F5, 0x0C2, 0x178, 0x140, 0x1D8, 0x114, 0x0E0, + 0x07B, 0x09C, 0x1EB, 0x04D, 0x154, 0x0D5, 0x082, 0x0BF, 0x0F2, 0x16E, 0x02E, 0x158, 0x0FF, 0x12F, 0x05E, 0x16C, + 0x163, 0x07F, 0x1C1, 0x11A, 0x0B9, 0x09A, 0x08D, 0x128, 0x08A, 0x02C, 0x03B, 0x023, 0x0BC, 0x1EA, 0x1B5, 0x098, + 0x097, 0x02A, 0x032, 0x16A, 0x092, 0x1D6, 0x13C, 0x104, 0x1B6, 0x1B1, 0x17B, 0x1C8, 0x10D, 0x148, 0x0B4, 0x01A, + 0x03F, 0x1ED, 0x0EC, 0x0A9, 0x168, 0x119, 0x035, 0x180, 0x1AA, 0x105, 0x1FC, 0x061, 0x0ED, 0x0AD, 0x0FC, 0x11C, + 0x0E7, 0x071, 0x04E, 0x077, 0x116, 0x07A, 0x143, 0x0FB, 0x11F, 0x1DA, 0x03C, 0x0A1, 0x12A, 0x120, 0x0D0, 0x0AC, + 0x15E, 0x145, 0x112, 0x09F, 0x155, 0x089, 0x06E, 0x1E2, 0x19D, 0x164, 0x0F9, 0x13B, 0x063, 0x196, 0x1B8, 0x0E6, + 0x1CC, 0x198, 0x1F6, 0x166, 0x122, 0x107, 0x13E, 0x095, 0x10C, 0x06F, 0x088, 0x05F, 0x057, 0x025, 0x1CA, 0x06A, + 0x040, 0x0B5, 0x0F5, 0x0F8, 0x109, 0x0A6, 0x0CF, 0x147, 0x185, 0x1E8, 0x110, 0x12C, 0x169, 0x103, 0x0D3, 0x167, + 0x0DA, 0x01E, 0x043, 0x066, 0x189, 0x093, 0x099, 0x130, 0x048, 0x037, 0x191, 0x059, 0x07D, 0x19B, 0x16F, 0x062, + 0x139, 0x1E5, 0x0C7, 0x01C, 0x1B2, 0x1E9, 0x142, 0x09D, 0x0E2, 0x162, 0x1CD, 0x0F7, 0x1B7, 0x12D, 0x0F1, 0x036, + 0x03A, 0x04A, 0x0EA, 0x184, 0x0CB, 0x0FE, 0x03D, 0x1A9, 0x187, 0x0A0, 0x070, 0x055, 0x02D, 0x1FB, 0x078, 0x1F4, + 0x188, 0x0B0, 0x118, 0x150, 0x10A, 0x1AE, 0x1AB, 0x069, 0x0AF, 0x0A7, 0x1C2, 0x121, 0x17A, 0x09B, 0x0CD, 0x16D, + 0x1F1, 0x041, 0x1DF, 0x094, 0x074, 0x1F8, 0x0CC, 0x019, 0x002, 0x05C, 0x1A8, 0x0C9, 0x100, 0x086, 0x14F, 0x090, + 0x1F2, 0x149, 0x165, 0x117, 0x1E1, 0x0A8, 0x133, 0x18E, 0x0B6, 0x15C, 0x157, 0x1C7, 0x15F, 0x193, 0x0AB, 0x17D, + 0x058, 0x0EE, 0x124, 0x0C3, 0x186, 0x022, 0x06B, 0x09E, 0x029, 0x14D, 0x096, 0x161, 0x1D9, 0x156, 0x176, 0x108, + 0x0BA, 0x1B4, 0x1C4, 0x08F, 0x14B, 0x0DF, 0x11D, 0x00E, 0x017, 0x151, 0x174, 0x14A, 0x085, 0x0D2, 0x18C, 0x00A, +}); diff --git a/src/arch/arm/Neon.cpp b/src/scanner/neon.cpp similarity index 86% rename from src/arch/arm/Neon.cpp rename to src/scanner/neon.cpp index 264910b..83ae6d6 100644 --- a/src/arch/arm/Neon.cpp +++ b/src/scanner/neon.cpp @@ -1,10 +1,9 @@ #include +#include #if defined(LIBHAT_ARM) || defined(LIBHAT_AARCH64) -#include - -#include "../../Utils.hpp" +#include "simd.hpp" #include @@ -52,8 +51,8 @@ namespace hat::detail { template static const_scan_result find_pattern_neon(const std::byte* begin, const std::byte* end, const scan_context& context) { - const auto signature = context.signature; - const auto cmpIndex = cmpeq2 ? *context.pairIndex : context.cmpIndex; + const auto signature = context.signature(); + const auto cmpIndex = context.get().cmpIndex; // 128 bit vector containing first signature byte repeated const auto firstByte = vdupq_n_u8(static_cast(*signature[cmpIndex])); @@ -71,7 +70,7 @@ namespace hat::detail { auto [pre, vec, post] = segment_scan(begin, end, signature.size(), cmpIndex); if (!pre.empty()) { - const auto result = find_pattern_single(pre.data(), pre.data() + pre.size(), context); + const auto result = find_pattern_search(pre.data(), pre.data() + pre.size(), context); if (result.has_result()) { return result; } @@ -115,23 +114,24 @@ namespace hat::detail { } if (!post.empty()) { - return find_pattern_single(post.data(), post.data() + post.size(), context); + return find_pattern_search(post.data(), post.data() + post.size(), context); } return {}; } template<> - scan_function_t resolve_scanner(scan_context& context) { - context.apply_hints({.vectorSize = 16}); - - const auto alignment = context.alignment; - const auto signature = context.signature; - const bool cmpeq2 = context.pairIndex.has_value(); - const bool veccmp = signature.size() <= 16; - - return find_specialization_switch<[]() consteval { + scan_context create_context(const scan_parameters& params) { + return create_simd_scanner<[]() consteval { return &find_pattern_neon; - }>(alignment, cmpeq2, veccmp); + }>(params, 16); + } +} +#else +namespace hat::detail { + + template<> + scan_context create_context(const scan_parameters&) { + LIBHAT_UNREACHABLE(); } } #endif diff --git a/src/scanner/scan_context.hpp b/src/scanner/scan_context.hpp new file mode 100644 index 0000000..daa5fc8 --- /dev/null +++ b/src/scanner/scan_context.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include + +namespace hat::detail { + + template + void scan_context::emplace(Args&&... args) { + static_assert(std::is_same_v>); + static_assert(sizeof(T) <= impl_buffer_size); + static_assert(alignof(T) <= impl_buffer_align); + + std::construct_at(reinterpret_cast(impl_buffer_.data()), std::forward(args)...); + + if constexpr (not std::is_trivially_destructible_v) { + impl_deleter_ = [](const void* buffer) { + std::destroy_at(static_cast(buffer)); + }; + } + } + + template + const T& scan_context::get() const { + return *reinterpret_cast(impl_buffer_.data()); + } +} diff --git a/src/scanner/scanner.cpp b/src/scanner/scanner.cpp new file mode 100644 index 0000000..49b8144 --- /dev/null +++ b/src/scanner/scanner.cpp @@ -0,0 +1,137 @@ +#include + +#include +#include + +#define TEST_EXT(f) \ + [](const auto& ext) -> bool { \ + if constexpr (requires { ext.f; }) { \ + return ext.f; \ + } \ + return false; \ + } + +#define TRY_SCAN_MODE(mode) \ + do { \ + if constexpr (::is_defined::value) \ + if (is_supported(scan_mode::mode)) \ + return create_context(params); \ + } while (false) + +namespace { + + template + struct is_defined : std::false_type {}; + + template<> + struct is_defined : std::true_type {}; + + template<> + struct is_defined : std::true_type {}; + + template<> + struct is_defined : std::true_type {}; + +#if (defined(LIBHAT_X86) || defined(LIBHAT_X86_64)) && defined(LIBHAT_FEATURE_SSE) + template<> + struct is_defined : std::true_type {}; +#endif + +#if defined(LIBHAT_X86) || defined(LIBHAT_X86_64) + template<> + struct is_defined : std::true_type {}; +#endif + +#if defined(LIBHAT_X86_64) && defined(LIBHAT_FEATURE_AVX512) + template<> + struct is_defined : std::true_type {}; +#endif + +#if defined(LIBHAT_ARM) || defined(LIBHAT_AARCH64) + template<> + struct is_defined : std::true_type {}; +#endif + + template + bool all_of(std::predicate auto&&... tests) { + if constexpr (is_defined::value) { + const auto& ext = hat::get_system().extensions; + return ((tests(hat::compiled_extensions) || tests(ext)) && ...); + } + return false; + } +} + +namespace hat::detail { + + bool is_supported(const scan_mode mode) { + switch (mode) { + case scan_mode::Auto: + case scan_mode::Search: + case scan_mode::Single: + return true; + case scan_mode::SSE: + return all_of(TEST_EXT(sse41)); + case scan_mode::AVX2: + return all_of(TEST_EXT(bmi), TEST_EXT(avx2)); + case scan_mode::AVX512: + return all_of(TEST_EXT(bmi), TEST_EXT(avx512f), TEST_EXT(avx512bw)); + case scan_mode::Neon: + return all_of(TEST_EXT(neon)); + } + LIBHAT_UNREACHABLE(); + } + + template<> + scan_context create_context(const scan_parameters& params) { + TRY_SCAN_MODE(AVX512); + TRY_SCAN_MODE(AVX2); + TRY_SCAN_MODE(SSE); + TRY_SCAN_MODE(Neon); + + // If none of the vectorized implementations are available/supported, then fallback to scanning per-byte + return create_context(params); + } +} + +// Validate return value const-ness for the root find_pattern impl +namespace hat { + static_assert(std::is_same_v(), + std::declval(), + std::declval()))>); + + static_assert(std::is_same_v(), + std::declval(), + std::declval()))>); + + consteval auto count_matches() { + constexpr std::array a{std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, std::byte{1}}; + constexpr hat::fixed_signature<1> s{std::byte{1}}; + + std::vector results{}; + hat::find_all_pattern(a.cbegin(), a.cend(), std::back_inserter(results), s); + return results.size(); + } + static_assert(count_matches() == 2); + + static_assert([] { + constexpr std::array a{std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, std::byte{1}}; + constexpr hat::fixed_signature<1> s{std::byte{1}}; + + std::vector results{}; + hat::find_all_pattern(a.cbegin(), a.cend(), std::back_inserter(results), s); + + return results == hat::find_all_pattern(a.cbegin(), a.cend(), s); + }()); + + static_assert([] { + constexpr std::array a{std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}, std::byte{1}}; + constexpr hat::fixed_signature<1> s{std::byte{1}}; + + std::array results{}; + const auto [scan_end, results_end] = hat::find_all_pattern(a.cbegin(), a.cend(), results.begin(), results.end(), s); + return scan_end == a.cend() && results_end == std::next(results.begin(), 2); + }()); +} diff --git a/src/Utils.hpp b/src/scanner/simd.hpp similarity index 66% rename from src/Utils.hpp rename to src/scanner/simd.hpp index 906f29b..19243c9 100644 --- a/src/Utils.hpp +++ b/src/scanner/simd.hpp @@ -1,37 +1,42 @@ #pragma once -#include -#include -#include -#include -#include - -#include +#include "scan_context.hpp" +#include "../utils.hpp" namespace hat::detail { - constexpr std::uintptr_t fast_align_down(std::uintptr_t address, std::size_t alignment) { - return address & ~static_cast(alignment - 1); - } - - constexpr std::uintptr_t fast_align_up(std::uintptr_t address, std::size_t alignment) { - return (address + alignment - 1) & ~static_cast(alignment - 1); - } + struct simd_context { + std::size_t cmpIndex{}; + }; template - auto* find_specialization_switch(const scan_alignment alignment, const bool cmpeq2, const bool veccmp) { - const auto with_alignment = [&](std::integral_constant) { + scan_context create_simd_scanner(const scan_parameters& params, const size_t width) { + const bool veccmp = params.signature.size() <= width; + auto cmpIndex = get_optimal_pair(params); + const bool cmpeq2 = cmpIndex.has_value(); + if (!cmpIndex) cmpIndex = get_optimal_byte(params); + + if (!cmpIndex) LIBHAT_UNLIKELY { + // Highly unlikely case (no elements with a 0xFF mask), but it is supported by the 'Single' implementation. + return create_context(params); + } + + const auto resolve = [&](std::integral_constant) { if (cmpeq2 && veccmp) return impl.template operator()(); if (cmpeq2) return impl.template operator()(); if (veccmp) return impl.template operator()(); return impl.template operator()(); }; - switch (alignment) { + const auto create = [&](std::integral_constant a) { + return scan_context{params.signature, resolve(a), std::type_identity{}, *cmpIndex}; + }; + + switch (params.alignment) { using enum scan_alignment; - case X1: return with_alignment(std::integral_constant{}); - case X4: return with_alignment(std::integral_constant{}); - case X16: return with_alignment(std::integral_constant{}); + case X1: return create(std::integral_constant{}); + case X4: return create(std::integral_constant{}); + case X16: return create(std::integral_constant{}); } LIBHAT_UNREACHABLE(); } diff --git a/src/scanner/single.cpp b/src/scanner/single.cpp new file mode 100644 index 0000000..dfe01e6 --- /dev/null +++ b/src/scanner/single.cpp @@ -0,0 +1,166 @@ +#include + +#include "scan_context.hpp" + +namespace { + + struct anchor_matcher { + + anchor_matcher(const hat::signature_view& signature, const std::span& anchors, const std::size_t literals) : + signature_(signature), + anchors_(anchors), + literals_(literals) {} + + [[nodiscard]] std::pair top() const { + return anchor(0); + } + + [[nodiscard]] bool matches(const std::byte* buffer) const { + for (std::size_t i = 1; i < literals_; i++) { + const auto [element, offset] = anchor(i); + if (buffer[offset] != element) { + std::swap(anchors_[i], anchors_[i - 1]); + return false; + } + } + + for (size_t i = literals_; i < anchors_.size(); i++) { + const auto [element, offset] = anchor(i); + if (buffer[offset] != element) { + return false; + } + } + + return true; + } + + [[nodiscard]] std::size_t literals() const { + return literals_; + } + + private: + [[nodiscard]] std::pair anchor(const size_t index) const { + const auto offset = anchors_[index]; + return {signature_[offset], offset}; + } + + hat::signature_view signature_; + std::span anchors_; + std::size_t literals_; + }; + + struct single_context { + + explicit single_context(const hat::detail::scan_parameters& params) { + total_ = static_cast(std::ranges::count_if(params.signature, &hat::signature_element::any)); + anchors_ = std::make_unique(total_); + auto it = anchors_.get(); + + // Add fully masked bytes + for (std::size_t i{}; auto e : params.signature) { + if (e.all()) { + *it++ = i; + } + i++; + } + literals_ = static_cast(std::distance(anchors_.get(), it)); + + // Add partially masked bytes + for (size_t i{}; auto e : params.signature) { + if (!e.all() && !e.none()) { + *it++ = i; + } + i++; + } + } + + static anchor_matcher create_matcher(const hat::detail::scan_context& context) { + const auto& std = context.get(); + return {context.signature(), {std.anchors_.get(), std.total_}, std.literals_}; + } + + private: + std::unique_ptr anchors_; + std::size_t total_{}; + std::size_t literals_{}; + }; +} + +namespace hat::detail { + + template + static const_scan_result find_pattern_single(const std::byte* begin, const std::byte* end, const scan_context& context) { + static constexpr auto stride = alignment_stride; + + const auto scanBegin = align_up(begin); + const auto scanEnd = align_up(end - context.signature().size() + 1); + if (scanBegin >= scanEnd) { + return nullptr; + } + + const auto matcher = single_context::create_matcher(context); + for (auto i = scanBegin; i != scanEnd; i += stride) { + if (matcher.literals() > 0) { + const auto [anchor, offset] = matcher.top(); + while (i != scanEnd) { + if (i[offset] == anchor) { + break; + } + i += stride; + } + if (i == scanEnd) LIBHAT_UNLIKELY break; + } + if (matcher.matches(i)) { + return i; + } + } + + return nullptr; + } + + template<> + const_scan_result find_pattern_single(const std::byte* begin, const std::byte* end, const scan_context& context) { + const auto signature = context.signature(); + const auto scanEnd = end - signature.size() + 1; + + const auto matcher = single_context::create_matcher(context); + for (auto i = begin; i != scanEnd; i++) { + // This check should get hoisted out by the optimizer + if (matcher.literals() > 0) { + const auto [anchor, offset] = matcher.top(); + + // Use std::find to efficiently find the first byte + #ifndef _MSC_VER + i = static_cast( + std::memchr(i + offset, static_cast(anchor.value()), static_cast(scanEnd - i))); + if (!i) LIBHAT_UNLIKELY break; + i -= offset; + #elif __cpp_lib_execution >= 201902L + i = std::find(std::execution::unseq, i + offset, scanEnd + offset, anchor.value()) - offset; + if (i == scanEnd) LIBHAT_UNLIKELY break; + #else + i = std::find(i + offset, scanEnd + offset, anchor.value()) - offset; + if (i == scanEnd) LIBHAT_UNLIKELY break; + #endif + } + if (matcher.matches(i)) { + return i; + } + } + return nullptr; + } + + template<> + scan_context create_context(const scan_parameters& params) { + const auto create = [&](std::integral_constant) { + return scan_context{params.signature, &find_pattern_single, std::type_identity{}, params}; + }; + switch (params.alignment) { + using enum scan_alignment; + case X1: return create(std::integral_constant{}); + case X4: return create(std::integral_constant{}); + case X16: return create(std::integral_constant{}); + } + LIBHAT_UNREACHABLE(); + } +} diff --git a/src/arch/x86/SSE.cpp b/src/scanner/sse.cpp similarity index 84% rename from src/arch/x86/SSE.cpp rename to src/scanner/sse.cpp index 9b9db84..0c525c1 100644 --- a/src/arch/x86/SSE.cpp +++ b/src/scanner/sse.cpp @@ -1,10 +1,9 @@ #include +#include #if (defined(LIBHAT_X86) || defined(LIBHAT_X86_64)) && defined(LIBHAT_FEATURE_SSE) -#include - -#include "../../Utils.hpp" +#include "simd.hpp" #include @@ -38,8 +37,8 @@ namespace hat::detail { template LIBHAT_TARGET("sse4.1") static const_scan_result find_pattern_sse(const std::byte* begin, const std::byte* end, const scan_context& context) { - const auto signature = context.signature; - const auto cmpIndex = cmpeq2 ? *context.pairIndex : context.cmpIndex; + const auto signature = context.signature(); + const auto cmpIndex = context.get().cmpIndex; // 128 bit vector containing first signature byte repeated const auto firstByte = _mm_set1_epi8(static_cast(*signature[cmpIndex])); @@ -57,7 +56,7 @@ namespace hat::detail { auto [pre, vec, post] = segment_scan<__m128i, 16, veccmp>(begin, end, signature.size(), cmpIndex); if (!pre.empty()) { - const auto result = find_pattern_single(pre.data(), pre.data() + pre.size(), context); + const auto result = find_pattern_search(pre.data(), pre.data() + pre.size(), context); if (result.has_result()) { return result; } @@ -100,23 +99,24 @@ namespace hat::detail { } if (!post.empty()) { - return find_pattern_single(post.data(), post.data() + post.size(), context); + return find_pattern_search(post.data(), post.data() + post.size(), context); } return {}; } template<> - scan_function_t resolve_scanner(scan_context& context) { - context.apply_hints({.vectorSize = 16}); - - const auto alignment = context.alignment; - const auto signature = context.signature; - const bool cmpeq2 = context.pairIndex.has_value(); - const bool veccmp = signature.size() <= 16; - - return find_specialization_switch<[]() consteval { + scan_context create_context(const scan_parameters& params) { + return create_simd_scanner<[]() consteval { return &find_pattern_sse; - }>(alignment, cmpeq2, veccmp); + }>(params, 16); + } +} +#else +namespace hat::detail { + + template<> + scan_context create_context(const scan_parameters&) { + LIBHAT_UNREACHABLE(); } } #endif diff --git a/src/arch/arm/System.cpp b/src/system/arm.cpp similarity index 100% rename from src/arch/arm/System.cpp rename to src/system/arm.cpp diff --git a/src/System.cpp b/src/system/singleton.cpp similarity index 100% rename from src/System.cpp rename to src/system/singleton.cpp diff --git a/src/os/unix/System.cpp b/src/system/unix.cpp similarity index 100% rename from src/os/unix/System.cpp rename to src/system/unix.cpp diff --git a/src/os/win32/System.cpp b/src/system/win32.cpp similarity index 100% rename from src/os/win32/System.cpp rename to src/system/win32.cpp diff --git a/src/arch/x86/System.cpp b/src/system/x86.cpp similarity index 100% rename from src/arch/x86/System.cpp rename to src/system/x86.cpp diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..9935f2c --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,127 @@ +#include + +#include +#include +#include + +#include "utils.hpp" + +namespace hat::detail { + + static constexpr std::uint16_t NUM_PAIRS = 512; + + using pair_hint_t = std::tuple< + const std::array, NUM_PAIRS>&, + const std::array& + >; + + static auto get_pair_hint(const scan_hint hints) -> std::optional { + [[maybe_unused]] constexpr auto p = [](const std::uint8_t a, const std::uint8_t b) { + return std::pair{std::byte{a}, std::byte{b}}; + }; + if (static_cast(hints & scan_hint::x86_64)) { +#ifdef LIBHAT_HINT_X86_64 +#include "scanner/frequency/x86_64.inl" + return std::tie(pairs_x1, scores_x1); +#endif + } + if (static_cast(hints & scan_hint::aarch64)) { +#ifdef LIBHAT_HINT_AARCH64 +#include "scanner/frequency/aarch64.inl" + return std::tie(pairs_x1, scores_x1); +#endif + } + return std::nullopt; + } + + static auto count_bytes(const signature_view signature) { + std::array counts{}; + for (const auto element : signature) { + const auto value = std::to_integer(element.value()); + auto& count = counts[value]; + if (element.all() && count < 0xFF) { + count++; + } + } + return counts; + } + + std::optional get_optimal_pair(const scan_parameters& params) { + const auto sig = params.signature; + + // Only utilize byte pair based scanning if the signature starts with a byte pair + if (static_cast(params.hints & scan_hint::pair0)) { + if (sig.size() >= 2 && sig[0].all() && sig[1].all()) { + return 0; + } + return {}; + } + + if (const auto pair_hint = get_pair_hint(params.hints)) { + const auto getScore = [&](const std::byte a, const std::byte b) -> std::uint16_t { + const auto& [pairs, scores] = *pair_hint; + const std::pair pair{a, b}; + const auto it = std::ranges::lower_bound(pairs, pair); + const auto index = static_cast(it - pairs.begin()); + return it != pairs.end() && *it == pair ? scores[index] : NUM_PAIRS; + }; + + std::optional> best{}; + for (auto it = sig.begin(); it != std::prev(sig.end()); it++) { + auto a = *it; + auto b = *std::next(it); + if (!a.all() || !b.all()) { + continue; + } + + const auto score = getScore(a.value(), b.value()); + if (!best || score > best->second) { + best.emplace(std::distance(sig.begin(), it), score); + } + } + + if (best) { + return best->first; + } + } + + // If no "optimal" pair was found based on hints, find the best one based on individual byte occurrences + const auto counts = count_bytes(sig); + std::optional> best{}; + for (auto it = sig.begin(); it != std::prev(sig.end()); it++) { + auto a = *it; + auto b = *std::next(it); + if (!a.all() || !b.all()) { + continue; + } + + const auto score = static_cast(counts[std::to_integer(*a)] + + counts[std::to_integer(*b)]); + if (!best || score < best->second) { + best.emplace(std::distance(sig.begin(), it), score); + if (score == 2) { + break; // minimum value + } + } + } + + if (best) { + return best->first; + } + return {}; + } + + std::optional get_optimal_byte(const scan_parameters& params) { + const auto signature = params.signature; + const auto counts = count_bytes(signature); + + auto bytes = signature | std::views::filter(&signature_element::all); + const auto min = std::ranges::min_element(bytes, std::less{}, + [&](const auto element) { return counts[std::to_integer(*element)]; }).base(); + + if (min != signature.end()) { + return std::distance(signature.begin(), min); + } + return {}; + } +} diff --git a/src/utils.hpp b/src/utils.hpp new file mode 100644 index 0000000..9868ac0 --- /dev/null +++ b/src/utils.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include + +namespace hat::detail { + + struct scan_parameters; + + constexpr std::uintptr_t fast_align_down(const std::uintptr_t address, const std::size_t alignment) { + return address & ~static_cast(alignment - 1); + } + + constexpr std::uintptr_t fast_align_up(const std::uintptr_t address, const std::size_t alignment) { + return (address + alignment - 1) & ~static_cast(alignment - 1); + } + + std::optional get_optimal_pair(const scan_parameters& params); + std::optional get_optimal_byte(const scan_parameters& params); +} diff --git a/src/os/linux/Common.hpp b/src/utils_linux.hpp similarity index 100% rename from src/os/linux/Common.hpp rename to src/utils_linux.hpp diff --git a/test/tests/Scanner.cpp b/test/tests/Scanner.cpp index e226564..0cecd3b 100644 --- a/test/tests/Scanner.cpp +++ b/test/tests/Scanner.cpp @@ -24,6 +24,12 @@ concept FindPatternTestCallback = std::invocable class FindPatternTest> : public ::testing::Test { protected: + void SetUp() override { + if (!hat::detail::is_supported(Mode)) { + GTEST_SKIP() << "Mode is not natively supported by hardware or OS"; + } + } + void run_cases( const hat::scan_alignment alignment, FindPatternTestCallback auto&& callback @@ -61,7 +67,6 @@ class FindPatternTest> }; using FindPatternTestTypes = ::testing::Types< -#if defined(LIBHAT_X86_64) || defined(LIBHAT_X86) FindPatternParameters, FindPatternParameters, FindPatternParameters, @@ -75,29 +80,34 @@ using FindPatternTestTypes = ::testing::Types< FindPatternParameters, FindPatternParameters, FindPatternParameters, -#endif -#ifdef LIBHAT_X86_64 + FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, -#endif -#if defined(LIBHAT_ARM) || defined(LIBHAT_AARCH64) + FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, -#endif + FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, FindPatternParameters, - FindPatternParameters + FindPatternParameters, + + FindPatternParameters, + FindPatternParameters, + FindPatternParameters, + FindPatternParameters, + FindPatternParameters, + FindPatternParameters >; class FindPatternTestNameGenerator { @@ -111,6 +121,7 @@ class FindPatternTestNameGenerator { template static consteval std::string_view getModeName() { if constexpr (Mode == hat::detail::scan_mode::Single) return "Single"; + else if constexpr (Mode == hat::detail::scan_mode::Search) return "Search"; else if constexpr (Mode == hat::detail::scan_mode::SSE) return "SSE"; else if constexpr (Mode == hat::detail::scan_mode::AVX2) return "AVX2"; else if constexpr (Mode == hat::detail::scan_mode::AVX512) return "AVX512";