Skip to content

Commit

Permalink
Add rand API (#5)
Browse files Browse the repository at this point in the history
The rand implementations have a bunch of basic dependencies, so these
are introduced as well:
- cxplat status code
- Init/Uninit APIs
- cxplat assertion APIs
- code annotations

Also add a simple test case for code coverage.

APIs and implementations taken from https://github.com/microsoft/msquic
  • Loading branch information
nigriMSFT authored Apr 29, 2024
1 parent d8e58a6 commit 8d4bab8
Show file tree
Hide file tree
Showing 22 changed files with 731 additions and 31 deletions.
24 changes: 20 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ message(STATUS "Platform: ${CX_PLATFORM}")
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
set(SELF_DIR "$\{SELF_DIR\}")

enable_testing()

option(CXPLAT_BUILD_TEST "Builds the test code" OFF)
option(CXPLAT_UWP_BUILD "Build for UWP" OFF)
option(CXPLAT_GAMECORE_BUILD "Build for GameCore" OFF)
Expand All @@ -93,9 +95,7 @@ if (CXPLAT_UWP_BUILD OR CXPLAT_GAMECORE_BUILD)
set(CXPLAT_BUILD_TEST OFF)
endif()

if (NOT CXPLAT_BUILD_SHARED)
cmake_minimum_required(VERSION 3.20)
endif()
cmake_minimum_required(VERSION 3.20)

if (CXPLAT_PDBALTPATH AND MSVC)
# Disabled in all cases because generation is broken.
Expand Down Expand Up @@ -131,6 +131,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CXPLAT_OUTPUT_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CXPLAT_OUTPUT_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CXPLAT_OUTPUT_DIR})

set(CXPLAT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/inc)

if (WIN32)
set(CXPLAT_WARNING_FLAGS /WX /W4 /sdl /wd4206 CACHE INTERNAL "")
set(CXPLAT_COMMON_FLAGS "")
Expand Down Expand Up @@ -168,14 +170,26 @@ else()
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckIncludeFile)
check_symbol_exists(_SC_PHYS_PAGES unistd.h HAS__SC_PHYS_PAGES)
check_function_exists(sysconf HAS_SYSCONF)

if (CX_PLATFORM STREQUAL "linux")
include(CheckCCompilerFlag)
elseif(CX_PLATFORM STREQUAL "darwin")
check_function_exists(sysctl HAS_SYSCTL)
endif()

set(CXPLAT_COMMON_FLAGS "")
set(CXPLAT_COMMON_DEFINES _GNU_SOURCE)

if (HAS__SC_PHYS_PAGES)
list(APPEND CXPLAT_COMMON_DEFINES HAS__SC_PHYS_PAGES)
endif()
if (HAS_SYSCONF)
list(APPEND CXPLAT_COMMON_DEFINES HAS_SYSCONF)
endif()
if (HAS_SYSCTL)
list(APPEND CXPLAT_COMMON_DEFINES HAS_SYSCTL)
endif()
set(CXPLAT_WARNING_FLAGS -Werror -Wall -Wextra -Wformat=2 -Wno-type-limits
-Wno-unknown-pragmas -Wno-multichar -Wno-missing-field-initializers
CACHE INTERNAL "")
Expand Down Expand Up @@ -347,6 +361,8 @@ else() #!WIN32
set(CXPLAT_CXX_FLAGS ${CXPLAT_COMMON_FLAGS})
endif()

add_subdirectory(src/inc)

# Product code
add_subdirectory(src/lib/)

Expand Down
30 changes: 30 additions & 0 deletions inc/cxplat.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,33 @@
#else
#error "Unsupported Platform"
#endif

#if defined(__cplusplus)
extern "C" {
#endif

//
// Initializes the cxplat library. Calls to this and CxPlatUninitialize must be
// serialized and cannot overlap.
//
PAGEDX
_IRQL_requires_max_(PASSIVE_LEVEL)
CXPLAT_STATUS
CxPlatInitialize(
void
);

//
// Uninitializes the cxplat library. Calls to this and CxPlatInitialize must be
// serialized and cannot overlap.
//
PAGEDX
_IRQL_requires_max_(PASSIVE_LEVEL)
void
CxPlatUninitialize(
void
);

#if defined(__cplusplus)
}
#endif
103 changes: 103 additions & 0 deletions inc/cxplat_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,115 @@
#ifndef CXPLAT_POSIX_H
#define CXPLAT_POSIX_H

