parent
cec9482921
commit
8da99dd6ae
@ -0,0 +1,134 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_API_MEMORY_H
|
||||||
|
#define ZYCORE_API_MEMORY_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#if defined(ZYAN_WINDOWS)
|
||||||
|
# include <windows.h>
|
||||||
|
#elif defined(ZYAN_POSIX)
|
||||||
|
# include <sys/mman.h>
|
||||||
|
#else
|
||||||
|
# error "Unsupported platform detected"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanMemoryPageProtection` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZyanMemoryPageProtection_
|
||||||
|
{
|
||||||
|
#if defined(ZYAN_WINDOWS)
|
||||||
|
|
||||||
|
ZYAN_PAGE_READONLY = PAGE_READONLY,
|
||||||
|
ZYAN_PAGE_READWRITE = PAGE_READWRITE,
|
||||||
|
ZYAN_PAGE_EXECUTE = PAGE_EXECUTE,
|
||||||
|
ZYAN_PAGE_EXECUTE_READ = PAGE_EXECUTE_READ,
|
||||||
|
ZYAN_PAGE_EXECUTE_READWRITE = PAGE_EXECUTE_READWRITE
|
||||||
|
|
||||||
|
#elif defined(ZYAN_POSIX)
|
||||||
|
|
||||||
|
ZYAN_PAGE_READONLY = PROT_READ,
|
||||||
|
ZYAN_PAGE_READWRITE = PROT_READ | PROT_WRITE,
|
||||||
|
ZYAN_PAGE_EXECUTE = PROT_EXEC,
|
||||||
|
ZYAN_PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ,
|
||||||
|
ZYAN_PAGE_EXECUTE_READWRITE = PROT_EXEC | PROT_READ | PROT_WRITE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
} ZyanMemoryPageProtection;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the system page size.
|
||||||
|
*
|
||||||
|
* @return The system page size.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemPageSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the system allocation granularity.
|
||||||
|
*
|
||||||
|
* The system allocation granularity specifies the minimum amount of bytes which can be allocated
|
||||||
|
* at a specific address by a single call of `ZyanMemoryVirtualAlloc`.
|
||||||
|
*
|
||||||
|
* This value is typically 64KiB on Windows systems and equal to the page size on most POSIX
|
||||||
|
* platforms.
|
||||||
|
*
|
||||||
|
* @return The system allocation granularity.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemAllocationGranularity();
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Memory management */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the memory protection value of one or more pages.
|
||||||
|
*
|
||||||
|
* @param address The start address aligned to a page boundary.
|
||||||
|
* @param size The size.
|
||||||
|
* @param protection The new page protection value.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size,
|
||||||
|
ZyanMemoryPageProtection protection);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases one or more memory pages starting at the given address.
|
||||||
|
*
|
||||||
|
* @param address The start address aligned to a page boundary.
|
||||||
|
* @param size The size.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#endif /* ZYCORE_API_MEMORY_H */
|
@ -0,0 +1,67 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_API_PROCESS_H
|
||||||
|
#define ZYCORE_API_PROCESS_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flushes the process instruction cache.
|
||||||
|
*
|
||||||
|
* @param address The address.
|
||||||
|
* @param size The size.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#endif /* ZYCORE_API_PROCESS_H */
|
@ -0,0 +1,133 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_API_SYNCHRONIZATION_H
|
||||||
|
#define ZYCORE_API_SYNCHRONIZATION_H
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(ZYAN_POSIX)
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Critical Section */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
typedef pthread_mutex_t ZyanCriticalSection;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#elif defined(ZYAN_WINDOWS)
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Critical Section */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
typedef CRITICAL_SECTION ZyanCriticalSection;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Unsupported platform detected"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Critical Section */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a critical section.
|
||||||
|
*
|
||||||
|
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enters a critical section.
|
||||||
|
*
|
||||||
|
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to enter a critical section.
|
||||||
|
*
|
||||||
|
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||||
|
*
|
||||||
|
* @return Returns `ZYAN_TRUE` if the critical section was successfully entered or `ZYAN_FALSE`,
|
||||||
|
* if not.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leaves a critical section.
|
||||||
|
*
|
||||||
|
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a critical section.
|
||||||
|
*
|
||||||
|
* @param critical_section A pointer to the `ZyanCriticalSection` struct.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYAN_NO_LIBC */
|
||||||
|
|
||||||
|
#endif /* ZYCORE_API_SYNCHRONIZATION_H */
|
@ -0,0 +1,163 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file Provides cross-platform terminal helper functions.
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_API_TERMINAL_H
|
||||||
|
#define ZYCORE_API_TERMINAL_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/LibC.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* VT100 CSI SGR sequences */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define ZYAN_VT100SGR_RESET "\033[0m"
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Foreground colors */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define ZYAN_VT100SGR_FG_DEFAULT "\033[39m"
|
||||||
|
|
||||||
|
#define ZYAN_VT100SGR_FG_BLACK "\033[30m"
|
||||||
|
#define ZYAN_VT100SGR_FG_RED "\033[31m"
|
||||||
|
#define ZYAN_VT100SGR_FG_GREEN "\033[32m"
|
||||||
|
#define ZYAN_VT100SGR_FG_YELLOW "\033[33m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BLUE "\033[34m"
|
||||||
|
#define ZYAN_VT100SGR_FG_MAGENTA "\033[35m"
|
||||||
|
#define ZYAN_VT100SGR_FG_CYAN "\033[36m"
|
||||||
|
#define ZYAN_VT100SGR_FG_WHITE "\033[37m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_BLACK "\033[90m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_RED "\033[91m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_GREEN "\033[92m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_YELLOW "\033[93m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_BLUE "\033[94m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_MAGENTA "\033[95m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_CYAN "\033[96m"
|
||||||
|
#define ZYAN_VT100SGR_FG_BRIGHT_WHITE "\033[97m"
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Background color */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define ZYAN_VT100SGR_BG_DEFAULT "\033[49m"
|
||||||
|
|
||||||
|
#define ZYAN_VT100SGR_BG_BLACK "\033[40m"
|
||||||
|
#define ZYAN_VT100SGR_BG_RED "\033[41m"
|
||||||
|
#define ZYAN_VT100SGR_BG_GREEN "\033[42m"
|
||||||
|
#define ZYAN_VT100SGR_BG_YELLOW "\033[43m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BLUE "\033[44m"
|
||||||
|
#define ZYAN_VT100SGR_BG_MAGENTA "\033[45m"
|
||||||
|
#define ZYAN_VT100SGR_BG_CYAN "\033[46m"
|
||||||
|
#define ZYAN_VT100SGR_BG_WHITE "\033[47m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_BLACK "\033[100m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_RED "\033[101m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_GREEN "\033[102m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_YELLOW "\033[103m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_BLUE "\033[104m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_MAGENTA "\033[105m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_CYAN "\033[106m"
|
||||||
|
#define ZYAN_VT100SGR_BG_BRIGHT_WHITE "\033[107m"
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares the `ZyanStandardStream` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZyanStandardStream_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The default input stream.
|
||||||
|
*/
|
||||||
|
ZYAN_STDSTREAM_IN,
|
||||||
|
/**
|
||||||
|
* The default output stream.
|
||||||
|
*/
|
||||||
|
ZYAN_STDSTREAM_OUT,
|
||||||
|
/**
|
||||||
|
* The default error stream.
|
||||||
|
*/
|
||||||
|
ZYAN_STDSTREAM_ERR
|
||||||
|
} ZyanStandardStream;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables VT100 ansi escape codes for the given stream.
|
||||||
|
*
|
||||||
|
* @param stream Either `ZYAN_STDSTREAM_OUT` or `ZYAN_STDSTREAM_ERR`.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This functions returns `ZYAN_STATUS_SUCCESS` on all non-Windows systems without performing any
|
||||||
|
* operations, assuming that VT100 is supported by default.
|
||||||
|
*
|
||||||
|
* On Windows systems, VT100 functionality is only supported on Windows 10 build 1607 (anniversary
|
||||||
|
* update) and later.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if the given standard stream reads from or writes to a terminal.
|
||||||
|
*
|
||||||
|
* @param stream The standard stream to check.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE`, if the stream is bound to a terminal, `ZYAN_STATUS_FALSE` if not,
|
||||||
|
* or another zyan status code if an error occured.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream);
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_API_TERMINAL_H */
|
@ -0,0 +1,244 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_API_THREAD_H
|
||||||
|
#define ZYCORE_API_THREAD_H
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(ZYAN_POSIX)
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThread` data-type.
|
||||||
|
*/
|
||||||
|
typedef pthread_t ZyanThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThreadId` data-type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU64 ZyanThreadId;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Thread Local Storage (TLS) */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThreadTlsIndex` data-type.
|
||||||
|
*/
|
||||||
|
typedef pthread_key_t ZyanThreadTlsIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThreadTlsCallback` function prototype.
|
||||||
|
*/
|
||||||
|
typedef void(*ZyanThreadTlsCallback)(void* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a Thread Local Storage (TLS) callback function.
|
||||||
|
*
|
||||||
|
* @param name The callback function name.
|
||||||
|
* @param param_type The callback data parameter type.
|
||||||
|
* @param param_name The callback data parameter name.
|
||||||
|
*/
|
||||||
|
#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \
|
||||||
|
void name(param_type* param_name)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#elif defined(ZYAN_WINDOWS)
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThread` data-type.
|
||||||
|
*/
|
||||||
|
typedef HANDLE ZyanThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThreadId` data-type.
|
||||||
|
*/
|
||||||
|
typedef DWORD ZyanThreadId;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Thread Local Storage (TLS) */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThreadTlsIndex` data-type.
|
||||||
|
*/
|
||||||
|
typedef DWORD ZyanThreadTlsIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanThreadTlsCallback` function prototype.
|
||||||
|
*/
|
||||||
|
typedef PFLS_CALLBACK_FUNCTION ZyanThreadTlsCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a Thread Local Storage (TLS) callback function.
|
||||||
|
*
|
||||||
|
* @param name The callback function name.
|
||||||
|
* @param param_type The callback data parameter type.
|
||||||
|
* @param param_name The callback data parameter name.
|
||||||
|
*/
|
||||||
|
#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \
|
||||||
|
VOID NTAPI name(param_type* param_name)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Unsupported platform detected"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the handle of the current thread.
|
||||||
|
*
|
||||||
|
* @param thread Receives the handle of the current thread.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unique id of the current thread.
|
||||||
|
*
|
||||||
|
* @param thread_id Receives the unique id of the current thread.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Thread Local Storage (TLS) */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a new Thread Local Storage (TLS) slot.
|
||||||
|
*
|
||||||
|
* @param index Receives the TLS slot index.
|
||||||
|
* @param destructor A pointer to a destructor callback which is invoked to finalize the data
|
||||||
|
* in the TLS slot or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* The maximum available number of TLS slots is implementation specific and different on each
|
||||||
|
* platform:
|
||||||
|
* - Windows
|
||||||
|
* - A total amount of 128 slots per process are guaranteed
|
||||||
|
* - POSIX
|
||||||
|
* - A total amount of 128 slots per process are guaranteed
|
||||||
|
* - Some systems guarantee larger amounts like e.g. 1024 slots per process
|
||||||
|
*
|
||||||
|
* Note that the invocation rules for the destructor callback are implementation specific and
|
||||||
|
* different on each platform:
|
||||||
|
* - Windows
|
||||||
|
* - The callback is invoked when a thread exits
|
||||||
|
* - The callback is invoked when the process exits
|
||||||
|
* - The callback is invoked when the TLS slot is released
|
||||||
|
* - POSIX
|
||||||
|
* - The callback is invoked when a thread exits and the stored value is not null
|
||||||
|
* - The callback is NOT invoked when the process exits
|
||||||
|
* - The callback is NOT invoked when the TLS slot is released
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index,
|
||||||
|
ZyanThreadTlsCallback destructor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases a Thread Local Storage (TLS) slot.
|
||||||
|
*
|
||||||
|
* @param index The TLS slot index.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value inside the given Thread Local Storage (TLS) slot for the
|
||||||
|
* calling thread.
|
||||||
|
*
|
||||||
|
* @param index The TLS slot index.
|
||||||
|
* @param data Receives the value inside the given Thread Local Storage
|
||||||
|
* (TLS) slot for the calling thread.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of the given Thread Local Storage (TLS) slot for the calling thread.
|
||||||
|
*
|
||||||
|
* @param index The TLS slot index.
|
||||||
|
* @param data The value to store inside the given Thread Local Storage (TLS) slot for the
|
||||||
|
* calling thread
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYAN_NO_LIBC */
|
||||||
|
|
||||||
|
#endif /* ZYCORE_API_THREAD_H */
|
@ -0,0 +1,143 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_ALLOCATOR_H
|
||||||
|
#define ZYCORE_ALLOCATOR_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
struct ZyanAllocator_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanAllocatorAllocate` function prototype.
|
||||||
|
*
|
||||||
|
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||||
|
* @param p Receives a pointer to the first memory block sufficient to hold an
|
||||||
|
* array of `n` elements with a size of `element_size`.
|
||||||
|
* @param element_size The size of a single element.
|
||||||
|
* @param n The number of elements to allocate storage for.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This prototype is used for the `allocate()` and `reallocate()` functions.
|
||||||
|
*
|
||||||
|
* The result of the `reallocate()` function is undefined, if `p` does not point to a memory block
|
||||||
|
* previously obtained by `(re-)allocate()`.
|
||||||
|
*/
|
||||||
|
typedef ZyanStatus (*ZyanAllocatorAllocate)(struct ZyanAllocator_* allocator, void** p,
|
||||||
|
ZyanUSize element_size, ZyanUSize n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanAllocatorDeallocate` function prototype.
|
||||||
|
*
|
||||||
|
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||||
|
* @param p The pointer obtained from `(re-)allocate()`.
|
||||||
|
* @param element_size The size of a single element.
|
||||||
|
* @param n The number of elements earlier passed to `(re-)allocate()`.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
typedef ZyanStatus (*ZyanAllocatorDeallocate)(struct ZyanAllocator_* allocator, void* p,
|
||||||
|
ZyanUSize element_size, ZyanUSize n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanAllocator` struct.
|
||||||
|
*
|
||||||
|
* This is the base class for all custom allocator implementations.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanAllocator_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The allocate function.
|
||||||
|
*/
|
||||||
|
ZyanAllocatorAllocate allocate;
|
||||||
|
/**
|
||||||
|
* The reallocate function.
|
||||||
|
*/
|
||||||
|
ZyanAllocatorAllocate reallocate;
|
||||||
|
/**
|
||||||
|
* The deallocate function.
|
||||||
|
*/
|
||||||
|
ZyanAllocatorDeallocate deallocate;
|
||||||
|
} ZyanAllocator;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanAllocator` instance.
|
||||||
|
*
|
||||||
|
* @param allocator A pointer to the `ZyanAllocator` instance.
|
||||||
|
* @param allocate The allocate function.
|
||||||
|
* @param reallocate The reallocate function.
|
||||||
|
* @param deallocate The deallocate function.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate,
|
||||||
|
ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate);
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default `ZyanAllocator` instance.
|
||||||
|
*
|
||||||
|
* @return A pointer to the default `ZyanAllocator` instance.
|
||||||
|
*
|
||||||
|
* The default allocator uses the default memory manager to allocate memory on the heap.
|
||||||
|
*
|
||||||
|
* You should in no case modify the returned allocator instance to avoid unexpected behavior.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanAllocator* ZyanAllocatorDefault(void);
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_ALLOCATOR_H */
|
@ -0,0 +1,173 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Implements command-line argument parsing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_ARGPARSE_H
|
||||||
|
#define ZYCORE_ARGPARSE_H
|
||||||
|
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Vector.h>
|
||||||
|
#include <Zycore/String.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Structs and other types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Definition of a single argument.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanArgParseDefinition_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The argument name, e.g. `--help`.
|
||||||
|
*
|
||||||
|
* Must start with either one or two dashes. Single dash arguments must consist of a single
|
||||||
|
* character, (e.g. `-n`), double-dash arguments can be of arbitrary length.
|
||||||
|
*/
|
||||||
|
const char* name;
|
||||||
|
/**
|
||||||
|
* Whether the argument is boolean or expects a value.
|
||||||
|
*/
|
||||||
|
ZyanBool boolean;
|
||||||
|
/**
|
||||||
|
* Whether this argument is required (error if missing).
|
||||||
|
*/
|
||||||
|
ZyanBool required;
|
||||||
|
} ZyanArgParseDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for argument parsing.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanArgParseConfig_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* `argv` argument passed to `main` by LibC.
|
||||||
|
*/
|
||||||
|
const char** argv;
|
||||||
|
/**
|
||||||
|
* `argc` argument passed to `main` by LibC.
|
||||||
|
*/
|
||||||
|
ZyanUSize argc;
|
||||||
|
/**
|
||||||
|
* Minimum # of accepted unnamed / anonymous arguments.
|
||||||
|
*/
|
||||||
|
ZyanUSize min_unnamed_args;
|
||||||
|
/**
|
||||||
|
* Maximum # of accepted unnamed / anonymous arguments.
|
||||||
|
*/
|
||||||
|
ZyanUSize max_unnamed_args;
|
||||||
|
/**
|
||||||
|
* Argument definition array, or `ZYAN_NULL`.
|
||||||
|
*
|
||||||
|
* Expects a pointer to an array of `ZyanArgParseDefinition` instances. The array is
|
||||||
|
* terminated by setting the `.name` field of the last element to `ZYAN_NULL`. If no named
|
||||||
|
* arguments should be parsed, you can also set this to `ZYAN_NULL`.
|
||||||
|
*/
|
||||||
|
ZyanArgParseDefinition* args;
|
||||||
|
} ZyanArgParseConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about a parsed argument.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanArgParseArg_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Corresponding argument definition, or `ZYAN_NULL` for unnamed args.
|
||||||
|
*
|
||||||
|
* This pointer is borrowed from the `cfg` pointer passed to `ZyanArgParse`.
|
||||||
|
*/
|
||||||
|
const ZyanArgParseDefinition* def;
|
||||||
|
/**
|
||||||
|
* Whether the argument has a value (is non-boolean).
|
||||||
|
*/
|
||||||
|
ZyanBool has_value;
|
||||||
|
/**
|
||||||
|
* If `has_value == true`, then the argument value.
|
||||||
|
*
|
||||||
|
* This is a view into the `argv` string array passed to `ZyanArgParse` via the `cfg` argument.
|
||||||
|
*/
|
||||||
|
ZyanStringView value;
|
||||||
|
} ZyanArgParseArg;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse arguments according to a `ZyanArgParseConfig` definition.
|
||||||
|
*
|
||||||
|
* @param cfg Argument parser config to use.
|
||||||
|
* @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is
|
||||||
|
* transferred to the user. Input is expected to be uninitialized. On error,
|
||||||
|
* the vector remains uninitialized.
|
||||||
|
* @param error_token On error, if it makes sense, receives the argument fragment causing the
|
||||||
|
* error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg`
|
||||||
|
* struct and doesn't have to be freed by the user.
|
||||||
|
*
|
||||||
|
* @return A `ZyanStatus` status determining whether the parsing succeeded.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||||
|
const char** error_token);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse arguments according to a `ZyanArgParseConfig` definition.
|
||||||
|
*
|
||||||
|
* This version allows specification of a custom memory allocator and thus supports no-libc.
|
||||||
|
*
|
||||||
|
* @param cfg Argument parser config to use.
|
||||||
|
* @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is
|
||||||
|
* transferred to the user. Input is expected to be uninitialized. On error,
|
||||||
|
* the vector remains uninitialized.
|
||||||
|
* @param error_token On error, if it makes sense, receives the argument fragment causing the
|
||||||
|
* error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg`
|
||||||
|
* struct and doesn't have to be freed by the user.
|
||||||
|
* @param allocator The `ZyanAllocator` to be used for allocating the output vector's data.
|
||||||
|
*
|
||||||
|
* @return A `ZyanStatus` status determining whether the parsing succeeded.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed,
|
||||||
|
const char** error_token, ZyanAllocator* allocator);
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_ARGPARSE_H */
|
@ -0,0 +1,484 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Implements the bitset class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_BITSET_H
|
||||||
|
#define ZYCORE_BITSET_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Allocator.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
#include <Zycore/Vector.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanVector` struct.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanBitset_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The bitset size.
|
||||||
|
*/
|
||||||
|
ZyanUSize size;
|
||||||
|
/**
|
||||||
|
* The bitset data.
|
||||||
|
*/
|
||||||
|
ZyanVector bits;
|
||||||
|
} ZyanBitset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanBitsetByteOperation` function prototype.
|
||||||
|
*
|
||||||
|
* @param v1 A pointer to the first byte. This value receives the result after performing the
|
||||||
|
* desired operation.
|
||||||
|
* @param v2 A pointer to the second byte.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function is used to perform byte-wise operations on two `ZyanBitset` instances.
|
||||||
|
*/
|
||||||
|
typedef ZyanStatus (*ZyanBitsetByteOperation)(ZyanU8* v1, const ZyanU8* v2);
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Constructor and destructor */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param count The initial amount of bits.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The space for the bitset is dynamically allocated by the default allocator using the default
|
||||||
|
* growth factor of `2.0f` and the default shrink threshold of `0.5f`.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count);
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanBitset` instance and sets a custom `allocator` and memory
|
||||||
|
* allocation/deallocation parameters.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param count The initial amount of bits.
|
||||||
|
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||||
|
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||||
|
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||||
|
* dynamic shrinking.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count,
|
||||||
|
ZyanAllocator* allocator, float growth_factor, float shrink_threshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanBitset` instance and configures it to use a custom user
|
||||||
|
* defined buffer with a fixed size.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param count The initial amount of bits.
|
||||||
|
* @param buffer A pointer to the buffer that is used as storage for the bits.
|
||||||
|
* @param capacity The maximum capacity (number of bytes) of the buffer.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer,
|
||||||
|
ZyanUSize capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the given `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Logical operations */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a byte-wise `operation` for every byte in the given `ZyanBitset` instances.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||||
|
* as the destination.
|
||||||
|
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||||
|
* @param operation A pointer to the function that performs the desired operation.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The `operation` callback is invoked once for every byte in the smallest of the `ZyanBitset`
|
||||||
|
* instances.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination,
|
||||||
|
const ZyanBitset* source, ZyanBitsetByteOperation operation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a logical `AND` operation on the given `ZyanBitset` instances.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||||
|
* as the destination.
|
||||||
|
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||||
|
* bits will be undefined.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a logical `OR` operation on the given `ZyanBitset` instances.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||||
|
* as the destination.
|
||||||
|
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||||
|
* bits will be undefined.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a logical `XOR` operation on the given `ZyanBitset` instances.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the `ZyanBitset` instance that is used as the first input and
|
||||||
|
* as the destination.
|
||||||
|
* @param source A pointer to the `ZyanBitset` instance that is used as the second input.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* If the destination bitmask contains more bits than the source one, the state of the remaining
|
||||||
|
* bits will be undefined.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flips all bits of the given `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Bit access */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bit at `index` of the given `ZyanBitset` instance to `1`.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param index The bit index.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bit at `index` of the given `ZyanBitset` instance to `0`.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param index The bit index.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bit at `index` of the given `ZyanBitset` instance to the specified `value`.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param index The bit index.
|
||||||
|
* @param value The new value.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles the bit at `index` of the given `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param index The bit index.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the bit at `index`.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param index The bit index.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not, Another zyan
|
||||||
|
* status code, if an error occured.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the most significant bit.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||||
|
* status code, if an error occured.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the least significant bit.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||||
|
* status code, if an error occured.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets all bits of the given `ZyanBitset` instance to `1`.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets all bits of the given `ZyanBitset` instance to `0`.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Size management */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new bit at the end of the bitset.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param value The value of the new bit.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the last bit of the bitset.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetPop(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all bits of the given `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetClear(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Memory management */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the capacity of the given `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param count The new capacity (number of bits).
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shrinks the capacity of the given bitset to match it's size.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Information */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current size of the bitset in bits.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param size Receives the size of the bitset in bits.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current capacity of the bitset in bits.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param capacity Receives the size of the bitset in bits.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current size of the bitset in bytes.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param size Receives the size of the bitset in bytes.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current capacity of the bitset in bytes.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param capacity Receives the size of the bitset in bytes.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of bits set in the given bitset.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
* @param count Receives the amount of bits set in the given bitset.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if all bits of the given bitset are set.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE`, if all bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||||
|
* status code, if an error occured.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if at least one bit of the given bitset is set.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE`, if at least one bit is set, `ZYAN_STATUS_FALSE`, if not. Another
|
||||||
|
* zyan status code, if an error occured.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if none bits of the given bitset are set.
|
||||||
|
*
|
||||||
|
* @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE`, if none bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan
|
||||||
|
* status code, if an error occured.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset);
|
||||||
|
|
||||||
|
///* ---------------------------------------------------------------------------------------------- */
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Returns a 32-bit unsigned integer representation of the data.
|
||||||
|
// *
|
||||||
|
// * @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
// * @param value Receives the 32-bit unsigned integer representation of the data.
|
||||||
|
// *
|
||||||
|
// * @return A zyan status code.
|
||||||
|
// */
|
||||||
|
//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value);
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Returns a 64-bit unsigned integer representation of the data.
|
||||||
|
// *
|
||||||
|
// * @param bitset A pointer to the `ZyanBitset` instance.
|
||||||
|
// * @param value Receives the 64-bit unsigned integer representation of the data.
|
||||||
|
// *
|
||||||
|
// * @return A zyan status code.
|
||||||
|
// */
|
||||||
|
//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_BITSET_H */
|
@ -0,0 +1,316 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Defines prototypes of general-purpose comparison functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_COMPARISON_H
|
||||||
|
#define ZYCORE_COMPARISON_H
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanEqualityComparison` function prototype.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first element.
|
||||||
|
* @param right A pointer to the second element.
|
||||||
|
*
|
||||||
|
* @return This function should return `ZYAN_TRUE` if the `left` element equals the `right` one
|
||||||
|
* or `ZYAN_FALSE`, if not.
|
||||||
|
*/
|
||||||
|
typedef ZyanBool (*ZyanEqualityComparison)(const void* left, const void* right);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanComparison` function prototype.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first element.
|
||||||
|
* @param right A pointer to the second element.
|
||||||
|
*
|
||||||
|
* @return This function should return values in the following range:
|
||||||
|
* `left == right -> result == 0`
|
||||||
|
* `left < right -> result < 0`
|
||||||
|
* `left > right -> result > 0`
|
||||||
|
*/
|
||||||
|
typedef ZyanI32 (*ZyanComparison)(const void* left, const void* right);
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Equality comparison functions */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a generic equality comparison function for an integral data-type.
|
||||||
|
*
|
||||||
|
* @param name The name of the function.
|
||||||
|
* @param type The name of the integral data-type.
|
||||||
|
*/
|
||||||
|
#define ZYAN_DECLARE_EQUALITY_COMPARISON(name, type) \
|
||||||
|
ZyanBool name(const type* left, const type* right) \
|
||||||
|
{ \
|
||||||
|
ZYAN_ASSERT(left); \
|
||||||
|
ZYAN_ASSERT(right); \
|
||||||
|
\
|
||||||
|
return (*left == *right) ? ZYAN_TRUE : ZYAN_FALSE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a generic equality comparison function that compares a single integral
|
||||||
|
* data-type field of a struct.
|
||||||
|
*
|
||||||
|
* @param name The name of the function.
|
||||||
|
* @param type The name of the integral data-type.
|
||||||
|
* @param field_name The name of the struct field.
|
||||||
|
*/
|
||||||
|
#define ZYAN_DECLARE_EQUALITY_COMPARISON_FOR_FIELD(name, type, field_name) \
|
||||||
|
ZyanBool name(const type* left, const type* right) \
|
||||||
|
{ \
|
||||||
|
ZYAN_ASSERT(left); \
|
||||||
|
ZYAN_ASSERT(right); \
|
||||||
|
\
|
||||||
|
return (left->field_name == right->field_name) ? ZYAN_TRUE : ZYAN_FALSE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Comparison functions */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a generic comparison function for an integral data-type.
|
||||||
|
*
|
||||||
|
* @param name The name of the function.
|
||||||
|
* @param type The name of the integral data-type.
|
||||||
|
*/
|
||||||
|
#define ZYAN_DECLARE_COMPARISON(name, type) \
|
||||||
|
ZyanI32 name(const type* left, const type* right) \
|
||||||
|
{ \
|
||||||
|
ZYAN_ASSERT(left); \
|
||||||
|
ZYAN_ASSERT(right); \
|
||||||
|
\
|
||||||
|
if (*left < *right) \
|
||||||
|
{ \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
if (*left > *right) \
|
||||||
|
{ \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a generic comparison function that compares a single integral data-type field
|
||||||
|
* of a struct.
|
||||||
|
*
|
||||||
|
* @param name The name of the function.
|
||||||
|
* @param type The name of the integral data-type.
|
||||||
|
* @param field_name The name of the struct field.
|
||||||
|
*/
|
||||||
|
#define ZYAN_DECLARE_COMPARISON_FOR_FIELD(name, type, field_name) \
|
||||||
|
ZyanI32 name(const type* left, const type* right) \
|
||||||
|
{ \
|
||||||
|
ZYAN_ASSERT(left); \
|
||||||
|
ZYAN_ASSERT(right); \
|
||||||
|
\
|
||||||
|
if (left->field_name < right->field_name) \
|
||||||
|
{ \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
if (left->field_name > right->field_name) \
|
||||||
|
{ \
|
||||||
|
return 1; \
|
||||||
|
} \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Default equality comparison functions */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default equality comparison function for pointer values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||||
|
* not.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsPointer, void* const)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default equality comparison function for `ZyanBool` values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||||
|
* not.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsBool, ZyanBool)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default equality comparison function for 8-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||||
|
* not.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric8, ZyanU8)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default equality comparison function for 16-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||||
|
* not.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric16, ZyanU16)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default equality comparison function for 32-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||||
|
* not.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric32, ZyanU32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default equality comparison function for 64-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if
|
||||||
|
* not.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric64, ZyanU64)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Default comparison functions */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default comparison function for pointer values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||||
|
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanComparePointer, void* const)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default comparison function for `ZyanBool` values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||||
|
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareBool, ZyanBool)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default comparison function for 8-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||||
|
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric8, ZyanU8)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default comparison function for 16-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||||
|
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric16, ZyanU16)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default comparison function for 32-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||||
|
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric32, ZyanU32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a default comparison function for 64-bit numeric values.
|
||||||
|
*
|
||||||
|
* @param left A pointer to the first value.
|
||||||
|
* @param right A pointer to the second value.
|
||||||
|
*
|
||||||
|
* @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is
|
||||||
|
* less than the `right` one, or `1` if the `left` value is greater than the `right` one.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric64, ZyanU64)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_COMPARISON_H */
|
@ -0,0 +1,451 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* General helper and platform detection macros.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_DEFINES_H
|
||||||
|
#define ZYCORE_DEFINES_H
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Meta macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenates two values using the stringify operator (`##`).
|
||||||
|
*
|
||||||
|
* @param x The first value.
|
||||||
|
* @param y The second value.
|
||||||
|
*
|
||||||
|
* @return The combined string of the given values.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MACRO_CONCAT(x, y) x ## y
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenates two values using the stringify operator (`##`) and expands the value to
|
||||||
|
* be used in another macro.
|
||||||
|
*
|
||||||
|
* @param x The first value.
|
||||||
|
* @param y The second value.
|
||||||
|
*
|
||||||
|
* @return The combined string of the given values.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y)
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Compiler detection */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# define ZYAN_CLANG
|
||||||
|
# define ZYAN_GNUC
|
||||||
|
#elif defined(__ICC) || defined(__INTEL_COMPILER)
|
||||||
|
# define ZYAN_ICC
|
||||||
|
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
# define ZYAN_GCC
|
||||||
|
# define ZYAN_GNUC
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define ZYAN_MSVC
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
# define ZYAN_BORLAND
|
||||||
|
#else
|
||||||
|
# define ZYAN_UNKNOWN_COMPILER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Platform detection */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# define ZYAN_WINDOWS
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
# define ZYAN_EMSCRIPTEN
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
# define ZYAN_APPLE
|
||||||
|
# define ZYAN_POSIX
|
||||||
|
#elif defined(__linux)
|
||||||
|
# define ZYAN_LINUX
|
||||||
|
# define ZYAN_POSIX
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
# define ZYAN_FREEBSD
|
||||||
|
# define ZYAN_POSIX
|
||||||
|
#elif defined(sun) || defined(__sun)
|
||||||
|
# define ZYAN_SOLARIS
|
||||||
|
# define ZYAN_POSIX
|
||||||
|
#elif defined(__unix)
|
||||||
|
# define ZYAN_UNIX
|
||||||
|
# define ZYAN_POSIX
|
||||||
|
#elif defined(__posix)
|
||||||
|
# define ZYAN_POSIX
|
||||||
|
#else
|
||||||
|
# define ZYAN_UNKNOWN_PLATFORM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Kernel mode detection */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \
|
||||||
|
(defined(ZYAN_APPLE) && defined(KERNEL)) || \
|
||||||
|
(defined(ZYAN_LINUX) && defined(__KERNEL__)) || \
|
||||||
|
(defined(__FreeBSD_kernel__))
|
||||||
|
# define ZYAN_KERNEL
|
||||||
|
#else
|
||||||
|
# define ZYAN_USER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Architecture detection */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(_M_AMD64) || defined(__x86_64__)
|
||||||
|
# define ZYAN_X64
|
||||||
|
#elif defined(_M_IX86) || defined(__i386__)
|
||||||
|
# define ZYAN_X86
|
||||||
|
#elif defined(_M_ARM64) || defined(__aarch64__)
|
||||||
|
# define ZYAN_AARCH64
|
||||||
|
#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__)
|
||||||
|
# define ZYAN_ARM
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
// Nothing to do, `ZYAN_EMSCRIPTEN` is both platform and arch macro for this one.
|
||||||
|
#else
|
||||||
|
# error "Unsupported architecture detected"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Debug/Release detection */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
|
||||||
|
# ifdef _DEBUG
|
||||||
|
# define ZYAN_DEBUG
|
||||||
|
# else
|
||||||
|
# define ZYAN_RELEASE
|
||||||
|
# endif
|
||||||
|
#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC)
|
||||||
|
# ifdef NDEBUG
|
||||||
|
# define ZYAN_RELEASE
|
||||||
|
# else
|
||||||
|
# define ZYAN_DEBUG
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define ZYAN_RELEASE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Misc compatibility macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(ZYAN_CLANG)
|
||||||
|
# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
|
||||||
|
#else
|
||||||
|
# define ZYAN_NO_SANITIZE(what)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND)
|
||||||
|
# define ZYAN_INLINE __inline
|
||||||
|
#else
|
||||||
|
# define ZYAN_INLINE static inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ZYAN_MSVC)
|
||||||
|
# define ZYAN_NOINLINE __declspec(noinline)
|
||||||
|
#elif defined(ZYAN_GCC) || defined(ZYAN_CLANG)
|
||||||
|
# define ZYAN_NOINLINE __attribute__((noinline))
|
||||||
|
#else
|
||||||
|
# define ZYAN_NOINLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Debugging and optimization macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime debug assertion.
|
||||||
|
*/
|
||||||
|
#if defined(ZYAN_NO_LIBC)
|
||||||
|
# define ZYAN_ASSERT(condition) (void)(condition)
|
||||||
|
#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
|
||||||
|
# include <wdm.h>
|
||||||
|
# define ZYAN_ASSERT(condition) NT_ASSERT(condition)
|
||||||
|
#else
|
||||||
|
# include <assert.h>
|
||||||
|
# define ZYAN_ASSERT(condition) assert(condition)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiler-time assertion.
|
||||||
|
*/
|
||||||
|
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
||||||
|
# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x)
|
||||||
|
#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \
|
||||||
|
(defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \
|
||||||
|
(defined (_MSC_VER) && (_MSC_VER >= 1800))
|
||||||
|
# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x)
|
||||||
|
#else
|
||||||
|
# define ZYAN_STATIC_ASSERT(x) \
|
||||||
|
typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the current code path as unreachable.
|
||||||
|
*/
|
||||||
|
#if defined(ZYAN_RELEASE)
|
||||||
|
# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs.
|
||||||
|
# if __has_builtin(__builtin_unreachable)
|
||||||
|
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||||
|
# else
|
||||||
|
# define ZYAN_UNREACHABLE for(;;)
|
||||||
|
# endif
|
||||||
|
# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4)
|
||||||
|
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||||
|
# elif defined(ZYAN_ICC)
|
||||||
|
# ifdef ZYAN_WINDOWS
|
||||||
|
# include <stdlib.h> // "missing return statement" workaround
|
||||||
|
# define ZYAN_UNREACHABLE __assume(0); (void)abort()
|
||||||
|
# else
|
||||||
|
# define ZYAN_UNREACHABLE __builtin_unreachable()
|
||||||
|
# endif
|
||||||
|
# elif defined(ZYAN_MSVC)
|
||||||
|
# define ZYAN_UNREACHABLE __assume(0)
|
||||||
|
# else
|
||||||
|
# define ZYAN_UNREACHABLE for(;;)
|
||||||
|
# endif
|
||||||
|
#elif defined(ZYAN_NO_LIBC)
|
||||||
|
# define ZYAN_UNREACHABLE for(;;)
|
||||||
|
#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL)
|
||||||
|
# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} }
|
||||||
|
#else
|
||||||
|
# include <stdlib.h>
|
||||||
|
# define ZYAN_UNREACHABLE { assert(0); abort(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Utils */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General purpose */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the specified parameter as unused.
|
||||||
|
*
|
||||||
|
* @param x The name of the unused parameter.
|
||||||
|
*/
|
||||||
|
#define ZYAN_UNUSED(x) (void)(x)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intentional fallthrough.
|
||||||
|
*/
|
||||||
|
#if defined(ZYAN_GCC) && __GNUC__ >= 7
|
||||||
|
# define ZYAN_FALLTHROUGH __attribute__((fallthrough))
|
||||||
|
#else
|
||||||
|
# define ZYAN_FALLTHROUGH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a bitfield.
|
||||||
|
*
|
||||||
|
* @param x The size (in bits) of the bitfield.
|
||||||
|
*/
|
||||||
|
#define ZYAN_BITFIELD(x) : x
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`).
|
||||||
|
*/
|
||||||
|
#define ZYAN_REQUIRES_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorator for `printf`-style functions.
|
||||||
|
*
|
||||||
|
* @param format_index The 1-based index of the format string parameter.
|
||||||
|
* @param first_to_check The 1-based index of the format arguments parameter.
|
||||||
|
*/
|
||||||
|
#if defined(__RESHARPER__)
|
||||||
|
# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
|
||||||
|
[[gnu::format(printf, format_index, first_to_check)]]
|
||||||
|
#elif defined(ZYAN_GCC)
|
||||||
|
# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \
|
||||||
|
__attribute__((format(printf, format_index, first_to_check)))
|
||||||
|
#else
|
||||||
|
# define ZYAN_PRINTF_ATTR(format_index, first_to_check)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorator for `wprintf`-style functions.
|
||||||
|
*
|
||||||
|
* @param format_index The 1-based index of the format string parameter.
|
||||||
|
* @param first_to_check The 1-based index of the format arguments parameter.
|
||||||
|
*/
|
||||||
|
#if defined(__RESHARPER__)
|
||||||
|
# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \
|
||||||
|
[[rscpp::format(wprintf, format_index, first_to_check)]]
|
||||||
|
#else
|
||||||
|
# define ZYAN_WPRINTF_ATTR(format_index, first_to_check)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Arrays */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length (number of elements) of an array.
|
||||||
|
*
|
||||||
|
* @param a The name of the array.
|
||||||
|
*
|
||||||
|
* @return The number of elements of the given array.
|
||||||
|
*/
|
||||||
|
#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Arithmetic */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the smaller value of `a` or `b`.
|
||||||
|
*
|
||||||
|
* @param a The first value.
|
||||||
|
* @param b The second value.
|
||||||
|
*
|
||||||
|
* @return The smaller value of `a` or `b`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bigger value of `a` or `b`.
|
||||||
|
*
|
||||||
|
* @param a The first value.
|
||||||
|
* @param b The second value.
|
||||||
|
*
|
||||||
|
* @return The bigger value of `a` or `b`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the absolute value of `a`.
|
||||||
|
*
|
||||||
|
* @param a The value.
|
||||||
|
*
|
||||||
|
* @return The absolute value of `a`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if the given value is a power of 2.
|
||||||
|
*
|
||||||
|
* @param x The value.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not.
|
||||||
|
*
|
||||||
|
* Note that this macro always returns `ZYAN_TRUE` for `x == 0`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if the given value is properly aligned.
|
||||||
|
*
|
||||||
|
* Note that this macro only works for powers of 2.
|
||||||
|
*/
|
||||||
|
#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aligns the value to the nearest given alignment boundary (by rounding it up).
|
||||||
|
*
|
||||||
|
* @param x The value.
|
||||||
|
* @param align The desired alignment.
|
||||||
|
*
|
||||||
|
* @return The aligned value.
|
||||||
|
*
|
||||||
|
* Note that this macro only works for powers of 2.
|
||||||
|
*/
|
||||||
|
#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aligns the value to the nearest given alignment boundary (by rounding it down).
|
||||||
|
*
|
||||||
|
* @param x The value.
|
||||||
|
* @param align The desired alignment.
|
||||||
|
*
|
||||||
|
* @return The aligned value.
|
||||||
|
*
|
||||||
|
* Note that this macro only works for powers of 2.
|
||||||
|
*/
|
||||||
|
#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1))
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Bit operations */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks, if the bit at index `b` is required to present the ordinal value `n`.
|
||||||
|
*
|
||||||
|
* @param n The ordinal value.
|
||||||
|
* @param b The bit index.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or
|
||||||
|
* `ZYAN_FALSE`, if not.
|
||||||
|
*
|
||||||
|
* Note that this macro always returns `ZYAN_FALSE` for `n == 0`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the number of bits required to represent the ordinal value `n`.
|
||||||
|
*
|
||||||
|
* @param n The ordinal value.
|
||||||
|
*
|
||||||
|
* @return The number of bits required to represent the ordinal value `n`.
|
||||||
|
*
|
||||||
|
* Note that this macro returns `0` for `n == 0`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_BITS_TO_REPRESENT(n) \
|
||||||
|
( \
|
||||||
|
ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \
|
||||||
|
ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#endif /* ZYCORE_DEFINES_H */
|
@ -0,0 +1,286 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Provides helper functions for performant number to string conversion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_FORMAT_H
|
||||||
|
#define ZYCORE_FORMAT_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/String.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Helpers */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the absolute value of a 64 bit int.
|
||||||
|
*
|
||||||
|
* @param x The value to process.
|
||||||
|
* @return The absolute, unsigned value.
|
||||||
|
*
|
||||||
|
* This gracefully deals with the special case of `x` being `INT_MAX`.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanU64 ZyanAbsI64(ZyanI64 x)
|
||||||
|
{
|
||||||
|
// INT_MIN special case. Can't use the value directly because GCC thinks
|
||||||
|
// it's too big for an INT64 literal, however is perfectly happy to accept
|
||||||
|
// this expression. This is also hit INT64_MIN is defined in `stdint.h`.
|
||||||
|
if (x == (-0x7fffffffffffffff - 1))
|
||||||
|
{
|
||||||
|
return 0x8000000000000000u;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ZyanU64)(x < 0 ? -x : x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Insertion */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts formatted text in the destination string at the given `index`.
|
||||||
|
*
|
||||||
|
* @param string The destination string.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param format The format string.
|
||||||
|
* @param ... The format arguments.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYAN_PRINTF_ATTR(3, 4)
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index,
|
||||||
|
const char* format, ...);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||||
|
* inserts it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||||
|
ZyanU8 padding_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||||
|
* inserts it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||||
|
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool force_sign, const ZyanString* prefix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||||
|
* inserts it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||||
|
* ones ('a'-'f').
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool uppercase);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||||
|
* inserts it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||||
|
* ones ('a'-'f').
|
||||||
|
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||||
|
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Appending */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends formatted text to the destination string.
|
||||||
|
*
|
||||||
|
* @param string The destination string.
|
||||||
|
* @param format The format string.
|
||||||
|
* @param ... The format arguments.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYAN_PRINTF_ATTR(2, 3)
|
||||||
|
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringAppendFormat(
|
||||||
|
ZyanString* string, const char* format, ...);
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value,
|
||||||
|
ZyanU8 padding_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||||
|
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||||
|
* ones ('a'-'f').
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool uppercase);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||||
|
* ones ('a'-'f').
|
||||||
|
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||||
|
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ZYCORE_FORMAT_H
|
@ -0,0 +1,511 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Provides a simple LibC abstraction and fallback routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_LIBC_H
|
||||||
|
#define ZYCORE_LIBC_H
|
||||||
|
|
||||||
|
#ifndef ZYAN_CUSTOM_LIBC
|
||||||
|
|
||||||
|
// Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC
|
||||||
|
// replacement functions
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* LibC is available */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* errno.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define ZYAN_ERRNO errno
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* stdarg.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanVAList` datatype.
|
||||||
|
*/
|
||||||
|
typedef va_list ZyanVAList;
|
||||||
|
|
||||||
|
#define ZYAN_VA_START va_start
|
||||||
|
#define ZYAN_VA_ARG va_arg
|
||||||
|
#define ZYAN_VA_END va_end
|
||||||
|
#define ZYAN_VA_COPY(dest, source) va_copy((dest), (source))
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* stdio.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define ZYAN_FPUTS fputs
|
||||||
|
#define ZYAN_FPUTC fputc
|
||||||
|
#define ZYAN_FPRINTF fprintf
|
||||||
|
#define ZYAN_PRINTF printf
|
||||||
|
#define ZYAN_PUTC putc
|
||||||
|
#define ZYAN_PUTS puts
|
||||||
|
#define ZYAN_SCANF scanf
|
||||||
|
#define ZYAN_SSCANF sscanf
|
||||||
|
#define ZYAN_VSNPRINTF vsnprintf
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanFile` datatype.
|
||||||
|
*/
|
||||||
|
typedef FILE ZyanFile;
|
||||||
|
|
||||||
|
#define ZYAN_STDIN stdin
|
||||||
|
#define ZYAN_STDOUT stdout
|
||||||
|
#define ZYAN_STDERR stderr
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* stdlib.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define ZYAN_CALLOC calloc
|
||||||
|
#define ZYAN_FREE free
|
||||||
|
#define ZYAN_MALLOC malloc
|
||||||
|
#define ZYAN_REALLOC realloc
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* string.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#define ZYAN_MEMCHR memchr
|
||||||
|
#define ZYAN_MEMCMP memcmp
|
||||||
|
#define ZYAN_MEMCPY memcpy
|
||||||
|
#define ZYAN_MEMMOVE memmove
|
||||||
|
#define ZYAN_MEMSET memset
|
||||||
|
#define ZYAN_STRCAT strcat
|
||||||
|
#define ZYAN_STRCHR strchr
|
||||||
|
#define ZYAN_STRCMP strcmp
|
||||||
|
#define ZYAN_STRCOLL strcoll
|
||||||
|
#define ZYAN_STRCPY strcpy
|
||||||
|
#define ZYAN_STRCSPN strcspn
|
||||||
|
#define ZYAN_STRLEN strlen
|
||||||
|
#define ZYAN_STRNCAT strncat
|
||||||
|
#define ZYAN_STRNCMP strncmp
|
||||||
|
#define ZYAN_STRNCPY strncpy
|
||||||
|
#define ZYAN_STRPBRK strpbrk
|
||||||
|
#define ZYAN_STRRCHR strrchr
|
||||||
|
#define ZYAN_STRSPN strspn
|
||||||
|
#define ZYAN_STRSTR strstr
|
||||||
|
#define ZYAN_STRTOK strtok
|
||||||
|
#define ZYAN_STRXFRM strxfrm
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#else // if ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* No LibC available, use our own functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These implementations are by no means optimized and will be outperformed by pretty much any
|
||||||
|
* libc implementation out there. We do not aim towards providing competetive implementations here,
|
||||||
|
* but towards providing a last resort fallback for environments without a working libc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* stdarg.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if defined(ZYAN_MSVC) || defined(ZYAN_ICC)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanVAList` datatype.
|
||||||
|
*/
|
||||||
|
typedef char* ZyanVAList;
|
||||||
|
|
||||||
|
# define ZYAN_VA_START __crt_va_start
|
||||||
|
# define ZYAN_VA_ARG __crt_va_arg
|
||||||
|
# define ZYAN_VA_END __crt_va_end
|
||||||
|
# define ZYAN_VA_COPY(destination, source) ((destination) = (source))
|
||||||
|
|
||||||
|
#elif defined(ZYAN_GNUC)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanVAList` datatype.
|
||||||
|
*/
|
||||||
|
typedef __builtin_va_list ZyanVAList;
|
||||||
|
|
||||||
|
# define ZYAN_VA_START(v, l) __builtin_va_start(v, l)
|
||||||
|
# define ZYAN_VA_END(v) __builtin_va_end(v)
|
||||||
|
# define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l)
|
||||||
|
# define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s)
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Unsupported compiler for no-libc mode."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* stdio.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count,
|
||||||
|
// char const* const format, ZyanVAList args)
|
||||||
|
// {
|
||||||
|
// // We cant provide a fallback implementation for this function
|
||||||
|
// ZYAN_UNUSED(buffer);
|
||||||
|
// ZYAN_UNUSED(count);
|
||||||
|
// ZYAN_UNUSED(format);
|
||||||
|
// ZYAN_UNUSED(args);
|
||||||
|
// return ZYAN_NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* stdlib.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size)
|
||||||
|
// {
|
||||||
|
// // We cant provide a fallback implementation for this function
|
||||||
|
// ZYAN_UNUSED(nitems);
|
||||||
|
// ZYAN_UNUSED(size);
|
||||||
|
// return ZYAN_NULL;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ZYAN_INLINE void ZYAN_FREE(void *p)
|
||||||
|
// {
|
||||||
|
// // We cant provide a fallback implementation for this function
|
||||||
|
// ZYAN_UNUSED(p);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n)
|
||||||
|
// {
|
||||||
|
// // We cant provide a fallback implementation for this function
|
||||||
|
// ZYAN_UNUSED(n);
|
||||||
|
// return ZYAN_NULL;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n)
|
||||||
|
// {
|
||||||
|
// // We cant provide a fallback implementation for this function
|
||||||
|
// ZYAN_UNUSED(p);
|
||||||
|
// ZYAN_UNUSED(n);
|
||||||
|
// return ZYAN_NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* string.h */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n)
|
||||||
|
{
|
||||||
|
const ZyanU8* p = (ZyanU8*)str;
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
if (*p != (ZyanU8)c)
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return (void*)p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n)
|
||||||
|
{
|
||||||
|
const ZyanU8* p1 = s1, *p2 = s2;
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
if (*p1 != *p2)
|
||||||
|
{
|
||||||
|
return *p1 - *p2;
|
||||||
|
}
|
||||||
|
p1++, p2++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n)
|
||||||
|
{
|
||||||
|
volatile ZyanU8* dp = dst;
|
||||||
|
const ZyanU8* sp = src;
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*dp++ = *sp++;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n)
|
||||||
|
{
|
||||||
|
volatile ZyanU8* pd = dst;
|
||||||
|
const ZyanU8* ps = src;
|
||||||
|
if (ps < pd)
|
||||||
|
{
|
||||||
|
for (pd += n, ps += n; n--;)
|
||||||
|
{
|
||||||
|
*--pd = *--ps;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*pd++ = *ps++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n)
|
||||||
|
{
|
||||||
|
volatile ZyanU8* p = dst;
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*p++ = (unsigned char)val;
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src)
|
||||||
|
{
|
||||||
|
char* ret = dest;
|
||||||
|
while (*dest)
|
||||||
|
{
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
while ((*dest++ = *src++));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c)
|
||||||
|
{
|
||||||
|
while (*s != (char)c)
|
||||||
|
{
|
||||||
|
if (!*s++)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (char*)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
while (*s1 && (*s1 == *s2))
|
||||||
|
{
|
||||||
|
s1++, s2++;
|
||||||
|
}
|
||||||
|
return *(const ZyanU8*)s1 - *(const ZyanU8*)s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
ZYAN_UNUSED(s1);
|
||||||
|
ZYAN_UNUSED(s2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src)
|
||||||
|
{
|
||||||
|
char* ret = dest;
|
||||||
|
while ((*dest++ = *src++));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
ZyanUSize ret = 0;
|
||||||
|
while (*s1)
|
||||||
|
{
|
||||||
|
if (ZYAN_STRCHR(s2, *s1))
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
s1++, ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str)
|
||||||
|
{
|
||||||
|
const char* p = str;
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
return str - p;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n)
|
||||||
|
{
|
||||||
|
char* ret = dest;
|
||||||
|
while (*dest)
|
||||||
|
{
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
if (!(*dest++ = *src++))
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dest = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n)
|
||||||
|
{
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
if (*s1++ != *s2++)
|
||||||
|
{
|
||||||
|
return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n)
|
||||||
|
{
|
||||||
|
char* ret = dest;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!n--)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} while ((*dest++ = *src++));
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*dest++ = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
while (*s1)
|
||||||
|
{
|
||||||
|
if(ZYAN_STRCHR(s2, *s1++))
|
||||||
|
{
|
||||||
|
return (char*)--s1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c)
|
||||||
|
{
|
||||||
|
char* ret = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (*s == (char)c)
|
||||||
|
{
|
||||||
|
ret = (char*)s;
|
||||||
|
}
|
||||||
|
} while (*s++);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
ZyanUSize ret = 0;
|
||||||
|
while (*s1 && ZYAN_STRCHR(s2, *s1++))
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
const ZyanUSize n = ZYAN_STRLEN(s2);
|
||||||
|
while (*s1)
|
||||||
|
{
|
||||||
|
if (!ZYAN_MEMCMP(s1++, s2, n))
|
||||||
|
{
|
||||||
|
return (char*)(s1 - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim)
|
||||||
|
{
|
||||||
|
static char* p = 0;
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
p = str;
|
||||||
|
} else
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
str = p + ZYAN_STRSPN(p, delim);
|
||||||
|
p = str + ZYAN_STRCSPN(str, delim);
|
||||||
|
if (p == str)
|
||||||
|
{
|
||||||
|
return p = 0;
|
||||||
|
}
|
||||||
|
p = *p ? *p = 0, p + 1 : 0;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n)
|
||||||
|
{
|
||||||
|
const ZyanUSize n2 = ZYAN_STRLEN(src);
|
||||||
|
if (n > n2)
|
||||||
|
{
|
||||||
|
ZYAN_STRCPY(dest, src);
|
||||||
|
}
|
||||||
|
return n2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#endif /* ZYCORE_LIBC_H */
|
@ -0,0 +1,574 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Implements a doubly linked list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_LIST_H
|
||||||
|
#define ZYCORE_LIST_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Allocator.h>
|
||||||
|
#include <Zycore/Object.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanListNode` struct.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanListNode_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A pointer to the previous list node.
|
||||||
|
*/
|
||||||
|
struct ZyanListNode_* prev;
|
||||||
|
/**
|
||||||
|
* A pointer to the next list node.
|
||||||
|
*/
|
||||||
|
struct ZyanListNode_* next;
|
||||||
|
} ZyanListNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanList` struct.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanList_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The memory allocator.
|
||||||
|
*/
|
||||||
|
ZyanAllocator* allocator;
|
||||||
|
/**
|
||||||
|
* The current number of elements in the list.
|
||||||
|
*/
|
||||||
|
ZyanUSize size;
|
||||||
|
/**
|
||||||
|
* The size of a single element in bytes.
|
||||||
|
*/
|
||||||
|
ZyanUSize element_size;
|
||||||
|
/**
|
||||||
|
* The element destructor callback.
|
||||||
|
*/
|
||||||
|
ZyanMemberProcedure destructor;
|
||||||
|
/**
|
||||||
|
* The head node.
|
||||||
|
*/
|
||||||
|
ZyanListNode* head;
|
||||||
|
/**
|
||||||
|
* The tail node.
|
||||||
|
*/
|
||||||
|
ZyanListNode* tail;
|
||||||
|
/**
|
||||||
|
* The data buffer.
|
||||||
|
*
|
||||||
|
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||||
|
*/
|
||||||
|
void* buffer;
|
||||||
|
/**
|
||||||
|
* The data buffer capacity (number of bytes).
|
||||||
|
*
|
||||||
|
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||||
|
*/
|
||||||
|
ZyanUSize capacity;
|
||||||
|
/**
|
||||||
|
* The first unused node.
|
||||||
|
*
|
||||||
|
* When removing a node, the first-unused value is updated to point at the removed node and the
|
||||||
|
* next node of the removed node will be updated to point at the old first-unused node.
|
||||||
|
*
|
||||||
|
* When appending the memory of the first unused-node is recycled to store the new node. The
|
||||||
|
* value of the first-unused node is then updated to point at the reused nodes next node.
|
||||||
|
*
|
||||||
|
* If the first-unused value is `ZYAN_NULL`, any new node will be "allocated" behind the tail
|
||||||
|
* node (if there is enough space left in the fixed size buffer).
|
||||||
|
*
|
||||||
|
* Only used for instances created by `ZyanListInitCustomBuffer`.
|
||||||
|
*/
|
||||||
|
ZyanListNode* first_unused;
|
||||||
|
} ZyanList;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines an uninitialized `ZyanList` instance.
|
||||||
|
*/
|
||||||
|
#define ZYAN_LIST_INITIALIZER \
|
||||||
|
{ \
|
||||||
|
/* allocator */ ZYAN_NULL, \
|
||||||
|
/* size */ 0, \
|
||||||
|
/* element_size */ 0, \
|
||||||
|
/* head */ ZYAN_NULL, \
|
||||||
|
/* destructor */ ZYAN_NULL, \
|
||||||
|
/* tail */ ZYAN_NULL, \
|
||||||
|
/* buffer */ ZYAN_NULL, \
|
||||||
|
/* capacity */ 0, \
|
||||||
|
/* first_unused */ ZYAN_NULL \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Helper macros */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data value of the given `node`.
|
||||||
|
*
|
||||||
|
* @param type The desired value type.
|
||||||
|
* @param node A pointer to the `ZyanListNode` struct.
|
||||||
|
*
|
||||||
|
* @result The data value of the given `node`.
|
||||||
|
*
|
||||||
|
* Note that this function is unsafe and might dereference a null-pointer.
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define ZYAN_LIST_GET(type, node) \
|
||||||
|
(*reinterpret_cast<const type*>(ZyanListGetNodeData(node)))
|
||||||
|
#else
|
||||||
|
#define ZYAN_LIST_GET(type, node) \
|
||||||
|
(*(const type*)ZyanListGetNodeData(node))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Constructor and destructor */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param element_size The size of a single element in bytes.
|
||||||
|
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||||
|
* `ZYAN_NULL` if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The memory for the list elements is dynamically allocated by the default allocator.
|
||||||
|
*
|
||||||
|
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size,
|
||||||
|
ZyanMemberProcedure destructor);
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanList` instance and sets a custom `allocator`.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param element_size The size of a single element in bytes.
|
||||||
|
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||||
|
* `ZYAN_NULL` if not needed.
|
||||||
|
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size,
|
||||||
|
ZyanMemberProcedure destructor, ZyanAllocator* allocator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanList` instance and configures it to use a custom user
|
||||||
|
* defined buffer with a fixed size.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param element_size The size of a single element in bytes.
|
||||||
|
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||||
|
* `ZYAN_NULL` if not needed.
|
||||||
|
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||||
|
* @param capacity The maximum capacity (number of bytes) of the buffer including the
|
||||||
|
* space required for the list-nodes.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The buffer capacity required to store `n` elements of type `T` is be calculated by:
|
||||||
|
* `size = n * sizeof(ZyanListNode) + n * sizeof(T)`
|
||||||
|
*
|
||||||
|
* Finalization is not required for instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size,
|
||||||
|
ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the given `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListDestroy(ZyanList* list);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Duplication */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new `ZyanList` instance by duplicating an existing list.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||||
|
* @param source A pointer to the source list.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The memory for the list is dynamically allocated by the default allocator.
|
||||||
|
*
|
||||||
|
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListDuplicate(ZyanList* destination,
|
||||||
|
const ZyanList* source);
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new `ZyanList` instance by duplicating an existing list and sets a
|
||||||
|
* custom `allocator`.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||||
|
* @param source A pointer to the source list.
|
||||||
|
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
|
||||||
|
* Finalization with `ZyanListDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListDuplicateEx(ZyanList* destination, const ZyanList* source,
|
||||||
|
ZyanAllocator* allocator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new `ZyanList` instance by duplicating an existing list and
|
||||||
|
* configures it to use a custom user defined buffer with a fixed size.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the (uninitialized) destination `ZyanList` instance.
|
||||||
|
* @param source A pointer to the source list.
|
||||||
|
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||||
|
* @param capacity The maximum capacity (number of bytes) of the buffer including the
|
||||||
|
* space required for the list-nodes.
|
||||||
|
|
||||||
|
* This function will fail, if the capacity of the buffer is not sufficient
|
||||||
|
* to store all elements of the source list.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The buffer capacity required to store `n` elements of type `T` is be calculated by:
|
||||||
|
* `size = n * sizeof(ZyanListNode) + n * sizeof(T)`
|
||||||
|
*
|
||||||
|
* Finalization is not required for instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListDuplicateCustomBuffer(ZyanList* destination,
|
||||||
|
const ZyanList* source, void* buffer, ZyanUSize capacity);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Item access */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the first `ZyanListNode` struct of the given list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param node Receives a pointer to the first `ZyanListNode` struct of the list.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the last `ZyanListNode` struct of the given list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param node Receives a pointer to the last `ZyanListNode` struct of the list.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives a pointer to the previous `ZyanListNode` struct linked to the passed one.
|
||||||
|
*
|
||||||
|
* @param node Receives a pointer to the previous `ZyanListNode` struct linked to the passed
|
||||||
|
* one.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives a pointer to the next `ZyanListNode` struct linked to the passed one.
|
||||||
|
*
|
||||||
|
* @param node Receives a pointer to the next `ZyanListNode` struct linked to the passed one.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListGetNextNode(const ZyanListNode** node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a constant pointer to the data of the given `node`.
|
||||||
|
*
|
||||||
|
* @param node A pointer to the `ZyanListNode` struct.
|
||||||
|
*
|
||||||
|
* @return A constant pointer to the the data of the given `node` or `ZYAN_NULL`, if an error
|
||||||
|
* occured.
|
||||||
|
*
|
||||||
|
* Take a look at `ZyanListGetNodeDataEx`, if you need a function that returns a zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT const void* ZyanListGetNodeData(const ZyanListNode* node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a constant pointer to the data of the given `node`..
|
||||||
|
*
|
||||||
|
* @param node A pointer to the `ZyanListNode` struct.
|
||||||
|
* @param value Receives a constant pointer to the data of the given `node`.
|
||||||
|
*
|
||||||
|
* Take a look at `ZyanListGetNodeData`, if you need a function that directly returns a pointer.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable pointer to the data of the given `node`.
|
||||||
|
*
|
||||||
|
* @param node A pointer to the `ZyanListNode` struct.
|
||||||
|
*
|
||||||
|
* @return A mutable pointer to the the data of the given `node` or `ZYAN_NULL`, if an error
|
||||||
|
* occured.
|
||||||
|
*
|
||||||
|
* Take a look at `ZyanListGetPointerMutableEx` instead, if you need a function that returns a
|
||||||
|
* zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT void* ZyanListGetNodeDataMutable(const ZyanListNode* node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable pointer to the data of the given `node`..
|
||||||
|
*
|
||||||
|
* @param node A pointer to the `ZyanListNode` struct.
|
||||||
|
* @param value Receives a mutable pointer to the data of the given `node`.
|
||||||
|
*
|
||||||
|
* Take a look at `ZyanListGetNodeDataMutable`, if you need a function that directly returns a
|
||||||
|
* pointer.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a new data value to the given `node`.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param node A pointer to the `ZyanListNode` struct.
|
||||||
|
* @param value The value to assign.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node,
|
||||||
|
const void* value);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Insertion */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new `item` to the end of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param item A pointer to the item to add.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListPushBack(ZyanList* list, const void* item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new `item` to the beginning of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param item A pointer to the item to add.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListPushFront(ZyanList* list, const void* item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an `item` in-place at the end of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param item Receives a pointer to the new item.
|
||||||
|
* @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in
|
||||||
|
* undefined state, if no constructor was passed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item,
|
||||||
|
ZyanMemberFunction constructor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an `item` in-place at the beginning of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param item Receives a pointer to the new item.
|
||||||
|
* @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in
|
||||||
|
* undefined state, if no constructor was passed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item,
|
||||||
|
ZyanMemberFunction constructor);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Deletion */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the last element of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListPopBack(ZyanList* list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the firstelement of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListPopFront(ZyanList* list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given `node` from the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param node A pointer to the `ZyanListNode` struct.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes multiple nodes from the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param first A pointer to the first node.
|
||||||
|
* @param last A pointer to the last node.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first,
|
||||||
|
const ZyanListNode* last);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erases all elements of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListClear(ZyanList* list);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Searching */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Memory management */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes the given `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param size The new size of the list.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes the given `ZyanList` instance.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param size The new size of the list.
|
||||||
|
* @param initializer A pointer to a value to be used as initializer for new items.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Information */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current size of the list.
|
||||||
|
*
|
||||||
|
* @param list A pointer to the `ZyanList` instance.
|
||||||
|
* @param size Receives the size of the list.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_VECTOR_H */
|
@ -0,0 +1,84 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Defines some generic object-related datatypes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_OBJECT_H
|
||||||
|
#define ZYCORE_OBJECT_H
|
||||||
|
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanMemberProcedure` function prototype.
|
||||||
|
*
|
||||||
|
* @param object A pointer to the object.
|
||||||
|
*/
|
||||||
|
typedef void (*ZyanMemberProcedure)(void* object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanConstMemberProcedure` function prototype.
|
||||||
|
*
|
||||||
|
* @param object A pointer to the object.
|
||||||
|
*/
|
||||||
|
typedef void (*ZyanConstMemberProcedure)(const void* object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanMemberFunction` function prototype.
|
||||||
|
*
|
||||||
|
* @param object A pointer to the object.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
typedef ZyanStatus (*ZyanMemberFunction)(void* object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanConstMemberFunction` function prototype.
|
||||||
|
*
|
||||||
|
* @param object A pointer to the object.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
typedef ZyanStatus (*ZyanConstMemberFunction)(const void* object);
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_OBJECT_H */
|
@ -0,0 +1,287 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zyan-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Status code definitions and check macros.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_STATUS_H
|
||||||
|
#define ZYCORE_STATUS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanStatus` data type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU32 ZyanStatus;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Definition */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a zyan status code.
|
||||||
|
*
|
||||||
|
* @param error `1`, if the status code signals an error or `0`, if not.
|
||||||
|
* @param module The module id.
|
||||||
|
* @param code The actual code.
|
||||||
|
*
|
||||||
|
* @return The zyan status code.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MAKE_STATUS(error, module, code) \
|
||||||
|
(ZyanStatus)((((error) & 0x01u) << 31u) | (((module) & 0x7FFu) << 20u) | ((code) & 0xFFFFFu))
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Checks */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a zyan operation was successful.
|
||||||
|
*
|
||||||
|
* @param status The zyan status-code to check.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_TRUE`, if the operation succeeded or `ZYAN_FALSE`, if not.
|
||||||
|
*/
|
||||||
|
#define ZYAN_SUCCESS(status) \
|
||||||
|
(!((status) & 0x80000000u))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a zyan operation failed.
|
||||||
|
*
|
||||||
|
* @param status The zyan status-code to check.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_TRUE`, if the operation failed or `ZYAN_FALSE`, if not.
|
||||||
|
*/
|
||||||
|
#define ZYAN_FAILED(status) \
|
||||||
|
((status) & 0x80000000u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a zyan operation was successful and returns with the status-code, if not.
|
||||||
|
*
|
||||||
|
* @param status The zyan status-code to check.
|
||||||
|
*/
|
||||||
|
#define ZYAN_CHECK(status) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
const ZyanStatus status_047620348 = (status); \
|
||||||
|
if (!ZYAN_SUCCESS(status_047620348)) \
|
||||||
|
{ \
|
||||||
|
return status_047620348; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Information */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the module id of a zyan status-code.
|
||||||
|
*
|
||||||
|
* @param status The zyan status-code.
|
||||||
|
*
|
||||||
|
* @return The module id of the zyan status-code.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_MODULE(status) \
|
||||||
|
(((status) >> 20) & 0x7FFu)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the code of a zyan status-code.
|
||||||
|
*
|
||||||
|
* @param status The zyan status-code.
|
||||||
|
*
|
||||||
|
* @return The code of the zyan status-code.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_CODE(status) \
|
||||||
|
((status) & 0xFFFFFu)
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Status codes */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Module IDs */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The zycore generic module id.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MODULE_ZYCORE 0x001u
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The zycore arg-parse submodule id.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MODULE_ARGPARSE 0x003u
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base module id for user-defined status codes.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MODULE_USER 0x3FFu
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Status codes (general purpose) */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operation completed successfully.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_SUCCESS \
|
||||||
|
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x00u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operation failed with an generic error.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_FAILED \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x01u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operation completed successfully and returned `ZYAN_TRUE`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_TRUE \
|
||||||
|
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x02u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operation completed successfully and returned `ZYAN_FALSE`.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_FALSE \
|
||||||
|
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x03u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An invalid argument was passed to a function.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_INVALID_ARGUMENT \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x04u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An attempt was made to perform an invalid operation.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_INVALID_OPERATION \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x05u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insufficient privileges to perform the requested operation.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_ACCESS_DENIED \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x06u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requested entity was not found.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_NOT_FOUND \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x07u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An index passed to a function was out of bounds.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_OUT_OF_RANGE \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x08u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A buffer passed to a function was too small to complete the requested operation.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x09u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insufficient memory to perform the operation.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_NOT_ENOUGH_MEMORY \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Au)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unknown error occurred during a system function call.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_BAD_SYSTEMCALL \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Bu)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The process ran out of resources while performing an operation.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_OUT_OF_RESOURCES \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Cu)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dependency library was not found or does have an unexpected version number or
|
||||||
|
* feature-set.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_MISSING_DEPENDENCY \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Du)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Status codes (arg parse) */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Argument was not expected.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_ARG_NOT_UNDERSTOOD \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x00u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Too few arguments were provided.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_TOO_FEW_ARGS \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x01u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Too many arguments were provided.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_TOO_MANY_ARGS \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x02u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An argument that expected a value misses its value.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_ARG_MISSES_VALUE \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x03u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A required argument is missing.
|
||||||
|
*/
|
||||||
|
#define ZYAN_STATUS_REQUIRED_ARG_MISSING \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x04u)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_STATUS_H */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,195 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zyan-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Includes and defines some default data types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_TYPES_H
|
||||||
|
#define ZYCORE_TYPES_H
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Integer types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#if defined(ZYAN_NO_LIBC) || \
|
||||||
|
(defined(ZYAN_MSVC) && defined(ZYAN_KERNEL)) // The WDK LibC lacks stdint.h.
|
||||||
|
// No LibC mode, use compiler built-in types / macros.
|
||||||
|
# if defined(ZYAN_MSVC) || defined(ZYAN_ICC)
|
||||||
|
typedef unsigned __int8 ZyanU8;
|
||||||
|
typedef unsigned __int16 ZyanU16;
|
||||||
|
typedef unsigned __int32 ZyanU32;
|
||||||
|
typedef unsigned __int64 ZyanU64;
|
||||||
|
typedef signed __int8 ZyanI8;
|
||||||
|
typedef signed __int16 ZyanI16;
|
||||||
|
typedef signed __int32 ZyanI32;
|
||||||
|
typedef signed __int64 ZyanI64;
|
||||||
|
# if _WIN64
|
||||||
|
typedef ZyanU64 ZyanUSize;
|
||||||
|
typedef ZyanI64 ZyanISize;
|
||||||
|
typedef ZyanU64 ZyanUPointer;
|
||||||
|
typedef ZyanI64 ZyanIPointer;
|
||||||
|
# else
|
||||||
|
typedef ZyanU32 ZyanUSize;
|
||||||
|
typedef ZyanI32 ZyanISize;
|
||||||
|
typedef ZyanU32 ZyanUPointer;
|
||||||
|
typedef ZyanI32 ZyanIPointer;
|
||||||
|
# endif
|
||||||
|
# elif defined(ZYAN_GNUC)
|
||||||
|
typedef __UINT8_TYPE__ ZyanU8;
|
||||||
|
typedef __UINT16_TYPE__ ZyanU16;
|
||||||
|
typedef __UINT32_TYPE__ ZyanU32;
|
||||||
|
typedef __UINT64_TYPE__ ZyanU64;
|
||||||
|
typedef __INT8_TYPE__ ZyanI8;
|
||||||
|
typedef __INT16_TYPE__ ZyanI16;
|
||||||
|
typedef __INT32_TYPE__ ZyanI32;
|
||||||
|
typedef __INT64_TYPE__ ZyanI64;
|
||||||
|
typedef __SIZE_TYPE__ ZyanUSize;
|
||||||
|
typedef __PTRDIFF_TYPE__ ZyanISize;
|
||||||
|
typedef __UINTPTR_TYPE__ ZyanUPointer;
|
||||||
|
typedef __INTPTR_TYPE__ ZyanIPointer;
|
||||||
|
# else
|
||||||
|
# error "Unsupported compiler for no-libc mode."
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
// If is LibC present, we use stdint types.
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <stddef.h>
|
||||||
|
typedef uint8_t ZyanU8;
|
||||||
|
typedef uint16_t ZyanU16;
|
||||||
|
typedef uint32_t ZyanU32;
|
||||||
|
typedef uint64_t ZyanU64;
|
||||||
|
typedef int8_t ZyanI8;
|
||||||
|
typedef int16_t ZyanI16;
|
||||||
|
typedef int32_t ZyanI32;
|
||||||
|
typedef int64_t ZyanI64;
|
||||||
|
typedef size_t ZyanUSize;
|
||||||
|
typedef ptrdiff_t ZyanISize;
|
||||||
|
typedef uintptr_t ZyanUPointer;
|
||||||
|
typedef intptr_t ZyanIPointer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Verify size assumptions.
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanU8 ) == 1 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanU16 ) == 2 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanU32 ) == 4 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanU64 ) == 8 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanI8 ) == 1 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanI16 ) == 2 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanI32 ) == 4 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanI64 ) == 8 );
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanUSize ) == sizeof(void*)); // TODO: This one is incorrect!
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanISize ) == sizeof(void*)); // TODO: This one is incorrect!
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanUPointer) == sizeof(void*));
|
||||||
|
ZYAN_STATIC_ASSERT(sizeof(ZyanIPointer) == sizeof(void*));
|
||||||
|
|
||||||
|
// Verify signedness assumptions (relies on size checks above).
|
||||||
|
ZYAN_STATIC_ASSERT((ZyanI8 )-1 >> 1 < (ZyanI8 )((ZyanU8 )-1 >> 1));
|
||||||
|
ZYAN_STATIC_ASSERT((ZyanI16)-1 >> 1 < (ZyanI16)((ZyanU16)-1 >> 1));
|
||||||
|
ZYAN_STATIC_ASSERT((ZyanI32)-1 >> 1 < (ZyanI32)((ZyanU32)-1 >> 1));
|
||||||
|
ZYAN_STATIC_ASSERT((ZyanI64)-1 >> 1 < (ZyanI64)((ZyanU64)-1 >> 1));
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Pointer */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanVoidPointer` data-type.
|
||||||
|
*/
|
||||||
|
typedef char* ZyanVoidPointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanConstVoidPointer` data-type.
|
||||||
|
*/
|
||||||
|
typedef const void* ZyanConstVoidPointer;
|
||||||
|
|
||||||
|
#define ZYAN_NULL ((void*)0)
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Logic types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Boolean */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define ZYAN_FALSE 0
|
||||||
|
#define ZYAN_TRUE 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanBool` data-type.
|
||||||
|
*
|
||||||
|
* Represents a default boolean data-type where `0` is interpreted as `false` and all other values
|
||||||
|
* as `true`.
|
||||||
|
*/
|
||||||
|
typedef ZyanU8 ZyanBool;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Ternary */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanTernary` data-type.
|
||||||
|
*
|
||||||
|
* The `ZyanTernary` is a balanced ternary type that uses three truth values indicating `true`,
|
||||||
|
* `false` and an indeterminate third value.
|
||||||
|
*/
|
||||||
|
typedef ZyanI8 ZyanTernary;
|
||||||
|
|
||||||
|
#define ZYAN_TERNARY_FALSE (-1)
|
||||||
|
#define ZYAN_TERNARY_UNKNOWN 0x00
|
||||||
|
#define ZYAN_TERNARY_TRUE 0x01
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* String types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* C-style strings */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanCharPointer` data-type.
|
||||||
|
*
|
||||||
|
* This type is most often used to represent null-terminated strings aka. C-style strings.
|
||||||
|
*/
|
||||||
|
typedef char* ZyanCharPointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanConstCharPointer` data-type.
|
||||||
|
*
|
||||||
|
* This type is most often used to represent null-terminated strings aka. C-style strings.
|
||||||
|
*/
|
||||||
|
typedef const char* ZyanConstCharPointer;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#endif /* ZYCORE_TYPES_H */
|
@ -0,0 +1,723 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Implements the vector container class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_VECTOR_H
|
||||||
|
#define ZYCORE_VECTOR_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Allocator.h>
|
||||||
|
#include <Zycore/Comparison.h>
|
||||||
|
#include <Zycore/Object.h>
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Constants */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial minimum capacity (number of elements) for all dynamically allocated vector
|
||||||
|
* instances.
|
||||||
|
*/
|
||||||
|
#define ZYAN_VECTOR_MIN_CAPACITY 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default growth factor for all vector instances.
|
||||||
|
*/
|
||||||
|
#define ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR 2.00f
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default shrink threshold for all vector instances.
|
||||||
|
*/
|
||||||
|
#define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 0.25f
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZyanVector` struct.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZyanVector_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The memory allocator.
|
||||||
|
*/
|
||||||
|
ZyanAllocator* allocator;
|
||||||
|
/**
|
||||||
|
* The growth factor.
|
||||||
|
*/
|
||||||
|
float growth_factor;
|
||||||
|
/**
|
||||||
|
* The shrink threshold.
|
||||||
|
*/
|
||||||
|
float shrink_threshold;
|
||||||
|
/**
|
||||||
|
* The current number of elements in the vector.
|
||||||
|
*/
|
||||||
|
ZyanUSize size;
|
||||||
|
/**
|
||||||
|
* The maximum capacity (number of elements).
|
||||||
|
*/
|
||||||
|
ZyanUSize capacity;
|
||||||
|
/**
|
||||||
|
* The size of a single element in bytes.
|
||||||
|
*/
|
||||||
|
ZyanUSize element_size;
|
||||||
|
/**
|
||||||
|
* The element destructor callback.
|
||||||
|
*/
|
||||||
|
ZyanMemberProcedure destructor;
|
||||||
|
/**
|
||||||
|
* The data pointer.
|
||||||
|
*/
|
||||||
|
void* data;
|
||||||
|
} ZyanVector;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines an uninitialized `ZyanVector` instance.
|
||||||
|
*/
|
||||||
|
#define ZYAN_VECTOR_INITIALIZER \
|
||||||
|
{ \
|
||||||
|
/* allocator */ ZYAN_NULL, \
|
||||||
|
/* growth_factor */ 0.0f, \
|
||||||
|
/* shrink_threshold */ 0.0f, \
|
||||||
|
/* size */ 0, \
|
||||||
|
/* capacity */ 0, \
|
||||||
|
/* element_size */ 0, \
|
||||||
|
/* destructor */ ZYAN_NULL, \
|
||||||
|
/* data */ ZYAN_NULL \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Helper macros */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the element at the given `index`.
|
||||||
|
*
|
||||||
|
* @param type The desired value type.
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The element index.
|
||||||
|
*
|
||||||
|
* @result The value of the desired element in the vector.
|
||||||
|
*
|
||||||
|
* Note that this function is unsafe and might dereference a null-pointer.
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define ZYAN_VECTOR_GET(type, vector, index) \
|
||||||
|
(*reinterpret_cast<const type*>(ZyanVectorGet(vector, index)))
|
||||||
|
#else
|
||||||
|
#define ZYAN_VECTOR_GET(type, vector, index) \
|
||||||
|
(*(const type*)ZyanVectorGet(vector, index))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loops through all elements of the vector.
|
||||||
|
*
|
||||||
|
* @param type The desired value type.
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param item_name The name of the iterator item.
|
||||||
|
* @param body The body to execute for each item in the vector.
|
||||||
|
*/
|
||||||
|
#define ZYAN_VECTOR_FOREACH(type, vector, item_name, body) \
|
||||||
|
{ \
|
||||||
|
const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \
|
||||||
|
for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \
|
||||||
|
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \
|
||||||
|
ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \
|
||||||
|
++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \
|
||||||
|
{ \
|
||||||
|
const type item_name = ZYAN_VECTOR_GET(type, vector, \
|
||||||
|
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \
|
||||||
|
body \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loops through all elements of the vector.
|
||||||
|
*
|
||||||
|
* @param type The desired value type.
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param item_name The name of the iterator item.
|
||||||
|
* @param body The body to execute for each item in the vector.
|
||||||
|
*/
|
||||||
|
#define ZYAN_VECTOR_FOREACH_MUTABLE(type, vector, item_name, body) \
|
||||||
|
{ \
|
||||||
|
const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \
|
||||||
|
for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \
|
||||||
|
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \
|
||||||
|
ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \
|
||||||
|
++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \
|
||||||
|
{ \
|
||||||
|
type* const item_name = ZyanVectorGetMutable(vector, \
|
||||||
|
ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \
|
||||||
|
body \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Constructor and destructor */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element_size The size of a single element in bytes.
|
||||||
|
* @param capacity The initial capacity (number of elements).
|
||||||
|
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||||
|
* `ZYAN_NULL` if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The memory for the vector elements is dynamically allocated by the default allocator using the
|
||||||
|
* default growth factor of `2.0f` and the default shrink threshold of `0.25f`.
|
||||||
|
*
|
||||||
|
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorInit(ZyanVector* vector,
|
||||||
|
ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor);
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanVector` instance and sets a custom `allocator` and memory
|
||||||
|
* allocation/deallocation parameters.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element_size The size of a single element in bytes.
|
||||||
|
* @param capacity The initial capacity (number of elements).
|
||||||
|
* @param destructor A destructor callback that is invoked every time an item is deleted,
|
||||||
|
* or `ZYAN_NULL` if not needed.
|
||||||
|
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||||
|
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||||
|
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||||
|
* dynamic shrinking.
|
||||||
|
*
|
||||||
|
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size,
|
||||||
|
ZyanUSize capacity, ZyanMemberProcedure destructor, ZyanAllocator* allocator,
|
||||||
|
float growth_factor, float shrink_threshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZyanVector` instance and configures it to use a custom user
|
||||||
|
* defined buffer with a fixed size.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element_size The size of a single element in bytes.
|
||||||
|
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||||
|
* @param capacity The maximum capacity (number of elements) of the buffer.
|
||||||
|
* @param destructor A destructor callback that is invoked every time an item is deleted, or
|
||||||
|
* `ZYAN_NULL` if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* Finalization is not required for instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size,
|
||||||
|
void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the given `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance..
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorDestroy(ZyanVector* vector);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Duplication */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new `ZyanVector` instance by duplicating an existing vector.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||||
|
* @param source A pointer to the source vector.
|
||||||
|
* @param capacity The initial capacity (number of elements).
|
||||||
|
*
|
||||||
|
* This value is automatically adjusted to the size of the source vector, if
|
||||||
|
* a smaller value was passed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* The memory for the vector is dynamically allocated by the default allocator using the default
|
||||||
|
* growth factor of `2.0f` and the default shrink threshold of `0.25f`.
|
||||||
|
*
|
||||||
|
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorDuplicate(ZyanVector* destination,
|
||||||
|
const ZyanVector* source, ZyanUSize capacity);
|
||||||
|
|
||||||
|
#endif // ZYAN_NO_LIBC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new `ZyanVector` instance by duplicating an existing vector and sets a
|
||||||
|
* custom `allocator` and memory allocation/deallocation parameters.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||||
|
* @param source A pointer to the source vector.
|
||||||
|
* @param capacity The initial capacity (number of elements).
|
||||||
|
|
||||||
|
* This value is automatically adjusted to the size of the source
|
||||||
|
* vector, if a smaller value was passed.
|
||||||
|
* @param allocator A pointer to a `ZyanAllocator` instance.
|
||||||
|
* @param growth_factor The growth factor (from `1.0f` to `x.xf`).
|
||||||
|
* @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`).
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables
|
||||||
|
* dynamic shrinking.
|
||||||
|
*
|
||||||
|
* Finalization with `ZyanVectorDestroy` is required for all instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source,
|
||||||
|
ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, float shrink_threshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new `ZyanVector` instance by duplicating an existing vector and
|
||||||
|
* configures it to use a custom user defined buffer with a fixed size.
|
||||||
|
*
|
||||||
|
* @param destination A pointer to the (uninitialized) destination `ZyanVector` instance.
|
||||||
|
* @param source A pointer to the source vector.
|
||||||
|
* @param buffer A pointer to the buffer that is used as storage for the elements.
|
||||||
|
* @param capacity The maximum capacity (number of elements) of the buffer.
|
||||||
|
|
||||||
|
* This function will fail, if the capacity of the buffer is less than the
|
||||||
|
* size of the source vector.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* Finalization is not required for instances created by this function.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination,
|
||||||
|
const ZyanVector* source, void* buffer, ZyanUSize capacity);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Element access */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a constant pointer to the element at the given `index`.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The element index.
|
||||||
|
*
|
||||||
|
* @return A constant pointer to the desired element in the vector or `ZYAN_NULL`, if an error
|
||||||
|
* occured.
|
||||||
|
*
|
||||||
|
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||||
|
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||||
|
*
|
||||||
|
* Take a look at `ZyanVectorGetPointer` instead, if you need a function that returns a zyan status
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable pointer to the element at the given `index`.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The element index.
|
||||||
|
*
|
||||||
|
* @return A mutable pointer to the desired element in the vector or `ZYAN_NULL`, if an error
|
||||||
|
* occured.
|
||||||
|
*
|
||||||
|
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||||
|
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||||
|
*
|
||||||
|
* Take a look at `ZyanVectorGetPointerMutable` instead, if you need a function that returns a
|
||||||
|
* zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a constant pointer to the element at the given `index`.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The element index.
|
||||||
|
* @param value Receives a constant pointer to the desired element in the vector.
|
||||||
|
*
|
||||||
|
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||||
|
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index,
|
||||||
|
const void** value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable pointer to the element at the given `index`.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The element index.
|
||||||
|
* @param value Receives a mutable pointer to the desired element in the vector.
|
||||||
|
*
|
||||||
|
* Note that the returned pointer might get invalid when the vector is resized by either a manual
|
||||||
|
* call to the memory-management functions or implicitly by inserting or removing elements.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index,
|
||||||
|
void** value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a new value to the element at the given `index`.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The value index.
|
||||||
|
* @param value The value to assign.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index,
|
||||||
|
const void* value);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Insertion */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new `element` to the end of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element A pointer to the element to add.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an `element` at the given `index` of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param element A pointer to the element to insert.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index,
|
||||||
|
const void* element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts multiple `elements` at the given `index` of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param elements A pointer to the first element.
|
||||||
|
* @param count The number of elements to insert.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index,
|
||||||
|
const void* elements, ZyanUSize count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an `element` in-place at the end of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element Receives a pointer to the new element.
|
||||||
|
* @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in
|
||||||
|
* undefined state, if no constructor was passed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element,
|
||||||
|
ZyanMemberFunction constructor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an `element` in-place and inserts it at the given `index` of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The insert index.
|
||||||
|
* @param element Receives a pointer to the new element.
|
||||||
|
* @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in
|
||||||
|
* undefined state, if no constructor was passed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index,
|
||||||
|
void** element, ZyanMemberFunction constructor);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Utils */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps the element at `index_first` with the element at `index_second`.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index_first The index of the first element.
|
||||||
|
* @param index_second The index of the second element.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function requires the vector to have spare capacity for one temporary element. Call
|
||||||
|
* `ZyanVectorReserve` before this function to increase capacity, if needed.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first,
|
||||||
|
ZyanUSize index_second);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Deletion */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the element at the given `index` of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The element index.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes multiple elements from the given vector, starting at `index`.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param index The index of the first element to delete.
|
||||||
|
* @param count The number of elements to delete.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index,
|
||||||
|
ZyanUSize count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the last element of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorPopBack(ZyanVector* vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erases all elements of the given vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorClear(ZyanVector* vector);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Searching */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sequentially searches for the first occurrence of `element` in the given vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element A pointer to the element to search for.
|
||||||
|
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||||
|
* @param comparison The comparison function to use.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||||
|
* zyan status code if an error occured.
|
||||||
|
*
|
||||||
|
* The `found_index` is set to `-1`, if the element was not found.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element,
|
||||||
|
ZyanISize* found_index, ZyanEqualityComparison comparison);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sequentially searches for the first occurrence of `element` in the given vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element A pointer to the element to search for.
|
||||||
|
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||||
|
* @param comparison The comparison function to use.
|
||||||
|
* @param index The start index.
|
||||||
|
* @param count The maximum number of elements to iterate, beginning from the start `index`.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||||
|
* zyan status code if an error occured.
|
||||||
|
*
|
||||||
|
* The `found_index` is set to `-1`, if the element was not found.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element,
|
||||||
|
ZyanISize* found_index, ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for the first occurrence of `element` in the given vector using a binary-
|
||||||
|
* search algorithm.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element A pointer to the element to search for.
|
||||||
|
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||||
|
* @param comparison The comparison function to use.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||||
|
* zyan status code if an error occured.
|
||||||
|
*
|
||||||
|
* If found, `found_index` contains the zero-based index of `element`. If not found, `found_index`
|
||||||
|
* contains the index of the first entry larger than `element`.
|
||||||
|
*
|
||||||
|
* This function requires all elements in the vector to be strictly ordered (sorted).
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element,
|
||||||
|
ZyanUSize* found_index, ZyanComparison comparison);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for the first occurrence of `element` in the given vector using a binary-
|
||||||
|
* search algorithm.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param element A pointer to the element to search for.
|
||||||
|
* @param found_index A pointer to a variable that receives the index of the found element.
|
||||||
|
* @param comparison The comparison function to use.
|
||||||
|
* @param index The start index.
|
||||||
|
* @param count The maximum number of elements to iterate, beginning from the start `index`.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic
|
||||||
|
* zyan status code if an error occured.
|
||||||
|
*
|
||||||
|
* If found, `found_index` contains the zero-based index of `element`. If not found, `found_index`
|
||||||
|
* contains the index of the first entry larger than `element`.
|
||||||
|
*
|
||||||
|
* This function requires all elements in the vector to be strictly ordered (sorted).
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element,
|
||||||
|
ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Memory management */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes the given `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param size The new size of the vector.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes the given `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param size The new size of the vector.
|
||||||
|
* @param initializer A pointer to a value to be used as initializer for new items.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size,
|
||||||
|
const void* initializer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the capacity of the given `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param capacity The new minimum capacity of the vector.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shrinks the capacity of the given vector to match it's size.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Information */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current capacity of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param capacity Receives the size of the vector.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current size of the vector.
|
||||||
|
*
|
||||||
|
* @param vector A pointer to the `ZyanVector` instance.
|
||||||
|
* @param size Receives the size of the vector.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_VECTOR_H */
|
@ -0,0 +1,111 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Core Library (Zycore-C)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Master include file, including everything else.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYCORE_H
|
||||||
|
#define ZYCORE_H
|
||||||
|
|
||||||
|
#include <ZycoreExportConfig.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Constants */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro that defines the zycore version.
|
||||||
|
*/
|
||||||
|
#define ZYCORE_VERSION (ZyanU64)0x0001000000000000
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Helper macros */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the major-part of the zycore version.
|
||||||
|
*
|
||||||
|
* @param version The zycore version value
|
||||||
|
*/
|
||||||
|
#define ZYCORE_VERSION_MAJOR(version_t) (ZyanU16)((version_t & 0xFFFF000000000000) >> 48)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the minor-part of the zycore version.
|
||||||
|
*
|
||||||
|
* @param version The zycore version value
|
||||||
|
*/
|
||||||
|
#define ZYCORE_VERSION_MINOR(version_t) (ZyanU16)((version_t & 0x0000FFFF00000000) >> 32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the patch-part of the zycore version.
|
||||||
|
*
|
||||||
|
* @param version The zycore version value
|
||||||
|
*/
|
||||||
|
#define ZYCORE_VERSION_PATCH(version_t) (ZyanU16)((version_t & 0x00000000FFFF0000) >> 16)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the build-part of the zycore version.
|
||||||
|
*
|
||||||
|
* @param version The zycore version value
|
||||||
|
*/
|
||||||
|
#define ZYCORE_VERSION_BUILD(version_t) (ZyanU16)(version_t & 0x000000000000FFFF)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the zycore version.
|
||||||
|
*
|
||||||
|
* @return The zycore version.
|
||||||
|
*
|
||||||
|
* Use the macros provided in this file to extract the major, minor, patch and build part from the
|
||||||
|
* returned version value.
|
||||||
|
*/
|
||||||
|
ZYCORE_EXPORT ZyanU64 ZycoreGetVersion(void);
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_H */
|
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
#ifndef ZYCORE_EXPORT_H
|
||||||
|
#define ZYCORE_EXPORT_H
|
||||||
|
|
||||||
|
#ifdef ZYCORE_STATIC_DEFINE
|
||||||
|
# define ZYCORE_EXPORT
|
||||||
|
# define ZYCORE_NO_EXPORT
|
||||||
|
#else
|
||||||
|
# ifndef ZYCORE_EXPORT
|
||||||
|
# ifdef Zycore_EXPORTS
|
||||||
|
/* We are building this library */
|
||||||
|
# define ZYCORE_EXPORT __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
/* We are using this library */
|
||||||
|
# define ZYCORE_EXPORT __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef ZYCORE_NO_EXPORT
|
||||||
|
# define ZYCORE_NO_EXPORT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYCORE_DEPRECATED
|
||||||
|
# define ZYCORE_DEPRECATED __declspec(deprecated)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYCORE_DEPRECATED_EXPORT
|
||||||
|
# define ZYCORE_DEPRECATED_EXPORT ZYCORE_EXPORT ZYCORE_DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYCORE_DEPRECATED_NO_EXPORT
|
||||||
|
# define ZYCORE_DEPRECATED_NO_EXPORT ZYCORE_NO_EXPORT ZYCORE_DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 /* DEFINE_NO_DEPRECATED */
|
||||||
|
# ifndef ZYCORE_NO_DEPRECATED
|
||||||
|
# define ZYCORE_NO_DEPRECATED
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYCORE_EXPORT_H */
|
@ -0,0 +1,237 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Functions for decoding instructions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DECODER_H
|
||||||
|
#define ZYDIS_DECODER_H
|
||||||
|
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zydis/DecoderTypes.h>
|
||||||
|
#include <Zydis/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Decoder mode */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisDecoderMode` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisDecoderMode_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Enables minimal instruction decoding without semantic analysis.
|
||||||
|
*
|
||||||
|
* This mode provides access to the mnemonic, the instruction-length, the effective
|
||||||
|
* operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`)
|
||||||
|
* and all of the information in the `raw` field of the `ZydisDecodedInstruction` struct.
|
||||||
|
*
|
||||||
|
* Operands, most attributes and other specific information (like `AVX` info) are not
|
||||||
|
* accessible in this mode.
|
||||||
|
*
|
||||||
|
* This mode is NOT enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_MINIMAL,
|
||||||
|
/**
|
||||||
|
* Enables the `AMD`-branch mode.
|
||||||
|
*
|
||||||
|
* Intel ignores the operand-size override-prefix (`0x66`) for all branches with 32-bit
|
||||||
|
* immediates and forces the operand-size of the instruction to 64-bit in 64-bit mode.
|
||||||
|
* In `AMD`-branch mode `0x66` is not ignored and changes the operand-size and the size of the
|
||||||
|
* immediate to 16-bit.
|
||||||
|
*
|
||||||
|
* This mode is NOT enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_AMD_BRANCHES,
|
||||||
|
/**
|
||||||
|
* Enables `KNC` compatibility-mode.
|
||||||
|
*
|
||||||
|
* `KNC` and `KNL+` chips are sharing opcodes and encodings for some mask-related instructions.
|
||||||
|
* Enable this mode to use the old `KNC` specifications (different mnemonics, operands, ..).
|
||||||
|
*
|
||||||
|
* This mode is NOT enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_KNC,
|
||||||
|
/**
|
||||||
|
* Enables the `MPX` mode.
|
||||||
|
*
|
||||||
|
* The `MPX` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||||
|
*
|
||||||
|
* This mode is enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_MPX,
|
||||||
|
/**
|
||||||
|
* Enables the `CET` mode.
|
||||||
|
*
|
||||||
|
* The `CET` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||||
|
*
|
||||||
|
* This mode is enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_CET,
|
||||||
|
/**
|
||||||
|
* Enables the `LZCNT` mode.
|
||||||
|
*
|
||||||
|
* The `LZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||||
|
*
|
||||||
|
* This mode is enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_LZCNT,
|
||||||
|
/**
|
||||||
|
* Enables the `TZCNT` mode.
|
||||||
|
*
|
||||||
|
* The `TZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||||
|
*
|
||||||
|
* This mode is enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_TZCNT,
|
||||||
|
/**
|
||||||
|
* Enables the `WBNOINVD` mode.
|
||||||
|
*
|
||||||
|
* The `WBINVD` instruction is interpreted as `WBNOINVD` on ICL chips, if a `F3` prefix is
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* This mode is disabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_WBNOINVD,
|
||||||
|
/**
|
||||||
|
* Enables the `CLDEMOTE` mode.
|
||||||
|
*
|
||||||
|
* The `CLDEMOTE` isa-extension reuses (overrides) some of the widenop instruction opcodes.
|
||||||
|
*
|
||||||
|
* This mode is enabled by default.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_CLDEMOTE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_MAX_VALUE = ZYDIS_DECODER_MODE_CLDEMOTE,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_DECODER_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECODER_MODE_MAX_VALUE)
|
||||||
|
} ZydisDecoderMode;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Decoder struct */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisDecoder` struct.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisDecoder_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The machine mode.
|
||||||
|
*/
|
||||||
|
ZydisMachineMode machine_mode;
|
||||||
|
/**
|
||||||
|
* The address width.
|
||||||
|
*/
|
||||||
|
ZydisAddressWidth address_width;
|
||||||
|
/**
|
||||||
|
* The decoder mode array.
|
||||||
|
*/
|
||||||
|
ZyanBool decoder_mode[ZYDIS_DECODER_MODE_MAX_VALUE + 1];
|
||||||
|
} ZydisDecoder;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup decoder Decoder
|
||||||
|
* Functions allowing decoding of instruction bytes to a machine interpretable struct.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the given `ZydisDecoder` instance.
|
||||||
|
*
|
||||||
|
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||||
|
* @param machine_mode The machine mode.
|
||||||
|
* @param address_width The address width.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
|
||||||
|
ZydisAddressWidth address_width);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables the specified decoder-mode.
|
||||||
|
*
|
||||||
|
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||||
|
* @param mode The decoder mode.
|
||||||
|
* @param enabled `ZYAN_TRUE` to enable, or `ZYAN_FALSE` to disable the specified decoder-mode.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode,
|
||||||
|
ZyanBool enabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the instruction in the given input `buffer`.
|
||||||
|
*
|
||||||
|
* @param decoder A pointer to the `ZydisDecoder` instance.
|
||||||
|
* @param buffer A pointer to the input buffer.
|
||||||
|
* @param length The length of the input buffer. Note that this can be bigger than the
|
||||||
|
* actual size of the instruction -- you don't have to know the size up
|
||||||
|
* front. This length is merely used to prevent Zydis from doing
|
||||||
|
* out-of-bounds reads on your buffer.
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct, that receives the
|
||||||
|
* details about the decoded instruction.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder,
|
||||||
|
const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_DECODER_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,306 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Implements the `ZydisFormatterToken` type and provides functions to use it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_FORMATTER_TOKEN_H
|
||||||
|
#define ZYDIS_FORMATTER_TOKEN_H
|
||||||
|
|
||||||
|
#include <ZydisExportConfig.h>
|
||||||
|
#include <Zycore/String.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
#include <Zydis/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Constants */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Token types */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @biref Defines the `ZydisTokenType` data-type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU8 ZydisTokenType;
|
||||||
|
|
||||||
|
#define ZYDIS_TOKEN_INVALID 0x00
|
||||||
|
/**
|
||||||
|
* A whitespace character.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_WHITESPACE 0x01
|
||||||
|
/**
|
||||||
|
* A delimiter character (like `','`, `':'`, `'+'`, `'-'`, `'*'`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_DELIMITER 0x02
|
||||||
|
/**
|
||||||
|
* An opening parenthesis character (like `'('`, `'['`, `'{'`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_PARENTHESIS_OPEN 0x03
|
||||||
|
/**
|
||||||
|
* A closing parenthesis character (like `')'`, `']'`, `'}'`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_PARENTHESIS_CLOSE 0x04
|
||||||
|
/**
|
||||||
|
* A prefix literal (like `"LOCK"`, `"REP"`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_PREFIX 0x05
|
||||||
|
/**
|
||||||
|
* A mnemonic literal (like `"MOV"`, `"VCMPPSD"`, `"LCALL"`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_MNEMONIC 0x06
|
||||||
|
/**
|
||||||
|
* A register literal (like `"RAX"`, `"DS"`, `"%ECX"`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_REGISTER 0x07
|
||||||
|
/**
|
||||||
|
* An absolute address literal (like `0x00400000`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_ADDRESS_ABS 0x08
|
||||||
|
/**
|
||||||
|
* A relative address literal (like `-0x100`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_ADDRESS_REL 0x09
|
||||||
|
/**
|
||||||
|
* A displacement literal (like `0xFFFFFFFF`, `-0x100`, `+0x1234`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_DISPLACEMENT 0x0A
|
||||||
|
/**
|
||||||
|
* An immediate literal (like `0xC0`, `-0x1234`, `$0x0000`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_IMMEDIATE 0x0B
|
||||||
|
/**
|
||||||
|
* A typecast literal (like `DWORD PTR`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_TYPECAST 0x0C
|
||||||
|
/**
|
||||||
|
* A decorator literal (like `"Z"`, `"1TO4"`).
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_DECORATOR 0x0D
|
||||||
|
/**
|
||||||
|
* A symbol literal.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_SYMBOL 0x0E
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base for user-defined token types.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_TOKEN_USER 0x80
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Token */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisFormatterToken` struct.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisFormatterToken_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The token type.
|
||||||
|
*/
|
||||||
|
ZydisTokenType type;
|
||||||
|
/**
|
||||||
|
* An offset to the next token, or `0`.
|
||||||
|
*/
|
||||||
|
ZyanU8 next;
|
||||||
|
} ZydisFormatterToken;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisFormatterTokenConst` data-type.
|
||||||
|
*/
|
||||||
|
typedef const ZydisFormatterToken ZydisFormatterTokenConst;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Buffer */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisFormatterBuffer` struct.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may
|
||||||
|
* lead to unexpected behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisFormatterBuffer_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* `ZYAN_TRUE`, if the buffer contains a token stream or `ZYAN_FALSE, if it
|
||||||
|
* contains a simple string.
|
||||||
|
*/
|
||||||
|
ZyanBool is_token_list;
|
||||||
|
/**
|
||||||
|
* The remaining capacity of the buffer.
|
||||||
|
*/
|
||||||
|
ZyanUSize capacity;
|
||||||
|
/**
|
||||||
|
* The `ZyanString` instance that refers to the literal value of the most
|
||||||
|
* recently added token.
|
||||||
|
*/
|
||||||
|
ZyanString string;
|
||||||
|
} ZydisFormatterBuffer;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Token */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the `type` and the string `value` of the given `token`.
|
||||||
|
*
|
||||||
|
* @param token A pointer to the `ZydisFormatterToken` struct.
|
||||||
|
* @param type Receives the token type.
|
||||||
|
* @param value Receives a pointer to the string value of the token.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token,
|
||||||
|
ZydisTokenType* type, ZyanConstCharPointer* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the next `token` linked to the passed one.
|
||||||
|
*
|
||||||
|
* @param token Receives a pointer to the next `ZydisFormatterToken` struct
|
||||||
|
* linked to the passed one.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Buffer */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current (most recently added) token.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param token Receives a pointer to the current token.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least
|
||||||
|
* one token.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer,
|
||||||
|
ZydisFormatterTokenConst** token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the `ZyanString` instance associated with the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param string Receives a pointer to the `ZyanString` instance associated with the given
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least
|
||||||
|
* one token.
|
||||||
|
*
|
||||||
|
* The returned string always refers to the literal value of the current (most recently added)
|
||||||
|
* token and will remain valid until the buffer is destroyed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer,
|
||||||
|
ZyanString** string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a new token to the `buffer`.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param type The type of the new token.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will
|
||||||
|
* automatically be updated by calling this function.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer,
|
||||||
|
ZydisTokenType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a snapshot of the buffer-state.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param state Receives a snapshot of the buffer-state.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* Note that the buffer-state is saved inside the buffer itself and thus becomes invalid as soon
|
||||||
|
* as the buffer gets overwritten or destroyed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer,
|
||||||
|
ZyanUPointer* state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores a previously saved buffer-state.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param state The buffer-state to restore.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* All tokens added after obtaining the given `state` snapshot will be removed. This function
|
||||||
|
* does NOT restore any string content.
|
||||||
|
*
|
||||||
|
* Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will
|
||||||
|
* automatically be updated by calling this function.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer,
|
||||||
|
ZyanUPointer state);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_FORMATTER_TOKEN_H */
|
@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* Defines the `ZydisISAExt` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisISAExt_
|
||||||
|
{
|
||||||
|
ZYDIS_ISA_EXT_INVALID,
|
||||||
|
ZYDIS_ISA_EXT_ADOX_ADCX,
|
||||||
|
ZYDIS_ISA_EXT_AES,
|
||||||
|
ZYDIS_ISA_EXT_AMD3DNOW,
|
||||||
|
ZYDIS_ISA_EXT_AMD3DNOW_PREFETCH,
|
||||||
|
ZYDIS_ISA_EXT_AMD_INVLPGB,
|
||||||
|
ZYDIS_ISA_EXT_AMX_BF16,
|
||||||
|
ZYDIS_ISA_EXT_AMX_INT8,
|
||||||
|
ZYDIS_ISA_EXT_AMX_TILE,
|
||||||
|
ZYDIS_ISA_EXT_AVX,
|
||||||
|
ZYDIS_ISA_EXT_AVX2,
|
||||||
|
ZYDIS_ISA_EXT_AVX2GATHER,
|
||||||
|
ZYDIS_ISA_EXT_AVX512EVEX,
|
||||||
|
ZYDIS_ISA_EXT_AVX512VEX,
|
||||||
|
ZYDIS_ISA_EXT_AVXAES,
|
||||||
|
ZYDIS_ISA_EXT_BASE,
|
||||||
|
ZYDIS_ISA_EXT_BMI1,
|
||||||
|
ZYDIS_ISA_EXT_BMI2,
|
||||||
|
ZYDIS_ISA_EXT_CET,
|
||||||
|
ZYDIS_ISA_EXT_CLDEMOTE,
|
||||||
|
ZYDIS_ISA_EXT_CLFLUSHOPT,
|
||||||
|
ZYDIS_ISA_EXT_CLFSH,
|
||||||
|
ZYDIS_ISA_EXT_CLWB,
|
||||||
|
ZYDIS_ISA_EXT_CLZERO,
|
||||||
|
ZYDIS_ISA_EXT_ENQCMD,
|
||||||
|
ZYDIS_ISA_EXT_F16C,
|
||||||
|
ZYDIS_ISA_EXT_FMA,
|
||||||
|
ZYDIS_ISA_EXT_FMA4,
|
||||||
|
ZYDIS_ISA_EXT_GFNI,
|
||||||
|
ZYDIS_ISA_EXT_INVPCID,
|
||||||
|
ZYDIS_ISA_EXT_KNC,
|
||||||
|
ZYDIS_ISA_EXT_KNCE,
|
||||||
|
ZYDIS_ISA_EXT_KNCV,
|
||||||
|
ZYDIS_ISA_EXT_LONGMODE,
|
||||||
|
ZYDIS_ISA_EXT_LZCNT,
|
||||||
|
ZYDIS_ISA_EXT_MCOMMIT,
|
||||||
|
ZYDIS_ISA_EXT_MMX,
|
||||||
|
ZYDIS_ISA_EXT_MONITOR,
|
||||||
|
ZYDIS_ISA_EXT_MONITORX,
|
||||||
|
ZYDIS_ISA_EXT_MOVBE,
|
||||||
|
ZYDIS_ISA_EXT_MOVDIR,
|
||||||
|
ZYDIS_ISA_EXT_MPX,
|
||||||
|
ZYDIS_ISA_EXT_PADLOCK,
|
||||||
|
ZYDIS_ISA_EXT_PAUSE,
|
||||||
|
ZYDIS_ISA_EXT_PCLMULQDQ,
|
||||||
|
ZYDIS_ISA_EXT_PCONFIG,
|
||||||
|
ZYDIS_ISA_EXT_PKU,
|
||||||
|
ZYDIS_ISA_EXT_PREFETCHWT1,
|
||||||
|
ZYDIS_ISA_EXT_PT,
|
||||||
|
ZYDIS_ISA_EXT_RDPID,
|
||||||
|
ZYDIS_ISA_EXT_RDPRU,
|
||||||
|
ZYDIS_ISA_EXT_RDRAND,
|
||||||
|
ZYDIS_ISA_EXT_RDSEED,
|
||||||
|
ZYDIS_ISA_EXT_RDTSCP,
|
||||||
|
ZYDIS_ISA_EXT_RDWRFSGS,
|
||||||
|
ZYDIS_ISA_EXT_RTM,
|
||||||
|
ZYDIS_ISA_EXT_SERIALIZE,
|
||||||
|
ZYDIS_ISA_EXT_SGX,
|
||||||
|
ZYDIS_ISA_EXT_SGX_ENCLV,
|
||||||
|
ZYDIS_ISA_EXT_SHA,
|
||||||
|
ZYDIS_ISA_EXT_SMAP,
|
||||||
|
ZYDIS_ISA_EXT_SMX,
|
||||||
|
ZYDIS_ISA_EXT_SNP,
|
||||||
|
ZYDIS_ISA_EXT_SSE,
|
||||||
|
ZYDIS_ISA_EXT_SSE2,
|
||||||
|
ZYDIS_ISA_EXT_SSE3,
|
||||||
|
ZYDIS_ISA_EXT_SSE4,
|
||||||
|
ZYDIS_ISA_EXT_SSE4A,
|
||||||
|
ZYDIS_ISA_EXT_SSSE3,
|
||||||
|
ZYDIS_ISA_EXT_SVM,
|
||||||
|
ZYDIS_ISA_EXT_TBM,
|
||||||
|
ZYDIS_ISA_EXT_TSX_LDTRK,
|
||||||
|
ZYDIS_ISA_EXT_VAES,
|
||||||
|
ZYDIS_ISA_EXT_VMFUNC,
|
||||||
|
ZYDIS_ISA_EXT_VPCLMULQDQ,
|
||||||
|
ZYDIS_ISA_EXT_VTX,
|
||||||
|
ZYDIS_ISA_EXT_WAITPKG,
|
||||||
|
ZYDIS_ISA_EXT_X87,
|
||||||
|
ZYDIS_ISA_EXT_XOP,
|
||||||
|
ZYDIS_ISA_EXT_XSAVE,
|
||||||
|
ZYDIS_ISA_EXT_XSAVEC,
|
||||||
|
ZYDIS_ISA_EXT_XSAVEOPT,
|
||||||
|
ZYDIS_ISA_EXT_XSAVES,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ISA_EXT_MAX_VALUE = ZYDIS_ISA_EXT_XSAVES,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ISA_EXT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_EXT_MAX_VALUE)
|
||||||
|
} ZydisISAExt;
|
@ -0,0 +1,184 @@
|
|||||||
|
/**
|
||||||
|
* Defines the `ZydisISASet` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisISASet_
|
||||||
|
{
|
||||||
|
ZYDIS_ISA_SET_INVALID,
|
||||||
|
ZYDIS_ISA_SET_ADOX_ADCX,
|
||||||
|
ZYDIS_ISA_SET_AES,
|
||||||
|
ZYDIS_ISA_SET_AMD,
|
||||||
|
ZYDIS_ISA_SET_AMD3DNOW,
|
||||||
|
ZYDIS_ISA_SET_AMX_BF16,
|
||||||
|
ZYDIS_ISA_SET_AMX_INT8,
|
||||||
|
ZYDIS_ISA_SET_AMX_TILE,
|
||||||
|
ZYDIS_ISA_SET_AVX,
|
||||||
|
ZYDIS_ISA_SET_AVX2,
|
||||||
|
ZYDIS_ISA_SET_AVX2GATHER,
|
||||||
|
ZYDIS_ISA_SET_AVX512BW_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512BW_128N,
|
||||||
|
ZYDIS_ISA_SET_AVX512BW_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512BW_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512BW_KOP,
|
||||||
|
ZYDIS_ISA_SET_AVX512CD_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512CD_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512CD_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512DQ_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512DQ_128N,
|
||||||
|
ZYDIS_ISA_SET_AVX512DQ_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512DQ_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512DQ_KOP,
|
||||||
|
ZYDIS_ISA_SET_AVX512DQ_SCALAR,
|
||||||
|
ZYDIS_ISA_SET_AVX512ER_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512ER_SCALAR,
|
||||||
|
ZYDIS_ISA_SET_AVX512F_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512F_128N,
|
||||||
|
ZYDIS_ISA_SET_AVX512F_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512F_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512F_KOP,
|
||||||
|
ZYDIS_ISA_SET_AVX512F_SCALAR,
|
||||||
|
ZYDIS_ISA_SET_AVX512PF_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_4FMAPS_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_4FMAPS_SCALAR,
|
||||||
|
ZYDIS_ISA_SET_AVX512_4VNNIW_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_BF16_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_BF16_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_BF16_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_BITALG_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_BITALG_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_BITALG_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_GFNI_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_GFNI_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_GFNI_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_IFMA_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_IFMA_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_IFMA_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VAES_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VAES_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VAES_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VBMI2_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VBMI2_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VBMI2_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VBMI_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VBMI_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VBMI_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VNNI_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VNNI_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VNNI_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VP2INTERSECT_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_512,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_128,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_256,
|
||||||
|
ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_512,
|
||||||
|
ZYDIS_ISA_SET_AVXAES,
|
||||||
|
ZYDIS_ISA_SET_AVX_GFNI,
|
||||||
|
ZYDIS_ISA_SET_BMI1,
|
||||||
|
ZYDIS_ISA_SET_BMI2,
|
||||||
|
ZYDIS_ISA_SET_CET,
|
||||||
|
ZYDIS_ISA_SET_CLDEMOTE,
|
||||||
|
ZYDIS_ISA_SET_CLFLUSHOPT,
|
||||||
|
ZYDIS_ISA_SET_CLFSH,
|
||||||
|
ZYDIS_ISA_SET_CLWB,
|
||||||
|
ZYDIS_ISA_SET_CLZERO,
|
||||||
|
ZYDIS_ISA_SET_CMOV,
|
||||||
|
ZYDIS_ISA_SET_CMPXCHG16B,
|
||||||
|
ZYDIS_ISA_SET_ENQCMD,
|
||||||
|
ZYDIS_ISA_SET_F16C,
|
||||||
|
ZYDIS_ISA_SET_FAT_NOP,
|
||||||
|
ZYDIS_ISA_SET_FCMOV,
|
||||||
|
ZYDIS_ISA_SET_FMA,
|
||||||
|
ZYDIS_ISA_SET_FMA4,
|
||||||
|
ZYDIS_ISA_SET_FXSAVE,
|
||||||
|
ZYDIS_ISA_SET_FXSAVE64,
|
||||||
|
ZYDIS_ISA_SET_GFNI,
|
||||||
|
ZYDIS_ISA_SET_I186,
|
||||||
|
ZYDIS_ISA_SET_I286PROTECTED,
|
||||||
|
ZYDIS_ISA_SET_I286REAL,
|
||||||
|
ZYDIS_ISA_SET_I386,
|
||||||
|
ZYDIS_ISA_SET_I486,
|
||||||
|
ZYDIS_ISA_SET_I486REAL,
|
||||||
|
ZYDIS_ISA_SET_I86,
|
||||||
|
ZYDIS_ISA_SET_INVPCID,
|
||||||
|
ZYDIS_ISA_SET_KNCE,
|
||||||
|
ZYDIS_ISA_SET_KNCJKBR,
|
||||||
|
ZYDIS_ISA_SET_KNCSTREAM,
|
||||||
|
ZYDIS_ISA_SET_KNCV,
|
||||||
|
ZYDIS_ISA_SET_KNC_MISC,
|
||||||
|
ZYDIS_ISA_SET_KNC_PF_HINT,
|
||||||
|
ZYDIS_ISA_SET_LAHF,
|
||||||
|
ZYDIS_ISA_SET_LONGMODE,
|
||||||
|
ZYDIS_ISA_SET_LZCNT,
|
||||||
|
ZYDIS_ISA_SET_MCOMMIT,
|
||||||
|
ZYDIS_ISA_SET_MONITOR,
|
||||||
|
ZYDIS_ISA_SET_MONITORX,
|
||||||
|
ZYDIS_ISA_SET_MOVBE,
|
||||||
|
ZYDIS_ISA_SET_MOVDIR,
|
||||||
|
ZYDIS_ISA_SET_MPX,
|
||||||
|
ZYDIS_ISA_SET_PADLOCK_ACE,
|
||||||
|
ZYDIS_ISA_SET_PADLOCK_PHE,
|
||||||
|
ZYDIS_ISA_SET_PADLOCK_PMM,
|
||||||
|
ZYDIS_ISA_SET_PADLOCK_RNG,
|
||||||
|
ZYDIS_ISA_SET_PAUSE,
|
||||||
|
ZYDIS_ISA_SET_PCLMULQDQ,
|
||||||
|
ZYDIS_ISA_SET_PCONFIG,
|
||||||
|
ZYDIS_ISA_SET_PENTIUMMMX,
|
||||||
|
ZYDIS_ISA_SET_PENTIUMREAL,
|
||||||
|
ZYDIS_ISA_SET_PKU,
|
||||||
|
ZYDIS_ISA_SET_POPCNT,
|
||||||
|
ZYDIS_ISA_SET_PPRO,
|
||||||
|
ZYDIS_ISA_SET_PREFETCHWT1,
|
||||||
|
ZYDIS_ISA_SET_PREFETCH_NOP,
|
||||||
|
ZYDIS_ISA_SET_PT,
|
||||||
|
ZYDIS_ISA_SET_RDPID,
|
||||||
|
ZYDIS_ISA_SET_RDPMC,
|
||||||
|
ZYDIS_ISA_SET_RDPRU,
|
||||||
|
ZYDIS_ISA_SET_RDRAND,
|
||||||
|
ZYDIS_ISA_SET_RDSEED,
|
||||||
|
ZYDIS_ISA_SET_RDTSCP,
|
||||||
|
ZYDIS_ISA_SET_RDWRFSGS,
|
||||||
|
ZYDIS_ISA_SET_RTM,
|
||||||
|
ZYDIS_ISA_SET_SERIALIZE,
|
||||||
|
ZYDIS_ISA_SET_SGX,
|
||||||
|
ZYDIS_ISA_SET_SGX_ENCLV,
|
||||||
|
ZYDIS_ISA_SET_SHA,
|
||||||
|
ZYDIS_ISA_SET_SMAP,
|
||||||
|
ZYDIS_ISA_SET_SMX,
|
||||||
|
ZYDIS_ISA_SET_SSE,
|
||||||
|
ZYDIS_ISA_SET_SSE2,
|
||||||
|
ZYDIS_ISA_SET_SSE2MMX,
|
||||||
|
ZYDIS_ISA_SET_SSE3,
|
||||||
|
ZYDIS_ISA_SET_SSE3X87,
|
||||||
|
ZYDIS_ISA_SET_SSE4,
|
||||||
|
ZYDIS_ISA_SET_SSE42,
|
||||||
|
ZYDIS_ISA_SET_SSE4A,
|
||||||
|
ZYDIS_ISA_SET_SSEMXCSR,
|
||||||
|
ZYDIS_ISA_SET_SSE_PREFETCH,
|
||||||
|
ZYDIS_ISA_SET_SSSE3,
|
||||||
|
ZYDIS_ISA_SET_SSSE3MMX,
|
||||||
|
ZYDIS_ISA_SET_SVM,
|
||||||
|
ZYDIS_ISA_SET_TBM,
|
||||||
|
ZYDIS_ISA_SET_TSX_LDTRK,
|
||||||
|
ZYDIS_ISA_SET_VAES,
|
||||||
|
ZYDIS_ISA_SET_VMFUNC,
|
||||||
|
ZYDIS_ISA_SET_VPCLMULQDQ,
|
||||||
|
ZYDIS_ISA_SET_VTX,
|
||||||
|
ZYDIS_ISA_SET_WAITPKG,
|
||||||
|
ZYDIS_ISA_SET_X87,
|
||||||
|
ZYDIS_ISA_SET_XOP,
|
||||||
|
ZYDIS_ISA_SET_XSAVE,
|
||||||
|
ZYDIS_ISA_SET_XSAVEC,
|
||||||
|
ZYDIS_ISA_SET_XSAVEOPT,
|
||||||
|
ZYDIS_ISA_SET_XSAVES,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ISA_SET_MAX_VALUE = ZYDIS_ISA_SET_XSAVES,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ISA_SET_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_SET_MAX_VALUE)
|
||||||
|
} ZydisISASet;
|
@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionCategory` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisInstructionCategory_
|
||||||
|
{
|
||||||
|
ZYDIS_CATEGORY_INVALID,
|
||||||
|
ZYDIS_CATEGORY_ADOX_ADCX,
|
||||||
|
ZYDIS_CATEGORY_AES,
|
||||||
|
ZYDIS_CATEGORY_AMD3DNOW,
|
||||||
|
ZYDIS_CATEGORY_AMX_TILE,
|
||||||
|
ZYDIS_CATEGORY_AVX,
|
||||||
|
ZYDIS_CATEGORY_AVX2,
|
||||||
|
ZYDIS_CATEGORY_AVX2GATHER,
|
||||||
|
ZYDIS_CATEGORY_AVX512,
|
||||||
|
ZYDIS_CATEGORY_AVX512_4FMAPS,
|
||||||
|
ZYDIS_CATEGORY_AVX512_4VNNIW,
|
||||||
|
ZYDIS_CATEGORY_AVX512_BITALG,
|
||||||
|
ZYDIS_CATEGORY_AVX512_VBMI,
|
||||||
|
ZYDIS_CATEGORY_AVX512_VP2INTERSECT,
|
||||||
|
ZYDIS_CATEGORY_BINARY,
|
||||||
|
ZYDIS_CATEGORY_BITBYTE,
|
||||||
|
ZYDIS_CATEGORY_BLEND,
|
||||||
|
ZYDIS_CATEGORY_BMI1,
|
||||||
|
ZYDIS_CATEGORY_BMI2,
|
||||||
|
ZYDIS_CATEGORY_BROADCAST,
|
||||||
|
ZYDIS_CATEGORY_CALL,
|
||||||
|
ZYDIS_CATEGORY_CET,
|
||||||
|
ZYDIS_CATEGORY_CLDEMOTE,
|
||||||
|
ZYDIS_CATEGORY_CLFLUSHOPT,
|
||||||
|
ZYDIS_CATEGORY_CLWB,
|
||||||
|
ZYDIS_CATEGORY_CLZERO,
|
||||||
|
ZYDIS_CATEGORY_CMOV,
|
||||||
|
ZYDIS_CATEGORY_COMPRESS,
|
||||||
|
ZYDIS_CATEGORY_COND_BR,
|
||||||
|
ZYDIS_CATEGORY_CONFLICT,
|
||||||
|
ZYDIS_CATEGORY_CONVERT,
|
||||||
|
ZYDIS_CATEGORY_DATAXFER,
|
||||||
|
ZYDIS_CATEGORY_DECIMAL,
|
||||||
|
ZYDIS_CATEGORY_ENQCMD,
|
||||||
|
ZYDIS_CATEGORY_EXPAND,
|
||||||
|
ZYDIS_CATEGORY_FCMOV,
|
||||||
|
ZYDIS_CATEGORY_FLAGOP,
|
||||||
|
ZYDIS_CATEGORY_FMA4,
|
||||||
|
ZYDIS_CATEGORY_GATHER,
|
||||||
|
ZYDIS_CATEGORY_GFNI,
|
||||||
|
ZYDIS_CATEGORY_IFMA,
|
||||||
|
ZYDIS_CATEGORY_INTERRUPT,
|
||||||
|
ZYDIS_CATEGORY_IO,
|
||||||
|
ZYDIS_CATEGORY_IOSTRINGOP,
|
||||||
|
ZYDIS_CATEGORY_KMASK,
|
||||||
|
ZYDIS_CATEGORY_KNC,
|
||||||
|
ZYDIS_CATEGORY_KNCMASK,
|
||||||
|
ZYDIS_CATEGORY_KNCSCALAR,
|
||||||
|
ZYDIS_CATEGORY_LOGICAL,
|
||||||
|
ZYDIS_CATEGORY_LOGICAL_FP,
|
||||||
|
ZYDIS_CATEGORY_LZCNT,
|
||||||
|
ZYDIS_CATEGORY_MISC,
|
||||||
|
ZYDIS_CATEGORY_MMX,
|
||||||
|
ZYDIS_CATEGORY_MOVDIR,
|
||||||
|
ZYDIS_CATEGORY_MPX,
|
||||||
|
ZYDIS_CATEGORY_NOP,
|
||||||
|
ZYDIS_CATEGORY_PADLOCK,
|
||||||
|
ZYDIS_CATEGORY_PCLMULQDQ,
|
||||||
|
ZYDIS_CATEGORY_PCONFIG,
|
||||||
|
ZYDIS_CATEGORY_PKU,
|
||||||
|
ZYDIS_CATEGORY_POP,
|
||||||
|
ZYDIS_CATEGORY_PREFETCH,
|
||||||
|
ZYDIS_CATEGORY_PREFETCHWT1,
|
||||||
|
ZYDIS_CATEGORY_PT,
|
||||||
|
ZYDIS_CATEGORY_PUSH,
|
||||||
|
ZYDIS_CATEGORY_RDPID,
|
||||||
|
ZYDIS_CATEGORY_RDPRU,
|
||||||
|
ZYDIS_CATEGORY_RDRAND,
|
||||||
|
ZYDIS_CATEGORY_RDSEED,
|
||||||
|
ZYDIS_CATEGORY_RDWRFSGS,
|
||||||
|
ZYDIS_CATEGORY_RET,
|
||||||
|
ZYDIS_CATEGORY_ROTATE,
|
||||||
|
ZYDIS_CATEGORY_SCATTER,
|
||||||
|
ZYDIS_CATEGORY_SEGOP,
|
||||||
|
ZYDIS_CATEGORY_SEMAPHORE,
|
||||||
|
ZYDIS_CATEGORY_SERIALIZE,
|
||||||
|
ZYDIS_CATEGORY_SETCC,
|
||||||
|
ZYDIS_CATEGORY_SGX,
|
||||||
|
ZYDIS_CATEGORY_SHA,
|
||||||
|
ZYDIS_CATEGORY_SHIFT,
|
||||||
|
ZYDIS_CATEGORY_SMAP,
|
||||||
|
ZYDIS_CATEGORY_SSE,
|
||||||
|
ZYDIS_CATEGORY_STRINGOP,
|
||||||
|
ZYDIS_CATEGORY_STTNI,
|
||||||
|
ZYDIS_CATEGORY_SYSCALL,
|
||||||
|
ZYDIS_CATEGORY_SYSRET,
|
||||||
|
ZYDIS_CATEGORY_SYSTEM,
|
||||||
|
ZYDIS_CATEGORY_TBM,
|
||||||
|
ZYDIS_CATEGORY_TSX_LDTRK,
|
||||||
|
ZYDIS_CATEGORY_UFMA,
|
||||||
|
ZYDIS_CATEGORY_UNCOND_BR,
|
||||||
|
ZYDIS_CATEGORY_VAES,
|
||||||
|
ZYDIS_CATEGORY_VBMI2,
|
||||||
|
ZYDIS_CATEGORY_VFMA,
|
||||||
|
ZYDIS_CATEGORY_VPCLMULQDQ,
|
||||||
|
ZYDIS_CATEGORY_VTX,
|
||||||
|
ZYDIS_CATEGORY_WAITPKG,
|
||||||
|
ZYDIS_CATEGORY_WIDENOP,
|
||||||
|
ZYDIS_CATEGORY_X87_ALU,
|
||||||
|
ZYDIS_CATEGORY_XOP,
|
||||||
|
ZYDIS_CATEGORY_XSAVE,
|
||||||
|
ZYDIS_CATEGORY_XSAVEOPT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_CATEGORY_MAX_VALUE = ZYDIS_CATEGORY_XSAVEOPT,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_CATEGORY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CATEGORY_MAX_VALUE)
|
||||||
|
} ZydisInstructionCategory;
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,301 @@
|
|||||||
|
/**
|
||||||
|
* Defines the `ZydisRegister` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisRegister_
|
||||||
|
{
|
||||||
|
ZYDIS_REGISTER_NONE,
|
||||||
|
|
||||||
|
// General purpose registers 8-bit
|
||||||
|
ZYDIS_REGISTER_AL,
|
||||||
|
ZYDIS_REGISTER_CL,
|
||||||
|
ZYDIS_REGISTER_DL,
|
||||||
|
ZYDIS_REGISTER_BL,
|
||||||
|
ZYDIS_REGISTER_AH,
|
||||||
|
ZYDIS_REGISTER_CH,
|
||||||
|
ZYDIS_REGISTER_DH,
|
||||||
|
ZYDIS_REGISTER_BH,
|
||||||
|
ZYDIS_REGISTER_SPL,
|
||||||
|
ZYDIS_REGISTER_BPL,
|
||||||
|
ZYDIS_REGISTER_SIL,
|
||||||
|
ZYDIS_REGISTER_DIL,
|
||||||
|
ZYDIS_REGISTER_R8B,
|
||||||
|
ZYDIS_REGISTER_R9B,
|
||||||
|
ZYDIS_REGISTER_R10B,
|
||||||
|
ZYDIS_REGISTER_R11B,
|
||||||
|
ZYDIS_REGISTER_R12B,
|
||||||
|
ZYDIS_REGISTER_R13B,
|
||||||
|
ZYDIS_REGISTER_R14B,
|
||||||
|
ZYDIS_REGISTER_R15B,
|
||||||
|
// General purpose registers 16-bit
|
||||||
|
ZYDIS_REGISTER_AX,
|
||||||
|
ZYDIS_REGISTER_CX,
|
||||||
|
ZYDIS_REGISTER_DX,
|
||||||
|
ZYDIS_REGISTER_BX,
|
||||||
|
ZYDIS_REGISTER_SP,
|
||||||
|
ZYDIS_REGISTER_BP,
|
||||||
|
ZYDIS_REGISTER_SI,
|
||||||
|
ZYDIS_REGISTER_DI,
|
||||||
|
ZYDIS_REGISTER_R8W,
|
||||||
|
ZYDIS_REGISTER_R9W,
|
||||||
|
ZYDIS_REGISTER_R10W,
|
||||||
|
ZYDIS_REGISTER_R11W,
|
||||||
|
ZYDIS_REGISTER_R12W,
|
||||||
|
ZYDIS_REGISTER_R13W,
|
||||||
|
ZYDIS_REGISTER_R14W,
|
||||||
|
ZYDIS_REGISTER_R15W,
|
||||||
|
// General purpose registers 32-bit
|
||||||
|
ZYDIS_REGISTER_EAX,
|
||||||
|
ZYDIS_REGISTER_ECX,
|
||||||
|
ZYDIS_REGISTER_EDX,
|
||||||
|
ZYDIS_REGISTER_EBX,
|
||||||
|
ZYDIS_REGISTER_ESP,
|
||||||
|
ZYDIS_REGISTER_EBP,
|
||||||
|
ZYDIS_REGISTER_ESI,
|
||||||
|
ZYDIS_REGISTER_EDI,
|
||||||
|
ZYDIS_REGISTER_R8D,
|
||||||
|
ZYDIS_REGISTER_R9D,
|
||||||
|
ZYDIS_REGISTER_R10D,
|
||||||
|
ZYDIS_REGISTER_R11D,
|
||||||
|
ZYDIS_REGISTER_R12D,
|
||||||
|
ZYDIS_REGISTER_R13D,
|
||||||
|
ZYDIS_REGISTER_R14D,
|
||||||
|
ZYDIS_REGISTER_R15D,
|
||||||
|
// General purpose registers 64-bit
|
||||||
|
ZYDIS_REGISTER_RAX,
|
||||||
|
ZYDIS_REGISTER_RCX,
|
||||||
|
ZYDIS_REGISTER_RDX,
|
||||||
|
ZYDIS_REGISTER_RBX,
|
||||||
|
ZYDIS_REGISTER_RSP,
|
||||||
|
ZYDIS_REGISTER_RBP,
|
||||||
|
ZYDIS_REGISTER_RSI,
|
||||||
|
ZYDIS_REGISTER_RDI,
|
||||||
|
ZYDIS_REGISTER_R8,
|
||||||
|
ZYDIS_REGISTER_R9,
|
||||||
|
ZYDIS_REGISTER_R10,
|
||||||
|
ZYDIS_REGISTER_R11,
|
||||||
|
ZYDIS_REGISTER_R12,
|
||||||
|
ZYDIS_REGISTER_R13,
|
||||||
|
ZYDIS_REGISTER_R14,
|
||||||
|
ZYDIS_REGISTER_R15,
|
||||||
|
// Floating point legacy registers
|
||||||
|
ZYDIS_REGISTER_ST0,
|
||||||
|
ZYDIS_REGISTER_ST1,
|
||||||
|
ZYDIS_REGISTER_ST2,
|
||||||
|
ZYDIS_REGISTER_ST3,
|
||||||
|
ZYDIS_REGISTER_ST4,
|
||||||
|
ZYDIS_REGISTER_ST5,
|
||||||
|
ZYDIS_REGISTER_ST6,
|
||||||
|
ZYDIS_REGISTER_ST7,
|
||||||
|
ZYDIS_REGISTER_X87CONTROL,
|
||||||
|
ZYDIS_REGISTER_X87STATUS,
|
||||||
|
ZYDIS_REGISTER_X87TAG,
|
||||||
|
// Floating point multimedia registers
|
||||||
|
ZYDIS_REGISTER_MM0,
|
||||||
|
ZYDIS_REGISTER_MM1,
|
||||||
|
ZYDIS_REGISTER_MM2,
|
||||||
|
ZYDIS_REGISTER_MM3,
|
||||||
|
ZYDIS_REGISTER_MM4,
|
||||||
|
ZYDIS_REGISTER_MM5,
|
||||||
|
ZYDIS_REGISTER_MM6,
|
||||||
|
ZYDIS_REGISTER_MM7,
|
||||||
|
// Floating point vector registers 128-bit
|
||||||
|
ZYDIS_REGISTER_XMM0,
|
||||||
|
ZYDIS_REGISTER_XMM1,
|
||||||
|
ZYDIS_REGISTER_XMM2,
|
||||||
|
ZYDIS_REGISTER_XMM3,
|
||||||
|
ZYDIS_REGISTER_XMM4,
|
||||||
|
ZYDIS_REGISTER_XMM5,
|
||||||
|
ZYDIS_REGISTER_XMM6,
|
||||||
|
ZYDIS_REGISTER_XMM7,
|
||||||
|
ZYDIS_REGISTER_XMM8,
|
||||||
|
ZYDIS_REGISTER_XMM9,
|
||||||
|
ZYDIS_REGISTER_XMM10,
|
||||||
|
ZYDIS_REGISTER_XMM11,
|
||||||
|
ZYDIS_REGISTER_XMM12,
|
||||||
|
ZYDIS_REGISTER_XMM13,
|
||||||
|
ZYDIS_REGISTER_XMM14,
|
||||||
|
ZYDIS_REGISTER_XMM15,
|
||||||
|
ZYDIS_REGISTER_XMM16,
|
||||||
|
ZYDIS_REGISTER_XMM17,
|
||||||
|
ZYDIS_REGISTER_XMM18,
|
||||||
|
ZYDIS_REGISTER_XMM19,
|
||||||
|
ZYDIS_REGISTER_XMM20,
|
||||||
|
ZYDIS_REGISTER_XMM21,
|
||||||
|
ZYDIS_REGISTER_XMM22,
|
||||||
|
ZYDIS_REGISTER_XMM23,
|
||||||
|
ZYDIS_REGISTER_XMM24,
|
||||||
|
ZYDIS_REGISTER_XMM25,
|
||||||
|
ZYDIS_REGISTER_XMM26,
|
||||||
|
ZYDIS_REGISTER_XMM27,
|
||||||
|
ZYDIS_REGISTER_XMM28,
|
||||||
|
ZYDIS_REGISTER_XMM29,
|
||||||
|
ZYDIS_REGISTER_XMM30,
|
||||||
|
ZYDIS_REGISTER_XMM31,
|
||||||
|
// Floating point vector registers 256-bit
|
||||||
|
ZYDIS_REGISTER_YMM0,
|
||||||
|
ZYDIS_REGISTER_YMM1,
|
||||||
|
ZYDIS_REGISTER_YMM2,
|
||||||
|
ZYDIS_REGISTER_YMM3,
|
||||||
|
ZYDIS_REGISTER_YMM4,
|
||||||
|
ZYDIS_REGISTER_YMM5,
|
||||||
|
ZYDIS_REGISTER_YMM6,
|
||||||
|
ZYDIS_REGISTER_YMM7,
|
||||||
|
ZYDIS_REGISTER_YMM8,
|
||||||
|
ZYDIS_REGISTER_YMM9,
|
||||||
|
ZYDIS_REGISTER_YMM10,
|
||||||
|
ZYDIS_REGISTER_YMM11,
|
||||||
|
ZYDIS_REGISTER_YMM12,
|
||||||
|
ZYDIS_REGISTER_YMM13,
|
||||||
|
ZYDIS_REGISTER_YMM14,
|
||||||
|
ZYDIS_REGISTER_YMM15,
|
||||||
|
ZYDIS_REGISTER_YMM16,
|
||||||
|
ZYDIS_REGISTER_YMM17,
|
||||||
|
ZYDIS_REGISTER_YMM18,
|
||||||
|
ZYDIS_REGISTER_YMM19,
|
||||||
|
ZYDIS_REGISTER_YMM20,
|
||||||
|
ZYDIS_REGISTER_YMM21,
|
||||||
|
ZYDIS_REGISTER_YMM22,
|
||||||
|
ZYDIS_REGISTER_YMM23,
|
||||||
|
ZYDIS_REGISTER_YMM24,
|
||||||
|
ZYDIS_REGISTER_YMM25,
|
||||||
|
ZYDIS_REGISTER_YMM26,
|
||||||
|
ZYDIS_REGISTER_YMM27,
|
||||||
|
ZYDIS_REGISTER_YMM28,
|
||||||
|
ZYDIS_REGISTER_YMM29,
|
||||||
|
ZYDIS_REGISTER_YMM30,
|
||||||
|
ZYDIS_REGISTER_YMM31,
|
||||||
|
// Floating point vector registers 512-bit
|
||||||
|
ZYDIS_REGISTER_ZMM0,
|
||||||
|
ZYDIS_REGISTER_ZMM1,
|
||||||
|
ZYDIS_REGISTER_ZMM2,
|
||||||
|
ZYDIS_REGISTER_ZMM3,
|
||||||
|
ZYDIS_REGISTER_ZMM4,
|
||||||
|
ZYDIS_REGISTER_ZMM5,
|
||||||
|
ZYDIS_REGISTER_ZMM6,
|
||||||
|
ZYDIS_REGISTER_ZMM7,
|
||||||
|
ZYDIS_REGISTER_ZMM8,
|
||||||
|
ZYDIS_REGISTER_ZMM9,
|
||||||
|
ZYDIS_REGISTER_ZMM10,
|
||||||
|
ZYDIS_REGISTER_ZMM11,
|
||||||
|
ZYDIS_REGISTER_ZMM12,
|
||||||
|
ZYDIS_REGISTER_ZMM13,
|
||||||
|
ZYDIS_REGISTER_ZMM14,
|
||||||
|
ZYDIS_REGISTER_ZMM15,
|
||||||
|
ZYDIS_REGISTER_ZMM16,
|
||||||
|
ZYDIS_REGISTER_ZMM17,
|
||||||
|
ZYDIS_REGISTER_ZMM18,
|
||||||
|
ZYDIS_REGISTER_ZMM19,
|
||||||
|
ZYDIS_REGISTER_ZMM20,
|
||||||
|
ZYDIS_REGISTER_ZMM21,
|
||||||
|
ZYDIS_REGISTER_ZMM22,
|
||||||
|
ZYDIS_REGISTER_ZMM23,
|
||||||
|
ZYDIS_REGISTER_ZMM24,
|
||||||
|
ZYDIS_REGISTER_ZMM25,
|
||||||
|
ZYDIS_REGISTER_ZMM26,
|
||||||
|
ZYDIS_REGISTER_ZMM27,
|
||||||
|
ZYDIS_REGISTER_ZMM28,
|
||||||
|
ZYDIS_REGISTER_ZMM29,
|
||||||
|
ZYDIS_REGISTER_ZMM30,
|
||||||
|
ZYDIS_REGISTER_ZMM31,
|
||||||
|
// Matrix registers
|
||||||
|
ZYDIS_REGISTER_TMM0,
|
||||||
|
ZYDIS_REGISTER_TMM1,
|
||||||
|
ZYDIS_REGISTER_TMM2,
|
||||||
|
ZYDIS_REGISTER_TMM3,
|
||||||
|
ZYDIS_REGISTER_TMM4,
|
||||||
|
ZYDIS_REGISTER_TMM5,
|
||||||
|
ZYDIS_REGISTER_TMM6,
|
||||||
|
ZYDIS_REGISTER_TMM7,
|
||||||
|
// Flags registers
|
||||||
|
ZYDIS_REGISTER_FLAGS,
|
||||||
|
ZYDIS_REGISTER_EFLAGS,
|
||||||
|
ZYDIS_REGISTER_RFLAGS,
|
||||||
|
// Instruction-pointer registers
|
||||||
|
ZYDIS_REGISTER_IP,
|
||||||
|
ZYDIS_REGISTER_EIP,
|
||||||
|
ZYDIS_REGISTER_RIP,
|
||||||
|
// Segment registers
|
||||||
|
ZYDIS_REGISTER_ES,
|
||||||
|
ZYDIS_REGISTER_CS,
|
||||||
|
ZYDIS_REGISTER_SS,
|
||||||
|
ZYDIS_REGISTER_DS,
|
||||||
|
ZYDIS_REGISTER_FS,
|
||||||
|
ZYDIS_REGISTER_GS,
|
||||||
|
// Table registers
|
||||||
|
ZYDIS_REGISTER_GDTR,
|
||||||
|
ZYDIS_REGISTER_LDTR,
|
||||||
|
ZYDIS_REGISTER_IDTR,
|
||||||
|
ZYDIS_REGISTER_TR,
|
||||||
|
// Test registers
|
||||||
|
ZYDIS_REGISTER_TR0,
|
||||||
|
ZYDIS_REGISTER_TR1,
|
||||||
|
ZYDIS_REGISTER_TR2,
|
||||||
|
ZYDIS_REGISTER_TR3,
|
||||||
|
ZYDIS_REGISTER_TR4,
|
||||||
|
ZYDIS_REGISTER_TR5,
|
||||||
|
ZYDIS_REGISTER_TR6,
|
||||||
|
ZYDIS_REGISTER_TR7,
|
||||||
|
// Control registers
|
||||||
|
ZYDIS_REGISTER_CR0,
|
||||||
|
ZYDIS_REGISTER_CR1,
|
||||||
|
ZYDIS_REGISTER_CR2,
|
||||||
|
ZYDIS_REGISTER_CR3,
|
||||||
|
ZYDIS_REGISTER_CR4,
|
||||||
|
ZYDIS_REGISTER_CR5,
|
||||||
|
ZYDIS_REGISTER_CR6,
|
||||||
|
ZYDIS_REGISTER_CR7,
|
||||||
|
ZYDIS_REGISTER_CR8,
|
||||||
|
ZYDIS_REGISTER_CR9,
|
||||||
|
ZYDIS_REGISTER_CR10,
|
||||||
|
ZYDIS_REGISTER_CR11,
|
||||||
|
ZYDIS_REGISTER_CR12,
|
||||||
|
ZYDIS_REGISTER_CR13,
|
||||||
|
ZYDIS_REGISTER_CR14,
|
||||||
|
ZYDIS_REGISTER_CR15,
|
||||||
|
// Debug registers
|
||||||
|
ZYDIS_REGISTER_DR0,
|
||||||
|
ZYDIS_REGISTER_DR1,
|
||||||
|
ZYDIS_REGISTER_DR2,
|
||||||
|
ZYDIS_REGISTER_DR3,
|
||||||
|
ZYDIS_REGISTER_DR4,
|
||||||
|
ZYDIS_REGISTER_DR5,
|
||||||
|
ZYDIS_REGISTER_DR6,
|
||||||
|
ZYDIS_REGISTER_DR7,
|
||||||
|
ZYDIS_REGISTER_DR8,
|
||||||
|
ZYDIS_REGISTER_DR9,
|
||||||
|
ZYDIS_REGISTER_DR10,
|
||||||
|
ZYDIS_REGISTER_DR11,
|
||||||
|
ZYDIS_REGISTER_DR12,
|
||||||
|
ZYDIS_REGISTER_DR13,
|
||||||
|
ZYDIS_REGISTER_DR14,
|
||||||
|
ZYDIS_REGISTER_DR15,
|
||||||
|
// Mask registers
|
||||||
|
ZYDIS_REGISTER_K0,
|
||||||
|
ZYDIS_REGISTER_K1,
|
||||||
|
ZYDIS_REGISTER_K2,
|
||||||
|
ZYDIS_REGISTER_K3,
|
||||||
|
ZYDIS_REGISTER_K4,
|
||||||
|
ZYDIS_REGISTER_K5,
|
||||||
|
ZYDIS_REGISTER_K6,
|
||||||
|
ZYDIS_REGISTER_K7,
|
||||||
|
// Bound registers
|
||||||
|
ZYDIS_REGISTER_BND0,
|
||||||
|
ZYDIS_REGISTER_BND1,
|
||||||
|
ZYDIS_REGISTER_BND2,
|
||||||
|
ZYDIS_REGISTER_BND3,
|
||||||
|
ZYDIS_REGISTER_BNDCFG,
|
||||||
|
ZYDIS_REGISTER_BNDSTATUS,
|
||||||
|
// Uncategorized
|
||||||
|
ZYDIS_REGISTER_MXCSR,
|
||||||
|
ZYDIS_REGISTER_PKRU,
|
||||||
|
ZYDIS_REGISTER_XCR0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGISTER_MAX_VALUE = ZYDIS_REGISTER_XCR0,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGISTER_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGISTER_MAX_VALUE)
|
||||||
|
} ZydisRegister;
|
@ -0,0 +1,331 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_INTERNAL_DECODERDATA_H
|
||||||
|
#define ZYDIS_INTERNAL_DECODERDATA_H
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zydis/DecoderTypes.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
// MSVC does not like types other than (un-)signed int for bit-fields
|
||||||
|
#ifdef ZYAN_MSVC
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4214)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Decoder tree */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisDecoderTreeNodeType` data-type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU8 ZydisDecoderTreeNodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Values that represent zydis decoder tree node types.
|
||||||
|
*/
|
||||||
|
enum ZydisDecoderTreeNodeTypes
|
||||||
|
{
|
||||||
|
ZYDIS_NODETYPE_INVALID = 0x00,
|
||||||
|
/**
|
||||||
|
* Reference to an instruction-definition.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_DEFINITION_MASK = 0x80,
|
||||||
|
/**
|
||||||
|
* Reference to an XOP-map filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_XOP = 0x01,
|
||||||
|
/**
|
||||||
|
* Reference to an VEX-map filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_VEX = 0x02,
|
||||||
|
/**
|
||||||
|
* Reference to an EVEX/MVEX-map filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_EMVEX = 0x03,
|
||||||
|
/**
|
||||||
|
* Reference to an opcode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_OPCODE = 0x04,
|
||||||
|
/**
|
||||||
|
* Reference to an instruction-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE = 0x05,
|
||||||
|
/**
|
||||||
|
* Reference to an compacted instruction-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_COMPACT = 0x06,
|
||||||
|
/**
|
||||||
|
* Reference to a ModRM.mod filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODRM_MOD = 0x07,
|
||||||
|
/**
|
||||||
|
* Reference to a compacted ModRM.mod filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT = 0x08,
|
||||||
|
/**
|
||||||
|
* Reference to a ModRM.reg filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODRM_REG = 0x09,
|
||||||
|
/**
|
||||||
|
* Reference to a ModRM.rm filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODRM_RM = 0x0A,
|
||||||
|
/**
|
||||||
|
* Reference to a PrefixGroup1 filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1 = 0x0B,
|
||||||
|
/**
|
||||||
|
* Reference to a mandatory-prefix filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX = 0x0C,
|
||||||
|
/**
|
||||||
|
* Reference to an operand-size filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_OPERAND_SIZE = 0x0D,
|
||||||
|
/**
|
||||||
|
* Reference to an address-size filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE = 0x0E,
|
||||||
|
/**
|
||||||
|
* Reference to a vector-length filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH = 0x0F,
|
||||||
|
/**
|
||||||
|
* Reference to an REX/VEX/EVEX.W filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_REX_W = 0x10,
|
||||||
|
/**
|
||||||
|
* Reference to an REX/VEX/EVEX.B filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_REX_B = 0x11,
|
||||||
|
/**
|
||||||
|
* Reference to an EVEX.b filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_EVEX_B = 0x12,
|
||||||
|
/**
|
||||||
|
* Reference to an MVEX.E filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MVEX_E = 0x13,
|
||||||
|
/**
|
||||||
|
* Reference to a AMD-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_AMD = 0x14,
|
||||||
|
/**
|
||||||
|
* Reference to a KNC-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_KNC = 0x15,
|
||||||
|
/**
|
||||||
|
* Reference to a MPX-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_MPX = 0x16,
|
||||||
|
/**
|
||||||
|
* Reference to a CET-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_CET = 0x17,
|
||||||
|
/**
|
||||||
|
* Reference to a LZCNT-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_LZCNT = 0x18,
|
||||||
|
/**
|
||||||
|
* Reference to a TZCNT-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_TZCNT = 0x19,
|
||||||
|
/**
|
||||||
|
* Reference to a WBNOINVD-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD = 0x1A,
|
||||||
|
/**
|
||||||
|
* Reference to a CLDEMOTE-mode filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE = 0x1B
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisDecoderTreeNodeValue` data-type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU16 ZydisDecoderTreeNodeValue;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisDecoderTreeNode` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisDecoderTreeNode_
|
||||||
|
{
|
||||||
|
ZydisDecoderTreeNodeType type;
|
||||||
|
ZydisDecoderTreeNodeValue value;
|
||||||
|
} ZydisDecoderTreeNode;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#ifdef ZYAN_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Physical instruction encoding info */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionEncodingFlags` data-type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU8 ZydisInstructionEncodingFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instruction has an optional modrm byte.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_INSTR_ENC_FLAG_HAS_MODRM 0x01
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instruction has an optional displacement value.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_INSTR_ENC_FLAG_HAS_DISP 0x02
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instruction has an optional immediate value.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM0 0x04
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instruction has a second optional immediate value.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM1 0x08
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instruction ignores the value of `modrm.mod` and always assumes `modrm.mod == 3`
|
||||||
|
* ("reg, reg" - form).
|
||||||
|
*
|
||||||
|
* Instructions with this flag can't have a SIB byte or a displacement value.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM 0x10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionEncodingInfo` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionEncodingInfo_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Contains flags with information about the physical instruction-encoding.
|
||||||
|
*/
|
||||||
|
ZydisInstructionEncodingFlags flags;
|
||||||
|
/**
|
||||||
|
* Displacement info.
|
||||||
|
*/
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The size of the displacement value.
|
||||||
|
*/
|
||||||
|
ZyanU8 size[3];
|
||||||
|
} disp;
|
||||||
|
/**
|
||||||
|
* Immediate info.
|
||||||
|
*/
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The size of the immediate value.
|
||||||
|
*/
|
||||||
|
ZyanU8 size[3];
|
||||||
|
/**
|
||||||
|
* Signals, if the value is signed.
|
||||||
|
*/
|
||||||
|
ZyanBool is_signed;
|
||||||
|
/**
|
||||||
|
* Signals, if the value is a relative offset.
|
||||||
|
*/
|
||||||
|
ZyanBool is_relative;
|
||||||
|
} imm[2];
|
||||||
|
} ZydisInstructionEncodingInfo;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Decoder tree */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
extern const ZydisDecoderTreeNode zydis_decoder_tree_root;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the root node of the instruction tree.
|
||||||
|
*
|
||||||
|
* @return The root node of the instruction tree.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE const ZydisDecoderTreeNode* ZydisDecoderTreeGetRootNode(void)
|
||||||
|
{
|
||||||
|
return &zydis_decoder_tree_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the child node of `parent` specified by `index`.
|
||||||
|
*
|
||||||
|
* @param parent The parent node.
|
||||||
|
* @param index The index of the child node to retrieve.
|
||||||
|
*
|
||||||
|
* @return The specified child node.
|
||||||
|
*/
|
||||||
|
ZYDIS_NO_EXPORT const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode(
|
||||||
|
const ZydisDecoderTreeNode* parent, ZyanU16 index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns information about optional instruction parts (like modrm, displacement or
|
||||||
|
* immediates) for the instruction that is linked to the given `node`.
|
||||||
|
*
|
||||||
|
* @param node The instruction definition node.
|
||||||
|
* @param info A pointer to the `ZydisInstructionParts` struct.
|
||||||
|
*/
|
||||||
|
ZYDIS_NO_EXPORT void ZydisGetInstructionEncodingInfo(const ZydisDecoderTreeNode* node,
|
||||||
|
const ZydisInstructionEncodingInfo** info);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_INTERNAL_DECODERDATA_H */
|
@ -0,0 +1,178 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Implements the `AT&T` style instruction-formatter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_FORMATTER_ATT_H
|
||||||
|
#define ZYDIS_FORMATTER_ATT_H
|
||||||
|
|
||||||
|
#include <Zydis/Formatter.h>
|
||||||
|
#include <Zydis/Internal/FormatterBase.h>
|
||||||
|
#include <Zydis/Internal/String.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Formatter functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Instruction */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operands */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Elemental tokens */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Fomatter presets */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* AT&T */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default formatter configuration for `AT&T` style disassembly.
|
||||||
|
*/
|
||||||
|
static const ZydisFormatter FORMATTER_ATT =
|
||||||
|
{
|
||||||
|
/* style */ ZYDIS_FORMATTER_STYLE_ATT,
|
||||||
|
/* force_memory_size */ ZYAN_FALSE,
|
||||||
|
/* force_memory_seg */ ZYAN_FALSE,
|
||||||
|
/* force_relative_branches */ ZYAN_FALSE,
|
||||||
|
/* force_relative_riprel */ ZYAN_FALSE,
|
||||||
|
/* print_branch_size */ ZYAN_FALSE,
|
||||||
|
/* detailed_prefixes */ ZYAN_FALSE,
|
||||||
|
/* addr_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||||
|
/* addr_padding_absolute */ ZYDIS_PADDING_AUTO,
|
||||||
|
/* addr_padding_relative */ 2,
|
||||||
|
/* disp_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||||
|
/* disp_padding */ 2,
|
||||||
|
/* imm_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO,
|
||||||
|
/* imm_padding */ 2,
|
||||||
|
/* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_registers */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* hex_uppercase */ ZYAN_TRUE,
|
||||||
|
/* number_format */
|
||||||
|
{
|
||||||
|
// ZYDIS_NUMERIC_BASE_DEC
|
||||||
|
{
|
||||||
|
// Prefix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
// Suffix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ZYDIS_NUMERIC_BASE_HEX
|
||||||
|
{
|
||||||
|
// Prefix
|
||||||
|
{
|
||||||
|
/* string */ &FORMATTER_ATT.number_format[
|
||||||
|
ZYDIS_NUMERIC_BASE_HEX][0].string_data,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
// Suffix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* func_pre_instruction */ ZYAN_NULL,
|
||||||
|
/* func_post_instruction */ ZYAN_NULL,
|
||||||
|
/* func_format_instruction */ &ZydisFormatterATTFormatInstruction,
|
||||||
|
/* func_pre_operand */ ZYAN_NULL,
|
||||||
|
/* func_post_operand */ ZYAN_NULL,
|
||||||
|
/* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG,
|
||||||
|
/* func_format_operand_mem */ &ZydisFormatterATTFormatOperandMEM,
|
||||||
|
/* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR,
|
||||||
|
/* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM,
|
||||||
|
/* func_print_mnemonic */ &ZydisFormatterATTPrintMnemonic,
|
||||||
|
/* func_print_register */ &ZydisFormatterATTPrintRegister,
|
||||||
|
/* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS,
|
||||||
|
/* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL,
|
||||||
|
/* func_print_disp */ &ZydisFormatterATTPrintDISP,
|
||||||
|
/* func_print_imm */ &ZydisFormatterATTPrintIMM,
|
||||||
|
/* func_print_typecast */ ZYAN_NULL,
|
||||||
|
/* func_print_segment */ &ZydisFormatterBasePrintSegment,
|
||||||
|
/* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes,
|
||||||
|
/* func_print_decorator */ &ZydisFormatterBasePrintDecorator
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ZYDIS_FORMATTER_ATT_H
|
@ -0,0 +1,318 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Provides formatter functions that are shared between the different formatters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_FORMATTER_BASE_H
|
||||||
|
#define ZYDIS_FORMATTER_BASE_H
|
||||||
|
|
||||||
|
#include <Zydis/Formatter.h>
|
||||||
|
#include <Zydis/Internal/String.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* String */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends an unsigned numeric value to the given string.
|
||||||
|
*
|
||||||
|
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||||
|
* @param base The numeric base.
|
||||||
|
* @param str The destination string.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length The padding length.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STRING_APPEND_NUM_U(formatter, base, str, value, padding_length) \
|
||||||
|
switch (base) \
|
||||||
|
{ \
|
||||||
|
case ZYDIS_NUMERIC_BASE_DEC: \
|
||||||
|
ZYAN_CHECK(ZydisStringAppendDecU(str, value, padding_length, \
|
||||||
|
(formatter)->number_format[base][0].string, \
|
||||||
|
(formatter)->number_format[base][1].string)); \
|
||||||
|
break; \
|
||||||
|
case ZYDIS_NUMERIC_BASE_HEX: \
|
||||||
|
ZYAN_CHECK(ZydisStringAppendHexU(str, value, padding_length, \
|
||||||
|
(formatter)->hex_uppercase, \
|
||||||
|
(formatter)->number_format[base][0].string, \
|
||||||
|
(formatter)->number_format[base][1].string)); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
return ZYAN_STATUS_INVALID_ARGUMENT; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a signed numeric value to the given string.
|
||||||
|
*
|
||||||
|
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||||
|
* @param base The numeric base.
|
||||||
|
* @param str The destination string.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length The padding length.
|
||||||
|
* @param force_sign Forces printing of the '+' sign for positive numbers.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STRING_APPEND_NUM_S(formatter, base, str, value, padding_length, force_sign) \
|
||||||
|
switch (base) \
|
||||||
|
{ \
|
||||||
|
case ZYDIS_NUMERIC_BASE_DEC: \
|
||||||
|
ZYAN_CHECK(ZydisStringAppendDecS(str, value, padding_length, force_sign, \
|
||||||
|
(formatter)->number_format[base][0].string, \
|
||||||
|
(formatter)->number_format[base][1].string)); \
|
||||||
|
break; \
|
||||||
|
case ZYDIS_NUMERIC_BASE_HEX: \
|
||||||
|
ZYAN_CHECK(ZydisStringAppendHexS(str, value, padding_length, \
|
||||||
|
(formatter)->hex_uppercase, force_sign, \
|
||||||
|
(formatter)->number_format[base][0].string, \
|
||||||
|
(formatter)->number_format[base][1].string)); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
return ZYAN_STATUS_INVALID_ARGUMENT; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Buffer */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the `ZydisFormatterBufferAppend` routine, if tokenization is enabled for the
|
||||||
|
* current pass.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param type The token type.
|
||||||
|
*
|
||||||
|
* Using this macro instead of direct calls to `ZydisFormatterBufferAppend` greatly improves the
|
||||||
|
* performance for non-tokenizing passes.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_BUFFER_APPEND_TOKEN(buffer, type) \
|
||||||
|
if ((buffer)->is_token_list) \
|
||||||
|
{ \
|
||||||
|
ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, type)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a snapshot of the buffer-state.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param state Receives a snapshot of the buffer-state.
|
||||||
|
*
|
||||||
|
* Using this macro instead of direct calls to `ZydisFormatterBufferRemember` improves the
|
||||||
|
* performance for non-tokenizing passes.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_BUFFER_REMEMBER(buffer, state) \
|
||||||
|
if ((buffer)->is_token_list) \
|
||||||
|
{ \
|
||||||
|
(state) = (ZyanUPointer)(buffer)->string.vector.data; \
|
||||||
|
} else \
|
||||||
|
{ \
|
||||||
|
(state) = (ZyanUPointer)(buffer)->string.vector.size; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix).
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param name The base name (without prefix) of the string- or token.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_BUFFER_APPEND(buffer, name) \
|
||||||
|
if ((buffer)->is_token_list) \
|
||||||
|
{ \
|
||||||
|
ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
|
||||||
|
} else \
|
||||||
|
{ \
|
||||||
|
ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ ## name)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement `letter_case` for predefined tokens
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix).
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param name The base name (without prefix) of the string- or token.
|
||||||
|
* @param letter-case The desired letter-case.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_BUFFER_APPEND_CASE(buffer, name, letter_case) \
|
||||||
|
if ((buffer)->is_token_list) \
|
||||||
|
{ \
|
||||||
|
ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
|
||||||
|
} else \
|
||||||
|
{ \
|
||||||
|
ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_ ## name, letter_case)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Helper functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Buffer */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// MSVC does not like the C99 flexible-array extension
|
||||||
|
#ifdef ZYAN_MSVC
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4200)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
typedef struct ZydisPredefinedToken_
|
||||||
|
{
|
||||||
|
ZyanU8 size;
|
||||||
|
ZyanU8 next;
|
||||||
|
ZyanU8 data[];
|
||||||
|
} ZydisPredefinedToken;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#ifdef ZYAN_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a predefined token-list to the `buffer`.
|
||||||
|
*
|
||||||
|
* @param buffer A pointer to the `ZydisFormatterBuffer` struct.
|
||||||
|
* @param data A pointer to the `ZydisPredefinedToken` struct.
|
||||||
|
*
|
||||||
|
* @return A zycore status code.
|
||||||
|
*
|
||||||
|
* This function is internally used to improve performance while adding static strings or multiple
|
||||||
|
* tokens at once.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanStatus ZydisFormatterBufferAppendPredefined(ZydisFormatterBuffer* buffer,
|
||||||
|
const ZydisPredefinedToken* data)
|
||||||
|
{
|
||||||
|
ZYAN_ASSERT(buffer);
|
||||||
|
ZYAN_ASSERT(data);
|
||||||
|
|
||||||
|
const ZyanUSize len = buffer->string.vector.size;
|
||||||
|
ZYAN_ASSERT((len > 0) && (len < 256));
|
||||||
|
if (buffer->capacity <= len + data->size)
|
||||||
|
{
|
||||||
|
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1;
|
||||||
|
last->next = (ZyanU8)len;
|
||||||
|
|
||||||
|
ZYAN_MEMCPY((ZyanU8*)buffer->string.vector.data + len, &data->data[0], data->size);
|
||||||
|
|
||||||
|
const ZyanUSize delta = len + data->next;
|
||||||
|
buffer->capacity -= delta;
|
||||||
|
buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta;
|
||||||
|
buffer->string.vector.size = data->size - data->next;
|
||||||
|
buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
|
||||||
|
|
||||||
|
return ZYAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* General */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size to be used as explicit size suffix (`AT&T`) or explicit typecast
|
||||||
|
* (`INTEL`), if required.
|
||||||
|
*
|
||||||
|
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||||
|
* @param context A pointer to the `ZydisFormatterContext` struct.
|
||||||
|
* @param memop_id The operand-id of the instructions first memory operand.
|
||||||
|
*
|
||||||
|
* @return Returns the explicit size, if required, or `0`, if not needed.
|
||||||
|
*
|
||||||
|
* This function always returns a size different to `0`, if the `ZYDIS_FORMATTER_PROP_FORCE_SIZE`
|
||||||
|
* is set to `ZYAN_TRUE`.
|
||||||
|
*/
|
||||||
|
ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterContext* context, ZyanU8 memop_id);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Formatter functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operands */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Elemental tokens */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Optional tokens */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ZYDIS_FORMATTER_BASE_H
|
@ -0,0 +1,267 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Implements the `INTEL` style instruction-formatter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_FORMATTER_INTEL_H
|
||||||
|
#define ZYDIS_FORMATTER_INTEL_H
|
||||||
|
|
||||||
|
#include <Zydis/Formatter.h>
|
||||||
|
#include <Zydis/Internal/FormatterBase.h>
|
||||||
|
#include <Zydis/Internal/String.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Formatter functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Intel */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* MASM */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
|
||||||
|
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Fomatter presets */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* INTEL */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default formatter configuration for `INTEL` style disassembly.
|
||||||
|
*/
|
||||||
|
static const ZydisFormatter FORMATTER_INTEL =
|
||||||
|
{
|
||||||
|
/* style */ ZYDIS_FORMATTER_STYLE_INTEL,
|
||||||
|
/* force_memory_size */ ZYAN_FALSE,
|
||||||
|
/* force_memory_seg */ ZYAN_FALSE,
|
||||||
|
/* force_relative_branches */ ZYAN_FALSE,
|
||||||
|
/* force_relative_riprel */ ZYAN_FALSE,
|
||||||
|
/* print_branch_size */ ZYAN_FALSE,
|
||||||
|
/* detailed_prefixes */ ZYAN_FALSE,
|
||||||
|
/* addr_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||||
|
/* addr_padding_absolute */ ZYDIS_PADDING_AUTO,
|
||||||
|
/* addr_padding_relative */ 2,
|
||||||
|
/* disp_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||||
|
/* disp_padding */ 2,
|
||||||
|
/* imm_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* imm_signedness */ ZYDIS_SIGNEDNESS_UNSIGNED,
|
||||||
|
/* imm_padding */ 2,
|
||||||
|
/* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_registers */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* hex_uppercase */ ZYAN_TRUE,
|
||||||
|
/* number_format */
|
||||||
|
{
|
||||||
|
// ZYDIS_NUMERIC_BASE_DEC
|
||||||
|
{
|
||||||
|
// Prefix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
// Suffix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ZYDIS_NUMERIC_BASE_HEX
|
||||||
|
{
|
||||||
|
// Prefix
|
||||||
|
{
|
||||||
|
/* string */ &FORMATTER_INTEL.number_format[
|
||||||
|
ZYDIS_NUMERIC_BASE_HEX][0].string_data,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
// Suffix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* func_pre_instruction */ ZYAN_NULL,
|
||||||
|
/* func_post_instruction */ ZYAN_NULL,
|
||||||
|
/* func_format_instruction */ &ZydisFormatterIntelFormatInstruction,
|
||||||
|
/* func_pre_operand */ ZYAN_NULL,
|
||||||
|
/* func_post_operand */ ZYAN_NULL,
|
||||||
|
/* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG,
|
||||||
|
/* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM,
|
||||||
|
/* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR,
|
||||||
|
/* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM,
|
||||||
|
/* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic,
|
||||||
|
/* func_print_register */ &ZydisFormatterIntelPrintRegister,
|
||||||
|
/* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS,
|
||||||
|
/* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL,
|
||||||
|
/* func_print_disp */ &ZydisFormatterIntelPrintDISP,
|
||||||
|
/* func_print_imm */ &ZydisFormatterBasePrintIMM,
|
||||||
|
/* func_print_typecast */ &ZydisFormatterIntelPrintTypecast,
|
||||||
|
/* func_print_segment */ &ZydisFormatterBasePrintSegment,
|
||||||
|
/* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes,
|
||||||
|
/* func_print_decorator */ &ZydisFormatterBasePrintDecorator
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* MASM */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default formatter configuration for `MASM` style disassembly.
|
||||||
|
*/
|
||||||
|
static const ZydisFormatter FORMATTER_INTEL_MASM =
|
||||||
|
{
|
||||||
|
/* style */ ZYDIS_FORMATTER_STYLE_INTEL_MASM,
|
||||||
|
/* force_memory_size */ ZYAN_TRUE,
|
||||||
|
/* force_memory_seg */ ZYAN_FALSE,
|
||||||
|
/* force_relative_branches */ ZYAN_FALSE,
|
||||||
|
/* force_relative_riprel */ ZYAN_FALSE,
|
||||||
|
/* print_branch_size */ ZYAN_FALSE,
|
||||||
|
/* detailed_prefixes */ ZYAN_FALSE,
|
||||||
|
/* addr_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||||
|
/* addr_padding_absolute */ ZYDIS_PADDING_DISABLED,
|
||||||
|
/* addr_padding_relative */ ZYDIS_PADDING_DISABLED,
|
||||||
|
/* disp_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED,
|
||||||
|
/* disp_padding */ ZYDIS_PADDING_DISABLED,
|
||||||
|
/* imm_base */ ZYDIS_NUMERIC_BASE_HEX,
|
||||||
|
/* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO,
|
||||||
|
/* imm_padding */ ZYDIS_PADDING_DISABLED,
|
||||||
|
/* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_registers */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/* hex_uppercase */ ZYAN_TRUE,
|
||||||
|
/* number_format */
|
||||||
|
{
|
||||||
|
// ZYDIS_NUMERIC_BASE_DEC
|
||||||
|
{
|
||||||
|
// Prefix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
// Suffix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ZYDIS_NUMERIC_BASE_HEX
|
||||||
|
{
|
||||||
|
// Prefix
|
||||||
|
{
|
||||||
|
/* string */ ZYAN_NULL,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW(""),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
// Suffix
|
||||||
|
{
|
||||||
|
/* string */ &FORMATTER_INTEL_MASM.number_format[
|
||||||
|
ZYDIS_NUMERIC_BASE_HEX][1].string_data,
|
||||||
|
/* string_data */ ZYAN_DEFINE_STRING_VIEW("h"),
|
||||||
|
/* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* func_pre_instruction */ ZYAN_NULL,
|
||||||
|
/* func_post_instruction */ ZYAN_NULL,
|
||||||
|
/* func_format_instruction */ &ZydisFormatterIntelFormatInstructionMASM,
|
||||||
|
/* func_pre_operand */ ZYAN_NULL,
|
||||||
|
/* func_post_operand */ ZYAN_NULL,
|
||||||
|
/* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG,
|
||||||
|
/* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM,
|
||||||
|
/* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR,
|
||||||
|
/* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM,
|
||||||
|
/* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic,
|
||||||
|
/* func_print_register */ &ZydisFormatterIntelPrintRegister,
|
||||||
|
/* func_print_address_abs */ &ZydisFormatterIntelPrintAddressMASM,
|
||||||
|
/* func_print_address_rel */ &ZydisFormatterIntelPrintAddressMASM,
|
||||||
|
/* func_print_disp */ &ZydisFormatterIntelPrintDISP,
|
||||||
|
/* func_print_imm */ &ZydisFormatterBasePrintIMM,
|
||||||
|
/* func_print_typecast */ &ZydisFormatterIntelPrintTypecast,
|
||||||
|
/* func_print_segment */ &ZydisFormatterBasePrintSegment,
|
||||||
|
/* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes,
|
||||||
|
/* func_print_decorator */ &ZydisFormatterBasePrintDecorator
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ZYDIS_FORMATTER_INTEL_H
|
@ -0,0 +1,974 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_INTERNAL_SHAREDDATA_H
|
||||||
|
#define ZYDIS_INTERNAL_SHAREDDATA_H
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zydis/Mnemonic.h>
|
||||||
|
#include <Zydis/Register.h>
|
||||||
|
#include <Zydis/SharedTypes.h>
|
||||||
|
#include <Zydis/DecoderTypes.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
// MSVC does not like types other than (un-)signed int for bit-fields
|
||||||
|
#ifdef ZYAN_MSVC
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4214)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operand definition */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisSemanticOperandType` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisSemanticOperandType_
|
||||||
|
{
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_UNUSED,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR8,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR16,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR32,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR64,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_FPR,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MMX,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_XMM,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_YMM,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_ZMM,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_TMM,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_BND,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_SREG,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_CR,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_DR,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MASK,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MEM,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_IMM,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_REL,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_PTR,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_AGEN,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MOFFS,
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MIB,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE = ZYDIS_SEMANTIC_OPTYPE_MIB,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE)
|
||||||
|
} ZydisSemanticOperandType;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInternalElementType` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisInternalElementType_
|
||||||
|
{
|
||||||
|
ZYDIS_IELEMENT_TYPE_INVALID,
|
||||||
|
ZYDIS_IELEMENT_TYPE_VARIABLE,
|
||||||
|
ZYDIS_IELEMENT_TYPE_STRUCT,
|
||||||
|
ZYDIS_IELEMENT_TYPE_INT,
|
||||||
|
ZYDIS_IELEMENT_TYPE_UINT,
|
||||||
|
ZYDIS_IELEMENT_TYPE_INT1,
|
||||||
|
ZYDIS_IELEMENT_TYPE_INT8,
|
||||||
|
ZYDIS_IELEMENT_TYPE_INT16,
|
||||||
|
ZYDIS_IELEMENT_TYPE_INT32,
|
||||||
|
ZYDIS_IELEMENT_TYPE_INT64,
|
||||||
|
ZYDIS_IELEMENT_TYPE_UINT8,
|
||||||
|
ZYDIS_IELEMENT_TYPE_UINT16,
|
||||||
|
ZYDIS_IELEMENT_TYPE_UINT32,
|
||||||
|
ZYDIS_IELEMENT_TYPE_UINT64,
|
||||||
|
ZYDIS_IELEMENT_TYPE_UINT128,
|
||||||
|
ZYDIS_IELEMENT_TYPE_UINT256,
|
||||||
|
ZYDIS_IELEMENT_TYPE_FLOAT16,
|
||||||
|
ZYDIS_IELEMENT_TYPE_FLOAT32,
|
||||||
|
ZYDIS_IELEMENT_TYPE_FLOAT64,
|
||||||
|
ZYDIS_IELEMENT_TYPE_FLOAT80,
|
||||||
|
ZYDIS_IELEMENT_TYPE_BCD80,
|
||||||
|
ZYDIS_IELEMENT_TYPE_CC3,
|
||||||
|
ZYDIS_IELEMENT_TYPE_CC5,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IELEMENT_TYPE_MAX_VALUE = ZYDIS_IELEMENT_TYPE_CC5,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_TYPE_MAX_VALUE)
|
||||||
|
} ZydisInternalElementType;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisImplicitRegisterType` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisImplicitRegisterType_
|
||||||
|
{
|
||||||
|
ZYDIS_IMPLREG_TYPE_STATIC,
|
||||||
|
ZYDIS_IMPLREG_TYPE_GPR_OSZ,
|
||||||
|
ZYDIS_IMPLREG_TYPE_GPR_ASZ,
|
||||||
|
ZYDIS_IMPLREG_TYPE_GPR_SSZ,
|
||||||
|
ZYDIS_IMPLREG_TYPE_IP_ASZ,
|
||||||
|
ZYDIS_IMPLREG_TYPE_IP_SSZ,
|
||||||
|
ZYDIS_IMPLREG_TYPE_FLAGS_SSZ,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IMPLREG_TYPE_MAX_VALUE = ZYDIS_IMPLREG_TYPE_FLAGS_SSZ,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IMPLREG_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLREG_TYPE_MAX_VALUE)
|
||||||
|
} ZydisImplicitRegisterType;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisImplicitMemBase` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisImplicitMemBase_
|
||||||
|
{
|
||||||
|
ZYDIS_IMPLMEM_BASE_AGPR_REG,
|
||||||
|
ZYDIS_IMPLMEM_BASE_AGPR_RM,
|
||||||
|
ZYDIS_IMPLMEM_BASE_AAX,
|
||||||
|
ZYDIS_IMPLMEM_BASE_ADX,
|
||||||
|
ZYDIS_IMPLMEM_BASE_ABX,
|
||||||
|
ZYDIS_IMPLMEM_BASE_ASP,
|
||||||
|
ZYDIS_IMPLMEM_BASE_ABP,
|
||||||
|
ZYDIS_IMPLMEM_BASE_ASI,
|
||||||
|
ZYDIS_IMPLMEM_BASE_ADI,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IMPLMEM_BASE_MAX_VALUE = ZYDIS_IMPLMEM_BASE_ADI,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IMPLMEM_BASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLMEM_BASE_MAX_VALUE)
|
||||||
|
} ZydisImplicitMemBase;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||||
|
// enum types
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ACTION_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_REGISTER_REQUIRED_BITS <= 16);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS <= 8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisOperandDefinition` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisOperandDefinition_
|
||||||
|
{
|
||||||
|
ZyanU8 type ZYAN_BITFIELD(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS);
|
||||||
|
ZyanU8 visibility ZYAN_BITFIELD(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS);
|
||||||
|
ZyanU8 actions ZYAN_BITFIELD(ZYDIS_OPERAND_ACTION_REQUIRED_BITS);
|
||||||
|
ZyanU16 size[3];
|
||||||
|
ZyanU8 element_type ZYAN_BITFIELD(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ZyanU8 encoding ZYAN_BITFIELD(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS);
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ZyanU8 type ZYAN_BITFIELD(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ZyanU16 reg ZYAN_BITFIELD(ZYDIS_REGISTER_REQUIRED_BITS);
|
||||||
|
ZyanU8 id ZYAN_BITFIELD(6);
|
||||||
|
} reg;
|
||||||
|
} reg;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ZyanU8 seg ZYAN_BITFIELD(3);
|
||||||
|
ZyanU8 base ZYAN_BITFIELD(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS);
|
||||||
|
} mem;
|
||||||
|
} op;
|
||||||
|
} ZydisOperandDefinition;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Instruction definition */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisReadWriteAction` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisReadWriteAction_
|
||||||
|
{
|
||||||
|
ZYDIS_RW_ACTION_NONE,
|
||||||
|
ZYDIS_RW_ACTION_READ,
|
||||||
|
ZYDIS_RW_ACTION_WRITE,
|
||||||
|
ZYDIS_RW_ACTION_READWRITE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_RW_ACTION_MAX_VALUE = ZYDIS_RW_ACTION_READWRITE,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_RW_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_RW_ACTION_MAX_VALUE)
|
||||||
|
} ZydisReadWriteAction;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisRegisterConstraint` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisRegisterConstraint_
|
||||||
|
{
|
||||||
|
ZYDIS_REG_CONSTRAINTS_UNUSED,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_NONE,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_GPR,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_SR_DEST,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_SR,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_CR,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_DR,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_MASK,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_BND,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_VSIB,
|
||||||
|
ZYDIS_REG_CONSTRAINTS_NO_REL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_REG_CONSTRAINTS_MAX_VALUE = ZYDIS_REG_CONSTRAINTS_NO_REL,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REG_CONSTRAINTS_MAX_VALUE)
|
||||||
|
} ZydisRegisterConstraint;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInternalVectorLength` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisInternalVectorLength_
|
||||||
|
{
|
||||||
|
ZYDIS_IVECTOR_LENGTH_DEFAULT,
|
||||||
|
ZYDIS_IVECTOR_LENGTH_FIXED_128,
|
||||||
|
ZYDIS_IVECTOR_LENGTH_FIXED_256,
|
||||||
|
ZYDIS_IVECTOR_LENGTH_FIXED_512,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IVECTOR_LENGTH_MAX_VALUE = ZYDIS_IVECTOR_LENGTH_FIXED_512,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IVECTOR_LENGTH_MAX_VALUE)
|
||||||
|
} ZydisInternalVectorLength;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInternalElementSize` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisInternalElementSize_
|
||||||
|
{
|
||||||
|
ZYDIS_IELEMENT_SIZE_INVALID,
|
||||||
|
ZYDIS_IELEMENT_SIZE_8,
|
||||||
|
ZYDIS_IELEMENT_SIZE_16,
|
||||||
|
ZYDIS_IELEMENT_SIZE_32,
|
||||||
|
ZYDIS_IELEMENT_SIZE_64,
|
||||||
|
ZYDIS_IELEMENT_SIZE_128,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IELEMENT_SIZE_MAX_VALUE = ZYDIS_IELEMENT_SIZE_128,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_IELEMENT_SIZE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_SIZE_MAX_VALUE)
|
||||||
|
} ZydisInternalElementSize;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisEVEXFunctionality` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisEVEXFunctionality_
|
||||||
|
{
|
||||||
|
ZYDIS_EVEX_FUNC_INVALID,
|
||||||
|
/**
|
||||||
|
* `EVEX.b` enables broadcast functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_BC,
|
||||||
|
/**
|
||||||
|
* `EVEX.b` enables embedded-rounding functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_RC,
|
||||||
|
/**
|
||||||
|
* `EVEX.b` enables sae functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_SAE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_MAX_VALUE = ZYDIS_EVEX_FUNC_SAE,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_FUNC_MAX_VALUE)
|
||||||
|
} ZydisEVEXFunctionality;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisEVEXTupleType` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisEVEXTupleType_
|
||||||
|
{
|
||||||
|
ZYDIS_TUPLETYPE_INVALID,
|
||||||
|
/**
|
||||||
|
* Full Vector
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_FV,
|
||||||
|
/**
|
||||||
|
* Half Vector
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_HV,
|
||||||
|
/**
|
||||||
|
* Full Vector Mem
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_FVM,
|
||||||
|
/**
|
||||||
|
* Tuple1 Scalar
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_T1S,
|
||||||
|
/**
|
||||||
|
* Tuple1 Fixed
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_T1F,
|
||||||
|
/**
|
||||||
|
* Tuple1 4x32
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_T1_4X,
|
||||||
|
/**
|
||||||
|
* Gather / Scatter
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_GSCAT,
|
||||||
|
/**
|
||||||
|
* Tuple2
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_T2,
|
||||||
|
/**
|
||||||
|
* Tuple4
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_T4,
|
||||||
|
/**
|
||||||
|
* Tuple8
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_T8,
|
||||||
|
/**
|
||||||
|
* Half Mem
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_HVM,
|
||||||
|
/**
|
||||||
|
* QuarterMem
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_QVM,
|
||||||
|
/**
|
||||||
|
* OctMem
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_OVM,
|
||||||
|
/**
|
||||||
|
* Mem128
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_M128,
|
||||||
|
/**
|
||||||
|
* MOVDDUP
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_DUP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_MAX_VALUE = ZYDIS_TUPLETYPE_DUP,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_TUPLETYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_TUPLETYPE_MAX_VALUE)
|
||||||
|
} ZydisEVEXTupleType;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisMVEXFunctionality` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisMVEXFunctionality_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The `MVEX.SSS` value is ignored.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_IGNORED,
|
||||||
|
/**
|
||||||
|
* `MVEX.SSS` must be `000b`.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_INVALID,
|
||||||
|
/**
|
||||||
|
* `MVEX.SSS` controls embedded-rounding functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_RC,
|
||||||
|
/**
|
||||||
|
* `MVEX.SSS` controls sae functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SAE,
|
||||||
|
/**
|
||||||
|
* No special operation (32bit float elements).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_F_32,
|
||||||
|
/**
|
||||||
|
* No special operation (32bit uint elements).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_I_32,
|
||||||
|
/**
|
||||||
|
* No special operation (64bit float elements).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_F_64,
|
||||||
|
/**
|
||||||
|
* No special operation (64bit uint elements).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_I_64,
|
||||||
|
/**
|
||||||
|
* Sf32(reg) or Si32(reg).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SWIZZLE_32,
|
||||||
|
/**
|
||||||
|
* Sf64(reg) or Si64(reg).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SWIZZLE_64,
|
||||||
|
/**
|
||||||
|
* Sf32(mem).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SF_32,
|
||||||
|
/**
|
||||||
|
* Sf32(mem) broadcast only.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SF_32_BCST,
|
||||||
|
/**
|
||||||
|
* Sf32(mem) broadcast 4to16 only.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16,
|
||||||
|
/**
|
||||||
|
* Sf64(mem).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SF_64,
|
||||||
|
/**
|
||||||
|
* Si32(mem).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SI_32,
|
||||||
|
/**
|
||||||
|
* Si32(mem) broadcast only.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SI_32_BCST,
|
||||||
|
/**
|
||||||
|
* Si32(mem) broadcast 4to16 only.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16,
|
||||||
|
/**
|
||||||
|
* Si64(mem).
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_SI_64,
|
||||||
|
/**
|
||||||
|
* Uf32.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_UF_32,
|
||||||
|
/**
|
||||||
|
* Uf64.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_UF_64,
|
||||||
|
/**
|
||||||
|
* Ui32.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_UI_32,
|
||||||
|
/**
|
||||||
|
* Ui64.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_UI_64,
|
||||||
|
/**
|
||||||
|
* Df32.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_DF_32,
|
||||||
|
/**
|
||||||
|
* Df64.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_DF_64,
|
||||||
|
/**
|
||||||
|
* Di32.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_DI_32,
|
||||||
|
/**
|
||||||
|
* Di64.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_DI_64,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_MAX_VALUE = ZYDIS_MVEX_FUNC_DI_64,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_FUNC_MAX_VALUE)
|
||||||
|
} ZydisMVEXFunctionality;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisVEXStaticBroadcast` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisVEXStaticBroadcast
|
||||||
|
{
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_NONE,
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_1_TO_2,
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_1_TO_4,
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_1_TO_8,
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_1_TO_16,
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_1_TO_32,
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_2_TO_4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_VEX_STATIC_BROADCAST_2_TO_4,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS =
|
||||||
|
ZYAN_BITS_TO_REPRESENT(ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE)
|
||||||
|
} ZydisVEXStaticBroadcast;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisEVEXStaticBroadcast` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisEVEXStaticBroadcast_
|
||||||
|
{
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_NONE,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_2,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_4,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_8,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_16,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_32,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_1_TO_64,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_2_TO_4,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_2_TO_8,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_2_TO_16,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_4_TO_8,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_4_TO_16,
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS =
|
||||||
|
ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE)
|
||||||
|
} ZydisEVEXStaticBroadcast;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisMVEXStaticBroadcast` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisMVEXStaticBroadcast_
|
||||||
|
{
|
||||||
|
ZYDIS_MVEX_STATIC_BROADCAST_NONE,
|
||||||
|
ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8,
|
||||||
|
ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16,
|
||||||
|
ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8,
|
||||||
|
ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS =
|
||||||
|
ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE)
|
||||||
|
} ZydisMVEXStaticBroadcast;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisMaskPolicy` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisMaskPolicy_
|
||||||
|
{
|
||||||
|
ZYDIS_MASK_POLICY_INVALID,
|
||||||
|
/**
|
||||||
|
* The instruction accepts mask-registers other than the default-mask (K0), but
|
||||||
|
* does not require them.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_ALLOWED,
|
||||||
|
/**
|
||||||
|
* The instruction requires a mask-register other than the default-mask (K0).
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_REQUIRED,
|
||||||
|
/**
|
||||||
|
* The instruction does not allow a mask-register other than the default-mask (K0).
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_FORBIDDEN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_MAX_VALUE = ZYDIS_MASK_POLICY_FORBIDDEN,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_POLICY_MAX_VALUE)
|
||||||
|
} ZydisMaskPolicy;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisMaskOverride` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisMaskOverride_
|
||||||
|
{
|
||||||
|
ZYDIS_MASK_OVERRIDE_DEFAULT,
|
||||||
|
ZYDIS_MASK_OVERRIDE_ZEROING,
|
||||||
|
ZYDIS_MASK_OVERRIDE_CONTROL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_OVERRIDE_MAX_VALUE = ZYDIS_MASK_OVERRIDE_CONTROL,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_OVERRIDE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_OVERRIDE_MAX_VALUE)
|
||||||
|
} ZydisMaskOverride;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||||
|
// enum types
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_MNEMONIC_REQUIRED_BITS <= 16);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_CATEGORY_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_ISA_SET_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_ISA_EXT_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_BRANCH_TYPE_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_RW_ACTION_REQUIRED_BITS <= 8);
|
||||||
|
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
# define ZYDIS_INSTRUCTION_DEFINITION_BASE \
|
||||||
|
ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \
|
||||||
|
ZyanU8 operand_count ZYAN_BITFIELD( 4); \
|
||||||
|
ZyanU16 operand_reference ZYAN_BITFIELD(15); \
|
||||||
|
ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \
|
||||||
|
ZyanU8 address_size_map ZYAN_BITFIELD( 2); \
|
||||||
|
ZyanU8 flags_reference ZYAN_BITFIELD( 7); \
|
||||||
|
ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \
|
||||||
|
ZyanU8 category ZYAN_BITFIELD(ZYDIS_CATEGORY_REQUIRED_BITS); \
|
||||||
|
ZyanU8 isa_set ZYAN_BITFIELD(ZYDIS_ISA_SET_REQUIRED_BITS); \
|
||||||
|
ZyanU8 isa_ext ZYAN_BITFIELD(ZYDIS_ISA_EXT_REQUIRED_BITS); \
|
||||||
|
ZyanU8 branch_type ZYAN_BITFIELD(ZYDIS_BRANCH_TYPE_REQUIRED_BITS); \
|
||||||
|
ZyanU8 exception_class ZYAN_BITFIELD(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS); \
|
||||||
|
ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \
|
||||||
|
ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \
|
||||||
|
ZyanU8 cpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \
|
||||||
|
ZyanU8 fpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \
|
||||||
|
ZyanU8 xmm_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS)
|
||||||
|
#else
|
||||||
|
# define ZYDIS_INSTRUCTION_DEFINITION_BASE \
|
||||||
|
ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \
|
||||||
|
ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \
|
||||||
|
ZyanU8 address_size_map ZYAN_BITFIELD( 2); \
|
||||||
|
ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \
|
||||||
|
ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \
|
||||||
|
ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR \
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE; \
|
||||||
|
ZyanU8 constr_NDSNDD ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS)
|
||||||
|
|
||||||
|
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL \
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \
|
||||||
|
ZyanBool is_gather ZYAN_BITFIELD( 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionDefinition` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionDefinition_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
||||||
|
} ZydisInstructionDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionDefinitionLEGACY` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionDefinitionLEGACY_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
ZyanBool is_privileged ZYAN_BITFIELD( 1);
|
||||||
|
#endif
|
||||||
|
ZyanBool accepts_LOCK ZYAN_BITFIELD( 1);
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
ZyanBool accepts_REP ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_REPEREPZ ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_REPNEREPNZ ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_BOUND ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_XACQUIRE ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_XRELEASE ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_hle_without_lock ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_branch_hints ZYAN_BITFIELD( 1);
|
||||||
|
ZyanBool accepts_segment ZYAN_BITFIELD( 1);
|
||||||
|
#endif
|
||||||
|
} ZydisInstructionDefinitionLEGACY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionDefinition3DNOW` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionDefinition3DNOW_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
||||||
|
} ZydisInstructionDefinition3DNOW;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionDefinitionXOP` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionDefinitionXOP_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR;
|
||||||
|
} ZydisInstructionDefinitionXOP;
|
||||||
|
|
||||||
|
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||||
|
// enum types
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS <= 8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionDefinitionVEX` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionDefinitionVEX_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL;
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS);
|
||||||
|
#endif
|
||||||
|
} ZydisInstructionDefinitionVEX;
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DISABLE_AVX512
|
||||||
|
|
||||||
|
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||||
|
// enum types
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_TUPLETYPE_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_EVEX_FUNC_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionDefinitionEVEX` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionDefinitionEVEX_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL;
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
ZyanU8 vector_length ZYAN_BITFIELD(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS);
|
||||||
|
ZyanU8 tuple_type ZYAN_BITFIELD(ZYDIS_TUPLETYPE_REQUIRED_BITS);
|
||||||
|
ZyanU8 element_size ZYAN_BITFIELD(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS);
|
||||||
|
ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_EVEX_FUNC_REQUIRED_BITS);
|
||||||
|
#endif
|
||||||
|
ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS);
|
||||||
|
ZyanBool accepts_zero_mask ZYAN_BITFIELD( 1);
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
ZyanU8 mask_override ZYAN_BITFIELD(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS);
|
||||||
|
ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS);
|
||||||
|
#endif
|
||||||
|
} ZydisInstructionDefinitionEVEX;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DISABLE_KNC
|
||||||
|
|
||||||
|
// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct
|
||||||
|
// enum types
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_MVEX_FUNC_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8);
|
||||||
|
ZYAN_STATIC_ASSERT(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionDefinitionMVEX` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionDefinitionMVEX_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL;
|
||||||
|
ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_MVEX_FUNC_REQUIRED_BITS);
|
||||||
|
ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS);
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
ZyanBool has_element_granularity ZYAN_BITFIELD( 1);
|
||||||
|
ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS);
|
||||||
|
#endif
|
||||||
|
} ZydisInstructionDefinitionMVEX;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Accessed CPU flags */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
typedef struct ZydisAccessedFlags_
|
||||||
|
{
|
||||||
|
ZydisCPUFlagAction action[ZYDIS_CPUFLAG_MAX_VALUE + 1];
|
||||||
|
ZyanU32 cpu_flags_read ZYAN_BITFIELD(22);
|
||||||
|
ZyanU32 cpu_flags_written ZYAN_BITFIELD(22);
|
||||||
|
ZyanU8 fpu_flags_read ZYAN_BITFIELD( 4);
|
||||||
|
ZyanU8 fpu_flags_written ZYAN_BITFIELD( 4);
|
||||||
|
} ZydisAccessedFlags;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#ifdef ZYAN_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Instruction definition */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the instruction-definition with the given `encoding` and `id`.
|
||||||
|
*
|
||||||
|
* @param encoding The instruction-encoding.
|
||||||
|
* @param id The definition-id.
|
||||||
|
* @param definition A pointer to the variable that receives a pointer to the instruction-
|
||||||
|
* definition.
|
||||||
|
*/
|
||||||
|
ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(ZydisInstructionEncoding encoding,
|
||||||
|
ZyanU16 id, const ZydisInstructionDefinition** definition);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operand definition */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
/**
|
||||||
|
* Returns the the operand-definitions for the given instruction-`definition`.
|
||||||
|
*
|
||||||
|
* @param definition A pointer to the instruction-definition.
|
||||||
|
* @param operand A pointer to the variable that receives a pointer to the first operand-
|
||||||
|
* definition of the instruction.
|
||||||
|
*
|
||||||
|
* @return The number of operands for the given instruction-definition.
|
||||||
|
*/
|
||||||
|
ZYDIS_NO_EXPORT ZyanU8 ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition,
|
||||||
|
const ZydisOperandDefinition** operand);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Element info */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
/**
|
||||||
|
* Returns the actual type and size of an internal element-type.
|
||||||
|
*
|
||||||
|
* @param element The internal element type.
|
||||||
|
* @param type The actual element type.
|
||||||
|
* @param size The element size.
|
||||||
|
*/
|
||||||
|
ZYDIS_NO_EXPORT void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type,
|
||||||
|
ZydisElementSize* size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Accessed CPU flags */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef ZYDIS_MINIMAL_MODE
|
||||||
|
/**
|
||||||
|
* Returns the the operand-definitions for the given instruction-`definition`.
|
||||||
|
*
|
||||||
|
* @param definition A pointer to the instruction-definition.
|
||||||
|
* @param flags A pointer to the variable that receives the `ZydisAccessedFlags` struct.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_TRUE`, if the instruction accesses any flags, or `ZYAN_FALSE`, if not.
|
||||||
|
*/
|
||||||
|
ZYDIS_NO_EXPORT ZyanBool ZydisGetAccessedFlags(const ZydisInstructionDefinition* definition,
|
||||||
|
const ZydisAccessedFlags** flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_INTERNAL_SHAREDDATA_H */
|
@ -0,0 +1,464 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd, Joel Hoener
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Provides some internal, more performant, but unsafe helper functions for the `ZyanString`
|
||||||
|
* data-type.
|
||||||
|
*
|
||||||
|
* Most of these functions are very similar to the ones in `Zycore/String.h`, but inlined and
|
||||||
|
* without optional overhead like parameter-validation checks, etc ...
|
||||||
|
*
|
||||||
|
* The `ZyanString` data-type is able to dynamically allocate memory on the heap, but as `Zydis` is
|
||||||
|
* designed to be a non-'malloc'ing library, all functions in this file assume that the instances
|
||||||
|
* they are operating on are created with a user-defined static-buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_INTERNAL_STRING_H
|
||||||
|
#define ZYDIS_INTERNAL_STRING_H
|
||||||
|
|
||||||
|
#include <Zycore/LibC.h>
|
||||||
|
#include <Zycore/String.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
#include <Zycore/Format.h>
|
||||||
|
#include <Zydis/ShortString.h>
|
||||||
|
#include <Zydis/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Letter Case */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisLetterCase` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisLetterCase_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Uses the given text "as is".
|
||||||
|
*/
|
||||||
|
ZYDIS_LETTER_CASE_DEFAULT,
|
||||||
|
/**
|
||||||
|
* Converts the given text to lowercase letters.
|
||||||
|
*/
|
||||||
|
ZYDIS_LETTER_CASE_LOWER,
|
||||||
|
/**
|
||||||
|
* Converts the given text to uppercase letters.
|
||||||
|
*/
|
||||||
|
ZYDIS_LETTER_CASE_UPPER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_LETTER_CASE_MAX_VALUE = ZYDIS_LETTER_CASE_UPPER,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_LETTER_CASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_LETTER_CASE_MAX_VALUE)
|
||||||
|
} ZydisLetterCase;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Internal macros */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for a terminating '\0' character at the end of the string data.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STRING_ASSERT_NULLTERMINATION(string) \
|
||||||
|
ZYAN_ASSERT(*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) == '\0');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a terminating '\0' character at the end of the string data.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STRING_NULLTERMINATE(string) \
|
||||||
|
*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0';
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Internal Functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Appending */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the content of the source string to the end of the destination string.
|
||||||
|
*
|
||||||
|
* @param destination The destination string.
|
||||||
|
* @param source The source string.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanStatus ZydisStringAppend(ZyanString* destination, const ZyanStringView* source)
|
||||||
|
{
|
||||||
|
ZYAN_ASSERT(destination && source);
|
||||||
|
ZYAN_ASSERT(!destination->vector.allocator);
|
||||||
|
ZYAN_ASSERT(destination->vector.size && source->string.vector.size);
|
||||||
|
|
||||||
|
if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity)
|
||||||
|
{
|
||||||
|
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1,
|
||||||
|
source->string.vector.data, source->string.vector.size - 1);
|
||||||
|
|
||||||
|
destination->vector.size += source->string.vector.size - 1;
|
||||||
|
ZYDIS_STRING_NULLTERMINATE(destination);
|
||||||
|
|
||||||
|
return ZYAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the content of the source string to the end of the destination
|
||||||
|
* string, converting the characters to the specified letter-case.
|
||||||
|
*
|
||||||
|
* @param destination The destination string.
|
||||||
|
* @param source The source string.
|
||||||
|
* @param letter_case The desired letter-case.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanStatus ZydisStringAppendCase(ZyanString* destination, const ZyanStringView* source,
|
||||||
|
ZydisLetterCase letter_case)
|
||||||
|
{
|
||||||
|
ZYAN_ASSERT(destination && source);
|
||||||
|
ZYAN_ASSERT(!destination->vector.allocator);
|
||||||
|
ZYAN_ASSERT(destination->vector.size && source->string.vector.size);
|
||||||
|
|
||||||
|
if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity)
|
||||||
|
{
|
||||||
|
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1,
|
||||||
|
source->string.vector.data, source->string.vector.size - 1);
|
||||||
|
|
||||||
|
switch (letter_case)
|
||||||
|
{
|
||||||
|
case ZYDIS_LETTER_CASE_DEFAULT:
|
||||||
|
break;
|
||||||
|
case ZYDIS_LETTER_CASE_LOWER:
|
||||||
|
{
|
||||||
|
const ZyanUSize index = destination->vector.size - 1;
|
||||||
|
const ZyanUSize count = source->string.vector.size - 1;
|
||||||
|
char* s = (char*)destination->vector.data + index;
|
||||||
|
for (ZyanUSize i = index; i < index + count; ++i)
|
||||||
|
{
|
||||||
|
const char c = *s;
|
||||||
|
if ((c >= 'A') && (c <= 'Z'))
|
||||||
|
{
|
||||||
|
*s = c | 32;
|
||||||
|
}
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ZYDIS_LETTER_CASE_UPPER:
|
||||||
|
{
|
||||||
|
const ZyanUSize index = destination->vector.size - 1;
|
||||||
|
const ZyanUSize count = source->string.vector.size - 1;
|
||||||
|
char* s = (char*)destination->vector.data + index;
|
||||||
|
for (ZyanUSize i = index; i < index + count; ++i)
|
||||||
|
{
|
||||||
|
const char c = *s;
|
||||||
|
if ((c >= 'a') && (c <= 'z'))
|
||||||
|
{
|
||||||
|
*s = c & ~32;
|
||||||
|
}
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ZYAN_UNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
destination->vector.size += source->string.vector.size - 1;
|
||||||
|
ZYDIS_STRING_NULLTERMINATE(destination);
|
||||||
|
|
||||||
|
return ZYAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the content of the source short-string to the end of the destination string.
|
||||||
|
*
|
||||||
|
* @param destination The destination string.
|
||||||
|
* @param source The source string.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanStatus ZydisStringAppendShort(ZyanString* destination,
|
||||||
|
const ZydisShortString* source)
|
||||||
|
{
|
||||||
|
ZYAN_ASSERT(destination && source);
|
||||||
|
ZYAN_ASSERT(!destination->vector.allocator);
|
||||||
|
ZYAN_ASSERT(destination->vector.size && source->size);
|
||||||
|
|
||||||
|
if (destination->vector.size + source->size > destination->vector.capacity)
|
||||||
|
{
|
||||||
|
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data,
|
||||||
|
(ZyanUSize)source->size + 1);
|
||||||
|
|
||||||
|
destination->vector.size += source->size;
|
||||||
|
ZYDIS_STRING_ASSERT_NULLTERMINATION(destination);
|
||||||
|
|
||||||
|
return ZYAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the content of the source short-string to the end of the destination string,
|
||||||
|
* converting the characters to the specified letter-case.
|
||||||
|
*
|
||||||
|
* @param destination The destination string.
|
||||||
|
* @param source The source string.
|
||||||
|
* @param letter_case The desired letter-case.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanStatus ZydisStringAppendShortCase(ZyanString* destination,
|
||||||
|
const ZydisShortString* source, ZydisLetterCase letter_case)
|
||||||
|
{
|
||||||
|
ZYAN_ASSERT(destination && source);
|
||||||
|
ZYAN_ASSERT(!destination->vector.allocator);
|
||||||
|
ZYAN_ASSERT(destination->vector.size && source->size);
|
||||||
|
|
||||||
|
if (destination->vector.size + source->size > destination->vector.capacity)
|
||||||
|
{
|
||||||
|
return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data,
|
||||||
|
(ZyanUSize)source->size + 1);
|
||||||
|
|
||||||
|
switch (letter_case)
|
||||||
|
{
|
||||||
|
case ZYDIS_LETTER_CASE_DEFAULT:
|
||||||
|
break;
|
||||||
|
case ZYDIS_LETTER_CASE_LOWER:
|
||||||
|
{
|
||||||
|
const ZyanUSize index = destination->vector.size - 1;
|
||||||
|
const ZyanUSize count = source->size;
|
||||||
|
char* s = (char*)destination->vector.data + index;
|
||||||
|
for (ZyanUSize i = index; i < index + count; ++i)
|
||||||
|
{
|
||||||
|
const char c = *s;
|
||||||
|
if ((c >= 'A') && (c <= 'Z'))
|
||||||
|
{
|
||||||
|
*s = c | 32;
|
||||||
|
}
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ZYDIS_LETTER_CASE_UPPER:
|
||||||
|
{
|
||||||
|
const ZyanUSize index = destination->vector.size - 1;
|
||||||
|
const ZyanUSize count = source->size;
|
||||||
|
char* s = (char*)destination->vector.data + index;
|
||||||
|
for (ZyanUSize i = index; i < index + count; ++i)
|
||||||
|
{
|
||||||
|
const char c = *s;
|
||||||
|
if ((c >= 'a') && (c <= 'z'))
|
||||||
|
{
|
||||||
|
*s = c & ~32;
|
||||||
|
}
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ZYAN_UNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
destination->vector.size += source->size;
|
||||||
|
ZYDIS_STRING_ASSERT_NULLTERMINATION(destination);
|
||||||
|
|
||||||
|
return ZYAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Formatting */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given unsigned ordinal `value` to its decimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||||
|
* @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZyanStatus ZydisStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
|
||||||
|
const ZyanStringView* prefix, const ZyanStringView* suffix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given signed ordinal `value` to its decimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers.
|
||||||
|
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||||
|
* @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanStatus ZydisStringAppendDecS(ZyanString* string, ZyanI64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix,
|
||||||
|
const ZyanStringView* suffix)
|
||||||
|
{
|
||||||
|
static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+");
|
||||||
|
static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-");
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub));
|
||||||
|
if (prefix)
|
||||||
|
{
|
||||||
|
ZYAN_CHECK(ZydisStringAppend(string, prefix));
|
||||||
|
}
|
||||||
|
return ZydisStringAppendDecU(string, ZyanAbsI64(value), padding_length,
|
||||||
|
(const ZyanStringView*)ZYAN_NULL, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force_sign)
|
||||||
|
{
|
||||||
|
ZYAN_ASSERT(value >= 0);
|
||||||
|
ZYAN_CHECK(ZydisStringAppendShort(string, &str_add));
|
||||||
|
}
|
||||||
|
return ZydisStringAppendDecU(string, value, padding_length, prefix, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given unsigned ordinal `value` to its hexadecimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the `ZyanString` instance.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length`.
|
||||||
|
* @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase
|
||||||
|
* ones ('a'-'f').
|
||||||
|
* @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed.
|
||||||
|
* @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
|
||||||
|
* `ZyanString` instance.
|
||||||
|
*/
|
||||||
|
ZyanStatus ZydisStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
|
||||||
|
ZyanBool uppercase, const ZyanStringView* prefix, const ZyanStringView* suffix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given signed ordinal `value` to its hexadecimal text-representation and
|
||||||
|
* appends it to the `string`.
|
||||||
|
*
|
||||||
|
* @param string A pointer to the string.
|
||||||
|
* @param value The value.
|
||||||
|
* @param padding_length Padds the converted value with leading zeros, if the number of chars is
|
||||||
|
* less than the `padding_length` (the sign char is ignored).
|
||||||
|
* @param uppercase Set `ZYAN_TRUE` to print the hexadecimal value in uppercase letters
|
||||||
|
* instead of lowercase ones.
|
||||||
|
* @param force_sign Set to `ZYAN_TRUE`, to force printing of the `+` sign for positive
|
||||||
|
* numbers.
|
||||||
|
* @param prefix The string to use as prefix or `NULL`, if not needed.
|
||||||
|
* @param suffix The string to use as suffix or `NULL`, if not needed.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_SUCCESS`, if the function succeeded, or
|
||||||
|
* `ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE`, if the size of the buffer was not
|
||||||
|
* sufficient to append the given `value`.
|
||||||
|
*
|
||||||
|
* The string-buffer pointer is increased by the number of chars written, if the call was
|
||||||
|
* successful.
|
||||||
|
*/
|
||||||
|
ZYAN_INLINE ZyanStatus ZydisStringAppendHexS(ZyanString* string, ZyanI64 value,
|
||||||
|
ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix,
|
||||||
|
const ZyanStringView* suffix)
|
||||||
|
{
|
||||||
|
static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+");
|
||||||
|
static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-");
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
{
|
||||||
|
ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub));
|
||||||
|
if (prefix)
|
||||||
|
{
|
||||||
|
ZYAN_CHECK(ZydisStringAppend(string, prefix));
|
||||||
|
}
|
||||||
|
return ZydisStringAppendHexU(string, ZyanAbsI64(value), padding_length, uppercase,
|
||||||
|
(const ZyanStringView*)ZYAN_NULL, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force_sign)
|
||||||
|
{
|
||||||
|
ZYAN_ASSERT(value >= 0);
|
||||||
|
ZYAN_CHECK(ZydisStringAppendShort(string, &str_add));
|
||||||
|
}
|
||||||
|
return ZydisStringAppendHexU(string, value, padding_length, uppercase, prefix, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ZYDIS_INTERNAL_STRING_H
|
@ -0,0 +1,88 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_METAINFO_H
|
||||||
|
#define ZYDIS_METAINFO_H
|
||||||
|
|
||||||
|
#include <ZydisExportConfig.h>
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#include <Zydis/Generated/EnumInstructionCategory.h>
|
||||||
|
#include <Zydis/Generated/EnumISASet.h>
|
||||||
|
#include <Zydis/Generated/EnumISAExt.h>
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified instruction category string.
|
||||||
|
*
|
||||||
|
* @param category The instruction category.
|
||||||
|
*
|
||||||
|
* @return The instruction category string or `ZYAN_NULL`, if an invalid category was passed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT const char* ZydisCategoryGetString(ZydisInstructionCategory category);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified isa-set string.
|
||||||
|
*
|
||||||
|
* @param isa_set The isa-set.
|
||||||
|
*
|
||||||
|
* @return The isa-set string or `ZYAN_NULL`, if an invalid isa-set was passed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT const char* ZydisISASetGetString(ZydisISASet isa_set);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified isa-extension string.
|
||||||
|
*
|
||||||
|
* @param isa_ext The isa-extension.
|
||||||
|
*
|
||||||
|
* @return The isa-extension string or `ZYAN_NULL`, if an invalid isa-extension was passed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT const char* ZydisISAExtGetString(ZydisISAExt isa_ext);
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_METAINFO_H */
|
@ -0,0 +1,88 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Mnemonic constant definitions and helper functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_MNEMONIC_H
|
||||||
|
#define ZYDIS_MNEMONIC_H
|
||||||
|
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
#include <Zydis/ShortString.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#include <Zydis/Generated/EnumMnemonic.h>
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup mnemonic Mnemonic
|
||||||
|
* Functions for retrieving mnemonic names.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified instruction mnemonic string.
|
||||||
|
*
|
||||||
|
* @param mnemonic The mnemonic.
|
||||||
|
*
|
||||||
|
* @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified instruction mnemonic as `ZydisShortString`.
|
||||||
|
*
|
||||||
|
* @param mnemonic The mnemonic.
|
||||||
|
*
|
||||||
|
* @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed.
|
||||||
|
*
|
||||||
|
* The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT const ZydisShortString* ZydisMnemonicGetStringWrapped(ZydisMnemonic mnemonic);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_MNEMONIC_H */
|
@ -0,0 +1,293 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Utility functions and constants for registers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_REGISTER_H
|
||||||
|
#define ZYDIS_REGISTER_H
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
#include <Zydis/SharedTypes.h>
|
||||||
|
#include <Zydis/ShortString.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Registers */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <Zydis/Generated/EnumRegister.h>
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Register classes */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisRegisterClass` enum.
|
||||||
|
*
|
||||||
|
* Please note that this enum does not contain a matching entry for all values of the
|
||||||
|
* `ZydisRegister` enum, but only for those registers where it makes sense to logically group them
|
||||||
|
* for decoding/encoding purposes.
|
||||||
|
*
|
||||||
|
* These are mainly the registers that can be identified by an id within their corresponding
|
||||||
|
* register-class. The `IP` and `FLAGS` values are exceptions to this rule.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisRegisterClass_
|
||||||
|
{
|
||||||
|
ZYDIS_REGCLASS_INVALID,
|
||||||
|
/**
|
||||||
|
* 8-bit general-purpose registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_GPR8,
|
||||||
|
/**
|
||||||
|
* 16-bit general-purpose registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_GPR16,
|
||||||
|
/**
|
||||||
|
* 32-bit general-purpose registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_GPR32,
|
||||||
|
/**
|
||||||
|
* 64-bit general-purpose registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_GPR64,
|
||||||
|
/**
|
||||||
|
* Floating point legacy registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_X87,
|
||||||
|
/**
|
||||||
|
* Floating point multimedia registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_MMX,
|
||||||
|
/**
|
||||||
|
* 128-bit vector registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_XMM,
|
||||||
|
/**
|
||||||
|
* 256-bit vector registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_YMM,
|
||||||
|
/**
|
||||||
|
* 512-bit vector registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_ZMM,
|
||||||
|
/**
|
||||||
|
* Matrix registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_TMM,
|
||||||
|
/*
|
||||||
|
* Flags registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_FLAGS,
|
||||||
|
/**
|
||||||
|
* Instruction-pointer registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_IP,
|
||||||
|
/**
|
||||||
|
* Segment registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_SEGMENT,
|
||||||
|
/**
|
||||||
|
* Test registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_TEST,
|
||||||
|
/**
|
||||||
|
* Control registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_CONTROL,
|
||||||
|
/**
|
||||||
|
* Debug registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_DEBUG,
|
||||||
|
/**
|
||||||
|
* Mask registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_MASK,
|
||||||
|
/**
|
||||||
|
* Bound registers.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_BOUND,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_MAX_VALUE = ZYDIS_REGCLASS_BOUND,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_REGCLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGCLASS_MAX_VALUE)
|
||||||
|
} ZydisRegisterClass;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Register width */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisRegisterWidth` data-type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU16 ZydisRegisterWidth;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Register context */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisRegisterContext` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisRegisterContext_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The values stored in the register context.
|
||||||
|
*/
|
||||||
|
ZyanU64 values[ZYDIS_REGISTER_MAX_VALUE + 1];
|
||||||
|
} ZydisRegisterContext;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup register Register
|
||||||
|
* Functions allowing retrieval of information about registers.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Register */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the register specified by the `register_class` and `id` tuple.
|
||||||
|
*
|
||||||
|
* @param register_class The register class.
|
||||||
|
* @param id The register id.
|
||||||
|
*
|
||||||
|
* @return The register specified by the `register_class` and `id` tuple or `ZYDIS_REGISTER_NONE`,
|
||||||
|
* if an invalid parameter was passed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the specified register.
|
||||||
|
*
|
||||||
|
* @param reg The register.
|
||||||
|
*
|
||||||
|
* @return The id of the specified register, or -1 if an invalid parameter was passed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanI8 ZydisRegisterGetId(ZydisRegister reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the register-class of the specified register.
|
||||||
|
*
|
||||||
|
* @param reg The register.
|
||||||
|
*
|
||||||
|
* @return The register-class of the specified register.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the width of the specified register.
|
||||||
|
*
|
||||||
|
* @param mode The active machine mode.
|
||||||
|
* @param reg The register.
|
||||||
|
*
|
||||||
|
* @return The width of the specified register, or `ZYDIS_REGISTER_NONE` if the register is
|
||||||
|
* invalid for the active machine-mode.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the largest enclosing register of the given register.
|
||||||
|
*
|
||||||
|
* @param mode The active machine mode.
|
||||||
|
* @param reg The register.
|
||||||
|
*
|
||||||
|
* @return The largest enclosing register of the given register, or `ZYDIS_REGISTER_NONE` if the
|
||||||
|
* register is invalid for the active machine-mode or does not have an enclosing-register.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode,
|
||||||
|
ZydisRegister reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified register string.
|
||||||
|
*
|
||||||
|
* @param reg The register.
|
||||||
|
*
|
||||||
|
* @return The register string or `ZYAN_NULL`, if an invalid register was passed.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified register string as `ZydisShortString`.
|
||||||
|
*
|
||||||
|
* @param reg The register.
|
||||||
|
*
|
||||||
|
* @return The register string or `ZYAN_NULL`, if an invalid register was passed.
|
||||||
|
*
|
||||||
|
* The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Register class */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the width of the specified register-class.
|
||||||
|
*
|
||||||
|
* @param mode The active machine mode.
|
||||||
|
* @param register_class The register class.
|
||||||
|
*
|
||||||
|
* @return The width of the specified register.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode,
|
||||||
|
ZydisRegisterClass register_class);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_REGISTER_H */
|
@ -0,0 +1,480 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Defines decoder/encoder-shared macros and types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_SHAREDTYPES_H
|
||||||
|
#define ZYDIS_SHAREDTYPES_H
|
||||||
|
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Constants */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define ZYDIS_MAX_INSTRUCTION_LENGTH 15
|
||||||
|
#define ZYDIS_MAX_OPERAND_COUNT 10
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Machine mode */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisMachineMode` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisMachineMode_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 64 bit mode.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_LONG_64,
|
||||||
|
/**
|
||||||
|
* 32 bit protected mode.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_LONG_COMPAT_32,
|
||||||
|
/**
|
||||||
|
* 16 bit protected mode.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_LONG_COMPAT_16,
|
||||||
|
/**
|
||||||
|
* 32 bit protected mode.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_LEGACY_32,
|
||||||
|
/**
|
||||||
|
* 16 bit protected mode.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_LEGACY_16,
|
||||||
|
/**
|
||||||
|
* 16 bit real mode.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_REAL_16,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_MAX_VALUE = ZYDIS_MACHINE_MODE_REAL_16,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_MACHINE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MACHINE_MODE_MAX_VALUE)
|
||||||
|
} ZydisMachineMode;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Address width */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisAddressWidth` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisAddressWidth_
|
||||||
|
{
|
||||||
|
ZYDIS_ADDRESS_WIDTH_16,
|
||||||
|
ZYDIS_ADDRESS_WIDTH_32,
|
||||||
|
ZYDIS_ADDRESS_WIDTH_64,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ADDRESS_WIDTH_MAX_VALUE = ZYDIS_ADDRESS_WIDTH_64,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ADDRESS_WIDTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ADDRESS_WIDTH_MAX_VALUE)
|
||||||
|
} ZydisAddressWidth;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Element type */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisElementType` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisElementType_
|
||||||
|
{
|
||||||
|
ZYDIS_ELEMENT_TYPE_INVALID,
|
||||||
|
/**
|
||||||
|
* A struct type.
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_STRUCT,
|
||||||
|
/**
|
||||||
|
* Unsigned integer value.
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_UINT,
|
||||||
|
/**
|
||||||
|
* Signed integer value.
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_INT,
|
||||||
|
/**
|
||||||
|
* 16-bit floating point value (`half`).
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_FLOAT16,
|
||||||
|
/**
|
||||||
|
* 32-bit floating point value (`single`).
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_FLOAT32,
|
||||||
|
/**
|
||||||
|
* 64-bit floating point value (`double`).
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_FLOAT64,
|
||||||
|
/**
|
||||||
|
* 80-bit floating point value (`extended`).
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_FLOAT80,
|
||||||
|
/**
|
||||||
|
* Binary coded decimal value.
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_LONGBCD,
|
||||||
|
/**
|
||||||
|
* A condition code (e.g. used by `CMPPD`, `VCMPPD`, ...).
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_CC,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_MAX_VALUE = ZYDIS_ELEMENT_TYPE_CC,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_ELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ELEMENT_TYPE_MAX_VALUE)
|
||||||
|
} ZydisElementType;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Element size */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisElementSize` datatype.
|
||||||
|
*/
|
||||||
|
typedef ZyanU16 ZydisElementSize;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operand type */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisOperandType` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisOperandType_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The operand is not used.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_TYPE_UNUSED,
|
||||||
|
/**
|
||||||
|
* The operand is a register operand.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_TYPE_REGISTER,
|
||||||
|
/**
|
||||||
|
* The operand is a memory operand.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_TYPE_MEMORY,
|
||||||
|
/**
|
||||||
|
* The operand is a pointer operand with a segment:offset lvalue.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_TYPE_POINTER,
|
||||||
|
/**
|
||||||
|
* The operand is an immediate operand.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_TYPE_IMMEDIATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_TYPE_MAX_VALUE = ZYDIS_OPERAND_TYPE_IMMEDIATE,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_TYPE_MAX_VALUE)
|
||||||
|
} ZydisOperandType;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operand encoding */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisOperandEncoding` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisOperandEncoding_
|
||||||
|
{
|
||||||
|
ZYDIS_OPERAND_ENCODING_NONE,
|
||||||
|
ZYDIS_OPERAND_ENCODING_MODRM_REG,
|
||||||
|
ZYDIS_OPERAND_ENCODING_MODRM_RM,
|
||||||
|
ZYDIS_OPERAND_ENCODING_OPCODE,
|
||||||
|
ZYDIS_OPERAND_ENCODING_NDSNDD,
|
||||||
|
ZYDIS_OPERAND_ENCODING_IS4,
|
||||||
|
ZYDIS_OPERAND_ENCODING_MASK,
|
||||||
|
ZYDIS_OPERAND_ENCODING_DISP8,
|
||||||
|
ZYDIS_OPERAND_ENCODING_DISP16,
|
||||||
|
ZYDIS_OPERAND_ENCODING_DISP32,
|
||||||
|
ZYDIS_OPERAND_ENCODING_DISP64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_DISP16_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_DISP32_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_DISP16_32_32,
|
||||||
|
ZYDIS_OPERAND_ENCODING_UIMM8,
|
||||||
|
ZYDIS_OPERAND_ENCODING_UIMM16,
|
||||||
|
ZYDIS_OPERAND_ENCODING_UIMM32,
|
||||||
|
ZYDIS_OPERAND_ENCODING_UIMM64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_UIMM16_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_UIMM32_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_UIMM16_32_32,
|
||||||
|
ZYDIS_OPERAND_ENCODING_SIMM8,
|
||||||
|
ZYDIS_OPERAND_ENCODING_SIMM16,
|
||||||
|
ZYDIS_OPERAND_ENCODING_SIMM32,
|
||||||
|
ZYDIS_OPERAND_ENCODING_SIMM64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_SIMM16_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_SIMM32_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_SIMM16_32_32,
|
||||||
|
ZYDIS_OPERAND_ENCODING_JIMM8,
|
||||||
|
ZYDIS_OPERAND_ENCODING_JIMM16,
|
||||||
|
ZYDIS_OPERAND_ENCODING_JIMM32,
|
||||||
|
ZYDIS_OPERAND_ENCODING_JIMM64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_JIMM16_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_JIMM32_32_64,
|
||||||
|
ZYDIS_OPERAND_ENCODING_JIMM16_32_32,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ENCODING_MAX_VALUE = ZYDIS_OPERAND_ENCODING_JIMM16_32_32,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ENCODING_MAX_VALUE)
|
||||||
|
} ZydisOperandEncoding;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operand visibility */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisOperandVisibility` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisOperandVisibility_
|
||||||
|
{
|
||||||
|
ZYDIS_OPERAND_VISIBILITY_INVALID,
|
||||||
|
/**
|
||||||
|
* The operand is explicitly encoded in the instruction.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_VISIBILITY_EXPLICIT,
|
||||||
|
/**
|
||||||
|
* The operand is part of the opcode, but listed as an operand.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_VISIBILITY_IMPLICIT,
|
||||||
|
/**
|
||||||
|
* The operand is part of the opcode, and not typically listed as an operand.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_VISIBILITY_HIDDEN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_VISIBILITY_MAX_VALUE = ZYDIS_OPERAND_VISIBILITY_HIDDEN,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS =
|
||||||
|
ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_VISIBILITY_MAX_VALUE)
|
||||||
|
} ZydisOperandVisibility;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Operand action */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisOperandAction` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisOperandAction_
|
||||||
|
{
|
||||||
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
/* Elemental actions */
|
||||||
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operand is read by the instruction.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_READ = 0x01,
|
||||||
|
/**
|
||||||
|
* The operand is written by the instruction (must write).
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_WRITE = 0x02,
|
||||||
|
/**
|
||||||
|
* The operand is conditionally read by the instruction.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_CONDREAD = 0x04,
|
||||||
|
/**
|
||||||
|
* The operand is conditionally written by the instruction (may write).
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_CONDWRITE = 0x08,
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
/* Combined actions */
|
||||||
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The operand is read (must read) and written by the instruction (must write).
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_READWRITE = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_WRITE,
|
||||||
|
/**
|
||||||
|
* The operand is conditionally read (may read) and conditionally written by
|
||||||
|
* the instruction (may write).
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_CONDREAD_CONDWRITE =
|
||||||
|
ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_CONDWRITE,
|
||||||
|
/**
|
||||||
|
* The operand is read (must read) and conditionally written by the
|
||||||
|
* instruction (may write).
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_READ_CONDWRITE =
|
||||||
|
ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDWRITE,
|
||||||
|
/**
|
||||||
|
* The operand is written (must write) and conditionally read by the
|
||||||
|
* instruction (may read).
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_CONDREAD_WRITE =
|
||||||
|
ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_WRITE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mask combining all reading access flags.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_MASK_READ = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDREAD,
|
||||||
|
/**
|
||||||
|
* Mask combining all writing access flags.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_MASK_WRITE = ZYDIS_OPERAND_ACTION_WRITE | ZYDIS_OPERAND_ACTION_CONDWRITE,
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this bitset.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPERAND_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ACTION_CONDWRITE)
|
||||||
|
} ZydisOperandAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisOperandActions` data-type.
|
||||||
|
*/
|
||||||
|
typedef ZyanU8 ZydisOperandActions;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Instruction encoding */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionEncoding` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisInstructionEncoding_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The instruction uses the legacy encoding.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_LEGACY,
|
||||||
|
/**
|
||||||
|
* The instruction uses the AMD 3DNow-encoding.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_3DNOW,
|
||||||
|
/**
|
||||||
|
* The instruction uses the AMD XOP-encoding.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_XOP,
|
||||||
|
/**
|
||||||
|
* The instruction uses the VEX-encoding.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_VEX,
|
||||||
|
/**
|
||||||
|
* The instruction uses the EVEX-encoding.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_EVEX,
|
||||||
|
/**
|
||||||
|
* The instruction uses the MVEX-encoding.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_MVEX,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE = ZYDIS_INSTRUCTION_ENCODING_MVEX,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTRUCTION_ENCODING_REQUIRED_BITS =
|
||||||
|
ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE)
|
||||||
|
} ZydisInstructionEncoding;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Opcode map */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisOpcodeMap` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisOpcodeMap_
|
||||||
|
{
|
||||||
|
ZYDIS_OPCODE_MAP_DEFAULT,
|
||||||
|
ZYDIS_OPCODE_MAP_0F,
|
||||||
|
ZYDIS_OPCODE_MAP_0F38,
|
||||||
|
ZYDIS_OPCODE_MAP_0F3A,
|
||||||
|
ZYDIS_OPCODE_MAP_0F0F,
|
||||||
|
ZYDIS_OPCODE_MAP_XOP8,
|
||||||
|
ZYDIS_OPCODE_MAP_XOP9,
|
||||||
|
ZYDIS_OPCODE_MAP_XOPA,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPCODE_MAP_MAX_VALUE = ZYDIS_OPCODE_MAP_XOPA,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_OPCODE_MAP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPCODE_MAP_MAX_VALUE)
|
||||||
|
} ZydisOpcodeMap;
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_SHAREDTYPES_H */
|
@ -0,0 +1,90 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Defines the immutable and storage-efficient `ZydisShortString` struct, which
|
||||||
|
* is used to store strings in the generated tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_SHORTSTRING_H
|
||||||
|
#define ZYDIS_SHORTSTRING_H
|
||||||
|
|
||||||
|
#include <ZydisExportConfig.h>
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisShortString` struct.
|
||||||
|
*
|
||||||
|
* This compact struct is mainly used for internal string-tables to save up some bytes.
|
||||||
|
*
|
||||||
|
* All fields in this struct should be considered as "private". Any changes may lead to unexpected
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisShortString_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The buffer that contains the actual (null-terminated) string.
|
||||||
|
*/
|
||||||
|
const char* data;
|
||||||
|
/**
|
||||||
|
* The length (number of characters) of the string (without 0-termination).
|
||||||
|
*/
|
||||||
|
ZyanU8 size;
|
||||||
|
} ZydisShortString;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a `ZydisShortString` from a static C-style string.
|
||||||
|
*
|
||||||
|
* @param string The C-string constant.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_MAKE_SHORTSTRING(string) \
|
||||||
|
{ string, sizeof(string) - 1 }
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_SHORTSTRING_H */
|
@ -0,0 +1,159 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Status code definitions and check macros.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_STATUS_H
|
||||||
|
#define ZYDIS_STATUS_H
|
||||||
|
|
||||||
|
#include <Zycore/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Status codes */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Module IDs */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The zydis module id.
|
||||||
|
*/
|
||||||
|
#define ZYAN_MODULE_ZYDIS 0x002u
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Status codes */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Decoder */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An attempt was made to read data from an input data-source that has no more
|
||||||
|
* data available.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_NO_MORE_DATA \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x00u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An general error occured while decoding the current instruction. The
|
||||||
|
* instruction might be undefined.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_DECODING_ERROR \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x01u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instruction exceeded the maximum length of 15 bytes.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_INSTRUCTION_TOO_LONG \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x02u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instruction encoded an invalid register.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_BAD_REGISTER \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x03u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A lock-prefix (F0) was found while decoding an instruction that does not
|
||||||
|
* support locking.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_ILLEGAL_LOCK \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x04u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A legacy-prefix (F2, F3, 66) was found while decoding a XOP/VEX/EVEX/MVEX
|
||||||
|
* instruction.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_ILLEGAL_LEGACY_PFX \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x05u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A rex-prefix was found while decoding a XOP/VEX/EVEX/MVEX instruction.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_ILLEGAL_REX \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x06u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An invalid opcode-map value was found while decoding a XOP/VEX/EVEX/MVEX-prefix.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_INVALID_MAP \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x07u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An error occured while decoding the EVEX-prefix.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_MALFORMED_EVEX \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x08u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An error occured while decoding the MVEX-prefix.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_MALFORMED_MVEX \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x09u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An invalid write-mask was specified for an EVEX/MVEX instruction.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_INVALID_MASK \
|
||||||
|
ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x0Au)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Formatter */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returning this status code in some specified formatter callbacks will cause
|
||||||
|
* the formatter to omit the corresponding token.
|
||||||
|
*
|
||||||
|
* Valid callbacks:
|
||||||
|
* - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND`
|
||||||
|
* - `ZYDIS_FORMATTER_FUNC_POST_OPERAND`
|
||||||
|
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG`
|
||||||
|
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM`
|
||||||
|
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR`
|
||||||
|
* - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM`
|
||||||
|
*/
|
||||||
|
#define ZYDIS_STATUS_SKIP_TOKEN \
|
||||||
|
ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYDIS, 0x0Bu)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_STATUS_H */
|
@ -0,0 +1,275 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Other utility functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_UTILS_H
|
||||||
|
#define ZYDIS_UTILS_H
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zydis/DecoderTypes.h>
|
||||||
|
#include <Zydis/Status.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Constants */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT 9
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionSegment` struct.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisInstructionSegment_
|
||||||
|
{
|
||||||
|
ZYDIS_INSTR_SEGMENT_NONE,
|
||||||
|
/**
|
||||||
|
* The legacy prefixes (including ignored `REX` prefixes).
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_PREFIXES,
|
||||||
|
/**
|
||||||
|
* The effective `REX` prefix byte.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_REX,
|
||||||
|
/**
|
||||||
|
* The `XOP` prefix bytes.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_XOP,
|
||||||
|
/**
|
||||||
|
* The `VEX` prefix bytes.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_VEX,
|
||||||
|
/**
|
||||||
|
* The `EVEX` prefix bytes.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_EVEX,
|
||||||
|
/**
|
||||||
|
* The `MVEX` prefix bytes.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_MVEX,
|
||||||
|
/**
|
||||||
|
* The opcode bytes.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_OPCODE,
|
||||||
|
/**
|
||||||
|
* The `ModRM` byte.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_MODRM,
|
||||||
|
/**
|
||||||
|
* The `SIB` byte.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_SIB,
|
||||||
|
/**
|
||||||
|
* The displacement bytes.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_DISPLACEMENT,
|
||||||
|
/**
|
||||||
|
* The immediate bytes.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_IMMEDIATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_MAX_VALUE = ZYDIS_INSTR_SEGMENT_IMMEDIATE,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_INSTR_SEGMENT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTR_SEGMENT_MAX_VALUE)
|
||||||
|
} ZydisInstructionSegment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisInstructionSegments` struct.
|
||||||
|
*/
|
||||||
|
typedef struct ZydisInstructionSegments_
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The number of logical instruction segments.
|
||||||
|
*/
|
||||||
|
ZyanU8 count;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The type of the segment.
|
||||||
|
*/
|
||||||
|
ZydisInstructionSegment type;
|
||||||
|
/**
|
||||||
|
* The offset of the segment relative to the start of the instruction (in bytes).
|
||||||
|
*/
|
||||||
|
ZyanU8 offset;
|
||||||
|
/**
|
||||||
|
* The size of the segment, in bytes.
|
||||||
|
*/
|
||||||
|
ZyanU8 size;
|
||||||
|
} segments[ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT];
|
||||||
|
} ZydisInstructionSegments;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup utils Utils
|
||||||
|
* Miscellaneous utility functions. Address translation and other helpers.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Address calculation */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// TODO: Provide a function that works in minimal-mode and does not require a operand parameter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the absolute address value for the given instruction operand.
|
||||||
|
*
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param operand A pointer to the `ZydisDecodedOperand` struct.
|
||||||
|
* @param runtime_address The runtime address of the instruction.
|
||||||
|
* @param result_address A pointer to the memory that receives the absolute address.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* You should use this function in the following cases:
|
||||||
|
* - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...)
|
||||||
|
* - `MEM` operands with `RIP`/`EIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`)
|
||||||
|
* - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`)
|
||||||
|
* - The displacement needs to get truncated and zero extended
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction,
|
||||||
|
const ZydisDecodedOperand* operand, ZyanU64 runtime_address, ZyanU64* result_address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the absolute address value for the given instruction operand.
|
||||||
|
*
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param operand A pointer to the `ZydisDecodedOperand` struct.
|
||||||
|
* @param runtime_address The runtime address of the instruction.
|
||||||
|
* @param register_context A pointer to the `ZydisRegisterContext` struct.
|
||||||
|
* @param result_address A pointer to the memory that receives the absolute target-address.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*
|
||||||
|
* This function behaves like `ZydisCalcAbsoluteAddress` but takes an additional register-context
|
||||||
|
* argument to allow calculation of addresses depending on runtime register values.
|
||||||
|
*
|
||||||
|
* Note that `IP/EIP/RIP` from the register-context will be ignored in favor of the passed
|
||||||
|
* runtime-address.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction,
|
||||||
|
const ZydisDecodedOperand* operand, ZyanU64 runtime_address,
|
||||||
|
const ZydisRegisterContext* register_context, ZyanU64* result_address);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Accessed CPU flags */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mask of accessed CPU-flags matching the given `action`.
|
||||||
|
*
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param action The CPU-flag action.
|
||||||
|
* @param flags Receives the flag mask.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisGetAccessedFlagsByAction(const ZydisDecodedInstruction* instruction,
|
||||||
|
ZydisCPUFlagAction action, ZydisCPUFlags* flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mask of accessed CPU-flags that are read (tested) by the current instruction.
|
||||||
|
*
|
||||||
|
* DEPRECATED. This function will be removed in the next major release. Please refer to the
|
||||||
|
* `cpu_flags_read` or `fpu_flags_read` fields of the `ZydisDecodedInstruction` instead.
|
||||||
|
*
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param flags Receives the flag mask.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsRead(
|
||||||
|
const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mask of accessed CPU-flags that are written (modified, undefined) by the current
|
||||||
|
* instruction.
|
||||||
|
*
|
||||||
|
* DEPRECATED. This function will be removed in the next major release. Please refer to the
|
||||||
|
* `cpu_flags_written` or `fpu_flags_written` fields of the `ZydisDecodedInstruction` instead.
|
||||||
|
*
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param flags Receives the flag mask.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsWritten(
|
||||||
|
const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Instruction segments */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns offsets and sizes of all logical instruction segments (e.g. `OPCODE`,
|
||||||
|
* `MODRM`, ...).
|
||||||
|
*
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param segments Receives the instruction segments information.
|
||||||
|
*
|
||||||
|
* @return A zyan status code.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction,
|
||||||
|
ZydisInstructionSegments* segments);
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_UTILS_H */
|
@ -0,0 +1,169 @@
|
|||||||
|
/***************************************************************************************************
|
||||||
|
|
||||||
|
Zyan Disassembler Library (Zydis)
|
||||||
|
|
||||||
|
Original Author : Florian Bernd
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
|
||||||
|
***************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Master include file, including everything else.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZYDIS_H
|
||||||
|
#define ZYDIS_H
|
||||||
|
|
||||||
|
#include <Zycore/Defines.h>
|
||||||
|
#include <Zycore/Types.h>
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DISABLE_DECODER
|
||||||
|
# include <Zydis/Decoder.h>
|
||||||
|
# include <Zydis/DecoderTypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DISABLE_FORMATTER
|
||||||
|
# include <Zydis/Formatter.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Zydis/MetaInfo.h>
|
||||||
|
#include <Zydis/Mnemonic.h>
|
||||||
|
#include <Zydis/Register.h>
|
||||||
|
#include <Zydis/SharedTypes.h>
|
||||||
|
#include <Zydis/Status.h>
|
||||||
|
#include <Zydis/Utils.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Macros */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Constants */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro that defines the zydis version.
|
||||||
|
*/
|
||||||
|
#define ZYDIS_VERSION (ZyanU64)0x0003000100000000
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* Helper macros */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the major-part of the zydis version.
|
||||||
|
*
|
||||||
|
* @param version The zydis version value
|
||||||
|
*/
|
||||||
|
#define ZYDIS_VERSION_MAJOR(version_t) (ZyanU16)(((version_t) & 0xFFFF000000000000) >> 48)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the minor-part of the zydis version.
|
||||||
|
*
|
||||||
|
* @param version The zydis version value
|
||||||
|
*/
|
||||||
|
#define ZYDIS_VERSION_MINOR(version_t) (ZyanU16)(((version_t) & 0x0000FFFF00000000) >> 32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the patch-part of the zydis version.
|
||||||
|
*
|
||||||
|
* @param version The zydis version value
|
||||||
|
*/
|
||||||
|
#define ZYDIS_VERSION_PATCH(version_t) (ZyanU16)(((version_t) & 0x00000000FFFF0000) >> 16)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the build-part of the zydis version.
|
||||||
|
*
|
||||||
|
* @param version The zydis version value
|
||||||
|
*/
|
||||||
|
#define ZYDIS_VERSION_BUILD(version_t) (ZyanU16)((version_t) & 0x000000000000FFFF)
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Enums and types */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the `ZydisFeature` enum.
|
||||||
|
*/
|
||||||
|
typedef enum ZydisFeature_
|
||||||
|
{
|
||||||
|
ZYDIS_FEATURE_DECODER,
|
||||||
|
ZYDIS_FEATURE_FORMATTER,
|
||||||
|
ZYDIS_FEATURE_AVX512,
|
||||||
|
ZYDIS_FEATURE_KNC,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_FEATURE_MAX_VALUE = ZYDIS_FEATURE_KNC,
|
||||||
|
/**
|
||||||
|
* The minimum number of bits required to represent all values of this enum.
|
||||||
|
*/
|
||||||
|
ZYDIS_FEATURE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FEATURE_MAX_VALUE)
|
||||||
|
} ZydisFeature;
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
/* Exported functions */
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup version Version
|
||||||
|
* Functions for checking the library version and build options.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the zydis version.
|
||||||
|
*
|
||||||
|
* @return The zydis version.
|
||||||
|
*
|
||||||
|
* Use the macros provided in this file to extract the major, minor, patch and build part from the
|
||||||
|
* returned version value.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanU64 ZydisGetVersion(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if the specified feature is enabled in the current zydis library instance.
|
||||||
|
*
|
||||||
|
* @param feature The feature.
|
||||||
|
*
|
||||||
|
* @return `ZYAN_STATUS_TRUE` if the feature is enabled, `ZYAN_STATUS_FALSE` if not. Another
|
||||||
|
* zyan status code, if an error occured.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZyanStatus ZydisIsFeatureEnabled(ZydisFeature feature);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_H */
|
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
#ifndef ZYDIS_EXPORT_H
|
||||||
|
#define ZYDIS_EXPORT_H
|
||||||
|
|
||||||
|
#ifdef ZYDIS_STATIC_DEFINE
|
||||||
|
# define ZYDIS_EXPORT
|
||||||
|
# define ZYDIS_NO_EXPORT
|
||||||
|
#else
|
||||||
|
# ifndef ZYDIS_EXPORT
|
||||||
|
# ifdef Zydis_EXPORTS
|
||||||
|
/* We are building this library */
|
||||||
|
# define ZYDIS_EXPORT __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
/* We are using this library */
|
||||||
|
# define ZYDIS_EXPORT __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef ZYDIS_NO_EXPORT
|
||||||
|
# define ZYDIS_NO_EXPORT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DEPRECATED
|
||||||
|
# define ZYDIS_DEPRECATED __declspec(deprecated)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DEPRECATED_EXPORT
|
||||||
|
# define ZYDIS_DEPRECATED_EXPORT ZYDIS_EXPORT ZYDIS_DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZYDIS_DEPRECATED_NO_EXPORT
|
||||||
|
# define ZYDIS_DEPRECATED_NO_EXPORT ZYDIS_NO_EXPORT ZYDIS_DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 /* DEFINE_NO_DEPRECATED */
|
||||||
|
# ifndef ZYDIS_NO_DEPRECATED
|
||||||
|
# define ZYDIS_NO_DEPRECATED
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZYDIS_EXPORT_H */
|
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "zydis-3.1.0"]
|
||||||
|
path = zydis-3.1.0
|
||||||
|
url = https://github.com/zyantific/zydis/commit/bfee99f49274a0eec3ffea16ede3a5bda9cda88f
|
@ -0,0 +1,201 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <map>
|
||||||
|
#include <Zydis/Zydis.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <functional>
|
||||||
|
#include <vmutils.h>
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
namespace transform
|
||||||
|
{
|
||||||
|
// taken from ida...
|
||||||
|
template<class T> inline T __ROL__(T value, int count)
|
||||||
|
{
|
||||||
|
const unsigned int nbits = sizeof(T) * 8;
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
count %= nbits;
|
||||||
|
T high = value >> (nbits - count);
|
||||||
|
if (T(-1) < 0) // signed value
|
||||||
|
high &= ~((T(-1) << count));
|
||||||
|
value <<= count;
|
||||||
|
value |= high;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = -count % nbits;
|
||||||
|
T low = value << (nbits - count);
|
||||||
|
value >>= count;
|
||||||
|
value |= low;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// taken from ida...
|
||||||
|
inline u8 __ROL1__(u8 value, int count) { return __ROL__((u8)value, count); }
|
||||||
|
inline u16 __ROL2__(u16 value, int count) { return __ROL__((u16)value, count); }
|
||||||
|
inline u32 __ROL4__(u32 value, int count) { return __ROL__((u32)value, count); }
|
||||||
|
inline u64 __ROL8__(u64 value, int count) { return __ROL__((u64)value, count); }
|
||||||
|
inline u8 __ROR1__(u8 value, int count) { return __ROL__((u8)value, -count); }
|
||||||
|
inline u16 __ROR2__(u16 value, int count) { return __ROL__((u16)value, -count); }
|
||||||
|
inline u32 __ROR4__(u32 value, int count) { return __ROL__((u32)value, -count); }
|
||||||
|
inline u64 __ROR8__(u64 value, int count) { return __ROL__((u64)value, -count); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using transform_t = std::function<T(T, T)>;
|
||||||
|
|
||||||
|
enum class type
|
||||||
|
{
|
||||||
|
rolling_key,
|
||||||
|
generic1,
|
||||||
|
generic2,
|
||||||
|
generic3,
|
||||||
|
update_key
|
||||||
|
};
|
||||||
|
|
||||||
|
using map_t = std::map<transform::type, ZydisDecodedInstruction>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _bswap = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, std::uint64_t>)
|
||||||
|
return _byteswap_uint64(a);
|
||||||
|
if constexpr (std::is_same_v<T, std::uint32_t>)
|
||||||
|
return _byteswap_ulong(a);
|
||||||
|
if constexpr (std::is_same_v<T, std::uint16_t>)
|
||||||
|
return _byteswap_ushort(a);
|
||||||
|
|
||||||
|
throw std::invalid_argument("invalid type size...");
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _add = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _xor = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
return a ^ b;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _sub = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
return a - b;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _neg = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
return a * -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _not = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
return ~a;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _ror = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, std::uint64_t>)
|
||||||
|
return __ROR8__(a, b);
|
||||||
|
if constexpr (std::is_same_v<T, std::uint32_t>)
|
||||||
|
return __ROR4__(a, b);
|
||||||
|
if constexpr (std::is_same_v<T, std::uint16_t>)
|
||||||
|
return __ROR2__(a, b);
|
||||||
|
if constexpr (std::is_same_v <T, std::uint8_t>)
|
||||||
|
return __ROR1__(a, b);
|
||||||
|
|
||||||
|
throw std::invalid_argument("invalid type size...");
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _rol = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, std::uint64_t>)
|
||||||
|
return __ROL8__(a, b);
|
||||||
|
if constexpr (std::is_same_v<T, std::uint32_t>)
|
||||||
|
return __ROL4__(a, b);
|
||||||
|
if constexpr (std::is_same_v<T, std::uint16_t>)
|
||||||
|
return __ROL2__(a, b);
|
||||||
|
if constexpr (std::is_same_v <T, std::uint8_t>)
|
||||||
|
return __ROL1__(a, b);
|
||||||
|
|
||||||
|
throw std::invalid_argument("invalid type size...");
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _inc = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
return a + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline const auto _dec = [](T a, T b) -> T
|
||||||
|
{
|
||||||
|
return a - 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline std::map<ZydisMnemonic, transform_t<T>> transforms =
|
||||||
|
{
|
||||||
|
{ ZYDIS_MNEMONIC_ADD, _add<T> },
|
||||||
|
{ ZYDIS_MNEMONIC_XOR, _xor<T> },
|
||||||
|
{ ZYDIS_MNEMONIC_BSWAP, _bswap<T> },
|
||||||
|
{ ZYDIS_MNEMONIC_SUB, _sub<T>},
|
||||||
|
{ ZYDIS_MNEMONIC_NEG, _neg<T>},
|
||||||
|
{ ZYDIS_MNEMONIC_NOT, _not<T>},
|
||||||
|
{ ZYDIS_MNEMONIC_ROR, _ror<T>},
|
||||||
|
{ ZYDIS_MNEMONIC_ROL, _rol<T>},
|
||||||
|
{ ZYDIS_MNEMONIC_INC, _inc<T>},
|
||||||
|
{ ZYDIS_MNEMONIC_DEC, _dec<T>}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::map<ZydisMnemonic, ZydisMnemonic> inverse =
|
||||||
|
{
|
||||||
|
{ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_SUB},
|
||||||
|
{ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR},
|
||||||
|
{ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP},
|
||||||
|
{ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD},
|
||||||
|
{ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NEG},
|
||||||
|
{ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT},
|
||||||
|
{ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL},
|
||||||
|
{ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR},
|
||||||
|
{ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC},
|
||||||
|
{ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC}
|
||||||
|
};
|
||||||
|
|
||||||
|
// max size of a and b is 64 bits, a and b is then converted to
|
||||||
|
// the number of bits in bitsize, the transformation is applied,
|
||||||
|
// finally the result is converted back to 64bits... zero extended...
|
||||||
|
inline auto apply(std::uint8_t bitsize, ZydisMnemonic op,
|
||||||
|
std::uint64_t a, std::uint64_t b) -> std::uint64_t
|
||||||
|
{
|
||||||
|
switch (bitsize)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
return transforms<std::uint8_t>[op](a, b);
|
||||||
|
case 16:
|
||||||
|
return transforms<std::uint16_t>[op](a, b);
|
||||||
|
case 32:
|
||||||
|
return transforms<std::uint32_t>[op](a, b);
|
||||||
|
case 64:
|
||||||
|
return transforms<std::uint64_t>[op](a, b);
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("invalid bit size...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool has_imm(ZydisDecodedInstruction* instr)
|
||||||
|
{
|
||||||
|
return instr->operand_count > 1 &&
|
||||||
|
(instr->operands[1].type & ZYDIS_OPERAND_TYPE_IMMEDIATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,603 @@
|
|||||||
|
#include "vm.h"
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
std::pair<std::uint64_t, std::uint64_t> decrypt_operand(transform::map_t& transforms,
|
||||||
|
std::uint64_t operand, std::uint64_t rolling_key)
|
||||||
|
{
|
||||||
|
const auto key_decrypt = &transforms[transform::type::rolling_key];
|
||||||
|
const auto generic_decrypt_1 = &transforms[transform::type::generic1];
|
||||||
|
const auto generic_decrypt_2 = &transforms[transform::type::generic2];
|
||||||
|
const auto generic_decrypt_3 = &transforms[transform::type::generic3];
|
||||||
|
const auto update_key = &transforms[transform::type::update_key];
|
||||||
|
|
||||||
|
// apply transformation with rolling decrypt key...
|
||||||
|
operand = transform::apply(key_decrypt->operands[0].size,
|
||||||
|
key_decrypt->mnemonic, operand, rolling_key);
|
||||||
|
|
||||||
|
// apply three generic transformations...
|
||||||
|
{
|
||||||
|
operand = transform::apply(
|
||||||
|
generic_decrypt_1->operands[0].size,
|
||||||
|
generic_decrypt_1->mnemonic, operand,
|
||||||
|
// check to see if this instruction has an IMM...
|
||||||
|
transform::has_imm(generic_decrypt_1) ?
|
||||||
|
generic_decrypt_1->operands[1].imm.value.u : 0);
|
||||||
|
|
||||||
|
operand = transform::apply(
|
||||||
|
generic_decrypt_2->operands[0].size,
|
||||||
|
generic_decrypt_2->mnemonic, operand,
|
||||||
|
// check to see if this instruction has an IMM...
|
||||||
|
transform::has_imm(generic_decrypt_2) ?
|
||||||
|
generic_decrypt_2->operands[1].imm.value.u : 0);
|
||||||
|
|
||||||
|
operand = transform::apply(
|
||||||
|
generic_decrypt_3->operands[0].size,
|
||||||
|
generic_decrypt_3->mnemonic, operand,
|
||||||
|
// check to see if this instruction has an IMM...
|
||||||
|
transform::has_imm(generic_decrypt_3) ?
|
||||||
|
generic_decrypt_3->operands[1].imm.value.u : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update rolling key...
|
||||||
|
auto result = transform::apply(update_key->operands[0].size,
|
||||||
|
update_key->mnemonic, rolling_key, operand);
|
||||||
|
|
||||||
|
// update decryption key correctly...
|
||||||
|
switch (update_key->operands[0].size)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
rolling_key = (rolling_key & ~0xFFull) + result;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
rolling_key = (rolling_key & ~0xFFFFull) + result;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rolling_key = result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { operand, rolling_key };
|
||||||
|
}
|
||||||
|
|
||||||
|
void inverse_transforms(transform::map_t& transforms, transform::map_t& inverse)
|
||||||
|
{
|
||||||
|
inverse[transform::type::rolling_key] = transforms[transform::type::rolling_key];
|
||||||
|
inverse[transform::type::rolling_key].mnemonic =
|
||||||
|
transform::inverse[transforms[transform::type::rolling_key].mnemonic];
|
||||||
|
|
||||||
|
inverse[transform::type::generic1] = transforms[transform::type::generic1];
|
||||||
|
inverse[transform::type::generic1].mnemonic =
|
||||||
|
transform::inverse[transforms[transform::type::generic1].mnemonic];
|
||||||
|
|
||||||
|
inverse[transform::type::generic2] = transforms[transform::type::generic2];
|
||||||
|
inverse[transform::type::generic2].mnemonic =
|
||||||
|
transform::inverse[transforms[transform::type::generic2].mnemonic];
|
||||||
|
|
||||||
|
inverse[transform::type::generic3] = transforms[transform::type::generic3];
|
||||||
|
inverse[transform::type::generic3].mnemonic =
|
||||||
|
transform::inverse[transforms[transform::type::generic3].mnemonic];
|
||||||
|
|
||||||
|
inverse[transform::type::update_key] = transforms[transform::type::update_key];
|
||||||
|
inverse[transform::type::update_key].mnemonic =
|
||||||
|
transform::inverse[transforms[transform::type::update_key].mnemonic];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::uint64_t, std::uint64_t> encrypt_operand(transform::map_t& transforms,
|
||||||
|
std::uint64_t operand, std::uint64_t rolling_key)
|
||||||
|
{
|
||||||
|
transform::map_t inverse;
|
||||||
|
inverse_transforms(transforms, inverse);
|
||||||
|
|
||||||
|
const auto key_decrypt = &inverse[transform::type::rolling_key];
|
||||||
|
const auto generic_decrypt_1 = &inverse[transform::type::generic1];
|
||||||
|
const auto generic_decrypt_2 = &inverse[transform::type::generic2];
|
||||||
|
const auto generic_decrypt_3 = &inverse[transform::type::generic3];
|
||||||
|
const auto update_key = &inverse[transform::type::update_key];
|
||||||
|
|
||||||
|
auto result = transform::apply(update_key->operands[0].size,
|
||||||
|
update_key->mnemonic, rolling_key, operand);
|
||||||
|
|
||||||
|
// make sure we update the rolling decryption key correctly...
|
||||||
|
switch (update_key->operands[0].size)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
rolling_key = (rolling_key & ~0xFFull) + result;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
rolling_key = (rolling_key & ~0xFFFFull) + result;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rolling_key = result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
operand = transform::apply(
|
||||||
|
generic_decrypt_3->operands[0].size,
|
||||||
|
generic_decrypt_3->mnemonic, operand,
|
||||||
|
// check to see if this instruction has an IMM...
|
||||||
|
transform::has_imm(generic_decrypt_3) ?
|
||||||
|
generic_decrypt_3->operands[1].imm.value.u : 0);
|
||||||
|
|
||||||
|
operand = transform::apply(
|
||||||
|
generic_decrypt_2->operands[0].size,
|
||||||
|
generic_decrypt_2->mnemonic, operand,
|
||||||
|
// check to see if this instruction has an IMM...
|
||||||
|
transform::has_imm(generic_decrypt_2) ?
|
||||||
|
generic_decrypt_2->operands[1].imm.value.u : 0);
|
||||||
|
|
||||||
|
operand = transform::apply(
|
||||||
|
generic_decrypt_1->operands[0].size,
|
||||||
|
generic_decrypt_1->mnemonic, operand,
|
||||||
|
// check to see if this instruction has an IMM...
|
||||||
|
transform::has_imm(generic_decrypt_1) ?
|
||||||
|
generic_decrypt_1->operands[1].imm.value.u : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
operand = transform::apply(key_decrypt->operands[0].size,
|
||||||
|
key_decrypt->mnemonic, operand, rolling_key);
|
||||||
|
|
||||||
|
return { operand, rolling_key };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_calc_jmp(const zydis_routine_t& vm_entry, zydis_routine_t& calc_jmp)
|
||||||
|
{
|
||||||
|
auto result = std::find_if(vm_entry.begin(), vm_entry.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
||||||
|
if (instr_data.instr.operand_count > 1 &&
|
||||||
|
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) &&
|
||||||
|
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||||
|
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX &&
|
||||||
|
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||||
|
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == vm_entry.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
calc_jmp.insert(calc_jmp.end(), result, vm_entry.end());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_vinstr_rva_transform(
|
||||||
|
const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// find mov esi, [rsp+0xA0]
|
||||||
|
//
|
||||||
|
|
||||||
|
auto result = std::find_if(vm_entry.begin(), vm_entry.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
if (instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
|
||||||
|
instr_data.instr.operand_count == 2 &&
|
||||||
|
instr_data.instr.operands[0].reg.value == ZYDIS_REGISTER_ESI &&
|
||||||
|
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSP &&
|
||||||
|
instr_data.instr.operands[1].mem.disp.has_displacement &&
|
||||||
|
instr_data.instr.operands[1].mem.disp.value == 0xA0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == vm_entry.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//
|
||||||
|
// find the next instruction with ESI as the dest...
|
||||||
|
//
|
||||||
|
|
||||||
|
result = std::find_if(++result, vm_entry.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
if (instr_data.instr.operands[0].reg.value == ZYDIS_REGISTER_ESI)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == vm_entry.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*transform_instr = result->instr;
|
||||||
|
transform_instr->mnemonic = transform::inverse[result->instr.mnemonic];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace handler
|
||||||
|
{
|
||||||
|
bool get(zydis_routine_t& calc_jmp, zydis_routine_t& vm_handler, std::uintptr_t handler_addr)
|
||||||
|
{
|
||||||
|
if (!vm::util::flatten(vm_handler, handler_addr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vm::util::deobfuscate(vm_handler);
|
||||||
|
|
||||||
|
static const auto calc_jmp_check =
|
||||||
|
[&](std::uintptr_t addr) -> bool
|
||||||
|
{
|
||||||
|
for (const auto& [instr, instr_raw, instr_addr] : calc_jmp)
|
||||||
|
if (instr_addr == addr)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto result = std::find_if(
|
||||||
|
vm_handler.begin(), vm_handler.end(),
|
||||||
|
[](const zydis_instr_t& instr) -> bool
|
||||||
|
{
|
||||||
|
if (instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA &&
|
||||||
|
instr.instr.operands[0].reg.value == ZYDIS_REGISTER_RAX &&
|
||||||
|
instr.instr.operands[1].mem.base == ZYDIS_REGISTER_RDI &&
|
||||||
|
instr.instr.operands[1].mem.disp.value == 0xE0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return calc_jmp_check(instr.addr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove calc_jmp from the vm handler vector...
|
||||||
|
if (result != vm_handler.end())
|
||||||
|
vm_handler.erase(result, vm_handler.end());
|
||||||
|
else // locate the last mov al, [rsi],
|
||||||
|
// then remove all instructions after that...
|
||||||
|
{
|
||||||
|
zydis_routine_t::iterator last = vm_handler.end();
|
||||||
|
result = vm_handler.begin();
|
||||||
|
|
||||||
|
while (result != vm_handler.end())
|
||||||
|
{
|
||||||
|
result = std::find_if(
|
||||||
|
++result, vm_handler.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
||||||
|
if (instr_data.instr.operand_count > 1 &&
|
||||||
|
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) &&
|
||||||
|
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||||
|
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX &&
|
||||||
|
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||||
|
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result != vm_handler.end())
|
||||||
|
last = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last != vm_handler.end())
|
||||||
|
vm_handler.erase(last, vm_handler.end());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_all(std::uintptr_t module_base, std::uintptr_t image_base,
|
||||||
|
zydis_routine_t& vm_entry, std::uintptr_t* vm_handler_table, std::vector<vm::handler_t>& vm_handlers)
|
||||||
|
{
|
||||||
|
ZydisDecodedInstruction instr;
|
||||||
|
if (!vm::handler::table::get_transform(vm_entry, &instr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
zydis_routine_t calc_jmp;
|
||||||
|
if (!vm::get_calc_jmp(vm_entry, calc_jmp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto idx = 0u; idx < 256; ++idx)
|
||||||
|
{
|
||||||
|
const auto decrypt_val =
|
||||||
|
vm::handler::table::decrypt(
|
||||||
|
instr, vm_handler_table[idx]);
|
||||||
|
|
||||||
|
vm::handler_t vm_handler;
|
||||||
|
vm::transform::map_t transforms;
|
||||||
|
zydis_routine_t vm_handler_instrs;
|
||||||
|
|
||||||
|
if (!vm::handler::get(calc_jmp, vm_handler_instrs, (decrypt_val - image_base) + module_base))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto has_imm =
|
||||||
|
vm::handler::has_imm(vm_handler_instrs);
|
||||||
|
|
||||||
|
const auto imm_size =
|
||||||
|
vm::handler::imm_size(vm_handler_instrs);
|
||||||
|
|
||||||
|
if (has_imm && !vm::handler::get_operand_transforms(vm_handler_instrs, transforms))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vm_handler.instrs = vm_handler_instrs;
|
||||||
|
vm_handler.imm_size = imm_size;
|
||||||
|
vm_handler.transforms = transforms;
|
||||||
|
vm_handler.profile = vm::handler::get_profile(vm_handler);
|
||||||
|
vm_handlers.push_back(vm_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_imm(const zydis_routine_t& vm_handler)
|
||||||
|
{
|
||||||
|
const auto result = std::find_if(
|
||||||
|
vm_handler.begin(), vm_handler.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
||||||
|
if (instr_data.instr.operand_count > 1 &&
|
||||||
|
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) &&
|
||||||
|
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||||
|
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX &&
|
||||||
|
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||||
|
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result != vm_handler.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint8_t imm_size(const zydis_routine_t& vm_handler)
|
||||||
|
{
|
||||||
|
const auto result = std::find_if(
|
||||||
|
vm_handler.begin(), vm_handler.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
||||||
|
if (instr_data.instr.operand_count > 1 &&
|
||||||
|
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) &&
|
||||||
|
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||||
|
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX &&
|
||||||
|
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||||
|
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == vm_handler.end())
|
||||||
|
return 0u;
|
||||||
|
|
||||||
|
return result->instr.operands[1].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_operand_transforms(const zydis_routine_t& vm_handler, transform::map_t& transforms)
|
||||||
|
{
|
||||||
|
auto imm_fetch = std::find_if(
|
||||||
|
vm_handler.begin(), vm_handler.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
// mov/movsx/movzx rax/eax/ax/al, [rsi]
|
||||||
|
if (instr_data.instr.operand_count > 1 &&
|
||||||
|
(instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX) &&
|
||||||
|
instr_data.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||||
|
util::reg::to64(instr_data.instr.operands[0].reg.value) == ZYDIS_REGISTER_RAX &&
|
||||||
|
instr_data.instr.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||||
|
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSI)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (imm_fetch == vm_handler.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// this finds the first transformation which looks like:
|
||||||
|
// transform rax, rbx <--- note these registers can be smaller so we to64 them...
|
||||||
|
auto key_transform = std::find_if(imm_fetch, vm_handler.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
if (util::reg::compare(instr_data.instr.operands[0].reg.value, ZYDIS_REGISTER_RAX) &&
|
||||||
|
util::reg::compare(instr_data.instr.operands[1].reg.value, ZYDIS_REGISTER_RBX))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// last transformation is the same as the first except src and dest are swwapped...
|
||||||
|
transforms[transform::type::rolling_key] = key_transform->instr;
|
||||||
|
auto instr_copy = key_transform->instr;
|
||||||
|
instr_copy.operands[0].reg.value = key_transform->instr.operands[1].reg.value;
|
||||||
|
instr_copy.operands[1].reg.value = key_transform->instr.operands[0].reg.value;
|
||||||
|
transforms[transform::type::update_key] = instr_copy;
|
||||||
|
|
||||||
|
if (key_transform == vm_handler.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// three generic transformations...
|
||||||
|
auto generic_transform = key_transform;
|
||||||
|
|
||||||
|
for (auto idx = 0u; idx < 3; ++idx)
|
||||||
|
{
|
||||||
|
generic_transform = std::find_if(++generic_transform, vm_handler.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
if (util::reg::compare(instr_data.instr.operands[0].reg.value, ZYDIS_REGISTER_RAX))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (generic_transform == vm_handler.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
transforms[(transform::type)(idx + 1)] = generic_transform->instr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm::handler::profile_t* get_profile(vm::handler_t& vm_handler)
|
||||||
|
{
|
||||||
|
static const auto vcontains =
|
||||||
|
[](vm::handler::profile_t* vprofile, vm::handler_t* vm_handler) -> bool
|
||||||
|
{
|
||||||
|
if (vprofile->imm_size != vm_handler->imm_size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto& instr : vprofile->signature)
|
||||||
|
{
|
||||||
|
const auto contains = std::find_if
|
||||||
|
(
|
||||||
|
vm_handler->instrs.begin(),
|
||||||
|
vm_handler->instrs.end(),
|
||||||
|
|
||||||
|
[&](zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
if (instr_data.raw.size() != instr.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return std::equal
|
||||||
|
(
|
||||||
|
instr_data.raw.begin(),
|
||||||
|
instr_data.raw.end(),
|
||||||
|
instr.begin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (contains == vm_handler->instrs.end())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto profile : vm::handler::profile::all)
|
||||||
|
if (vcontains(profile, &vm_handler))
|
||||||
|
return profile;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace table
|
||||||
|
{
|
||||||
|
std::uintptr_t* get(const zydis_routine_t& vm_entry)
|
||||||
|
{
|
||||||
|
const auto result = std::find_if(
|
||||||
|
vm_entry.begin(), vm_entry.end(),
|
||||||
|
[](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
const auto instr = &instr_data.instr;
|
||||||
|
// lea r12, vm_handlers... (always r12)...
|
||||||
|
if (instr->mnemonic == ZYDIS_MNEMONIC_LEA &&
|
||||||
|
instr->operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||||
|
instr->operands[0].reg.value == ZYDIS_REGISTER_R12 &&
|
||||||
|
!instr->raw.sib.base) // no register used for the sib base...
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == vm_entry.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::uintptr_t ptr = 0u;
|
||||||
|
ZydisCalcAbsoluteAddress(&result->instr,
|
||||||
|
&result->instr.operands[1], result->addr, &ptr);
|
||||||
|
|
||||||
|
return reinterpret_cast<std::uintptr_t*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_transform(const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr)
|
||||||
|
{
|
||||||
|
ZydisRegister rcx_or_rdx = ZYDIS_REGISTER_NONE;
|
||||||
|
|
||||||
|
auto handler_fetch = std::find_if(
|
||||||
|
vm_entry.begin(), vm_entry.end(),
|
||||||
|
[&](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
const auto instr = &instr_data.instr;
|
||||||
|
if (instr->mnemonic == ZYDIS_MNEMONIC_MOV &&
|
||||||
|
instr->operand_count == 2 &&
|
||||||
|
instr->operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY &&
|
||||||
|
instr->operands[1].mem.base == ZYDIS_REGISTER_R12 &&
|
||||||
|
instr->operands[1].mem.index == ZYDIS_REGISTER_RAX &&
|
||||||
|
instr->operands[1].mem.scale == 8 &&
|
||||||
|
instr->operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||||
|
(instr->operands[0].reg.value == ZYDIS_REGISTER_RDX ||
|
||||||
|
instr->operands[0].reg.value == ZYDIS_REGISTER_RCX))
|
||||||
|
{
|
||||||
|
rcx_or_rdx = instr->operands[0].reg.value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// check to see if we found the fetch instruction and if the next instruction
|
||||||
|
// is not the end of the vector...
|
||||||
|
if (handler_fetch == vm_entry.end() || ++handler_fetch == vm_entry.end() ||
|
||||||
|
// must be RCX or RDX... else something went wrong...
|
||||||
|
(rcx_or_rdx != ZYDIS_REGISTER_RCX && rcx_or_rdx != ZYDIS_REGISTER_RDX))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// find the next instruction that writes to RCX or RDX...
|
||||||
|
// the register is determined by the vm handler fetch above...
|
||||||
|
auto handler_transform = std::find_if(
|
||||||
|
handler_fetch, vm_entry.end(),
|
||||||
|
[&](const zydis_instr_t& instr_data) -> bool
|
||||||
|
{
|
||||||
|
if (instr_data.instr.operands[0].reg.value == rcx_or_rdx &&
|
||||||
|
instr_data.instr.operands[0].actions & ZYDIS_OPERAND_ACTION_WRITE)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (handler_transform == vm_entry.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*transform_instr = handler_transform->instr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t encrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val)
|
||||||
|
{
|
||||||
|
assert(transform_instr.operands[0].size == 64,
|
||||||
|
"invalid transformation for vm handler table entries...");
|
||||||
|
|
||||||
|
const auto operation = vm::transform::inverse[transform_instr.mnemonic];
|
||||||
|
const auto bitsize = transform_instr.operands[0].size;
|
||||||
|
const auto imm = vm::transform::has_imm(&transform_instr) ?
|
||||||
|
transform_instr.operands[1].imm.value.u : 0u;
|
||||||
|
|
||||||
|
return vm::transform::apply(bitsize, operation, val, imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t decrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val)
|
||||||
|
{
|
||||||
|
assert(transform_instr.operands[0].size == 64,
|
||||||
|
"invalid transformation for vm handler table entries...");
|
||||||
|
|
||||||
|
const auto operation = transform_instr.mnemonic;
|
||||||
|
const auto bitsize = transform_instr.operands[0].size;
|
||||||
|
const auto imm = vm::transform::has_imm(&transform_instr) ?
|
||||||
|
transform_instr.operands[1].imm.value.u : 0u;
|
||||||
|
|
||||||
|
return vm::transform::apply(bitsize, operation, val, imm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <transform.hpp>
|
||||||
|
#include <vmutils.h>
|
||||||
|
#include <vmprofiler.hpp>
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
std::pair<std::uint64_t, std::uint64_t> decrypt_operand(transform::map_t& transforms,
|
||||||
|
std::uint64_t operand, std::uint64_t rolling_key);
|
||||||
|
|
||||||
|
std::pair<std::uint64_t, std::uint64_t> encrypt_operand(transform::map_t& transforms,
|
||||||
|
std::uint64_t operand, std::uint64_t rolling_key);
|
||||||
|
|
||||||
|
void inverse_transforms(transform::map_t& transforms, transform::map_t& inverse);
|
||||||
|
bool get_calc_jmp(const zydis_routine_t& vm_entry, zydis_routine_t& calc_jmp);
|
||||||
|
bool get_vinstr_rva_transform(
|
||||||
|
const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr);
|
||||||
|
|
||||||
|
struct handler_t
|
||||||
|
{
|
||||||
|
u8 imm_size; // size in bits...
|
||||||
|
vm::transform::map_t transforms;
|
||||||
|
vm::handler::profile_t* profile;
|
||||||
|
zydis_routine_t instrs;
|
||||||
|
std::uintptr_t address;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace handler
|
||||||
|
{
|
||||||
|
bool has_imm(const zydis_routine_t& vm_handler);
|
||||||
|
std::uint8_t imm_size(const zydis_routine_t& vm_handler);
|
||||||
|
bool get(zydis_routine_t& vm_entry, zydis_routine_t& vm_handler, std::uintptr_t handler_addr);
|
||||||
|
|
||||||
|
// may throw an exception...
|
||||||
|
bool get_all(std::uintptr_t module_base, std::uintptr_t image_base,
|
||||||
|
zydis_routine_t& vm_entry, std::uintptr_t* vm_handler_table, std::vector<vm::handler_t>& vm_handlers);
|
||||||
|
|
||||||
|
// can be used on calc_jmp...
|
||||||
|
bool get_operand_transforms(const zydis_routine_t& vm_handler, transform::map_t& transforms);
|
||||||
|
vm::handler::profile_t* get_profile(vm::handler_t& vm_handler);
|
||||||
|
|
||||||
|
namespace table
|
||||||
|
{
|
||||||
|
std::uintptr_t* get(const zydis_routine_t& vm_entry);
|
||||||
|
bool get_transform(const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr);
|
||||||
|
|
||||||
|
std::uint64_t encrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val);
|
||||||
|
std::uint64_t decrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
#include "vmctx.h"
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
vmctx_t::vmctx_t(
|
||||||
|
vmp2::file_header* file_header,
|
||||||
|
vmp2::entry_t* entry_list,
|
||||||
|
std::vector<vm::handler_t>& vm_handlers,
|
||||||
|
std::uintptr_t module_base,
|
||||||
|
std::uintptr_t image_base
|
||||||
|
)
|
||||||
|
: module_base(module_base),
|
||||||
|
image_base(image_base),
|
||||||
|
entry_list(entry_list),
|
||||||
|
file_header(file_header),
|
||||||
|
vm_handlers(vm_handlers),
|
||||||
|
idx(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::pair<std::string, const vmp2::entry_t*> vmctx_t::step() const
|
||||||
|
{
|
||||||
|
if (idx >= file_header->entry_count)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto vm_handler = &vm_handlers[entry_list[idx].handler_idx];
|
||||||
|
|
||||||
|
if (vm_handler->imm_size)
|
||||||
|
{
|
||||||
|
const auto operand = get_imm(file_header->advancement,
|
||||||
|
entry_list[idx].vip, vm_handler->imm_size / 8);
|
||||||
|
|
||||||
|
auto transforms = vm_handler->transforms;
|
||||||
|
auto [decrypted_operand, rolling_key] =
|
||||||
|
vm::decrypt_operand(transforms,
|
||||||
|
operand, entry_list[idx].decrypt_key);
|
||||||
|
|
||||||
|
if (vm_handler->profile)
|
||||||
|
{
|
||||||
|
if (vm_handler->profile->extention ==
|
||||||
|
vm::handler::extention_t::sign_extend)
|
||||||
|
{
|
||||||
|
switch (vm_handler->imm_size)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
if ((u8)(decrypted_operand >> 7))
|
||||||
|
decrypted_operand += ~0xFFull;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16:
|
||||||
|
{
|
||||||
|
if ((u16)(decrypted_operand >> 15))
|
||||||
|
decrypted_operand += ~0xFFFFull;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 32:
|
||||||
|
{
|
||||||
|
if ((u32)(decrypted_operand >> 31))
|
||||||
|
decrypted_operand += ~0xFFFFFFFFull;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument(
|
||||||
|
"invalid imm size for sign extention...\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char buff[256];
|
||||||
|
if (vm_handler->profile)
|
||||||
|
{
|
||||||
|
snprintf(buff, sizeof buff, "%s 0x%p",
|
||||||
|
vm_handler->profile->name, decrypted_operand);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(buff, sizeof buff, "UNK(%d) 0x%p",
|
||||||
|
entry_list[idx].handler_idx, decrypted_operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { buff, &entry_list[idx++] };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm_handler->profile)
|
||||||
|
return { vm_handler->profile->name, &entry_list[idx++] };
|
||||||
|
|
||||||
|
char buff[256];
|
||||||
|
snprintf(buff, sizeof buff, "UNK(%d)", entry_list[idx++].handler_idx);
|
||||||
|
return { buff, &entry_list[idx++] };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uintptr_t vmctx_t::get_imm(vmp2::exec_type_t exec_type_t,
|
||||||
|
std::uint32_t vip_offset, std::uint8_t imm_size) const
|
||||||
|
{
|
||||||
|
std::uintptr_t operand = 0u;
|
||||||
|
if (file_header->advancement == vmp2::exec_type_t::forward)
|
||||||
|
{
|
||||||
|
const auto operand_ptr =
|
||||||
|
reinterpret_cast<void*>((entry_list[idx].vip -
|
||||||
|
file_header->module_base) + module_base);
|
||||||
|
|
||||||
|
memcpy(&operand, operand_ptr, imm_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto operand_ptr =
|
||||||
|
reinterpret_cast<void*>(((entry_list[idx].vip -
|
||||||
|
file_header->module_base) + module_base) - imm_size);
|
||||||
|
|
||||||
|
memcpy(&operand, operand_ptr, imm_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vm.h>
|
||||||
|
#include <vmp2.hpp>
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
class vmctx_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit vmctx_t(
|
||||||
|
vmp2::file_header* file_header,
|
||||||
|
vmp2::entry_t* entry_list,
|
||||||
|
std::vector<vm::handler_t>& vm_handlers,
|
||||||
|
std::uintptr_t module_base,
|
||||||
|
std::uintptr_t image_base
|
||||||
|
);
|
||||||
|
|
||||||
|
std::pair<std::string, const vmp2::entry_t*> step() const;
|
||||||
|
private:
|
||||||
|
std::uintptr_t get_imm(vmp2::exec_type_t exec_type_t,
|
||||||
|
std::uint32_t vip_offset, std::uint8_t imm_size) const;
|
||||||
|
|
||||||
|
mutable std::uint32_t idx;
|
||||||
|
const std::uintptr_t image_base, module_base;
|
||||||
|
const vmp2::entry_t* entry_list;
|
||||||
|
const vmp2::file_header* file_header;
|
||||||
|
std::vector<vm::handler_t> vm_handlers;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "vm.h"
|
||||||
|
|
||||||
|
namespace vmp2
|
||||||
|
{
|
||||||
|
enum class exec_type_t
|
||||||
|
{
|
||||||
|
forward,
|
||||||
|
backward
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class version_t
|
||||||
|
{
|
||||||
|
invalid,
|
||||||
|
v1 = 0x101
|
||||||
|
};
|
||||||
|
|
||||||
|
struct file_header
|
||||||
|
{
|
||||||
|
u32 magic; // VMP2
|
||||||
|
u64 epoch_time;
|
||||||
|
u64 module_base;
|
||||||
|
exec_type_t advancement;
|
||||||
|
version_t version;
|
||||||
|
|
||||||
|
u32 entry_count;
|
||||||
|
u32 entry_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct entry_t
|
||||||
|
{
|
||||||
|
u8 handler_idx;
|
||||||
|
u64 decrypt_key;
|
||||||
|
u64 vip;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u64 r15;
|
||||||
|
u64 r14;
|
||||||
|
u64 r13;
|
||||||
|
u64 r12;
|
||||||
|
u64 r11;
|
||||||
|
u64 r10;
|
||||||
|
u64 r9;
|
||||||
|
u64 r8;
|
||||||
|
u64 rbp;
|
||||||
|
u64 rdi;
|
||||||
|
u64 rsi;
|
||||||
|
u64 rdx;
|
||||||
|
u64 rcx;
|
||||||
|
u64 rbx;
|
||||||
|
u64 rax;
|
||||||
|
u64 rflags;
|
||||||
|
};
|
||||||
|
u64 raw[16];
|
||||||
|
} regs;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 qword[0x28];
|
||||||
|
u8 raw[0x140];
|
||||||
|
} vregs;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 qword[0x20];
|
||||||
|
u8 raw[0x100];
|
||||||
|
} vsp;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,367 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <transform.hpp>
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
namespace handler
|
||||||
|
{
|
||||||
|
enum extention_t
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
sign_extend,
|
||||||
|
zero_extend
|
||||||
|
};
|
||||||
|
|
||||||
|
struct profile_t
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
u8 imm_size;
|
||||||
|
std::vector<std::vector<u8>> signature;
|
||||||
|
extention_t extention;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace profile
|
||||||
|
{
|
||||||
|
// store a value from the stack into scratch register X (RDI+X)...
|
||||||
|
// where X is an 8bit immediate value...
|
||||||
|
inline vm::handler::profile_t sregq =
|
||||||
|
{
|
||||||
|
"SREGQ", 8,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x8B, 0x55, 0x0 }, // mov rdx, [rbp+0]
|
||||||
|
{ 0x48, 0x83, 0xC5, 0x8 }, // add rbp, 8
|
||||||
|
{ 0x48, 0x89, 0x14, 0x38 }, // mov [rax+rdi], rdx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t sregdw =
|
||||||
|
{
|
||||||
|
"SREGDW", 8,
|
||||||
|
{
|
||||||
|
{ 0x8B, 0x55, 0x00 },
|
||||||
|
{ 0x48, 0x83, 0xC5, 0x04 },
|
||||||
|
{ 0x89, 0x14, 0x38 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t sregw =
|
||||||
|
{
|
||||||
|
"SREGW", 8,
|
||||||
|
{
|
||||||
|
{ 0x66, 0x8B, 0x55, 0x00 }, // mov dx, [rbp]
|
||||||
|
{ 0x48, 0x83, 0xC5, 0x02 }, // add rbp, 0x02
|
||||||
|
{ 0x66, 0x89, 0x14, 0x38 } // mov [rax+rdi], dx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// load scratch register value onto virtual stack...
|
||||||
|
inline vm::handler::profile_t lregq =
|
||||||
|
{
|
||||||
|
"LREGQ", 8,
|
||||||
|
{
|
||||||
|
{0x48, 0x8B, 0x14, 0x38}, // mov rdx, [rax+rdi]
|
||||||
|
{0x48, 0x83, 0xED, 0x08}, // sub rbp, 8
|
||||||
|
{0x48, 0x89, 0x55, 0x0} // mov [rbp+0], rdx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
> 0x00007FF64724445C mov edx, [rax+rdi*1]
|
||||||
|
> 0x00007FF647244463 sub rbp, 0x04
|
||||||
|
> 0x00007FF647246333 mov [rbp], edx
|
||||||
|
*/
|
||||||
|
inline vm::handler::profile_t lregdw =
|
||||||
|
{
|
||||||
|
"LREGDW", 8,
|
||||||
|
{
|
||||||
|
{ 0x8B, 0x14, 0x38 },
|
||||||
|
{ 0x48, 0x83, 0xED, 0x04 },
|
||||||
|
{ 0x89, 0x55, 0x00 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// load constant value into stack....
|
||||||
|
inline vm::handler::profile_t lconstq =
|
||||||
|
{
|
||||||
|
"LCONSTQ", 64,
|
||||||
|
{
|
||||||
|
{0x48, 0x83, 0xED, 0x08}, // sub rbp, 8
|
||||||
|
{0x48, 0x89, 0x45, 0x00} // mov [rbp+0], rax
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// load 1 byte constant zero extended into 2bytes on the stack...
|
||||||
|
inline vm::handler::profile_t lconstbzx =
|
||||||
|
{
|
||||||
|
"LCONSTBZX", 8,
|
||||||
|
{
|
||||||
|
{0x48, 0x83, 0xED, 0x02}, // sub rbp, 2
|
||||||
|
{0x66, 0x89, 0x45, 0x00} // mov [rbp+0], ax
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t lconstbsx =
|
||||||
|
{
|
||||||
|
"LCONSTBSX", 8,
|
||||||
|
{
|
||||||
|
{ 0x98 },
|
||||||
|
{ 0x48, 0x83, 0xED, 0x04 },
|
||||||
|
{ 0x89, 0x45, 0x00 }
|
||||||
|
},
|
||||||
|
vm::handler::extention_t::sign_extend
|
||||||
|
};
|
||||||
|
|
||||||
|
// load 4 byte constant value sign extended qword into vsp...
|
||||||
|
inline vm::handler::profile_t lconstbsx1 =
|
||||||
|
{
|
||||||
|
"LCONSTBSX", 8,
|
||||||
|
{
|
||||||
|
{0x48, 0x98}, // cdqe
|
||||||
|
{0x48, 0x83, 0xED, 0x8}, // sub rbp, 8
|
||||||
|
{0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax
|
||||||
|
},
|
||||||
|
vm::handler::extention_t::sign_extend
|
||||||
|
};
|
||||||
|
|
||||||
|
// load 4 byte constant value sign extended qword into vsp...
|
||||||
|
inline vm::handler::profile_t lconstdsx =
|
||||||
|
{
|
||||||
|
"LCONSTDSX", 32,
|
||||||
|
{
|
||||||
|
{0x48, 0x98}, // cdqe
|
||||||
|
{0x48, 0x83, 0xED, 0x8}, // sub rbp, 8
|
||||||
|
{0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax
|
||||||
|
},
|
||||||
|
vm::handler::extention_t::sign_extend
|
||||||
|
};
|
||||||
|
|
||||||
|
// load 2 byte constant value sign extended qword into vsp...
|
||||||
|
inline vm::handler::profile_t lconstwsx =
|
||||||
|
{
|
||||||
|
"LCONSTWSX", 16,
|
||||||
|
{
|
||||||
|
{0x48, 0x98}, // cdqe
|
||||||
|
{0x48, 0x83, 0xED, 0x8}, // sub rbp, 8
|
||||||
|
{0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax
|
||||||
|
},
|
||||||
|
vm::handler::extention_t::sign_extend
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t lconstw =
|
||||||
|
{
|
||||||
|
"LCONSTW", 8,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x83, 0xED, 0x02 }, // sub rbp, 0x02
|
||||||
|
{ 0x66, 0x89, 0x45, 0x00 } // mov [rbp], ax
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t lconstdw =
|
||||||
|
{
|
||||||
|
"LCONSTDW", 32,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x83, 0xED, 0x04 },
|
||||||
|
{ 0x89, 0x45, 0x00 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t pushvsp =
|
||||||
|
{
|
||||||
|
"PUSHVSP", 0,
|
||||||
|
{
|
||||||
|
{0x48, 0x89, 0xE8}, // mov rax, rbp
|
||||||
|
{0x48, 0x83, 0xED, 0x08}, // sub rbp, 8
|
||||||
|
{0x48, 0x89, 0x45, 0x0} // mov [rbp+0], rax
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// add two stack values together...
|
||||||
|
inline vm::handler::profile_t addq =
|
||||||
|
{
|
||||||
|
"ADDQ", 0,
|
||||||
|
{
|
||||||
|
{0x48, 0x1, 0x45, 0x8}, // add [rbp+8], rax
|
||||||
|
{0x9C}, // pushfq
|
||||||
|
{0x8F, 0x45, 0x0} // pop qword ptr [rbp+0]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t adddw =
|
||||||
|
{
|
||||||
|
"ADDDW", 0,
|
||||||
|
{
|
||||||
|
{ 0x01, 0x45, 0x08 }, // add [rbp+0x08], eax
|
||||||
|
{ 0x9C }, // pushfq
|
||||||
|
{ 0x8F, 0x45, 0x00 } // pop [rbp]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// two qwords on the top of the stack together then not the result...
|
||||||
|
// ~(VSP[0] | VSP[1])...
|
||||||
|
inline vm::handler::profile_t nandq =
|
||||||
|
{
|
||||||
|
"NANDQ", 0,
|
||||||
|
{
|
||||||
|
{0x48, 0x8B, 0x45, 0x0}, // mov rax, [rbp+0]
|
||||||
|
{0x48, 0x8B, 0x55, 0x8}, // mov rdx, [rbp+8]
|
||||||
|
{0x48, 0xF7, 0xD0}, // not rax
|
||||||
|
{0x48, 0xF7, 0xD2}, // not rdx
|
||||||
|
{0x48, 0x21, 0xD0}, // and rax, rdx
|
||||||
|
{0x48, 0x89, 0x45, 0x8}, // mov [rbp+8], rax
|
||||||
|
{0x9C}, // pushfq
|
||||||
|
{0x8F, 0x45, 0x0} // pop qword ptr [rbp+0]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// leaves the virtual machine...
|
||||||
|
inline vm::handler::profile_t vmexit =
|
||||||
|
{
|
||||||
|
"VMEXIT", 0,
|
||||||
|
{
|
||||||
|
{0x48, 0x89, 0xec}, // mov rsp, rbp
|
||||||
|
{0x9d}, // popfq
|
||||||
|
{0xc3} // ret
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t jmp =
|
||||||
|
{
|
||||||
|
"JMP", 0,
|
||||||
|
{
|
||||||
|
{ 0x8B, 0x75, 0x00 }, // mov esi, [rbp]
|
||||||
|
{ 0x48, 0x01, 0xC6 }, // add rsi, rax
|
||||||
|
{ 0x48, 0x89, 0xF3 }, // mov rbx, rsi
|
||||||
|
{ 0x48, 0x03, 0x75, 0x00 } // add rsi, [rbp]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t readw =
|
||||||
|
{
|
||||||
|
"READW", 0,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp]
|
||||||
|
{ 0x48, 0x83, 0xC5, 0x06 }, // add rbp, 0x06
|
||||||
|
{ 0x36, 0x66, 0x8B, 0x00 }, // mov ax, ss:[rax]
|
||||||
|
{ 0x66, 0x89, 0x45, 0x00 } // mov [rbp], ax
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t writeq =
|
||||||
|
{
|
||||||
|
"WRITEQ", 0,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp]
|
||||||
|
{ 0x48, 0x8B, 0x55, 0x08 }, // mov rdx, [rbp+0x08]
|
||||||
|
{ 0x48, 0x83, 0xC5, 0x10 }, // add rbp, 0x10
|
||||||
|
{ 0x36, 0x48, 0x89, 0x10 }, // mov ss:[rax], rdx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t writeq1 =
|
||||||
|
{
|
||||||
|
"WRITEQ", 0,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp]
|
||||||
|
{ 0x48, 0x8B, 0x55, 0x08 }, // mov rdx, [rbp+0x08]
|
||||||
|
{ 0x48, 0x83, 0xC5, 0x10 }, // add rbp, 0x10
|
||||||
|
{ 0x48, 0x89, 0x10 } // mov [rax], rdx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t shrw =
|
||||||
|
{
|
||||||
|
"SHRW", 0,
|
||||||
|
{
|
||||||
|
{ 0x66, 0x8B, 0x45, 0x00 },
|
||||||
|
{ 0x8A, 0x4D, 0x02 },
|
||||||
|
{ 0x48, 0x83, 0xED, 0x06 },
|
||||||
|
{ 0x66, 0xD3, 0xE8 },
|
||||||
|
{ 0x66, 0x89, 0x45, 0x08 },
|
||||||
|
{ 0x9C },
|
||||||
|
{ 0x8F, 0x45, 0x00 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t shrdw =
|
||||||
|
{
|
||||||
|
"SHRDW", 0,
|
||||||
|
{
|
||||||
|
{ 0x8B, 0x45, 0x00 },
|
||||||
|
{ 0x8A, 0x4D, 0x04 },
|
||||||
|
{ 0x48, 0x83, 0xED, 0x06 },
|
||||||
|
{ 0xD3, 0xE8 },
|
||||||
|
{ 0x89, 0x45, 0x08 },
|
||||||
|
{ 0x9C },
|
||||||
|
{ 0x8F, 0x45, 0x00 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t shrq =
|
||||||
|
{
|
||||||
|
"SHRQ", 0,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x8B, 0x45, 0x00 },
|
||||||
|
{ 0x8A, 0x4D, 0x08 },
|
||||||
|
{ 0x48, 0x83, 0xED, 0x06 },
|
||||||
|
{ 0x48, 0xD3, 0xE8 },
|
||||||
|
{ 0x48, 0x89, 0x45, 0x08 },
|
||||||
|
{ 0x9C },
|
||||||
|
{ 0x8F, 0x45, 0x00 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t nanddw =
|
||||||
|
{
|
||||||
|
"NANDDW", 0,
|
||||||
|
{
|
||||||
|
{ 0x48, 0xF7, 0x55, 0x00 }, // not qword ptr [rbp+0]
|
||||||
|
{ 0x8B, 0x45, 0x00 }, // mov eax, [rbp+0]
|
||||||
|
{ 0x48, 0x83, 0xED, 0x04 }, // sub rbp, 4
|
||||||
|
{ 0x21, 0x45, 0x08 }, // and [rbp+8], eax
|
||||||
|
{ 0x9C }, // pushfq
|
||||||
|
{ 0x8F, 0x45, 0x00 } // pop qword ptr [rbp+0]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vm::handler::profile_t lvsp =
|
||||||
|
{
|
||||||
|
"LVSP", 0,
|
||||||
|
{
|
||||||
|
{ 0x48, 0x8B, 0x6D, 0x00 } // mov rbp, [rbp]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::vector<vm::handler::profile_t*> all =
|
||||||
|
{
|
||||||
|
&sregq,
|
||||||
|
&lregq,
|
||||||
|
&lconstq,
|
||||||
|
&lconstdsx,
|
||||||
|
&lconstwsx,
|
||||||
|
&lconstbzx,
|
||||||
|
&addq,
|
||||||
|
&nandq,
|
||||||
|
&pushvsp,
|
||||||
|
&vmexit,
|
||||||
|
&jmp,
|
||||||
|
&adddw,
|
||||||
|
&writeq,
|
||||||
|
&sregw,
|
||||||
|
&lconstw,
|
||||||
|
&shrw,
|
||||||
|
&shrq,
|
||||||
|
&writeq1,
|
||||||
|
&readw,
|
||||||
|
&lregdw,
|
||||||
|
&shrdw,
|
||||||
|
&sregdw,
|
||||||
|
&lconstbsx,
|
||||||
|
&lconstbsx1,
|
||||||
|
&shrq,
|
||||||
|
&lvsp,
|
||||||
|
&lconstdw,
|
||||||
|
&nanddw
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{D0B6092A-9944-4F24-9486-4B7DAE372619}</ProjectGuid>
|
||||||
|
<RootNamespace>vmprofiler</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>vmprofiler</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>$(ProjectDir)..\libs\*;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<ProjectReference>
|
||||||
|
<LinkLibraryDependencies>true</LinkLibraryDependencies>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="vm.cpp" />
|
||||||
|
<ClCompile Include="vmctx.cpp" />
|
||||||
|
<ClCompile Include="vmutils.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="vmctx.h" />
|
||||||
|
<ClInclude Include="vmp2.hpp" />
|
||||||
|
<ClInclude Include="vmprofiler.hpp" />
|
||||||
|
<ClInclude Include="transform.hpp" />
|
||||||
|
<ClInclude Include="vm.h" />
|
||||||
|
<ClInclude Include="vmutils.h" />
|
||||||
|
<ClInclude Include="ZycoreExportConfig.h" />
|
||||||
|
<ClInclude Include="Zycore\Allocator.h" />
|
||||||
|
<ClInclude Include="Zycore\API\Memory.h" />
|
||||||
|
<ClInclude Include="Zycore\API\Process.h" />
|
||||||
|
<ClInclude Include="Zycore\API\Synchronization.h" />
|
||||||
|
<ClInclude Include="Zycore\API\Terminal.h" />
|
||||||
|
<ClInclude Include="Zycore\API\Thread.h" />
|
||||||
|
<ClInclude Include="Zycore\ArgParse.h" />
|
||||||
|
<ClInclude Include="Zycore\Bitset.h" />
|
||||||
|
<ClInclude Include="Zycore\Comparison.h" />
|
||||||
|
<ClInclude Include="Zycore\Defines.h" />
|
||||||
|
<ClInclude Include="Zycore\Format.h" />
|
||||||
|
<ClInclude Include="Zycore\LibC.h" />
|
||||||
|
<ClInclude Include="Zycore\List.h" />
|
||||||
|
<ClInclude Include="Zycore\Object.h" />
|
||||||
|
<ClInclude Include="Zycore\Status.h" />
|
||||||
|
<ClInclude Include="Zycore\String.h" />
|
||||||
|
<ClInclude Include="Zycore\Types.h" />
|
||||||
|
<ClInclude Include="Zycore\Vector.h" />
|
||||||
|
<ClInclude Include="Zycore\Zycore.h" />
|
||||||
|
<ClInclude Include="ZydisExportConfig.h" />
|
||||||
|
<ClInclude Include="Zydis\Decoder.h" />
|
||||||
|
<ClInclude Include="Zydis\DecoderTypes.h" />
|
||||||
|
<ClInclude Include="Zydis\Formatter.h" />
|
||||||
|
<ClInclude Include="Zydis\FormatterBuffer.h" />
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumInstructionCategory.h" />
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumISAExt.h" />
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumISASet.h" />
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumMnemonic.h" />
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumRegister.h" />
|
||||||
|
<ClInclude Include="Zydis\Internal\DecoderData.h" />
|
||||||
|
<ClInclude Include="Zydis\Internal\FormatterATT.h" />
|
||||||
|
<ClInclude Include="Zydis\Internal\FormatterBase.h" />
|
||||||
|
<ClInclude Include="Zydis\Internal\FormatterIntel.h" />
|
||||||
|
<ClInclude Include="Zydis\Internal\SharedData.h" />
|
||||||
|
<ClInclude Include="Zydis\Internal\String.h" />
|
||||||
|
<ClInclude Include="Zydis\MetaInfo.h" />
|
||||||
|
<ClInclude Include="Zydis\Mnemonic.h" />
|
||||||
|
<ClInclude Include="Zydis\Register.h" />
|
||||||
|
<ClInclude Include="Zydis\SharedTypes.h" />
|
||||||
|
<ClInclude Include="Zydis\ShortString.h" />
|
||||||
|
<ClInclude Include="Zydis\Status.h" />
|
||||||
|
<ClInclude Include="Zydis\Utils.h" />
|
||||||
|
<ClInclude Include="Zydis\Zydis.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,191 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\Zydis">
|
||||||
|
<UniqueIdentifier>{43dd25dc-b71a-48bd-8a82-85d8b110d20e}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\Zycore">
|
||||||
|
<UniqueIdentifier>{8da4f34c-1d15-45b3-a629-f9d5ade75933}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\Zydis\Generated">
|
||||||
|
<UniqueIdentifier>{0ced62af-23a0-4a79-b71c-8c61ede4464e}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\Zydis\Internal">
|
||||||
|
<UniqueIdentifier>{8616528d-41ba-47bd-8516-500eca2a2f67}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\Zycore\API">
|
||||||
|
<UniqueIdentifier>{30014ebf-0535-460c-9cde-01ac1729831f}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="vm.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vmutils.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vmctx.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="vm.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vmutils.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="transform.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ZycoreExportConfig.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ZydisExportConfig.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Decoder.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\DecoderTypes.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Formatter.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\FormatterBuffer.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\MetaInfo.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Mnemonic.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Register.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\SharedTypes.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\ShortString.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Status.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Utils.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Zydis.h">
|
||||||
|
<Filter>Header Files\Zydis</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumInstructionCategory.h">
|
||||||
|
<Filter>Header Files\Zydis\Generated</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumISAExt.h">
|
||||||
|
<Filter>Header Files\Zydis\Generated</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumISASet.h">
|
||||||
|
<Filter>Header Files\Zydis\Generated</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumMnemonic.h">
|
||||||
|
<Filter>Header Files\Zydis\Generated</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Generated\EnumRegister.h">
|
||||||
|
<Filter>Header Files\Zydis\Generated</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Internal\DecoderData.h">
|
||||||
|
<Filter>Header Files\Zydis\Internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Internal\FormatterATT.h">
|
||||||
|
<Filter>Header Files\Zydis\Internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Internal\FormatterBase.h">
|
||||||
|
<Filter>Header Files\Zydis\Internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Internal\FormatterIntel.h">
|
||||||
|
<Filter>Header Files\Zydis\Internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Internal\SharedData.h">
|
||||||
|
<Filter>Header Files\Zydis\Internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zydis\Internal\String.h">
|
||||||
|
<Filter>Header Files\Zydis\Internal</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Allocator.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\ArgParse.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Bitset.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Comparison.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Defines.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Format.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\LibC.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\List.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Object.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Status.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\String.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Types.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Vector.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\Zycore.h">
|
||||||
|
<Filter>Header Files\Zycore</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\API\Memory.h">
|
||||||
|
<Filter>Header Files\Zycore\API</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\API\Process.h">
|
||||||
|
<Filter>Header Files\Zycore\API</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\API\Synchronization.h">
|
||||||
|
<Filter>Header Files\Zycore\API</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\API\Terminal.h">
|
||||||
|
<Filter>Header Files\Zycore\API</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Zycore\API\Thread.h">
|
||||||
|
<Filter>Header Files\Zycore\API</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vmprofiler.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vmp2.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vmctx.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LocalDebuggerCommandArguments>$(ProjectDir)..\refbuilds\vmptest.vmp.exe output.vmp2 0x1000 0x140000000</LocalDebuggerCommandArguments>
|
||||||
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,334 @@
|
|||||||
|
#include "vmutils.h"
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
namespace reg
|
||||||
|
{
|
||||||
|
ZydisRegister to64(ZydisRegister reg)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case ZYDIS_REGISTER_AL:
|
||||||
|
return ZYDIS_REGISTER_RAX;
|
||||||
|
case ZYDIS_REGISTER_CL:
|
||||||
|
return ZYDIS_REGISTER_RCX;
|
||||||
|
case ZYDIS_REGISTER_DL:
|
||||||
|
return ZYDIS_REGISTER_RDX;
|
||||||
|
case ZYDIS_REGISTER_BL:
|
||||||
|
return ZYDIS_REGISTER_RBX;
|
||||||
|
case ZYDIS_REGISTER_AH:
|
||||||
|
return ZYDIS_REGISTER_RAX;
|
||||||
|
case ZYDIS_REGISTER_CH:
|
||||||
|
return ZYDIS_REGISTER_RCX;
|
||||||
|
case ZYDIS_REGISTER_DH:
|
||||||
|
return ZYDIS_REGISTER_RDX;
|
||||||
|
case ZYDIS_REGISTER_BH:
|
||||||
|
return ZYDIS_REGISTER_RBX;
|
||||||
|
case ZYDIS_REGISTER_SPL:
|
||||||
|
return ZYDIS_REGISTER_RSP;
|
||||||
|
case ZYDIS_REGISTER_BPL:
|
||||||
|
return ZYDIS_REGISTER_RBP;
|
||||||
|
case ZYDIS_REGISTER_SIL:
|
||||||
|
return ZYDIS_REGISTER_RSI;
|
||||||
|
case ZYDIS_REGISTER_DIL:
|
||||||
|
return ZYDIS_REGISTER_RDI;
|
||||||
|
case ZYDIS_REGISTER_R8B:
|
||||||
|
return ZYDIS_REGISTER_R8;
|
||||||
|
case ZYDIS_REGISTER_R9B:
|
||||||
|
return ZYDIS_REGISTER_R9;
|
||||||
|
case ZYDIS_REGISTER_R10B:
|
||||||
|
return ZYDIS_REGISTER_R10;
|
||||||
|
case ZYDIS_REGISTER_R11B:
|
||||||
|
return ZYDIS_REGISTER_R11;
|
||||||
|
case ZYDIS_REGISTER_R12B:
|
||||||
|
return ZYDIS_REGISTER_R12;
|
||||||
|
case ZYDIS_REGISTER_R13B:
|
||||||
|
return ZYDIS_REGISTER_R13;
|
||||||
|
case ZYDIS_REGISTER_R14B:
|
||||||
|
return ZYDIS_REGISTER_R14;
|
||||||
|
case ZYDIS_REGISTER_R15B:
|
||||||
|
return ZYDIS_REGISTER_R15;
|
||||||
|
case ZYDIS_REGISTER_AX:
|
||||||
|
return ZYDIS_REGISTER_RAX;
|
||||||
|
case ZYDIS_REGISTER_CX:
|
||||||
|
return ZYDIS_REGISTER_RCX;
|
||||||
|
case ZYDIS_REGISTER_DX:
|
||||||
|
return ZYDIS_REGISTER_RDX;
|
||||||
|
case ZYDIS_REGISTER_BX:
|
||||||
|
return ZYDIS_REGISTER_RBX;
|
||||||
|
case ZYDIS_REGISTER_SP:
|
||||||
|
return ZYDIS_REGISTER_RSP;
|
||||||
|
case ZYDIS_REGISTER_BP:
|
||||||
|
return ZYDIS_REGISTER_RBP;
|
||||||
|
case ZYDIS_REGISTER_SI:
|
||||||
|
return ZYDIS_REGISTER_RSI;
|
||||||
|
case ZYDIS_REGISTER_DI:
|
||||||
|
return ZYDIS_REGISTER_RDI;
|
||||||
|
case ZYDIS_REGISTER_R8W:
|
||||||
|
return ZYDIS_REGISTER_R8;
|
||||||
|
case ZYDIS_REGISTER_R9W:
|
||||||
|
return ZYDIS_REGISTER_R9;
|
||||||
|
case ZYDIS_REGISTER_R10W:
|
||||||
|
return ZYDIS_REGISTER_R10;
|
||||||
|
case ZYDIS_REGISTER_R11W:
|
||||||
|
return ZYDIS_REGISTER_R11;
|
||||||
|
case ZYDIS_REGISTER_R12W:
|
||||||
|
return ZYDIS_REGISTER_R12;
|
||||||
|
case ZYDIS_REGISTER_R13W:
|
||||||
|
return ZYDIS_REGISTER_R13;
|
||||||
|
case ZYDIS_REGISTER_R14W:
|
||||||
|
return ZYDIS_REGISTER_R14;
|
||||||
|
case ZYDIS_REGISTER_R15W:
|
||||||
|
return ZYDIS_REGISTER_R15;
|
||||||
|
case ZYDIS_REGISTER_EAX:
|
||||||
|
return ZYDIS_REGISTER_RAX;
|
||||||
|
case ZYDIS_REGISTER_ECX:
|
||||||
|
return ZYDIS_REGISTER_RCX;
|
||||||
|
case ZYDIS_REGISTER_EDX:
|
||||||
|
return ZYDIS_REGISTER_RDX;
|
||||||
|
case ZYDIS_REGISTER_EBX:
|
||||||
|
return ZYDIS_REGISTER_RBX;
|
||||||
|
case ZYDIS_REGISTER_ESP:
|
||||||
|
return ZYDIS_REGISTER_RSP;
|
||||||
|
case ZYDIS_REGISTER_EBP:
|
||||||
|
return ZYDIS_REGISTER_RBP;
|
||||||
|
case ZYDIS_REGISTER_ESI:
|
||||||
|
return ZYDIS_REGISTER_RSI;
|
||||||
|
case ZYDIS_REGISTER_EDI:
|
||||||
|
return ZYDIS_REGISTER_RDI;
|
||||||
|
case ZYDIS_REGISTER_R8D:
|
||||||
|
return ZYDIS_REGISTER_R8;
|
||||||
|
case ZYDIS_REGISTER_R9D:
|
||||||
|
return ZYDIS_REGISTER_R9;
|
||||||
|
case ZYDIS_REGISTER_R10D:
|
||||||
|
return ZYDIS_REGISTER_R10;
|
||||||
|
case ZYDIS_REGISTER_R11D:
|
||||||
|
return ZYDIS_REGISTER_R11;
|
||||||
|
case ZYDIS_REGISTER_R12D:
|
||||||
|
return ZYDIS_REGISTER_R12;
|
||||||
|
case ZYDIS_REGISTER_R13D:
|
||||||
|
return ZYDIS_REGISTER_R13;
|
||||||
|
case ZYDIS_REGISTER_R14D:
|
||||||
|
return ZYDIS_REGISTER_R14;
|
||||||
|
case ZYDIS_REGISTER_R15D:
|
||||||
|
return ZYDIS_REGISTER_R15;
|
||||||
|
}
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compare(ZydisRegister a, ZydisRegister b)
|
||||||
|
{
|
||||||
|
return to64(a) == to64(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(const ZydisDecodedInstruction& instr)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
ZydisFormatter formatter;
|
||||||
|
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||||
|
ZydisFormatterFormatInstruction(&formatter, &instr,
|
||||||
|
buffer, sizeof(buffer), 0u);
|
||||||
|
|
||||||
|
puts(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(zydis_routine_t& routine)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
ZydisFormatter formatter;
|
||||||
|
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||||
|
|
||||||
|
for (auto [instr, raw, addr] : routine)
|
||||||
|
{
|
||||||
|
std::printf("> 0x%p ", addr);
|
||||||
|
ZydisFormatterFormatInstruction(&formatter, &instr,
|
||||||
|
buffer, sizeof(buffer), addr);
|
||||||
|
|
||||||
|
puts(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_jmp(const ZydisDecodedInstruction& instr)
|
||||||
|
{
|
||||||
|
switch (instr.mnemonic)
|
||||||
|
{
|
||||||
|
case ZYDIS_MNEMONIC_JB:
|
||||||
|
case ZYDIS_MNEMONIC_JBE:
|
||||||
|
case ZYDIS_MNEMONIC_JCXZ:
|
||||||
|
case ZYDIS_MNEMONIC_JECXZ:
|
||||||
|
case ZYDIS_MNEMONIC_JKNZD:
|
||||||
|
case ZYDIS_MNEMONIC_JKZD:
|
||||||
|
case ZYDIS_MNEMONIC_JL:
|
||||||
|
case ZYDIS_MNEMONIC_JLE:
|
||||||
|
case ZYDIS_MNEMONIC_JMP:
|
||||||
|
case ZYDIS_MNEMONIC_JNB:
|
||||||
|
case ZYDIS_MNEMONIC_JNBE:
|
||||||
|
case ZYDIS_MNEMONIC_JNL:
|
||||||
|
case ZYDIS_MNEMONIC_JNLE:
|
||||||
|
case ZYDIS_MNEMONIC_JNO:
|
||||||
|
case ZYDIS_MNEMONIC_JNP:
|
||||||
|
case ZYDIS_MNEMONIC_JNS:
|
||||||
|
case ZYDIS_MNEMONIC_JNZ:
|
||||||
|
case ZYDIS_MNEMONIC_JO:
|
||||||
|
case ZYDIS_MNEMONIC_JP:
|
||||||
|
case ZYDIS_MNEMONIC_JRCXZ:
|
||||||
|
case ZYDIS_MNEMONIC_JS:
|
||||||
|
case ZYDIS_MNEMONIC_JZ:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool flatten(zydis_routine_t& routine, std::uintptr_t routine_addr, bool keep_jmps)
|
||||||
|
{
|
||||||
|
ZydisDecoder decoder;
|
||||||
|
ZydisDecodedInstruction instr;
|
||||||
|
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
|
||||||
|
|
||||||
|
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, reinterpret_cast<void*>(
|
||||||
|
routine_addr), 0x1000, &instr)))
|
||||||
|
{
|
||||||
|
std::vector<u8> raw_instr;
|
||||||
|
raw_instr.insert(raw_instr.begin(),
|
||||||
|
(u8*)routine_addr,
|
||||||
|
(u8*)routine_addr + instr.length);
|
||||||
|
|
||||||
|
if (is_jmp(instr))
|
||||||
|
{
|
||||||
|
if (instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER)
|
||||||
|
{
|
||||||
|
routine.push_back({ instr, raw_instr, routine_addr });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keep_jmps)
|
||||||
|
routine.push_back({ instr, raw_instr, routine_addr });
|
||||||
|
|
||||||
|
ZydisCalcAbsoluteAddress(&instr, &instr.operands[0], routine_addr, &routine_addr);
|
||||||
|
}
|
||||||
|
else if (instr.mnemonic == ZYDIS_MNEMONIC_RET)
|
||||||
|
{
|
||||||
|
routine.push_back({ instr, raw_instr, routine_addr });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
routine.push_back({ instr, raw_instr, routine_addr });
|
||||||
|
routine_addr += instr.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deobfuscate(zydis_routine_t& routine)
|
||||||
|
{
|
||||||
|
static const auto _uses =
|
||||||
|
[](ZydisDecodedOperand& op, ZydisRegister reg) -> bool
|
||||||
|
{
|
||||||
|
switch (op.type)
|
||||||
|
{
|
||||||
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
|
{
|
||||||
|
return reg::compare(op.mem.base, reg) || reg::compare(op.mem.index, reg);
|
||||||
|
}
|
||||||
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||||
|
{
|
||||||
|
return reg::compare(op.reg.value, reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const auto _writes =
|
||||||
|
[](ZydisDecodedInstruction& inst) -> bool
|
||||||
|
{
|
||||||
|
for (auto idx = 0; idx < inst.operand_count; ++idx)
|
||||||
|
if (inst.operands[idx].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const auto _remove =
|
||||||
|
[](zydis_routine_t& routine, zydis_routine_t::iterator itr,
|
||||||
|
ZydisRegister reg, u32 opcode_size) -> void
|
||||||
|
{
|
||||||
|
for (; itr >= routine.begin(); --itr)
|
||||||
|
{
|
||||||
|
const auto instruction = &itr->instr;
|
||||||
|
bool stop = false;
|
||||||
|
|
||||||
|
if (instruction->mnemonic == ZYDIS_MNEMONIC_JMP)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (auto op_idx = 0u; op_idx < instruction->operand_count; ++op_idx)
|
||||||
|
{
|
||||||
|
const auto op = &instruction->operands[op_idx];
|
||||||
|
|
||||||
|
if (!_uses(*op, reg))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (op->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
|
{
|
||||||
|
stop = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcode_size < 32 && op->size > opcode_size)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE)
|
||||||
|
op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE;
|
||||||
|
else stop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_writes(*instruction))
|
||||||
|
routine.erase(itr);
|
||||||
|
|
||||||
|
else if (stop) break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& instr_data : routine)
|
||||||
|
{
|
||||||
|
if (routine.empty() || routine.size() == 1 ||
|
||||||
|
instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (auto itr = routine.begin() + 1; itr != routine.end(); itr++)
|
||||||
|
{
|
||||||
|
if (itr->instr.mnemonic == ZYDIS_MNEMONIC_JMP ||
|
||||||
|
itr->instr.mnemonic == ZYDIS_MNEMONIC_RET)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// find the write operations that happen...
|
||||||
|
for (auto idx = 0u; idx < itr->instr.operand_count; ++idx)
|
||||||
|
{
|
||||||
|
const auto op = &itr->instr.operands[idx];
|
||||||
|
// if its a read, continue to next opcode...
|
||||||
|
if (op->actions & ZYDIS_OPERAND_ACTION_MASK_READ)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if its not a write then continue to next opcode...
|
||||||
|
if (!(op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if this operand is not a register then we continue...
|
||||||
|
if (op->type != ZYDIS_OPERAND_TYPE_REGISTER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// else we see if we can remove dead writes to this register...
|
||||||
|
_remove(routine, itr - 1, op->reg.value, op->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <Zydis/Zydis.h>
|
||||||
|
#include <Zydis/Utils.h>
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
|
using u8 = unsigned char;
|
||||||
|
using u16 = unsigned short;
|
||||||
|
using u32 = unsigned int;
|
||||||
|
using u64 = unsigned long long;
|
||||||
|
using u128 = __m128;
|
||||||
|
|
||||||
|
struct zydis_instr_t
|
||||||
|
{
|
||||||
|
ZydisDecodedInstruction instr;
|
||||||
|
std::vector<u8> raw;
|
||||||
|
std::uintptr_t addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
using zydis_routine_t = std::vector<zydis_instr_t>;
|
||||||
|
|
||||||
|
namespace vm
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
namespace reg
|
||||||
|
{
|
||||||
|
// converts say... AL to RAX...
|
||||||
|
ZydisRegister to64(ZydisRegister reg);
|
||||||
|
bool compare(ZydisRegister a, ZydisRegister b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(zydis_routine_t& routine);
|
||||||
|
void print(const ZydisDecodedInstruction& instr);
|
||||||
|
bool is_jmp(const ZydisDecodedInstruction& instr);
|
||||||
|
|
||||||
|
bool flatten(zydis_routine_t& routine, std::uintptr_t routine_addr, bool keep_jmps = false);
|
||||||
|
void deobfuscate(zydis_routine_t& routine);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue