十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PCSX2 内置的 Zycore-C:一套支撑 Zydis 反汇编引擎的跨平台 C 基础库深度解析

PCSX2 内置的 Zycore-C:一套支撑 Zydis 反汇编引擎的跨平台 C 基础库深度解析 PCSX2 内置的 Zycore-C一套支撑 Zydis 反汇编引擎的跨平台 C 基础库深度解析【免费下载链接】pcsx2PCSX2 - The Playstation 2 Emulator项目地址: https://gitcode.com/GitHub_Trending/pc/pcsx2导读ZycoreZyan Core Library for C是一套以平台无关为核心目标的 C 语言基础库它为上层代码统一提供整型/布尔类型、编译器与平台与架构检测宏、断言与工具宏、位集Bitset、字符串String以及 Vector/List 等容器类型并提供了面向无 LibC 环境的函数回退实现。在 PCSX2 仓库中Zycore 以 Zydis 反汇编器内嵌依赖的形式存在源码位于 3rdparty/zydis/dependencies/zycore并被 3rdparty/zydis/CMakeLists.txt 直接编译进 zydis 库是调试器与动态重编译器如 pcsx2/x86/ix86-32/iR5900.cpp正确解析 x86/x86-64 指令的前提。读完本文你将掌握 Zycore 的类型体系、宏机制、容器设计与无 LibC 回退策略并能看懂 PCSX2 中 Zydis/Zycore 相关代码的底层原理。一、Zycore 在 PCSX2 中的定位Zycore 在官方 README 中的自我定位是Internal library providing platform independent types, macros and a fallback for environments without LibC.面向内部使用的库提供平台无关的类型、宏以及针对无 LibC 环境的回退方案。它不是独立对外发布的工具库而是为 Zydisx86/x86-64 反汇编器这类底层解析引擎提供地基的支撑库。在 PCSX2 中它的落点非常具体3rdparty/zydis/CMakeLists.txt 把dependencies/zycore/src/下的Allocator.c、ArgParse.c、Bitset.c、Format.c、List.c、String.c、Vector.c、Zycore.c以及API/下的Memory.c、Process.c、Synchronization.c、Terminal.c、Thread.c全部直接编译进zydis静态库并把dependencies/zycore/include/Zycore/*.h作为公开头文件暴露PCSX2 的 x86 重编译器/调试器代码通过#include Zydis/Zydis.h间接引入 Zycore 的头文件见 pcsx2/x86/ix86-32/iR5900.cpp。例如该文件中自定义的反汇编 Formatter 回调直接使用ZYAN_CHECK(...)、ZyanStatus等 Zycore 提供的宏与类型来拼接符号与绝对地址输出。也就是说Zycore 表面上隐身但 PCSX2 的指令反汇编、绝对地址计算、符号格式化等调试能力都依赖这套基础类型与宏体系才能跨 MSVC/GCC/Clang 正确编译运行。二、平台无关类型体系Types.hZycore 的全部类型定义集中在 include/Zycore/Types.h 中其设计原则是无论底层是标准 LibC、还是完全没有 LibC 的裸机环境上层代码看到的类型签名永远一致。2.1 整型家族类型含义备注ZyanU8/ZyanU16/ZyanU32/ZyanU64无符号整型宽度固定与uint8_t等对齐ZyanI8/ZyanI16/ZyanI32/ZyanI64有符号整型宽度固定ZyanUSize/ZyanISize与指针等宽的尺寸/差值类型等价于size_t/ptrdiff_tZyanUPointer/ZyanIPointer指针相关整型等价于uintptr_t/intptr_t类型映射分两条路径实现Types.h有 LibC 时直接#include stdint.h/stddef.h将uint8_t、size_t、uintptr_t等一一 typedef 为Zyan*类型保证与标准库完全一致无 LibC 时ZYAN_NO_LIBCMSVC/ICC 路径使用unsigned __int8等编译器内建类型GNU 路径优先使用__UINT8_TYPE__、__UINT64_TYPE__、__SIZE_TYPE__等编译器预定义宏仅在缺少这些宏时才回退到unsigned char等基础 C 类型。对于ZyanU64在__x86_64__且非__ILP32__时使用unsigned long int否则使用unsigned long long int。这套路径还顺带定义了与stdint.h平行的极值宏ZYAN_INT8_MIN、ZYAN_UINT32_MAX、ZYAN_UINT64_MAX等确保无 LibC 环境下也能写出可移植的边界判断。有趣的是Types.h 用ZYAN_STATIC_ASSERT在编译期硬性校验所有类型的大小与符号性假设例如sizeof(ZyanU64) 8、sizeof(ZyanUPointer) sizeof(void*)任何平台上类型宽度不符都会直接编译失败从根源上杜绝移植了但类型错了的隐患。2.2 逻辑类型与指针ZyanBool底层就是ZyanU80视为假、非 0 视为真配合ZYAN_FALSE (0u)与ZYAN_TRUE (1u)使用ZyanTernaryZyanI8实现的三态类型取值为ZYAN_TERNARY_FALSE (-1)、ZYAN_TERNARY_UNKNOWN (0)、ZYAN_TERNARY_TRUE (1)用于表达未知这种既非真也非假的中间状态ZyanVoidPointer/ZyanConstVoidPointervoid*/const void*的别名ZYAN_NULL定义为((void*)0)ZyanCharPointer/ZyanConstCharPointerC 风格NUL 结尾字符串指针。三、宏体系检测、断言与工具Defines.hinclude/Zycore/Defines.h 是 Zycore 的元编程中枢它让同一份 C 代码可以在 MSVC、GCC、Clang、Intel ICC 下获得一致的宏接口。3.1 编译器 / 平台 / 架构三级检测三级检测逐层递进全部基于预定义宏优先级与语义如下Defines.h编译器ZYAN_CLANG、ZYAN_GCC、ZYAN_ICC、ZYAN_MSVC、ZYAN_BORLAND其中 Clang 同时定义ZYAN_GNUC以获得 GCC 兼容行为且 Clang-cl 还会额外定义ZYAN_CLANG_CL与ZYAN_MSVC平台ZYAN_WINDOWS、ZYAN_EMSCRIPTEN、ZYAN_WASI、ZYAN_APPLE、ZYAN_LINUX、ZYAN_FREEBSD、ZYAN_NETBSD、ZYAN_SOLARIS、ZYAN_HAIKU、ZYAN_UNIX其中所有类 Unix 平台会统一追加ZYAN_POSIX架构ZYAN_X64、ZYAN_X86、ZYAN_AARCH64、ZYAN_ARM、ZYAN_WASM、ZYAN_LOONGARCH、ZYAN_PPC64、ZYAN_PPC、ZYAN_RISCV64无法识别时直接#error Unsupported architecture detected强制终止编译内核/用户态检测到_KERNEL_MODE、KERNEL、__KERNEL__等时定义ZYAN_KERNEL否则定义ZYAN_USER调试/发布MSVC/Borland 依据_DEBUGGCC/ICC/Clang 依据NDEBUG分别定义ZYAN_DEBUG或ZYAN_RELEASE。3.2 断言与调试宏ZYAN_ASSERT(condition)运行时断言。无 LibC 时退化为(void)(condition)空操作Windows 内核模式映射到NT_ASSERT其余情况映射到标准assertZYAN_STATIC_ASSERT(x)编译期断言按标准依次尝试 C11_Static_assert、C11static_assert最终退化为用typedef声明一个长度依赖条件真假1 或 -1的数组这一经典技巧失败即编译错误Defines.hZYAN_UNREACHABLE按平台/编译器映射到__builtin_unreachable()、__assume(0)、__fastfail(0)或{ assert(0); abort(); }向编译器声明代码路径不可达。3.3 常用工具宏宏作用ZYAN_MACRO_CONCAT(x, y)/ZYAN_MACRO_CONCAT_EXPAND(x, y)用##拼接标识符EXPAND 版先展开参数再拼接ZYAN_UNUSED(x)消除未使用参数告警ZYAN_FALLTHROUGH标注 switch 中有意穿透的分支ZYAN_BITFIELD(x)声明位域的: x语法包装ZYAN_ARRAY_LENGTH(a)sizeof(a)/sizeof((a)[0])求数组元素个数ZYAN_MIN/ZYAN_MAX/ZYAN_ABS极值与绝对值ZYAN_IS_POWER_OF_2(x)判断 2 的幂注意x 0恒真ZYAN_IS_ALIGNED_TO(x, align)/ZYAN_ALIGN_UP/ZYAN_ALIGN_DOWN对齐判断与向上/向下取整仅支持 2 的幂对齐ZYAN_NEEDS_BIT(n, b)/ZYAN_BITS_TO_REPRESENT(n)判断表示 n 是否需要第 b 位、计算表示 n 所需的最少位数ZYAN_DIV64(n, divisor)Linux 内核态映射到内核的do_div否则普通除法此外还有一批编译器属性宏ZYAN_DEPRECATED、ZYAN_DLLEXPORT/ZYAN_DLLIMPORT、ZYAN_INLINE、ZYAN_NOINLINE、ZYAN_NO_SANITIZE(what)、ZYAN_PRINTF_ATTR/ZYAN_WPRINTF_ATTRprintf 风格格式化函数检查等。3.4 符号导出与版本控制ZYCORE_EXPORT/ZYCORE_NO_EXPORT静态构建ZYCORE_STATIC_BUILD时为空宏共享库构建时依据ZYCORE_SHOULD_EXPORT映射到__declspec(dllexport/dllimport)或 GCC 的__attribute__((visibility(...)))。Defines.h 中还保留了旧宏名ZYCORE_STATIC_DEFINE、Zycore_EXPORTS的兼容转换并打印改名警告Defines.hZYCORE_VERSION是 64 位版本号常量配合 include/Zycore/Zycore.h 中的ZYCORE_VERSION_MAJOR/MINOR/PATCH/BUILD四个宏可按位拆分出主/次/补丁/构建号ZycoreGetVersion()在运行时返回该值。四、LibC 抽象与无 LibC 回退LibC.hinclude/Zycore/LibC.h 是 README 中标注为 WiP进行中 的部分但它的设计已经非常清晰未定义ZYAN_NO_LIBC时直接把标准库函数/类型逐一定义为ZYAN_*别名ZYAN_MALLOC→malloc、ZYAN_FREE→free、ZYAN_MEMCPY→memcpy、ZYAN_STRLEN→strlen、ZYAN_VSNPRINTF→vsnprintf以及ZyanVAList→va_list、ZyanFile→FILE、ZYAN_STDIN/STDOUT/STDERR等定义ZYAN_NO_LIBC时则提供一组内联实现作为最后防线。作者在注释中明确承认这些实现完全不追求性能优化任何标准库实现都能轻松胜过它们其目的是为没有可用 libc 的环境提供兜底。这部分目前覆盖了全部string.h类函数ZYAN_MEMCHR、ZYAN_MEMCMP、ZYAN_MEMCPY、ZYAN_MEMMOVE正确处理源/目标重叠、ZYAN_MEMSET、ZYAN_STRCAT、ZYAN_STRCHR、ZYAN_STRCMP、ZYAN_STRCPY、ZYAN_STRLEN、ZYAN_STRTOK、ZYAN_STRSTR等而malloc/free与vsnprintf的兜底实现目前仍是注释占位无法在无内存管理器的环境里凭空实现开发者也可以定义ZYAN_CUSTOM_LIBC自行提供整套替换函数绕过内置路径。五、容器类型Vector、List、Bitset 与 StringZycore 把最常见的容器以结构体 操作函数的 C 风格实现出来这也是 README 中列出的重点能力。5.1 ZyanVector动态数组include/Zycore/Vector.h 定义的ZyanVector结构包含内存分配器指针、增长因子growth_factor、收缩阈值shrink_threshold、当前元素数size、容量capacity、单元素字节数element_size、元素析构回调destructor与数据指针。它提供三类关键行为容量策略常量最小容量为ZYAN_VECTOR_MIN_CAPACITY (1)默认增长因子为 2成倍扩容默认收缩阈值为 4元素数降到容量的 1/4 时收缩见 Vector.h构造方式支持栈上静态初始化与基于分配器的动态初始化ZyanVectorInit/ZyanVectorInitCustomBuffer等以及ZyanVectorDestroy释放操作接口ZyanVectorPushBack、ZyanVectorPopBack、ZyanVectorGet、ZyanVectorSet、ZyanVectorInsert、ZyanVectorDelete、ZyanVectorResize、ZyanVectorClear、ZyanVectorReserve等构成完整的动态数组语义。5.2 ZyanList链表include/Zycore/List.h 提供双向链表实现支持头插/尾插/中间插入、按节点遍历ZyanListNode、节点析构回调以及整表销毁适用于需要频繁插入删除、不要求随机访问的场景。5.3 ZyanBitset位集include/Zycore/Bitset.h 实现的ZyanBitset结构非常简洁——一个size字段记录位集大小内部数据则直接内嵌一个ZyanVectorZyanVector bits即用动态数组承载位数据。它提供的核心能力包括按位读写ZyanBitsetSet、ZyanBitsetGet、ZyanBitsetFlip批量清零/置位ZyanBitsetClear、ZyanBitsetSetAll集合运算ZyanBitsetAND、ZyanBitsetOR、ZyanBitsetXOR这些运算通过函数指针类型ZyanBitsetByteOperation对两个字节执行操作的回调逐字节作用于两个位集见 Bitset.h枚举已置位索引ZyanBitsetEnumeratorInitZyanBitsetEnumeratorNext支持高效遍历所有为 1 的位。5.4 ZyanString / ZyanStringView字符串include/Zycore/String.h 提供两类字符串抽象ZyanString拥有缓冲区的动态字符串内嵌ZyanVector管理字符数据支持ZyanStringInit、ZyanStringAppend、ZyanStringInsert、ZyanStringReplace、ZyanStringToLowerCase/UpperCase以及格式化为子串视图等操作ZyanStringView只读视图仅指向已有字符串的一段区间不拥有数据适合作为函数参数避免拷贝。六、配套设施分配器、状态码与原子操作除 README 列出的能力外Zycore 还提供了一批支撑性模块共同构成完整的基础设施分配器抽象include/Zycore/Allocator.hZyanAllocator将malloc/calloc/realloc/free包装成可替换的分配器接口容器可通过它实现自定义内存管理状态码体系include/Zycore/Status.hZyanStatus是 32 位状态码ZYAN_MAKE_STATUS(error, module, code)把是否错误(1 位) 模块 ID(11 位) 具体错误码(20 位)打包成单一值ZYAN_SUCCESS/ZYAN_FAILED用于判断成败ZYAN_CHECK(status)则是在失败时直接return状态码的快速失败惯用法。模块 ID 已预定义ZYAN_MODULE_ZYCORE、ZYAN_MODULE_ARGPARSE等。PCSX2 中 Zydis 的 Formatter 回调就大量使用ZYAN_CHECK链式传播错误原子操作include/Zycore/Atomic.h 及其Internal/AtomicGNU.h、AtomicMSVC.h分别基于 GCC 内建原子与 MSVC 的Interlocked*函数族提供跨平台原子读写/加减OS API 封装include/Zycore/API/Memory.h、Process.h、Synchronization.h、Terminal.h、Thread.h将内存映射、进程、同步原语、终端 IO、线程等系统能力统一封装Windows 走 Win32 API、POSIX 平台走 pthread/mmap 等命令行解析include/Zycore/ArgParse.h提供参数解析器格式化include/Zycore/Format.h提供格式化输出能力对象操作include/Zycore/Object.h与比较器include/Zycore/Comparison.h则为容器提供元素析构回调与比较回调的通用定义。七、编译集成方式与使用前提Zycore 不是一个需要单独安装的系统库而是作为 Zydis 的源码依赖直接参与构建在 PCSX2 中zycore 的全部.c与.h被 3rdparty/zydis/CMakeLists.txt 显式列为zydis库的源文件与头文件与 Zydis 自身的src/Decoder.c、src/Formatter*.c等编译进同一目标最终由 PCSX2 的 CMake 体系参见根目录 CMakeLists.txt链接进模拟器使用方只需#include Zycore/Zycore.h主入口包含类型定义并声明ZycoreGetVersion或按需引入Zycore/Types.h、Zycore/Vector.h等细分头文件由于 zycore 的所有头文件都带有完善的extern C保护如 Zycore.hC 项目如 PCSX2 的重编译器与调试器代码可以直接包含而不必担心名字修饰问题需要无 LibC 环境时编译期定义ZYAN_NO_LIBC即可切换到内建回退实现如需完全自定义替换函数则定义ZYAN_CUSTOM_LIBC并提供自己的实现。八、源码阅读路线图如果希望深入理解 Zycore 的每个模块可以沿以下路径在仓库内继续探索全部路径相对于仓库根目录include/Zycore/Types.h类型体系 编译期大小/符号性校验include/Zycore/Defines.h检测宏、断言、工具宏、导出宏include/Zycore/LibC.hLibC 别名与无 LibC 内联回退实现include/Zycore/Vector.h、include/Zycore/List.h、include/Zycore/Bitset.h、include/Zycore/String.h四类容器/字符串include/Zycore/Status.h、include/Zycore/Allocator.h、include/Zycore/Atomic.h状态码、分配器、原子操作落地示例pcsx2/x86/ix86-32/iR5900.cpp 中 Zydis Formatter 回调对ZyanStatus、ZYAN_CHECK的调用可以直观看到这些基础设施在生产代码中的真实用法。结语Zycore 的定位决定了它的价值不在于功能花哨而在于稳定与可移植从整型宽度、布尔语义到编译器/平台/架构检测再到无 LibC 环境下的内联回退它把写一次、处处编译这件事做到了 C 语言能实现的极致。在 PCSX2 中正是这套基础库支撑着 Zydis 反汇编器在多编译器、多平台下稳定工作从而为模拟器的调试与动态重编译功能提供了可靠底座。【免费下载链接】pcsx2PCSX2 - The Playstation 2 Emulator项目地址: https://gitcode.com/GitHub_Trending/pc/pcsx2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表