diff --git a/CMakeLists.txt b/CMakeLists.txt index f859feb..7ca73fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,26 +15,20 @@ option(ZYDIS_FEATURE_DECODER option(ZYDIS_FEATURE_FORMATTER "Enable instruction formatting functionality" ON) -#option(ZYDIS_FEATURE_ENCODER -# "Enable instruction encoding functionality" -# OFF) option(ZYDIS_FEATURE_EVEX "Enable support for EVEX instructions" ON) option(ZYDIS_FEATURE_MVEX "Enable support for MVEX instructions" ON) -option(ZYDIS_FEATURE_FLAGS - "Include information about affected flags" - ON) -option(ZYDIS_FEATURE_CPUID - "Include information about CPUID feature-flags" - OFF) # Build configuration option(BUILD_SHARED_LIBS "Build shared libraries" OFF) +option(ZYDIS_NO_LIBC + "Don't use any C standard library functions (for exotic build-envs like kernel drivers)" + OFF) option(ZYDIS_BUILD_EXAMPLES "Build examples" ON) @@ -95,6 +89,9 @@ endif () if (NOT ZYDIS_FEATURE_MVEX) target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_MVEX") endif () +if (ZYDIS_NO_LIBC) + target_compile_definitions("Zydis" PUBLIC "ZYDIS_NO_LIBC") +endif () target_sources("Zydis" PUBLIC diff --git a/src/Decoder.c b/src/Decoder.c index c7da321..c7ef291 100644 --- a/src/Decoder.c +++ b/src/Decoder.c @@ -29,6 +29,7 @@ #include #include #include +#include /* ============================================================================================== */ /* Internal enums and types */ @@ -327,10 +328,10 @@ static ZydisStatus ZydisInputNextBytes(ZydisDecoderContext* context, if (context->bufferLen >= numberOfBytes) { - memcpy(&instruction->data[instruction->length], context->buffer, numberOfBytes); + ZydisMemoryCopy(&instruction->data[instruction->length], context->buffer, numberOfBytes); instruction->length += numberOfBytes; - memcpy(value, context->buffer, numberOfBytes); + ZydisMemoryCopy(value, context->buffer, numberOfBytes); context->buffer += numberOfBytes; context->bufferLen -= numberOfBytes; @@ -2243,7 +2244,7 @@ static void ZydisSetAccessedFlags(ZydisDecodedInstruction* instruction, ZYDIS_ASSERT(ZYDIS_ARRAY_SIZE(instruction->accessedFlags) == ZYDIS_ARRAY_SIZE(flags->action)); - memcpy(&instruction->accessedFlags, &flags->action, ZYDIS_ARRAY_SIZE(flags->action)); + ZydisMemoryCopy(&instruction->accessedFlags, &flags->action, ZYDIS_ARRAY_SIZE(flags->action)); } /** @@ -4447,7 +4448,7 @@ ZydisStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machineMode decoder->machineMode = machineMode; decoder->addressWidth = addressWidth; - memcpy(&decoder->decoderMode, &decoderModes, sizeof(decoderModes)); + ZydisMemoryCopy(&decoder->decoderMode, &decoderModes, sizeof(decoderModes)); return ZYDIS_STATUS_SUCCESS; } @@ -4478,14 +4479,14 @@ ZydisStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder, const void* bu } ZydisDecoderContext context; - memset(&context.cache, 0, sizeof(context.cache)); + ZydisMemorySet(&context.cache, 0, sizeof(context.cache)); context.decoder = decoder; context.buffer = (uint8_t*)buffer; context.bufferLen = bufferLen; context.lastSegmentPrefix = 0; context.mandatoryCandidate = 0; - memset(instruction, 0, sizeof(*instruction)); + ZydisMemorySet(instruction, 0, sizeof(*instruction)); instruction->machineMode = decoder->machineMode; instruction->stackWidth = decoder->addressWidth; instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_DEFAULT; diff --git a/src/FormatHelper.c b/src/FormatHelper.c index 55e4aa2..b61d6b5 100644 --- a/src/FormatHelper.c +++ b/src/FormatHelper.c @@ -27,6 +27,7 @@ #include #include #include +#include /* ============================================================================================== */ /* Constants */ @@ -113,10 +114,10 @@ ZydisStatus ZydisPrintDecU32(char** buffer, size_t bufferLen, uint32_t value, ui uint32_t const old = value; p -= 2; value /= 100; - memcpy(p, &decimalLookup[(old - (value * 100)) * 2], sizeof(uint16_t)); + ZydisMemoryCopy(p, &decimalLookup[(old - (value * 100)) * 2], sizeof(uint16_t)); } p -= 2; - memcpy(p, &decimalLookup[value * 2], sizeof(uint16_t)); + ZydisMemoryCopy(p, &decimalLookup[value * 2], sizeof(uint16_t)); const size_t n = &temp[ZYDIS_MAXCHARS_DEC_32] - p; if ((bufferLen < (size_t)(n + 1)) || (bufferLen < (size_t)(paddingLength + 1))) @@ -128,10 +129,10 @@ ZydisStatus ZydisPrintDecU32(char** buffer, size_t bufferLen, uint32_t value, ui if (n <= paddingLength) { offset = paddingLength - n + 1; - memset(*buffer, '0', offset); + ZydisMemorySet(*buffer, '0', offset); } - memcpy(&(*buffer)[offset], &p[value < 10], n + 1); + ZydisMemoryCopy(&(*buffer)[offset], &p[value < 10], n + 1); *buffer += n + offset - (uint8_t)(value < 10); return ZYDIS_STATUS_SUCCESS; @@ -163,7 +164,7 @@ ZydisStatus ZydisPrintHexU32(char** buffer, size_t bufferLen, uint32_t value, ui return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; } - memset(*buffer, '0', n); + ZydisMemorySet(*buffer, '0', n); (*buffer)[n] = '\0'; *buffer += n; return ZYDIS_STATUS_SUCCESS; @@ -186,7 +187,7 @@ ZydisStatus ZydisPrintHexU32(char** buffer, size_t bufferLen, uint32_t value, ui if (paddingLength > i) { n = paddingLength - i - 1; - memset(*buffer, '0', n); + ZydisMemorySet(*buffer, '0', n); } } if (uppercase) @@ -222,10 +223,10 @@ ZydisStatus ZydisPrintDecU64(char** buffer, size_t bufferLen, uint64_t value, ui uint64_t const old = value; p -= 2; value /= 100; - memcpy(p, &decimalLookup[(old - (value * 100)) * 2], 2); + ZydisMemoryCopy(p, &decimalLookup[(old - (value * 100)) * 2], 2); } p -= 2; - memcpy(p, &decimalLookup[value * 2], 2); + ZydisMemoryCopy(p, &decimalLookup[value * 2], 2); const size_t n = &temp[ZYDIS_MAXCHARS_DEC_64] - p; if ((bufferLen < (size_t)(n + 1)) || (bufferLen < (size_t)(paddingLength + 1))) @@ -237,10 +238,10 @@ ZydisStatus ZydisPrintDecU64(char** buffer, size_t bufferLen, uint64_t value, ui if (n <= paddingLength) { offset = paddingLength - n + 1; - memset(*buffer, '0', offset); + ZydisMemorySet(*buffer, '0', offset); } - memcpy(&(*buffer)[offset], &p[value < 10], n + 1); + ZydisMemoryCopy(&(*buffer)[offset], &p[value < 10], n + 1); *buffer += n + offset - (uint8_t)(value < 10); return ZYDIS_STATUS_SUCCESS; @@ -272,7 +273,7 @@ ZydisStatus ZydisPrintHexU64(char** buffer, size_t bufferLen, uint64_t value, ui return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; } - memset(*buffer, '0', n); + ZydisMemorySet(*buffer, '0', n); (*buffer)[n] = '\0'; *buffer += n; return ZYDIS_STATUS_SUCCESS; @@ -296,7 +297,7 @@ ZydisStatus ZydisPrintHexU64(char** buffer, size_t bufferLen, uint64_t value, ui if (paddingLength > i) { n = paddingLength - i - 1; - memset(*buffer, '0', n); + ZydisMemorySet(*buffer, '0', n); } } if (uppercase) @@ -329,13 +330,13 @@ ZydisStatus ZydisPrintStr(char** buffer, size_t bufferLen, const char* text, ZYDIS_ASSERT(bufferLen > 0); ZYDIS_ASSERT(text); - const size_t strLen = strlen(text); + const size_t strLen = ZydisStrLen(text); if (strLen >= bufferLen) { return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; } - memcpy(*buffer, text, strLen + 1); + ZydisMemoryCopy(*buffer, text, strLen + 1); switch (letterCase) { case ZYDIS_LETTER_CASE_DEFAULT: diff --git a/src/Formatter.c b/src/Formatter.c index da70db2..2e03fd5 100644 --- a/src/Formatter.c +++ b/src/Formatter.c @@ -29,6 +29,7 @@ #include #include #include +#include /* ============================================================================================== */ /* Instruction formatter */ @@ -909,7 +910,7 @@ ZydisStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle st return ZYDIS_STATUS_INVALID_PARAMETER; } - memset(formatter, 0, sizeof(ZydisFormatter)); + ZydisMemorySet(formatter, 0, sizeof(ZydisFormatter)); formatter->letterCase = ZYDIS_LETTER_CASE_DEFAULT; formatter->forceSegments = ZYDIS_FALSE; formatter->forceOperandSize = ZYDIS_FALSE; diff --git a/src/LibC.h b/src/LibC.h new file mode 100644 index 0000000..0ee831f --- /dev/null +++ b/src/LibC.h @@ -0,0 +1,82 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Joel Höner + + * 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_LIBC_H +#define ZYDIS_LIBC_H + +#include +#include + +#ifndef ZYDIS_NO_LIBC + +/* ============================================================================================== */ +/* LibC is available */ +/* ============================================================================================== */ + +# define ZydisMemoryCopy memcpy +# define ZydisMemorySet memset +# define ZydisStrLen strlen + +#else + +/* ============================================================================================== */ +/* No LibC available, use our own functions */ +/* ============================================================================================== */ + +/* + * 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. + */ + +ZYDIS_INLINE void* ZydisMemorySet(void* ptr, int value, size_t num) +{ + uint8_t c = value & 0xff; + for (size_t i = 0; i < num; ++i) ((uint8_t*)ptr)[i] = c; + return ptr; +} + +ZYDIS_INLINE void* ZydisMemoryCopy(void* dst, const void* src, size_t num) +{ + for (size_t i = 0; i < num; ++i) + { + ((uint8_t*)dst)[i] = ((const uint8_t*)src)[i]; + } + return dst; +} + +ZYDIS_INLINE size_t ZydisStrLen(const char* str) +{ + const char *s; + for (s = str; *s; ++s); + return s - str; +} + +/* ============================================================================================== */ + +#endif + +#endif /* ZYDIS_LIBC_H */