diff --git a/src/ebpf/api/Source.def b/src/ebpf/api/Source.def
new file mode 100644
index 000000000..75be5a4c3
--- /dev/null
+++ b/src/ebpf/api/Source.def
@@ -0,0 +1,10 @@
+LIBRARY
+EXPORTS
+ EbpfApiInit
+ EbpfApiTerminate
+ EbpfLoadProgram
+ EbpfFreeErrorMessage
+ EbpfUnloadProgram
+ EbpfAttachProgram
+ EbpfDetachProgram
+
diff --git a/src/ebpf/api/api.h b/src/ebpf/api/api.h
deleted file mode 100644
index f582df86e..000000000
--- a/src/ebpf/api/api.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved
- * SPDX-License-Identifier: MIT
-*/
-
-#pragma once
-
-#if defined(EBPF_API)
-#define DLL __declspec(dllexport)
-#else
-#define DLL __declspec(dllimport)
-#endif
-
-#define EBPF_HOOK_POINT_XDP 1
-
-DLL DWORD EbpfApiInit();
-
-DLL void EbpfApiTerminate();
-
-DLL DWORD EbpfLoadProgram(const char* file, const char* section_name, HANDLE* handle, char ** error_message);
-DLL void EbpfFreeErrorMessage(char* error_message);
-DLL void EbpfUnloadProgram(HANDLE handle);
-
-DLL DWORD EbpfAttachProgram(HANDLE handle, DWORD hook_point);
-DLL DWORD EbpfDetachProgram(HANDLE handle, DWORD hook_point);
diff --git a/src/ebpf/api/dllmain.cpp b/src/ebpf/api/dllmain.cpp
index d5082a9b2..addcd0007 100644
--- a/src/ebpf/api/dllmain.cpp
+++ b/src/ebpf/api/dllmain.cpp
@@ -22,3 +22,57 @@ BOOL APIENTRY DllMain( HMODULE hModule,
return TRUE;
}
+
+namespace Platform {
+ BOOL
+ DeviceIoControl(
+ _In_ HANDLE hDevice,
+ _In_ DWORD dwIoControlCode,
+ _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer,
+ _In_ DWORD nInBufferSize,
+ _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer,
+ _In_ DWORD nOutBufferSize,
+ _Out_opt_ LPDWORD lpBytesReturned,
+ _Inout_opt_ LPOVERLAPPED lpOverlapped
+ )
+ {
+ return ::DeviceIoControl(
+ hDevice,
+ dwIoControlCode,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize,
+ lpBytesReturned,
+ lpOverlapped);
+ }
+
+ HANDLE
+ CreateFileW(
+ _In_ LPCWSTR lpFileName,
+ _In_ DWORD dwDesiredAccess,
+ _In_ DWORD dwShareMode,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ _In_ DWORD dwCreationDisposition,
+ _In_ DWORD dwFlagsAndAttributes,
+ _In_opt_ HANDLE hTemplateFile
+ )
+ {
+ return ::CreateFileW(
+ lpFileName,
+ dwDesiredAccess,
+ dwShareMode,
+ lpSecurityAttributes,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ hTemplateFile);
+ }
+ BOOL
+ CloseHandle(
+ _In_ _Post_ptr_invalid_ HANDLE hObject
+ )
+ {
+ return ::CloseHandle(hObject);
+ }
+
+}
\ No newline at end of file
diff --git a/src/ebpf/api/ebpfapi.sln b/src/ebpf/api/ebpfapi.sln
index d9b563634..5238dac29 100644
--- a/src/ebpf/api/ebpfapi.sln
+++ b/src/ebpf/api/ebpfapi.sln
@@ -3,12 +3,16 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30907.101
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfapi", "ebpfapi.vcxproj", "{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "EbpfApi.vcxproj", "{75FE223A-3E45-4B0E-A2E8-04285E52E440}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api", "..\libs\api\api.vcxproj", "{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EbpfJitterDemoLib", "..\libs\EbpfJitterDemoLib\EbpfJitterDemoLib.vcxproj", "{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfverifier", "..\..\..\external\ebpf-verifier\build\ebpfverifier.vcxproj", "{939A079D-A1E8-35D9-950F-11B1894D342E}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "..\libs\api\test\test.vcxproj", "{4C10AC76-384C-4539-B884-38E998749FB2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -21,14 +25,30 @@ Global
RelWithDebInfo|x86 = RelWithDebInfo|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x64.ActiveCfg = Debug|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x64.Build.0 = Debug|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x86.ActiveCfg = Debug|Win32
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x86.Build.0 = Debug|Win32
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x64.Build.0 = Release|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x86.ActiveCfg = Release|Win32
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x86.Build.0 = Release|Win32
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x64.ActiveCfg = Release|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x64.Build.0 = Release|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x86.ActiveCfg = Release|Win32
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x86.Build.0 = Release|Win32
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x86.Build.0 = Release|Win32
{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.ActiveCfg = Debug|x64
{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.Build.0 = Debug|x64
{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.ActiveCfg = Debug|Win32
{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.Build.0 = Debug|Win32
- {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.ActiveCfg = Release|x64
- {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.Build.0 = Release|x64
- {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.ActiveCfg = Release|Win32
- {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.Build.0 = Release|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.ActiveCfg = Debug|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.Build.0 = Debug|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.ActiveCfg = Debug|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.Build.0 = Debug|Win32
{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.ActiveCfg = Release|x64
{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.Build.0 = Release|x64
{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x86.ActiveCfg = Release|Win32
@@ -41,10 +61,10 @@ Global
{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x64.Build.0 = Debug|x64
{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.ActiveCfg = Debug|Win32
{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.Build.0 = Debug|Win32
- {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.ActiveCfg = Release|x64
- {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.Build.0 = Release|x64
- {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.ActiveCfg = Release|Win32
- {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.Build.0 = Release|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.ActiveCfg = Debug|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.Build.0 = Debug|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.ActiveCfg = Debug|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.Build.0 = Debug|Win32
{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.ActiveCfg = Release|x64
{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.Build.0 = Release|x64
{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x86.ActiveCfg = Release|Win32
@@ -65,11 +85,27 @@ Global
{939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.ActiveCfg = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.Build.0 = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.ActiveCfg = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.Build.0 = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.ActiveCfg = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.Build.0 = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.ActiveCfg = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.Build.0 = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.ActiveCfg = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.Build.0 = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.ActiveCfg = Release|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.Build.0 = Release|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {9DEA0F2A-7674-46AA-9E15-BC880EF5895D}
+ SolutionGuid = {24EA473A-CDF1-4A87-9E6C-57149BE1EAC0}
EndGlobalSection
EndGlobal
diff --git a/src/ebpf/api/ebpfapi.vcxproj b/src/ebpf/api/ebpfapi.vcxproj
index 133ee0cf3..2e5d5b4d1 100644
--- a/src/ebpf/api/ebpfapi.vcxproj
+++ b/src/ebpf/api/ebpfapi.vcxproj
@@ -21,10 +21,10 @@
16.0
Win32Proj
- {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68}
- ebpfapi
+ {75fe223a-3e45-4b0e-a2e8-04285e52e440}
+ EbpfApi
10.0
- $(ProjectDir)../../../external/ebpf-verifier/
+ dll
@@ -79,9 +79,11 @@
true
+ EbpfApi
false
+ EbpfApi
@@ -96,6 +98,7 @@
Windows
true
false
+ Source.def
@@ -115,6 +118,7 @@
true
true
false
+ Source.def
@@ -125,13 +129,12 @@
true
Use
pch.h
- $(PrevailDir)src;..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories)
- stdcpp17
Windows
true
false
+ Source.def
@@ -144,8 +147,7 @@
true
Use
pch.h
- $(PrevailDir)src;..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories)
- stdcpp17
+ ..\libs\api;%(AdditionalIncludeDirectories)
Windows
@@ -153,17 +155,14 @@
true
true
false
+ Source.def
-
-
-
-
Create
@@ -171,29 +170,22 @@
Create
Create
-
- NotUsing
-
{939a079d-a1e8-35d9-950f-11b1894d342e}
+
+ {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68}
+
{245f0ec7-1ebc-4d68-8b1f-f758ea9196ae}
-
+
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
\ No newline at end of file
diff --git a/src/ebpf/api/ebpfapi.vcxproj.filters b/src/ebpf/api/ebpfapi.vcxproj.filters
index e4556dd75..3bc758dad 100644
--- a/src/ebpf/api/ebpfapi.vcxproj.filters
+++ b/src/ebpf/api/ebpfapi.vcxproj.filters
@@ -21,15 +21,6 @@
Header Files
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
@@ -38,14 +29,10 @@
Source Files
-
- Source Files
-
-
- Source Files
-
-
+
+ Source Files
+
\ No newline at end of file
diff --git a/src/ebpf/api/framework.h b/src/ebpf/api/framework.h
index 6890eb25b..54b83e94f 100644
--- a/src/ebpf/api/framework.h
+++ b/src/ebpf/api/framework.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved
- * SPDX-License-Identifier: MIT
-*/
-
#pragma once
-#include
-#include
-#include
-#include
-
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include
-#include
-
-
diff --git a/src/ebpf/api/pch.h b/src/ebpf/api/pch.h
index c9343d163..885d5d62e 100644
--- a/src/ebpf/api/pch.h
+++ b/src/ebpf/api/pch.h
@@ -1,7 +1,8 @@
-/*
- * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved
- * SPDX-License-Identifier: MIT
-*/
+// pch.h: This is a precompiled header file.
+// Files listed below are compiled only once, improving build performance for future builds.
+// This also affects IntelliSense performance, including code completion and many code browsing features.
+// However, files listed here are ALL re-compiled if any one of them is updated between builds.
+// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
diff --git a/src/ebpf/api/UnwindHelper.h b/src/ebpf/libs/api/UnwindHelper.h
similarity index 100%
rename from src/ebpf/api/UnwindHelper.h
rename to src/ebpf/libs/api/UnwindHelper.h
diff --git a/src/ebpf/api/Verifier.cpp b/src/ebpf/libs/api/Verifier.cpp
similarity index 82%
rename from src/ebpf/api/Verifier.cpp
rename to src/ebpf/libs/api/Verifier.cpp
index 312f5967f..fa183e5ef 100644
--- a/src/ebpf/api/Verifier.cpp
+++ b/src/ebpf/libs/api/Verifier.cpp
@@ -22,6 +22,15 @@ int get_file_size(char* filename, size_t* byte_code_size)
return result;
}
+static char * allocate_error_string(const std::string& str)
+{
+ char* retval;
+ size_t error_message_length = str.size() + 1;
+ retval = (char*)malloc(error_message_length);
+ strcpy_s(retval, error_message_length, str.c_str());
+ return retval; // Error;
+}
+
static int analyze(raw_program& raw_prog, char ** error_message)
{
std::ostringstream oss;
@@ -29,15 +38,15 @@ static int analyze(raw_program& raw_prog, char ** error_message)
std::variant prog_or_error = unmarshal(raw_prog, platform);
if (!std::holds_alternative(prog_or_error)) {
+ *error_message = allocate_error_string(std::get(prog_or_error));
return 1; // Error;
}
auto& prog = std::get(prog_or_error);
cfg_t cfg = prepare_cfg(prog, raw_prog.info, true);
- bool res = run_ebpf_analysis(oss, cfg, raw_prog.info, nullptr);
+ ebpf_verifier_options_t options{ true, false, true };
+ bool res = run_ebpf_analysis(oss, cfg, raw_prog.info, &options);
if (!res) {
- size_t error_message_length = oss.str().size() + 1;
- *error_message = (char*)malloc(error_message_length);
- strcpy_s(*error_message, error_message_length, oss.str().c_str());
+ *error_message = allocate_error_string(oss.str());
return 1; // Error;
}
return 0; // Success.
diff --git a/src/ebpf/api/Verifier.h b/src/ebpf/libs/api/Verifier.h
similarity index 100%
rename from src/ebpf/api/Verifier.h
rename to src/ebpf/libs/api/Verifier.h
diff --git a/src/ebpf/api/api.cpp b/src/ebpf/libs/api/api.cpp
similarity index 87%
rename from src/ebpf/api/api.cpp
rename to src/ebpf/libs/api/api.cpp
index 3ebb07db3..d57de881b 100644
--- a/src/ebpf/api/api.cpp
+++ b/src/ebpf/libs/api/api.cpp
@@ -4,6 +4,7 @@
*/
#include "pch.h"
+#include "platform.h"
#define EBPF_API
extern "C"
{
@@ -14,6 +15,7 @@ extern "C"
#include "protocol.h"
#include "UnwindHelper.h"
+#include
#include "Verifier.h"
#define MAX_CODE_SIZE (32 * 1024) // 32 KB
@@ -66,7 +68,7 @@ static DWORD invoke_ioctl(HANDLE handle, request_t request, reply_t reply)
reply_ptr = reply;
}
- auto result = DeviceIoControl(
+ auto result = Platform::DeviceIoControl(
handle,
(DWORD)IOCTL_EBPFCTL_METHOD_BUFFERED,
request_ptr,
@@ -76,12 +78,17 @@ static DWORD invoke_ioctl(HANDLE handle, request_t request, reply_t reply)
&actual_reply_size,
nullptr);
+ if (!result)
+ {
+ return GetLastError();
+ }
+
if (actual_reply_size != reply_size)
{
return ERROR_INVALID_PARAMETER;
}
- return result;
+ return ERROR_SUCCESS;
}
DWORD EbpfApiInit()
@@ -93,7 +100,7 @@ DWORD EbpfApiInit()
return ERROR_ALREADY_INITIALIZED;
}
- device_handle = CreateFile(ebpfDeviceName,
+ device_handle = Platform::CreateFile(ebpfDeviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
@@ -113,7 +120,7 @@ void EbpfApiTerminate()
{
if (device_handle != INVALID_HANDLE_VALUE)
{
- CloseHandle(device_handle);
+ Platform::CloseHandle(device_handle);
device_handle = INVALID_HANDLE_VALUE;
}
}
@@ -175,9 +182,23 @@ DLL DWORD EbpfLoadProgram(const char* file_name, const char* section_name, HANDL
DWORD result;
- // Verify code.
- if (verify(file_name, section_name, byte_code.data(), &byte_code_size, error_message) != 0)
+ try
{
+ // Verify code.
+ if (verify(file_name, section_name, byte_code.data(), &byte_code_size, error_message) != 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+ catch (std::runtime_error & err)
+ {
+ auto message = err.what();
+ auto message_length = strlen(message) + 1;
+ *error_message = reinterpret_cast(calloc(message_length + 1, sizeof(char)));
+ if (*error_message)
+ {
+ strcpy_s(*error_message, message_length, message);
+ }
return ERROR_INVALID_PARAMETER;
}
@@ -187,11 +208,7 @@ DLL DWORD EbpfLoadProgram(const char* file_name, const char* section_name, HANDL
{
return ERROR_OUTOFMEMORY;
}
-
- if (ubpf_load(vm, byte_code.data(), static_cast(byte_code.size()), error_message) < 0)
- {
- return ERROR_INVALID_PARAMETER;
- }
+ byte_code.resize(byte_code_size);
if (ubpf_register_map_resolver(vm, device_handle, map_resolver) < 0)
{
@@ -203,6 +220,11 @@ DLL DWORD EbpfLoadProgram(const char* file_name, const char* section_name, HANDL
return ERROR_INVALID_PARAMETER;
}
+ if (ubpf_load(vm, byte_code.data(), static_cast(byte_code.size()), error_message) < 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
if (ubpf_translate(vm, machine_code.data(), &machine_code_size, error_message))
{
return ERROR_INVALID_PARAMETER;
diff --git a/src/ebpf/libs/api/api.h b/src/ebpf/libs/api/api.h
new file mode 100644
index 000000000..98446bd1b
--- /dev/null
+++ b/src/ebpf/libs/api/api.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved
+ * SPDX-License-Identifier: MIT
+*/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(EBPF_API)
+#define DLL __declspec(dllexport)
+#else
+#define DLL __declspec(dllimport)
+#endif
+
+#define EBPF_HOOK_POINT_XDP 1
+
+ DLL DWORD EbpfApiInit();
+
+ DLL void EbpfApiTerminate();
+
+ DLL DWORD EbpfLoadProgram(const char* file, const char* section_name, HANDLE* handle, char** error_message);
+ DLL void EbpfFreeErrorMessage(char* error_message);
+ DLL void EbpfUnloadProgram(HANDLE handle);
+
+ DLL DWORD EbpfAttachProgram(HANDLE handle, DWORD hook_point);
+ DLL DWORD EbpfDetachProgram(HANDLE handle, DWORD hook_point);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/ebpf/libs/api/api.vcxproj b/src/ebpf/libs/api/api.vcxproj
new file mode 100644
index 000000000..ce967b704
--- /dev/null
+++ b/src/ebpf/libs/api/api.vcxproj
@@ -0,0 +1,191 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68}
+ ebpfapi
+ 10.0
+ $(ProjectDir)../../../../external/ebpf-verifier/
+
+
+
+ DynamicLibrary
+ true
+ v142
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ Unicode
+
+
+ StaticLibrary
+ true
+ v142
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ true
+ true
+ false
+
+
+
+
+ Level3
+ true
+ _DEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+ $(PrevailDir)src;..\..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories)
+ stdcpp17
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+ $(PrevailDir)src;..\..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories)
+ stdcpp17
+
+
+ Windows
+ true
+ true
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+ NotUsing
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/src/ebpf/libs/api/ebpfapi.sln b/src/ebpf/libs/api/ebpfapi.sln
new file mode 100644
index 000000000..396c2bc03
--- /dev/null
+++ b/src/ebpf/libs/api/ebpfapi.sln
@@ -0,0 +1,93 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30907.101
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfapi", "ebpfapi.vcxproj", "{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EbpfJitterDemoLib", "..\EbpfJitterDemoLib\EbpfJitterDemoLib.vcxproj", "{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfverifier", "..\..\..\..\external\ebpf-verifier\build\ebpfverifier.vcxproj", "{939A079D-A1E8-35D9-950F-11B1894D342E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{4C10AC76-384C-4539-B884-38E998749FB2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ MinSizeRel|x64 = MinSizeRel|x64
+ MinSizeRel|x86 = MinSizeRel|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ RelWithDebInfo|x64 = RelWithDebInfo|x64
+ RelWithDebInfo|x86 = RelWithDebInfo|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.ActiveCfg = Debug|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.Build.0 = Debug|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.ActiveCfg = Debug|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.Build.0 = Debug|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.Build.0 = Release|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.ActiveCfg = Release|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.Build.0 = Release|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.ActiveCfg = Release|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.Build.0 = Release|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x86.ActiveCfg = Release|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x86.Build.0 = Release|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x86.Build.0 = Release|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x64.ActiveCfg = Debug|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x64.Build.0 = Debug|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.ActiveCfg = Debug|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.Build.0 = Debug|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.ActiveCfg = Debug|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.Build.0 = Debug|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.ActiveCfg = Debug|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.Build.0 = Debug|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.ActiveCfg = Release|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.Build.0 = Release|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x86.ActiveCfg = Release|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x86.Build.0 = Release|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x86.Build.0 = Release|Win32
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.Debug|x64.ActiveCfg = Debug|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.Debug|x64.Build.0 = Debug|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.Debug|x86.ActiveCfg = Debug|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.Release|x64.ActiveCfg = Release|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.Release|x64.Build.0 = Release|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.Release|x86.ActiveCfg = Release|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
+ {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.ActiveCfg = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.Build.0 = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.ActiveCfg = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.Build.0 = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.ActiveCfg = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.Build.0 = Debug|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.ActiveCfg = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.Build.0 = Debug|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.ActiveCfg = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.Build.0 = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.ActiveCfg = Release|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.Build.0 = Release|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {9DEA0F2A-7674-46AA-9E15-BC880EF5895D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/ebpf/libs/api/ebpfapi.vcxproj.filters b/src/ebpf/libs/api/ebpfapi.vcxproj.filters
new file mode 100644
index 000000000..9b4362409
--- /dev/null
+++ b/src/ebpf/libs/api/ebpfapi.vcxproj.filters
@@ -0,0 +1,54 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ebpf/libs/api/framework.h b/src/ebpf/libs/api/framework.h
new file mode 100644
index 000000000..6890eb25b
--- /dev/null
+++ b/src/ebpf/libs/api/framework.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved
+ * SPDX-License-Identifier: MIT
+*/
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files
+#include
+#include
+
+
diff --git a/src/ebpf/api/packages.config b/src/ebpf/libs/api/packages.config
similarity index 100%
rename from src/ebpf/api/packages.config
rename to src/ebpf/libs/api/packages.config
diff --git a/src/ebpf/libs/api/pch.cpp b/src/ebpf/libs/api/pch.cpp
new file mode 100644
index 000000000..64b7eef6d
--- /dev/null
+++ b/src/ebpf/libs/api/pch.cpp
@@ -0,0 +1,5 @@
+// pch.cpp: source file corresponding to the pre-compiled header
+
+#include "pch.h"
+
+// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
diff --git a/src/ebpf/libs/api/pch.h b/src/ebpf/libs/api/pch.h
new file mode 100644
index 000000000..c9343d163
--- /dev/null
+++ b/src/ebpf/libs/api/pch.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved
+ * SPDX-License-Identifier: MIT
+*/
+
+#ifndef PCH_H
+#define PCH_H
+
+// add headers that you want to pre-compile here
+#include "framework.h"
+
+#endif //PCH_H
diff --git a/src/ebpf/libs/api/platform.h b/src/ebpf/libs/api/platform.h
new file mode 100644
index 000000000..72f9224be
--- /dev/null
+++ b/src/ebpf/libs/api/platform.h
@@ -0,0 +1,35 @@
+#pragma once
+/*
+ * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved
+ * SPDX-License-Identifier: MIT
+*/
+namespace Platform
+{
+ BOOL
+ DeviceIoControl(
+ _In_ HANDLE hDevice,
+ _In_ DWORD dwIoControlCode,
+ _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer,
+ _In_ DWORD nInBufferSize,
+ _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer,
+ _In_ DWORD nOutBufferSize,
+ _Out_opt_ LPDWORD lpBytesReturned,
+ _Inout_opt_ LPOVERLAPPED lpOverlapped
+ );
+
+ HANDLE
+ CreateFileW(
+ _In_ LPCWSTR lpFileName,
+ _In_ DWORD dwDesiredAccess,
+ _In_ DWORD dwShareMode,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ _In_ DWORD dwCreationDisposition,
+ _In_ DWORD dwFlagsAndAttributes,
+ _In_opt_ HANDLE hTemplateFile
+ );
+
+ BOOL
+ CloseHandle(
+ _In_ _Post_ptr_invalid_ HANDLE hObject
+ );
+}
diff --git a/src/ebpf/api/protocol.h b/src/ebpf/libs/api/protocol.h
similarity index 100%
rename from src/ebpf/api/protocol.h
rename to src/ebpf/libs/api/protocol.h
diff --git a/src/ebpf/libs/api/test/bpf.c b/src/ebpf/libs/api/test/bpf.c
new file mode 100644
index 000000000..2c07eca6d
--- /dev/null
+++ b/src/ebpf/libs/api/test/bpf.c
@@ -0,0 +1,6 @@
+#pragma clang section text="xdp_prog"
+int func()
+{
+ return 42;
+}
+
diff --git a/src/ebpf/libs/api/test/bpf.o b/src/ebpf/libs/api/test/bpf.o
new file mode 100644
index 000000000..3595a96b1
Binary files /dev/null and b/src/ebpf/libs/api/test/bpf.o differ
diff --git a/src/ebpf/libs/api/test/bpf_call.c b/src/ebpf/libs/api/test/bpf_call.c
new file mode 100644
index 000000000..fb7085129
--- /dev/null
+++ b/src/ebpf/libs/api/test/bpf_call.c
@@ -0,0 +1,21 @@
+#pragma clang section text="xdp_prog"
+
+typedef int (*bpf_helper)(int a, int b, int c, int d);
+
+#define ebpf_map_lookup_elem ((bpf_helper)0)
+#define ebpf_map_update_elem ((bpf_helper)1)
+#define ebpf_map_delete_elem ((bpf_helper)2)
+#define ebpf_get_tick_count ((bpf_helper)3)
+
+typedef struct xdp_md
+{
+ unsigned char* data;
+ unsigned char* data_end;
+ unsigned char* data_meta;
+} xdp_md;
+
+int func(xdp_md * ctx)
+{
+ return ebpf_get_tick_count(ctx, 0, 0, 0);
+}
+
diff --git a/src/ebpf/libs/api/test/bpf_call.o b/src/ebpf/libs/api/test/bpf_call.o
new file mode 100644
index 000000000..eaa3a326c
Binary files /dev/null and b/src/ebpf/libs/api/test/bpf_call.o differ
diff --git a/src/ebpf/libs/api/test/mock.cpp b/src/ebpf/libs/api/test/mock.cpp
new file mode 100644
index 000000000..21243308d
--- /dev/null
+++ b/src/ebpf/libs/api/test/mock.cpp
@@ -0,0 +1,58 @@
+#include "mock.h"
+std::function create_file_handler;
+std::function device_io_control_handler;
+std::function close_handle_handler;
+
+namespace Platform {
+ BOOL
+ DeviceIoControl(
+ _In_ HANDLE hDevice,
+ _In_ DWORD dwIoControlCode,
+ _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer,
+ _In_ DWORD nInBufferSize,
+ _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer,
+ _In_ DWORD nOutBufferSize,
+ _Out_opt_ LPDWORD lpBytesReturned,
+ _Inout_opt_ LPOVERLAPPED lpOverlapped
+ )
+ {
+ return device_io_control_handler(
+ hDevice,
+ dwIoControlCode,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize,
+ lpBytesReturned,
+ lpOverlapped);
+ }
+
+ HANDLE
+ CreateFileW(
+ _In_ LPCWSTR lpFileName,
+ _In_ DWORD dwDesiredAccess,
+ _In_ DWORD dwShareMode,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ _In_ DWORD dwCreationDisposition,
+ _In_ DWORD dwFlagsAndAttributes,
+ _In_opt_ HANDLE hTemplateFile
+ )
+ {
+ return create_file_handler(
+ lpFileName,
+ dwDesiredAccess,
+ dwShareMode,
+ lpSecurityAttributes,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ hTemplateFile);
+ }
+ BOOL
+ CloseHandle(
+ _In_ _Post_ptr_invalid_ HANDLE hObject
+ )
+ {
+ return close_handle_handler(hObject);
+ }
+
+}
\ No newline at end of file
diff --git a/src/ebpf/libs/api/test/mock.h b/src/ebpf/libs/api/test/mock.h
new file mode 100644
index 000000000..e29105dc3
--- /dev/null
+++ b/src/ebpf/libs/api/test/mock.h
@@ -0,0 +1,7 @@
+#pragma once
+#include
+#include
+
+extern std::function create_file_handler;
+extern std::function device_io_control_handler;
+extern std::function close_handle_handler;
diff --git a/src/ebpf/libs/api/test/packages.config b/src/ebpf/libs/api/test/packages.config
new file mode 100644
index 000000000..448cd1e38
--- /dev/null
+++ b/src/ebpf/libs/api/test/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/ebpf/libs/api/test/resource.h b/src/ebpf/libs/api/test/resource.h
new file mode 100644
index 000000000..d6780c176
--- /dev/null
+++ b/src/ebpf/libs/api/test/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by test.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/ebpf/libs/api/test/test.aps b/src/ebpf/libs/api/test/test.aps
new file mode 100644
index 000000000..caeafab52
Binary files /dev/null and b/src/ebpf/libs/api/test/test.aps differ
diff --git a/src/ebpf/libs/api/test/test.cpp b/src/ebpf/libs/api/test/test.cpp
new file mode 100644
index 000000000..a952bc0bd
--- /dev/null
+++ b/src/ebpf/libs/api/test/test.cpp
@@ -0,0 +1,259 @@
+// test.cpp : This file contains the 'main' function. Program execution begins and ends there.
+//
+
+#include
+#include
+#include
+#include
+#include
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
+
+#define EBPF_API
+#include "../api.h"
+#include "mock.h"
+#include "../protocol.h"
+
+uint8_t h = 0;
+auto success_create_file_handler = [&](_In_ LPCWSTR lpFileName,
+ _In_ DWORD dwDesiredAccess,
+ _In_ DWORD dwShareMode,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ _In_ DWORD dwCreationDisposition,
+ _In_ DWORD dwFlagsAndAttributes,
+ _In_opt_ HANDLE hTemplateFile) -> HANDLE
+{
+ SetLastError(ERROR_SUCCESS);
+ return reinterpret_cast(&h);
+};
+auto success_close_handle_handler = [&](_In_ HANDLE hObject) -> BOOL
+{
+ if (hObject != &h)
+ {
+ throw std::exception("Test failed - closing wrong handle");
+ }
+ return TRUE;
+};
+
+std::list> request_messages;
+std::list> reply_messages;
+
+auto success_ioctl = [&](_In_ HANDLE hDevice,
+ _In_ DWORD dwIoControlCode,
+ _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer,
+ _In_ DWORD nInBufferSize,
+ _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer,
+ _In_ DWORD nOutBufferSize,
+ _Out_opt_ LPDWORD lpBytesReturned,
+ _Inout_opt_ LPOVERLAPPED lpOverlapped
+ ) -> BOOL
+{
+ if (hDevice != &h)
+ {
+ throw std::exception("Test failed - using wrong handle");
+ }
+
+ if (reply_messages.empty())
+ {
+ throw std::exception("Test failed - no reply message queue");
+ }
+
+ auto in_begin = reinterpret_cast(lpInBuffer);
+ auto in_end = in_begin + nInBufferSize;
+ auto out_begin = reinterpret_cast(lpOutBuffer);
+ auto out_end = out_begin + nOutBufferSize;
+
+ std::vector request;
+ std::vector& reply = reply_messages.front();
+ if (reply.size() > nOutBufferSize)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ *lpBytesReturned = static_cast(reply.size());
+
+ request.resize(nInBufferSize);
+ std::copy(in_begin, in_end, request.begin());
+ std::copy(reply.begin(), reply.end(), out_begin);
+
+ reply_messages.pop_front();
+ request_messages.emplace_back(std::move(request));
+
+ return TRUE;
+};
+
+void push_back_reply_message(EbpfOpHeader* header)
+{
+ std::vector reply(header->length);
+
+ std::copy(reinterpret_cast(header), reinterpret_cast(header) + header->length, reply.begin());
+ reply_messages.emplace_back(std::move(reply));
+}
+
+template
+request_message_t* front_request_message()
+{
+ auto message = reinterpret_cast(request_messages.front().data());
+ size_t expected_size = 0;
+ EbpfOperation expected_id = (EbpfOperation)-1;
+ if constexpr (std::is_same::value) {
+ expected_size = sizeof(EbpfOpEvidenceRequest);
+ expected_id = EbpfOperation::evidence;
+ }
+ else if constexpr (std::is_same::value) {
+ expected_size = sizeof(EbpfOpResolveHelperRequest);
+ expected_id = EbpfOperation::resolve_helper;
+ }
+ else if constexpr (std::is_same::value) {
+ expected_size = sizeof(EbpfOpResolveMapRequest);
+ expected_id = EbpfOperation::resolve_map;
+ }
+ else if constexpr (std::is_same::value) {
+ expected_id = EbpfOperation::load_code;
+ }
+ else if constexpr (std::is_same::value) {
+ expected_size = sizeof(EbpfOpAttachDetachRequest);
+ switch (message->header.id) {
+ case EbpfOperation::attach:
+ case EbpfOperation::detach:
+ break;
+ default:
+ REQUIRE(message->header.id == EbpfOperation::attach);
+ break;
+ }
+ }
+ if (expected_id != (EbpfOperation)-1)
+ REQUIRE(expected_id == message->header.id);
+
+ if (expected_size > 0)
+ REQUIRE(expected_size == message->header.length);
+ return message;
+}
+
+TEST_CASE("Open failed", "[open_fail]") {
+ create_file_handler = [](_In_ LPCWSTR lpFileName,
+ _In_ DWORD dwDesiredAccess,
+ _In_ DWORD dwShareMode,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ _In_ DWORD dwCreationDisposition,
+ _In_ DWORD dwFlagsAndAttributes,
+ _In_opt_ HANDLE hTemplateFile) -> HANDLE {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return INVALID_HANDLE_VALUE;
+ };
+
+ close_handle_handler = [](_In_ HANDLE hObject) -> BOOL {
+ throw std::exception("Test failed - closing handle not opened");
+ };
+
+ REQUIRE(EbpfApiInit() == ERROR_FILE_NOT_FOUND);
+ EbpfApiTerminate();
+}
+
+TEST_CASE("Open success", "[open_success]") {
+ create_file_handler = success_create_file_handler;
+ close_handle_handler = success_close_handle_handler;
+
+ REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
+ EbpfApiTerminate();
+}
+
+TEST_CASE("Load program fail - file not found", "[load_fail_not_found]") {
+ create_file_handler = success_create_file_handler;
+ close_handle_handler = success_close_handle_handler;
+
+ HANDLE handle;
+ char* error_message = nullptr;
+ const char* fake_file_name = "not_a_real_file.elf";
+
+ REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
+
+ REQUIRE(EbpfLoadProgram(fake_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER);
+ REQUIRE_THAT(error_message, Catch::Matchers::Contains(fake_file_name));
+ EbpfFreeErrorMessage(error_message);
+ EbpfApiTerminate();
+}
+
+TEST_CASE("Load program fail - malformed", "[load_fail_bad_file]") {
+ create_file_handler = success_create_file_handler;
+ close_handle_handler = success_close_handle_handler;
+
+ char temp_file_name[MAX_PATH];
+ REQUIRE(GetTempFileNameA(".", "bad_elf", 0, temp_file_name) != 0);
+
+ HANDLE handle;
+ char* error_message = nullptr;
+
+ std::fstream out_file(temp_file_name, std::ios_base::out | std::ios_base::trunc);
+ std::default_random_engine generator;
+ std::uniform_int_distribution distribution(0, 255);
+
+ for (size_t i = 0; i < 4096; i++)
+ {
+ out_file.put(static_cast(distribution(generator)));
+ }
+ out_file.flush();
+ out_file.close();
+
+ REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
+
+ REQUIRE(EbpfLoadProgram(temp_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER);
+ REQUIRE_THAT(error_message, Catch::Matchers::Contains(temp_file_name));
+ EbpfFreeErrorMessage(error_message);
+ EbpfApiTerminate();
+
+ DeleteFileA(temp_file_name);
+}
+
+TEST_CASE("Load program success", "[load_success]") {
+ create_file_handler = success_create_file_handler;
+ close_handle_handler = success_close_handle_handler;
+ device_io_control_handler = success_ioctl;
+
+ HANDLE handle;
+ char* error_message = nullptr;
+
+ EbpfOpLoadReply load_reply{ sizeof(EbpfOpLoadReply), EbpfOperation::load_code, reinterpret_cast(&h) };
+ push_back_reply_message(&load_reply.header);
+
+ REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
+
+ REQUIRE(EbpfLoadProgram("bpf.o", "xdp_prog", &handle, &error_message) == ERROR_SUCCESS);
+
+ auto load_request = front_request_message();
+
+ request_messages.clear();
+
+ EbpfFreeErrorMessage(error_message);
+ EbpfApiTerminate();
+}
+
+TEST_CASE("Load program success - resolve helper", "[load_success - resolve helper]") {
+ create_file_handler = success_create_file_handler;
+ close_handle_handler = success_close_handle_handler;
+ device_io_control_handler = success_ioctl;
+
+ HANDLE handle;
+ char* error_message = nullptr;
+
+ EbpfOpResolveHelperReply helper_reply{ sizeof(EbpfOpResolveHelperReply), EbpfOperation::resolve_helper, reinterpret_cast(&GetTickCount) };
+ push_back_reply_message(&helper_reply.header);
+
+ EbpfOpLoadReply load_reply{ sizeof(EbpfOpLoadReply), EbpfOperation::load_code, reinterpret_cast(&h) };
+ push_back_reply_message(&load_reply.header);
+
+ REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
+
+ REQUIRE(EbpfLoadProgram("bpf_call.o", "xdp_prog", &handle, &error_message) == 0);
+
+ auto resolve_request = front_request_message();
+ REQUIRE(resolve_request->helper_id[0] == 3);
+ request_messages.pop_front();
+
+ auto load_request = front_request_message();
+ request_messages.pop_front();
+
+ EbpfFreeErrorMessage(error_message);
+ EbpfApiTerminate();
+}
\ No newline at end of file
diff --git a/src/ebpf/libs/api/test/test.rc b/src/ebpf/libs/api/test/test.rc
new file mode 100644
index 000000000..3b3fdcbfd
--- /dev/null
+++ b/src/ebpf/libs/api/test/test.rc
@@ -0,0 +1,60 @@
+// Microsoft Visual C++ generated resource script.
+//
+
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE 9, 1
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/src/ebpf/libs/api/test/test.vcxproj b/src/ebpf/libs/api/test/test.vcxproj
new file mode 100644
index 000000000..93f11c2fd
--- /dev/null
+++ b/src/ebpf/libs/api/test/test.vcxproj
@@ -0,0 +1,177 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {4c10ac76-384c-4539-b884-38e998749fb2}
+ test
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ stdcpp17
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ stdcpp17
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ {939a079d-a1e8-35d9-950f-11b1894d342e}
+
+
+ {245f0ec7-1ebc-4d68-8b1f-f758ea9196ae}
+
+
+ {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
\ No newline at end of file
diff --git a/src/ebpf/libs/api/test/test.vcxproj.filters b/src/ebpf/libs/api/test/test.vcxproj.filters
new file mode 100644
index 000000000..f330d705c
--- /dev/null
+++ b/src/ebpf/libs/api/test/test.vcxproj.filters
@@ -0,0 +1,41 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file