mirror of
https://github.com/intel/linux-sgx
synced 2026-06-08 14:49:32 +00:00
Added pre-release libc++ to enable C++11 inside the enclave.
Signed-off-by: Li, Xun <xun.li@intel.com>
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
# include <unistd.h>
|
||||
# include <pwd.h>
|
||||
# define MAX_PATH FILENAME_MAX
|
||||
|
||||
#include "sgx_urts.h"
|
||||
#include "sgx_uae_service.h"
|
||||
#include "App.h"
|
||||
#include "Enclave_u.h"
|
||||
|
||||
/* Global EID shared by multiple threads */
|
||||
sgx_enclave_id_t global_eid = 0;
|
||||
|
||||
typedef struct _sgx_errlist_t {
|
||||
sgx_status_t err;
|
||||
const char *msg;
|
||||
const char *sug; /* Suggestion */
|
||||
} sgx_errlist_t;
|
||||
|
||||
/* Error code returned by sgx_create_enclave */
|
||||
static sgx_errlist_t sgx_errlist[] = {
|
||||
{
|
||||
SGX_ERROR_UNEXPECTED,
|
||||
"Unexpected error occurred.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_PARAMETER,
|
||||
"Invalid parameter.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_OUT_OF_MEMORY,
|
||||
"Out of memory.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_ENCLAVE_LOST,
|
||||
"Power transition occurred.",
|
||||
"Please refer to the sample \"PowerTransition\" for details."
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_ENCLAVE,
|
||||
"Invalid enclave image.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_ENCLAVE_ID,
|
||||
"Invalid enclave identification.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_SIGNATURE,
|
||||
"Invalid enclave signature.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_OUT_OF_EPC,
|
||||
"Out of EPC memory.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_NO_DEVICE,
|
||||
"Invalid SGX device.",
|
||||
"Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards."
|
||||
},
|
||||
{
|
||||
SGX_ERROR_MEMORY_MAP_CONFLICT,
|
||||
"Memory map conflicted.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_METADATA,
|
||||
"Invalid enclave metadata.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_DEVICE_BUSY,
|
||||
"SGX device was busy.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_VERSION,
|
||||
"Enclave version was invalid.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_INVALID_ATTRIBUTE,
|
||||
"Enclave was not authorized.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_ENCLAVE_FILE_ACCESS,
|
||||
"Can't open enclave file.",
|
||||
NULL
|
||||
},
|
||||
{
|
||||
SGX_ERROR_NDEBUG_ENCLAVE,
|
||||
"The enclave is signed as product enclave, and can not be created as debuggable enclave.",
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
||||
/* Check error conditions for loading enclave */
|
||||
void print_error_message(sgx_status_t ret)
|
||||
{
|
||||
size_t idx = 0;
|
||||
size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0];
|
||||
|
||||
for (idx = 0; idx < ttl; idx++) {
|
||||
if(ret == sgx_errlist[idx].err) {
|
||||
if(NULL != sgx_errlist[idx].sug)
|
||||
printf("Info: %s\n", sgx_errlist[idx].sug);
|
||||
printf("Error: %s\n", sgx_errlist[idx].msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == ttl)
|
||||
printf("Error: Unexpected error occurred.\n");
|
||||
}
|
||||
|
||||
/* Initialize the enclave:
|
||||
* Step 1: try to retrieve the launch token saved by last transaction
|
||||
* Step 2: call sgx_create_enclave to initialize an enclave instance
|
||||
* Step 3: save the launch token if it is updated
|
||||
*/
|
||||
int initialize_enclave(void)
|
||||
{
|
||||
char token_path[MAX_PATH] = {'\0'};
|
||||
sgx_launch_token_t token = {0};
|
||||
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
|
||||
int updated = 0;
|
||||
|
||||
/* Step 1: try to retrieve the launch token saved by last transaction
|
||||
* if there is no token, then create a new one.
|
||||
*/
|
||||
/* try to get the token saved in $HOME */
|
||||
const char *home_dir = getpwuid(getuid())->pw_dir;
|
||||
|
||||
if (home_dir != NULL &&
|
||||
(strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
|
||||
/* compose the token path */
|
||||
strncpy(token_path, home_dir, strlen(home_dir));
|
||||
strncat(token_path, "/", strlen("/"));
|
||||
strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1);
|
||||
} else {
|
||||
/* if token path is too long or $HOME is NULL */
|
||||
strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME));
|
||||
}
|
||||
|
||||
FILE *fp = fopen(token_path, "rb");
|
||||
if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) {
|
||||
printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path);
|
||||
}
|
||||
|
||||
if (fp != NULL) {
|
||||
/* read the token from saved file */
|
||||
size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp);
|
||||
if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) {
|
||||
/* if token is invalid, clear the buffer */
|
||||
memset(&token, 0x0, sizeof(sgx_launch_token_t));
|
||||
printf("Warning: Invalid launch token read from \"%s\".\n", token_path);
|
||||
}
|
||||
}
|
||||
/* Step 2: call sgx_create_enclave to initialize an enclave instance */
|
||||
/* Debug Support: set 2nd parameter to 1 */
|
||||
ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL);
|
||||
if (ret != SGX_SUCCESS) {
|
||||
print_error_message(ret);
|
||||
if (fp != NULL) fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Step 3: save the launch token if it is updated */
|
||||
if (updated == FALSE || fp == NULL) {
|
||||
/* if the token is not updated, or file handler is invalid, do not perform saving */
|
||||
if (fp != NULL) fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reopen the file with write capablity */
|
||||
fp = freopen(token_path, "wb", fp);
|
||||
if (fp == NULL) return 0;
|
||||
size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp);
|
||||
if (write_num != sizeof(sgx_launch_token_t))
|
||||
printf("Warning: Failed to save launch token to \"%s\".\n", token_path);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OCall functions */
|
||||
void ocall_print_string(const char *str)
|
||||
{
|
||||
/* Proxy/Bridge will check the length and null-terminate
|
||||
* the input string to prevent buffer overflow.
|
||||
*/
|
||||
printf("%s", str);
|
||||
}
|
||||
|
||||
|
||||
/* Application entry */
|
||||
int SGX_CDECL main(int argc, char *argv[])
|
||||
{
|
||||
(void)(argc);
|
||||
(void)(argv);
|
||||
|
||||
|
||||
/* Initialize the enclave */
|
||||
if(initialize_enclave() < 0){
|
||||
printf("Enter a character before exit ...\n");
|
||||
getchar();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Utilize trusted libraries */
|
||||
ecall_libcxx_functions();
|
||||
|
||||
/* Destroy the enclave */
|
||||
sgx_destroy_enclave(global_eid);
|
||||
|
||||
printf("Info: Cxx11DemoEnclave successfully returned.\n");
|
||||
|
||||
//printf("Enter a character before exit ...\n");
|
||||
//getchar();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _APP_H_
|
||||
#define _APP_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "sgx_error.h" /* sgx_status_t */
|
||||
#include "sgx_eid.h" /* sgx_enclave_id_t */
|
||||
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
# define FALSE 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define TOKEN_FILENAME "enclave.token"
|
||||
# define ENCLAVE_FILENAME "enclave.signed.so"
|
||||
#endif
|
||||
|
||||
extern sgx_enclave_id_t global_eid; /* global enclave id */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ecall_libcxx_functions(void);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_APP_H_ */
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../App.h"
|
||||
#include "Enclave_u.h"
|
||||
#include <thread>
|
||||
|
||||
/* ecall_libcxx_functions:
|
||||
* Invokes standard C++11 functions.
|
||||
*/
|
||||
|
||||
//This function is part of mutex demo
|
||||
void demo_counter_without_mutex()
|
||||
{
|
||||
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
|
||||
ret = ecall_mutex_demo_no_protection(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
}
|
||||
|
||||
//This function is part of mutex demo
|
||||
void demo_counter_mutex()
|
||||
{
|
||||
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
|
||||
ret = ecall_mutex_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
}
|
||||
|
||||
//This function is used by processing thread of condition variable demo
|
||||
void demo_cond_var_run()
|
||||
{
|
||||
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
|
||||
ret = ecall_condition_variable_run(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
}
|
||||
|
||||
//This function is used by the loader thread of condition variable demo
|
||||
void demo_cond_var_load()
|
||||
{
|
||||
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
|
||||
ret = ecall_condition_variable_load(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
}
|
||||
|
||||
// Examples for C++11 library and compiler features
|
||||
void ecall_libcxx_functions(void)
|
||||
{
|
||||
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
|
||||
|
||||
// Example for lambda function feature:
|
||||
ret = ecall_lambdas_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for auto feature:
|
||||
ret = ecall_auto_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for decltype:
|
||||
ret = ecall_decltype_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for strongly_typed_enum:
|
||||
ret = ecall_strongly_typed_enum_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for range based for loops:
|
||||
ret = ecall_range_based_for_loops_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for static_assert:
|
||||
ret = ecall_static_assert_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for virtual function controls : override, final, default, and delete
|
||||
ret = ecall_virtual_function_control_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for delegating_constructors:
|
||||
ret = ecall_delegating_constructors_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for std::function:
|
||||
ret = ecall_std_function_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for algorithms (std::all_of, std::any_of, std::none_of):
|
||||
ret = ecall_cxx11_algorithms_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for variadic_templates feature:
|
||||
ret = ecall_variadic_templates_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for SFINAE:
|
||||
ret = ecall_SFINAE_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for initializer_list:
|
||||
ret = ecall_initializer_list_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for rvalue:
|
||||
ret = ecall_rvalue_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for nullptr:
|
||||
ret = ecall_nullptr_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for enum class:
|
||||
ret = ecall_enum_class_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for new container classes (unordered_set, unordered_map, unordered_multiset, and unordered_multimap):
|
||||
ret = ecall_new_container_classes_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for tuple:
|
||||
ret = ecall_tuple_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
// Example for shared_ptr:
|
||||
ret = ecall_shared_ptr_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
// Example for atomic:
|
||||
ret = ecall_atomic_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
//The following threads are part of mutex demo
|
||||
std::thread t1(demo_counter_without_mutex);
|
||||
std::thread t2(demo_counter_without_mutex);
|
||||
std::thread t3(demo_counter_without_mutex);
|
||||
t1.join();
|
||||
t2.join();
|
||||
t3.join();
|
||||
ret = ecall_print_final_value_no_protection(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
|
||||
|
||||
//The following threads are part of mutex demo
|
||||
std::thread tm1(demo_counter_mutex);
|
||||
std::thread tm2(demo_counter_mutex);
|
||||
std::thread tm3(demo_counter_mutex);
|
||||
tm1.join();
|
||||
tm2.join();
|
||||
tm3.join();
|
||||
ret = ecall_print_final_value_mutex_demo(global_eid);
|
||||
if (ret != SGX_SUCCESS)
|
||||
abort();
|
||||
|
||||
//The following threads are part of condition variable demo
|
||||
std::thread th1(demo_cond_var_run);
|
||||
std::thread th2(demo_cond_var_load);
|
||||
th2.join();
|
||||
th1.join();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<!-- Please refer to User's Guide for the explanation of each field -->
|
||||
<EnclaveConfiguration>
|
||||
<ProdID>0</ProdID>
|
||||
<ISVSVN>0</ISVSVN>
|
||||
<StackMaxSize>0x40000</StackMaxSize>
|
||||
<HeapMaxSize>0x100000</HeapMaxSize>
|
||||
<TCSNum>10</TCSNum>
|
||||
<TCSPolicy>1</TCSPolicy>
|
||||
<DisableDebug>0</DisableDebug>
|
||||
<MiscSelect>0</MiscSelect>
|
||||
<MiscMask>0xFFFFFFFF</MiscMask>
|
||||
</EnclaveConfiguration>
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* vsnprintf */
|
||||
|
||||
#include "Enclave.h"
|
||||
#include "Enclave_t.h" /* print_string */
|
||||
|
||||
/*
|
||||
* printf:
|
||||
* Invokes OCALL to display the enclave buffer to the terminal.
|
||||
*/
|
||||
void printf(const char *fmt, ...)
|
||||
{
|
||||
char buf[BUFSIZ] = {'\0'};
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, BUFSIZ, fmt, ap);
|
||||
va_end(ap);
|
||||
ocall_print_string(buf);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Enclave.edl - Top EDL file. */
|
||||
|
||||
enclave {
|
||||
|
||||
|
||||
/* Import ECALL/OCALL from sub-directory EDLs.
|
||||
* [from]: specifies the location of EDL file.
|
||||
* [import]: specifies the functions to import,
|
||||
* [*]: implies to import all functions.
|
||||
*/
|
||||
|
||||
from "TrustedLibrary/Libcxx.edl" import *;
|
||||
from "sgx_tstdc.edl" import sgx_thread_wait_untrusted_event_ocall, sgx_thread_set_untrusted_event_ocall, sgx_thread_setwait_untrusted_events_ocall, sgx_thread_set_multiple_untrusted_events_ocall;
|
||||
|
||||
/*
|
||||
* ocall_print_string - invokes OCALL to display string buffer inside the enclave.
|
||||
* [in]: copy the string buffer to App outside.
|
||||
* [string]: specifies 'str' is a NULL terminated buffer.
|
||||
*/
|
||||
untrusted {
|
||||
void ocall_print_string([in, string] const char *str);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ENCLAVE_H_
|
||||
#define _ENCLAVE_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void printf(const char *fmt, ...);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_ENCLAVE_H_ */
|
||||
@@ -0,0 +1,9 @@
|
||||
enclave.so
|
||||
{
|
||||
global:
|
||||
g_global_data_sim;
|
||||
g_global_data;
|
||||
enclave_entry;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
enclave.so
|
||||
{
|
||||
global:
|
||||
g_global_data_sim;
|
||||
g_global_data;
|
||||
enclave_entry;
|
||||
g_peak_heap_used;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ
|
||||
AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ
|
||||
ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr
|
||||
nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b
|
||||
3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H
|
||||
ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD
|
||||
5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW
|
||||
KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC
|
||||
1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe
|
||||
K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z
|
||||
AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q
|
||||
ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6
|
||||
JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826
|
||||
5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02
|
||||
wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9
|
||||
osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm
|
||||
WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i
|
||||
Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9
|
||||
xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd
|
||||
vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD
|
||||
Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a
|
||||
cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC
|
||||
0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ
|
||||
gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo
|
||||
gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t
|
||||
k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz
|
||||
Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6
|
||||
O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5
|
||||
afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom
|
||||
e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G
|
||||
BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv
|
||||
fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN
|
||||
t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9
|
||||
yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp
|
||||
6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg
|
||||
WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH
|
||||
NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -0,0 +1,919 @@
|
||||
/**
|
||||
* Copyright(C) 2011-2016 Intel Corporation All Rights Reserved.
|
||||
*
|
||||
* The source code, information and material ("Material") contained herein is
|
||||
* owned by Intel Corporation or its suppliers or licensors, and title to such
|
||||
* Material remains with Intel Corporation or its suppliers or licensors. The
|
||||
* Material contains proprietary information of Intel or its suppliers and
|
||||
* licensors. The Material is protected by worldwide copyright laws and treaty
|
||||
* provisions. No part of the Material may be used, copied, reproduced,
|
||||
* modified, published, uploaded, posted, transmitted, distributed or disclosed
|
||||
* in any way without Intel's prior express written permission. No license
|
||||
* under any patent, copyright or other intellectual property rights in the
|
||||
* Material is granted to or conferred upon you, either expressly, by
|
||||
* implication, inducement, estoppel or otherwise. Any license under such
|
||||
* intellectual property rights must be express and approved by Intel in
|
||||
* writing.
|
||||
*
|
||||
* *Third Party trademarks are the property of their respective owners.
|
||||
*
|
||||
* Unless otherwise agreed by Intel in writing, you may not remove or alter
|
||||
* this notice or any other notice embedded in Materials by Intel or Intel's
|
||||
* suppliers or licensors in any way.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <typeinfo>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <initializer_list>
|
||||
#include <tuple>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <map>
|
||||
|
||||
#include "../Enclave.h"
|
||||
#include "Enclave_t.h"
|
||||
|
||||
|
||||
// Feature name : Lambda functions
|
||||
// Feature description : It is used to create a function object that can capture variables in scope.
|
||||
// Demo description : Shows lambda capture options and a some basic usages.
|
||||
void ecall_lambdas_demo()
|
||||
{
|
||||
// Lambdas capture options:
|
||||
int local_var = 0;
|
||||
|
||||
[] { return true; }; // captures nothing
|
||||
|
||||
[&] { return ++local_var; }; // captures all variable by reference
|
||||
[&local_var] { return ++local_var; }; // captures local_var by reference
|
||||
[&, local_var] { return local_var; }; // captures all by reference except local_var
|
||||
|
||||
[=] { return local_var; }; // captures all variable by value
|
||||
[local_var] { return local_var; }; // captures local_var by value
|
||||
[=, &local_var] { return ++local_var; }; // captures all variable by value except local_var
|
||||
|
||||
// Sample usages for lamdbas:
|
||||
std::vector< int> v { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
printf("[Lambdas] Initial array using lambdas: { ");
|
||||
|
||||
// Print the elements in an array using lambdas
|
||||
std::for_each(std::begin(v), std::end(v), [](int elem) { printf("%d ", elem); }); //capture specification
|
||||
printf("}.\n");
|
||||
|
||||
// Find the first odd number using lambda as an unary predicate when calling find_if.
|
||||
auto first_odd_element = std::find_if(std::begin(v), std::end(v), [=](int elem) { return elem % 2 == 1; });
|
||||
|
||||
if (first_odd_element != std::end(v))
|
||||
printf("[Lambdas] First odd element in the array is %d. \n", *first_odd_element);
|
||||
else
|
||||
printf("[Lambdas] No odd element found in the array.\n");
|
||||
|
||||
// Count the even numbers using a lambda function as an unary predicate when calling count_if.
|
||||
long long number_of_even_elements = std::count_if(std::begin(v), std::end(v), [=](int val) { return val % 2 == 0; });
|
||||
printf("[Lambdas] Number of even elements in the array is %lld.\n", number_of_even_elements);
|
||||
|
||||
// Sort the elements of an array using lambdas
|
||||
std::sort(std::begin(v), std::end(v), [](int e1, int e2) {return e2 < e1; });
|
||||
|
||||
// Print the elements in an array using lambdas
|
||||
printf("[Lambdas] Array after sort: { ");
|
||||
std::for_each(std::begin(v), std::end(v), [](int elem) { printf("%d ", elem); });
|
||||
printf("}. \n");
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
|
||||
// Feature name : auto
|
||||
// Feature description : It is used for type deduction
|
||||
// Demo description : Shows basic usages of auto specifier with different types.
|
||||
|
||||
// Helper function for ecall_auto_demo:
|
||||
void sample_func_auto_demo()
|
||||
{
|
||||
printf("[auto] Function sample_func_auto_demo is called. \n");
|
||||
}
|
||||
|
||||
void ecall_auto_demo()
|
||||
{
|
||||
double local_var = 0.0;
|
||||
|
||||
auto a = 7; // Type of variable a is deduced to be int
|
||||
printf("[auto] Type of a is int. typeid = %s.\n", typeid(a).name());
|
||||
|
||||
const auto b1 = local_var, *b2 = &local_var; // auto can be used with modifiers like const or &.
|
||||
printf("[auto] Type of b1 is const double. typeid = %s.\n", typeid(b1).name());
|
||||
printf("[auto] Type of b2 is const double*. typeid = %s.\n", typeid(b2).name());
|
||||
(void)b1;
|
||||
(void)b2;
|
||||
|
||||
auto c = 0, *d = &a; // multiple variable initialization if the deduced type does match
|
||||
printf("[auto] Type of c is int. typeid = %s.\n", typeid(c).name());
|
||||
printf("[auto] Type of d is int*. typeid = %s.\n", typeid(d).name());
|
||||
(void)c;
|
||||
(void)d;
|
||||
|
||||
auto lambda = [] {}; // can be used to define lambdas
|
||||
printf("[auto] Type of lambda is [] {}. typeid = %s.\n", typeid(lambda).name());
|
||||
(void)lambda;
|
||||
|
||||
auto func = sample_func_auto_demo; // can be used to deduce type of function
|
||||
printf("[auto] Type of func is void(__cdecl*)(void). typeid = %s.\n", typeid(func).name());
|
||||
func();
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : decltype
|
||||
// Feature description : It is used for type deduction
|
||||
// Demo description : Shows basic usages of decltype specifier with different types.
|
||||
void ecall_decltype_demo()
|
||||
{
|
||||
int a = 0 ;
|
||||
decltype(a) b = 0; // create an element of the same type as another element
|
||||
printf("[decltype] Type of b is int. typeid = %s.\n", typeid(b).name());
|
||||
|
||||
double c = 0;
|
||||
decltype(a + c) sum = a + c; // deduce type of a sum of elements of different types and create an element of that type.
|
||||
// most usefull in templates.
|
||||
printf("[decltype] Type of sum is double. typeid = %s.\n", typeid(sum).name());
|
||||
(void)sum;
|
||||
(void)b;
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : enum classes
|
||||
// Feature description : A new type of enum that solves problems found in old enum like :
|
||||
// unscoping of enum values and the possibility to compare them with int
|
||||
// Demo description : Shows basic usages of enum classes.
|
||||
void ecall_strongly_typed_enum_demo()
|
||||
{
|
||||
// In enum class the underlying type can be set. In the case bellow it is char.
|
||||
enum class DaysOfWeek : char { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY };
|
||||
|
||||
// initialization of variable of type DaysOfWeek
|
||||
DaysOfWeek random_day = DaysOfWeek::MONDAY;
|
||||
(void)random_day;
|
||||
|
||||
// In is not mandatory to specify the underlying type.
|
||||
enum class Weekend { SATURDAY, SUNDAY };
|
||||
|
||||
// The two enum classes above: days_of_week and weekend ilustrate that it is now possible to have two enum classes with the same values in them.
|
||||
|
||||
// end of demo
|
||||
}
|
||||
|
||||
// Feature name : Range based for loops
|
||||
// Feature description : Easy to read way of accessing elements in an container.
|
||||
// Demo description : Shows basic usage of range based for loop with c array and vector.
|
||||
void ecall_range_based_for_loops_demo()
|
||||
{
|
||||
char array_of_letters[] = { 'a','b','c','d' };
|
||||
std::vector<char> vector_of_letters = { 'a','b','c','d' };
|
||||
|
||||
printf("[range_based_for_loops] Using range based for loops to print the content of an array: { ");
|
||||
for (auto elem : array_of_letters)
|
||||
printf("%c ", elem);
|
||||
printf("}. \n");
|
||||
|
||||
printf("[range_based_for_loops] Using range based for loops to print the content of an vector: { ");
|
||||
for (auto elem : vector_of_letters)
|
||||
printf("%c ", elem);
|
||||
printf("}.\n");
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
|
||||
// Feature name : static_assert
|
||||
// Feature description : It is used to make assertions at compile time.
|
||||
// Demo description : Shows basic usage of static_assert with compile time operation.
|
||||
void ecall_static_assert_demo()
|
||||
{
|
||||
static_assert(sizeof(int) < sizeof(double), "Error : sizeof(int) < sizeof(double) ");
|
||||
const int a = 0;
|
||||
static_assert(a == 0, "Error: value of a is not 0");
|
||||
|
||||
// end of demo
|
||||
}
|
||||
|
||||
|
||||
// Feature name : New virtual function controls : override, final, default, and delete
|
||||
// Feature description : - delete : a deleted function cannot be inherited
|
||||
// - final : a final function cannot be overrided in the derived class
|
||||
// - default : intruction to the compiler to generate a default function
|
||||
// - override : ensures that a virtual function from derived class overrides a function from base
|
||||
// Demo description : Shows basic usage of new virtual function control.
|
||||
|
||||
/* Helper class for ecall_virtual_function_control_demo.*/
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void f_cannot_be_inherited() final {};
|
||||
Base(const Base &) = delete;
|
||||
Base() = default;
|
||||
virtual void f_must_be_overrided() {};
|
||||
};
|
||||
|
||||
/* Helper class for ecall_virtual_function_control_demo.*/
|
||||
class Derived : Base
|
||||
{
|
||||
public:
|
||||
/* The code bellow in this comment does not compile.
|
||||
The function cannot be override because it is declared with keyword final in base
|
||||
virtual double f_cannot_be_inherited() {};
|
||||
*/
|
||||
|
||||
/*The keyword override assures that the function overrides a base class member*/
|
||||
virtual void f_must_be_overrided() override {};
|
||||
};
|
||||
|
||||
void ecall_virtual_function_control_demo()
|
||||
{
|
||||
// The default constructor will be called generated by the compiler with explicit keyword default
|
||||
Base a;
|
||||
// Trying to use the copy contructor will generate code that does not compile because it is deleted
|
||||
// Base b = a;
|
||||
|
||||
// end of demo
|
||||
}
|
||||
|
||||
// Feature name : Delegating constructors
|
||||
// Feature description : A class constructors may have common code which can be delegated to a constructor to avoid code repetion
|
||||
// Demo description : Shows basic usage of delegating constructors
|
||||
|
||||
// Helper class for ecall_delegating_constructors
|
||||
class DemoDelegatingConstructors
|
||||
{
|
||||
int a, b, c;
|
||||
public:
|
||||
DemoDelegatingConstructors(int param_a, int param_b, int param_c)
|
||||
{
|
||||
this->a = param_a;
|
||||
this->b = param_b;
|
||||
this->c = param_c;
|
||||
/*common initialization*/
|
||||
switch (c)
|
||||
{
|
||||
case 1:
|
||||
printf("[delegating constructors] Called from DemoDelegatingConstructors(int a, int b). \n");
|
||||
break;
|
||||
case 2:
|
||||
printf("[delegating constructors] Called from DemoDelegatingConstructors(int a). \n");
|
||||
break;
|
||||
default:
|
||||
printf("[delegating constructors] Called from DemoDelegatingConstructors(int a, int b, int c).\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
DemoDelegatingConstructors(int param_a, int param_b) : DemoDelegatingConstructors(param_a, param_b, 1) {}
|
||||
DemoDelegatingConstructors(int param_a) : DemoDelegatingConstructors(param_a, 0, 2) {}
|
||||
};
|
||||
|
||||
void ecall_delegating_constructors_demo()
|
||||
{
|
||||
DemoDelegatingConstructors a(1, 2, 3);
|
||||
DemoDelegatingConstructors b(1, 2);
|
||||
DemoDelegatingConstructors c(1);
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : std::function
|
||||
// Feature description : It is used to store and invoke a callable
|
||||
// Demo description : Shows basic usage of std::function
|
||||
|
||||
// Helper class for ecall_std_function_demo:
|
||||
void sample_std_function1()
|
||||
{
|
||||
printf("[std_function] calling sample_std_function1\n");
|
||||
}
|
||||
|
||||
void ecall_std_function_demo()
|
||||
{
|
||||
// Example with functions
|
||||
std::function<void()> funct = sample_std_function1;
|
||||
funct();
|
||||
|
||||
//Example with lambda
|
||||
std::function<void()> funct_lambda = [] { printf("[std_function] calling a lambda function\n"); };
|
||||
funct_lambda();
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : std::all_of, std::any_of, std::none_of
|
||||
// Feature description : New C++11 algorithms
|
||||
// Demo description : Shows basic usage of the std::all_of, std::any_of, std::none_of.
|
||||
void ecall_cxx11_algorithms_demo()
|
||||
{
|
||||
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
|
||||
bool are_all_of = all_of(begin(v), end(v), [](int e) { return e % 2 == 0; });
|
||||
printf("[cxx11_algorithms] All elements in { 0 1 2 3 4 5 } are even is %s. \n", are_all_of ? "true" : "false");
|
||||
|
||||
bool are_any_of = any_of(begin(v), end(v), [](int e) { return e % 2 == 0; });
|
||||
printf("[cxx11_algorithms] Some elements in { 0 1 2 3 4 5 } are even is %s. \n", are_any_of ? "true" : "false");
|
||||
|
||||
bool are_none_of = none_of(begin(v), end(v), [](int e) { return e % 2 == 0; });
|
||||
printf("[cxx11_algorithms] Some elements in { 0 1 2 3 4 5 } are even is %s. \n", are_none_of ? "true" : "false");
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
|
||||
// Feature name : variadic templates
|
||||
// Feature description : Templates that can have multiple arguments
|
||||
// Demo description : Shows basic usage of variadic templates
|
||||
|
||||
// Helper template for ecall_variadic_templates_demo:
|
||||
template<typename T>
|
||||
T sum(T elem)
|
||||
{
|
||||
return elem;
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T sum(T elem1, T elem2, Args... args)
|
||||
{
|
||||
return elem1 + elem2 + sum(args...);
|
||||
}
|
||||
|
||||
void ecall_variadic_templates_demo()
|
||||
{
|
||||
int computed_sum = sum(1, 2, 3, 4, 5);
|
||||
printf("[variadic_templates] The sum of paramters (1, 2, 3, 4, 5) is %d. \n", computed_sum);
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : Substitution failure is not an error (SFINAE)
|
||||
// Feature description : Describes the case where a substitution error in templates does not cause errors
|
||||
// Demo description : Shows basic usage of SFINAE
|
||||
|
||||
/*first candidate for substitution*/
|
||||
template <typename T> void f(typename T::A*) { printf("[sfinae] First candidate for substitution is matched.\n"); };
|
||||
|
||||
/*second candidate for substitution*/
|
||||
template <typename T> void f(T) { printf("[sfinae] Second candidate for substitution is matched.\n"); }
|
||||
|
||||
void ecall_SFINAE_demo()
|
||||
{
|
||||
f<int>(0x0); // even if the first canditate substition will fail, the second one will pass
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
//Feature name : Initializer lists
|
||||
//Feature description : An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T.
|
||||
//Demo description : Demonstrates the usage of initializer list in the constructor of an object in enclave.
|
||||
class Number
|
||||
{
|
||||
public:
|
||||
Number(const std::initializer_list<int> &v) {
|
||||
for (auto i : v) {
|
||||
elements.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void print_elements() {
|
||||
printf("[initializer_list] The elements of the vector are:");
|
||||
for (auto item : elements) {
|
||||
printf(" %d", item);
|
||||
}
|
||||
printf(".\n");
|
||||
}
|
||||
private:
|
||||
std::vector<int> elements;
|
||||
};
|
||||
|
||||
void ecall_initializer_list_demo()
|
||||
{
|
||||
printf("[initializer_list] Using initializer list in the constructor. \n");
|
||||
Number m = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
|
||||
m.print_elements();
|
||||
|
||||
printf("\n"); //end of demo
|
||||
}
|
||||
|
||||
|
||||
// Feature name : Rvalue references and move semantics;
|
||||
// Feature description : They are used for memory usage optimazation by eliminating copy operations
|
||||
// Demo description : Shows basic usage of rvalue, move constructor, and move operator
|
||||
|
||||
// Helper class for ecall_rvalue_demo
|
||||
class DemoBuffer
|
||||
{
|
||||
public:
|
||||
unsigned int size = 100;
|
||||
char *buffer;
|
||||
|
||||
DemoBuffer(int param_size)
|
||||
{
|
||||
this->size = param_size;
|
||||
buffer = new char[size];
|
||||
printf("[rvalue] Called constructor : DemoBuffer(int size).\n");
|
||||
}
|
||||
|
||||
// A typical copy constructor needs to alocate memory for a new copy
|
||||
// Copying an big array is an expensive operation
|
||||
DemoBuffer(const DemoBuffer & rhs)
|
||||
{
|
||||
this->size = rhs.size;
|
||||
buffer = new char[rhs.size];
|
||||
memcpy(buffer, rhs.buffer, size);
|
||||
printf("[rvalue] Called copy constructor : DemoBuffer(const DemoBuffer & rhs).\n");
|
||||
}
|
||||
|
||||
// A typical move constructor can reuse the memory pointed by the buffer
|
||||
DemoBuffer(DemoBuffer && rhs)
|
||||
{
|
||||
buffer = rhs.buffer;
|
||||
size = rhs.size;
|
||||
// reset state of rhs
|
||||
rhs.buffer = NULL;
|
||||
rhs.size = 0;
|
||||
printf("[rvalue] Called move constructor : DemoBuffer(DemoBuffer && rhs).\n");
|
||||
}
|
||||
~DemoBuffer()
|
||||
{
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Helper class for ecall_rvalue_demo
|
||||
DemoBuffer foobar(int a)
|
||||
{
|
||||
DemoBuffer x(100);
|
||||
DemoBuffer y(100);
|
||||
|
||||
if (a > 0)
|
||||
return x;
|
||||
else
|
||||
return y;
|
||||
}
|
||||
void ecall_rvalue_demo()
|
||||
{
|
||||
// This will call the constructor
|
||||
printf("[rvalue] DemoBuffer a(100).\n");
|
||||
DemoBuffer a(100);
|
||||
|
||||
printf("[rvalue] DemoBuffer foobar(100). \n");
|
||||
// Initializing variable d using a temporary object will result in a call to move constructor
|
||||
// This is usefull because it reduces the memory cost of the operation.
|
||||
DemoBuffer d(foobar(100));
|
||||
|
||||
// This will call the copy constructor. State of a will not change.
|
||||
printf("[rvalue] DemoBuffer b(a).\n");
|
||||
DemoBuffer b(a);
|
||||
|
||||
printf("[rvalue] DemoBuffer c(std::move(a)).\n");
|
||||
// explicitly cast a to an rvalue so that c will be created using move constructor.
|
||||
// State of a is going to be reseted.
|
||||
DemoBuffer c(std::move(a));
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : Nullptr
|
||||
// Feature description : Resolves the issues of converting NULL to integral types
|
||||
// Demo description : Shows basic usage of nullptr
|
||||
|
||||
// overload candidate 1
|
||||
void nullptr_overload_candidate(int i) {
|
||||
(void)i;
|
||||
printf("[nullptr] called void nullptr_overload_candidate(int i).\n");
|
||||
}
|
||||
|
||||
// overload candidate 2
|
||||
void nullptr_overload_candidate(int* ptr) {
|
||||
(void)ptr;
|
||||
printf("[nullptr] called void nullptr_overload_candidate(int* ptr).\n");
|
||||
}
|
||||
|
||||
template<class F, class A>
|
||||
void Fwd(F f, A a)
|
||||
{
|
||||
f(a);
|
||||
}
|
||||
|
||||
void g(int* i)
|
||||
{
|
||||
(void)i;
|
||||
printf("[nullptr] Function %s called\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
// Feature name :
|
||||
// Feature description :
|
||||
// Demo description :
|
||||
void ecall_nullptr_demo()
|
||||
{
|
||||
// NULL can be converted to integral types() like int and will call overload candidate 1
|
||||
nullptr_overload_candidate(NULL);
|
||||
|
||||
// nullptr can't be converted to integral types() like int and will call overload candidate 2
|
||||
nullptr_overload_candidate(nullptr);
|
||||
|
||||
g(NULL); // Fine
|
||||
g(0); // Fine
|
||||
Fwd(g, nullptr); // Fine
|
||||
//Fwd(g, NULL); // ERROR: No function g(int)
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : Scoped enums
|
||||
// Feature description :
|
||||
// Demo description :
|
||||
enum class Color { orange, brown, green = 30, blue, red };
|
||||
|
||||
void ecall_enum_class_demo()
|
||||
{
|
||||
int n = 0;
|
||||
Color color1 = Color::brown;
|
||||
switch (color1)
|
||||
{
|
||||
case Color::orange: printf("[enum class] orange"); break;
|
||||
case Color::brown: printf("[enum class] brown"); break;
|
||||
case Color::green: printf("[enum class] green"); break;
|
||||
case Color::blue: printf("[enum class] blue"); break;
|
||||
case Color::red: printf("[enum class] red"); break;
|
||||
}
|
||||
// n = color1; // Not allowed: no scoped enum to int conversion
|
||||
n = static_cast<int>(color1); // OK, n = 1
|
||||
printf(" - int = %d\n", n);
|
||||
|
||||
Color color2 = Color::red;
|
||||
switch (color2)
|
||||
{
|
||||
case Color::orange: printf("[enum class] orange"); break;
|
||||
case Color::brown: printf("[enum class] brown"); break;
|
||||
case Color::green: printf("[enum class] green"); break;
|
||||
case Color::blue: printf("[enum class] blue"); break;
|
||||
case Color::red: printf("[enum class] red"); break;
|
||||
}
|
||||
n = static_cast<int>(color2); // OK, n = 32
|
||||
printf(" - int = %d\n", n);
|
||||
|
||||
Color color3 = Color::green;
|
||||
switch (color3)
|
||||
{
|
||||
case Color::orange: printf("[enum class] orange"); break;
|
||||
case Color::brown: printf("[enum class] brown"); break;
|
||||
case Color::green: printf("[enum class] green"); break;
|
||||
case Color::blue: printf("[enum class] blue"); break;
|
||||
case Color::red: printf("[enum class] red"); break;
|
||||
}
|
||||
n = static_cast<int>(color3); // OK, n = 30
|
||||
printf(" - int = %d\n", n);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Feature name : new container classes
|
||||
// Feature description : unordered_set, unordered_map, unordered_multiset, and unordered_multimap
|
||||
// Demo description : Shows basic usage of new container classes
|
||||
void ecall_new_container_classes_demo()
|
||||
{
|
||||
// unordered_set
|
||||
// container used for fast acces that groups elements in buckets based on their hash
|
||||
|
||||
std::unordered_set<int> set_of_numbers = { 0, 1, 2, 3, 4, 5 };
|
||||
const int searchVal = 3;
|
||||
std::unordered_set<int>::const_iterator got = set_of_numbers.find(searchVal);
|
||||
|
||||
if (got == set_of_numbers.end())
|
||||
printf("[new_container_classes] unordered_set { 0, 1, 2, 3, 4, 5} has value 3.\n");
|
||||
else
|
||||
printf("[new_container_classes] unordered_set { 0, 1, 2, 3, 4, 5} it does not have value 3.\n");
|
||||
|
||||
// unordered_multiset
|
||||
// container used for fast acces that groups non unique elements in buckets based on their hash
|
||||
std::unordered_multiset<int> multiset_of_numbers = { 0, 1, 2, 3, 3, 3 };
|
||||
printf("[new_container_classes] multiset_set { 0, 1, 2, 3, 3, 3} has %d elements with value %d.\n",
|
||||
(int)multiset_of_numbers.count(searchVal), searchVal);
|
||||
|
||||
// unordered_map
|
||||
std::unordered_map<std::string, int> grades{ { "A", 10 },{ "B", 8 },{ "C", 7 },{ "D", 5 },{ "E", 3 } };
|
||||
printf("[new_container_classes] unordered_map elements: {");
|
||||
for (auto pair : grades) {
|
||||
printf("[%s %d] ", pair.first.c_str(), pair.second);
|
||||
}
|
||||
|
||||
printf("}.\n");
|
||||
|
||||
// unordered_multimap
|
||||
std::unordered_multimap<std::string, int> multimap_grades{ { "A", 10 },{ "B", 8 },{ "B", 7 },{ "E", 5 },{ "E", 3 },{ "E",1 } };
|
||||
|
||||
printf("[new_container_classes] unordered_multimap elements: {");
|
||||
for (auto pair : multimap_grades) {
|
||||
printf("[%s %d] ", pair.first.c_str(), pair.second);
|
||||
}
|
||||
printf("}.\n");
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : Tuple
|
||||
// Feature description : Objects that pack elements of multiple types which can be accessed by index
|
||||
// Demo description : Shows basic usage of tuple: creation and access
|
||||
void ecall_tuple_demo()
|
||||
{
|
||||
// Create tuple using std::make_tuple
|
||||
char array_of_letters[4] = {'A','B','C','D'};
|
||||
std::vector<char> vector_of_letters = { 'A','B','C','D' };
|
||||
std::map<char, char> map_of_letters = { {'B','b' } };
|
||||
|
||||
// Creating a tuple using a tuple constructor
|
||||
std::tuple<int, std::string> tuple_sample_with_constructor(42, "Sample tuple");
|
||||
(void)tuple_sample_with_constructor;
|
||||
|
||||
// Creating a tuple using std::make_tuple
|
||||
auto tuple_sample = std::make_tuple("<First element of TupleSample>", 1, 7.9, vector_of_letters, array_of_letters, map_of_letters);
|
||||
|
||||
// Access the elements in tupleSample using std::get<index>
|
||||
printf("[tuple] show first element in TupleSample: %s. \n", std::get<0>(tuple_sample));
|
||||
printf("[tuple] show second element in TupleSample: %d. \n", std::get<1>(tuple_sample));
|
||||
printf("[tuple] show third element in TupleSample: %f. \n", std::get<2>(tuple_sample));
|
||||
|
||||
// Getting vector from a tuple
|
||||
std::vector<char> temp_vector = std::get<3>(tuple_sample);
|
||||
(void)temp_vector;
|
||||
|
||||
// Getting array from a tuple
|
||||
int first_elem_of_array = std::get<4>(tuple_sample)[0];
|
||||
(void)first_elem_of_array;
|
||||
|
||||
// Getting map from a tuple
|
||||
std::map<char, char> temp_map = std::get<5>(tuple_sample);
|
||||
(void)temp_map;
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
|
||||
// Feature name : new smart pointer
|
||||
// Feature description : shared_ptr and unique_ptr
|
||||
// Demo decription : Shows basic usage of smart pointers
|
||||
// Helper class for ecall_shared_ptr_demo
|
||||
class DemoSmartPtr
|
||||
{
|
||||
std::string smartPointerType;
|
||||
public:
|
||||
DemoSmartPtr(std::string param_smartPointerType)
|
||||
{
|
||||
printf("[smart_ptr] In construct of object demo_smart_ptr using %s. \n", param_smartPointerType.c_str());
|
||||
this->smartPointerType = param_smartPointerType;
|
||||
}
|
||||
~DemoSmartPtr()
|
||||
{
|
||||
printf("[smart_ptr] In deconstructor of object demo_smart_ptr using %s. \n", smartPointerType.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
void ecall_shared_ptr_demo()
|
||||
{
|
||||
// std::shared_ptr is smart pointer that takes ownership of an object using a pointer
|
||||
// The object is freed when the last smart_pointer does not point to it.
|
||||
|
||||
// Creating a shared pointer using std::make_shared
|
||||
auto shared_ptr = std::make_shared<DemoSmartPtr>("smart_ptr."); // The constructor of DemoSmartPtr will be called here
|
||||
|
||||
printf("[smart_ptr] shared_ptr reference count = %ld. \n", shared_ptr.use_count());
|
||||
auto shared_ptr2 = shared_ptr;
|
||||
printf("[smart_ptr] shared_ptr reference count = %ld incresead after creating another shared pointer.\n", shared_ptr.use_count());
|
||||
shared_ptr2.reset();
|
||||
printf("[smart_ptr] shared_ptr reference count = %ld decresead after calling releasing ownership. \n", shared_ptr.use_count());
|
||||
|
||||
// std::unique_ptr is smart pointer that takes ownership of an object using a pointer
|
||||
// it is different from smart_ptr in the sense that only one unique_ptr can take ownership
|
||||
|
||||
std::unique_ptr<DemoSmartPtr> unique_ptr(new DemoSmartPtr("unique_ptr"));
|
||||
// When going out of scope both shared_ptr and unique_ptr release the objects they own
|
||||
|
||||
// end of demo
|
||||
}
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
//Feature name : atomic
|
||||
//Feature description: The atomic library provides components for fine-grained atomic operations allowing for lockless concurrent programming.
|
||||
// Each atomic operation is indivisible with regards to any other atomic operation that involves the same object.
|
||||
// Atomic objects are free of data races.
|
||||
//Demo description : Demonstrates the usage of atomic types, objects and functions in enclave.
|
||||
void ecall_atomic_demo()
|
||||
{
|
||||
printf("[atomic] Atomic types, objects and functions demo.\n");
|
||||
|
||||
printf("[atomic_store] Defining an atomic_char object with an initial value of 5.\n");
|
||||
std::atomic_char atc(5);
|
||||
printf("[atomic_store] The current value stored in the atomic object is: %d\n", atc.load());
|
||||
printf("[atomic_store] Replacing the value of the atomic object with a non-atomic value of 3.\n");
|
||||
std::atomic_store<char>(&atc, 3);
|
||||
printf("[atomic_store] The new value of the atomic object is: %d.\n", atc.load());
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("[atomic_store_explicit] Defining an atomic_short object with an initial value of 5.\n");
|
||||
std::atomic_short ats(5);
|
||||
printf("[atomic_store_explicit] The current value stored in the atomic object is: %d.\n", ats.load());
|
||||
printf("[atomic_store_explicit] Replacing the value of the atomic object with a non-atomic value of 3.\n");
|
||||
std::atomic_store_explicit<short>(&ats, 3, std::memory_order_seq_cst);
|
||||
printf("[atomic_store] The new value of the atomic object is: %d.\n", ats.load());
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("[atomic_load] Defining an atomic_int object with an initial value of 4.\n");
|
||||
std::atomic_int ati1(4);
|
||||
printf("[atomic_load] Obtaining the value of the atomic object and saving it in a int variable.\n");
|
||||
int val = std::atomic_load(&ati1);
|
||||
printf("[atomic_load] The obtained value is %d.\n", val);
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("[atomic_load_explicit] Defining an atomic_int object with an initial value of 2.\n");
|
||||
std::atomic_int ati2(2);
|
||||
printf("[atomic_load_explicit] Obtaining the value of the atomic object and saving it in a int variable.\n");
|
||||
int val1 = std::atomic_load_explicit(&ati2, std::memory_order_seq_cst);
|
||||
printf("[atomic_load_explicit] The obtained value is %d.\n", val1);
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("[atomic_fetch_add] Defining an atomic_int object with an initial value of 7.\n");
|
||||
std::atomic_int ati(7);
|
||||
printf("[atomic_fetch_add] The current value stored in the atomic object is: %d.\n", ati.load());
|
||||
printf("[atomic_fetch_add] Adding a non-atomic value of 8 to the atomic object.\n");
|
||||
std::atomic_fetch_add(&ati, 8);
|
||||
printf("[atomic_fetch_add] The new value of the atomic object is: %d.\n", ati.load());
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("[atomic_fetch_add_explicit] Defining an atomic_uint object with an initial value of 7.\n");
|
||||
std::atomic_uint atui(7);
|
||||
printf("[atomic_fetch_add_explicit] The current value stored in the atomic object is: %u.\n", atui.load());
|
||||
printf("[atomic_fetch_add_explicit] Adding a non-atomic value of 8 to the atomic object.\n");
|
||||
std::atomic_fetch_add_explicit<unsigned int>(&atui, 8, std::memory_order_seq_cst);
|
||||
printf("[atomic_fetch_add_explicit] The new value of the atomic object is: %u.\n", atui.load());
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("[atomic_fetch_sub] Defining an atomic_long object with an initial value of 20.\n");
|
||||
std::atomic_long atl(20);
|
||||
printf("[atomic_fetch_sub] The current value stored in the atomic object is: %ld.\n", atl.load());
|
||||
printf("[atomic_fetch_sub] Substracting a non-atomic value of 8 from the value of the atomic object.\n");
|
||||
std::atomic_fetch_sub<long>(&atl, 8);
|
||||
printf("[atomic_fetch_sub] The new value of the atomic object is: %ld.\n", atl.load());
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("[atomic_fetch_sub_explicit] Defining an atomic_llong object with an initial value of 20.\n");
|
||||
std::atomic_llong atll(20);
|
||||
printf("[atomic_fetch_sub_explicit] The current value stored in the atomic object is: %lld.\n", atll.load());
|
||||
printf("[atomic_fetch_sub_explicit] Adding a non-atomic value of 8 to the atomic object.\n");
|
||||
std::atomic_fetch_sub_explicit<long long>(&atll, 8, std::memory_order_seq_cst);
|
||||
printf("[atomic_fetch_sub_explicit] The new value of the atomic object is: %lld.\n", atll.load());
|
||||
|
||||
printf("\n"); // end of demo
|
||||
}
|
||||
#else
|
||||
void ecall_atomic_demo() {}
|
||||
#endif /*defined(__INTEL_COMPILER)*/
|
||||
|
||||
//Feature name : mutex
|
||||
//Feature description : The mutex class is a synchronization primitive that can be used to protect shared data
|
||||
// from being simultaneously accessed by multiple threads.
|
||||
//Demo description : Demonstrates mutex protection when incrementing values in multiple threads.
|
||||
|
||||
//Structure used in mutex demo to show the behavior without using a mutex
|
||||
struct CounterWithoutMutex {
|
||||
int value;
|
||||
|
||||
CounterWithoutMutex() : value(0) {}
|
||||
|
||||
void increment() {
|
||||
++value;
|
||||
}
|
||||
};
|
||||
|
||||
CounterWithoutMutex counter_without_protection;
|
||||
|
||||
//E-call used by mutex demo to perform the incrementation using a counter without mutex protection
|
||||
void ecall_mutex_demo_no_protection()
|
||||
{
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
counter_without_protection.increment();
|
||||
}
|
||||
}
|
||||
|
||||
//E-call used by mutex demo to get the final value of the counter from enclave
|
||||
void ecall_print_final_value_no_protection()
|
||||
{
|
||||
printf("[mutex] Incrementing values in three threads without mutex protection, using a 100000 times loop. \n[mutex]Expected value is 300000. The final value is %d.\n", counter_without_protection.value);
|
||||
}
|
||||
|
||||
|
||||
//Structure used in mutex demo
|
||||
struct CounterProtectedByMutex {
|
||||
std::mutex mutex;
|
||||
int value;
|
||||
|
||||
CounterProtectedByMutex() : value(0) {}
|
||||
|
||||
void increment() {
|
||||
//locking the mutex to avoid simultaneous incrementation in different threads
|
||||
mutex.lock();
|
||||
++value;
|
||||
//unlocking the mutex
|
||||
mutex.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
CounterProtectedByMutex counter_with_protection;
|
||||
|
||||
//E-call used by mutex demo to perform the actual incrementation
|
||||
void ecall_mutex_demo()
|
||||
{
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
counter_with_protection.increment();
|
||||
}
|
||||
}
|
||||
|
||||
//E-call used by mutex demo to get the final value of the counter from enclave
|
||||
void ecall_print_final_value_mutex_demo()
|
||||
{
|
||||
printf("[mutex] Mutex protection when incrementing a value in 3 threads, using a 100000 times loop. \n[mutex]Expected value is 300000. The final value is %d.\n", counter_with_protection.value);
|
||||
}
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
//Feature name : condition_variable
|
||||
//Feature description: The condition_variable class is a synchronization primitive that can be used to block a thread,
|
||||
// or multiple threads at the same time, until another thread both modifies a shared variable (the condition),
|
||||
// and notifies the condition_variable.
|
||||
//Demo description : Demonstrates condition_variable usage in a two threads environment. One thread is used for loading the data and
|
||||
// the other processes the loaded data. The thread for processing the data waits untill the data is loaded in the
|
||||
// other thread and gets notified when loading is completed.
|
||||
|
||||
//This class is used by condition variable demo
|
||||
class DemoConditionVariable
|
||||
{
|
||||
std::mutex mtx;
|
||||
std::condition_variable cond_var;
|
||||
bool data_loaded;
|
||||
public:
|
||||
DemoConditionVariable()
|
||||
{
|
||||
data_loaded = false;
|
||||
}
|
||||
void load_data()
|
||||
{
|
||||
//Simulating loading of the data
|
||||
printf("[condition_variable] Loading Data...\n");
|
||||
{
|
||||
// Locking the data structure
|
||||
std::lock_guard<std::mutex> guard(mtx);
|
||||
// Setting the flag to true to signal load data completion
|
||||
data_loaded = true;
|
||||
}
|
||||
// Notify to unblock the waiting thread
|
||||
cond_var.notify_one();
|
||||
}
|
||||
bool is_data_loaded()
|
||||
{
|
||||
return data_loaded;
|
||||
}
|
||||
void main_task()
|
||||
{
|
||||
printf("\n");
|
||||
printf("[condition_variable] Running condition variable demo.\n");
|
||||
|
||||
// Acquire the lock
|
||||
std::unique_lock<std::mutex> lck(mtx);
|
||||
|
||||
printf("[condition_variable] Waiting for the data to be loaded in the other thread.\n");
|
||||
cond_var.wait(lck, std::bind(&DemoConditionVariable::is_data_loaded, this));
|
||||
printf("[condition_variable] Processing the loaded data.\n");
|
||||
printf("[condition_variable] Done.\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
DemoConditionVariable app;
|
||||
|
||||
//E-call used by condition_variable demo - processing thread
|
||||
|
||||
void ecall_condition_variable_run()
|
||||
{
|
||||
app.main_task();
|
||||
}
|
||||
|
||||
//E-call used by condifion_variable demo - loader thread
|
||||
void ecall_condition_variable_load()
|
||||
{
|
||||
app.load_data();
|
||||
}
|
||||
#else
|
||||
void ecall_condition_variable_run() {}
|
||||
void ecall_condition_variable_load() {}
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Libcxx.edl - EDL sample for trusted C++ library. */
|
||||
|
||||
enclave {
|
||||
|
||||
/*
|
||||
* A subset of the C++03 standard is supported.
|
||||
*/
|
||||
|
||||
trusted {
|
||||
|
||||
public void ecall_lambdas_demo(void);
|
||||
public void ecall_auto_demo(void);
|
||||
public void ecall_decltype_demo(void);
|
||||
public void ecall_strongly_typed_enum_demo(void);
|
||||
public void ecall_range_based_for_loops_demo(void);
|
||||
public void ecall_static_assert_demo(void);
|
||||
public void ecall_virtual_function_control_demo(void);
|
||||
public void ecall_delegating_constructors_demo(void);
|
||||
public void ecall_std_function_demo(void);
|
||||
public void ecall_cxx11_algorithms_demo(void);
|
||||
public void ecall_variadic_templates_demo(void);
|
||||
public void ecall_SFINAE_demo(void);
|
||||
public void ecall_initializer_list_demo(void);
|
||||
public void ecall_rvalue_demo(void);
|
||||
public void ecall_nullptr_demo(void);
|
||||
public void ecall_enum_class_demo(void);
|
||||
public void ecall_new_container_classes_demo(void);
|
||||
public void ecall_tuple_demo(void);
|
||||
public void ecall_shared_ptr_demo(void);
|
||||
public void ecall_atomic_demo(void);
|
||||
public void ecall_mutex_demo(void);
|
||||
public void ecall_print_final_value_mutex_demo(void);
|
||||
public void ecall_mutex_demo_no_protection(void);
|
||||
public void ecall_print_final_value_no_protection(void);
|
||||
public void ecall_condition_variable_run(void);
|
||||
public void ecall_condition_variable_load(void);
|
||||
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,249 @@
|
||||
#
|
||||
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
######## SGX SDK Settings ########
|
||||
|
||||
SGX_SDK ?= /opt/intel/sgxsdk
|
||||
SGX_MODE ?= HW
|
||||
SGX_ARCH ?= x64
|
||||
SGX_DEBUG ?= 1
|
||||
|
||||
ifeq ($(shell getconf LONG_BIT), 32)
|
||||
SGX_ARCH := x86
|
||||
else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32)
|
||||
SGX_ARCH := x86
|
||||
endif
|
||||
|
||||
ifeq ($(SGX_ARCH), x86)
|
||||
SGX_COMMON_CFLAGS := -m32
|
||||
SGX_LIBRARY_PATH := $(SGX_SDK)/lib
|
||||
SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign
|
||||
SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r
|
||||
else
|
||||
SGX_COMMON_CFLAGS := -m64
|
||||
SGX_LIBRARY_PATH := $(SGX_SDK)/lib64
|
||||
SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign
|
||||
SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r
|
||||
endif
|
||||
|
||||
ifeq ($(SGX_DEBUG), 1)
|
||||
ifeq ($(SGX_PRERELEASE), 1)
|
||||
$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(SGX_DEBUG), 1)
|
||||
SGX_COMMON_CFLAGS += -O0 -g
|
||||
else
|
||||
SGX_COMMON_CFLAGS += -O2
|
||||
endif
|
||||
|
||||
######## App Settings ########
|
||||
|
||||
ifneq ($(SGX_MODE), HW)
|
||||
Urts_Library_Name := sgx_urts_sim
|
||||
else
|
||||
Urts_Library_Name := sgx_urts
|
||||
endif
|
||||
|
||||
App_Cpp_Files := App/App.cpp $(wildcard App/TrustedLibrary/*.cpp)
|
||||
App_Include_Paths := -IInclude -IApp -I$(SGX_SDK)/include
|
||||
|
||||
App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
|
||||
|
||||
# Three configuration modes - Debug, prerelease, release
|
||||
# Debug - Macro DEBUG enabled.
|
||||
# Prerelease - Macro NDEBUG and EDEBUG enabled.
|
||||
# Release - Macro NDEBUG enabled.
|
||||
ifeq ($(SGX_DEBUG), 1)
|
||||
App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG
|
||||
else ifeq ($(SGX_PRERELEASE), 1)
|
||||
App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG
|
||||
else
|
||||
App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG
|
||||
endif
|
||||
|
||||
App_Cpp_Flags := $(App_C_Flags) -std=c++11
|
||||
App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
|
||||
|
||||
ifneq ($(SGX_MODE), HW)
|
||||
App_Link_Flags += -lsgx_uae_service_sim
|
||||
else
|
||||
App_Link_Flags += -lsgx_uae_service
|
||||
endif
|
||||
|
||||
App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o)
|
||||
|
||||
App_Name := app
|
||||
|
||||
######## Enclave Settings ########
|
||||
|
||||
Enclave_Version_Script := Enclave/Enclave_debug.lds
|
||||
ifeq ($(SGX_MODE), HW)
|
||||
ifneq ($(SGX_DEBUG), 1)
|
||||
ifneq ($(SGX_PRERELEASE), 1)
|
||||
# Choose to use 'Enclave.lds' for HW release mode
|
||||
Enclave_Version_Script = Enclave/Enclave.lds
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(SGX_MODE), HW)
|
||||
Trts_Library_Name := sgx_trts_sim
|
||||
Service_Library_Name := sgx_tservice_sim
|
||||
else
|
||||
Trts_Library_Name := sgx_trts
|
||||
Service_Library_Name := sgx_tservice
|
||||
endif
|
||||
Crypto_Library_Name := sgx_tcrypto
|
||||
|
||||
Enclave_Cpp_Files := Enclave/Enclave.cpp $(wildcard Enclave/TrustedLibrary/*.cpp)
|
||||
Enclave_Include_Paths := -IInclude -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/libcxx -I$(SGX_SDK)/include/tlibc
|
||||
|
||||
Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths)
|
||||
Enclave_Cpp_Flags := $(Enclave_C_Flags) -nostdinc++ -std=c++11
|
||||
|
||||
# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries:
|
||||
# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options,
|
||||
# so that the whole content of trts is included in the enclave.
|
||||
# 2. For other libraries, you just need to pull the required symbols.
|
||||
# Use `--start-group' and `--end-group' to link these libraries.
|
||||
# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options.
|
||||
# Otherwise, you may get some undesirable errors.
|
||||
Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \
|
||||
-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
|
||||
-Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \
|
||||
-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
|
||||
-Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
|
||||
-Wl,--defsym,__ImageBase=0 \
|
||||
-Wl,--version-script=$(Enclave_Version_Script)
|
||||
|
||||
Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o)
|
||||
|
||||
Enclave_Name := enclave.so
|
||||
Signed_Enclave_Name := enclave.signed.so
|
||||
Enclave_Config_File := Enclave/Enclave.config.xml
|
||||
|
||||
ifeq ($(SGX_MODE), HW)
|
||||
ifeq ($(SGX_DEBUG), 1)
|
||||
Build_Mode = HW_DEBUG
|
||||
else ifeq ($(SGX_PRERELEASE), 1)
|
||||
Build_Mode = HW_PRERELEASE
|
||||
else
|
||||
Build_Mode = HW_RELEASE
|
||||
endif
|
||||
else
|
||||
ifeq ($(SGX_DEBUG), 1)
|
||||
Build_Mode = SIM_DEBUG
|
||||
else ifeq ($(SGX_PRERELEASE), 1)
|
||||
Build_Mode = SIM_PRERELEASE
|
||||
else
|
||||
Build_Mode = SIM_RELEASE
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: all run
|
||||
|
||||
ifeq ($(Build_Mode), HW_RELEASE)
|
||||
all: $(App_Name) $(Enclave_Name)
|
||||
@echo "The project has been built in release hardware mode."
|
||||
@echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave."
|
||||
@echo "To sign the enclave use the command:"
|
||||
@echo " $(SGX_ENCLAVE_SIGNER) sign -key <your key> -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)"
|
||||
@echo "You can also sign the enclave using an external signing tool."
|
||||
@echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW."
|
||||
else
|
||||
all: $(App_Name) $(Signed_Enclave_Name)
|
||||
ifeq ($(Build_Mode), HW_DEBUG)
|
||||
@echo "The project has been built in debug hardware mode."
|
||||
else ifeq ($(Build_Mode), SIM_DEBUG)
|
||||
@echo "The project has been built in debug simulation mode."
|
||||
else ifeq ($(Build_Mode), HW_PRERELEASE)
|
||||
@echo "The project has been built in pre-release hardware mode."
|
||||
else ifeq ($(Build_Mode), SIM_PRERELEASE)
|
||||
@echo "The project has been built in pre-release simulation mode."
|
||||
else
|
||||
@echo "The project has been built in release simulation mode."
|
||||
endif
|
||||
endif
|
||||
|
||||
run: all
|
||||
ifneq ($(Build_Mode), HW_RELEASE)
|
||||
@$(CURDIR)/$(App_Name)
|
||||
@echo "RUN => $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]"
|
||||
endif
|
||||
|
||||
######## App Objects ########
|
||||
|
||||
App/Enclave_u.c: $(SGX_EDGER8R) Enclave/Enclave.edl
|
||||
@cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include
|
||||
@echo "GEN => $@"
|
||||
|
||||
App/Enclave_u.o: App/Enclave_u.c
|
||||
@$(CC) $(App_C_Flags) -c $< -o $@
|
||||
@echo "CC <= $<"
|
||||
|
||||
App/%.o: App/%.cpp
|
||||
@$(CXX) $(App_Cpp_Flags) -c $< -o $@
|
||||
@echo "CXX <= $<"
|
||||
|
||||
$(App_Name): App/Enclave_u.o $(App_Cpp_Objects)
|
||||
@$(CXX) $^ -o $@ $(App_Link_Flags)
|
||||
@echo "LINK => $@"
|
||||
|
||||
|
||||
######## Enclave Objects ########
|
||||
|
||||
Enclave/Enclave_t.c: $(SGX_EDGER8R) Enclave/Enclave.edl
|
||||
@cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include
|
||||
@echo "GEN => $@"
|
||||
|
||||
Enclave/Enclave_t.o: Enclave/Enclave_t.c
|
||||
@$(CC) $(Enclave_C_Flags) -c $< -o $@
|
||||
@echo "CC <= $<"
|
||||
|
||||
Enclave/%.o: Enclave/%.cpp
|
||||
@$(CXX) $(Enclave_Cpp_Flags) -c $< -o $@
|
||||
@echo "CXX <= $<"
|
||||
|
||||
$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects)
|
||||
@$(CXX) $^ -o $@ $(Enclave_Link_Flags)
|
||||
@echo "LINK => $@"
|
||||
|
||||
$(Signed_Enclave_Name): $(Enclave_Name)
|
||||
@$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File)
|
||||
@echo "SIGN => $@"
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
@rm -f $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.*
|
||||
@@ -0,0 +1,44 @@
|
||||
-----------------------
|
||||
Purpose of Cxx11SGXDemo
|
||||
-----------------------
|
||||
|
||||
The project demonstrates serveral C++11 features inside the Enclave:
|
||||
- lambda expressions;
|
||||
- rvalue references and move semantics;
|
||||
- automatic type deduction with auto and decltype;
|
||||
- nullptr type;
|
||||
- strongly typed enum classes;
|
||||
- Range-based for statements;
|
||||
- static_assert keyword for compile-time assertion;
|
||||
- initializer lists and uniform initialization syntax;
|
||||
- New virtual function controls: override, final, default, and delete;
|
||||
- delegating constructors;
|
||||
- new container classes (unordered_set, unordered_map, unordered_multiset, and unordered_multimap);
|
||||
- tuple class;
|
||||
- function object wrapper;
|
||||
- atomic, mutexes, condition_variables;
|
||||
- new smart pointer classes: shared_ptr, unique_ptr;
|
||||
- new c++ algorithms: all_off, any_of, none_of;
|
||||
- variadic templates;
|
||||
- SFINAE;
|
||||
|
||||
---------------------------------------------
|
||||
How to Build/Execute the C++11 sample program
|
||||
---------------------------------------------
|
||||
1. Install Intel(R) SGX SDK for Linux* OS
|
||||
2. Build the project with the prepared Makefile:
|
||||
a. Hardware Mode, Debug build:
|
||||
$ make
|
||||
b. Hardware Mode, Pre-release build:
|
||||
$ make SGX_PRERELEASE=1 SGX_DEBUG=0
|
||||
c. Hardware Mode, Release build:
|
||||
$ make SGX_DEBUG=0
|
||||
d. Simulation Mode, Debug build:
|
||||
$ make SGX_MODE=SIM
|
||||
e. Simulation Mode, Pre-release build:
|
||||
$ make SGX_MODE=SIM SGX_PRERELEASE=1 SGX_DEBUG=0
|
||||
f. Simulation Mode, Release build:
|
||||
$ make SGX_MODE=SIM SGX_DEBUG=0
|
||||
3. Execute the binary directly:
|
||||
$ ./app
|
||||
4. Remember to "make clean" before switching build mode
|
||||
Reference in New Issue
Block a user