// For FreeBSD
#if defined(__FreeBSD__)
#include <sys/socket.h>
#include <netinet/in.h>
#define ETIME ETIMEDOUT
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdalign.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include "cxplat_sal_stub.h"

#if defined(__cplusplus)
extern "C" {
#endif

//
// Defines that are present on other platforms but not this one
//

#define UNREFERENCED_PARAMETER(P) (void)(P)

//
// Status Codes
//

#define CXPLAT_STATUS unsigned int
#define CXPLAT_FAILED(X) ((int)(X) > 0)
#define CXPLAT_SUCCEEDED(X) ((int)(X) <= 0)

#define CXPLAT_STATUS_SUCCESS ((CXPLAT_STATUS)0) // 0

//
// Code Annotations
//

#define INITCODE
#define PAGEDX

//
// Static Analysis Interfaces
//

#if defined(__clang__)
#define CXPLAT_NO_SANITIZE(X) __attribute__((no_sanitize(X)))
#else
#define CXPLAT_NO_SANITIZE(X)
#endif

#define CXPLAT_ANALYSIS_ASSERT(X)
#define CXPLAT_ANALYSIS_ASSUME(X)

//
// Assertion Interfaces
//

__attribute__((noinline, noreturn))
void
cxplat_bugcheck(
_In_z_ const char* File,
_In_ int Line,
_In_z_ const char* Expr
);

void
CxPlatLogAssert(
_In_z_ const char* File,
_In_ int Line,
_In_z_ const char* Expr
);

#define CXPLAT_STATIC_ASSERT(X,Y) static_assert(X, Y);

#define CXPLAT_FRE_ASSERT(exp) ((exp) ? (void)0 : (CxPlatLogAssert(__FILE__, __LINE__, #exp), cxplat_bugcheck(__FILE__, __LINE__, #exp)));
#define CXPLAT_FRE_ASSERTMSG(exp, Y) CXPLAT_FRE_ASSERT(exp)

#ifdef DEBUG
#define CXPLAT_DBG_ASSERT(exp) CXPLAT_FRE_ASSERT(exp)
#define CXPLAT_DBG_ASSERTMSG(exp, msg) CXPLAT_FRE_ASSERT(exp)
#else
#define CXPLAT_DBG_ASSERT(exp)
#define CXPLAT_DBG_ASSERTMSG(exp, msg)
#endif

//
// Crypto Interfaces
//

CXPLAT_STATUS
CxPlatRandom(
_In_ uint32_t BufferLen,
_Out_writes_bytes_(BufferLen) void* Buffer
);

#if defined(__cplusplus)
}
Expand Down
118 changes: 118 additions & 0 deletions inc/cxplat_winkernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,128 @@
#ifndef CXPLAT_WINKERNEL_H
#define CXPLAT_WINKERNEL_H

#include <ntddk.h>

