Improved no-libc support

- Added `ZYDIS_NO_LIBC` CMake switch
- When enabled, removes dependency on `memset`, `memcpy` and `strlen`
This commit is contained in:
Joel Höner 2017-11-24 19:25:48 +01:00
parent eefeb6c18d
commit df949a5eb0
5 changed files with 112 additions and 30 deletions

View File

@ -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

View File

@ -29,6 +29,7 @@
#include <Zydis/Status.h>
#include <DecoderData.h>
#include <SharedData.h>
#include <LibC.h>
/* ============================================================================================== */
/* 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;

View File

@ -27,6 +27,7 @@
#include <string.h>
#include <ctype.h>
#include <FormatHelper.h>
#include <LibC.h>
/* ============================================================================================== */
/* 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:

View File

@ -29,6 +29,7 @@
#include <Zydis/Formatter.h>
#include <Zydis/Utils.h>
#include <FormatHelper.h>
#include <LibC.h>
/* ============================================================================================== */
/* 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;

82
src/LibC.h Normal file
View File

@ -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 <Zydis/Defines.h>
#include <stdint.h>
#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 (uint8_t* p = (uint8_t*)ptr; *p; ++p) *p = 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 */