Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libunwind changes needed to run code in sgx environment via rust-sgx. #57

Merged
merged 1 commit into from
Jun 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libunwind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ if (LIBUNWIND_ENABLE_ASSERTIONS)

# On Release builds cmake automatically defines NDEBUG, so we
# explicitly undefine it:
if (uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
if ((uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE") AND (NOT RUST_SGX))
add_compile_flags(-UNDEBUG)
endif()
else()
Expand Down
22 changes: 22 additions & 0 deletions libunwind/README_RUST_SGX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Libunwind customizations for linking with x86_64-fortanix-unknown-sgx Rust target.

## Description
### Initial Fork
Initial Fork has been made from 5.0 release of llvm (commit: 6a075b6de4)
### Detailed Description
#### Header files that we do not include for this target
1. pthread.h
#### Library that we do not link to for this target.
1. pthread (Locks used by libunwind is provided by rust stdlib for this target)

## Building unwind for rust-sgx target
### Generate Make files:
* `cd where you want to build libunwind`
* `mkdir build`
* `cd build`
* `cmake -DCMAKE_BUILD_TYPE="RELEASE" -DRUST_SGX=1 -G "Unix Makefiles" -DLLVM_ENABLE_WARNINGS=1 -DLIBUNWIND_ENABLE_PEDANTIC=0 -DLLVM_PATH=<path/to/llvm> <path/to/libunwind>`
* `"DEBUG"` could be used instead of `"RELEASE"` to enable debug logs of libunwind.

### Build:
* `make unwind_static`
* `build/lib/` will have the built library.
5 changes: 5 additions & 0 deletions libunwind/docs/BuildingLibunwind.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,8 @@ libunwind specific options
.. option:: LIBUNWIND_SYSROOT

Sysroot for cross compiling

.. option:: LIBUNWIND_ENABLE_RUST_SGX:BOOL

**Default**: ``OFF``

27 changes: 27 additions & 0 deletions libunwind/src/AddressSpace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ namespace libunwind {
// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;

#if !defined(RUST_SGX)
extern char __eh_frame_start;
extern char __eh_frame_end;

Expand All @@ -132,6 +133,15 @@ extern char __eh_frame_hdr_start;
extern char __eh_frame_hdr_end;
#endif

#elif defined(RUST_SGX)
extern "C" char IMAGE_BASE;
extern "C" uint64_t EH_FRM_HDR_OFFSET;
extern "C" uint64_t EH_FRM_HDR_LEN;
extern "C" uint64_t EH_FRM_OFFSET;
extern "C" uint64_t EH_FRM_LEN;
#endif


#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)

// When statically linked on bare-metal, the symbols for the EH table are looked
Expand Down Expand Up @@ -392,6 +402,10 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
return result;
}

#if defined(RUST_SGX)
extern "C" char IMAGE_BASE;
#endif

inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
UnwindInfoSections &info) {
#ifdef __APPLE__
Expand All @@ -408,6 +422,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
}
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
// Bare metal is statically linked, so no need to ask the dynamic loader

#if !defined(RUST_SGX)
info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
info.dwarf_section = (uintptr_t)(&__eh_frame_start);
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
Expand All @@ -418,6 +434,17 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
(void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
#endif

#elif defined(RUST_SGX)
info.dwarf_section = (uintptr_t)EH_FRM_OFFSET + (uintptr_t)(&IMAGE_BASE);
info.dwarf_section_length = (uintptr_t)EH_FRM_LEN;
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
info.dwarf_index_section = (uintptr_t)EH_FRM_HDR_OFFSET + (uintptr_t)(&IMAGE_BASE);
info.dwarf_index_section_length = (uintptr_t)EH_FRM_HDR_LEN;
#endif

#endif

if (info.dwarf_section_length)
return true;
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
Expand Down
48 changes: 41 additions & 7 deletions libunwind/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Get sources

enable_language(C CXX ASM)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(LIBUNWIND_CXX_SOURCES
libunwind.cpp
Unwind-EHABI.cpp
Expand All @@ -16,17 +20,11 @@ set(LIBUNWIND_C_SOURCES
UnwindLevel1-gcc-ext.c
Unwind-sjlj.c
)
set_source_files_properties(${LIBUNWIND_C_SOURCES}
PROPERTIES
COMPILE_FLAGS "-std=c99")

set(LIBUNWIND_ASM_SOURCES
UnwindRegistersRestore.S
UnwindRegistersSave.S
)
set_source_files_properties(${LIBUNWIND_ASM_SOURCES}
PROPERTIES
LANGUAGE C)

set(LIBUNWIND_HEADERS
AddressSpace.hpp
Expand Down Expand Up @@ -55,6 +53,42 @@ if (MSVC_IDE)
source_group("Header Files" FILES ${LIBUNWIND_HEADERS})
endif()

if (RUST_SGX)
# Compile Flags
add_definitions(-DRUST_SGX)
add_definitions(-D__NO_STRING_INLINES)
add_definitions(-D__NO_MATH_INLINES)
add_definitions(-D_LIBUNWIND_IS_BAREMETAL)
# Can't use add_definitions because CMake will reorder these arguments
list(APPEND LIBUNWIND_COMPILE_FLAGS -U_FORTIFY_SOURCE)
list(APPEND LIBUNWIND_COMPILE_FLAGS -D_FORTIFY_SOURCE=0)

list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-stack-protector)
list(APPEND LIBUNWIND_COMPILE_FLAGS -ffreestanding)
list(APPEND LIBUNWIND_COMPILE_FLAGS -fexceptions)
# Avoid too new relocation types being emitted, which might prevent linking
# on older platforms.
#
# See https://github.com/rust-lang/rust/issues/34978
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
list(APPEND LIBUNWIND_COMPILE_FLAGS -Wa,-mrelax-relocations=no)
else()
list(APPEND LIBUNWIND_COMPILE_FLAGS)
endif()

# Sources
list(APPEND LIBUNWIND_HEADERS UnwindRustSgx.h)
list(APPEND LIBUNWIND_C_SOURCES UnwindRustSgx.c)
endif()


set_source_files_properties(${LIBUNWIND_C_SOURCES}
PROPERTIES
COMPILE_FLAGS "-std=c99")
set_source_files_properties(${LIBUNWIND_ASM_SOURCES}
PROPERTIES
LANGUAGE ASM)

set(LIBUNWIND_SOURCES
${LIBUNWIND_CXX_SOURCES}
${LIBUNWIND_C_SOURCES}
Expand All @@ -69,7 +103,7 @@ else()
add_library_flags_if(LIBUNWIND_HAS_GCC_LIB gcc)
endif()
add_library_flags_if(LIBUNWIND_HAS_DL_LIB dl)
if (LIBUNWIND_ENABLE_THREADS)
if (LIBUNWIND_ENABLE_THREADS AND (NOT RUST_SGX))
add_library_flags_if(LIBUNWIND_HAS_PTHREAD_LIB pthread)
add_compile_flags_if(LIBUNWIND_WEAK_PTHREAD_LIB -DLIBUNWIND_USE_WEAK_PTHREAD=1)
endif()
Expand Down
2 changes: 1 addition & 1 deletion libunwind/src/RWMutex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

#if defined(_WIN32)
#include <windows.h>
#elif !defined(_LIBUNWIND_HAS_NO_THREADS)
#elif !defined(_LIBUNWIND_HAS_NO_THREADS) && !defined(RUST_SGX)
#include <pthread.h>
#if defined(__ELF__) && defined(_LIBUNWIND_LINK_PTHREAD_LIB)
#pragma comment(lib, "pthread")
Expand Down
125 changes: 125 additions & 0 deletions libunwind/src/UnwindRustSgx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//===--------------------- UnwindRustSgx.c ----------------------------------===//
//
//// The LLVM Compiler Infrastructure
////
//// This file is dual licensed under the MIT and the University of Illinois Open
//// Source Licenses. See LICENSE.TXT for details.
////
////
////===----------------------------------------------------------------------===//

#define _GNU_SOURCE
#include <link.h>

#include <elf.h>
#include <stdarg.h>
#include <stdio.h>
#include <stddef.h>
#include "UnwindRustSgx.h"

#define max_log 256

__attribute__((weak)) struct _IO_FILE *stderr = (_IO_FILE *)-1;

static int vwrite_err(const char *format, va_list ap)
{
int len = 0;
#ifndef NDEBUG
char s[max_log];
s[0]='\0';
len = vsnprintf(s, max_log, format, ap);
__rust_print_err((uint8_t *)s, len);
#endif
return len;
}

static int write_err(const char *format, ...)
{
int ret;
va_list args;
va_start(args, format);
ret = vwrite_err(format, args);
va_end(args);


return ret;
}

__attribute__((weak)) int fprintf (FILE *__restrict __stream,
const char *__restrict __format, ...)
{

int ret;
if (__stream != stderr) {
write_err("Rust SGX Unwind supports only writing to stderr\n");
return -1;
} else {
va_list args;
ret = 0;
va_start(args, __format);
ret += vwrite_err(__format, args);
va_end(args);
}

return ret;
}

__attribute__((weak)) int fflush (FILE *__stream)
{
// We do not need to do anything here.
return 0;
}

__attribute__((weak)) void __assert_fail(const char * assertion,
const char * file,
unsigned int line,
const char * function)
{
write_err("%s:%d %s %s\n", file, line, function, assertion);
abort();
}

// We do not report stack over flow detected.
// Calling write_err uses more stack due to the way we have implemented it.
// With possible enabling of stack probes, we should not
// get into __stack_chk_fail() at all.
__attribute__((weak)) void __stack_chk_fail() {
abort();
}

/*
* Below are defined for all executibles compiled for
* x86_64-fortanix-unknown-sgx rust target.
* Ref: rust/src/libstd/sys/sgx/abi/entry.S
*/

struct libwu_rs_alloc_meta {
size_t alloc_size;
// Should we put a signatre guard before ptr for oob access?
unsigned char ptr[0];
};

#define META_FROM_PTR(__PTR) (struct libwu_rs_alloc_meta *) \
((unsigned char *)__PTR - offsetof(struct libwu_rs_alloc_meta, ptr))

void *libuw_malloc(size_t size)
{
struct libwu_rs_alloc_meta *meta;
size_t alloc_size = size + sizeof(struct libwu_rs_alloc_meta);
meta = (void *)__rust_c_alloc(alloc_size, sizeof(size_t));
if (!meta) {
return NULL;
}
meta->alloc_size = alloc_size;
return (void *)meta->ptr;
}

void libuw_free(void *p)
{
struct libwu_rs_alloc_meta *meta;
if (!p) {
return;
}
meta = META_FROM_PTR(p);
__rust_c_dealloc((unsigned char *)meta, meta->alloc_size, sizeof(size_t));
}
Loading