#if defined(__cplusplus)
extern "C" {
#endif

//
// Defines that are present on other platforms but not this one
//

typedef INT8 int8_t;
typedef INT16 int16_t;
typedef INT32 int32_t;
typedef INT64 int64_t;

typedef UINT8 uint8_t;
typedef UINT16 uint16_t;
typedef UINT32 uint32_t;
typedef UINT64 uint64_t;

//
// Status Codes
//

#define CXPLAT_STATUS NTSTATUS
#define CXPLAT_FAILED(X) (!NT_SUCCESS(X))
#define CXPLAT_SUCCEEDED(X) NT_SUCCESS(X)

#define CXPLAT_STATUS_SUCCESS STATUS_SUCCESS // 0x0

//
// Code Annotations
//

#ifndef KRTL_INIT_SEGMENT
#define KRTL_INIT_SEGMENT "INIT"
#endif
#ifndef KRTL_PAGE_SEGMENT
#define KRTL_PAGE_SEGMENT "PAGE"
#endif
#ifndef KRTL_NONPAGED_SEGMENT
#define KRTL_NONPAGED_SEGMENT ".text"
#endif

// Use on code in the INIT segment. (Code is discarded after DriverEntry returns.)
#define INITCODE __declspec(code_seg(KRTL_INIT_SEGMENT))

// Use on pageable functions.
#define PAGEDX __declspec(code_seg(KRTL_PAGE_SEGMENT))

//
// Static Analysis Interfaces
//

#define CXPLAT_NO_SANITIZE(X)

#if defined(_PREFAST_)
// _Analysis_assume_ will never result in any code generation for _exp,
// so using it will not have runtime impact, even if _exp has side effects.
#define CXPLAT_ANALYSIS_ASSUME(_exp) _Analysis_assume_(_exp)
#else // _PREFAST_
// CXPLAT_ANALYSIS_ASSUME ensures that _exp is parsed in non-analysis compile.
// On DEBUG, it's guaranteed to be parsed as part of the normal compile, but
// with non-DEBUG, use __noop to ensure _exp is parseable but without code
// generation.
#if DEBUG
#define CXPLAT_ANALYSIS_ASSUME(_exp) ((void) 0)
#else // DEBUG
#define CXPLAT_ANALYSIS_ASSUME(_exp) __noop(_exp)
#endif // DEBUG
#endif // _PREFAST_

#define CXPLAT_ANALYSIS_ASSERT(X) __analysis_assert(X)

//
// Assertion Interfaces
//

_IRQL_requires_max_(DISPATCH_LEVEL)
void
CxPlatLogAssert(
_In_z_ const char* File,
_In_ int Line,
_In_z_ const char* Expr
);

#define CXPLAT_WIDE_STRING(_str) L##_str

#define CXPLAT_ASSERT_NOOP(_exp, _msg) \
(CXPLAT_ANALYSIS_ASSUME(_exp), 0)

#define CXPLAT_ASSERT_CRASH(_exp, _msg) \
(CXPLAT_ANALYSIS_ASSUME(_exp), \
((!(_exp)) ? \
(CxPlatLogAssert(__FILE__, __LINE__, #_exp), \
__annotation(L"Debug", L"AssertFail", _msg), \
DbgRaiseAssertionFailure(), FALSE) : \
TRUE))

#define CXPLAT_STATIC_ASSERT(X,Y) static_assert(X,Y)

#define CXPLAT_FRE_ASSERT(_exp) CXPLAT_ASSERT_CRASH(_exp, CXPLAT_WIDE_STRING(#_exp))
#define CXPLAT_FRE_ASSERTMSG(_exp, _msg) CXPLAT_ASSERT_CRASH(_exp, CXPLAT_WIDE_STRING(_msg))

#if DEBUG
#define CXPLAT_DBG_ASSERT(_exp) CXPLAT_ASSERT_CRASH(_exp, CXPLAT_WIDE_STRING(#_exp))
#define CXPLAT_DBG_ASSERTMSG(_exp, _msg) CXPLAT_ASSERT_CRASH(_exp, CXPLAT_WIDE_STRING(_msg))
#else
#define CXPLAT_DBG_ASSERT(_exp) CXPLAT_ASSERT_NOOP(_exp, CXPLAT_WIDE_STRING(#_exp))
#define CXPLAT_DBG_ASSERTMSG(_exp, _msg) CXPLAT_ASSERT_NOOP(_exp, CXPLAT_WIDE_STRING(_msg))
#endif

//
// Crypto Interfaces
//

_IRQL_requires_max_(DISPATCH_LEVEL)
CXPLAT_STATUS
CxPlatRandom(
_In_ uint32_t BufferLen,
_Out_writes_bytes_(BufferLen) void* Buffer
);

#if defined(__cplusplus)
}
Expand Down
Loading

0 comments on commit 8d4bab8

Please sign in to comment.