576 строки
20 KiB
C
576 строки
20 KiB
C
/*
|
|
* Copyright (c) Microsoft Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
#pragma once
|
|
#include "ebpf_windows.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#define EBPF_COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0]))
|
|
#define EBPF_OFFSET_OF(s, m) (((size_t) & ((s*)0)->m))
|
|
#define EBPF_FROM_FIELD(s, m, o) (s*)((uint8_t*)o - EBPF_OFFSET_OF(s, m))
|
|
|
|
#define EBPF_DEVICE_NAME L"\\Device\\EbpfIoDevice"
|
|
#define EBPF_SYMBOLIC_DEVICE_NAME L"\\GLOBAL??\\EbpfIoDevice"
|
|
#define EBPF_DEVICE_WIN32_NAME L"\\\\.\\EbpfIoDevice"
|
|
|
|
#define EBPF_MAX_GLOBAL_HELPER_FUNCTION 0xFFFF
|
|
|
|
/**
|
|
* @brief A UTF-8 encoded string.
|
|
* Notes:
|
|
* 1) This string is not NULL terminated, instead relies on length.
|
|
* 2) A single UTF-8 code point (aka character) could be 1-4 bytes in
|
|
* length.
|
|
*
|
|
*/
|
|
typedef struct _ebpf_utf8_string
|
|
{
|
|
uint8_t* value;
|
|
size_t length;
|
|
} ebpf_utf8_string_t;
|
|
|
|
typedef enum _ebpf_memory_type
|
|
{
|
|
EBPF_MEMORY_NO_EXECUTE = 0,
|
|
EBPF_MEMORY_EXECUTE = 1,
|
|
} ebpf_memory_type_t;
|
|
|
|
typedef enum _ebpf_code_integrity_state
|
|
{
|
|
EBPF_CODE_INTEGRITY_DEFAULT = 0,
|
|
EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE = 1
|
|
} ebpf_code_integrity_state_t;
|
|
|
|
typedef struct _ebpf_non_preemptible_work_item ebpf_non_preemptible_work_item_t;
|
|
typedef struct _ebpf_timer_work_item ebpf_timer_work_item_t;
|
|
typedef struct _ebpf_extension_client ebpf_extension_client_t;
|
|
typedef struct _ebpf_extension_provider ebpf_extension_provider_t;
|
|
typedef ebpf_error_code_t (*_ebpf_extension_dispatch_function)();
|
|
typedef struct _ebpf_extension_dispatch_table
|
|
{
|
|
uint16_t version;
|
|
uint16_t size;
|
|
_ebpf_extension_dispatch_function function[1];
|
|
} ebpf_extension_dispatch_table_t;
|
|
|
|
typedef struct _ebpf_extension_data
|
|
{
|
|
uint16_t version;
|
|
uint16_t size;
|
|
uint8_t data[1];
|
|
} ebpf_extension_data_t;
|
|
|
|
#pragma pack(push)
|
|
#pragma pack(1)
|
|
typedef struct _ebpf_trampoline_entry
|
|
{
|
|
uint16_t load_rax;
|
|
void* indirect_address;
|
|
uint16_t jmp_rax;
|
|
void* address;
|
|
} ebpf_trampoline_entry_t;
|
|
#pragma pack(pop)
|
|
|
|
#define EBPF_LOCK_SIZE sizeof(uint64_t)
|
|
#define EBPF_LOCK_STATE_SIZE sizeof(uint64_t)
|
|
typedef uint8_t ebpf_lock_t[EBPF_LOCK_SIZE];
|
|
typedef uint8_t ebpf_lock_state_t[EBPF_LOCK_STATE_SIZE];
|
|
|
|
/**
|
|
* @brief Initialize the eBPF platform abstraction layer.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_platform_initiate();
|
|
|
|
/**
|
|
* @brief Terminate the eBPF platform abstraction layer.
|
|
*/
|
|
void
|
|
ebpf_platform_terminate();
|
|
|
|
/**
|
|
* @brief Allocate memory.
|
|
* @param[in] size Size of memory to allocate
|
|
* @param[in] type Allocate memory as executable vs non-executable
|
|
* @returns Pointer to memory block allocated, or null on failure.
|
|
*/
|
|
void*
|
|
ebpf_allocate(size_t size, ebpf_memory_type_t type);
|
|
|
|
/**
|
|
* @brief Free memory.
|
|
* @param[in] memory Allocation to be freed.
|
|
*/
|
|
void
|
|
ebpf_free(void* memory);
|
|
|
|
/**
|
|
* @brief Allocate and copy a UTF-8 string.
|
|
*
|
|
* @param[out] destination Pointer to memory where the new UTF-8 character
|
|
* sequence will be allocated.
|
|
* @param[in] source UTF-8 string that will be copied.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* UTF-8 string.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_duplicate_utf8_string(ebpf_utf8_string_t* destination, const ebpf_utf8_string_t* source);
|
|
|
|
/**
|
|
* @brief Get the code integrity state from the platform.
|
|
* @param[out] state The code integrity state being enforced.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_NOT_SUPPORTED Unable to obtain state from platform.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_get_code_integrity_state(ebpf_code_integrity_state_t* state);
|
|
|
|
/**
|
|
* @brief Multiplies one value of type size_t by another and check for
|
|
* overflow.
|
|
* @param[in] multiplicand The value to be multiplied by multiplier.
|
|
* @param[in] multiplier The value by which to multiply multiplicand.
|
|
* @param[out] result A pointer to the result.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_ARITHMETIC_OVERFLOW Multiplication overflowed.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_safe_size_t_multiply(size_t multiplicand, size_t multiplier, size_t* result);
|
|
|
|
/**
|
|
* @brief Add one value of type size_t by another and check for
|
|
* overflow.
|
|
* @param[in] augend The value to be added by addend.
|
|
* @param[in] addend The value add to augend.
|
|
* @param[out] result A pointer to the result.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_ARITHMETIC_OVERFLOW Addition overflowed.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_safe_size_t_add(size_t augend, size_t addend, size_t* result);
|
|
|
|
/**
|
|
* @brief Create an instance of a lock.
|
|
* @param[in] lock Pointer to memory location that will contain the lock.
|
|
*/
|
|
void
|
|
ebpf_lock_create(ebpf_lock_t* lock);
|
|
|
|
/**
|
|
* @brief Destroy an instance of a lock.
|
|
* @param[in] lock Pointer to memory location that contains the lock.
|
|
*/
|
|
void
|
|
ebpf_lock_destroy(ebpf_lock_t* lock);
|
|
|
|
/**
|
|
* @brief Acquire exclusive access to the lock.
|
|
* @param[in] lock Pointer to memory location that contains the lock.
|
|
* @param[out] state Pointer to memory location that contains state that
|
|
* needs to be passed to ebpf_lock_unlock.
|
|
*/
|
|
void
|
|
ebpf_lock_lock(ebpf_lock_t* lock, ebpf_lock_state_t* state);
|
|
|
|
/**
|
|
* @brief Release exclusive access to the lock.
|
|
* @param[in] lock Pointer to memory location that contains the lock.
|
|
* @param[in] state Pointer to memory location that contains state that
|
|
* needs to be passed to ebpf_lock_unlock.
|
|
*/
|
|
void
|
|
ebpf_lock_unlock(ebpf_lock_t* lock, ebpf_lock_state_t* state);
|
|
|
|
/**
|
|
* @brief Query the platform for the total number of CPUs.
|
|
* @param[out] cpu_count Pointer to memory location that contains the
|
|
* number of CPUs.
|
|
*/
|
|
void
|
|
ebpf_get_cpu_count(uint32_t* cpu_count);
|
|
|
|
/**
|
|
* @brief Query the platform to determine if the current execution can
|
|
* be preempted by other execution.
|
|
* @retrval True if this execution can be preempted.
|
|
*/
|
|
bool
|
|
ebpf_is_preemptible();
|
|
|
|
/**
|
|
* @brief Query the platform to determine which CPU this execution is
|
|
* running on. Only valid if ebpf_is_preemptible() == true.
|
|
* @retval Zero based index of CPUs.
|
|
*/
|
|
uint32_t
|
|
ebpf_get_current_cpu();
|
|
|
|
/**
|
|
* @brief Query the platform to determine an opaque identifier for the
|
|
* current thread. Only valid if ebpf_is_preemptible() == false.
|
|
* @return Opaque identifier for the current thread.
|
|
*/
|
|
uint64_t
|
|
ebpf_get_current_thread_id();
|
|
|
|
/**
|
|
* @brief Query the platform to determine if non-preemptible work items are
|
|
* supported.
|
|
*
|
|
* @retval true Non-preemptible work items are supported.
|
|
* @retval false Non-preemptible work items are not supported.
|
|
*/
|
|
bool
|
|
ebpf_is_non_preemptible_work_item_supported();
|
|
|
|
/**
|
|
* @brief Create a non-preemptible work item.
|
|
*
|
|
* @param[out] work_item Pointer to memory that will contain the pointer to
|
|
* the non-preemptible work item on success.
|
|
* @param[in] cpu_id Associate the work item with this CPU.
|
|
* @param[in] work_item_routine Routine to execute as a work item.
|
|
* @param[in] work_item_context Context to pass to the routine.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* work item.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_allocate_non_preemptible_work_item(
|
|
ebpf_non_preemptible_work_item_t** work_item,
|
|
uint32_t cpu_id,
|
|
void (*work_item_routine)(void* work_item_context, void* parameter_1),
|
|
void* work_item_context);
|
|
|
|
/**
|
|
* @brief Free a non-preemptible work item.
|
|
*
|
|
* @param[in] work_item Pointer to the work item to free.
|
|
*/
|
|
void
|
|
ebpf_free_non_preemptible_work_item(ebpf_non_preemptible_work_item_t* work_item);
|
|
|
|
/**
|
|
* @brief Schedule a non-preemptible work item to run.
|
|
*
|
|
* @param[in] work_item Work item to schedule.
|
|
* @param[in] parameter_1 Parameter to pass to work item.
|
|
* @retval true Work item was queued.
|
|
* @retval false Work item is already queued.
|
|
*/
|
|
bool
|
|
ebpf_queue_non_preemptible_work_item(ebpf_non_preemptible_work_item_t* work_item, void* parameter_1);
|
|
|
|
/**
|
|
* @brief Allocate a timer to run a non-preemptible work item.
|
|
*
|
|
* @param[out] timer Pointer to memory that will contain timer on success.
|
|
* @param[in] work_item_routine Routine to execute when time expires.
|
|
* @param[in] work_item_context Context to pass to routine.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* timer.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_allocate_timer_work_item(
|
|
ebpf_timer_work_item_t** timer, void (*work_item_routine)(void* work_item_context), void* work_item_context);
|
|
|
|
/**
|
|
* @brief Schedule a work item to be executed after elaped_microseconds.
|
|
*
|
|
* @param[in] timer Pointer to timer to schedule.
|
|
* @param[in] elapsed_microseconds Microseconds to delay before executing
|
|
* work item.
|
|
*/
|
|
void
|
|
ebpf_schedule_timer_work_item(ebpf_timer_work_item_t* timer, uint32_t elapsed_microseconds);
|
|
|
|
/**
|
|
* @brief Free a timer.
|
|
*
|
|
* @param[in] timer Timer to be freed.
|
|
*/
|
|
void
|
|
ebpf_free_timer_work_item(ebpf_timer_work_item_t* timer);
|
|
|
|
typedef struct _ebpf_hash_table ebpf_hash_table_t;
|
|
|
|
typedef enum _ebpf_hash_table_compare_result
|
|
{
|
|
EBPF_HASH_TABLE_LESS_THAN = 0,
|
|
EBPF_HASH_TABLE_GREATER_THAN = 1,
|
|
EBPF_HASH_TABLE_EQUAL = 2,
|
|
} ebpf_hash_table_compare_result_t;
|
|
|
|
/**
|
|
* @brief Allocate and initialize a hash table.
|
|
*
|
|
* @param[out] hash_table Pointer to memory that will contain hash table on
|
|
* success.
|
|
* @param[in] allocate Function to use when allocating elements in the
|
|
* hash table.
|
|
* @param[in] free Function to use when freeing elements in the hash table.
|
|
* @param[in] key_size Size of the keys used in the hash table.
|
|
* @param[in] value_size Size of the values used in the hash table.
|
|
* @param[in] compare_function Function used to lexicographically order
|
|
* keys.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* hash table.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_hash_table_create(
|
|
ebpf_hash_table_t** hash_table,
|
|
void* (*allocate)(size_t size, ebpf_memory_type_t type),
|
|
void (*free)(void* memory),
|
|
size_t key_size,
|
|
size_t value_size,
|
|
ebpf_hash_table_compare_result_t (*compare_function)(const uint8_t* key1, const uint8_t* key2));
|
|
|
|
/**
|
|
* @brief Remove all items from the hash table and release memory.
|
|
*
|
|
* @param[in] hash_table Hash-table to release.
|
|
*/
|
|
void
|
|
ebpf_hash_table_destroy(ebpf_hash_table_t* hash_table);
|
|
|
|
/**
|
|
* @brief Find an element in the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to search.
|
|
* @param[in] key Key to find in hash table.
|
|
* @param[out] value Pointer to value if found.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_NOT_FOUND Key not found in hash table.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_hash_table_find(ebpf_hash_table_t* hash_table, const uint8_t* key, uint8_t** value);
|
|
|
|
/**
|
|
* @brief Insert or update an entry in the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to update.
|
|
* @param[in] key Key to find and insert or update.
|
|
* @param[in] value Value to insert into hash table.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate memory for this
|
|
* entry in the hash table.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_hash_table_update(ebpf_hash_table_t* hash_table, const uint8_t* key, const uint8_t* value);
|
|
|
|
/**
|
|
* @brief Remove an entry from the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to update.
|
|
* @param[in] key Key to find and remove.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_hash_table_delete(ebpf_hash_table_t* hash_table, const uint8_t* key);
|
|
|
|
/**
|
|
* @brief Find the next key in the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to query.
|
|
* @param[in] previous_key Previous key or NULL to restart.
|
|
* @param[out] next_key Next key if it exists.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_NO_MORE_KEYS No keys exist in the hash table that
|
|
* are lexicographically after the specified key.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_hash_table_next_key(ebpf_hash_table_t* hash_table, const uint8_t* previous_key, uint8_t* next_key);
|
|
|
|
/**
|
|
* @brief Atomically increase the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to increase by 1.
|
|
* @return The new value.
|
|
*/
|
|
int32_t
|
|
ebpf_interlocked_increment_int32(volatile int32_t* addend);
|
|
|
|
/**
|
|
* @brief Atomically decrease the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to decrease by 1.
|
|
* @return The new value.
|
|
*/
|
|
int32_t
|
|
ebpf_interlocked_decrement_int32(volatile int32_t* addend);
|
|
|
|
/**
|
|
* @brief Atomically increase the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to increase by 1.
|
|
* @return The new value.
|
|
*/
|
|
int64_t
|
|
ebpf_interlocked_increment_int64(volatile int64_t* addend);
|
|
|
|
/**
|
|
* @brief Atomically decrease the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to increase by 1.
|
|
* @return The new value.
|
|
*/
|
|
int64_t
|
|
ebpf_interlocked_decrement_int64(volatile int64_t* addend);
|
|
|
|
/**
|
|
* @brief Performs an atomic operation that compares the input value pointed
|
|
* to by destination with the value of comperand and replaces it with
|
|
* exchange.
|
|
*
|
|
* @param[in,out] destination A pointer to the input value that is compared
|
|
* with the value of comperand.
|
|
* @param[in] exchange Specifies the output value pointed to by destination
|
|
* if the input value pointed to by destination equals the value of
|
|
* comperand.
|
|
* @param[in] comperand Specifies the value that is compared with the input
|
|
* value pointed to by destination.
|
|
* @return Returns the original value of memory pointed to by
|
|
* destination.
|
|
*/
|
|
int32_t
|
|
ebpf_interlocked_compare_exchange_int32(volatile int32_t* destination, int32_t exchange, int32_t comperand);
|
|
|
|
typedef void (*ebpf_extension_change_callback_t)(
|
|
void* client_binding_context,
|
|
const void* provider_binding_context,
|
|
const ebpf_extension_data_t* provider_data,
|
|
const ebpf_extension_dispatch_table_t* provider_dispatch_table);
|
|
|
|
/**
|
|
* @brief Load an extension and get its dispatch table.
|
|
*
|
|
* @param[out] client_context Context used to unload the extension.
|
|
* @param[in] interface_id GUID representing the identity of the interface.
|
|
* @param[in] client_binding_context Opaque per-instance pointer passed to the extension.
|
|
* @param[in] client_data Opaque client data passed to the extension.
|
|
* @param[in] client_data_length Length of the client data.
|
|
* @param[in] client_dispatch_table Table of function pointers the client
|
|
* exposes.
|
|
* @param[in] provider_id GUID representing the extension to load.
|
|
* @param[out] provider_data Opaque provider data.
|
|
* @param[out] provider_dispatch_table Table of function pointers the
|
|
* provider exposes.
|
|
* @param[in] extension_changed Callback invoked when a provider attaches
|
|
* or detaches.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_NOT_FOUND The provider was not found.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_extension_load(
|
|
ebpf_extension_client_t** client_context,
|
|
const GUID* interface_id,
|
|
void* client_binding_context,
|
|
const ebpf_extension_data_t* client_data,
|
|
const ebpf_extension_dispatch_table_t* client_dispatch_table,
|
|
void** provider_binding_context,
|
|
const ebpf_extension_data_t** provider_data,
|
|
const ebpf_extension_dispatch_table_t** provider_dispatch_table,
|
|
ebpf_extension_change_callback_t extension_changed);
|
|
|
|
/**
|
|
* @brief Unload an extension.
|
|
*
|
|
* @param[in] client_context Context of the extension to unload.
|
|
*/
|
|
void
|
|
ebpf_extension_unload(ebpf_extension_client_t* client_context);
|
|
|
|
typedef ebpf_error_code_t (*ebpf_provider_client_attach_callback_t)(
|
|
void* context,
|
|
const GUID* client_id,
|
|
void* client_binding_context,
|
|
const ebpf_extension_data_t* client_data,
|
|
const ebpf_extension_dispatch_table_t* client_dispatch_table);
|
|
|
|
typedef ebpf_error_code_t (*ebpf_provider_client_detach_callback_t)(void* context, const GUID* client_id);
|
|
|
|
/**
|
|
* @brief Register as an extension provider.
|
|
*
|
|
* @param[out] provider_context Context used to unload the provider.
|
|
* @param[in] interface_id GUID representing the identity of the interface.
|
|
* @param[in] provider_data Opaque provider data.
|
|
* @param[in] provider_dispatch_table Table of function pointers the
|
|
* provider exposes.
|
|
* @param[in] client_attach_callback Function invoked when a client attaches.
|
|
* @param[in] client_detach_callback Function invoked when a client detaches.
|
|
* @retval EBPF_ERROR_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_EXTENSION_FAILED_TO_LOAD The provider was unable to
|
|
* load.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_provider_load(
|
|
ebpf_extension_provider_t** provider_context,
|
|
const GUID* interface_id,
|
|
void* provider_binding_context,
|
|
const ebpf_extension_data_t* provider_data,
|
|
const ebpf_extension_dispatch_table_t* provider_dispatch_table,
|
|
void* callback_context,
|
|
ebpf_provider_client_attach_callback_t client_attach_callback,
|
|
ebpf_provider_client_detach_callback_t client_detach_callback);
|
|
|
|
/**
|
|
* @brief Unload a provider.
|
|
*
|
|
* @param[in] provider_context Provider to unload.
|
|
*/
|
|
void
|
|
ebpf_provider_unload(ebpf_extension_provider_t* provider_context);
|
|
|
|
ebpf_error_code_t
|
|
ebpf_guid_create(GUID* new_guid);
|
|
|
|
int32_t
|
|
ebpf_log_function(void* context, const char* format_string, ...);
|
|
|
|
/**
|
|
* @brief Create or update a table of ebpf_trampoline_entry_t with
|
|
* trampoline functions to allow for relocation of functions in the
|
|
* dispatch table.
|
|
*
|
|
* @param[in,out] entry_count Size of the ebpf_trampoline_entry_t table.
|
|
* @param[in,out] entries Block of memory that contains the trampoline
|
|
* functions on success.
|
|
* @param[in] dispatch_table Dispatch table to build trampoline functions for.
|
|
* @retval EBPF_ERROR_SUCCESS ebpf_trampoline_entry_t table successfully
|
|
* populated.
|
|
* @retval EBPF_ERROR_EXTENSION_FAILED_TO_LOAD Unable to populate
|
|
* ebpf_trampoline_entry_t table.
|
|
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate resources for this
|
|
* operation.
|
|
* @retval EBPF_ERROR_NOT_SUPPORTED This operation is not supported on this
|
|
* platform.
|
|
*/
|
|
ebpf_error_code_t
|
|
ebpf_build_trampoline_table(
|
|
size_t* entry_count, ebpf_trampoline_entry_t** entries, const ebpf_extension_dispatch_table_t* dispatch_table);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|